www.usr.com/support/gpl/USR9113_release1.0.tar.gz
[bcm963xx.git] / kernel / linux / net / bridge / netfilter / ebt_ip.c
index 7bab7d0..dce03c6 100755 (executable)
@@ -18,6 +18,8 @@
 #include <linux/in.h>
 #include <linux/module.h>
 
+#define PPPOE_HDR_OFFSET 8
+
 struct tcpudphdr {
        uint16_t src;
        uint16_t dst;
@@ -29,45 +31,88 @@ static int ebt_filter_ip(const struct sk_buff *skb, const struct net_device *in,
 {
        struct ebt_ip_info *info = (struct ebt_ip_info *)data;
        union {struct iphdr iph; struct tcpudphdr ports;} u;
-
-       if (skb_copy_bits(skb, 0, &u.iph, sizeof(u.iph)))
-               return EBT_NOMATCH;
-       if (info->bitmask & EBT_IP_TOS &&
-          FWINV(info->tos != u.iph.tos, EBT_IP_TOS))
-               return EBT_NOMATCH;
-       if (info->bitmask & EBT_IP_SOURCE &&
-          FWINV((u.iph.saddr & info->smsk) !=
-          info->saddr, EBT_IP_SOURCE))
-               return EBT_NOMATCH;
-       if ((info->bitmask & EBT_IP_DEST) &&
-          FWINV((u.iph.daddr & info->dmsk) !=
-          info->daddr, EBT_IP_DEST))
-               return EBT_NOMATCH;
-       if (info->bitmask & EBT_IP_PROTO) {
-               if (FWINV(info->protocol != u.iph.protocol, EBT_IP_PROTO))
+       if(ETH_P_PPP_SES!= skb->mac.ethernet->h_proto)
+       {
+               if (skb_copy_bits(skb, 0, &u.iph, sizeof(u.iph)))
+                       return EBT_NOMATCH;
+               if (info->bitmask & EBT_IP_TOS &&
+                  FWINV(info->tos != u.iph.tos, EBT_IP_TOS))
                        return EBT_NOMATCH;
-               if (!(info->bitmask & EBT_IP_DPORT) &&
-                   !(info->bitmask & EBT_IP_SPORT))
-                       return EBT_MATCH;
-               if (skb_copy_bits(skb, u.iph.ihl*4, &u.ports,
-                   sizeof(u.ports)))
+               if (info->bitmask & EBT_IP_SOURCE &&
+                  FWINV((u.iph.saddr & info->smsk) !=
+                  info->saddr, EBT_IP_SOURCE))
                        return EBT_NOMATCH;
-               if (info->bitmask & EBT_IP_DPORT) {
-                       u.ports.dst = ntohs(u.ports.dst);
-                       if (FWINV(u.ports.dst < info->dport[0] ||
-                                 u.ports.dst > info->dport[1],
-                                 EBT_IP_DPORT))
+               if ((info->bitmask & EBT_IP_DEST) &&
+                  FWINV((u.iph.daddr & info->dmsk) !=
+                  info->daddr, EBT_IP_DEST))
                        return EBT_NOMATCH;
+               if (info->bitmask & EBT_IP_PROTO) {
+                       if (FWINV(info->protocol != u.iph.protocol, EBT_IP_PROTO))
+                               return EBT_NOMATCH;
+                       if (!(info->bitmask & EBT_IP_DPORT) &&
+                           !(info->bitmask & EBT_IP_SPORT))
+                               return EBT_MATCH;
+                       if (skb_copy_bits(skb, u.iph.ihl*4, &u.ports,
+                           sizeof(u.ports)))
+                               return EBT_NOMATCH;
+                       if (info->bitmask & EBT_IP_DPORT) {
+                               u.ports.dst = ntohs(u.ports.dst);
+                               if (FWINV(u.ports.dst < info->dport[0] ||
+                                         u.ports.dst > info->dport[1],
+                                         EBT_IP_DPORT))
+                               return EBT_NOMATCH;
+                       }
+                       if (info->bitmask & EBT_IP_SPORT) {
+                               u.ports.src = ntohs(u.ports.src);
+                               if (FWINV(u.ports.src < info->sport[0] ||
+                                         u.ports.src > info->sport[1],
+                                         EBT_IP_SPORT))
+                               return EBT_NOMATCH;
+                       }
                }
-               if (info->bitmask & EBT_IP_SPORT) {
-                       u.ports.src = ntohs(u.ports.src);
-                       if (FWINV(u.ports.src < info->sport[0] ||
-                                 u.ports.src > info->sport[1],
-                                 EBT_IP_SPORT))
+               return EBT_MATCH;
+       }
+       else
+       {
+               if (skb_copy_bits(skb, PPPOE_HDR_OFFSET, &u.iph, sizeof(u.iph)))
+                       return EBT_NOMATCH;
+               if (info->bitmask & EBT_IP_TOS &&
+                  FWINV(info->tos != u.iph.tos, EBT_IP_TOS))
+                       return EBT_NOMATCH;
+               if (info->bitmask & EBT_IP_SOURCE &&
+                  FWINV((u.iph.saddr & info->smsk) !=
+                  info->saddr, EBT_IP_SOURCE))
+                       return EBT_NOMATCH;
+               if ((info->bitmask & EBT_IP_DEST) &&
+                  FWINV((u.iph.daddr & info->dmsk) !=
+                  info->daddr, EBT_IP_DEST))
                        return EBT_NOMATCH;
+               if (info->bitmask & EBT_IP_PROTO) {
+                       if (FWINV(info->protocol != u.iph.protocol, EBT_IP_PROTO))
+                               return EBT_NOMATCH;
+                       if (!(info->bitmask & EBT_IP_DPORT) &&
+                           !(info->bitmask & EBT_IP_SPORT))
+                               return EBT_MATCH;
+                       if (skb_copy_bits(skb, u.iph.ihl*4+PPPOE_HDR_OFFSET, &u.ports,
+                           sizeof(u.ports)))
+                               return EBT_NOMATCH;
+                       if (info->bitmask & EBT_IP_DPORT) {
+                               u.ports.dst = ntohs(u.ports.dst);
+                               if (FWINV(u.ports.dst < info->dport[0] ||
+                                         u.ports.dst > info->dport[1],
+                                         EBT_IP_DPORT))
+                               return EBT_NOMATCH;
+                       }
+                       if (info->bitmask & EBT_IP_SPORT) {
+                               u.ports.src = ntohs(u.ports.src);
+                               if (FWINV(u.ports.src < info->sport[0] ||
+                                         u.ports.src > info->sport[1],
+                                         EBT_IP_SPORT))
+                               return EBT_NOMATCH;
+                       }
                }
+               return EBT_MATCH;
        }
-       return EBT_MATCH;
 }
 
 static int ebt_ip_check(const char *tablename, unsigned int hookmask,