📄 sock.c
字号:
/* CIPE - encrypted IP over UDP tunneling sock.c - socket/input interface Copyright 1996 Olaf Titz <olaf@bigred.inka.de> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.*//* $Id: linux-2.4.0-cipe-1.4.5.patch,v 1.6 2001/04/17 18:50:11 arjanv Exp $ */#include "cipe.h"#include <linux/config.h>#include <linux/sched.h>#include <net/sock.h>#include <net/ip.h>#include <net/udp.h>#ifdef LINUX_21#include <asm/uaccess.h>#elsetypedef unsigned short mm_segment_t;#endif#ifdef LINUX_21#define kfreeskb(s,t) kfree_skb(s)#define saddr(skb) ((skb)->nh.iph->saddr)#define daddr(skb) ((skb)->nh.iph->daddr)#else#define kfreeskb(s,t) kfree_skb(s,t)#define saddr(skb) ((skb)->saddr)#define daddr(skb) ((skb)->daddr)#endif/* Rewire generic socket operations to our device-specific ones. We have new routines for close, sendmsg, recvmsg. *//* init struct cipe *c based on struct sock *sk */#ifdef LINUX_21#define SOCKTOC(nam,sk,c,r) \ struct cipe *c=(struct cipe *)sk->user_data; \ if ((!c) || (c->magic!=CIPE_MAGIC)) { \ printk(KERN_ERR "Ouch: SOCKTOC" nam "\n"); return r; } \ else { \ dprintk(DEB_CALL, (KERN_DEBUG "%s: " nam "\n", c->dev->name)); }#else#define SOCKTOC(nam,sk,c,r) \ struct cipe *c=(struct cipe *)sk->protinfo.af_packet.bound_dev; \ if ((!c) || (c->magic!=CIPE_MAGIC)) { \ printk(KERN_ERR "Ouch: SOCKTOC" nam "\n"); return r; } \ else { \ dprintk(DEB_CALL, (KERN_DEBUG "%s: " nam "\n", c->dev->name)); }#endif/* Close the socket */void cipe_sock_close(struct sock *sock, timeout_t timeout){ SOCKTOC("sock_close",sock,c,); c->sock=NULL; /* Put back the old protocol block and let it do the close */ sock->prot=c->udp_prot; sock->prot->close(sock, timeout); if (c->dev->flags&IFF_UP) { rtnl_LOCK(); dev_close(c->dev); rtnl_UNLOCK(); } else { cipe_close(c); }}/* Anything we send to this socket is in fact a key exchange block. Encode and encrypt it accordingly.*/int cipe_sendmsg(struct sock *sock, struct msghdr *msg, int len#ifndef LINUX_21 , int nonblock, int flags#endif ){ struct msghdr mymsg; struct iovec myio[2]; struct sockaddr_in sa; struct sockshdr sh; int e, n=0; unsigned char buf[KEYXCHGBLKMAX+blockSize]; SOCKTOC("cipe_sendmsg",sock,c,-ENOSYS); if (len>KEYXCHGBLKMAX) return -EMSGSIZE; cipe_prnpad(buf, sizeof(buf));#ifdef VER_SHORT memcpy_fromiovec(buf, msg->msg_iov, len);#else memcpy_fromiovec(buf+blockSize, msg->msg_iov, len); len+=blockSize;#endif if (buf[0#ifndef VER_SHORT +blockSize#endif ]>=CT_DUMMY) { if (!c->flags&CIPF_HAVE_KEY) return -EINVAL; buf[KEYXCHGTSPOS-1]='\0'; } else { if (len<KEYXCHGBLKMIN) return -EINVAL; } (*(__u32 *)(buf+KEYXCHGTSPOS))=htonl(CURRENT_TIME); /* timestamp */ len=KEYXCHGBLKMIN+buf[sizeof(buf)-1]; /* random */ cipe_encrypt(c, buf, &len, TW_NEWKEY); sa.sin_family=AF_INET; sa.sin_addr.s_addr=c->peeraddr; sa.sin_port=c->peerport; if (c->sockshost) { /* Prepend a socks header. */ memset(&sh, 0, sizeof(sh)); sh.atyp=1; sh.dstaddr=c->sockshost; sh.dstport=c->socksport; myio[n].iov_base=&sh; myio[n].iov_len=sizeof(sh); ++n; } myio[n].iov_base=&buf; myio[n].iov_len=len; /* mymsg=*msg; */ mymsg.msg_name=&sa; mymsg.msg_namelen=sizeof(sa); mymsg.msg_iov=myio; mymsg.msg_iovlen=n+1; /* just to be sure */ mymsg.msg_control=NULL; mymsg.msg_controllen=0; mymsg.msg_flags=0; /* Call the real thing. Pretend this is user space segment. */ { mm_segment_t fs=get_fs(); set_fs(get_ds()); if (c->sockshost) len+=sizeof(struct sockshdr); dprintk(DEB_KXC, (KERN_DEBUG "%s: real sendmsg len %d text=%04x...\n", c->dev->name, len, ntohs(*((unsigned short *)(myio[n].iov_base))))); e=c->udp_prot->sendmsg(sock, &mymsg, len#ifndef LINUX_21 , nonblock, flags#endif ); set_fs(fs); } return e;}/* Check if we have a new peer */static void checkpeer(struct cipe *c, __u32 saddr, __u16 sport){ if (c->sockshost) { if (c->sockshost==saddr && c->socksport==sport) return; /* sockshost and socksport contain the real peer's address and the configured/guessed peer is really the socks relayer! */ c->sockshost=saddr; c->socksport=sport; } else { if (c->peeraddr==saddr && c->peerport==sport) return; c->peeraddr=saddr; c->peerport=sport; } printk(KERN_NOTICE "%s: new peer %s:%d\n", c->dev->name, cipe_ntoa(saddr), ntohs(sport));}/* Decrypt a received packet. Requeue it or return kxc block. *//* On entry the packet starts with the original UDP header, ip_hdr and h.uh are set to the IP and UDP headers. */struct sk_buff *cipe_decrypt_skb(struct cipe *c, struct sock *sk, struct sk_buff *skb, int *offset, int *msgflag){ struct sk_buff *n=NULL; int length; __u32 rsaddr; __u16 rsport;#ifdef DEBUG if (cipe_debug&DEB_PKIN) cipe_dump_packet("received", skb, 1);#endif length = skb->len - sizeof(struct udphdr); n=alloc_skb(skb->len, GFP_KERNEL); if (!n) { printk(KERN_WARNING "%s: cipe_decrypt_skb: out of memory\n", c->dev->name); ++c->stat.rx_dropped; return NULL; }#if 0 /*def LINUX_21*/ if (skb->sk) skb_set_owner_r(n, skb->sk);#endif#ifndef LINUX_21 n->free=1;#endif n->dev=c->dev; /* Copy the datagram into new buffer, skip IP header */ /* We must copy here because raw sockets get only a clone of the skbuff, so they would receive the plaintext */ dprintk(DEB_INP, (KERN_DEBUG DEVNAME ": sa=%s da=%s us=%d ud=%d ul=%d\n", cipe_ntoa(saddr(skb)), cipe_ntoa(daddr(skb)), ntohs(skb->h.uh->source), ntohs(skb->h.uh->dest), ntohs(skb->h.uh->len))); /* why did this get swapped?? */#ifdef LINUX_21 rsaddr=saddr(skb);#else rsaddr=daddr(skb);#endif rsport=skb->h.uh->source; skb_put(n,skb->len);#ifdef MAX_SKB_FRAGS /* Zerocopy version. -DaveM */ skb_copy_bits(skb, (skb->h.raw - skb->data), n->data, skb->len);#else memcpy(n->data, skb->h.raw, skb->len);#endif n->h.uh=(struct udphdr *)n->data; if (c->sockshost) { /* Pull out the SOCKS header and correct the peer's address. */ struct sockshdr *sh; sh=(struct sockshdr *)skb_pull(n, sizeof(struct udphdr)); dprintk(DEB_INP, (KERN_DEBUG "socks: fr=%d at=%d da=%s dp=%d\n", sh->frag, sh->atyp, cipe_ntoa(sh->dstaddr), ntohs(sh->dstport))); if (sh->frag || (sh->atyp!=1)) goto error; /* Pull out UDP header */#ifdef LINUX_21 n->nh.iph=(struct iphdr *)skb_pull(n, sizeof(struct sockshdr));#else n->ip_hdr=(struct iphdr *)skb_pull(n, sizeof(struct sockshdr));#endif /***saddr(n)=sh->dstaddr;*/ rsaddr=sh->dstaddr; rsport=n->h.uh->source=sh->dstport; length-=sizeof(struct sockshdr); *offset=sizeof(struct sockshdr)+sizeof(struct udphdr); } else { /* Pull out UDP header */#ifdef LINUX_21 n->nh.iph=(struct iphdr *) skb_pull(n, sizeof(struct udphdr));#else n->ip_hdr=(struct iphdr *) skb_pull(n, sizeof(struct udphdr));#endif /***saddr(n)=rsaddr;*/ n->h.uh->source=rsport; *offset=0; } n->mac.raw=n->data; /* no hardware header */ if (c->flags&CIPF_HAVE_KEY) { if (length%blockSize) { printk(KERN_DEBUG "%s: got bogus length=%d\n", c->dev->name, length); goto error; } switch (cipe_decrypt(c, n->data, &length)) { case TW_DATA: if (!c->flags&CIPF_MAY_STKEY && !c->flags&CIPF_HAVE_RKEY) { printk(KERN_ERR "%s: got data using invalid static key\n", c->dev->name); goto error; } break; case TW_CTRL: /* return it as a control block - out of band datagram */ *msgflag|=MSG_OOB; /* fall thru */ case TW_NEWKEY: /* return it as key exchange block - proper UDP datagram */ dprintk(DEB_INP, (KERN_DEBUG "TW_NEWKEY data=%p len=%d length=%d\n", n->data, n->len, length));#ifdef LINUX_21 do_gettimeofday(&n->stamp);#endif skb_trim(n, length); checkpeer(c, rsaddr, rsport);#if 0 n->saddr=c->myaddr; n->daddr=c->peeraddr;#endif n->h.uh->check=0; return n; default: /* Bogus packet etc. */ ++c->stat.rx_crc_errors; goto error; } } else if (!c->flags&CIPF_MAY_CLEAR) { goto error; } dprintk(DEB_INP, (KERN_DEBUG "TW_DATA data=%p len=%d length=%d\n", n->data, n->len, length)); skb_trim(n, length); checkpeer(c, rsaddr, rsport); /* adjust pointers */#ifdef LINUX_21 n->nh.iph=(struct iphdr *)n->data; memset(&(IPCB(n)->opt), 0, sizeof(IPCB(n)->opt));#else n->h.iph=(struct iphdr *)n->data; memset(n->proto_priv, 0, sizeof(struct options));#endif if (length<cipehdrlen+(c->sockshost?sizeof(struct sockshdr):0)) { printk(KERN_INFO "%s: got short packet from %s\n", c->dev->name, cipe_ntoa(saddr(skb))); goto framerr; } n->protocol = __constant_htons(ETH_P_IP); n->ip_summed = 0; n->pkt_type = PACKET_HOST; dprintk(DEB_INP, (KERN_DEBUG "%s: real src %s dst %s len %d\n", n->dev->name, cipe_ntoa(saddr(n)),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -