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

📄 device.c

📁 cipe 编程
💻 C
📖 第 1 页 / 共 2 页
字号:
/*   CIPE - encrypted IP over UDP tunneling   device.c - the net device driver   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: device.c,v 1.56 2004/08/03 08:21:17 olaf81825 Exp $ */#include "cipe.h"#include "version.h"#include <stddef.h>#include <linux/if_arp.h>#include <linux/sched.h>#include <linux/etherdevice.h>#ifdef LINUX_21#include <asm/uaccess.h>#include <linux/rtnetlink.h>#include <linux/notifier.h>#else#define register_netdevice register_netdev#define unregister_netdevice unregister_netdev#endif/*** Globals ***/static const char driver_version[]=VERSION;struct cipe_ctrl **cipe_ctrls = NULL;/* Parameters settable via insmod, from module.c */extern int cipe_maxdev;#ifdef DEBUGextern int cipe_debug;#endif/* clear all potentially sensitive info and stats */static void cipe_zero_c(struct cipe *c){#define freekey(K)                                              \    if (c->K) {                                                 \        cipe_free_tfm(c->K);                                    \        c->K = NULL;                                            \    }    /* clear and free keys */    freekey(key);    freekey(skey);    freekey(rkey);    /* clear other parameters */    /* NB. this nulls the key pointers */    memset(&(c->peeraddr), 0,           offsetof(struct cipe, udp_prot)-offsetof(struct cipe, peeraddr));    /* reset these to sensible values */    c->tmo_keyxchg = 10*HZ;    c->tmo_keylife = 10*60*HZ;#undef freekey}/* weak but fast PRNG, used for padding only */static __u32 prnseed;void cipe_prnpad(unsigned char *buf, int len){    while (len>0) {	prnseed=prnseed*0x01001001+1;	if (len>=2) {	    *(__u16 *)buf=prnseed>>16;	    len-=2; buf+=2;	} else {	    *buf=(prnseed>>24)^jiffies; return;	}    }}#ifdef DO_LOCK_PRINTKspinlock_t cipe_printk_lock = SPIN_LOCK_UNLOCKED;#endif/* inet_ntoa() for multiple use. */#ifdef __SMP__#define NTOABUFS	16#else#define NTOABUFS	4#endifstatic char ntoabuf[NTOABUFS][16];static int ntoaptr=0;#ifdef LINUX_21spinlock_t cipe_ntoa_lock=SPIN_LOCK_UNLOCKED;#endifconst char *cipe_ntoa(const __u32 addr){    const unsigned char *x=(const unsigned char *)&addr;    char *p;    int b, i;#ifdef LINUX_21    unsigned long flags;    spin_lock_irqsave(&cipe_ntoa_lock, flags);#endif    b=ntoaptr;    if (++b>=NTOABUFS)	b=0;    ntoaptr=b;#ifdef LINUX_21    spin_unlock_irqrestore(&cipe_ntoa_lock, flags);#endif    p=ntoabuf[b];    for (i=0; i<4; ++i) {        int k=x[i]/100;        int l=(x[i]/10)%10;        if (k)            *p++=k+'0';        if (k || l)            *p++=l+'0';        *p++=(x[i]%10)+'0';        if (i<3)            *p++='.';    }    *p='\0';    return ntoabuf[b];}/*** IOCTL handlers ***/#ifdef SIOCGIFCIPPARstatic int cipe_getpar(struct NET_DEVICE *dev, struct siocgifcippar *parm){    DEVTOCIPE(dev,c,-ENODEV);    memset(parm->socks, 0, sizeof(parm->socks));    if (c->sockshost&&c->socksport) {	parm->socks.sin_family=PF_INET;	parm->socks.sin_port=c->socksport;	parm->socks.sin_addr.s_addr=c->sockshost;    }    parm->tmo_keyxchg=c->tmo_keyxchg/HZ;    parm->tmo_keylife=c->tmo_keylife/HZ;    parm->flags=c->flags;    parm->cttl=c->cttl;    *parm->cname=0; /* currently no name info available */    return 0;}#endifstatic int cipe_setpar(struct NET_DEVICE *dev, struct siocsifcippar *parm){    DEVTOCIPE(dev,c,-ENODEV);    if (parm->socks.sin_family==PF_INET) {	c->sockshost=parm->socks.sin_addr.s_addr;	c->socksport=parm->socks.sin_port;    }    if (parm->tmo_keyxchg>10*60*HZ)	return -EINVAL;    if (parm->tmo_keyxchg)	c->tmo_keyxchg=parm->tmo_keyxchg*HZ;    if (parm->tmo_keylife>24*60*60*HZ)	return -EINVAL;    if (parm->tmo_keylife)	c->tmo_keylife=parm->tmo_keylife*HZ;    c->flags=(parm->flags&CIPF_MASK_EXT)|(c->flags&CIPF_MASK_INT);    c->cttl=parm->cttl;    printk(KERN_DEBUG "crypto_alloc_tfm `%s'\n", parm->cname);    if (!(c->key=cipe_alloc_tfm(parm->cname, CRYPTO_TFM_MODE_CBC)))        return(-ENXIO);    if (crypto_tfm_alg_blocksize(c->key)!=8||crypto_tfm_alg_ivsize(c->key)!=8)        printk(KERN_WARNING "%s: %s: unsupported cipher block size\n",               dev->name, parm->cname);    if (crypto_tfm_alg_ivsize(c->key)>MAXIVSIZE) {        printk(KERN_ERR "%s: %s: cipher ivsize too big\n",               dev->name, parm->cname);        return(-ENXIO);    }    if (!(c->skey=cipe_alloc_tfm(parm->cname, CRYPTO_TFM_MODE_CBC)))        return(-ENXIO);    if (!(c->rkey=cipe_alloc_tfm(parm->cname, CRYPTO_TFM_MODE_CBC)))        return(-ENXIO);    dprintk(DEB_CALL, (KERN_DEBUG "%s: setpar %s:%d %ld %ld %04x %d\n",                       dev->name,                       cipe_ntoa(c->sockshost), ntohs(c->socksport),                       c->tmo_keyxchg, c->tmo_keylife,                       c->flags, c->cttl));    return 0;}static int cipe_setkey(struct NET_DEVICE *dev, struct siocsifcipkey *parm){    DEVTOCIPE(dev,c,-ENODEV);#define ExpandUserKey(K) \        crypto_cipher_setkey(c->K, parm->thekey, parm->keylen);#define NullKey(K) \        crypto_cipher_setkey(c->K, "\0\0\0\0\0\0\0\0", 8);    dprintk(DEB_KXC, (KERN_INFO "%s: setkey %d\n", dev->name, parm->which));    switch (parm->which) {    case KEY_STATIC:	ExpandUserKey(key);	c->flags|=CIPF_HAVE_KEY+CIPF_NOTIFY_DERR;	break;    case KEY_SEND:	ExpandUserKey(skey);	c->timeskey=jiffies+c->tmo_keylife;	c->cntskey=0;	c->flags|=CIPF_HAVE_SKEY;	break;    case KEY_RECV:	ExpandUserKey(rkey);	c->timerkey=jiffies+2*c->tmo_keylife; /* allow for fuzz */	c->cntrkey=0;	c->flags|=CIPF_HAVE_RKEY;	break;    case KEY_STATIC+KEY_INVAL:        c->flags&=~(CIPF_HAVE_KEY|CIPF_HAVE_SKEY|CIPF_HAVE_RKEY);        if (c->key)            NullKey(key);	break;    case KEY_SEND+KEY_INVAL:        c->flags&=~CIPF_HAVE_SKEY;        if (c->skey)            NullKey(skey);	c->timeskey=jiffies+c->tmo_keyxchg;	break;    case KEY_RECV+KEY_INVAL:        c->flags&=~CIPF_HAVE_RKEY;        if (c->rkey)            NullKey(rkey);	c->timerkey=jiffies+c->tmo_keyxchg;	break;    default:        return -EINVAL;    }    return 0;#undef ExpandUserKey#undef NullKey}static int cipe_alloc_dev(int n);static void cipe_unalloc_dev(int n);static int cipe_owner(struct cipe *c){    struct task_struct *p;    pid_t pid=c->owner;    tasklist_LOCK();    p=current;    do {	if (p->pid==pid) {	    tasklist_UNLOCK();	    return pid;	}        p=next_task(p);    } while (p!=current);    tasklist_UNLOCK();    return 0;}#define cipe_nowner(n) cipe_owner(&cipe_ctrls[(n)]->cipe)static int cipe_alloc(struct NET_DEVICE *dev, struct siocsifcipall *parm){#ifdef NO_DYNDEV    return -ENOSYS;#else    int n=parm->num;    int e;    if (n>=cipe_maxdev)        return -EINVAL;    if ((e=cipe_alloc_LOCK()))        return e;    if (n>=0) {        if (cipe_ctrls[n]) {            if (cipe_ctrls[n]->cipe.sock || (e=cipe_nowner(n))) {		printk(KERN_DEBUG DEVNAME ": dev %d busy pid=%d\n", n, e);                e=-EBUSY;            } else {                cipe_ctrls[n]->cipe.owner=current->pid;	    }        } else {            e=cipe_alloc_dev(n);        }    } else {        e=-EMFILE;        for (n=0; n<cipe_maxdev; ++n) {            if (!cipe_ctrls[n]) {                e=cipe_alloc_dev(n);                break;            }            if (!cipe_nowner(n)) {                cipe_ctrls[n]->cipe.owner=current->pid;                e=0;                break;            }        }    }    if (!e) {        parm->num=n;        strncpy(parm->name, cipe_ctrls[n]->dev.name, sizeof(parm->name)-1);        parm->name[sizeof(parm->name)-1]='\0';    }    cipe_alloc_UNLOCK();    return e;#endif}static int cipe_unalloc(struct NET_DEVICE *dev, struct siocsifcipall *parm){#ifdef NO_DYNDEV    return -ENOSYS;#else    int e;    if (parm->num<0 || parm->num>=cipe_maxdev)        return -EINVAL;    if ((e=cipe_alloc_LOCK()))        return e;    if (cipe_ctrls[parm->num]->cipe.sock) {        e=-EBUSY;    } else {        if (parm->num>0)            cipe_unalloc_dev(parm->num);    }    cipe_alloc_UNLOCK();    return e;#endif}/*** Device operation handlers ***/int cipe_dev_ioctl(struct NET_DEVICE *dev, struct ifreq *ifr, int cmd){    int e=-ENOTTY;#ifdef LINUX_21    if (!capable(CAP_NET_ADMIN))	return -EPERM;#define doioctl(nam,fun,str) {                                          \    struct str parm;                                                    \    dprintk(DEB_CALL, (KERN_INFO "%s: " nam "\n", dev->name));          \    if (copy_from_user((void*)&parm,(void*)ifr->ifr_data,               \                       sizeof(parm))) {                                 \        e=-EFAULT; goto out; }                                          \    if (parm.magic!=VERSION_MAGIC) {                                    \        printk(KERN_WARNING "%s: ciped version mismatch\n", dev->name); \        e=-EINVAL; goto out; }                                          \    if ((e=fun(dev, &parm))<0)                                          \        goto out;                                                       \

⌨️ 快捷键说明

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