static u16 imq_hash(struct net_device *dev, struct sk_buff *skb) { unsigned int pull_len; u16 protocol = skb->protocol; u32 addr1, addr2; u32 hash, ihl = 0; union { u16 in16[2]; u32 in32; } ports; u8 ip_proto; pull_len = 0; recheck: switch (protocol) { case htons(ETH_P_8021Q): { if (unlikely(skb_pull(skb, VLAN_HLEN) == NULL)) goto other; pull_len += VLAN_HLEN; skb->network_header += VLAN_HLEN; protocol = vlan_eth_hdr(skb)->h_vlan_encapsulated_proto; goto recheck; } case htons(ETH_P_PPP_SES): { if (unlikely(skb_pull(skb, PPPOE_SES_HLEN) == NULL)) goto other; pull_len += PPPOE_SES_HLEN; skb->network_header += PPPOE_SES_HLEN; protocol = pppoe_proto(skb); goto recheck; } case htons(ETH_P_IP): { const struct iphdr *iph = ip_hdr(skb); if (unlikely(!pskb_may_pull(skb, sizeof(struct iphdr)))) goto other; addr1 = iph->daddr; addr2 = iph->saddr; ip_proto = !(ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) ? iph->protocol : 0; ihl = ip_hdrlen(skb); break; } #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) case htons(ETH_P_IPV6): { const struct ipv6hdr *iph = ipv6_hdr(skb); if (unlikely(!pskb_may_pull(skb, sizeof(struct ipv6hdr)))) goto other; addr1 = iph->daddr.s6_addr32[3]; addr2 = iph->saddr.s6_addr32[3]; ihl = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &ip_proto); if (unlikely(ihl < 0)) goto other; break; } #endif default: other: if (pull_len != 0) { skb_push(skb, pull_len); skb->network_header -= pull_len; } return (u16)(ntohs(protocol) % dev->real_num_tx_queues); } if (addr1 > addr2) swap(addr1, addr2); switch (ip_proto) { case IPPROTO_TCP: case IPPROTO_UDP: case IPPROTO_DCCP: case IPPROTO_ESP: case IPPROTO_AH: case IPPROTO_SCTP: case IPPROTO_UDPLITE: { if (likely(skb_copy_bits(skb, ihl, &ports.in32, 4) >= 0)) { if (ports.in16[0] > ports.in16[1]) swap(ports.in16[0], ports.in16[1]); break; } /* fall-through */ } default: ports.in32 = 0; break; } if (pull_len != 0) { skb_push(skb, pull_len); skb->network_header -= pull_len; } hash = jhash_3words(addr1, addr2, ports.in32, imq_hashrnd ^ ip_proto); return (u16)(((u64)hash * dev->real_num_tx_queues) >> 32); }
static bool ebt_ip_mt(const struct sk_buff *skb, struct xt_action_param *par) { const struct ebt_ip_info *info = par->matchinfo; const struct iphdr *ih; struct iphdr _iph; const struct tcpudphdr *pptr; struct tcpudphdr _ports; #if 1 /*Rodney_20090724*/ if(skb->protocol == htons(ETH_P_IP)) ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph); else if((skb->protocol == htons(ETH_P_8021Q)) && (vlan_proto(skb) == htons(ETH_P_IP))) ih = (struct iphdr *)(skb_mac_header(skb) + VLAN_ETH_HLEN); else if((skb->protocol == htons(ETH_P_PPP_SES)) && (pppoe_proto(skb) == htons(0x0021))) ih = (struct iphdr *)(skb_mac_header(skb) + ETH_HLEN +PPPOE_SES_HLEN); else ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph); #else ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph); #endif if (ih == NULL) return false; #if 1 /*Rodney_20090724*/ if (info->bitmask & EBT_IP_IPP){ if (FWINV((ih->tos & 0xe0) < info->ipp[0] || (ih->tos & 0xe0) > info->ipp[1], EBT_IP_IPP)) return false; } if (info->bitmask & EBT_IP_DSCP){ if (FWINV((ih->tos & 0xfc) < info->dscp[0] || (ih->tos & 0xfc) > info->dscp[1], EBT_IP_DSCP)) return false; } if (info->bitmask & EBT_IP_TOS && FWINV((info->tos & 0x1e) != (ih->tos & 0x1e), EBT_IP_TOS)) #else if (info->bitmask & EBT_IP_TOS && FWINV(info->tos != ih->tos, EBT_IP_TOS)) #endif return false; #if 0 if (info->bitmask & EBT_IP_SOURCE && FWINV((ih->saddr & info->smsk) != info->saddr, EBT_IP_SOURCE)) return false; if ((info->bitmask & EBT_IP_DEST) && FWINV((ih->daddr & info->dmsk) != info->daddr, EBT_IP_DEST)) return false; #else /*xyzhu_20100413*/ if ( info->bitmask & EBT_IP_SOURCE && FWINV( ((ih->saddr & info->smsk[0]) < info->saddr[0]) || ((ih->saddr & info->smsk[0]) > info->saddr[1]), EBT_IP_SOURCE ) ) { return false; } if ( info->bitmask & EBT_IP_DEST && FWINV( ((ih->daddr & info->dmsk[0]) < info->daddr[0]) || ((ih->daddr & info->dmsk[0]) > info->daddr[1]), EBT_IP_DEST ) ) { return false; } #endif if (info->bitmask & EBT_IP_PROTO) { #if 1 /*Rodney_20090724*/ if (FWINV((info->protocol[0] != ih->protocol) && (info->protocol[1] != ih->protocol), EBT_IP_PROTO)) #else if (FWINV(info->protocol != ih->protocol, EBT_IP_PROTO)) #endif return false; if (!(info->bitmask & EBT_IP_DPORT) && !(info->bitmask & EBT_IP_SPORT)) return true; if (ntohs(ih->frag_off) & IP_OFFSET) return false; #if 1 /*Rodney_20090724*/ if(skb->protocol == htons(ETH_P_IP)) pptr = (struct tcpudphdr *)skb_header_pointer(skb, ih->ihl*4, sizeof(_ports), &_ports); else if((skb->protocol == htons(ETH_P_8021Q)) && (vlan_proto(skb) == htons(ETH_P_IP))) pptr = (struct tcpudphdr *)(skb_mac_header(skb) + VLAN_ETH_HLEN + ih->ihl*4); else if((skb->protocol == htons(ETH_P_PPP_SES)) && (pppoe_proto(skb) == htons(0x0021))) pptr = (struct tcpudphdr *)(skb_mac_header(skb) + ETH_HLEN + PPPOE_SES_HLEN + ih->ihl*4); else pptr = (struct tcpudphdr *)skb_header_pointer(skb, ih->ihl*4, sizeof(_ports), &_ports); #else pptr = skb_header_pointer(skb, ih->ihl*4, sizeof(_ports), &_ports); #endif if (pptr == NULL) return false; if (info->bitmask & EBT_IP_DPORT) { u32 dst = ntohs(pptr->dst); if (FWINV(dst < info->dport[0] || dst > info->dport[1], EBT_IP_DPORT)) return false; } if (info->bitmask & EBT_IP_SPORT) { u32 src = ntohs(pptr->src); if (FWINV(src < info->sport[0] || src > info->sport[1], EBT_IP_SPORT)) return false; } } return true; }
static bool ebt_ip6_mt(const struct sk_buff *skb, struct xt_action_param *par) { const struct ebt_ip6_info *info = par->matchinfo; const struct ipv6hdr *ih6; struct ipv6hdr _ip6h; const struct tcpudphdr *pptr; struct tcpudphdr _ports; struct in6_addr tmp_addr; int i; #if 1 if(skb->protocol == htons(ETH_P_IPV6)) ih6 = (struct ipv6hdr *)skb_header_pointer(skb, 0, sizeof(_ip6h), &_ip6h); else if((skb->protocol == htons(ETH_P_8021Q)) && (vlan_proto(skb) == htons(ETH_P_IPV6))) ih6 = (struct ipv6hdr *)(skb_mac_header(skb) + VLAN_ETH_HLEN); else if((skb->protocol == htons(ETH_P_PPP_SES)) && (pppoe_proto(skb) == htons(0x0021))) ih6 = (struct ipv6hdr *)(skb_mac_header(skb) + ETH_HLEN +PPPOE_SES_HLEN); else ih6 = (struct ipv6hdr *)skb_header_pointer(skb, 0, sizeof(_ip6h), &_ip6h); #else ih6 = skb_header_pointer(skb, 0, sizeof(_ip6h), &_ip6h); #endif if (ih6 == NULL) return false; #if 1 if (info->bitmask & EBT_IP6_TCLASS) { __u8 tc = ipv6_get_dsfield((struct ipv6hdr *)ih6); if (FWINV(tc < info->tclass[0] || tc > info->tclass[1], EBT_IP6_TCLASS)) return false; } #else if (info->bitmask & EBT_IP6_TCLASS && FWINV(info->tclass != ipv6_get_dsfield((struct ipv6hdr *)ih6), EBT_IP6_TCLASS)) //return false; return false; #endif #if 1 for (i = 0; i < 4; i++) tmp_addr.in6_u.u6_addr32[i] = ih6->saddr.in6_u.u6_addr32[i] & info->smsk.in6_u.u6_addr32[i]; if (info->bitmask & EBT_IP6_SOURCE && FWINV((ipv6_addr_cmp(&tmp_addr, &info->saddr) != 0), EBT_IP6_SOURCE)) return false; for (i = 0; i < 4; i++) tmp_addr.in6_u.u6_addr32[i] = ih6->daddr.in6_u.u6_addr32[i] & info->dmsk.in6_u.u6_addr32[i]; if (info->bitmask & EBT_IP6_DEST && FWINV((ipv6_addr_cmp(&tmp_addr, &info->daddr) != 0), EBT_IP6_DEST)) return false; #else if (FWINV(ipv6_masked_addr_cmp(&ih6->saddr, &info->smsk, &info->saddr), EBT_IP6_SOURCE) || FWINV(ipv6_masked_addr_cmp(&ih6->daddr, &info->dmsk, &info->daddr), EBT_IP6_DEST)) return false; #endif if (info->bitmask & EBT_IP6_PROTO) { uint8_t nexthdr = ih6->nexthdr; int offset_ph; offset_ph = ipv6_skip_exthdr(skb, sizeof(_ip6h), &nexthdr); if (offset_ph == -1) return false; #if 1 if ( FWINV((info->protocol[0] != nexthdr) && (info->protocol[1] != nexthdr), EBT_IP6_PROTO) ) return false; #else if (FWINV(info->protocol != nexthdr, EBT_IP6_PROTO)) return false; #endif if (!(info->bitmask & EBT_IP6_DPORT) && !(info->bitmask & EBT_IP6_SPORT)){ return true; } #if 1 if(skb->protocol == htons(ETH_P_IP)) pptr = (struct tcpudphdr *)skb_header_pointer(skb, offset_ph, sizeof(_ports), &_ports); else if((skb->protocol == htons(ETH_P_8021Q)) && (vlan_proto(skb) == htons(ETH_P_IP))) pptr = (struct tcpudphdr *)(skb_mac_header(skb) + VLAN_ETH_HLEN + offset_ph); else if((skb->protocol == htons(ETH_P_PPP_SES)) && (pppoe_proto(skb) == htons(0x0021))) pptr = (struct tcpudphdr *)(skb_mac_header(skb) + ETH_HLEN + PPPOE_SES_HLEN + offset_ph); else pptr = (struct tcpudphdr *)skb_header_pointer(skb, offset_ph, sizeof(_ports), &_ports); #else pptr = skb_header_pointer(skb, offset_ph, sizeof(_ports), &_ports); #endif if (pptr == NULL) return false; if (info->bitmask & EBT_IP6_DPORT) { u32 dst = ntohs(pptr->dst); if (FWINV(dst < info->dport[0] || dst > info->dport[1], EBT_IP6_DPORT)) return false; } if (info->bitmask & EBT_IP6_SPORT) { u32 src = ntohs(pptr->src); if (FWINV(src < info->sport[0] || src > info->sport[1], EBT_IP6_SPORT)) return false; } return true; } return true; }