Messages in this thread | | | Date | Thu, 31 May 2001 16:21:52 -0400 | From | Brad Chapman <> | Subject | Defragging/refragging IPv6 packets |
| |
Hello,
My name is Brad Chapman and I am currently attempting to port the iptables ip_conntrack component of Netfilter to the IPv6 protocol. My port is almost feature-complete, but I cannot figure out how to properly defragment/refragment IPv6 packets. Also, I have written an IPv6 header parsing function to grab headers from the IPv6 header chain. I would appreciate some feedback on that as well. Below are some code examples.
DEFRAGGING PACKETS:
/* Returns defragged sk_buff, or NULL */ /* FIXME: is this the "right" way to do it? -- BC */ struct sk_buff *ip6_ct_gather_frags(struct sk_buff *skb) { #ifdef CONFIG_NETFILTER_DEBUG unsigned int old_debug = skb->nf_debug; #endif struct frag_hdr *fhdr = (struct frag_hdr *) ipv6_get_header(skb->nh.ipv6h, NEXTHDR_FRAGMENT, NULL); local_bh_disable(); if (!ipv6_reassembly(skb, (u8 *)fhdr)) return NULL; local_bh_enable();
skb->nfcache |= NFC_ALTERED; #ifdef CONFIG_NETFILTER_DEBUG skb->nf_debug = old_debug; #endif return skb; }
REFRAGGING PACKETS:
/* This gets the fragmentable part - I think -- BC */ static int ip6_refrag_getfrag(const void *data, struct in6_addr *addr, char *buff, unsigned int offset, unsigned int len) { return 0; }
static unsigned int ip6_refrag(unsigned int hooknum, struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { struct frag_hdr *fhdr = (struct frag_hdr *) ipv6_get_header((*pskb)->nh.ipv6h, NEXTHDR_FRAGMENT, NULL); struct flowi *flow; int ret; __u8 protonum;
/* Verify the protocol */ if (!ipv6_get_header((*pskb)->nh.ipv6h, NEXTHDR_PROTOANY, &protonum)) return NF_DROP;
/* We've seen it coming out the other side: confirm */ ip6_confirm(hooknum, pskb, in, out, okfn);
/* Local packets are never produced too large for their interface. We degfragment them at LOCAL_OUT, however, so we have to refragment them here. */ if ((fhdr) && !(fhdr->frag_off & htons(IP6_NON_FRAG_OFFSET))) {
/* Build the flowlabel */ flow.proto = (int)protonum; ipv6_addr_copy(flow.fl6_src, (*pskb)->nh.ipv6h->saddr); ipv6_addr_copy(flow.fl6_dst, (*pskb)->nh.ipv6h->daddr); flow.fl6_flowlabel = 0; if (protonum == NEXTHDR_TCP) { flow.uli_u.ports.sport = (*pskb)->nh.tcph->sport; flow.uli_u.ports.dport = (*pskb)->nh.tcph->dport; } else if (protonum == NEXTHDR_UDP) { flow.uli_u.ports.sport = (*pskb)->nh.udph->sport; flow.uli_u.ports.dport = (*pskb)->nh.udph->dport; } else if (protonum == NEXTHDR_ICMP) { struct icmp6hdr *icmph; icmph = (struct icmp6hdr *)ipv6_get_header((*pskb)->nh.ipv6h, NEXTHDR_ICMP, NULL); if (!icmph) return NF_DROP; flow.uli_u.icmpt.type = icmph->icmp6_type; flow.uli_u.icmpt.code = icmph->icmp6_code; } else return NF_DROP; ret = ip6_build_xmit((*pskb)->sk, ip6_refrag_getfrag, (*pskb)->data, flow, (*pskb)->nh.ipv6h->payload_len, NULL, 0, 0);
if (ret < 0) return NF_DROP; return NF_STOLEN; } return NF_ACCEPT; }
PARSING IPV6 HEADERS
/* Find a particular header in the IPv6 header chains */ struct ipv6_opt_hdr * ipv6_get_header(const struct ipv6hdr *ipv6h, __u8 header, __u8 *result) { struct ipv6_opt_hdr *newhdr = NULL; __u8 *hdrptr = (__u8 *)&ipv6h->nexthdr; int hdrlen, length;
IP_NF_ASSERT(header != NEXTHDR_NONE); IP_NF_ASSERT(*hdrptr != NEXTHDR_NONE);
/* Start bouncing */ length = sizeof(struct ipv6hdr); hdrlen = 0; while (*hdrptr != NEXTHDR_NONE) { if (header == NEXTHDR_PROTOANY && (*hdrptr == NEXTHDR_TCP || *hdrptr == NEXTHDR_UDP || *hdrptr == NEXTHDR_ICMP) && result != NULL) { *result = *hdrptr; newhdr = (struct ipv6_opt_hdr *)hdrptr; break; } else if (*hdrptr == header) { newhdr = (struct ipv6_opt_hdr *)hdrptr; break; } else if (hdrlen > length) { break; } hdrlen = sizeof((__u8 *)hdrptr); hdrptr = (__u8 *)(hdrptr + hdrlen); length -= hdrlen; } return newhdr; }
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |