summaryrefslogtreecommitdiff
path: root/pfinet/linux-src/net
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>2000-02-05 12:21:17 +0000
committerRoland McGrath <roland@gnu.org>2000-02-05 12:21:17 +0000
commite5f75e8ece5d1a8d3c17bd0156082caf153d3779 (patch)
tree316ee48be396f95770ccd5511ea442b83cadca51 /pfinet/linux-src/net
parentb39cd08347c72483a4521a55301a0fa147a2a2b1 (diff)
Import of Linux 2.2.14 subset (ipv4 stack and related)
Diffstat (limited to 'pfinet/linux-src/net')
-rw-r--r--pfinet/linux-src/net/core/dev.c65
-rw-r--r--pfinet/linux-src/net/ethernet/eth.c2
-rw-r--r--pfinet/linux-src/net/ipv4/arp.c33
-rw-r--r--pfinet/linux-src/net/ipv4/devinet.c11
-rw-r--r--pfinet/linux-src/net/ipv4/icmp.c2
-rw-r--r--pfinet/linux-src/net/ipv4/ip_forward.c15
-rw-r--r--pfinet/linux-src/net/ipv4/ip_fw.c13
-rw-r--r--pfinet/linux-src/net/ipv4/ip_input.c8
-rw-r--r--pfinet/linux-src/net/ipv4/ip_masq.c25
-rw-r--r--pfinet/linux-src/net/ipv4/ip_masq_user.c4
-rw-r--r--pfinet/linux-src/net/ipv4/route.c2
-rw-r--r--pfinet/linux-src/net/ipv4/syncookies.c8
-rw-r--r--pfinet/linux-src/net/ipv4/tcp.c43
-rw-r--r--pfinet/linux-src/net/ipv4/tcp_input.c4
-rw-r--r--pfinet/linux-src/net/ipv4/tcp_ipv4.c39
-rw-r--r--pfinet/linux-src/net/ipv4/tcp_timer.c10
16 files changed, 207 insertions, 77 deletions
diff --git a/pfinet/linux-src/net/core/dev.c b/pfinet/linux-src/net/core/dev.c
index 75fae54a..0baa1371 100644
--- a/pfinet/linux-src/net/core/dev.c
+++ b/pfinet/linux-src/net/core/dev.c
@@ -57,6 +57,8 @@
* A network device unload needs to purge
* the backlog queue.
* Paul Rusty Russel : SIOCSIFNAME
+ * Andrea Arcangeli : dev_clear_backlog() needs the
+ * skb_queue_lock held.
*/
#include <asm/uaccess.h>
@@ -711,7 +713,8 @@ static void netdev_wakeup(void)
static void dev_clear_backlog(struct device *dev)
{
- struct sk_buff *prev, *curr;
+ struct sk_buff *curr;
+ unsigned long flags;
/*
*
@@ -719,27 +722,24 @@ static void dev_clear_backlog(struct device *dev)
*
* We are competing here both with netif_rx() and net_bh().
* We don't want either of those to mess with skb ptrs
- * while we work on them, thus cli()/sti().
- *
- * It looks better to use net_bh trick, at least
- * to be sure, that we keep interrupt latency really low. --ANK (980727)
+ * while we work on them, thus we must grab the
+ * skb_queue_lock.
*/
if (backlog.qlen) {
- start_bh_atomic();
- curr = backlog.next;
- while ( curr != (struct sk_buff *)(&backlog) ) {
- unsigned long flags;
- curr=curr->next;
- if ( curr->prev->dev == dev ) {
- prev = curr->prev;
- spin_lock_irqsave(&skb_queue_lock, flags);
- __skb_unlink(prev, &backlog);
+ repeat:
+ spin_lock_irqsave(&skb_queue_lock, flags);
+ for (curr = backlog.next;
+ curr != (struct sk_buff *)(&backlog);
+ curr = curr->next)
+ if (curr->dev == dev)
+ {
+ __skb_unlink(curr, &backlog);
spin_unlock_irqrestore(&skb_queue_lock, flags);
- kfree_skb(prev);
+ kfree_skb(curr);
+ goto repeat;
}
- }
- end_bh_atomic();
+ spin_unlock_irqrestore(&skb_queue_lock, flags);
#ifdef CONFIG_NET_HW_FLOWCONTROL
if (netdev_dropping)
netdev_wakeup();
@@ -796,7 +796,11 @@ void netif_rx(struct sk_buff *skb)
#ifdef CONFIG_BRIDGE
static inline void handle_bridge(struct sk_buff *skb, unsigned short type)
{
- if (br_stats.flags & BR_UP && br_protocol_ok(ntohs(type)))
+ /*
+ * The br_stats.flags is checked here to save the expense of a
+ * function call.
+ */
+ if ((br_stats.flags & BR_UP) && br_call_bridge(skb, type))
{
/*
* We pass the bridge a complete frame. This means
@@ -820,7 +824,6 @@ static inline void handle_bridge(struct sk_buff *skb, unsigned short type)
}
#endif
-
/*
* When we are called the queue is ready to grab, the interrupts are
* on and hardware can interrupt and queue to the receive queue as we
@@ -1275,8 +1278,9 @@ static int sprintf_wireless_stats(char *buffer, struct device *dev)
int size;
if(stats != (struct iw_statistics *) NULL)
+ {
size = sprintf(buffer,
- "%6s: %02x %3d%c %3d%c %3d%c %5d %5d %5d\n",
+ "%6s: %04x %3d%c %3d%c %3d%c %6d %6d %6d\n",
dev->name,
stats->status,
stats->qual.qual,
@@ -1288,6 +1292,8 @@ static int sprintf_wireless_stats(char *buffer, struct device *dev)
stats->discard.nwid,
stats->discard.code,
stats->discard.misc);
+ stats->qual.updated = 0;
+ }
else
size = 0;
@@ -1309,8 +1315,9 @@ int dev_get_wireless_info(char * buffer, char **start, off_t offset,
struct device * dev;
size = sprintf(buffer,
- "Inter-|sta| Quality | Discarded packets\n"
- " face |tus|link level noise| nwid crypt misc\n");
+ "Inter-| sta-| Quality | Discarded packets\n"
+ " face | tus | link level noise | nwid crypt misc\n"
+ );
pos+=size;
len+=size;
@@ -1846,6 +1853,7 @@ extern int lance_init(void);
extern int bpq_init(void);
extern int scc_init(void);
extern void sdla_setup(void);
+extern void sdla_c_setup(void);
extern void dlci_setup(void);
extern int dmascc_init(void);
extern int sm_init(void);
@@ -1855,6 +1863,7 @@ extern int baycom_ser_hdx_init(void);
extern int baycom_par_init(void);
extern int lapbeth_init(void);
+extern int comx_init(void);
extern void arcnet_init(void);
extern void ip_auto_config(void);
#ifdef CONFIG_8xx
@@ -1922,7 +1931,7 @@ __initfunc(int net_dev_init(void))
dlci_setup();
#endif
#if defined(CONFIG_SDLA)
- sdla_setup();
+ sdla_c_setup();
#endif
#if defined(CONFIG_BAYCOM_PAR)
baycom_par_init();
@@ -1948,6 +1957,9 @@ __initfunc(int net_dev_init(void))
#if defined(CONFIG_8xx)
cpm_enet_init();
#endif
+#if defined(CONFIG_COMX)
+ comx_init();
+#endif
/*
* SLHC if present needs attaching so other people see it
* even if not opened.
@@ -2018,6 +2030,13 @@ __initfunc(int net_dev_init(void))
dev_mcast_init();
+#ifdef CONFIG_BRIDGE
+ /*
+ * Register any statically linked ethernet devices with the bridge
+ */
+ br_spacedevice_register();
+#endif
+
#ifdef CONFIG_IP_PNP
ip_auto_config();
#endif
diff --git a/pfinet/linux-src/net/ethernet/eth.c b/pfinet/linux-src/net/ethernet/eth.c
index bce35d48..945f4a06 100644
--- a/pfinet/linux-src/net/ethernet/eth.c
+++ b/pfinet/linux-src/net/ethernet/eth.c
@@ -201,7 +201,7 @@ unsigned short eth_type_trans(struct sk_buff *skb, struct device *dev)
* seems to set IFF_PROMISC.
*/
- else if(dev->flags&(IFF_PROMISC/*|IFF_ALLMULTI*/))
+ else if(1 /*dev->flags&IFF_PROMISC*/)
{
if(memcmp(eth->h_dest,dev->dev_addr, ETH_ALEN))
skb->pkt_type=PACKET_OTHERHOST;
diff --git a/pfinet/linux-src/net/ipv4/arp.c b/pfinet/linux-src/net/ipv4/arp.c
index 1e5cf1b1..d81c1bee 100644
--- a/pfinet/linux-src/net/ipv4/arp.c
+++ b/pfinet/linux-src/net/ipv4/arp.c
@@ -1,6 +1,6 @@
/* linux/net/inet/arp.c
*
- * Version: $Id: arp.c,v 1.77.2.1 1999/06/28 10:39:23 davem Exp $
+ * Version: $Id: arp.c,v 1.77.2.4 1999/09/23 19:03:36 davem Exp $
*
* Copyright (C) 1994 by Florian La Roche
*
@@ -65,6 +65,8 @@
* clean up the APFDDI & gen. FDDI bits.
* Alexey Kuznetsov: new arp state machine;
* now it is in net/core/neighbour.c.
+ * Julian Anastasov: "hidden" flag: hide the
+ * interface and don't reply for it
*/
/* RFC1122 Status:
@@ -308,10 +310,15 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb)
u32 saddr;
u8 *dst_ha = NULL;
struct device *dev = neigh->dev;
+ struct device *dev2;
+ struct in_device *in_dev2;
u32 target = *(u32*)neigh->primary_key;
int probes = neigh->probes;
- if (skb && inet_addr_type(skb->nh.iph->saddr) == RTN_LOCAL)
+ if (skb &&
+ (dev2 = ip_dev_find(skb->nh.iph->saddr)) != NULL &&
+ (in_dev2 = dev2->ip_ptr) != NULL &&
+ !IN_DEV_HIDDEN(in_dev2))
saddr = skb->nh.iph->saddr;
else
saddr = inet_select_addr(dev, target, RT_SCOPE_LINK);
@@ -653,8 +660,14 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
/* Special case: IPv4 duplicate address detection packet (RFC2131) */
if (sip == 0) {
+ struct device *dev2;
+ struct in_device *in_dev2;
+
if (arp->ar_op == __constant_htons(ARPOP_REQUEST) &&
- inet_addr_type(tip) == RTN_LOCAL)
+ (dev2 = ip_dev_find(tip)) != NULL &&
+ (dev2 == dev ||
+ ((in_dev2 = dev2->ip_ptr) != NULL &&
+ !IN_DEV_HIDDEN(in_dev2))))
arp_send(ARPOP_REPLY,ETH_P_ARP,tip,dev,tip,sha,dev->dev_addr,dev->dev_addr);
goto out;
}
@@ -668,6 +681,20 @@ int arp_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
if (addr_type == RTN_LOCAL) {
n = neigh_event_ns(&arp_tbl, sha, &sip, dev);
if (n) {
+ if (ipv4_devconf.hidden &&
+ skb->pkt_type != PACKET_HOST) {
+ struct device *dev2;
+ struct in_device *in_dev2;
+
+ if ((dev2 = ip_dev_find(tip)) != NULL &&
+ dev2 != dev &&
+ (in_dev2 = dev2->ip_ptr) != NULL &&
+ IN_DEV_HIDDEN(in_dev2)) {
+ neigh_release(n);
+ goto out;
+ }
+ }
+
arp_send(ARPOP_REPLY,ETH_P_ARP,sip,dev,tip,sha,dev->dev_addr,sha);
neigh_release(n);
}
diff --git a/pfinet/linux-src/net/ipv4/devinet.c b/pfinet/linux-src/net/ipv4/devinet.c
index a50ee3bd..41b42a52 100644
--- a/pfinet/linux-src/net/ipv4/devinet.c
+++ b/pfinet/linux-src/net/ipv4/devinet.c
@@ -658,7 +658,7 @@ u32 inet_select_addr(struct device *dev, u32 dst, int scope)
addr = ifa->ifa_local;
} endfor_ifa(in_dev);
- if (addr || scope >= RT_SCOPE_LINK)
+ if (addr)
return addr;
/* Not loopback addresses on loopback should be preferred
@@ -670,7 +670,9 @@ u32 inet_select_addr(struct device *dev, u32 dst, int scope)
continue;
for_primary_ifa(in_dev) {
- if (ifa->ifa_scope <= scope)
+ if (!IN_DEV_HIDDEN(in_dev) &&
+ ifa->ifa_scope <= scope &&
+ ifa->ifa_scope != RT_SCOPE_LINK)
return ifa->ifa_local;
} endfor_ifa(in_dev);
}
@@ -923,7 +925,7 @@ int devinet_sysctl_forward(ctl_table *ctl, int write, struct file * filp,
static struct devinet_sysctl_table
{
struct ctl_table_header *sysctl_header;
- ctl_table devinet_vars[12];
+ ctl_table devinet_vars[13];
ctl_table devinet_dev[2];
ctl_table devinet_conf_dir[2];
ctl_table devinet_proto_dir[2];
@@ -963,6 +965,9 @@ static struct devinet_sysctl_table
{NET_IPV4_CONF_LOG_MARTIANS, "log_martians",
&ipv4_devconf.log_martians, sizeof(int), 0644, NULL,
&proc_dointvec},
+ {NET_IPV4_CONF_HIDDEN, "hidden",
+ &ipv4_devconf.hidden, sizeof(int), 0644, NULL,
+ &proc_dointvec},
{0}},
{{NET_PROTO_CONF_ALL, "all", NULL, 0, 0555, devinet_sysctl.devinet_vars},{0}},
diff --git a/pfinet/linux-src/net/ipv4/icmp.c b/pfinet/linux-src/net/ipv4/icmp.c
index 78c54be8..6c1edfd7 100644
--- a/pfinet/linux-src/net/ipv4/icmp.c
+++ b/pfinet/linux-src/net/ipv4/icmp.c
@@ -3,7 +3,7 @@
*
* Alan Cox, <alan@redhat.com>
*
- * Version: $Id: icmp.c,v 1.52.2.3 1999/09/22 16:33:02 davem Exp $
+ * Version: $Id: icmp.c,v 1.52.2.4 1999/11/16 02:28:40 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
diff --git a/pfinet/linux-src/net/ipv4/ip_forward.c b/pfinet/linux-src/net/ipv4/ip_forward.c
index 08ebbc2f..fd8c0435 100644
--- a/pfinet/linux-src/net/ipv4/ip_forward.c
+++ b/pfinet/linux-src/net/ipv4/ip_forward.c
@@ -5,11 +5,12 @@
*
* The IP forwarding functionality.
*
- * Version: $Id: ip_forward.c,v 1.43 1999/03/21 05:22:37 davem Exp $
+ * Version: $Id: ip_forward.c,v 1.43.2.1 1999/11/16 06:33:43 davem Exp $
*
* Authors: see ip.c
*
* Fixes:
+ * Joseph Gooch : Removed maddr selection for ip_masq, now done in ip_masq.c
* Many : Split from ip.c , see ip_input.c for
* history.
* Dave Gregorich : NULL ip_rt_put fix for multicast
@@ -168,7 +169,6 @@ int ip_forward(struct sk_buff *skb)
* and skip the firewall checks
*/
if (iph->protocol == IPPROTO_ICMP) {
- __u32 maddr;
#ifdef CONFIG_IP_MASQUERADE_ICMP
struct icmphdr *icmph = (struct icmphdr *)((char*)iph + (iph->ihl << 2));
if ((icmph->type==ICMP_DEST_UNREACH)||
@@ -176,8 +176,7 @@ int ip_forward(struct sk_buff *skb)
(icmph->type==ICMP_TIME_EXCEEDED))
{
#endif
- maddr = inet_select_addr(dev2, rt->rt_gateway, RT_SCOPE_UNIVERSE);
- fw_res = ip_fw_masq_icmp(&skb, maddr);
+ fw_res = ip_fw_masquerade(&skb, 0);
if (fw_res < 0) {
kfree_skb(skb);
return -1;
@@ -187,7 +186,7 @@ int ip_forward(struct sk_buff *skb)
/* ICMP matched - skip firewall */
goto skip_call_fw_firewall;
#ifdef CONFIG_IP_MASQUERADE_ICMP
- }
+ }
#endif
}
if (rt->rt_flags&RTCF_MASQ)
@@ -219,15 +218,11 @@ skip_call_fw_firewall:
*/
if (!(IPCB(skb)->flags&IPSKB_MASQUERADED) &&
(fw_res==FW_MASQUERADE || rt->rt_flags&RTCF_MASQ)) {
- u32 maddr;
+ u32 maddr = 0;
#ifdef CONFIG_IP_ROUTE_NAT
maddr = (rt->rt_flags&RTCF_MASQ) ? rt->rt_src_map : 0;
-
- if (maddr == 0)
#endif
- maddr = inet_select_addr(dev2, rt->rt_gateway, RT_SCOPE_UNIVERSE);
-
if (ip_fw_masquerade(&skb, maddr) < 0) {
kfree_skb(skb);
return -1;
diff --git a/pfinet/linux-src/net/ipv4/ip_fw.c b/pfinet/linux-src/net/ipv4/ip_fw.c
index 6319b89e..400f46c0 100644
--- a/pfinet/linux-src/net/ipv4/ip_fw.c
+++ b/pfinet/linux-src/net/ipv4/ip_fw.c
@@ -40,11 +40,12 @@
* 23-Jul-1999: Fixed small fragment security exposure opened on 15-May-1998.
* John McDonald <jm@dataprotect.com>
* Thomas Lopatic <tl@dataprotect.com>
+ * 21-Oct-1999: Applied count fix by Emanuele Caratti <wiz@iol.it> --RR
*/
/*
*
- * The origina Linux port was done Alan Cox, with changes/fixes from
+ * The original Linux port was done Alan Cox, with changes/fixes from
* Pauline Middlelink, Jos Vos, Thomas Quinot, Wouter Gadeyne, Juan
* Jose Ciarlante, Bernd Eckenfels, Keith Owens and others.
*
@@ -86,6 +87,7 @@
#include <net/udp.h>
#include <net/sock.h>
#include <net/icmp.h>
+#include <net/ip_masq.h>
#include <linux/netlink.h>
#include <linux/init.h>
#include <linux/firewall.h>
@@ -228,6 +230,7 @@ struct ip_reent
{
struct ip_chain *prevchain; /* Pointer to referencing chain */
struct ip_fwkernel *prevrule; /* Pointer to referencing rule */
+ unsigned int count;
struct ip_counters counters;
};
@@ -488,7 +491,10 @@ static int find_special(ip_chainlabel label, int *answer)
static int enabled = 0;
if(!enabled)
+ {
+ enabled=1;
sysctl_ip_always_defrag++;
+ }
*answer = FW_REDIRECT;
return 1;
#endif
@@ -729,8 +735,8 @@ ip_fw_check(struct iphdr *ip,
else FWC_HAVE_LOCK(fwc_rlocks);
f = chain->chain;
+ count = 0;
do {
- count = 0;
for (; f; f = f->next) {
count++;
if (ip_rule_match(f,rif,ip,
@@ -768,10 +774,12 @@ ip_fw_check(struct iphdr *ip,
else {
f->branch->reent[slot].prevchain
= chain;
+ f->branch->reent[slot].count = count;
f->branch->reent[slot].prevrule
= f->next;
chain = f->branch;
f = chain->chain;
+ count = 0;
}
}
else if (f->simplebranch == FW_SKIP)
@@ -790,6 +798,7 @@ ip_fw_check(struct iphdr *ip,
if (chain->reent[slot].prevchain) {
struct ip_chain *tmp = chain;
f = chain->reent[slot].prevrule;
+ count = chain->reent[slot].count;
chain = chain->reent[slot].prevchain;
tmp->reent[slot].prevchain = NULL;
}
diff --git a/pfinet/linux-src/net/ipv4/ip_input.c b/pfinet/linux-src/net/ipv4/ip_input.c
index b1725fa3..545f093c 100644
--- a/pfinet/linux-src/net/ipv4/ip_input.c
+++ b/pfinet/linux-src/net/ipv4/ip_input.c
@@ -97,6 +97,7 @@
* Alan Cox : Multicast routing hooks
* Jos Vos : Do accounting *before* call_in_firewall
* Willy Konynenberg : Transparent proxying support
+ * Stephan Uphoff : Check IP header length field
*
*
*
@@ -421,6 +422,10 @@ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
if (skb->len < sizeof(struct iphdr))
goto inhdr_error;
+
+ if (skb->len < (iph->ihl << 2))
+ goto inhdr_error;
+
if (iph->ihl < 5 || iph->version != 4 || ip_fast_csum((u8 *)iph, iph->ihl) != 0)
goto inhdr_error;
@@ -429,6 +434,9 @@ int ip_rcv(struct sk_buff *skb, struct device *dev, struct packet_type *pt)
if (skb->len < len)
goto inhdr_error;
+ if (len < (iph->ihl << 2))
+ goto inhdr_error;
+
/*
* Our transport medium may have padded the buffer out. Now we know it
* is IP we can trim to the true length of the frame.
diff --git a/pfinet/linux-src/net/ipv4/ip_masq.c b/pfinet/linux-src/net/ipv4/ip_masq.c
index 6d0588c0..8f00409f 100644
--- a/pfinet/linux-src/net/ipv4/ip_masq.c
+++ b/pfinet/linux-src/net/ipv4/ip_masq.c
@@ -10,6 +10,9 @@
* See ip_fw.c for original log
*
* Fixes:
+ * Joseph Gooch : Modified ip_fw_masquerade() to do a ip_route_output()
+ * (help by Dan Drown) : to choose the proper local address.
+ * (and Alexey) :
* Juan Jose Ciarlante : Modularized application masquerading (see ip_masq_app.c)
* Juan Jose Ciarlante : New struct ip_masq_seq that holds output/input delta seq.
* Juan Jose Ciarlante : Added hashed lookup by proto,maddr,mport and proto,saddr,sport
@@ -787,6 +790,8 @@ void ip_masq_put(struct ip_masq *ms)
}
}
+extern int sysctl_ip_always_defrag;
+
static void masq_expire(unsigned long data)
{
struct ip_masq *ms = (struct ip_masq *)data;
@@ -839,6 +844,7 @@ static void masq_expire(unsigned long data)
*/
if (atomic_read(&ms->refcnt) == 1) {
kfree_s(ms,sizeof(*ms));
+ sysctl_ip_always_defrag--;
MOD_DEC_USE_COUNT;
goto masq_expire_out;
}
@@ -880,8 +886,6 @@ static __u16 get_next_mport(void)
* Be careful, it can be called from u-space
*/
-extern int sysctl_ip_always_defrag;
-
struct ip_masq * ip_masq_new(int proto, __u32 maddr, __u16 mport, __u32 saddr, __u16 sport, __u32 daddr, __u16 dport, unsigned mflags)
{
struct ip_masq *ms, *mst;
@@ -1141,6 +1145,23 @@ int ip_fw_masquerade(struct sk_buff **skb_p, __u32 maddr)
return -1;
}
+ /* Lets determine our maddr now, shall we? */
+ if (maddr == 0) {
+ struct rtable *rt;
+ struct rtable *skb_rt = (struct rtable*)skb->dst;
+ struct device *skb_dev = skb_rt->u.dst.dev;
+
+ if (ip_route_output(&rt, iph->daddr, 0, RT_TOS(iph->tos)|RTO_CONN, skb_dev?skb_dev->ifindex:0)) {
+ /* Fallback on old method */
+ /* This really shouldn't happen... */
+ maddr = inet_select_addr(skb_dev, skb_rt->rt_gateway, RT_SCOPE_UNIVERSE);
+ } else {
+ /* Route lookup succeeded */
+ maddr = rt->rt_src;
+ ip_rt_put(rt);
+ }
+ }
+
switch (iph->protocol) {
case IPPROTO_ICMP:
return(ip_fw_masq_icmp(skb_p, maddr));
diff --git a/pfinet/linux-src/net/ipv4/ip_masq_user.c b/pfinet/linux-src/net/ipv4/ip_masq_user.c
index f369f03d..848cbfe8 100644
--- a/pfinet/linux-src/net/ipv4/ip_masq_user.c
+++ b/pfinet/linux-src/net/ipv4/ip_masq_user.c
@@ -2,7 +2,7 @@
* IP_MASQ_USER user space control module
*
*
- * $Id: ip_masq_user.c,v 1.1.2.2 1999/08/13 18:26:33 davem Exp $
+ * $Id: ip_masq_user.c,v 1.1.2.3 1999/11/16 06:33:51 davem Exp $
*/
#include <linux/config.h>
@@ -100,7 +100,7 @@ static int ip_masq_user_maddr(struct ip_masq_user *ums)
return ret;
}
dev = rt->u.dst.dev;
- ums->maddr = ip_masq_select_addr(dev, rt->rt_gateway, RT_SCOPE_UNIVERSE);
+ ums->maddr = rt->rt_src; /* Per Alexey */
IP_MASQ_DEBUG(1-debug, "did setup maddr=%lX\n", ntohl(ums->maddr));
ip_rt_put(rt);
diff --git a/pfinet/linux-src/net/ipv4/route.c b/pfinet/linux-src/net/ipv4/route.c
index b308995b..2b114b3e 100644
--- a/pfinet/linux-src/net/ipv4/route.c
+++ b/pfinet/linux-src/net/ipv4/route.c
@@ -5,7 +5,7 @@
*
* ROUTE - implementation of the IP router.
*
- * Version: $Id: route.c,v 1.67.2.3 1999/08/08 08:43:12 davem Exp $
+ * Version: $Id: route.c,v 1.67.2.4 1999/11/16 02:28:43 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
diff --git a/pfinet/linux-src/net/ipv4/syncookies.c b/pfinet/linux-src/net/ipv4/syncookies.c
index fb4e8f80..62884aae 100644
--- a/pfinet/linux-src/net/ipv4/syncookies.c
+++ b/pfinet/linux-src/net/ipv4/syncookies.c
@@ -9,7 +9,7 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
- * $Id: syncookies.c,v 1.7.2.1 1999/08/08 08:43:13 davem Exp $
+ * $Id: syncookies.c,v 1.7.2.3 1999/12/07 03:11:07 davem Exp $
*
* Missing: IPv6 support.
*/
@@ -184,8 +184,10 @@ cookie_v4_check(struct sock *sk, struct sk_buff *skb, struct ip_options *opt)
req->af.v4_req.loc_addr,
sk->ip_tos | RTO_CONN,
0)) {
- tcp_openreq_free(req);
- return NULL;
+ if (req->af.v4_req.opt)
+ kfree(req->af.v4_req.opt);
+ tcp_openreq_free(req);
+ return NULL;
}
/* Try to redo what tcp_v4_send_synack did. */
diff --git a/pfinet/linux-src/net/ipv4/tcp.c b/pfinet/linux-src/net/ipv4/tcp.c
index 65763215..68b7e5e7 100644
--- a/pfinet/linux-src/net/ipv4/tcp.c
+++ b/pfinet/linux-src/net/ipv4/tcp.c
@@ -5,7 +5,7 @@
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp.c,v 1.140.2.4 1999/08/09 03:13:12 davem Exp $
+ * Version: $Id: tcp.c,v 1.140.2.5 1999/09/23 19:21:16 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1798,6 +1798,8 @@ extern void __skb_cb_too_small_for_tcp(int, int);
void __init tcp_init(void)
{
struct sk_buff *skb = NULL;
+ unsigned long goal;
+ int order;
if(sizeof(struct tcp_skb_cb) > sizeof(skb->cb))
__skb_cb_too_small_for_tcp(sizeof(struct tcp_skb_cb),
@@ -1823,4 +1825,43 @@ void __init tcp_init(void)
NULL, NULL);
if(!tcp_timewait_cachep)
panic("tcp_init: Cannot alloc tcp_tw_bucket cache.");
+
+ /* Size and allocate TCP hash tables. */
+ goal = num_physpages >> (20 - PAGE_SHIFT);
+ for (order = 0; (1UL << order) < goal; order++)
+ ;
+ do {
+ tcp_ehash_size = (1UL << order) * PAGE_SIZE /
+ sizeof(struct sock *);
+ tcp_ehash = (struct sock **)
+ __get_free_pages(GFP_ATOMIC, order);
+ } while (tcp_ehash == NULL && --order >= 0);
+
+ if (!tcp_ehash)
+ panic("Failed to allocate TCP established hash table\n");
+ memset(tcp_ehash, 0, tcp_ehash_size * sizeof(struct sock *));
+
+ goal = (((1UL << order) * PAGE_SIZE) / sizeof(struct tcp_bind_bucket *));
+ if (goal > (64 * 1024)) {
+ /* Don't size the bind-hash larger than the port
+ * space, that is just silly.
+ */
+ goal = (((64 * 1024) * sizeof(struct tcp_bind_bucket *)) / PAGE_SIZE);
+ for (order = 0; (1UL << order) < goal; order++)
+ ;
+ }
+
+ do {
+ tcp_bhash_size = (1UL << order) * PAGE_SIZE /
+ sizeof(struct tcp_bind_bucket *);
+ tcp_bhash = (struct tcp_bind_bucket **)
+ __get_free_pages(GFP_ATOMIC, order);
+ } while (tcp_bhash == NULL && --order >= 0);
+
+ if (!tcp_bhash)
+ panic("Failed to allocate TCP bind hash table\n");
+ memset(tcp_bhash, 0, tcp_bhash_size * sizeof(struct tcp_bind_bucket *));
+
+ printk("TCP: Hash tables configured (ehash %d bhash %d)\n",
+ tcp_ehash_size, tcp_bhash_size);
}
diff --git a/pfinet/linux-src/net/ipv4/tcp_input.c b/pfinet/linux-src/net/ipv4/tcp_input.c
index a753b128..7f5cc4e7 100644
--- a/pfinet/linux-src/net/ipv4/tcp_input.c
+++ b/pfinet/linux-src/net/ipv4/tcp_input.c
@@ -5,7 +5,7 @@
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp_input.c,v 1.164.2.7 1999/08/13 16:14:27 davem Exp $
+ * Version: $Id: tcp_input.c,v 1.164.2.8 1999/09/23 19:21:23 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -1043,7 +1043,7 @@ static __inline__ void tcp_tw_hashdance(struct sock *sk, struct tcp_tw_bucket *t
sk->prot->inuse--;
/* Step 4: Hash TW into TIMEWAIT half of established hash table. */
- head = &tcp_established_hash[sk->hashent + (TCP_HTABLE_SIZE/2)];
+ head = &tcp_ehash[sk->hashent + (tcp_ehash_size/2)];
sktw = (struct sock *)tw;
if((sktw->next = *head) != NULL)
(*head)->pprev = &sktw->next;
diff --git a/pfinet/linux-src/net/ipv4/tcp_ipv4.c b/pfinet/linux-src/net/ipv4/tcp_ipv4.c
index 904f8b5d..1864f096 100644
--- a/pfinet/linux-src/net/ipv4/tcp_ipv4.c
+++ b/pfinet/linux-src/net/ipv4/tcp_ipv4.c
@@ -5,7 +5,7 @@
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp_ipv4.c,v 1.175.2.10 1999/08/13 16:14:35 davem Exp $
+ * Version: $Id: tcp_ipv4.c,v 1.175.2.13 1999/11/16 06:33:53 davem Exp $
*
* IPv4 specific functions
*
@@ -90,12 +90,14 @@ void tcp_v4_send_check(struct sock *sk, struct tcphdr *th, int len,
* First half of the table is for sockets not in TIME_WAIT, second half
* is for TIME_WAIT sockets only.
*/
-struct sock *tcp_established_hash[TCP_HTABLE_SIZE];
+unsigned int tcp_ehash_size;
+struct sock **tcp_ehash;
/* Ok, let's try this, I give up, we do need a local binding
* TCP hash as well as the others for fast bind/connect.
*/
-struct tcp_bind_bucket *tcp_bound_hash[TCP_BHTABLE_SIZE];
+unsigned int tcp_bhash_size;
+struct tcp_bind_bucket **tcp_bhash;
/* All sockets in TCP_LISTEN state will be in here. This is the only table
* where wildcard'd TCP sockets can exist. Hash function here is just local
@@ -117,7 +119,7 @@ int tcp_port_rover = (1024 - 1);
static __inline__ int tcp_hashfn(__u32 laddr, __u16 lport,
__u32 faddr, __u16 fport)
{
- return ((laddr ^ lport) ^ (faddr ^ fport)) & ((TCP_HTABLE_SIZE/2) - 1);
+ return ((laddr ^ lport) ^ (faddr ^ fport)) & ((tcp_ehash_size/2) - 1);
}
static __inline__ int tcp_sk_hashfn(struct sock *sk)
@@ -140,7 +142,7 @@ struct tcp_bind_bucket *tcp_bucket_create(unsigned short snum)
tb = kmem_cache_alloc(tcp_bucket_cachep, SLAB_ATOMIC);
if(tb != NULL) {
struct tcp_bind_bucket **head =
- &tcp_bound_hash[tcp_bhashfn(snum)];
+ &tcp_bhash[tcp_bhashfn(snum)];
tb->port = snum;
tb->fastreuse = 0;
tb->owners = NULL;
@@ -162,7 +164,7 @@ static __inline__ int __tcp_bucket_check(unsigned short snum)
{
struct tcp_bind_bucket *tb;
- tb = tcp_bound_hash[tcp_bhashfn(snum)];
+ tb = tcp_bhash[tcp_bhashfn(snum)];
for( ; (tb && (tb->port != snum)); tb = tb->next)
;
if (tb == NULL) {
@@ -180,8 +182,8 @@ static __inline__ void __tcp_inherit_port(struct sock *sk, struct sock *child)
#ifdef CONFIG_IP_TRANSPARENT_PROXY
if (child->num != sk->num) {
- unsigned short snum = ntohs(child->num);
- for(tb = tcp_bound_hash[tcp_bhashfn(snum)];
+ unsigned short snum = child->num;
+ for(tb = tcp_bhash[tcp_bhashfn(snum)];
tb && tb->port != snum;
tb = tb->next)
;
@@ -220,7 +222,7 @@ static int tcp_v4_get_port(struct sock *sk, unsigned short snum)
do { rover++;
if ((rover < low) || (rover > high))
rover = low;
- tb = tcp_bound_hash[tcp_bhashfn(rover)];
+ tb = tcp_bhash[tcp_bhashfn(rover)];
for ( ; tb; tb = tb->next)
if (tb->port == rover)
goto next;
@@ -237,7 +239,7 @@ static int tcp_v4_get_port(struct sock *sk, unsigned short snum)
snum = rover;
tb = NULL;
} else {
- for (tb = tcp_bound_hash[tcp_bhashfn(snum)];
+ for (tb = tcp_bhash[tcp_bhashfn(snum)];
tb != NULL;
tb = tb->next)
if (tb->port == snum)
@@ -328,7 +330,7 @@ static __inline__ void __tcp_v4_hash(struct sock *sk)
if(sk->state == TCP_LISTEN)
skp = &tcp_listening_hash[tcp_sk_listen_hashfn(sk)];
else
- skp = &tcp_established_hash[(sk->hashent = tcp_sk_hashfn(sk))];
+ skp = &tcp_ehash[(sk->hashent = tcp_sk_hashfn(sk))];
if((sk->next = *skp) != NULL)
(*skp)->pprev = &sk->next;
@@ -421,7 +423,7 @@ static inline struct sock *__tcp_v4_lookup(struct tcphdr *th,
* have wildcards anyways.
*/
hash = tcp_hashfn(daddr, hnum, saddr, sport);
- for(sk = tcp_established_hash[hash]; sk; sk = sk->next) {
+ for(sk = tcp_ehash[hash]; sk; sk = sk->next) {
if(TCP_IPV4_MATCH(sk, acookie, saddr, daddr, ports, dif)) {
if (sk->state == TCP_ESTABLISHED)
TCP_RHASH(sport) = sk;
@@ -429,7 +431,7 @@ static inline struct sock *__tcp_v4_lookup(struct tcphdr *th,
}
}
/* Must check for a TIME_WAIT'er before going to listener hash. */
- for(sk = tcp_established_hash[hash+(TCP_HTABLE_SIZE/2)]; sk; sk = sk->next)
+ for(sk = tcp_ehash[hash+(tcp_ehash_size/2)]; sk; sk = sk->next)
if(TCP_IPV4_MATCH(sk, acookie, saddr, daddr, ports, dif))
goto hit;
sk = tcp_v4_lookup_listener(daddr, hnum, dif);
@@ -469,7 +471,7 @@ static struct sock *tcp_v4_proxy_lookup(unsigned short num, unsigned long raddr,
/* This code must run only from NET_BH. */
{
- struct tcp_bind_bucket *tb = tcp_bound_hash[tcp_bhashfn(hnum)];
+ struct tcp_bind_bucket *tb = tcp_bhash[tcp_bhashfn(hnum)];
for( ; (tb && tb->port != hnum); tb = tb->next)
;
if(tb == NULL)
@@ -510,7 +512,7 @@ pass2:
}
next:
if(firstpass--) {
- struct tcp_bind_bucket *tb = tcp_bound_hash[tcp_bhashfn(hpnum)];
+ struct tcp_bind_bucket *tb = tcp_bhash[tcp_bhashfn(hpnum)];
for( ; (tb && tb->port != hpnum); tb = tb->next)
;
if(tb) {
@@ -547,7 +549,7 @@ static int tcp_v4_unique_address(struct sock *sk)
/* Freeze the hash while we snoop around. */
SOCKHASH_LOCK();
- tb = tcp_bound_hash[tcp_bhashfn(snum)];
+ tb = tcp_bhash[tcp_bhashfn(snum)];
for(; tb; tb = tb->next) {
if(tb->port == snum && tb->owners != NULL) {
/* Almost certainly the re-use port case, search the real hashes
@@ -1615,7 +1617,8 @@ static inline struct sock *tcp_v4_hnd_req(struct sock *sk,struct sk_buff *skb)
sk = tcp_check_req(sk, skb, req);
}
#ifdef CONFIG_SYN_COOKIES
- else if (flg == __constant_htonl(0x00120000)) {
+ else if ((flg & __constant_htonl(0x00120000))==__constant_htonl(0x00100000))
+ {
sk = cookie_v4_check(sk, skb, &(IPCB(skb)->opt));
}
#endif
@@ -1793,7 +1796,7 @@ do_time_wait:
static void __tcp_v4_rehash(struct sock *sk)
{
- struct sock **skp = &tcp_established_hash[(sk->hashent = tcp_sk_hashfn(sk))];
+ struct sock **skp = &tcp_ehash[(sk->hashent = tcp_sk_hashfn(sk))];
SOCKHASH_LOCK();
if(sk->pprev) {
diff --git a/pfinet/linux-src/net/ipv4/tcp_timer.c b/pfinet/linux-src/net/ipv4/tcp_timer.c
index 21029f8e..7529a441 100644
--- a/pfinet/linux-src/net/ipv4/tcp_timer.c
+++ b/pfinet/linux-src/net/ipv4/tcp_timer.c
@@ -5,7 +5,7 @@
*
* Implementation of the Transmission Control Protocol(TCP).
*
- * Version: $Id: tcp_timer.c,v 1.62.2.3 1999/06/20 20:14:30 davem Exp $
+ * Version: $Id: tcp_timer.c,v 1.62.2.4 1999/09/23 19:21:39 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -363,8 +363,8 @@ static void tcp_keepalive(unsigned long data)
int count = 0;
int i;
- for(i = chain_start; i < (chain_start + ((TCP_HTABLE_SIZE/2) >> 2)); i++) {
- struct sock *sk = tcp_established_hash[i];
+ for(i = chain_start; i < (chain_start + ((tcp_ehash_size/2) >> 2)); i++) {
+ struct sock *sk = tcp_ehash[i];
while(sk) {
if(!atomic_read(&sk->sock_readers) && sk->keepopen) {
count += tcp_keepopen_proc(sk);
@@ -375,8 +375,8 @@ static void tcp_keepalive(unsigned long data)
}
}
out:
- chain_start = ((chain_start + ((TCP_HTABLE_SIZE/2)>>2)) &
- ((TCP_HTABLE_SIZE/2) - 1));
+ chain_start = ((chain_start + ((tcp_ehash_size/2)>>2)) &
+ ((tcp_ehash_size/2) - 1));
}
/*