public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Brad Chapman <kakadu@earthlink.net>
To: linux-kernel@vger.kernel.org
Subject: Defragging/refragging IPv6 packets
Date: Thu, 31 May 2001 16:21:52 -0400	[thread overview]
Message-ID: <3B16A7E0.2070008@earthlink.net> (raw)

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;
}




                 reply	other threads:[~2001-05-31 21:26 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=3B16A7E0.2070008@earthlink.net \
    --to=kakadu@earthlink.net \
    --cc=linux-kernel@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox