From 343c5aed4b129b9e70330cb628edf51ad2d5a1e7 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Fri, 23 Nov 2007 15:10:35 -0500 Subject: [PATCH] Import 1.3.66 --- Makefile | 2 +- drivers/char/console.c | 4 +- drivers/char/keyboard.c | 1 + include/linux/ip_fw.h | 7 +- include/net/tcp.h | 37 +++++---- net/core/sock.c | 6 +- net/ipv4/ip_fw.c | 164 +++++++++++++++++++++++++++++----------- net/ipv4/tcp_input.c | 9 +++ 8 files changed, 166 insertions(+), 64 deletions(-) diff --git a/Makefile b/Makefile index fbf202f2e726..da1b340fea7e 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ VERSION = 1 PATCHLEVEL = 3 -SUBLEVEL = 65 +SUBLEVEL = 66 ARCH = i386 diff --git a/drivers/char/console.c b/drivers/char/console.c index 56e94219f1b2..7da2fae0d1a7 100644 --- a/drivers/char/console.c +++ b/drivers/char/console.c @@ -1386,7 +1386,7 @@ static int con_write(struct tty_struct * tty, int from_user, if (currcons == sel_cons) clear_selection(); - disable_bh(KEYBOARD_BH); + disable_bh(CONSOLE_BH); while (!tty->stopped && count) { c = from_user ? get_user(buf) : *buf; buf++; n++; count--; @@ -1820,7 +1820,7 @@ static int con_write(struct tty_struct * tty, int from_user, } if (vcmode != KD_GRAPHICS) set_cursor(currcons); - enable_bh(KEYBOARD_BH); + enable_bh(CONSOLE_BH); return n; } diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c index 425710e5ba02..a3018131d7fd 100644 --- a/drivers/char/keyboard.c +++ b/drivers/char/keyboard.c @@ -376,6 +376,7 @@ static void keyboard_interrupt(int irq, struct pt_regs *regs) goto end_kbd_intr; } do_poke_blanked_console = 1; + mark_bh(CONSOLE_BH); add_keyboard_randomness(scancode); tty = ttytab[fg_console]; diff --git a/include/linux/ip_fw.h b/include/linux/ip_fw.h index 968bf3fd6da4..8ef7ad86da86 100644 --- a/include/linux/ip_fw.h +++ b/include/linux/ip_fw.h @@ -20,6 +20,7 @@ * chains, new "insert" and "append" * commands to replace "add" commands, * add ICMP header to struct ip_fwpkt. + * Jos Vos : Add support for matching device names. * * All the real work was done by ..... */ @@ -55,6 +56,7 @@ struct ip_fw struct in_addr fw_src, fw_dst; /* Source and destination IP addr */ struct in_addr fw_smsk, fw_dmsk; /* Mask for src and dest IP addr */ struct in_addr fw_via; /* IP address of interface "via" */ + struct device *fw_viadev; /* device of interface "via" */ unsigned short fw_flg; /* Flags word */ unsigned short fw_nsp, fw_ndp; /* N'of src ports and # of dst ports */ /* in ports array (dst ports follow */ @@ -63,7 +65,8 @@ struct ip_fw #define IP_FW_MAX_PORTS 10 /* A reasonable maximum */ unsigned short fw_pts[IP_FW_MAX_PORTS]; /* Array of port numbers to match */ unsigned long fw_pcnt,fw_bcnt; /* Packet and byte counters */ - unsigned char fw_tosand, fw_tosxor; /* Revised packet priority */ + unsigned char fw_tosand, fw_tosxor; /* Revised packet priority */ + char fw_vianame[IFNAMSIZ]; /* name of interface "via" */ }; /* @@ -112,6 +115,7 @@ struct ip_fw #define IP_FW_IN 1 #define IP_FW_OUT 2 #define IP_FW_ACCT 3 +#define IP_FW_CHAINS 4 /* total number of ip_fw chains */ #define IP_FW_INSERT (IP_FW_BASE_CTL) #define IP_FW_APPEND (IP_FW_BASE_CTL+1) @@ -160,6 +164,7 @@ struct ip_fwpkt struct icmphdr fwp_icmph; /* ICMP header */ } fwp_protoh; struct in_addr fwp_via; /* interface address */ + char fwp_vianame[IFNAMSIZ]; /* interface name */ }; /* diff --git a/include/net/tcp.h b/include/net/tcp.h index 9493e774f8e1..28b58406b9bd 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -295,24 +295,33 @@ static char *statename[]={ static __inline__ void tcp_set_state(struct sock *sk, int state) { - if(sk->state==TCP_ESTABLISHED) - tcp_statistics.TcpCurrEstab--; + int oldstate = sk->state; + + sk->state = state; + #ifdef STATE_TRACE if(sk->debug) - printk("TCP sk=%p, State %s -> %s\n",sk, statename[sk->state],statename[state]); + printk("TCP sk=%p, State %s -> %s\n",sk, statename[oldstate],statename[state]); #endif - /* This is a hack but it doesn't occur often and it's going to - be a real to fix nicely */ - - if(state==TCP_ESTABLISHED && sk->state==TCP_SYN_RECV) - { - wake_up_interruptible(&master_select_wakeup); - } - sk->state=state; - if(state==TCP_ESTABLISHED) - tcp_statistics.TcpCurrEstab++; - if(sk->state==TCP_CLOSE) + + switch (state) { + case TCP_ESTABLISHED: + if (oldstate != TCP_ESTABLISHED) { + tcp_statistics.TcpCurrEstab++; + /* This is a hack but it doesn't occur often and it's going to + be a real to fix nicely */ + if (oldstate == TCP_SYN_RECV) + wake_up_interruptible(&master_select_wakeup); + } + break; + + case TCP_CLOSE: tcp_cache_zap(); + /* fall through */ + default: + if (oldstate==TCP_ESTABLISHED) + tcp_statistics.TcpCurrEstab--; + } } #endif /* _TCP_H */ diff --git a/net/core/sock.c b/net/core/sock.c index e022c1c095a1..505f3bdbece2 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -570,10 +570,10 @@ void __release_sock(struct sock *sk) sk->users = 0; barrier(); } - if (sk->dead && sk->state == TCP_CLOSE) - { + + if (sk->dead && sk->state == TCP_CLOSE) { /* Should be about 2 rtt's */ - reset_timer(sk, TIME_DONE, min(sk->rtt * 2, TCP_DONE_TIME)); + reset_timer(sk, TIME_DONE, min(sk->rtt * 2, TCP_DONE_TIME)); } #endif } diff --git a/net/ipv4/ip_fw.c b/net/ipv4/ip_fw.c index 890decf9db44..81f7d7812113 100644 --- a/net/ipv4/ip_fw.c +++ b/net/ipv4/ip_fw.c @@ -31,6 +31,8 @@ * only delete the first matching entry, use 0xFFFF (0xFF) as ports (ICMP * types) when counting packets being 2nd and further fragments. * Jos Vos 8/2/1996. + * Add support for matching on device names. + * Jos Vos 15/2/1996. * * Masquerading functionality * @@ -363,13 +365,23 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int pol if (match) { /* - * Look for a VIA match + * Look for a VIA address match */ if(f->fw_via.s_addr && rif) { if(rif->pa_addr!=f->fw_via.s_addr) continue; /* Mismatch */ } + + /* + * Look for a VIA device match + */ + if(f->fw_viadev) + { + if(rif!=f->fw_viadev) + continue; /* Mismatch */ + } + /* * Drop through - this is a match */ @@ -472,43 +484,39 @@ int ip_fw_chk(struct iphdr *ip, struct device *rif, struct ip_fw *chain, int pol break; } /* Loop */ - answer = FW_BLOCK; - - /* - * We rely on policy defined in the rejecting entry or, if no match - * was found, we rely on the general policy variable for this type - * of firewall. - */ + if (opt != 1) { - if(f!=NULL) - { - policy=f->fw_flg; - tosand=f->fw_tosand; - tosxor=f->fw_tosxor; - } - else - { - tosand=0xFF; - tosxor=0x00; - } - - if(opt != 1) - { - if(policy&IP_FW_F_ACCEPT) + /* + * We rely on policy defined in the rejecting entry or, if no match + * was found, we rely on the general policy variable for this type + * of firewall. + */ + + if (f!=NULL) { + policy=f->fw_flg; + tosand=f->fw_tosand; + tosxor=f->fw_tosxor; + } else { + tosand=0xFF; + tosxor=0x00; + } + + if (policy&IP_FW_F_ACCEPT) { + /* Adjust priority and recompute checksum */ + __u8 old_tos = ip->tos; + ip->tos = (old_tos & tosand) ^ tosxor; + if (ip->tos != old_tos) + ip_send_check(ip); answer=(policy&IP_FW_F_MASQ)?FW_MASQUERADE:FW_ACCEPT; + } else if(policy&IP_FW_F_ICMPRPL) + answer = FW_REJECT; else - if(policy&IP_FW_F_ICMPRPL) - answer = FW_REJECT; - } - - if (policy&IP_FW_F_ACCEPT) { /* Adjust priority and recompute checksum */ - __u8 old_tos = ip->tos; - ip->tos = (old_tos & tosand) ^ tosxor; - if (ip->tos != old_tos) - ip_send_check(ip); - } + answer = FW_BLOCK; - return answer; + return answer; + } else + /* we're doing accounting, always ok */ + return 0; } #ifdef CONFIG_IP_MASQUERADE @@ -897,6 +905,7 @@ void ip_fw_masquerade(struct sk_buff **skb_ptr, struct device *dev) } else ms->timer.expires = jiffies+MASQUERADE_EXPIRE_TCP; + skb->csum = csum_partial(th + 1, size - sizeof(*th), 0); tcp_send_check(th,iph->saddr,iph->daddr,size,skb); } add_timer(&ms->timer); @@ -1002,6 +1011,8 @@ int ip_fw_demasquerade(struct sk_buff *skb) #endif } } + skb->csum = csum_partial(portptr + sizeof(struct tcphdr), + size - sizeof(struct tcphdr), 0); tcp_send_check((struct tcphdr *)portptr,iph->saddr,iph->daddr,size,skb); } ip_send_check(iph); @@ -1072,6 +1083,12 @@ static int insert_in_chain(struct ip_fw *volatile* chainptr, struct ip_fw *frwl, cli(); + if ((ftmp->fw_vianame)[0]) { + if (!(ftmp->fw_viadev = dev_get(ftmp->fw_vianame))) + ftmp->fw_viadev = (struct device *) -1; + } else + ftmp->fw_viadev = NULL; + ftmp->fw_next = *chainptr; *chainptr=ftmp; restore_flags(flags); @@ -1106,6 +1123,12 @@ static int append_to_chain(struct ip_fw *volatile* chainptr, struct ip_fw *frwl, cli(); + if ((ftmp->fw_vianame)[0]) { + if (!(ftmp->fw_viadev = dev_get(ftmp->fw_vianame))) + ftmp->fw_viadev = (struct device *) -1; + } else + ftmp->fw_viadev = NULL; + chtmp_prev=NULL; for (chtmp=*chainptr;chtmp!=NULL;chtmp=chtmp->fw_next) chtmp_prev=chtmp; @@ -1145,7 +1168,7 @@ static int del_from_chain(struct ip_fw *volatile*chainptr, struct ip_fw *frwl) while( !was_found && ftmp != NULL ) { matches=1; - if (ftmp->fw_src.s_addr!=frwl->fw_src.s_addr + if (ftmp->fw_src.s_addr!=frwl->fw_src.s_addr || ftmp->fw_dst.s_addr!=frwl->fw_dst.s_addr || ftmp->fw_smsk.s_addr!=frwl->fw_smsk.s_addr || ftmp->fw_dmsk.s_addr!=frwl->fw_dmsk.s_addr @@ -1163,6 +1186,8 @@ static int del_from_chain(struct ip_fw *volatile*chainptr, struct ip_fw *frwl) if (ftmp->fw_pts[tmpnum]!=frwl->fw_pts[tmpnum]) matches=0; } + if (strncmp(ftmp->fw_vianame, frwl->fw_vianame, IFNAMSIZ)) + matches=0; if(matches) { was_found=1; @@ -1332,11 +1357,11 @@ int ip_fw_ctl(int stage, void *m, int len) if ( cmd == IP_FW_CHECK ) { - struct device viadev; + struct device *viadev; struct ip_fwpkt *ipfwp; struct iphdr *ip; - if ( len < sizeof(struct ip_fwpkt) ) + if ( len != sizeof(struct ip_fwpkt) ) { #ifdef DEBUG_CONFIG_IP_FIREWALL printk("ip_fw_ctl: length=%d, expected %d\n", @@ -1348,8 +1373,18 @@ int ip_fw_ctl(int stage, void *m, int len) ipfwp = (struct ip_fwpkt *)m; ip = &(ipfwp->fwp_iph); - if ( ip->ihl != sizeof(struct iphdr) / sizeof(int)) - { + if ( !(viadev = dev_get(ipfwp->fwp_vianame)) ) { +#ifdef DEBUG_CONFIG_IP_FIREWALL + printk("ip_fw_ctl: invalid device \"%s\"\n", ipfwp->fwp_vianame); +#endif + return(EINVAL); + } else if ( viadev->pa_addr != ipfwp->fwp_via.s_addr ) { +#ifdef DEBUG_CONFIG_IP_FIREWALL + printk("ip_fw_ctl: device \"%s\" has another IP address\n", + ipfwp->fwp_vianame); +#endif + return(EINVAL); + } else if ( ip->ihl != sizeof(struct iphdr) / sizeof(int)) { #ifdef DEBUG_CONFIG_IP_FIREWALL printk("ip_fw_ctl: ip->ihl=%d, want %d\n",ip->ihl, sizeof(struct iphdr)/sizeof(int)); @@ -1357,9 +1392,7 @@ int ip_fw_ctl(int stage, void *m, int len) return(EINVAL); } - viadev.pa_addr = ipfwp->fwp_via.s_addr; - - if ((ret = ip_fw_chk(ip, &viadev, *chains[fwtype], + if ((ret = ip_fw_chk(ip, viadev, *chains[fwtype], *policies[fwtype], 2)) == FW_ACCEPT) return(0); else if (ret == FW_MASQUERADE) @@ -1459,9 +1492,10 @@ static int ip_chain_procinfo(int stage, char *buffer, char **start, while(i!=NULL) { - len+=sprintf(buffer+len,"%08lX/%08lX->%08lX/%08lX %08lX %X ", + len+=sprintf(buffer+len,"%08lX/%08lX->%08lX/%08lX %.16s %08lX %X ", ntohl(i->fw_src.s_addr),ntohl(i->fw_smsk.s_addr), ntohl(i->fw_dst.s_addr),ntohl(i->fw_dmsk.s_addr), + (i->fw_vianame)[0] ? i->fw_vianame : "-", ntohl(i->fw_via.s_addr),i->fw_flg); len+=sprintf(buffer+len,"%u %u %-9lu %-9lu", i->fw_nsp,i->fw_ndp, i->fw_pcnt,i->fw_bcnt); @@ -1611,6 +1645,46 @@ struct firewall_ops ipfw_ops= #endif +#if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL) + +int ipfw_device_event(struct notifier_block *this, unsigned long event, void *ptr) +{ + struct device *dev=ptr; + char *devname = dev->name; + unsigned long flags; + struct ip_fw *fw; + int chn; + + save_flags(flags); + cli(); + + if (event == NETDEV_UP) { + for (chn = 0; chn < IP_FW_CHAINS; chn++) + for (fw = *chains[chn]; fw; fw = fw->fw_next) + if ((fw->fw_vianame)[0] && !strncmp(devname, + fw->fw_vianame, IFNAMSIZ)) + fw->fw_viadev = dev; + } else if (event == NETDEV_DOWN) { + for (chn = 0; chn < IP_FW_CHAINS; chn++) + for (fw = *chains[chn]; fw; fw = fw->fw_next) + /* we could compare just the pointers ... */ + if ((fw->fw_vianame)[0] && !strncmp(devname, + fw->fw_vianame, IFNAMSIZ)) + fw->fw_viadev = (struct device *) -1; + } + + restore_flags(flags); + return NOTIFY_DONE; +} + +static struct notifier_block ipfw_dev_notifier={ + ipfw_device_event, + NULL, + 0 +}; + +#endif + void ip_fw_init(void) { #ifdef CONFIG_IP_ACCT @@ -1653,4 +1727,8 @@ void ip_fw_init(void) ip_msqhst_procinfo }); #endif +#if defined(CONFIG_IP_ACCT) || defined(CONFIG_IP_FIREWALL) + /* Register for device up/down reports */ + register_netdevice_notifier(&ipfw_dev_notifier); +#endif } diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 0a2d10eabd6d..19ea9fb84be3 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -1929,6 +1929,15 @@ rfc_step6: /* I'll clean this up later */ if(tcp_data(skb,sk, saddr, len)) kfree_skb(skb, FREE_READ); + /* + * Finally, if we've moved to TCP_CLOSE, check if we should + * get rid of the socket + */ + if (sk->dead && sk->state == TCP_CLOSE) { + /* Should be about 2 rtt's */ + reset_timer(sk, TIME_DONE, min(sk->rtt * 2, TCP_DONE_TIME)); + } + /* * And done */ -- 2.39.5