diff options
author | Roland McGrath <roland@gnu.org> | 2000-02-05 12:21:17 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 2000-02-05 12:21:17 +0000 |
commit | e5f75e8ece5d1a8d3c17bd0156082caf153d3779 (patch) | |
tree | 316ee48be396f95770ccd5511ea442b83cadca51 /pfinet/linux-src/net | |
parent | b39cd08347c72483a4521a55301a0fa147a2a2b1 (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.c | 65 | ||||
-rw-r--r-- | pfinet/linux-src/net/ethernet/eth.c | 2 | ||||
-rw-r--r-- | pfinet/linux-src/net/ipv4/arp.c | 33 | ||||
-rw-r--r-- | pfinet/linux-src/net/ipv4/devinet.c | 11 | ||||
-rw-r--r-- | pfinet/linux-src/net/ipv4/icmp.c | 2 | ||||
-rw-r--r-- | pfinet/linux-src/net/ipv4/ip_forward.c | 15 | ||||
-rw-r--r-- | pfinet/linux-src/net/ipv4/ip_fw.c | 13 | ||||
-rw-r--r-- | pfinet/linux-src/net/ipv4/ip_input.c | 8 | ||||
-rw-r--r-- | pfinet/linux-src/net/ipv4/ip_masq.c | 25 | ||||
-rw-r--r-- | pfinet/linux-src/net/ipv4/ip_masq_user.c | 4 | ||||
-rw-r--r-- | pfinet/linux-src/net/ipv4/route.c | 2 | ||||
-rw-r--r-- | pfinet/linux-src/net/ipv4/syncookies.c | 8 | ||||
-rw-r--r-- | pfinet/linux-src/net/ipv4/tcp.c | 43 | ||||
-rw-r--r-- | pfinet/linux-src/net/ipv4/tcp_input.c | 4 | ||||
-rw-r--r-- | pfinet/linux-src/net/ipv4/tcp_ipv4.c | 39 | ||||
-rw-r--r-- | pfinet/linux-src/net/ipv4/tcp_timer.c | 10 |
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)); } /* |