]> git.neil.brown.name Git - history.git/commitdiff
Import 1.3.66 1.3.66
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:10:35 +0000 (15:10 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:10:35 +0000 (15:10 -0500)
Makefile
drivers/char/console.c
drivers/char/keyboard.c
include/linux/ip_fw.h
include/net/tcp.h
net/core/sock.c
net/ipv4/ip_fw.c
net/ipv4/tcp_input.c

index fbf202f2e72636b8fca784fdcf630b28d9993f52..da1b340fea7e74679a5605e8f4f97f76477c3045 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 3
-SUBLEVEL = 65
+SUBLEVEL = 66
 
 ARCH = i386
 
index 56e94219f1b29c1fcffecf7415c07cebe75c7570..7da2fae0d1a7d9c3fc628a8bc8f2bc2d0019cb51 100644 (file)
@@ -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;
 }
 
index 425710e5ba027727b0a8b0e33b5742bcb9cfc725..a3018131d7fdeb02d31f76cf3df200ccb980ccf5 100644 (file)
@@ -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];
index 968bf3fd6da44c02030639f548e57028469af7b0..8ef7ad86da865373161f6945f06f1b179bc3758c 100644 (file)
@@ -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 */
 };
 
 /*
index 9493e774f8e19de88d907cee0965f42630318ae4..28b58406b9bd45d1e4cdf73e4be30e53edd8e61b 100644 (file)
@@ -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 */
index e022c1c095a13c2e977eb507fc35d6a553b3e7ab..505f3bdbece270d56b88e641522cd440b838734b 100644 (file)
@@ -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  
 }
index 890decf9db44671bf650b2faff8092b562a41e35..81f7d78121139760c49084950ddf5813240baeb2 100644 (file)
@@ -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 <jos@xos.nl> 8/2/1996.
+ *     Add support for matching on device names.
+ *             Jos Vos <jos@xos.nl> 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
 }
index 0a2d10eabd6dd4b94a341b4c599149ae36b145d8..19ea9fb84be365c2ab6fce373556d920052767ec 100644 (file)
@@ -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
         */