⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 exthdrs.c

📁 嵌入式系统设计与实验教材二源码linux内核移植与编译
💻 C
📖 第 1 页 / 共 2 页
字号:
	len = (skb->h.raw[1]+1)<<2;	if (len&7)		goto fail;	if (!pskb_may_pull(skb, (skb->h.raw-skb->data)+len))		goto fail;	opt->auth = skb->h.raw - skb->nh.raw;	skb->h.raw += len;	return opt->auth;fail:	kfree_skb(skb);	return -1;}/* This list MUST NOT contain entry for NEXTHDR_HOP.   It is parsed immediately after packet received   and if it occurs somewhere in another place we must   generate error. */struct hdrtype_proc hdrproc_lst[] = {	{NEXTHDR_FRAGMENT,	ipv6_reassembly},	{NEXTHDR_ROUTING,	ipv6_routing_header},	{NEXTHDR_DEST,		ipv6_dest_opt},	{NEXTHDR_NONE,		ipv6_nodata},	{NEXTHDR_AUTH,		ipv6_auth_hdr},   /*	{NEXTHDR_ESP,		ipv6_esp_hdr},    */	{-1,			NULL}};int ipv6_parse_exthdrs(struct sk_buff **skb_in, int nhoff){	struct hdrtype_proc *hdrt;	u8 nexthdr = (*skb_in)->nh.raw[nhoff];restart:	for (hdrt=hdrproc_lst; hdrt->type >= 0; hdrt++) {		if (hdrt->type == nexthdr) {			if ((nhoff = hdrt->func(skb_in, nhoff)) >= 0) {				nexthdr = (*skb_in)->nh.raw[nhoff];				goto restart;			}			return -1;		}	}	return nhoff;}/**********************************  Hop-by-hop options. **********************************//* Router Alert as of draft-ietf-ipngwg-ipv6router-alert-04 */static int ipv6_hop_ra(struct sk_buff *skb, int optoff){	if (skb->nh.raw[optoff+1] == 2) {		((struct inet6_skb_parm*)skb->cb)->ra = optoff;		return 1;	}	if (net_ratelimit())		printk(KERN_DEBUG "ipv6_hop_ra: wrong RA length %d\n", skb->nh.raw[optoff+1]);	kfree_skb(skb);	return 0;}/* Jumbo payload */static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff){	u32 pkt_len;	if (skb->nh.raw[optoff+1] != 4 || (optoff&3) != 2) {		if (net_ratelimit())			printk(KERN_DEBUG "ipv6_hop_jumbo: wrong jumbo opt length/alignment %d\n", skb->nh.raw[optoff+1]);		goto drop;	}	pkt_len = ntohl(*(u32*)(skb->nh.raw+optoff+2));	if (pkt_len < 0x10000) {		icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff+2);		return 0;	}	if (skb->nh.ipv6h->payload_len) {		icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, optoff);		return 0;	}	if (pkt_len > skb->len - sizeof(struct ipv6hdr)) {		IP6_INC_STATS_BH(Ip6InTruncatedPkts);		goto drop;	}	if (pkt_len + sizeof(struct ipv6hdr) < skb->len) {		__pskb_trim(skb, pkt_len + sizeof(struct ipv6hdr));		if (skb->ip_summed == CHECKSUM_HW)			skb->ip_summed = CHECKSUM_NONE;	}	return 1;drop:	kfree_skb(skb);	return 0;}struct tlvtype_proc tlvprochopopt_lst[] = {	{IPV6_TLV_ROUTERALERT,	ipv6_hop_ra},	{IPV6_TLV_JUMBO,	ipv6_hop_jumbo},	{-1,			NULL}};int ipv6_parse_hopopts(struct sk_buff *skb, int nhoff){	((struct inet6_skb_parm*)skb->cb)->hop = sizeof(struct ipv6hdr);	if (ip6_parse_tlv(tlvprochopopt_lst, skb))		return sizeof(struct ipv6hdr);	return -1;}/* *	Creating outbound headers. * *	"build" functions work when skb is filled from head to tail (datagram) *	"push"	functions work when headers are added from tail to head (tcp) * *	In both cases we assume, that caller reserved enough room *	for headers. */u8 *ipv6_build_rthdr(struct sk_buff *skb, u8 *prev_hdr,		     struct ipv6_rt_hdr *opt, struct in6_addr *addr){	struct rt0_hdr *phdr, *ihdr;	int hops;	ihdr = (struct rt0_hdr *) opt;		phdr = (struct rt0_hdr *) skb_put(skb, (ihdr->rt_hdr.hdrlen + 1) << 3);	memcpy(phdr, ihdr, sizeof(struct rt0_hdr));	hops = ihdr->rt_hdr.hdrlen >> 1;	if (hops > 1)		memcpy(phdr->addr, ihdr->addr + 1,		       (hops - 1) * sizeof(struct in6_addr));	ipv6_addr_copy(phdr->addr + (hops - 1), addr);	phdr->rt_hdr.nexthdr = *prev_hdr;	*prev_hdr = NEXTHDR_ROUTING;	return &phdr->rt_hdr.nexthdr;}static u8 *ipv6_build_exthdr(struct sk_buff *skb, u8 *prev_hdr, u8 type, struct ipv6_opt_hdr *opt){	struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_put(skb, ipv6_optlen(opt));	memcpy(h, opt, ipv6_optlen(opt));	h->nexthdr = *prev_hdr;	*prev_hdr = type;	return &h->nexthdr;}static u8 *ipv6_build_authhdr(struct sk_buff *skb, u8 *prev_hdr, struct ipv6_opt_hdr *opt){	struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_put(skb, (opt->hdrlen+2)<<2);	memcpy(h, opt, (opt->hdrlen+2)<<2);	h->nexthdr = *prev_hdr;	*prev_hdr = NEXTHDR_AUTH;	return &h->nexthdr;}u8 *ipv6_build_nfrag_opts(struct sk_buff *skb, u8 *prev_hdr, struct ipv6_txoptions *opt,			  struct in6_addr *daddr, u32 jumbolen){	struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb->data;	if (opt && opt->hopopt)		prev_hdr = ipv6_build_exthdr(skb, prev_hdr, NEXTHDR_HOP, opt->hopopt);	if (jumbolen) {		u8 *jumboopt = (u8 *)skb_put(skb, 8);		if (opt && opt->hopopt) {			*jumboopt++ = IPV6_TLV_PADN;			*jumboopt++ = 0;			h->hdrlen++;		} else {			h = (struct ipv6_opt_hdr *)jumboopt;			h->nexthdr = *prev_hdr;			h->hdrlen = 0;			jumboopt += 2;			*prev_hdr = NEXTHDR_HOP;			prev_hdr = &h->nexthdr;		}		jumboopt[0] = IPV6_TLV_JUMBO;		jumboopt[1] = 4;		*(u32*)(jumboopt+2) = htonl(jumbolen);	}	if (opt) {		if (opt->dst0opt)			prev_hdr = ipv6_build_exthdr(skb, prev_hdr, NEXTHDR_DEST, opt->dst0opt);		if (opt->srcrt)			prev_hdr = ipv6_build_rthdr(skb, prev_hdr, opt->srcrt, daddr);	}	return prev_hdr;}u8 *ipv6_build_frag_opts(struct sk_buff *skb, u8 *prev_hdr, struct ipv6_txoptions *opt){	if (opt->auth)		prev_hdr = ipv6_build_authhdr(skb, prev_hdr, opt->auth);	if (opt->dst1opt)		prev_hdr = ipv6_build_exthdr(skb, prev_hdr, NEXTHDR_DEST, opt->dst1opt);	return prev_hdr;}static void ipv6_push_rthdr(struct sk_buff *skb, u8 *proto,			    struct ipv6_rt_hdr *opt,			    struct in6_addr **addr_p){	struct rt0_hdr *phdr, *ihdr;	int hops;	ihdr = (struct rt0_hdr *) opt;		phdr = (struct rt0_hdr *) skb_push(skb, (ihdr->rt_hdr.hdrlen + 1) << 3);	memcpy(phdr, ihdr, sizeof(struct rt0_hdr));	hops = ihdr->rt_hdr.hdrlen >> 1;	if (hops > 1)		memcpy(phdr->addr, ihdr->addr + 1,		       (hops - 1) * sizeof(struct in6_addr));	ipv6_addr_copy(phdr->addr + (hops - 1), *addr_p);	*addr_p = ihdr->addr;	phdr->rt_hdr.nexthdr = *proto;	*proto = NEXTHDR_ROUTING;}static void ipv6_push_exthdr(struct sk_buff *skb, u8 *proto, u8 type, struct ipv6_opt_hdr *opt){	struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_push(skb, ipv6_optlen(opt));	memcpy(h, opt, ipv6_optlen(opt));	h->nexthdr = *proto;	*proto = type;}static void ipv6_push_authhdr(struct sk_buff *skb, u8 *proto, struct ipv6_opt_hdr *opt){	struct ipv6_opt_hdr *h = (struct ipv6_opt_hdr *)skb_push(skb, (opt->hdrlen+2)<<2);	memcpy(h, opt, (opt->hdrlen+2)<<2);	h->nexthdr = *proto;	*proto = NEXTHDR_AUTH;}void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt,			  u8 *proto,			  struct in6_addr **daddr){	if (opt->srcrt)		ipv6_push_rthdr(skb, proto, opt->srcrt, daddr);	if (opt->dst0opt)		ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst0opt);	if (opt->hopopt)		ipv6_push_exthdr(skb, proto, NEXTHDR_HOP, opt->hopopt);}void ipv6_push_frag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, u8 *proto){	if (opt->dst1opt)		ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst1opt);	if (opt->auth)		ipv6_push_authhdr(skb, proto, opt->auth);}struct ipv6_txoptions *ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt){	struct ipv6_txoptions *opt2;	opt2 = sock_kmalloc(sk, opt->tot_len, GFP_ATOMIC);	if (opt2) {		long dif = (char*)opt2 - (char*)opt;		memcpy(opt2, opt, opt->tot_len);		if (opt2->hopopt)			*((char**)&opt2->hopopt) += dif;		if (opt2->dst0opt)			*((char**)&opt2->dst0opt) += dif;		if (opt2->dst1opt)			*((char**)&opt2->dst1opt) += dif;		if (opt2->auth)			*((char**)&opt2->auth) += dif;		if (opt2->srcrt)			*((char**)&opt2->srcrt) += dif;	}	return opt2;}/*  * find out if nexthdr is a well-known extension header or a protocol */int ipv6_ext_hdr(u8 nexthdr){	/* 	 * find out if nexthdr is an extension header or a protocol	 */	return ( (nexthdr == NEXTHDR_HOP)	||		 (nexthdr == NEXTHDR_ROUTING)	||		 (nexthdr == NEXTHDR_FRAGMENT)	||		 (nexthdr == NEXTHDR_AUTH)	||		 (nexthdr == NEXTHDR_NONE)	||		 (nexthdr == NEXTHDR_DEST) );}/* * Skip any extension headers. This is used by the ICMP module. * * Note that strictly speaking this conflicts with RFC1883 4.0: * ...The contents and semantics of each extension header determine whether  * or not to proceed to the next header.  Therefore, extension headers must * be processed strictly in the order they appear in the packet; a * receiver must not, for example, scan through a packet looking for a * particular kind of extension header and process that header prior to * processing all preceding ones. *  * We do exactly this. This is a protocol bug. We can't decide after a * seeing an unknown discard-with-error flavour TLV option if it's a  * ICMP error message or not (errors should never be send in reply to * ICMP error messages). *  * But I see no other way to do this. This might need to be reexamined * when Linux implements ESP (and maybe AUTH) headers. * --AK * * This function parses (probably truncated) exthdr set "hdr" * of length "len". "nexthdrp" initially points to some place, * where type of the first header can be found. * * It skips all well-known exthdrs, and returns pointer to the start * of unparsable area i.e. the first header with unknown type. * If it is not NULL *nexthdr is updated by type/protocol of this header. * * NOTES: - if packet terminated with NEXTHDR_NONE it returns NULL. *        - it may return pointer pointing beyond end of packet, *	    if the last recognized header is truncated in the middle. *        - if packet is truncated, so that all parsed headers are skipped, *	    it returns NULL. *	  - First fragment header is skipped, not-first ones *	    are considered as unparsable. *	  - ESP is unparsable for now and considered like *	    normal payload protocol. *	  - Note also special handling of AUTH header. Thanks to IPsec wizards. * * --ANK (980726) */int ipv6_skip_exthdr(struct sk_buff *skb, int start, u8 *nexthdrp, int len){	u8 nexthdr = *nexthdrp;	while (ipv6_ext_hdr(nexthdr)) {		struct ipv6_opt_hdr hdr;		int hdrlen;		if (len < (int)sizeof(struct ipv6_opt_hdr))			return -1;		if (nexthdr == NEXTHDR_NONE)			return -1;		if (skb_copy_bits(skb, start, &hdr, sizeof(hdr)))			BUG();		if (nexthdr == NEXTHDR_FRAGMENT) {			struct frag_hdr *fhdr = (struct frag_hdr *) &hdr;			if (ntohs(fhdr->frag_off) & ~0x7)				break;			hdrlen = 8;		} else if (nexthdr == NEXTHDR_AUTH)			hdrlen = (hdr.hdrlen+2)<<2; 		else			hdrlen = ipv6_optlen(&hdr); 		nexthdr = hdr.nexthdr;		len -= hdrlen;		start += hdrlen;	}	*nexthdrp = nexthdr;	return start;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -