Common subdirectories: exp-rjulian-KSEREL-002/default/usr/build/godspeed/freebsd/mods/src/sys/netinet/CVS and exp-rjulian-KSEREL-001/default/usr/build/godspeed/freebsd/mods/src/sys/netinet/CVS diff -u exp-rjulian-KSEREL-002/default/usr/build/godspeed/freebsd/mods/src/sys/netinet/ip_fw.h exp-rjulian-KSEREL-001/default/usr/build/godspeed/freebsd/mods/src/sys/netinet/ip_fw.h --- exp-rjulian-KSEREL-002/default/usr/build/godspeed/freebsd/mods/src/sys/netinet/ip_fw.h Fri Feb 17 08:46:47 2006 +++ exp-rjulian-KSEREL-001/default/usr/build/godspeed/freebsd/mods/src/sys/netinet/ip_fw.h Thu Dec 14 13:35:16 2006 @@ -522,7 +522,7 @@ struct sockaddr_in *next_hop; /* forward address */ struct ip_fw *rule; /* matching rule */ struct ether_header *eh; /* for bridged packets */ - + int vlan_hlen; /* length of vlan header to skip */ struct ipfw_flow_id f_id; /* grabbed from IP header */ u_int32_t cookie; /* a cookie depending on rule action */ struct inpcb *inp; Only in exp-rjulian-KSEREL-001/default/usr/build/godspeed/freebsd/mods/src/sys/netinet: ip_fw.h.orig diff -u exp-rjulian-KSEREL-002/default/usr/build/godspeed/freebsd/mods/src/sys/netinet/ip_fw2.c exp-rjulian-KSEREL-001/default/usr/build/godspeed/freebsd/mods/src/sys/netinet/ip_fw2.c --- exp-rjulian-KSEREL-002/default/usr/build/godspeed/freebsd/mods/src/sys/netinet/ip_fw2.c Fri Dec 15 12:54:43 2006 +++ exp-rjulian-KSEREL-001/default/usr/build/godspeed/freebsd/mods/src/sys/netinet/ip_fw2.c Thu Dec 14 18:28:19 2006 @@ -201,6 +201,7 @@ }; static int fw_debug = 1; +static int fw_stripvlans = 1; static int autoinc_step = 100; /* bounded to 1..1000 in add_rule() */ #ifdef SYSCTL_NODE @@ -221,6 +222,9 @@ &fw_verbose, 0, "Log matches to ipfw rules"); SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, verbose_limit, CTLFLAG_RW, &verbose_limit, 0, "Set upper limit of matches of ipfw rules logged"); +SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, stripvlan, CTLFLAG_RW, + &fw_stripvlans, 0, "strip off vlan headers if working at layer 2"); + /* * Description of dynamic rules. @@ -701,8 +705,11 @@ } static void -send_reject6(struct ip_fw_args *args, int code, u_short offset, u_int hlen) +send_reject6(struct ip_fw_args *args, int code, u_int hlen, struct ip6_hdr *ip6) { + struct mbuf *m; + m = args->m; + if (code == ICMP6_UNREACH_RST && offset == 0 && args->f_id.proto == IPPROTO_TCP) { struct ip6_hdr *ip6; @@ -714,17 +721,11 @@ struct tcphdr th; } ti; - if (args->m->m_len < (hlen+sizeof(struct tcphdr))) { - args->m = m_pullup(args->m, hlen+sizeof(struct tcphdr)); - if (args->m == NULL) - return; - } - - ip6 = mtod(args->m, struct ip6_hdr *); - tcp = (struct tcphdr *)(mtod(args->m, char *) + hlen); + tcp = (struct tcphdr *)((char *)ip6 + hlen); if ((tcp->th_flags & TH_RST) != 0) { - m_freem(args->m); + m_freem(m); + args->m = NULL; return; } @@ -740,14 +741,21 @@ flags = TH_RST; } else { ack = ti.th.th_seq; - if (((args->m)->m_flags & M_PKTHDR) != 0) { - ack += (args->m)->m_pkthdr.len - hlen + if ((m->m_flags & M_PKTHDR) != 0) { + /* + * total new data to ACK is: + * total packet length, + * minus the header length, + * minus the tcp header length. + */ + ack += m->m_pkthdr.len - args->vlan_hlen - hlen - (ti.th.th_off << 2); } else if (ip6->ip6_plen) { - ack += ntohs(ip6->ip6_plen) + sizeof(*ip6) - - hlen - (ti.th.th_off << 2); + ack += ntohs(ip6->ip6_plen) + + sizeof(*ip6) - + hlen - (ti.th.th_off << 2); } else { - m_freem(args->m); + m_freem(m); return; } if (tcp->th_flags & TH_SYN) @@ -756,14 +764,20 @@ flags = TH_RST|TH_ACK; } bcopy(&ti, ip6, sizeof(ti)); - tcp_respond(NULL, ip6, (struct tcphdr *)(ip6 + 1), - args->m, ack, seq, flags); + /* m only used to recycle the mbuf */ + tcp_respond(NULL, ip6, tcp, m, ack, seq, flags); } else if (code != ICMP6_UNREACH_RST) { /* Send an ICMPv6 unreach. */ - icmp6_error(args->m, ICMP6_DST_UNREACH, code, 0); - + /* + * m is interpreted as if the ip6 header is the + * first thing in it, so skip any vlan header. + * m is consumed so we can modify it. + */ + if (args->vlan_hlen) + m = m_adj(m, args->vlan_hlen); + icmp6_error(m, ICMP6_DST_UNREACH, code, 0); } else - m_freem(args->m); + m_freem(m); args->m = NULL; } @@ -781,7 +795,7 @@ */ static void ipfw_log(struct ip_fw *f, u_int hlen, struct ip_fw_args *args, - struct mbuf *m, struct ifnet *oif, u_short offset) + struct mbuf *m, struct ifnet *oif, u_short offset, char *baseaddr) { struct ether_header *eh = args->eh; char *action; @@ -917,13 +931,13 @@ snprintf(dst, sizeof(dst), "[%s]", ip6_sprintf(&args->f_id.dst_ip6)); - ip6 = (struct ip6_hdr *)mtod(m, struct ip6_hdr *); - tcp = (struct tcphdr *)(mtod(args->m, char *) + hlen); - udp = (struct udphdr *)(mtod(args->m, char *) + hlen); + ip6 = (struct ip6_hdr *)baseaddr; + tcp = (struct tcphdr *)(baseaddr + hlen); + udp = (struct udphdr *)(baseaddr + hlen); } else #endif { - ip = mtod(m, struct ip *); + ip = (struct ip *)baseaddr; tcp = L3HDR(struct tcphdr, ip); udp = L3HDR(struct udphdr, ip); @@ -967,7 +981,7 @@ break; #ifdef INET6 case IPPROTO_ICMPV6: - icmp6 = (struct icmp6_hdr *)(mtod(args->m, char *) + hlen); + icmp6 = (struct icmp6_hdr *)(baseaddr + hlen); if (offset == 0) len = snprintf(SNPARGS(proto, 0), "ICMPv6:%u.%u ", @@ -1648,6 +1662,11 @@ if (code != ICMP_REJECT_RST) { /* Send an ICMP unreach */ /* We need the IP header in host order for icmp_error(). */ if (args->eh != NULL) { + /* if we had a vlan header, skip past it */ + if (args->vlan_hlen) { + m_adj(args->m, args->vlan_hlen); + args->vlan_hlen = 0; + } struct ip *ip = mtod(args->m, struct ip *); ip->ip_len = ntohs(ip->ip_len); ip->ip_off = ntohs(ip->ip_off); @@ -2027,6 +2046,7 @@ * args->m (in/out) The packet; we set to NULL when/if we nuke it. * Starts with the IP header. * args->eh (in) Mac header if present, or NULL for layer3 packet. + * args->vlan_hlen Vlan header lenght bypassed. * args->oif Outgoing interface, or NULL if packet is incoming. * The incoming interface is in the mbuf. (in) * args->divert_rule (in/out) @@ -2048,6 +2068,10 @@ * IP_FW_NETGRAPH into netgraph, cookie args->cookie * */ +struct vlhdr { + u_int16_t evl_tag; + u_int16_t evl_proto; +}; int ipfw_chk(struct ip_fw_args *args) @@ -2142,6 +2166,9 @@ struct in_addr src_ip, dst_ip; /* NOTE: network format */ u_int16_t ip_len=0; int pktlen; + u_int16_t etype = 0; /* Host order stored ether type */ + int vltag; /* Host order stored vlan tag */ + /* -1 == no tag */ /* * dyn_dir = MATCH_UNKNOWN when rules unchecked, @@ -2202,14 +2229,38 @@ p = (mtod(m, char *) + (len)); \ } while (0) + /* + * if we have an ether header, + * then check if we also have a vlan header. + */ + if (args->eh && + (etype = (ntohs(args->eh->ether_type)) == ETHERTYPE_VLAN) && + fw_stripvlans) { + struct vlhdr *vlt; + if (pktlen >= sizeof(struct vlhdr)) { + PULLUP_TO(0, ulp, struct vlhdr); + } else { + return IP_FW_DENY; + } + vlt = (struct vlhdr *)ulp; + etype = ntohs(vlt->evl_proto); + vltag = ntohs(vlt->evl_tag); + args->vlan_hlen = 4; + ip = (struct ip *)((char *)ulp + args->vlan_hlen); + } else { + args->vlan_hlen = 0; + vltag = -1; + ip = (struct ip *)mtod(m, char *); + } + /* Identify IP packets and fill up variables. */ if (pktlen >= sizeof(struct ip6_hdr) && - (args->eh == NULL || ntohs(args->eh->ether_type)==ETHERTYPE_IPV6) && - mtod(m, struct ip *)->ip_v == 6) { + (args->eh == NULL || etype == ETHERTYPE_IPV6) && ip->ip_v == 6) { + struct ip6_hdr *ip6 = (struct ip6_hdr *)ip; is_ipv6 = 1; args->f_id.addr_type = 6; - hlen = sizeof(struct ip6_hdr); - proto = mtod(m, struct ip6_hdr *)->ip6_nxt; + hlen = args->vlan_hlen + sizeof(struct ip6_hdr); + proto = ip6->ip6_nxt; /* Search extension headers to find upper layer protocols */ while (ulp == NULL) { @@ -2320,18 +2371,20 @@ return (IP_FW_DENY); break; } /*switch */ + /* pullup may have replaced the mbuf so reset ip */ + ip = (struct ip *)(mtod(m, char *) + args->vlan_hlen); } - args->f_id.src_ip6 = mtod(m,struct ip6_hdr *)->ip6_src; - args->f_id.dst_ip6 = mtod(m,struct ip6_hdr *)->ip6_dst; + ip6 = (struct ip6_hdr *)ip; + args->f_id.src_ip6 = ip6->ip6_src; + args->f_id.dst_ip6 = ip6->ip6_dst; args->f_id.src_ip = 0; args->f_id.dst_ip = 0; - args->f_id.flow_id6 = ntohl(mtod(m, struct ip6_hdr *)->ip6_flow); + args->f_id.flow_id6 = ntohl(ip6->ip6_flow); + hlen -= args->vlan_hlen; } else if (pktlen >= sizeof(struct ip) && - (args->eh == NULL || ntohs(args->eh->ether_type) == ETHERTYPE_IP) && - mtod(m, struct ip *)->ip_v == 4) { + (args->eh == NULL || etype == ETHERTYPE_IP) && ip->ip_v == 4) { is_ipv4 = 1; - ip = mtod(m, struct ip *); - hlen = ip->ip_hl << 2; + hlen = args->vlan_hlen + (ip->ip_hl << 2); args->f_id.addr_type = 4; /* @@ -2374,8 +2427,10 @@ } } + ip = (struct ip *)(mtod(m, char *) + args->vlan_hlen); args->f_id.src_ip = ntohl(src_ip.s_addr); args->f_id.dst_ip = ntohl(dst_ip.s_addr); + hlen -= args->vlan_hlen; } #undef PULLUP_TO if (proto) { /* we may have port numbers, store them */ @@ -2540,8 +2595,7 @@ case O_MAC_TYPE: if (args->eh != NULL) { - u_int16_t t = - ntohs(args->eh->ether_type); + u_int16_t t = etype; u_int16_t *p = ((ipfw_insn_u16 *)cmd)->ports; int i; @@ -2700,12 +2754,12 @@ case O_IPOPT: match = (is_ipv4 && - ipopts_match(mtod(m, struct ip *), cmd) ); + ipopts_match(ip, cmd) ); break; case O_IPVER: match = (is_ipv4 && - cmd->arg1 == mtod(m, struct ip *)->ip_v); + cmd->arg1 == ip->ip_v); break; case O_IPID: @@ -2719,9 +2773,9 @@ if (cmd->opcode == O_IPLEN) x = ip_len; else if (cmd->opcode == O_IPTTL) - x = mtod(m, struct ip *)->ip_ttl; + x = ip->ip_ttl; else /* must be IPID */ - x = ntohs(mtod(m, struct ip *)->ip_id); + x = ntohs(ip->ip_id); if (cmdlen == 1) { match = (cmd->arg1 == x); break; @@ -2736,12 +2790,12 @@ case O_IPPRECEDENCE: match = (is_ipv4 && - (cmd->arg1 == (mtod(m, struct ip *)->ip_tos & 0xe0)) ); + (cmd->arg1 == (ip->ip_tos & 0xe0)) ); break; case O_IPTOS: match = (is_ipv4 && - flags_match(cmd, mtod(m, struct ip *)->ip_tos)); + flags_match(cmd, ip->ip_tos)); break; case O_TCPDATALEN: @@ -2832,7 +2886,8 @@ case O_LOG: if (fw_verbose) - ipfw_log(f, hlen, args, m, oif, offset); + ipfw_log(f, hlen, args, m, + oif, offset, (char *)ip); match = 1; break; @@ -3113,6 +3168,8 @@ is_icmp_query(ICMP(ulp))) && !(m->m_flags & (M_BCAST|M_MCAST)) && !IN_MULTICAST(ntohl(dst_ip.s_addr))) { + if (args->vlan_hlen) + m_adj(m, args->vlan_hlen); send_reject(args, cmd->arg1, offset,ip_len); m = args->m; @@ -3125,8 +3182,11 @@ (is_icmp6_query(args->f_id.flags) == 1)) && !(m->m_flags & (M_BCAST|M_MCAST)) && !IN6_IS_ADDR_MULTICAST(&args->f_id.dst_ip6)) { - send_reject6(args, cmd->arg1, - offset, hlen); + if (args->vlan_hlen) + m_adj(m, args->vlan_hlen); + send_reject6( + args, cmd->arg1, + hlen, (struct ip6_hdr *)ip); m = args->m; } /* FALLTHROUGH */ Only in exp-rjulian-KSEREL-001/default/usr/build/godspeed/freebsd/mods/src/sys/netinet: ip_fw2.c.orig Only in exp-rjulian-KSEREL-001/default/usr/build/godspeed/freebsd/mods/src/sys/netinet: ip_fw2.c.rej Common subdirectories: exp-rjulian-KSEREL-002/default/usr/build/godspeed/freebsd/mods/src/sys/netinet/libalias and exp-rjulian-KSEREL-001/default/usr/build/godspeed/freebsd/mods/src/sys/netinet/libalias