📄 myip_output.c
字号:
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 + -