📄 output.c
字号:
udph->dest = tunnel->peerport; udph->len = htons(length+sizeof(struct udphdr)); /* Encrypted packets are checksummed already, so we can safely ignore the UDP checksum. Provide a means to do it nonetheless */ udph->check = 0; if (tunnel->flags&CIPF_DO_CSUM) { udph->check=csum_tcpudp_magic( iph->saddr, iph->daddr, length+sizeof(struct udphdr), IPPROTO_UDP, csum_partial((char *)udph, length+sizeof(struct udphdr), 0)); if (!udph->check) udph->check=-1; } dprintk(DEB_OUT, (KERN_INFO "%s: sending %d from %s:%d to %s:%d\n", dev->name, skb->len, cipe_ntoa(iph->saddr), ntohs(udph->source), cipe_ntoa(iph->daddr), ntohs(udph->dest))); if (tunnel->sockshost) dprintk(DEB_OUT, (KERN_INFO "%s: via SOCKS to %s:%d\n", dev->name, cipe_ntoa(tunnel->sockshost), ntohs(tunnel->socksport)));#if 0 dprintk(DEB_OUT, (KERN_INFO "dst: (%d,%d) %s %d %d\n", skb->dst->refcnt, skb->dst->use, skb->dst->dev->name, skb->dst->pmtu, skb->dst->error));#endif#ifdef DEBUG if (cipe_debug&DEB_PKOU) cipe_dump_packet("sending", skb, 0);#endif nf_conntrack_null(skb); skb->ip_summed = CHECKSUM_NONE;#ifdef LINUX_24 { int err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, do_ip_send); if (err==NET_XMIT_SUCCESS || err==NET_XMIT_CN) { tunnel->stat.tx_bytes += skb->len; tunnel->stat.tx_packets++; } else { tunnel->stat.tx_errors++; tunnel->stat.tx_aborted_errors++; } }#else ip_send(skb); tunnel->stat.tx_bytes += skb->len; tunnel->stat.tx_packets++;#endif tunnel->recursion--; return 0; tx_error: ip_rt_put(rt); tx_error_out: tunnel->stat.tx_errors++; dev_kfree_skb(skb); tunnel->recursion--; return 0;}#else /* LINUX_21 *//* An adapted version of Linux 2.0 drivers/net/new_tunnel.c. */#ifdef SO_BINDTODEVICE #define iproute(t,o,d) ip_rt_route(t,o,d)#else #define iproute(t,o,d) ip_rt_route(t,o)#endif#if LINUX_VERSION_CODE < 131102 /* < 2.0.30 */ #include <linux/config.h> #ifdef CONFIG_IP_FORWARD #define ipforward(s,d,o,t) ip_forward(s,d,o,t) #else #error "Requires IP forwarding enabled in kernel" #endif#else /* >= 2.0.30 */ #define ipforward(s,d,o,t) (sysctl_ip_forward ? ip_forward(s,d,o,t) : -1)#endifint cipe_xmit(struct sk_buff *skb, struct NET_DEVICE *dev){ struct enet_statistics *stats; /* This device's statistics */ struct rtable *rt; /* Route to the other host */ struct NET_DEVICE *tdev; /* Device to other host */ struct iphdr *iph; /* Our new IP header */ struct udphdr *udph; __u32 target; /* The other host's IP address */ int max_headroom; /* The extra header space needed */ int max_tailroom; int tos, ttl, length; DEVTOCIPE(dev,c,0); if (skb == NULL || dev == NULL) { dprintk(DEB_OUT, (KERN_INFO "%s: nothing to do\n", dev->name)); return 0; } /* * Make sure we are not busy (check lock variable) */ stats = &(c->stat); if (dev->tbusy != 0) { printk(KERN_WARNING "%s: device timeout (really possible?)\n", dev->name); dev->tbusy=0; stats->tx_errors++; return(1); }#ifdef DEBUG if (cipe_debug&DEB_PKOU) cipe_dump_packet("original", skb, 0);#endif /* * First things first. Look up the destination address in the * routing tables */ target = c->peeraddr; if ((!target) || (!c->peerport) || (!c->myport)) { /* unconfigured device */ printk(KERN_INFO "%s: unconfigured\n", dev->name); goto error; } if ((rt = iproute(target, 0, skb->sk?skb->sk->bound_device:NULL)) == NULL) { /* No route to host */ printk(KERN_INFO "%s: target unreachable\n", dev->name); goto error; } dprintk(DEB_OUT, (KERN_INFO "%s: routing to %08lX from %08lX via %08lX dev %s\n", dev->name, ntohl(rt->rt_dst), ntohl(rt->rt_src), ntohl(rt->rt_gateway), rt->rt_dev->name)); tdev = rt->rt_dev; ip_rt_put(rt); if (tdev == dev) { /* Tunnel to ourselves? -- I don't think so. */ printk ( KERN_INFO "%s: Packet targetted at myself!\n" , dev->name); goto error; } /* * Okay, now see if we can stuff it in the buffer as-is. We can not. */ max_headroom = (((tdev->hard_header_len+15)&~15)+cipehdrlen+ ((c->sockshost) ? sizeof(struct sockshdr) : 0)); max_tailroom = (c->flags&CIPF_HAVE_KEY) ? cipefootlen : 0; { struct sk_buff *new_skb; if ( !(new_skb = dev_alloc_skb(skb->len+max_headroom+max_tailroom)) ) { printk(KERN_INFO "%s: Out of memory, dropped packet\n", dev->name); dev->tbusy = 0; stats->tx_dropped++; dev_kfree_skb(skb, FREE_WRITE); return 0; } new_skb->free = 1; /* * Reserve space for our header and the lower device header */ skb_reserve(new_skb, max_headroom); /* * Copy the old packet to the new buffer. * Note that new_skb->h.iph will be our (tunnel driver's) header * and new_skb->ip_hdr is the IP header of the old packet. */ new_skb->ip_hdr = (struct iphdr *) skb_put(new_skb, skb->len); new_skb->mac.raw = new_skb->data; new_skb->dev = skb->dev; memcpy(new_skb->ip_hdr, skb->data, skb->len); memset(new_skb->proto_priv, 0, sizeof(skb->proto_priv)); /* Free the old packet, we no longer need it */ dev_kfree_skb(skb, FREE_WRITE); skb = new_skb; }#ifdef VER_ETH if (skb->mac.ethernet->h_proto==htons(ETH_P_IP)) {#endif tos = skb->ip_hdr->tos; ttl = skb->ip_hdr->ttl;#ifdef VER_ETH } else { tos = 0; ttl = 64; }#endif length = skb->len; if (c->flags&CIPF_HAVE_KEY) { /* Add an IV */ cipe_cryptpad(skb_push(skb, c->cipher->ivsize), c->cipher->ivsize); length+=c->cipher->ivsize; if (!c->flags&CIPF_MAY_STKEY && !c->flags&CIPF_HAVE_SKEY) /* Attempt to encrypt data using invalid static key */ goto error; cipe_encrypt(c, skb->data, &length, TW_DATA); /* This is incorrect - the tail room gets first used and then reserved. Doesn't matter in the current (2.0.29) implementation of skb_put though. Alternative solution would ruin the nice module separation - we don't need to know the real amount of padding here. */ (void) skb_put(skb, length-skb->len); } else if (!c->flags&CIPF_MAY_CLEAR) { goto error; } if (c->sockshost) { /* Install a SOCKS header */ struct sockshdr *sh = (struct sockshdr *) skb_push(skb, sizeof(struct sockshdr)); memset(sh, 0, 4); sh->atyp=1; /* sockshost and socksport contain the real peer's address and the configured/guessed peer is really the socks relayer! */ sh->dstaddr=c->sockshost; sh->dstport=c->socksport; length+=sizeof(struct sockshdr); } /* Install our new headers */ udph = (struct udphdr *) skb_push(skb, sizeof(struct udphdr)); skb->h.iph = (struct iphdr *) skb_push(skb, sizeof(struct iphdr)); /* * Push down and install the CIPE/UDP header. */ iph = skb->h.iph; iph->version = 4; iph->tos = tos; /* In new_tunnel.c, we use the original packet's TTL here. Setting a new TTL behaves better to the user, and RFC2003 recommends it too. But this doesn't fully protect against routing loops. So make it configurable via an argument: "cttl" gives the TTL value; if 0 use the packet's value. Default should be 64, as with the other protocols (ip_statistics.IpDefaultTTL, but this variable is not available for modules). */ iph->ttl = c->cttl ? c->cttl : ttl; iph->frag_off = 0; iph->daddr = target; iph->saddr = c->myaddr; /* tdev->pa_addr; */ iph->protocol = IPPROTO_UDP; iph->ihl = 5; iph->tot_len = htons(skb->len); iph->id = htons(ip_id_count++); /* Race condition here? */ ip_send_check(iph); udph->source = c->myport; udph->dest = c->peerport; udph->len = htons(length+sizeof(struct udphdr)); /* Encrypted packets are checksummed already, so we can safely ignore the UDP checksum. Provide a means to do it nonetheless */ udph->check = 0; if (c->flags&CIPF_DO_CSUM) { udph->check=csum_tcpudp_magic( iph->saddr, iph->daddr, length+sizeof(struct udphdr), IPPROTO_UDP, csum_partial((char *)udph, length+sizeof(struct udphdr), 0)); if (!udph->check) udph->check=-1; } skb->ip_hdr = skb->h.iph; skb->protocol = htons(ETH_P_IP); /* * Send the packet on its way! * Note that dev_queue_xmit() will eventually free the skb. * If ip_forward() made a copy, it will return 1 so we can free. */ dprintk(DEB_OUT, (KERN_INFO "%s: send to %s via %s\n", dev->name, cipe_ntoa(target), tdev->name));#ifdef DEBUG if (cipe_debug&DEB_PKOU) cipe_dump_packet("sending", skb, 0);#endif switch (ipforward(skb, dev, IPFWD_NOTTLDEC, target)) { case -1: printk(KERN_INFO "%s: forwarding failed\n", dev->name); /* fall thru */ case 1: dev_kfree_skb(skb, FREE_WRITE); /* Does it really need dev_ here? I think so. */ break; default: /* nothing to do */ } /* * Clean up: We're done with the route and the packet */ /* Record statistics and return */ stats->tx_packets++; dev->tbusy=0; return 0; error: stats->tx_errors++; dev_kfree_skb(skb, FREE_WRITE); dev->tbusy=0; return 0;}#endif /* LINUX_21 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -