📄 device.c
字号:
/* 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: linux-2.4.0-cipe-1.4.5.patch,v 1.6 2001/04/17 18:50:11 arjanv Exp $ */#include "cipe.h"#include "version.h"#include <stddef.h>#include <linux/if_arp.h>#include <linux/sched.h>#include <linux/init.h>#include <linux/config.h>#ifdef LINUX_21#include <asm/uaccess.h>#include <linux/rtnetlink.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;#ifdef NO_DYNDEVint cipe_maxdev = 4; /* changeable via insmod */#elseint cipe_maxdev = 100; /* changeable via insmod */#endif#ifdef DEBUGint cipe_debug = DEB_CALL; /* changeable via insmod */#endif/* clear all potentially sensitive info and stats */static void cipe_zero_c(struct cipe *c){ 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;}/* 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 CONFIG_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); parm->sockshost=c->sockshost; parm->socksport=c->socksport; parm->tmo_keyxchg=c->tmo_keyxchg/HZ; parm->tmo_keylife=c->tmo_keylife/HZ; parm->flags=c->flags; parm->cttl=c->cttl; return 0;}#endifstatic int cipe_setpar(struct NET_DEVICE *dev, struct siocsifcippar *parm){ DEVTOCIPE(dev,c,-ENODEV); if (parm->sockshost) c->sockshost=parm->sockshost; if (parm->socksport) c->socksport=parm->socksport; 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; 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); dprintk(DEB_KXC, (KERN_DEBUG "%s: setkey %d\n", dev->name, parm->which)); switch (parm->which) { case KEY_STATIC: ExpandUserKey(parm->thekey, c->key_e);#if 0 dprintk(DEB_CRYPT, (KERN_DEBUG "ExpandUserKey: %08x\n", *(__u32*)(c->key_e)));#endif InvertKey(c->key_e, c->key_d); c->flags|=CIPF_HAVE_KEY; break; case KEY_SEND: ExpandUserKey(parm->thekey, c->skey_e); c->timeskey=jiffies+c->tmo_keylife; c->cntskey=0; c->flags|=CIPF_HAVE_SKEY; break; case KEY_RECV: ExpandUserKey(parm->thekey, c->rkey_d); InvertKey(c->rkey_d, c->rkey_d); 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); memset(&(c->key_e), 0, sizeof(c->key_e)); memset(&(c->key_d), 0, sizeof(c->key_d)); break; case KEY_SEND+KEY_INVAL: c->flags&=~CIPF_HAVE_SKEY; memset(&(c->skey_e), 0, sizeof(c->skey_e)); c->timeskey=jiffies+c->tmo_keyxchg; break; case KEY_RECV+KEY_INVAL: c->flags&=~CIPF_HAVE_RKEY; memset(&(c->rkey_d), 0, sizeof(c->rkey_d)); c->timerkey=jiffies+c->tmo_keyxchg; break; default: return -EINVAL; } return 0;}static int cipe_alloc_dev(int n);static void cipe_unalloc_dev(int n);static int cipe_isowned(struct cipe *c){ struct task_struct *p; pid_t pid=c->owner; if (!pid) return 0; tasklist_LOCK(); p=current; do { if (p->pid==pid) { tasklist_UNLOCK(); return 1; } p=next_task(p); } while (p!=current); tasklist_UNLOCK(); return 0;}#define cipe_hasowner(n) cipe_isowned(&cipe_ctrls[(n)]->cipe)#ifdef LINUX_21/* In 2.1 the ioctl operations are run under lock. Beware of deadlocks. */#define cipe_alloc_LOCK() 0 /* nop */#define cipe_alloc_UNLOCK() /* nop */#elsestatic struct semaphore cipe_alloc_sem=MUTEX;#define cipe_alloc_LOCK() down_interruptible(&cipe_alloc_sem)#define cipe_alloc_UNLOCK() up(&cipe_alloc_sem)#endifstatic 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 || cipe_hasowner(n)) 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_hasowner(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=-EINVAL;#ifdef LINUX_21
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -