diff -u --recursive --new-file v2.1.99/linux/Documentation/filesystems/vfs.txt linux/Documentation/filesystems/vfs.txt --- v2.1.99/linux/Documentation/filesystems/vfs.txt Sat May 2 14:19:51 1998 +++ linux/Documentation/filesystems/vfs.txt Sat May 2 14:35:51 1998 @@ -10,7 +10,6 @@ Hopefully this helps anyone attempting such a feat, as well as clearing up a few important points/dependencies. - register_filesystem (struct file_system_type *fstype) ===================================================== @@ -133,10 +132,12 @@ int (*follow_link) (struct inode *,struct inode *,int,int,struct inode **); [optional] - The follow_link function is only necessary if a filesystem uses a really - twisted form of symbolic links - namely if the symbolic link comes from a - foreign filesystem that makes no sense.... - I threw this one out - too much redundant code! + follow_link must be implemented if readlink is implemented. + Note that follow_link can return a different inode than a + lookup_dentry() on the result of readlink() would return. + The proc filesystem, in particular, uses this feature heavily. + For most user filesystems, however, follow_link() and readlink() + should return consistent results. int (*readpage) (struct inode *, struct page *); [optional] int (*writepage) (struct inode *, struct page *); [mandatory with readpage] diff -u --recursive --new-file v2.1.99/linux/Makefile linux/Makefile --- v2.1.99/linux/Makefile Sat May 2 14:19:52 1998 +++ linux/Makefile Fri May 1 11:20:31 1998 @@ -1,6 +1,6 @@ VERSION = 2 PATCHLEVEL = 1 -SUBLEVEL = 99 +SUBLEVEL = 100 ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/) diff -u --recursive --new-file v2.1.99/linux/drivers/net/sdla_fr.c linux/drivers/net/sdla_fr.c --- v2.1.99/linux/drivers/net/sdla_fr.c Wed Apr 8 19:36:27 1998 +++ linux/drivers/net/sdla_fr.c Sat May 2 14:22:29 1998 @@ -831,7 +831,7 @@ { int hdr_len = 0; skb->protocol = type; - hdr_len = wan_encapsulate(skb, dev); + hdr_len = wanrouter_encapsulate(skb, dev); if (hdr_len < 0) { hdr_len = 0; @@ -1486,7 +1486,7 @@ /* Decapsulate packet and pass it up the protocol stack */ skb->dev = dev; buf = skb_pull(skb, 1); /* remove hardware header */ - if (!wan_type_trans(skb, dev)) + if (!wanrouter_type_trans(skb, dev)) { /* can't decapsulate packet */ dev_kfree_skb(skb); @@ -1601,7 +1601,7 @@ skb->dev = dev; /* remove hardware header */ buf = skb_pull(skb, 1); - if (!wan_type_trans(skb, dev)) + if (!wanrouter_type_trans(skb, dev)) { /* can't decapsulate packet */ dev_kfree_skb(skb); @@ -2746,7 +2746,7 @@ stack */ new_skb->dev = dev; buf = skb_pull(new_skb, 1); /* remove hardware header */ - if (!wan_type_trans(new_skb, dev)) + if (!wanrouter_type_trans(new_skb, dev)) { ++chan->UDP_FPIPE_mgmt_not_passed_to_stack; /* can't decapsulate packet */ @@ -2944,7 +2944,7 @@ new_skb->dev = dev; /* remove hardware header */ buf = skb_pull(new_skb, 1); - if (!wan_type_trans(new_skb, dev)) + if (!wanrouter_type_trans(new_skb, dev)) { /* can't decapsulate packet */ ++chan->UDP_DRVSTATS_mgmt_not_passed_to_stack; diff -u --recursive --new-file v2.1.99/linux/drivers/net/sdla_x25.c linux/drivers/net/sdla_x25.c --- v2.1.99/linux/drivers/net/sdla_x25.c Wed Apr 8 19:36:27 1998 +++ linux/drivers/net/sdla_x25.c Sat May 2 14:22:29 1998 @@ -649,7 +649,7 @@ skb->protocol = type; if (!chan->protocol) { - hdr_len = wan_encapsulate(skb, dev); + hdr_len = wanrouter_encapsulate(skb, dev); if (hdr_len < 0) { hdr_len = 0; @@ -999,7 +999,7 @@ chan->rx_skb = NULL; /* dequeue packet */ /* Decapsulate packet, if necessary */ - if (!skb->protocol && !wan_type_trans(skb, dev)) + if (!skb->protocol && !wanrouter_type_trans(skb, dev)) { /* can't decapsulate packet */ dev_kfree_skb(skb); diff -u --recursive --new-file v2.1.99/linux/drivers/net/sdlamain.c linux/drivers/net/sdlamain.c --- v2.1.99/linux/drivers/net/sdlamain.c Mon Jan 12 14:46:16 1998 +++ linux/drivers/net/sdlamain.c Sat May 2 14:22:29 1998 @@ -152,7 +152,7 @@ wandev->setup = &setup; wandev->shutdown = &shutdown; wandev->ioctl = &ioctl; - err = register_wandev(wandev); + err = register_wan_device(wandev); if (err) { printk(KERN_ERR @@ -179,7 +179,7 @@ for (i = 0; i < ncards; ++i) { sdla_t* card = &card_array[i]; - unregister_wandev(card->devname); + unregister_wan_device(card->devname); } kfree(card_array); } diff -u --recursive --new-file v2.1.99/linux/drivers/net/smc-mca.c linux/drivers/net/smc-mca.c --- v2.1.99/linux/drivers/net/smc-mca.c Wed Apr 1 20:11:52 1998 +++ linux/drivers/net/smc-mca.c Sat May 2 14:22:29 1998 @@ -337,7 +337,7 @@ dev->name = namelist+(NAMELEN*this_dev); dev->irq = irq[this_dev]; dev->base_addr = io[this_dev]; - dev->init = ultra_probe; + dev->init = ultramca_probe; if (io[this_dev] == 0) { if (this_dev != 0) diff -u --recursive --new-file v2.1.99/linux/drivers/scsi/scsi_ioctl.c linux/drivers/scsi/scsi_ioctl.c --- v2.1.99/linux/drivers/scsi/scsi_ioctl.c Sat May 2 14:19:53 1998 +++ linux/drivers/scsi/scsi_ioctl.c Fri May 1 11:19:58 1998 @@ -17,8 +17,13 @@ #include "hosts.h" #include -#define MAX_RETRIES 5 -#define MAX_TIMEOUT (9 * HZ) +#define NORMAL_RETRIES 5 +#define NORMAL_TIMEOUT (10 * HZ) +#define FORMAT_UNIT_TIMEOUT (2 * 60 * 60 * HZ) +#define START_STOP_TIMEOUT (60 * HZ) +#define MOVE_MEDIUM_TIMEOUT (5 * 60 * HZ) +#define READ_ELEMENT_STATUS_TIMEOUT (5 * 60 * HZ) + #define MAX_BUF PAGE_SIZE #define max(a,b) (((a) > (b)) ? (a) : (b)) @@ -61,7 +66,7 @@ /* * * The SCSI_IOCTL_SEND_COMMAND ioctl sends a command out to the SCSI host. - * The MAX_TIMEOUT and MAX_RETRIES variables are used. + * The NORMAL_TIMEOUT and NORMAL_RETRIES variables are used. * * dev is the SCSI device struct ptr, *(int *) arg is the length of the * input data, if any, not including the command string & counts, @@ -94,7 +99,8 @@ } } -static int ioctl_internal_command(Scsi_Device *dev, char * cmd) +static int ioctl_internal_command(Scsi_Device *dev, char * cmd, + int timeout, int retries) { unsigned long flags; int result; @@ -107,9 +113,7 @@ struct semaphore sem = MUTEX_LOCKED; SCpnt->request.sem = &sem; spin_lock_irqsave(&io_request_lock, flags); - scsi_do_cmd(SCpnt, cmd, NULL, 0, - scsi_ioctl_done, MAX_TIMEOUT, - MAX_RETRIES); + scsi_do_cmd(SCpnt, cmd, NULL, 0, scsi_ioctl_done, timeout, retries); spin_unlock_irqrestore(&io_request_lock, flags); down(&sem); SCpnt->request.sem = NULL; @@ -250,21 +254,24 @@ switch (opcode) { case FORMAT_UNIT: - timeout = 2 * 60 * 60 * HZ; /* 2 Hours */ + timeout = FORMAT_UNIT_TIMEOUT; retries = 1; break; case START_STOP: - timeout = 2 * 60 * HZ; /* 2 minutes */ - retries = 1; + timeout = START_STOP_TIMEOUT; + retries = NORMAL_RETRIES; break; case MOVE_MEDIUM: + timeout = MOVE_MEDIUM_TIMEOUT; + retries = NORMAL_RETRIES; + break; case READ_ELEMENT_STATUS: - timeout = 5 * 60 * HZ; /* 5 minutes */ - retries = 1; + timeout = READ_ELEMENT_STATUS_TIMEOUT; + retries = NORMAL_RETRIES; break; default: - timeout = MAX_TIMEOUT; - retries = MAX_RETRIES; + timeout = NORMAL_TIMEOUT; + retries = NORMAL_RETRIES; break; } @@ -395,7 +402,8 @@ scsi_cmd[1] = dev->lun << 5; scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; scsi_cmd[4] = SCSI_REMOVAL_PREVENT; - return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd); + return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd, + NORMAL_TIMEOUT, NORMAL_RETRIES); break; case SCSI_IOCTL_DOORUNLOCK: if (!dev->removable || !dev->lockable) return 0; @@ -403,13 +411,31 @@ scsi_cmd[1] = dev->lun << 5; scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; scsi_cmd[4] = SCSI_REMOVAL_ALLOW; - return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd); + return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd, + NORMAL_TIMEOUT, NORMAL_RETRIES); case SCSI_IOCTL_TEST_UNIT_READY: scsi_cmd[0] = TEST_UNIT_READY; scsi_cmd[1] = dev->lun << 5; scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; scsi_cmd[4] = 0; - return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd); + return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd, + NORMAL_TIMEOUT, NORMAL_RETRIES); + break; + case SCSI_IOCTL_START_UNIT: + scsi_cmd[0] = START_STOP; + scsi_cmd[1] = dev->lun << 5; + scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; + scsi_cmd[4] = 1; + return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd, + START_STOP_TIMEOUT, NORMAL_RETRIES); + break; + case SCSI_IOCTL_STOP_UNIT: + scsi_cmd[0] = START_STOP; + scsi_cmd[1] = dev->lun << 5; + scsi_cmd[2] = scsi_cmd[3] = scsi_cmd[5] = 0; + scsi_cmd[4] = 0; + return ioctl_internal_command((Scsi_Device *) dev, scsi_cmd, + START_STOP_TIMEOUT, NORMAL_RETRIES); break; default : if (dev->host->hostt->ioctl) diff -u --recursive --new-file v2.1.99/linux/drivers/scsi/sd.c linux/drivers/scsi/sd.c --- v2.1.99/linux/drivers/scsi/sd.c Fri Apr 10 13:03:49 1998 +++ linux/drivers/scsi/sd.c Fri May 1 11:19:58 1998 @@ -1060,8 +1060,15 @@ } inode.i_rdev = full_dev; /* This is all we really need here */ - retval = sd_ioctl(&inode, NULL, SCSI_IOCTL_TEST_UNIT_READY, 0); + /* Using Start/Stop enables differentiation between drive with + * no cartridge loaded - NOT READY, drive with changed cartridge - + * UNIT ATTENTION, or with same cartridge - GOOD STATUS. + * This also handles drives that auto spin down. eg iomega jaz 1GB + * as this will spin up the drive. + */ + retval = sd_ioctl(&inode, NULL, SCSI_IOCTL_START_UNIT, 0); + if(retval){ /* Unable to test, unit probably not ready. This usually * means there is no disc in the drive. Mark as changed, * and we will figure it out later once the drive is diff -u --recursive --new-file v2.1.99/linux/fs/dcache.c linux/fs/dcache.c --- v2.1.99/linux/fs/dcache.c Sat May 2 14:19:53 1998 +++ linux/fs/dcache.c Sat May 2 14:07:52 1998 @@ -430,12 +430,17 @@ * more memory, but aren't really sure how much. So we * carefully try to free a _bit_ of our dcache, but not * too much. + * + * Priority: + * 0 - very urgent: schrink everything + * ... + * 6 - base-level: try to shrink a bit. */ -void shrink_dcache_memory(void) +void shrink_dcache_memory(int priority, unsigned int gfp_mask) { int count = select_dcache(32, 8); if (count) - prune_dcache(count); + prune_dcache((count << 6) >> priority); } #define NAME_ALLOC_LEN(len) ((len+16) & ~15) diff -u --recursive --new-file v2.1.99/linux/fs/namei.c linux/fs/namei.c --- v2.1.99/linux/fs/namei.c Sat May 2 14:19:53 1998 +++ linux/fs/namei.c Fri May 1 11:21:54 1998 @@ -43,17 +43,24 @@ * * The new code replaces the old recursive symlink resolution with * an iterative one (in case of non-nested symlink chains). It does - * this by looking up the symlink name from the particular filesystem, - * and then follows this name as if it were a user-supplied one. This - * is done solely in the VFS level, such that _follow_link() is not - * used any more and could be removed in future. As a side effect, - * dir_namei(), _namei() and follow_link() are now replaced with a single - * function lookup_dentry() that can handle all the special cases of the former - * code. + * this with calls to _follow_link(). + * As a side effect, dir_namei(), _namei() and follow_link() are now + * replaced with a single function lookup_dentry() that can handle all + * the special cases of the former code. * * With the new dcache, the pathname is stored at each inode, at least as * long as the refcount of the inode is positive. As a side effect, the * size of the dcache depends on the inode cache and thus is dynamic. + * + * [29-Apr-1998 C. Scott Ananian] Updated above description of symlink + * resolution to correspond with current state of the code. + * + * Note that the symlink resolution is not *completely* iterative. + * There is still a significant amount of tail- and mid- recursion in + * the algorithm. Also, note that _readlink() is not used in + * lookup_dentry(): lookup_dentry() on the result of _readlink() + * may return different results than _follow_link(). Many virtual + * filesystems (including /proc) exhibit this behavior. */ /* [24-Feb-97 T. Schoebel-Theuer] Side effects caused by new implementation: diff -u --recursive --new-file v2.1.99/linux/include/linux/icmpv6.h linux/include/linux/icmpv6.h --- v2.1.99/linux/include/linux/icmpv6.h Fri Feb 6 15:33:34 1998 +++ linux/include/linux/icmpv6.h Sat May 2 14:22:29 1998 @@ -138,9 +138,12 @@ __u32 info, struct device *dev); -extern void icmpv6_init(struct net_proto_family *ops); +extern int icmpv6_init(struct net_proto_family *ops); extern int icmpv6_err_convert(int type, int code, int *err); +extern void icmpv6_cleanup(void); +extern void icmpv6_param_prob(struct sk_buff *skb, + int code, void *pos); #endif #endif diff -u --recursive --new-file v2.1.99/linux/include/linux/ipv6.h linux/include/linux/ipv6.h --- v2.1.99/linux/include/linux/ipv6.h Fri Feb 6 15:33:34 1998 +++ linux/include/linux/ipv6.h Sat May 2 14:22:29 1998 @@ -42,6 +42,24 @@ */ }; + +struct ipv6_opt_hdr { + __u8 nexthdr; + __u8 hdrlen; + /* + * TLV encoded option data follows. + */ +}; + +#define ipv6_destopt_hdr ipv6_opt_hdr +#define ipv6_hopopt_hdr ipv6_opt_hdr + +#ifdef __KERNEL__ +#define ipv6_optlen(p) (((p)->hdrlen+1) << 3) +#endif + + + /* * routing header type 0 (used in cmsghdr struct) */ @@ -95,12 +113,12 @@ /* * protocol options - * usualy carried in IPv6 extension headers + * usually carried in IPv6 extension headers */ struct ipv6_rt_hdr *srcrt; /* Routing Header */ - }; + #endif diff -u --recursive --new-file v2.1.99/linux/include/net/ipv6.h linux/include/net/ipv6.h --- v2.1.99/linux/include/net/ipv6.h Tue Mar 17 22:18:15 1998 +++ linux/include/net/ipv6.h Sat May 2 14:22:29 1998 @@ -4,7 +4,7 @@ * Authors: * Pedro Roque * - * $Id: ipv6.h,v 1.9 1998/03/08 05:55:20 davem Exp $ + * $Id: ipv6.h,v 1.10 1998/04/30 16:24:14 freitag Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -108,6 +108,8 @@ struct frag_queue *prev; __u32 id; /* fragment id */ + struct in6_addr saddr; + struct in6_addr daddr; struct timer_list timer; /* expire timer */ struct ipv6_frag *fragments; struct device *dev; @@ -247,6 +249,10 @@ int len); extern void ipv6opt_free(struct ipv6_options *opt); + +extern struct ipv6_opt_hdr * ipv6_skip_exthdr(struct ipv6_opt_hdr *hdr, + u8 *nexthdrp, int len); + /* diff -u --recursive --new-file v2.1.99/linux/include/net/ndisc.h linux/include/net/ndisc.h --- v2.1.99/linux/include/net/ndisc.h Fri Feb 6 15:35:04 1998 +++ linux/include/net/ndisc.h Sat May 2 14:22:29 1998 @@ -101,6 +101,8 @@ struct icmp6hdr *hdr, int len); +extern void igmp6_cleanup(void); + extern __inline__ struct neighbour * ndisc_get_neigh(struct device *dev, struct in6_addr *addr) { diff -u --recursive --new-file v2.1.99/linux/include/net/tcp.h linux/include/net/tcp.h --- v2.1.99/linux/include/net/tcp.h Sat May 2 14:19:54 1998 +++ linux/include/net/tcp.h Sat May 2 14:22:29 1998 @@ -642,7 +642,7 @@ /* PMTU discovery event has occurred. */ sk->mtu = dst->pmtu; - sk->mss = sk->mtu - mss_distance; + mss_now = sk->mss = sk->mtu - mss_distance; } if(tp->sack_ok && tp->num_sacks) diff -u --recursive --new-file v2.1.99/linux/include/scsi/scsi_ioctl.h linux/include/scsi/scsi_ioctl.h --- v2.1.99/linux/include/scsi/scsi_ioctl.h Sat May 2 14:19:54 1998 +++ linux/include/scsi/scsi_ioctl.h Fri May 1 11:19:58 1998 @@ -5,6 +5,8 @@ #define SCSI_IOCTL_TEST_UNIT_READY 2 #define SCSI_IOCTL_BENCHMARK_COMMAND 3 #define SCSI_IOCTL_SYNC 4 /* Request synchronous parameters */ +#define SCSI_IOCTL_START_UNIT 5 +#define SCSI_IOCTL_STOP_UNIT 6 /* The door lock/unlock constants are compatible with Sun constants for the cdrom */ #define SCSI_IOCTL_DOORLOCK 0x5380 /* lock the eject mechanism */ diff -u --recursive --new-file v2.1.99/linux/mm/vmscan.c linux/mm/vmscan.c --- v2.1.99/linux/mm/vmscan.c Sat May 2 14:19:54 1998 +++ linux/mm/vmscan.c Sat May 2 14:04:52 1998 @@ -455,17 +455,20 @@ switch (state) { do { case 0: - state = 1; if (shrink_mmap(i, gfp_mask)) return 1; + state = 1; case 1: - state = 2; if ((gfp_mask & __GFP_IO) && shm_swap(i, gfp_mask)) return 1; - default: - state = 0; + state = 2; + case 2: if (swap_out(i, gfp_mask)) return 1; + state = 3; + case 3: + shrink_dcache_memory(i, gfp_mask); + state = 0; i--; } while ((i - stop) >= 0); } @@ -545,9 +548,6 @@ schedule(); swapstats.wakeups++; - /* This will gently shrink the dcache.. */ - shrink_dcache_memory(); - /* * Do the background pageout: be * more aggressive if we're really diff -u --recursive --new-file v2.1.99/linux/net/core/dev.c linux/net/core/dev.c --- v2.1.99/linux/net/core/dev.c Sat May 2 14:19:54 1998 +++ linux/net/core/dev.c Sat May 2 14:22:29 1998 @@ -1764,6 +1764,9 @@ extern int lapbeth_init(void); extern void arcnet_init(void); extern void ip_auto_config(void); +#ifdef CONFIG_8xx +extern int cpm_enet_init(void); +#endif /* CONFIG_8xx */ #ifdef CONFIG_PROC_FS static struct proc_dir_entry proc_net_dev = { @@ -1845,6 +1848,9 @@ #endif #if defined(CONFIG_ARCNET) arcnet_init(); +#endif +#if defined(CONFIG_8xx) + cpm_enet_init(); #endif /* * SLHC if present needs attaching so other people see it diff -u --recursive --new-file v2.1.99/linux/net/ethernet/pe2.c linux/net/ethernet/pe2.c --- v2.1.99/linux/net/ethernet/pe2.c Sun Mar 24 22:58:24 1996 +++ linux/net/ethernet/pe2.c Sat May 2 14:22:29 1998 @@ -11,7 +11,8 @@ struct device *dev = skb->dev; skb->protocol = htons (ETH_P_IPX); - dev->hard_header(skb, dev, ETH_P_IPX, dest_node, NULL, skb->len); + if(dev->hard_header) + dev->hard_header(skb, dev, ETH_P_IPX, dest_node, NULL, skb->len); } struct datalink_proto * diff -u --recursive --new-file v2.1.99/linux/net/ipv4/ip_fw.c linux/net/ipv4/ip_fw.c --- v2.1.99/linux/net/ipv4/ip_fw.c Thu Mar 26 15:57:13 1998 +++ linux/net/ipv4/ip_fw.c Sat May 2 14:22:29 1998 @@ -6,7 +6,7 @@ * license in recognition of the original copyright. * -- Alan Cox. * - * $Id: ip_fw.c,v 1.34 1998/03/20 09:12:06 davem Exp $ + * $Id: ip_fw.c,v 1.35 1998/04/30 16:29:51 freitag Exp $ * * Ported from BSD to Linux, * Alan Cox 22/Nov/1994. @@ -62,6 +62,7 @@ * Wouter Gadeyne : Fixed masquerading support of ftp PORT commands * * Juan Jose Ciarlante : Masquerading code moved to ip_masq.c + * Andi Kleen : Print frag_offsets and the ip flags properly. * * All the real work was done by ..... * @@ -202,6 +203,90 @@ #if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL) +#ifdef CONFIG_IP_FIREWALL_VERBOSE + +/* + * VERY ugly piece of code which actually makes kernel printf for + * matching packets. + */ + +static char *chain_name(struct ip_fw *chain, int mode) +{ + switch (mode) { + case IP_FW_MODE_ACCT_IN: return "acct in"; + case IP_FW_MODE_ACCT_OUT: return "acct out"; + default: + if (chain == ip_fw_fwd_chain) + return "fw-fwd"; + else if (chain == ip_fw_in_chain) + return "fw-in"; + else + return "fw-out"; + } +} + +static char *rule_name(struct ip_fw *f, int mode, char *buf) +{ + if (mode == IP_FW_MODE_ACCT_IN || mode == IP_FW_MODE_ACCT_OUT) + return ""; + + if(f->fw_flg&IP_FW_F_ACCEPT) { + if(f->fw_flg&IP_FW_F_REDIR) { + sprintf(buf, "acc/r%d ", f->fw_pts[f->fw_nsp+f->fw_ndp]); + return buf; + } else if(f->fw_flg&IP_FW_F_MASQ) + return "acc/masq "; + else + return "acc "; + } else if(f->fw_flg&IP_FW_F_ICMPRPL) { + return "rej "; + } else { + return "deny "; + } +} + +static void print_packet(struct iphdr *ip, + u16 src_port, u16 dst_port, u16 icmp_type, + char *chain, char *rule, char *devname) +{ + __u32 *opt = (__u32 *) (ip + 1); + int opti; + __u16 foff = ntohs(ip->frag_off); + + printk(KERN_INFO "IP %s %s%s", chain, rule, devname); + + switch(ip->protocol) + { + case IPPROTO_TCP: + printk(" TCP "); + break; + case IPPROTO_UDP: + printk(" UDP "); + break; + case IPPROTO_ICMP: + printk(" ICMP/%d ", icmp_type); + break; + default: + printk(" PROTO=%d ", ip->protocol); + break; + } + print_ip(ip->saddr); + if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP) + printk(":%hu", src_port); + printk(" "); + print_ip(ip->daddr); + if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP) + printk(":%hu", dst_port); + printk(" L=%hu S=0x%2.2hX I=%hu FO=0x%4.4hX T=%hu", + ntohs(ip->tot_len), ip->tos, ntohs(ip->id), + foff & IP_OFFSET, ip->ttl); + if (foff & IP_DF) printk(" DF=1"); + if (foff & IP_MF) printk(" MF=1"); + for (opti = 0; opti < (ip->ihl - sizeof(struct iphdr) / 4); opti++) + printk(" O=0x%8.8X", *opt++); + printk("\n"); +} +#endif /* * Returns one of the generic firewall policies, like FW_ACCEPT. @@ -483,68 +568,14 @@ } #ifdef CONFIG_IP_FIREWALL_VERBOSE - /* - * VERY ugly piece of code which actually - * makes kernel printf for matching packets... - */ - if (f->fw_flg & IP_FW_F_PRN) { - __u32 *opt = (__u32 *) (ip + 1); - int opti; + char buf[16]; - if(mode == IP_FW_MODE_ACCT_IN) - printk(KERN_INFO "IP acct in "); - else if(mode == IP_FW_MODE_ACCT_OUT) - printk(KERN_INFO "IP acct out "); - else { - if(chain == ip_fw_fwd_chain) - printk(KERN_INFO "IP fw-fwd "); - else if(chain == ip_fw_in_chain) - printk(KERN_INFO "IP fw-in "); - else - printk(KERN_INFO "IP fw-out "); - if(f->fw_flg&IP_FW_F_ACCEPT) { - if(f->fw_flg&IP_FW_F_REDIR) - printk("acc/r%d ", f->fw_pts[f->fw_nsp+f->fw_ndp]); - else if(f->fw_flg&IP_FW_F_MASQ) - printk("acc/masq "); - else - printk("acc "); - } else if(f->fw_flg&IP_FW_F_ICMPRPL) - printk("rej "); - else - printk("deny "); - } - printk(rif ? rif->name : "-"); - switch(ip->protocol) - { - case IPPROTO_TCP: - printk(" TCP "); - break; - case IPPROTO_UDP: - printk(" UDP "); - break; - case IPPROTO_ICMP: - printk(" ICMP/%d ", icmp_type); - break; - default: - printk(" PROTO=%d ", ip->protocol); - break; - } - print_ip(ip->saddr); - if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP) - printk(":%hu", src_port); - printk(" "); - print_ip(ip->daddr); - if(ip->protocol == IPPROTO_TCP || ip->protocol == IPPROTO_UDP) - printk(":%hu", dst_port); - printk(" L=%hu S=0x%2.2hX I=%hu F=0x%4.4hX T=%hu", - ntohs(ip->tot_len), ip->tos, ntohs(ip->id), - ip->frag_off, ip->ttl); - for (opti = 0; opti < (ip->ihl - sizeof(struct iphdr) / 4); opti++) - printk(" O=0x%8.8X", *opt++); - printk("\n"); + print_packet(ip, src_port, dst_port, icmp_type, + chain_name(chain, mode), + rule_name(f, mode, buf), + rif ? rif->name : "-"); } #endif if (mode != IP_FW_MODE_CHK) { diff -u --recursive --new-file v2.1.99/linux/net/ipv4/tcp_input.c linux/net/ipv4/tcp_input.c --- v2.1.99/linux/net/ipv4/tcp_input.c Sat May 2 14:19:55 1998 +++ linux/net/ipv4/tcp_input.c Sat May 2 14:22:29 1998 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_input.c,v 1.114 1998/04/28 06:42:22 davem Exp $ + * Version: $Id: tcp_input.c,v 1.116 1998/05/02 14:50:11 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -421,33 +421,6 @@ return 1; } -#if 0 /* Not working yet... -DaveM */ -static void tcp_compute_tsack(struct sock *sk, struct tcp_opt *tp) -{ - struct sk_buff *skb = skb_peek(&sk->write_queue); - __u32 tstamp = tp->rcv_tsecr; - int fack_count = 0; - - while((skb != NULL) && - (skb != tp->send_head) && - (skb != (struct sk_buff *)&sk->write_queue)) { - if(TCP_SKB_CB(skb)->when == tstamp) { - __u8 sacked = TCP_SKB_CB(skb)->sacked; - - sacked |= TCPCB_SACKED_ACKED; - if(sacked & TCPCB_SACKED_RETRANS) - tp->retrans_out--; - TCP_SKB_CB(skb)->sacked = sacked; - } - if(!before(TCP_SKB_CB(skb)->when, tstamp)) - fack_count++; - skb = skb->next; - } - if(fack_count > tp->fackets_out) - tp->fackets_out = fack_count; -} -#endif - #define FLAG_DATA 0x01 /* Incoming frame contained data. */ #define FLAG_WIN_UPDATE 0x02 /* Incoming ACK was a window update. */ #define FLAG_DATA_ACKED 0x04 /* This ACK acknowledged new data. */ @@ -481,13 +454,6 @@ if (ack == tp->snd_una && tp->packets_out && (not_dup == 0)) { /* This is the standard reno style fast retransmit branch. */ -#if 0 /* Not working yet... -DaveM */ - /* If not doing SACK, but doing timestamps, compute timestamp - * based pseudo-SACKs when we see duplicate ACKs. - */ - if(!tp->sack_ok && tp->saw_tstamp) - tcp_compute_tsack(sk, tp); -#endif /* 1. When the third duplicate ack is received, set ssthresh * to one half the current congestion window, but no less * than two segments. Retransmit the missing segment. @@ -611,6 +577,7 @@ while((skb=skb_peek(&sk->write_queue)) && (skb != tp->send_head)) { struct tcp_skb_cb *scb = TCP_SKB_CB(skb); + __u8 sacked = scb->sacked; /* If our packet is before the ack sequence we can * discard it as it's confirmed to have arrived at @@ -626,22 +593,12 @@ * connection startup slow start one packet too * quickly. This is severely frowned upon behavior. */ + if(sacked & TCPCB_SACKED_RETRANS && tp->retrans_out) + tp->retrans_out--; if(!(scb->flags & TCPCB_FLAG_SYN)) { - __u8 sacked = scb->sacked; - acked |= FLAG_DATA_ACKED; - if(sacked & TCPCB_SACKED_RETRANS) { + if(sacked & TCPCB_SACKED_RETRANS) acked |= FLAG_RETRANS_DATA_ACKED; - - /* XXX The race is, fast retrans frame --> - * XXX retrans timeout sends older frame --> - * XXX ACK arrives for fast retrans frame --> - * XXX retrans_out goes negative --> splat. - * XXX Please help me find a better way -DaveM - */ - if(tp->retrans_out) - tp->retrans_out--; - } if(tp->fackets_out) tp->fackets_out--; } else { diff -u --recursive --new-file v2.1.99/linux/net/ipv4/tcp_ipv4.c linux/net/ipv4/tcp_ipv4.c --- v2.1.99/linux/net/ipv4/tcp_ipv4.c Sat May 2 14:19:55 1998 +++ linux/net/ipv4/tcp_ipv4.c Sat May 2 14:22:29 1998 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_ipv4.c,v 1.142 1998/04/30 12:00:45 davem Exp $ + * Version: $Id: tcp_ipv4.c,v 1.145 1998/05/02 12:47:13 davem Exp $ * * IPv4 specific functions * @@ -48,7 +48,6 @@ #include #include -#include #include #include #include @@ -61,12 +60,15 @@ #include #include +#include extern int sysctl_tcp_timestamps; extern int sysctl_tcp_window_scaling; extern int sysctl_tcp_sack; extern int sysctl_tcp_syncookies; extern int sysctl_ip_dynaddr; +extern __u32 sysctl_wmem_max; +extern __u32 sysctl_rmem_max; /* Check TCP sequence numbers in ICMP packets. */ #define ICMP_MIN_LENGTH 8 @@ -166,17 +168,21 @@ return tb; } +#ifdef CONFIG_IP_TRANSPARENT_PROXY /* Ensure that the bound bucket for the port exists. * Return 0 on success. */ static __inline__ int tcp_bucket_check(unsigned short snum) { - if (tcp_bound_hash[tcp_bhashfn(snum)] == NULL && - tcp_bucket_create(snum) == NULL) + struct tcp_bind_bucket *tb = tcp_bound_hash[tcp_bhashfn(snum)]; + for( ; (tb && (tb->port != snum)); tb = tb->next) + ; + if(tb == NULL && tcp_bucket_create(snum) == NULL) return 1; else return 0; } +#endif static int tcp_v4_verify_bind(struct sock *sk, unsigned short snum) { @@ -215,10 +221,21 @@ result = 1; } } - if((result == 0) && - (tb == NULL) && - (tcp_bucket_create(snum) == NULL)) - result = 1; + if(result == 0) { + if(tb == NULL) { + if(tcp_bucket_create(snum) == NULL) + result = 1; + } else { + /* It could be pending garbage collection, this + * kills the race and prevents it from disappearing + * out from under us by the time we use it. -DaveM + */ + if(tb->owners == NULL && !(tb->flags & TCPB_FLAG_LOCKED)) { + tb->flags = TCPB_FLAG_LOCKED; + tcp_dec_slow_timer(TCP_SLT_BUCKETGC); + } + } + } go_like_smoke: SOCKHASH_UNLOCK(); return result; @@ -1308,6 +1325,11 @@ if (!newsk) goto exit; + if (newsk->rcvbuf < (3 * newsk->mtu)) + newsk->rcvbuf = min ((3 * newsk->mtu), sysctl_rmem_max); + if (newsk->sndbuf < (3 * newsk->mtu)) + newsk->sndbuf = min ((3 * newsk->mtu), sysctl_wmem_max); + sk->tp_pinfo.af_tcp.syn_backlog--; sk->ack_backlog++; diff -u --recursive --new-file v2.1.99/linux/net/ipv4/tcp_timer.c linux/net/ipv4/tcp_timer.c --- v2.1.99/linux/net/ipv4/tcp_timer.c Sat May 2 14:19:55 1998 +++ linux/net/ipv4/tcp_timer.c Sat May 2 14:22:29 1998 @@ -5,7 +5,7 @@ * * Implementation of the Transmission Control Protocol(TCP). * - * Version: $Id: tcp_timer.c,v 1.50 1998/04/14 09:08:59 davem Exp $ + * Version: $Id: tcp_timer.c,v 1.51 1998/05/02 15:19:26 davem Exp $ * * Authors: Ross Biro, * Fred N. van Kempen, @@ -448,26 +448,24 @@ */ if(tp->sack_ok) { struct sk_buff *skb = skb_peek(&sk->write_queue); - __u8 toclear = TCPCB_SACKED_ACKED; - if(tp->retransmits == 0) - toclear |= TCPCB_SACKED_RETRANS; while((skb != NULL) && (skb != tp->send_head) && (skb != (struct sk_buff *)&sk->write_queue)) { - TCP_SKB_CB(skb)->sacked &= ~(toclear); + TCP_SKB_CB(skb)->sacked &= + ~(TCPCB_SACKED_ACKED | TCPCB_SACKED_RETRANS); skb = skb->next; } - tp->fackets_out = 0; } /* Retransmission. */ tp->retrans_head = NULL; + tp->fackets_out = 0; + tp->retrans_out = 0; if (tp->retransmits == 0) { /* remember window where we lost * "one half of the current window but at least 2 segments" */ - tp->retrans_out = 0; tp->snd_ssthresh = max(tp->snd_cwnd >> (1 + TCP_CWND_SHIFT), 2); tp->snd_cwnd = (1 << TCP_CWND_SHIFT); } diff -u --recursive --new-file v2.1.99/linux/net/ipv6/exthdrs.c linux/net/ipv6/exthdrs.c --- v2.1.99/linux/net/ipv6/exthdrs.c Tue Mar 17 22:18:16 1998 +++ linux/net/ipv6/exthdrs.c Sat May 2 14:22:29 1998 @@ -4,8 +4,9 @@ * * Authors: * Pedro Roque + * Andi Kleen * - * $Id: exthdrs.c,v 1.5 1998/02/12 07:43:39 davem Exp $ + * $Id: exthdrs.c,v 1.6 1998/04/30 16:24:20 freitag Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -34,6 +35,10 @@ #include #include +#include + +#define swap(a,b) do { typeof (a) tmp; tmp = (a); (a) = (b); (b) = (tmp); } while(0) + /* * inbound */ @@ -135,7 +140,7 @@ */ int ipv6opt_bld_rthdr(struct sk_buff *skb, struct ipv6_options *opt, - struct in6_addr *addr, int proto) + struct in6_addr *addr) { struct rt0_hdr *phdr, *ihdr; int hops; @@ -153,8 +158,76 @@ ipv6_addr_copy(phdr->addr + (hops - 1), addr); - phdr->rt_hdr.nexthdr = proto; - + phdr->rt_hdr.nexthdr = proto; return NEXTHDR_ROUTING; } #endif + +/* + * find out if nexthdr is an extension header or a protocol + */ + +static __inline__ int ipv6_ext_hdr(u8 nexthdr) +{ + /* + * find out if nexthdr is an extension header or a protocol + */ + return ( (nexthdr == NEXTHDR_HOP) || + (nexthdr == NEXTHDR_ROUTING) || + (nexthdr == NEXTHDR_FRAGMENT) || + (nexthdr == NEXTHDR_ESP) || + (nexthdr == NEXTHDR_AUTH) || + (nexthdr == NEXTHDR_NONE) || + (nexthdr == NEXTHDR_DEST) ); + +} + +/* + * Skip any extension headers. This is used by the ICMP module. + * + * Note that strictly speaking this conflicts with RFC1883 4.0: + * ...The contents and semantics of each extension header determine whether + * or not to proceed to the next header. Therefore, extension headers must + * be processed strictly in the order they appear in the packet; a + * receiver must not, for example, scan through a packet looking for a + * particular kind of extension header and process that header prior to + * processing all preceding ones. + * + * We do exactly this. This is a protocol bug. We can't decide after a + * seeing an unknown discard-with-error flavour TLV option if it's a + * ICMP error message or not (errors should never be send in reply to + * ICMP error messages). + * + * But I see no other way to do this. This might need to be reexamined + * when Linux implements ESP (and maybe AUTH) headers. + */ +struct ipv6_opt_hdr *ipv6_skip_exthdr(struct ipv6_opt_hdr *hdr, + u8 *nexthdrp, int len) +{ + u8 nexthdr = *nexthdrp; + + while (ipv6_ext_hdr(nexthdr)) { + int hdrlen; + + if (nexthdr == NEXTHDR_NONE) + return NULL; + if (len < sizeof(struct ipv6_opt_hdr)) /* be anal today */ + return NULL; + + hdrlen = ipv6_optlen(hdr); + if (len < hdrlen) + return NULL; + + nexthdr = hdr->nexthdr; + hdr = (struct ipv6_opt_hdr *) ((u8*)hdr + hdrlen); + len -= hdrlen; + } + + /* Hack.. Do the same for AUTH headers? */ + if (nexthdr == NEXTHDR_ESP) + return NULL; + + *nexthdrp = nexthdr; + return hdr; +} + diff -u --recursive --new-file v2.1.99/linux/net/ipv6/icmp.c linux/net/ipv6/icmp.c --- v2.1.99/linux/net/ipv6/icmp.c Thu Mar 26 15:57:13 1998 +++ linux/net/ipv6/icmp.c Sat May 2 14:22:30 1998 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: icmp.c,v 1.15 1998/03/21 07:28:03 davem Exp $ + * $Id: icmp.c,v 1.17 1998/05/01 10:31:41 davem Exp $ * * Based on net/ipv4/icmp.c * @@ -21,6 +21,8 @@ * Changes: * * Andi Kleen : exception handling + * Andi Kleen add rate limits. never reply to a icmp. + * add more length checks and other fixes. */ #define __NO_VERSION__ @@ -51,6 +53,7 @@ #include #include #include +#include #include #include @@ -129,6 +132,62 @@ return 0; } + +/* + * Slightly more convenient version of icmpv6_send. + */ +void icmpv6_param_prob(struct sk_buff *skb, int code, void *pos) +{ + int offset = (u8*)pos - (u8*)skb->nh.ipv6h; + + icmpv6_send(skb, ICMPV6_PARAMPROB, code, offset, skb->dev); + kfree_skb(skb); +} + +static inline int is_icmp(struct ipv6hdr *hdr, int len) +{ + __u8 nexthdr = hdr->nexthdr; + + if (!ipv6_skip_exthdr((struct ipv6_opt_hdr *)(hdr+1), &nexthdr, len)) + return 0; + return nexthdr == IPPROTO_ICMP; +} + +int sysctl_icmpv6_time = 1*HZ; + +/* + * Check the ICMP output rate limit + */ +static inline int icmpv6_xrlim_allow(struct sock *sk, int type, + struct flowi *fl) +{ +#if 0 + struct dst_entry *dst; + int allow = 0; +#endif + /* Informational messages are not limited. */ + if (type & 0x80) + return 1; + +#if 0 /* not yet, first fix routing COW */ + + /* + * Look up the output route. + * XXX: perhaps the expire for routing entries cloned by + * this lookup should be more aggressive (not longer than timeout). + */ + dst = ip6_route_output(sk, fl, 1); + if (dst->error) + ipv6_statistics.Ip6OutNoRoutes++; + else + allow = xrlim_allow(dst, sysctl_icmpv6_time); + dst_release(dst); + return allow; +#else + return 1; +#endif +} + /* * an inline helper for the "simple" if statement below * checks if parameter problem report is caused by an @@ -214,6 +273,24 @@ return; } + /* + * Never answer to a ICMP packet. + */ + if (is_icmp(hdr, (u8*)skb->tail - (u8*)hdr)) { + printk(KERN_DEBUG "icmpv6_send: no reply to icmp\n"); + return; + } + + fl.proto = IPPROTO_ICMPV6; + fl.nl_u.ip6_u.daddr = &hdr->saddr; + fl.nl_u.ip6_u.saddr = saddr; + fl.oif = iif; + fl.uli_u.icmpt.type = type; + fl.uli_u.icmpt.code = code; + + if (!icmpv6_xrlim_allow(sk, type, &fl)) + return; + /* * ok. kick it. checksum will be provided by the * getfrag_t callback. @@ -248,13 +325,6 @@ msg.len = len; - fl.proto = IPPROTO_ICMPV6; - fl.nl_u.ip6_u.daddr = &hdr->saddr; - fl.nl_u.ip6_u.saddr = saddr; - fl.oif = iif; - fl.uli_u.icmpt.type = type; - fl.uli_u.icmpt.code = code; - ip6_build_xmit(sk, icmpv6_getfrag, &msg, &fl, len, NULL, -1, MSG_DONTWAIT); @@ -312,21 +382,6 @@ dst_release(xchg(&sk->dst_cache, NULL)); } -static __inline__ int ipv6_ext_hdr(u8 nexthdr) -{ - /* - * find out if nexthdr is an extension header or a protocol - */ - return ( (nexthdr == NEXTHDR_HOP) || - (nexthdr == NEXTHDR_ROUTING) || - (nexthdr == NEXTHDR_FRAGMENT) || - (nexthdr == NEXTHDR_ESP) || - (nexthdr == NEXTHDR_AUTH) || - (nexthdr == NEXTHDR_NONE) || - (nexthdr == NEXTHDR_DEST) ); - -} - static void icmpv6_notify(struct sk_buff *skb, int type, int code, unsigned char *buff, int len, struct in6_addr *saddr, struct in6_addr *daddr, @@ -335,39 +390,22 @@ struct ipv6hdr *hdr = (struct ipv6hdr *) buff; struct inet6_protocol *ipprot; struct sock *sk; - char * pbuff; + struct ipv6_opt_hdr *pb; __u32 info = 0; int hash; u8 nexthdr; - /* now skip over extension headers */ - nexthdr = hdr->nexthdr; - pbuff = (char *) (hdr + 1); + pb = (struct ipv6_opt_hdr *) (hdr + 1); len -= sizeof(struct ipv6hdr); + if (len < 0) + return; - while (ipv6_ext_hdr(nexthdr)) { - int hdrlen; - - if (nexthdr == NEXTHDR_NONE) - return; - - nexthdr = *pbuff; - - /* Header length is size in 8-octet units, not - * including the first 8 octets. - */ - hdrlen = *(pbuff+1); - hdrlen = (hdrlen + 1) << 3; - - if (hdrlen > len) - return; - - /* Now this is right. */ - pbuff += hdrlen; - len -= hdrlen; - } + /* now skip over extension headers */ + pb = ipv6_skip_exthdr(pb, &nexthdr, len); + if (!pb) + return; hash = nexthdr & (MAX_INET_PROTOS - 1); @@ -378,7 +416,7 @@ continue; if (ipprot->err_handler) - ipprot->err_handler(skb, type, code, pbuff, info, + ipprot->err_handler(skb, type, code, (u8*)pb, info, saddr, daddr, ipprot); return; } @@ -391,7 +429,7 @@ return; while((sk = raw_v6_lookup(sk, nexthdr, daddr, saddr))) { - rawv6_err(sk, type, code, pbuff, saddr, daddr); + rawv6_err(sk, type, code, (char*)pb, saddr, daddr); sk = sk->next; } } @@ -514,7 +552,7 @@ return 0; } -__initfunc(void icmpv6_init(struct net_proto_family *ops)) +__initfunc(int icmpv6_init(struct net_proto_family *ops)) { struct sock *sk; int err; @@ -528,11 +566,11 @@ icmpv6_socket->state = SS_UNCONNECTED; icmpv6_socket->type=SOCK_RAW; - if((err=ops->create(icmpv6_socket, IPPROTO_ICMPV6))<0) + if((err=ops->create(icmpv6_socket, IPPROTO_ICMPV6))<0) { printk(KERN_DEBUG "Failed to create the ICMP6 control socket.\n"); - - MOD_DEC_USE_COUNT; + return 1; + } sk = icmpv6_socket->sk; sk->allocation = GFP_ATOMIC; @@ -542,6 +580,16 @@ ndisc_init(ops); igmp6_init(ops); + return 0; +} + +void icmpv6_cleanup(void) +{ + inet6_del_protocol(&icmpv6_protocol); +#if 0 + ndisc_cleanup(); +#endif + igmp6_cleanup(); } static struct icmp6_err { diff -u --recursive --new-file v2.1.99/linux/net/ipv6/ip6_input.c linux/net/ipv6/ip6_input.c --- v2.1.99/linux/net/ipv6/ip6_input.c Tue Mar 17 22:18:16 1998 +++ linux/net/ipv6/ip6_input.c Sat May 2 14:22:30 1998 @@ -6,7 +6,7 @@ * Pedro Roque * Ian P. Morris * - * $Id: ip6_input.c,v 1.8 1998/02/12 07:43:43 davem Exp $ + * $Id: ip6_input.c,v 1.9 1998/04/30 16:24:24 freitag Exp $ * * Based in linux/net/ipv4/ip_input.c * @@ -69,12 +69,6 @@ u8 type; u8 len; }; - -struct ipv6_destopt_hdr { - u8 nexthdr; - u8 hdrlen; -}; - struct tlvtype_proc { u8 type; diff -u --recursive --new-file v2.1.99/linux/net/ipv6/ipv6_sockglue.c linux/net/ipv6/ipv6_sockglue.c --- v2.1.99/linux/net/ipv6/ipv6_sockglue.c Thu Mar 26 15:57:13 1998 +++ linux/net/ipv6/ipv6_sockglue.c Sat May 2 14:22:30 1998 @@ -7,7 +7,7 @@ * * Based on linux/net/ipv4/ip_sockglue.c * - * $Id: ipv6_sockglue.c,v 1.18 1998/03/20 09:12:18 davem Exp $ + * $Id: ipv6_sockglue.c,v 1.19 1998/04/30 16:24:26 freitag Exp $ * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -242,7 +242,7 @@ ipv6_sysctl_unregister(); #endif ip6_route_cleanup(); - ndisc_cleanup(); + icmpv6_cleanup(); addrconf_cleanup(); } #endif diff -u --recursive --new-file v2.1.99/linux/net/ipv6/mcast.c linux/net/ipv6/mcast.c --- v2.1.99/linux/net/ipv6/mcast.c Thu Mar 26 15:57:13 1998 +++ linux/net/ipv6/mcast.c Sat May 2 14:22:30 1998 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: mcast.c,v 1.14 1998/03/20 09:12:18 davem Exp $ + * $Id: mcast.c,v 1.15 1998/04/30 16:24:28 freitag Exp $ * * Based on linux/ipv4/igmp.c and linux/ipv4/ip_sockglue.c * @@ -619,8 +619,6 @@ printk(KERN_DEBUG "Failed to create the IGMP6 control socket.\n"); - MOD_DEC_USE_COUNT; - sk = igmp6_socket->sk; sk->allocation = GFP_ATOMIC; sk->num = 256; /* Don't receive any data */ @@ -632,3 +630,9 @@ #endif } +void igmp6_cleanup(void) +{ +#ifdef CONFIG_PROC_FS + remove_proc_entry("net/igmp6", 0); +#endif +} diff -u --recursive --new-file v2.1.99/linux/net/ipv6/ndisc.c linux/net/ipv6/ndisc.c --- v2.1.99/linux/net/ipv6/ndisc.c Thu Mar 26 15:57:13 1998 +++ linux/net/ipv6/ndisc.c Sat May 2 14:22:30 1998 @@ -1152,9 +1152,6 @@ printk(KERN_DEBUG "Failed to create the NDISC control socket.\n"); - /* Eeeh... What is it? --ANK */ - MOD_DEC_USE_COUNT; - sk = ndisc_socket->sk; sk->allocation = GFP_ATOMIC; sk->net_pinfo.af_inet6.hop_limit = 255; diff -u --recursive --new-file v2.1.99/linux/net/ipv6/reassembly.c linux/net/ipv6/reassembly.c --- v2.1.99/linux/net/ipv6/reassembly.c Tue Mar 17 22:18:16 1998 +++ linux/net/ipv6/reassembly.c Sat May 2 14:22:30 1998 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: reassembly.c,v 1.9 1998/02/12 07:43:48 davem Exp $ + * $Id: reassembly.c,v 1.10 1998/04/30 16:24:32 freitag Exp $ * * Based on: net/ipv4/ip_fragment.c * @@ -15,6 +15,11 @@ * 2 of the License, or (at your option) any later version. */ +/* + * Fixes: + * Andi Kleen Make it work with multiple hosts. + * More RFC compliance. + */ #include #include #include @@ -39,8 +44,9 @@ static struct frag_queue ipv6_frag_queue = { &ipv6_frag_queue, &ipv6_frag_queue, - 0, {0}, NULL, NULL, - 0 + 0, {{{0}}}, {{{0}}}, + {0}, NULL, NULL, + 0, 0, NULL }; static void create_frag_entry(struct sk_buff *skb, @@ -72,12 +78,11 @@ * one it's the kmalloc for a struct ipv6_frag. * Feel free to try other alternatives... */ - reasm_queue(fq, *skb, fhdr); - if ((fhdr->frag_off & __constant_htons(0x0001)) == 0) { fq->last_in = 1; fq->nhptr = nhptr; } + reasm_queue(fq, *skb, fhdr); if (fq->last_in) { if ((nh = reasm_frag_1(fq, skb))) @@ -90,18 +95,27 @@ return 0; } -int ipv6_reassembly(struct sk_buff **skb, struct device *dev, __u8 *nhptr, +int ipv6_reassembly(struct sk_buff **skbp, struct device *dev, __u8 *nhptr, struct ipv6_options *opt) { - struct frag_hdr *fhdr = (struct frag_hdr *) ((*skb)->h.raw); + struct sk_buff *skb = *skbp; + struct frag_hdr *fhdr = (struct frag_hdr *) (skb->h.raw); struct frag_queue *fq; - + struct ipv6hdr *hdr; + + if ((u8 *)(fhdr+1) > skb->tail) { + icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb->h.raw); + return 0; + } + hdr = skb->nh.ipv6h; for (fq = ipv6_frag_queue.next; fq != &ipv6_frag_queue; fq = fq->next) { - if (fq->id == fhdr->identification) - return reasm_frag(fq, skb, nhptr,fhdr); + if (fq->id == fhdr->identification && + !ipv6_addr_cmp(&hdr->saddr, &fq->saddr) && + !ipv6_addr_cmp(&hdr->daddr, &fq->daddr)) + return reasm_frag(fq, skbp, nhptr,fhdr); } - create_frag_entry(*skb, dev, nhptr, fhdr); + create_frag_entry(skb, dev, nhptr, fhdr); return 0; } @@ -154,6 +168,7 @@ struct frag_hdr *fhdr) { struct frag_queue *fq; + struct ipv6hdr *hdr; fq = (struct frag_queue *) kmalloc(sizeof(struct frag_queue), GFP_ATOMIC); @@ -167,6 +182,10 @@ fq->id = fhdr->identification; + hdr = skb->nh.ipv6h; + ipv6_addr_copy(&fq->saddr, &hdr->saddr); + ipv6_addr_copy(&fq->daddr, &hdr->daddr); + fq->dev = dev; /* init_timer has been done by the memset */ @@ -193,14 +212,14 @@ static void reasm_queue(struct frag_queue *fq, struct sk_buff *skb, - struct frag_hdr *fhdr) + struct frag_hdr *fhdr) { struct ipv6_frag *nfp, *fp, **bptr; nfp = (struct ipv6_frag *) kmalloc(sizeof(struct ipv6_frag), GFP_ATOMIC); - if (nfp == NULL) { + if (nfp == NULL) { kfree_skb(skb); return; } @@ -209,6 +228,10 @@ nfp->len = (ntohs(skb->nh.ipv6h->payload_len) - ((u8 *) (fhdr + 1) - (u8 *) (skb->nh.ipv6h + 1))); + if ((u32)nfp->offset + (u32)nfp->len > 65536) { + icmpv6_param_prob(skb,ICMPV6_HDR_FIELD, (u8*)&fhdr->frag_off); + goto err; + } nfp->skb = skb; nfp->fhdr = fhdr; @@ -224,19 +247,37 @@ } if (fp && fp->offset == nfp->offset) { - if (fp->len != nfp->len) { - /* this cannot happen */ + if (nfp->len != fp->len) { printk(KERN_DEBUG "reasm_queue: dup with wrong len\n"); } /* duplicate. discard it. */ - kfree_skb(skb); - kfree(nfp); - return; + goto err; } *bptr = nfp; nfp->next = fp; + +#ifdef STRICT_RFC + if (fhdr->frag_off & __constant_htons(0x0001)) { + /* Check if the fragment is rounded to 8 bytes. + * Required by the RFC. + */ + if (nfp->len & 0x7) { + printk(KERN_DEBUG "fragment not rounded to 8bytes\n"); + + icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, + &skb->nh.ipv6h->payload_len); + goto err; + } + } +#endif + + return; + +err: + kfree(nfp); + kfree_skb(skb); } /* @@ -303,6 +344,8 @@ /* * FIXME: If we don't have a checksum we ought to be able * to defragment and checksum in this pass. [AC] + * Note that we don't really know yet whether the protocol + * needs checksums at all. It might still be a good idea. -AK */ for(fp = fq->fragments; fp; ) { struct ipv6_frag *back; diff -u --recursive --new-file v2.1.99/linux/net/ipv6/tcp_ipv6.c linux/net/ipv6/tcp_ipv6.c --- v2.1.99/linux/net/ipv6/tcp_ipv6.c Sat May 2 14:19:55 1998 +++ linux/net/ipv6/tcp_ipv6.c Sat May 2 14:22:30 1998 @@ -5,7 +5,7 @@ * Authors: * Pedro Roque * - * $Id: tcp_ipv6.c,v 1.78 1998/04/16 16:29:22 freitag Exp $ + * $Id: tcp_ipv6.c,v 1.80 1998/05/02 12:47:15 davem Exp $ * * Based on: * linux/net/ipv4/tcp.c @@ -123,10 +123,21 @@ result = 1; } } - if((result == 0) && - (tb == NULL) && - (tcp_bucket_create(snum) == NULL)) - result = 1; + if(result == 0) { + if(tb == NULL) { + if(tcp_bucket_create(snum) == NULL) + result = 1; + } else { + /* It could be pending garbage collection, this + * kills the race and prevents it from disappearing + * out from under us by the time we use it. -DaveM + */ + if(tb->owners == NULL && !(tb->flags & TCPB_FLAG_LOCKED)) { + tb->flags = TCPB_FLAG_LOCKED; + tcp_dec_slow_timer(TCP_SLT_BUCKETGC); + } + } + } go_like_smoke: SOCKHASH_UNLOCK(); return result; @@ -731,7 +742,7 @@ isn = tcp_v6_init_sequence(sk,skb); /* - * There are no SYN attacks on IPv6, yet... + * There are no SYN attacks on IPv6, yet... */ if (BACKLOG(sk) >= BACKLOGMAX(sk)) { printk(KERN_DEBUG "droping syn ack:%d max:%d\n", diff -u --recursive --new-file v2.1.99/linux/net/netsyms.c linux/net/netsyms.c --- v2.1.99/linux/net/netsyms.c Sat May 2 14:19:55 1998 +++ linux/net/netsyms.c Sat May 2 14:22:30 1998 @@ -458,7 +458,7 @@ EXPORT_SYMBOL(qdisc_new_estimator); EXPORT_SYMBOL(qdisc_kill_estimator); #endif -#ifdef CONFIG_NET_POLICE +#ifdef CONFIG_NET_CLS_POLICE EXPORT_SYMBOL(tcf_police); EXPORT_SYMBOL(tcf_police_locate); EXPORT_SYMBOL(tcf_police_destroy);