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

📄 ciped.c

📁 cipe 编程
💻 C
📖 第 1 页 / 共 2 页
字号:
/*   CIPE - encrypted IP over UDP tunneling   ciped.c - the user mode 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: ciped.c,v 1.63 2004/01/18 14:57:51 olaf81825 Exp $ */#ifndef CTLDIR#define CTLDIR "/etc/cipe"#endif#define _GNU_SOURCE#include <ctype.h>#include <errno.h>#include <fcntl.h>#include <netdb.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <syslog.h>#include <time.h>#include <unistd.h>#include <arpa/inet.h>#include <net/if_arp.h>#include <sys/ioctl.h>#include <sys/mman.h>#include <sys/socket.h>#include <sys/time.h>#include <sys/wait.h>#include <values.h>#include <linux/if_ether.h>#include "ciped.h"#include "ioctl.h"#include "cipelib.h"#ifndef LOGFAC#define LOGFAC LOG_DAEMON#endifstatic const char daemon_version[]=VERSION;void usage(const char *p){    fprintf(stderr, "usage: %s [ -i | -s fd ] [ -o file ] [option...]\n", p);    exit(1);}/* Statistics */struct kstat {    int rreq, req, ind, indb, ack, ackb, bogus;} ks = { 0, 0, 0, 0, 0, 0, 0 };char device[16] = "";int devnum = -1;int inetd = 0;int usesock = -1;typedef unsigned long crc;#define CRCFORM "%08lX"/*** Locked memory structure, contains everything to do with keys */#define SECPOOL 256struct lockmem {    char pool[SECPOOL];                         /* for strings */    int poolptr;    struct siocsifcipkey sio;                   /* setkey ioctl */    unsigned char kxbuf[KEYXCHGBLKMIN+2];       /* KX comm buff */    crc scrc;    unsigned char skey[userKeySize];            /* holds current KX key */} *LM;char *secstrdup(const char *p){    char *q=LM->pool+LM->poolptr;    int n=strlen(p)+1;    if (LM->poolptr+n>SECPOOL)        return NULL;    strcpy(q, p);    LM->poolptr+=n;    return q;}#ifdef HAVE_MLOCKvoid xmlock(void *addr, size_t len){    if (mlock(addr, len)<0)        Log(LOG_WARNING, "mlock: %m"); /* not fatal */}void xmunlock(void *addr, size_t len){    if (munlock(addr, len)<0)        Log(LOG_WARNING, "munlock: %m"); /* not fatal */}#else#define xmlock(a,l)#define xmunlock(a,l)#endif/* Configuration info structure */struct confinfo {    char cmd;    char fill[3];    char magic[4];    char protocol, crypto, swmaj, swmin;    char keyright;};struct confinfo myconfinfo = {    CT_CONF, "\0",    "CIPE", ProtocolVersion, CRNAMEC,    VERSION_MAJ, VERSION_MIN,#ifdef BUG_COMPATIBLE    0#else    1#endif};/*** Option parser ***//* Set an option */int setopt(const char *n, char *v, int r){    struct options *o=opts;    static const char * const protos[]={NULL, "udp", "tcp"};    while (o->oname) {	if (!strcmp(o->oname, n)) {	    if ((!v) && (o->otyp!=Tbool)) {		fprintf(stderr, "missing value for %s\n", n); return -1;	    }	    switch(o->otyp) {	    case Tbool:		o->ov.ovint=1;		break;	    case Tint:		o->ov.ovint=atoi(v);		break;	    case Tstr:		if (!(o->ov.ovstr=strdup(v))) {		    fprintf(stderr, "setopt: out of memory\n"); return -1;		}		break;	    case Taddr:	    case Tuaddr:	    case Ttaddr:		if (!(o->ov.ovsaddr=malloc(sizeof(*o->ov.ovsaddr)))) {		    fprintf(stderr, "setopt: out of memory\n"); return -1;		}		if (getaddr(v, o->ov.ovsaddr, protos[o->otyp-Taddr])<0) {		    return -1;		}		break;            case Tsecret:                if (r) {                    fprintf(stderr, "Refused to set key from command line!\n");                    return -1;                }		if (!(o->ov.ovstr=secstrdup(v))) {		    fprintf(stderr, "setopt: out of secret-pool memory\n");                    return -1;		}		break;	    default:		fprintf(stderr, "internal error: %d\n", __LINE__); return -1;	    }	    return 0;	}	++o;    }    fprintf(stderr, "unknown option: %s\n", n);    return -1;}/* Set options from command line */void setopt_cmdline(int argc, char *argv[]){    int i;    char *q;    for (i=0; i<argc; ++i) {	if ((q=strchr(argv[i], '=')))	    *q++='\0';	(void) setopt(argv[i], q, 1);    }}/* Set options from file, report file not found if (v) */int setopt_file(const char *n, int v){    FILE *f;    char b[128];    char *p, *q;    if (secchk(n, 0077, 0022, v))        return -1;    if (!(f=fopen(n, "r"))) {	if (v)	    perror("setopt_file: open");	return -1;    }    xmlock(b, sizeof(b));    /* FIXME: perhaps fgets could allocate unlocked memory */    while (fgets(b, sizeof(b), f)) {        for (p=b; isspace(*p); ++p);        if ((!*p) || strchr("#;:!", *p))            continue;        parseopt(b, &p, &q);        (void) setopt(p, q, 0);        memset(b, 0, sizeof(b));    }    xmunlock(b, sizeof(b));    fclose(f);    return 0;}/* Make a "name=value" string of option */char *optstr(struct options *o){    static char buf[1024];    switch(o->otyp) {    case Tbool:        snprintf(buf, sizeof(buf), "%s=%s", o->oname,                 o->ov.ovint?"yes":"no");        break;    case Tint:        snprintf(buf, sizeof(buf), "%s=%d", o->oname, o->ov.ovint);        break;    case Tstr:        snprintf(buf, sizeof(buf), "%s=%s", o->oname,                 o->ov.ovstr?o->ov.ovstr:"(none)");        break;    case Tsecret:        snprintf(buf, sizeof(buf), "%s=%s", o->oname,                 o->ov.ovstr?"(secret)":"(none)");        break;    case Taddr:        if (o->ov.ovsaddr)            snprintf(buf, sizeof(buf), "%s=%s", o->oname,                     inet_ntoa(o->ov.ovsaddr->sin_addr));        else            snprintf(buf, sizeof(buf), "%s=", o->oname);        break;    case Tuaddr:    case Ttaddr:        if (o->ov.ovsaddr)            snprintf(buf, sizeof(buf), "%s=%s:%d", o->oname,                     inet_ntoa(o->ov.ovsaddr->sin_addr),                     ntohs(o->ov.ovsaddr->sin_port));        else            snprintf(buf, sizeof(buf), "%s=", o->oname);        break;    default: fprintf(stderr, "internal error: %d\n", __LINE__);    }    return buf;}/* Print out all options */void dumpopt(void){    struct options *o;    for (o=opts; o->oname; ++o)        printf("%s\n", optstr(o));}/*** Logging ***//* missing option */void argmiss(const char *s){    Log(LOG_ERR, "missing argument: %s", s);}/* print if debugging */#define dprintf(f)    if(OI(debug)){printf f;}/*** Initialize, open and attach the CIPE device. ***/int opendev(void){    int f, i, iffl;#ifndef NO_DYNDEV    struct siocsifcipall d;#endif    struct siocsifcippar p;    struct siocsifcipatt a;    struct ifreq r;#define amiss(s) do{ argmiss(s); goto error; }while(0)#define err(s)   do{ Log(LOG_ERR, s); goto error; }while(0)    /* Initialize, bind and connect the socket */    if (inetd) {        f=0;    } else if (usesock>=0) {#if 0        /* this seems to be unnecessary */	struct sockaddr_in sa;	memset(&sa, 0, sizeof(sa));	sa.sin_family=AF_UNSPEC;	f=usesock;	if (connect(f, (struct sockaddr *)&sa, sizeof(sa))<0) {	    err("opendev: disconnect: %m");	}#else	f=usesock;#endif    } else {        if ((f=socket(AF_INET, SOCK_DGRAM, 0))<0) {            Log(LOG_ERR, "opendev: socket: %m");            return -1;        }    }    i=65536; /* we need much to receive fast */    if (setsockopt(f, SOL_SOCKET, SO_RCVBUF, &i, sizeof(i)))	/* not fatal */	Log(LOG_NOTICE, "opendev: setsockopt: %m");    if (!OA(me)) {	if (!(OA(me)=malloc(sizeof(*OA(me)))))	    err("opendev: malloc: %m");	OA(me)->sin_family=AF_INET;	OAaddr(me).s_addr=INADDR_ANY;	OAport(me)=0;    }    if (!inetd) {	if (usesock<0) {	    if (bind(f, (struct sockaddr *)OA(me), sizeof(*OA(me)))<0)		err("opendev: bind: %m");	}        if (OA(peer)) {            if (connect(f, (struct sockaddr *)OA(peer), sizeof(*OA(peer)))<0)                err("opendev: connect: %m");        } else            amiss("peer");    }    i=sizeof(*OA(me));    if (getsockname(f, (struct sockaddr *)OA(me), &i)<0)	/* not fatal */	Log(LOG_NOTICE, "opendev: getsockname: %m");#ifdef NO_DYNDEV    if (!OS(device))        amiss("device");    if (strlen(OS(device)) > 15)        err("opendev: device name too long.");    strcpy(device, OS(device));#else    /* Allocate the device name */    if (OS(device)) {        char *x=OS(device)+strlen(OS(device))-1;        while (x>=OS(device) && isdigit(*x))            --x;        d.num=atoi(++x);    } else {        d.num=-1;    }    if (ioctl_alloc(f, DEVNAME "0", &d)<0)        err("opendev: alloc: %m");    strcpy(device, d.name);    devnum=d.num;    dprintf(("Using %s index %d\n", device, devnum));#endif    /* Set the CIPE operation parameters */    memset(&p, 0, sizeof(p));    if (OA(socks))	p.socks=*OA(socks);    p.tmo_keyxchg=OI(tokxc);    p.tmo_keylife=OI(tokey);    p.flags=CIPF_MAY_STKEY;    if (OI(nokey))        p.flags|=CIPF_MAY_CLEAR;    if (OI(dynip))        p.flags|=CIPF_MAY_DYNIP;    if (OI(checksum))	p.flags|=CIPF_DO_CSUM;    if (OI(ignoredf))    	p.flags|=CIPF_IGNORE_DF;    if (OI(forcemtu))    	p.flags|=CIPF_FORCE_MTU;    p.cttl=OI(cttl);    if (OS(cipher)) {        strncpy(p.cname, OS(cipher), sizeof(p.cname)-5);    } else {        strcpy(p.cname, "blowfish-internal");    }    myconfinfo.crypto=p.cname[0];    if (ioctl_setpar(f, device, &p)<0)	err("opendev: setpar: %m");    /* Set the key */    if (OS(key)) {	unsigned char *c=OS(key);	unsigned char *x=(unsigned char *)&LM->sio.thekey;	LM->sio.which=KEY_STATIC;#ifdef BUG_COMPATIBLE	/* BROKEN attempt at a primitive hex decoder */	i=0;	while(*c) {	    x[i]=((*c)<<4)&0xF0;	    *c++='\0'; /* clear after use */	    if (!*c) break;	    x[i++]|=(*c)&0x0F;	    *c++='\0';	    if (i>=userKeySize) break;	}#else	gethex(c, x, userKeySize);	memset(c, 0, strlen(c)); /* clear after use */#endif        LM->sio.keylen=userKeySize;	if (ioctl_setkey(f, device, &LM->sio)<0)	    err("opendev: setkey: %m");    } else {	if (!OI(nokey))	    amiss("key");    }    /* Perform attach */    a.fd=f;    if (ioctl_attach(f, device, &a)<0)	err("opendev: attach: %m");    if (OI(ifconfig))	return f;    /* Perform ifconfig */    strcpy(r.ifr_name, device);    if (ioctl(f, SIOCGIFFLAGS, &r)<0)	err("opendev: SIOCGIFFLAGS: %m");    iffl=r.ifr_flags;    if (OA(ipaddr)) {	memcpy(&r.ifr_addr, OA(ipaddr), sizeof(*OA(ipaddr)));	if (ioctl(f, SIOCSIFADDR, &r)<0)	    err("opendev: SIOCSIFADDR: %m");    } else	amiss("ipaddr");    if (OA(ptpaddr)) {	memcpy(&r.ifr_dstaddr, OA(ptpaddr), sizeof(*OA(ptpaddr)));	if (ioctl(f, SIOCSIFDSTADDR, &r)<0)	    err("opendev: SIOCSIFDSTADDR: %m");	iffl|=IFF_POINTOPOINT;    }    if (OA(mask)) {	memcpy(&r.ifr_netmask, OA(mask), sizeof(*OA(mask)));	if (ioctl(f, SIOCSIFNETMASK, &r)<0)	    err("opendev: SIOCSIFNETMASK: %m");    }    if (OA(bcast)) {	memcpy(&r.ifr_broadaddr, OA(bcast), sizeof(*OA(bcast)));	if (ioctl(f, SIOCSIFBRDADDR, &r)<0)	    err("opendev: SIOCSIFBRDADDR: %m");    }    if (OI(mtu)) {	r.ifr_mtu=OI(mtu);	if (ioctl(f, SIOCSIFMTU, &r)<0)	    err("opendev: SIOCSIFMTU: %m");    }    if (OI(metric)) {	r.ifr_metric=OI(metric);	if (ioctl(f, SIOCSIFMETRIC, &r)<0)	    err("opendev: SIOCSIFMETRIC: %m");    }    if (OS(hwaddr)) {	struct sockaddr sa;	sa.sa_family=ARPHRD_ETHER;	gethex(OS(hwaddr), (unsigned char *)&sa.sa_data, ETH_ALEN);	memcpy(&r.ifr_hwaddr, &sa, sizeof(sa));	if (ioctl(f, SIOCSIFHWADDR, &r)<0)	    err("opendev: SIOCSIFHWADDR: %m");    }    iffl|=IFF_UP|IFF_RUNNING;    r.ifr_flags=iffl;    if (ioctl(f, SIOCSIFFLAGS, &r)<0)	err("opendev: SIOCSIFFLAGS: %m");    return f; error:    close(f);    return -1;#undef amiss#undef err}/* Close the device. */void closedev(int f){    struct ifreq r;    strcpy(r.ifr_name, device);    if (ioctl(f, SIOCGIFFLAGS, &r)<0)	Log(LOG_ERR, "closedev: SIOCGIFFLAGS: %m");    r.ifr_flags&=~(IFF_UP|IFF_RUNNING);    if (ioctl(f, SIOCSIFFLAGS, &r)<0)	Log(LOG_ERR, "closedev: SIOCSIFFLAGS: %m");    close(f);#ifndef NO_DYNDEV    if (devnum>0) {        struct siocsifcipall x;        if ((f=socket(AF_INET, SOCK_DGRAM, 0))<0) {            Log(LOG_ERR, "closedev: socket: %m");            return;        }        x.num=devnum;        if (ioctl_unalloc(f, device, &x)<0)            Log(LOG_ERR, "closedev: unalloc: %m");        close(f);    }#endif}/* Fetch the device statistics. */char *getstats(void){    static char b[256];    char *p, *q;    FILE *f=fopen("/proc/net/dev", "r");    if (!f)        return NULL;    while (fgets(b, sizeof(b), f)) {        for (p=b; *p==' '; ++p);        for (q=p; *q && *q!=':'; ++q);        if (!*q)            continue;        *q++='\0';        if (strcmp(p, device))            continue;        fclose(f);        return(q);    }    fclose(f);    return NULL;}/*** Open a SOCKS5 connection ***/int opensocks(void) {    struct sockaddr_in a;    int fd=socks5_open(OA(socks));    if (fd>=0) {	/* 3rd par of socks5_cmd is in: my address, out: relayer */	a=*OA(me);	fd=socks5_cmd(fd, S5_UDP, &a);	/* Swap peer and socks addresses.	   Use the SOCKS relayer as "peer" and the real peer as "socks"

⌨️ 快捷键说明

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