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

📄 sock.c

📁 cipe 编程
💻 C
📖 第 1 页 / 共 2 页
字号:
/*   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: sock.c,v 1.47 2004/03/06 22:16:41 olaf81825 Exp $ */#include "cipe.h"#include <linux/config.h>#include <linux/sched.h>#include <net/sock.h>#include <net/ip.h>#include <linux/tcp.h>#include <linux/etherdevice.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. */#ifndef LINUX_21#define user_data protinfo.af_packet.bound_dev#endif/* init struct cipe *c based on struct sock *sk */#define SOCKTOC(nam,sk,c) \    struct cipe *c=(struct cipe *)sk->sk_user_data; \    BUG_ON((!c) || (c->magic!=CIPE_MAGIC)); \    dprintk(DEB_CALL, (KERN_INFO "%s: " nam "\n", c->dev->name));/* 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->sk_prot=c->udp_prot;    sock->sk_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(#ifdef LINUX_25    struct kiocb *iocb,#endif    struct sock *sock, struct msghdr *msg#ifdef LINUX_25    , size_t len#else    , int len#endif#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, ivs;    unsigned char buf[KEYXCHGBLKMAX];    SOCKTOC("cipe_sendmsg",sock,c);    ivs=crypto_tfm_alg_ivsize(c->key);    if (!(c->flags&CIPF_HAVE_KEY) && !(msg->msg_flags&MSG_OOB))        return -EINVAL;    if (len>KEYXCHGBLKMAX-ivs)	return -EMSGSIZE;    cipe_prnpad(buf, sizeof(buf));    memcpy_fromiovec(buf+ivs, msg->msg_iov, len);    len+=ivs;    if (!(msg->msg_flags&MSG_OOB)) {	if (buf[ivs]>=CT_DUMMY) {	    buf[KEYXCHGTSPOS-1]='\0';	} else {	    if (len<KEYXCHGBLKMIN)		return -EINVAL;	}    }    (*(__u32 *)(buf+KEYXCHGTSPOS))=htonl(CURRENT_TIME_SEC); /* timestamp */    if (msg->msg_flags&MSG_OOB) {	memset(buf, 0, ivs);    } else {	len=KEYXCHGBLKMIN+buf[sizeof(buf)-1]; /* random */	cipe_encrypt(c, buf, (int*)&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;    if (c->sockshost)        len+=sizeof(struct sockshdr);    /* 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());        dprintk(DEB_KXC, (KERN_INFO "%s: real sendmsg len %ld text=%04x...\n",                          c->dev->name, (long)len,                          ntohs(*((unsigned short *)(myio[n].iov_base)))));#ifdef LINUX_25        e=c->udp_prot->sendmsg(NULL, sock, &mymsg, len);#else#ifdef LINUX_21        e=c->udp_prot->sendmsg(sock, &mymsg, len);#else        e=c->udp_prot->sendmsg(sock, &mymsg, len, nonblock, flags);#endif#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 *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=ntohs(skb->h.uh->len)-sizeof(struct udphdr);#if 0 /* UDP should check this */    if (length!=skb->len-sizeof(struct udphdr)) {	dprintk(DEB_INP, (KERN_INFO "%s: bogus UDP length (%d/%d)\n",                          c->dev->name, length,                          skb->len-sizeof(struct udphdr)));	goto framerr;    }#endif    if (length<9+(c->sockshost?sizeof(struct sockshdr):0)) {        /* XX hardcoded IV size */        printk(KERN_INFO "%s: got short packet from %s\n", c->dev->name,               cipe_ntoa(saddr(skb)));	goto framerr;    }    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_INFO 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 LINUX_24    if (skb_is_nonlinear(skb)) {#ifdef DEBUG       dprintk(DEB_INP, (KERN_INFO DEVNAME                         ": skb is non linear, will linearize\n"));#endif       if (skb_linearize(skb, GFP_KERNEL) != 0)       {               printk(KERN_WARNING "%s: cipe_decrypt_skb: out of memory\n",                      c->dev->name);               goto error;       }    }#endif    memcpy(n->data, skb->h.raw, skb->len);    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_INFO "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);    } 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;    }    if (!(*((__u32 *)n->data) & htonl(0x7FFFFFFF))) {	dprintk(DEB_INP,                (KERN_INFO "got unencrypted control packet (iv=0) len=%d\n",                 length));	skb_pull(n, 8); /* XX hardcoded IV size */	/* XX not sure about TW_CTRL handling... */        switch (*n->data) {            /* Restrict what can be received unencrypted. */        case CT_DUMMY: case CT_DEBUG: case CT_CONFREQ: case CT_CONF:            break;        default:            printk(KERN_WARNING                   "%s: got disallowed unencrypted control %02x\n",                   c->dev->name, *n->data);            goto error;        }#ifdef LINUX_21	get_fast_time(&n->stamp);#endif	/* No checkpeer() here because not authenticated! */	n->h.uh->check=0;	return n;    }    if (c->flags&CIPF_HAVE_KEY) {	if (length%crypto_tfm_alg_ivsize(c->key)) {	    printk(KERN_INFO "%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=" FLEN                              " length=%d\n", n->data, n->len, length));#ifdef LINUX_21	    get_fast_time(&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=" FLEN "length=%d\n",                      n->data, n->len, length));    skb_trim(n, length);    checkpeer(c, rsaddr, rsport);    /* adjust pointers */#ifdef VER_ETH    n->protocol = eth_type_trans(n, c->dev);    /* n->pkt_type = PACKET_HOST; */#else    n->mac.raw=n->data;	/* no hw header */

⌨️ 快捷键说明

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