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

📄 myip_output.c

📁 一个基于linux的TCP/IP协议栈的实现
💻 C
📖 第 1 页 / 共 2 页
字号:
		sk_setup_caps(sk, &rt->u.dst);	}	skb->dst = dst_clone(&rt->u.dst);packet_routed:	if (opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway)		goto no_route;	iph = (struct iphdr *) skb_push(skb, sizeof(struct iphdr) + (opt ? opt->optlen : 0));	*((__u16 *)iph)	= htons((4 << 12) | (5 << 8) | (inet->tos & 0xff));	iph->tot_len = htons(skb->len);	if (ip_dont_fragment(sk, &rt->u.dst) && !ipfragok)		iph->frag_off = htons(IP_DF);	else		iph->frag_off = 0;	iph->ttl      = myip_select_ttl(inet, &rt->u.dst);	iph->protocol = sk->sk_protocol - ( MY_IPPROTO_UDP - IPPROTO_UDP );	iph->saddr    = rt->rt_src;	iph->daddr    = rt->rt_dst;	skb->nh.iph   = iph;	if (opt && opt->optlen) {		iph->ihl += opt->optlen >> 2;		myip_options_build(skb, opt, inet->daddr, rt, 0);	}	ip_select_ident_more(iph, &rt->u.dst, sk,			     (skb_shinfo(skb)->tso_segs ?: 1) - 1);	myip_send_check(iph);	skb->priority = sk->sk_priority;	return NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev,					dst_output);no_route:	MYIP_INC_STATS(IPSTATS_MIB_OUTNOROUTES);	kfree_skb(skb);	return -EHOSTUNREACH;}static int myip_dev_loopback_xmit(struct sk_buff *newskb){	newskb->mac.raw = newskb->data;	__skb_pull(newskb, newskb->nh.raw - newskb->data);	newskb->pkt_type = PACKET_LOOPBACK;	newskb->ip_summed = CHECKSUM_UNNECESSARY;	BUG_TRAP(newskb->dst);	netif_rx(newskb);	return 0;}void myip_flush_pending_frames(struct sock *sk){	struct inet_sock *inet = inet_sk(sk);	struct sk_buff *skb;	while ((skb = __skb_dequeue_tail(&sk->sk_write_queue)) != NULL)		kfree_skb(skb);	inet->cork.flags &= ~IPCORK_OPT;	kfree(inet->cork.opt);	inet->cork.opt = NULL;	if (inet->cork.rt) {		ip_rt_put(inet->cork.rt);		inet->cork.rt = NULL;	}}__inline__ void myip_send_check(struct iphdr *iph){	iph->check = 0;	iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);}int myip_push_pending_frames(struct sock *sk){	struct sk_buff *skb, *tmp_skb;	struct sk_buff **tail_skb;	struct inet_sock *inet = inet_sk(sk);	struct ip_options *opt = NULL;	struct rtable *rt = inet->cork.rt;	struct iphdr *iph;	__be16 df = 0;	__u8 ttl;	int err = 0;		if ((skb = __skb_dequeue(&sk->sk_write_queue)) == NULL)		goto out;	tail_skb = &(skb_shinfo(skb)->frag_list);	if (skb->data < skb->nh.raw)		__skb_pull(skb, skb->nh.raw - skb->data);	while ((tmp_skb = __skb_dequeue(&sk->sk_write_queue)) != NULL) {		__skb_pull(tmp_skb, skb->h.raw - skb->nh.raw);		*tail_skb = tmp_skb;		tail_skb = &(tmp_skb->next);		skb->len += tmp_skb->len;		skb->data_len += tmp_skb->len;		skb->truesize += tmp_skb->truesize;		__sock_put(tmp_skb->sk);		tmp_skb->destructor = NULL;		tmp_skb->sk = NULL;	}	if (inet->pmtudisc != IP_PMTUDISC_DO)		skb->local_df = 1;	if (inet->pmtudisc == IP_PMTUDISC_DO || (skb->len <= dst_mtu(&rt->u.dst) &&							ip_dont_fragment(sk, &rt->u.dst)))		df = htons(IP_DF);		if (inet->cork.flags & IPCORK_OPT)		opt = inet->cork.opt;	if (rt->rt_type == RTN_MULTICAST)		ttl = inet->mc_ttl;	else		ttl = myip_select_ttl(inet, &rt->u.dst);	iph = (struct iphdr *)skb->data;	iph->version = 4;	iph->ihl = 5;	if (opt) {		iph->ihl += opt->optlen>>2;		myip_options_build(skb, opt, inet->cork.addr, rt, 0);	}	iph->tos = inet->tos;	iph->tot_len = htons(skb->len);	iph->frag_off = df;	if (!df) {		__myip_select_ident(iph, &rt->u.dst, 0);	} else {		iph->id = htons(inet->id++);	}	iph->ttl = ttl;	iph->protocol = sk->sk_protocol - (MY_IPPROTO_UDP - IPPROTO_UDP);	iph->saddr = rt->rt_src;	iph->daddr = rt->rt_dst;	myip_send_check(iph);	skb->priority = sk->sk_priority;	skb->dst = dst_clone(&rt->u.dst);	err = NF_HOOK(MY_PF_INET, NF_IP_LOCAL_OUT, skb, NULL, skb->dst->dev, dst_output);	if( err ){		if (err > 0)			err = inet->recverr ? net_xmit_errno(err) : 0;		if( err )			goto error;	}out:	inet->cork.flags &= ~IPCORK_OPT;	kfree(inet->cork.opt);	inet->cork.opt = NULL;	if (inet->cork.rt) {		ip_rt_put(inet->cork.rt);		inet->cork.rt = NULL;	}	return err;error:	MYIP_INC_STATS(IPSTATS_MIB_OUTDISCARDS);	goto out;}static inline int myip_finish_output2(struct sk_buff *skb){	struct dst_entry *dst = skb->dst;	struct hh_cache *hh = dst->hh;	struct net_device *dev = dst->dev;	int hh_len = LL_RESERVED_SPACE(dev);		if (unlikely(skb_headroom(skb) < hh_len && dev->hard_header)) {		struct sk_buff *skb2;		skb2 = skb_realloc_headroom(skb, LL_RESERVED_SPACE(dev));		if (skb2 == NULL) {			kfree_skb(skb);			return -ENOMEM;		}		if (skb->sk)			skb_set_owner_w(skb2, skb->sk);		kfree_skb(skb);		skb = skb2;	}	if (hh) {		int hh_alen;		read_lock_bh(&hh->hh_lock);		hh_alen = HH_DATA_ALIGN(hh->hh_len);  		memcpy(skb->data - hh_alen, hh->hh_data, hh_alen);		read_unlock_bh(&hh->hh_lock);	        skb_push(skb, hh->hh_len);		return hh->hh_output(skb);	} else if (dst->neighbour)		return dst->neighbour->output(skb);	if (net_ratelimit())		printk(KERN_DEBUG "ip_finish_output2: No header cache and no neighbour!\n");	kfree_skb(skb);	return -EINVAL;}static inline int myip_finish_output(struct sk_buff *skb){#if defined(CONFIG_NETFILTER) && defined(CONFIG_XFRM)	/* Policy lookup after SNAT yielded a new policy */	if (skb->dst->xfrm != NULL) {		//IPCB(skb)->flags |= IPSKB_REROUTED;		//return dst_output(skb);		printk(KERN_INFO "xfrm != 0\n" );	}#endif	if (skb->len > dst_mtu(skb->dst) &&	    !(skb_shinfo(skb)->ufo_size || skb_shinfo(skb)->tso_size))		//return ip_fragment(skb, ip_finish_output2);		printk(KERN_INFO "need fragment!\n");	else		return myip_finish_output2(skb);}int myip_output(struct sk_buff *skb){	struct net_device *dev = skb->dst->dev;	MYIP_INC_STATS(IPSTATS_MIB_OUTREQUESTS);	skb->dev = dev;	skb->protocol = htons(ETH_P_IP);	return NF_HOOK_COND(MY_PF_INET, NF_IP_POST_ROUTING, skb, NULL, dev,					myip_finish_output,					!(IPCB(skb)->flags & IPSKB_REROUTED));}int myip_mc_output(struct sk_buff *skb){	struct sock *sk = skb->sk;	struct rtable *rt = (struct rtable*)skb->dst;	struct net_device *dev = rt->u.dst.dev;	MYIP_INC_STATS(IPSTATS_MIB_OUTREQUESTS);	skb->dev = dev;	skb->protocol = htons(ETH_P_IP);		if( rt->rt_flags & RTCF_MULTICAST ){		if ((!sk || inet_sk(sk)->mc_loop)#ifdef CONFIG_IP_MROUTE						&& ((rt->rt_flags&RTCF_LOCAL) || !(IPCB(skb)->flags&IPSKB_FORWARDED))#endif		){			struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC);			if (newskb)				NF_HOOK(MY_PF_INET, NF_IP_POST_ROUTING, newskb, NULL,								newskb->dev, myip_dev_loopback_xmit);		}		if (skb->nh.iph->ttl == 0) {			kfree_skb(skb);			return 0;		}	}	if( rt->rt_flags & RTCF_BROADCAST ){		struct sk_buff *newskb = skb_clone(skb, GFP_ATOMIC);		if (newskb)			NF_HOOK(PF_INET, NF_IP_POST_ROUTING, newskb, NULL,				newskb->dev, myip_dev_loopback_xmit);	}	return NF_HOOK_COND(PF_INET, NF_IP_POST_ROUTING, skb, NULL, skb->dev,					myip_finish_output,					!(IPCB(skb)->flags & IPSKB_REROUTED));}static int myip_reply_glue_bits(void *dptr, char *to, int offset, 				int len, int odd, struct sk_buff *skb){	unsigned int csum;	csum = csum_partial_copy_nocheck(dptr+offset, to, len, 0);	skb->csum = csum_block_add(skb->csum, csum, odd);	return 0;  }void myip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *arg,		   unsigned int len){	struct inet_sock *inet = inet_sk(sk);	struct {		struct ip_options	opt;		char			data[40];	} replyopts;	struct ipcm_cookie ipc;	u32 daddr;	struct rtable *rt = (struct rtable*)skb->dst;	if( myip_options_echo(&replyopts.opt, skb) )		return;	daddr = ipc.addr = rt->rt_src;	ipc.opt = NULL;	if( replyopts.opt.optlen ){		ipc.opt = &replyopts.opt;		if (ipc.opt->srr)			daddr = replyopts.opt.faddr;	}	{		struct flowi fl = { .nl_u = { .ip4_u =					      { .daddr = daddr,						.saddr = rt->rt_spec_dst,						.tos = RT_TOS(skb->nh.iph->tos) } },				    .uli_u = { .ports =					       { .sport = skb->h.th->dest,					         .dport = skb->h.th->source } },				    .proto = sk->sk_protocol };		if( myip_route_output_key(&rt, &fl) )			return;	}	bh_lock_sock(sk);	inet->tos = skb->nh.iph->tos;	sk->sk_priority = skb->priority;	sk->sk_protocol = skb->nh.iph->protocol + (MY_IPPROTO_UDP - IPPROTO_UDP);	myip_append_data(sk, myip_reply_glue_bits, arg->iov->iov_base, len, 0,					&ipc, rt, MSG_DONTWAIT);	if ((skb = skb_peek(&sk->sk_write_queue)) != NULL) {		if (arg->csumoffset >= 0)			*((u16 *)skb->h.raw + arg->csumoffset) = csum_fold(csum_add(skb->csum, arg->csum));		skb->ip_summed = CHECKSUM_NONE;		myip_push_pending_frames(sk);	}	bh_unlock_sock(sk);	ip_rt_put(rt);}

⌨️ 快捷键说明

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