void set_tap(void) { skfd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); if (skfd < 0) perrx("socket PF_INET"); skfd6 = socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP); if (skfd6 < 0) perrx("socket PF_INET6"); }
/* Lock Init */ static _inline void arp_cache_lock_init(void) { #ifndef STATIC_MUTEX /* It is evil to init pthread mutex dynamically X< */ pthread_mutexattr_t attr; if (pthread_mutexattr_init(&attr) != 0) perrx("pthread_mutexattr_init"); if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL) != 0) perrx("pthread_mutexattr_settype"); if (pthread_mutex_init(&arp_cache_mutex, &attr) != 0) perrx("pthread_mutex_init"); #endif }
void *xzalloc(size_t size) { void *p = calloc(1,size); if(!p) perrx("calloc"); return p; }
void getname_tap(int tapfd, unsigned char *name) { struct ifreq ifr = {}; if (ioctl(tapfd, TUNGETIFF, (void *)&ifr) < 0) perrx("ioctl SIOCGIFHWADDR"); strcpy((char *)name, ifr.ifr_name); dbg("net device: %s", name); }
void *xmalloc(size_t size) { void *p = malloc(size); if(!p) perrx("xmalloc"); return p; }
void gethwaddr_tap(int tapfd, unsigned char *ha) { struct ifreq ifr; memset(&ifr, 0x0, sizeof(ifr)); /* get net order hardware address */ if (ioctl(tapfd, SIOCGIFHWADDR, (void *)&ifr) < 0) perrx("ioctl SIOCGIFHWADDR"); hwacpy(ha, ifr.ifr_hwaddr.sa_data); dbg("mac addr: %02x:%02x:%02x:%02x:%02x:%02x", ha[0], ha[1], ha[2], ha[3], ha[4], ha[5]); }
void setflags_tap(unsigned char *name, unsigned short flags, int set) { struct ifreq ifr = {}; strcpy(ifr.ifr_name, (char *)name); /* get original flags */ if (ioctl(skfd, SIOCGIFFLAGS, (void *)&ifr) < 0) { close(skfd); perrx("socket SIOCGIFFLAGS"); } /* set new flags */ if (set) ifr.ifr_flags |= flags; else ifr.ifr_flags &= ~flags & 0xffff; if (ioctl(skfd, SIOCSIFFLAGS, (void *)&ifr) < 0) { close(skfd); perrx("socket SIOCGIFFLAGS"); } }
void getmtu_tap(unsigned char *name, int *mtu) { struct ifreq ifr = {}; strcpy(ifr.ifr_name, (char *)name); /* get net order hardware address */ if (ioctl(skfd6, SIOCGIFMTU, (void *)&ifr) < 0) { close(skfd6); perrx("ioctl SIOCGIFHWADDR"); } *mtu = ifr.ifr_mtu; dbg("mtu: %d", ifr.ifr_mtu); }
void getipaddr_tap(unsigned char *name, unsigned int *ipaddr) { struct ifreq ifr = {}; struct sockaddr_in *saddr; strcpy(ifr.ifr_name, (char *)name); if (ioctl(skfd, SIOCGIFADDR, (void *)&ifr) < 0) { close(skfd); perrx("socket SIOCGIFADDR"); } saddr = (struct sockaddr_in *)&ifr.ifr_addr; *ipaddr = saddr->sin_addr.s_addr; dbg("get IPaddr: "IPFMT, ipfmt(*ipaddr)); }
void setnetmask_tap(unsigned char *name, unsigned int netmask) { struct ifreq ifr = {}; struct sockaddr_in *saddr; strcpy(ifr.ifr_name, (char *)name); saddr = (struct sockaddr_in *)&ifr.ifr_netmask; saddr->sin_family = AF_INET; saddr->sin_addr.s_addr = netmask; if (ioctl(skfd, SIOCSIFNETMASK, (void *)&ifr) < 0) { close(skfd); perrx("socket SIOCSIFNETMASK"); } dbg("set Netmask: "IPFMT, ipfmt(netmask)); }
void setipaddr_tap(unsigned char *name, unsigned int ipaddr) { struct ifreq ifr = {}; struct sockaddr_in *saddr; strcpy(ifr.ifr_name, (char *)name); saddr = (struct sockaddr_in *)&ifr.ifr_addr; saddr->sin_family = AF_INET; saddr->sin_addr.s_addr = ipaddr; if (ioctl(skfd, SIOCSIFADDR, (void *)&ifr) < 0) { close(skfd); perrx("socket SIOCSIFADDR"); } dbg("set IPaddr: "IPFMT, ipfmt(ipaddr)); }
static int veth_dev_init(struct netdev *dev) { /* init tap: out network nic */ if (tap_dev_init() < 0) perrx("Cannot init tap device"); /* init veth: information for our netstack */ dev->net_mtu = tap->dev.net_mtu; dev->net_ipaddr = FAKE_IPADDR; dev->net_mask = FAKE_NETMASK; hwacpy(dev->net_hwaddr, FAKE_HWADDR); dbg("%s ip address: " IPFMT, dev->net_name, ipfmt(dev->net_ipaddr)); dbg("%s hw address: " MACFMT, dev->net_name, macfmt(dev->net_hwaddr)); /* net stats have been zero */ return 0; }
void veth_poll(void) { struct pollfd pfd = {}; int ret; while (1) { pfd.fd = tap->fd; pfd.events = POLLIN; pfd.revents = 0; /* one event, infinite time */ ret = poll(&pfd, 1, -1); if (ret <= 0) perrx("poll /dev/net/tun"); /* get a packet and handle it */ veth_rx(); } }
/* cr_load_certs : loads private key and certificates from files * if cert_file and key_file are NULL , the function will generate * a dynamic certificate and private key */ void cr_load_certs(SSL_CTX *ssl,u_char *cert_file,u_char *key_file) { X509 *cert = NULL; EVP_PKEY *pkey = NULL; if(cert_file == NULL || key_file == NULL) { /* generate a public certificate and a private key */ cr_make_cert(&cert,&pkey,2048,0,365); SSL_CTX_use_certificate(ssl, cert); SSL_CTX_use_PrivateKey(ssl, pkey); #ifdef CR_MK_CERT RSA_print_fp(stdout,pkey->pkey.rsa,0); X509_print_fp(stdout,cert); PEM_write_PrivateKey(stdout,pkey,NULL,NULL,0,NULL, NULL); PEM_write_X509(stdout,cert); #endif } else { if (SSL_CTX_use_certificate_file(ssl, (const char*)cert_file, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); exit(3); } if (SSL_CTX_use_RSAPrivateKey_file(ssl, (const char*)key_file, SSL_FILETYPE_PEM) <= 0) { ERR_print_errors_fp(stderr); exit(4); } } if (!SSL_CTX_check_private_key(ssl)) { perrx("Private key does not match the certificate public key\n"); exit(5); } }
int main(int argc,char **argv) { struct netdev *nd; int ret; struct socket *sock; if(argc != 4) banner(argv[0]); ret = -1; nd = xzalloc(sizeof(struct netdev)); if(!nd) { perrx("Couldn't create netdev structure"); goto bad; } sock = socket_alloc(); if(sock == NULL) goto bad; nd->nd_ipaddr = inet_addr(argv[3]); nd->nd_ops = &nd_ops; if(cl_sock_connect(&sock,argv[1],atoi(argv[2])) < 0) goto bad; nd->nd_ipaddr = inet_addr(argv[3]); nd->nd_ops = &nd_ops; nd->sk = sock; if(cl_setup_promisc(nd) < 0) goto bad; return 0; bad: if(sock) free(sock); return ret; }
static void run_file(const char *filename, uid_t uid, gid_t gid) { /* Run a file by spawning off a process which redirects I/O, * spawns a subshell, then waits for it to complete and sends * mail to the user. */ pid_t pid; int fd_out, fd_in; int queue; char mailbuf[LOGNAMESIZE + 1], fmt[49]; char *mailname = NULL; FILE *stream; int send_mail = 0; struct stat buf, lbuf; off_t size; struct passwd *pentry; int fflags; uid_t nuid; gid_t ngid; #ifdef PAM pam_handle_t *pamh = NULL; int pam_err; struct pam_conv pamc = { .conv = openpam_nullconv, .appdata_ptr = NULL }; #endif PRIV_START if (chmod(filename, S_IRUSR) != 0) { perr("cannot change file permissions"); } PRIV_END pid = fork(); if (pid == -1) perr("cannot fork"); else if (pid != 0) return; /* Let's see who we mail to. Hopefully, we can read it from * the command file; if not, send it to the owner, or, failing that, * to root. */ pentry = getpwuid(uid); if (pentry == NULL) perrx("Userid %lu not found - aborting job %s", (unsigned long) uid, filename); #ifdef PAM PRIV_START pam_err = pam_start(atrun, pentry->pw_name, &pamc, &pamh); if (pam_err != PAM_SUCCESS) perrx("cannot start PAM: %s", pam_strerror(pamh, pam_err)); pam_err = pam_acct_mgmt(pamh, PAM_SILENT); /* Expired password shouldn't prevent the job from running. */ if (pam_err != PAM_SUCCESS && pam_err != PAM_NEW_AUTHTOK_REQD) perrx("Account %s (userid %lu) unavailable for job %s: %s", pentry->pw_name, (unsigned long)uid, filename, pam_strerror(pamh, pam_err)); pam_end(pamh, pam_err); PRIV_END #endif /* PAM */ PRIV_START stream=fopen(filename, "r"); PRIV_END if (stream == NULL) perr("cannot open input file"); if ((fd_in = dup(fileno(stream))) <0) perr("error duplicating input file descriptor"); if (fstat(fd_in, &buf) == -1) perr("error in fstat of input file descriptor"); if (lstat(filename, &lbuf) == -1) perr("error in fstat of input file"); if (S_ISLNK(lbuf.st_mode)) perrx("Symbolic link encountered in job %s - aborting", filename); if ((lbuf.st_dev != buf.st_dev) || (lbuf.st_ino != buf.st_ino) || (lbuf.st_uid != buf.st_uid) || (lbuf.st_gid != buf.st_gid) || (lbuf.st_size!=buf.st_size)) perrx("Somebody changed files from under us for job %s - aborting", filename); if (buf.st_nlink > 1) perrx("Somebody is trying to run a linked script for job %s", filename); if ((fflags = fcntl(fd_in, F_GETFD)) <0) perr("error in fcntl"); fcntl(fd_in, F_SETFD, fflags & ~FD_CLOEXEC); snprintf(fmt, sizeof(fmt), "#!/bin/sh\n# atrun uid=%%ld gid=%%ld\n# mail %%%ds %%d", LOGNAMESIZE); if (fscanf(stream, fmt, &nuid, &ngid, mailbuf, &send_mail) != 4) perrx("File %s is in wrong format - aborting", filename); if (mailbuf[0] == '-') perrx("Illegal mail name %s in %s", mailbuf, filename); mailname = mailbuf; if (nuid != uid) perrx("Job %s - userid %u does not match file uid %u", filename, nuid, uid); if (ngid != gid) perrx("Job %s - groupid %u does not match file gid %u", filename, ngid, gid); fclose(stream); if (chdir(ATSPOOL_DIR) < 0) perr("cannot chdir to %s", ATSPOOL_DIR); /* Create a file to hold the output of the job we are about to run. * Write the mail header. */ if((fd_out=open(filename, O_WRONLY | O_CREAT | O_EXCL, S_IWUSR | S_IRUSR)) < 0) perr("cannot create output file"); write_string(fd_out, "Subject: Output from your job "); write_string(fd_out, filename); write_string(fd_out, "\n\n"); fstat(fd_out, &buf); size = buf.st_size; close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); pid = fork(); if (pid < 0) perr("error in fork"); else if (pid == 0) { char *nul = NULL; char **nenvp = &nul; /* Set up things for the child; we want standard input from the input file, * and standard output and error sent to our output file. */ if (lseek(fd_in, (off_t) 0, SEEK_SET) < 0) perr("error in lseek"); if (dup(fd_in) != STDIN_FILENO) perr("error in I/O redirection"); if (dup(fd_out) != STDOUT_FILENO) perr("error in I/O redirection"); if (dup(fd_out) != STDERR_FILENO) perr("error in I/O redirection"); close(fd_in); close(fd_out); if (chdir(ATJOB_DIR) < 0) perr("cannot chdir to %s", ATJOB_DIR); queue = *filename; PRIV_START nice(tolower(queue) - 'a'); #ifdef LOGIN_CAP /* * For simplicity and safety, set all aspects of the user context * except for a selected subset: Don't set priority, which was * set based on the queue file name according to the tradition. * Don't bother to set environment, including path vars, either * because it will be discarded anyway. Although the job file * should set umask, preset it here just in case. */ if (setusercontext(NULL, pentry, uid, LOGIN_SETALL & ~(LOGIN_SETPRIORITY | LOGIN_SETPATH | LOGIN_SETENV)) != 0) exit(EXIT_FAILURE); /* setusercontext() logged the error */ #else /* LOGIN_CAP */ if (initgroups(pentry->pw_name,pentry->pw_gid)) perr("cannot init group access list"); if (setgid(gid) < 0 || setegid(pentry->pw_gid) < 0) perr("cannot change group"); if (setlogin(pentry->pw_name)) perr("cannot set login name"); if (setuid(uid) < 0 || seteuid(uid) < 0) perr("cannot set user id"); #endif /* LOGIN_CAP */ if (chdir(pentry->pw_dir)) chdir("/"); if(execle("/bin/sh","sh",NULL, nenvp) != 0) perr("exec failed for /bin/sh"); PRIV_END }
/* cr_make_cert generates a server public/private keys * cert : X509 instance * pkey : private key instance * bits : RSA key length * serial : serial number * days : how many days the certificate is valid */ int cr_make_cert(X509 **cert,EVP_PKEY **pkey,int bits,int serial,int days) { X509 *x; EVP_PKEY *pk; RSA *rsa; X509_NAME *name = NULL; if((pkey == NULL) || (*pkey == NULL)) { pk = EVP_PKEY_new(); if(pk == NULL) { perrx("EVP_PKEY_new() failed\n"); return -1; } } else pk = *pkey; if((cert == NULL) || (*cert == NULL)) { x = X509_new(); if ((x == NULL)) { perrx("X509_new() failed\n"); return -1; } }else x= *cert; /* generate RSA key */ rsa = RSA_generate_key(bits,RSA_F4,NULL,NULL); if(!EVP_PKEY_assign_RSA(pk, rsa)) { perrx("X509_new() failed\n"); return -1; } rsa = NULL; X509_set_version(x,2); ASN1_INTEGER_set(X509_get_serialNumber(x),serial); X509_gmtime_adj(X509_get_notBefore(x),0); X509_gmtime_adj(X509_get_notAfter(x),(long)60*60*24*days); X509_set_pubkey(x,pk); name=X509_get_subject_name(x); X509_NAME_add_entry_by_txt(name,"C", MBSTRING_ASC, (const unsigned char *)"UK", -1, -1, 0); X509_NAME_add_entry_by_txt(name,"CN", MBSTRING_ASC, (const unsigned char*)"VPNPivot", -1, -1, 0); /* Its self signed so set the issuer name to be the same as the * subject. */ X509_set_issuer_name(x, name); if(!X509_sign(x, pk, EVP_md5())) // secured more with sha1? md5/sha1? sha256? abort(); *cert = x; *pkey = pk; return 1; }
static int cl_dev_xmit(struct netdev *nd,struct socket *sk) { int ret; struct mbuf mb_d,mb; int maxfd,flags=0; fd_set in; unsigned int nbytes; mb_d.mb_data = xmalloc(IP_MAXRECV); mb_d.mb_len = 0; if(mb_d.mb_data == NULL) goto bad; mb.mb_data = xmalloc(2000*sizeof(char)); mb.mb_len = 0; if(mb.mb_data == NULL) goto bad; FD_ZERO(&in); maxfd = (nd->sk->sk_fd > nd->nd_fd)? nd->sk->sk_fd:nd->nd_fd; while(1) { FD_SET(nd->nd_fd,&in); FD_SET(nd->sk->sk_fd,&in); ret = select(maxfd+1,&in,NULL,NULL,NULL); if(ret == -1 || errno == EINTR) continue; /* we got something from device */ if(FD_ISSET(nd->nd_fd,&in)) { mb_d.mb_len = recvfrom(nd->nd_fd,mb_d.mb_data,IP_MAXPACKET,0,NULL,NULL); if(mb_d.mb_len == -1) { perrx("etn_cli_recv:recv"); goto bad; } #ifdef USE_SSL ret = SSL_write(nd->sk->sk_ssl,mb_d.mb_data,mb_d.mb_len); if(ret < 0) { perrx("etn_cli_recv:send"); goto bad; } #else ret = write(nd->sk->sk_fd,mb_d.mb_data,mb_d.mb_len); if(ret == -1) { perrx("etn_cli_recv:send"); goto bad; } #endif } /* we got something from socket */ if(FD_ISSET(nd->sk->sk_fd,&in)) { /* printf("lol\n"); mb.mb_len = read(nd->sk->sk_fd,mb.mb_data,4096); printf("READ : %d\n",mb.mb_len); if(mb.mb_len == -1) { perrx("recv_sock_handler:recv"); goto bad; } */ if(read_packet(nd->sk,&mb,1514) <= 0) { perrx("read"); perrx("read_packet():"); exit(0); goto bad; } printf("READ : %d\n",mb.mb_len); nbytes = sendto(nd->nd_fd,mb.mb_data,mb.mb_len,0,NULL,0); if(nbytes == -1) { perrx("recv_sock_handler:sendto"); goto bad; } } } bad: if(mb_d.mb_data) free(mb.mb_data); exit(0); return -1; }
int cl_sock_connect(struct socket **sock,char *server,u_short port) { struct socket *sk; int fd,ret; struct linger so_linger; struct hostent *h; char **pptr; char ip[15]={0}; struct sockaddr_in cli; sk = *sock; fd = socket(AF_INET,SOCK_STREAM,0); if(fd < 0) { printf("socket error \n"); return -1; } #ifdef USE_SSL printf("use ssl\n"); sk->sk_ctx = cr_ssl_context_cli(); SSL_CTX_set_options(sk->sk_ctx, SSL_OP_NO_SSLv2); sk->sk_ssl = SSL_new(sk->sk_ctx); #endif /* set linger socket option */ so_linger.l_onoff = 1; so_linger.l_linger = 0; /* resolve name */ h = gethostbyname(server); if(!h) { perrx("The hostname couln't be resolved\n"); return -1; } pptr = h->h_addr_list; for(;*pptr;pptr++) { inet_ntop(h->h_addrtype,*pptr,ip,sizeof(ip)); break; } memset(&cli,0,sizeof(struct sockaddr_in)); sk->scli.sin_port = htons(port); sk->scli.sin_family = AF_INET; sk->scli.sin_addr.s_addr = inet_addr(ip); /* fill socket buffer */ sk->sport = port; sk->ipaddr = htonl(sk->sk_cli.sin_addr.s_addr); ret = connect(fd,(const struct sockaddr*)&sk->sk_cli,sizeof(struct sockaddr)); if(ret == -1) { perrx("cl_sock_connect() failed"); return -1; } sk->sk_fd = fd; #ifdef USE_SSL int r; r = cr_ssl_connect(sk); #endif return 0; }
int main(int argc,char **argv) { int opt,long_opt_index = 0,ret; struct netdev *vdev,dev; struct socket sk; u_char *ifconf; struct linger so_linger; u_int mtu=0; memset(&dev,0,sizeof(struct netdev)); memset(&sk,0,sizeof(struct socket)); ifconf = NULL; vdev = &dev; vdev->nd_ops = &nd_ops; vdev->sk = &sk; while( (opt =getopt_long(argc,argv,"hi:I:p:u:vm:H:K:d",long_opt,&long_opt_index)) != -1 ) { switch(opt) { case 'h': banner(argv[0]); break; case 'i': memcpy(&dev.nd_name,optarg,IFNAMSIZ-1); break; case 'I': ifconf = (u_char*)strdup(optarg); has_ifconf |=1; break; case 'p': sk.sk_port = atoi(optarg); break; case 'u': dev.nd_owner = (u_int8_t*)strdup(optarg); break; case 'v': verbose |= 1; break; case 'm': mtu = atoi(optarg); break; case 'K': shr_key = (unsigned char*)strdup(optarg); break; case 'H': hwaddr = (u_char *)strdup(optarg); break; case 'd': daemonize |=1; break; default: banner(argv[0]); break; } } /* device name is not required , the kernel will give us a random name */ dev.nd_flags = IFF_TAP | IFF_NO_PI; if(daemonize) if(daemon(0,0) == -1) { perrx("main():daemon()"); return -1; } if(!has_ifconf ) { fprintf(stderr,"[!] Device configuration is not set \n"); } else parse_conf((char*)ifconf,&dev); if (!sk.sk_port) sk.sk_port = DEFAULT_PORT; if(!mtu || mtu < 0 || mtu > 4096) vdev->nd_mtu = MTU; else vdev->nd_mtu = mtu; if(shr_key == NULL) { printf("[-] Shared key is not set\n"); return -1; } sk.sk_fd = socket(AF_INET,SOCK_STREAM,0); if(sk.sk_fd < 0) { perror("main():socket()"); return -1; } /* set linger socket option */ so_linger.l_onoff = 1; so_linger.l_linger = 0; ret = setsockopt(sk.sk_fd,SOL_SOCKET,SO_LINGER,&so_linger,sizeof(struct linger)); if(ret == -1) { perror("main:setsockopt(SO_LINGER)"); close(sk.sk_fd); return ret; } /* let's create a virtual device interface */ if(vdev->nd_ops->init(&dev)) return -1; int yes = 1; struct socket *sk_cli; sk.sk_serv.sin_family = AF_INET; sk.sk_serv.sin_port = htons(sk.sk_port); sk.sk_serv.sin_addr.s_addr = htonl(INADDR_ANY); /* enable socket address re-use */ ret = setsockopt(sk.sk_fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)); if(ret == -1) { perror("main:setsockopt(SO_REUSEADDR)"); close(sk.sk_fd); return ret; } ret = bind(sk.sk_fd,(struct sockaddr*)&sk.sk_serv,sizeof(struct sockaddr_in)); if(ret == -1) { perror("main:bind()"); close(sk.sk_fd); return ret; } ret = listen(sk.sk_fd,4); if(ret == -1) { perror("main:listen()"); return -1; } if(verbose) printf("[+] Listening on port : %d\n",sk.sk_port); for(;;) { sk_cli =sock_accept(&dev); if(!sk_cli) return -1; vdev->nd_ops->xmit(vdev,sk_cli); } vdev->nd_ops->exit(vdev); return 0; }
static int dev_xmit(struct netdev* dev,struct socket *sk) { fd_set in; int ret,maxfd; struct mbuf mb; struct rc4_context ctx; rc4_prepare_shared_key(&ctx,shr_key); memset(&mb,0,sizeof(struct mbuf)); mb.mb_data = (u_int8_t*)malloc(dev->nd_mtu * sizeof(u_int8_t)); if(!mb.mb_data) { perror("dev_xmit:malloc"); return -1; } memset(mb.mb_data,0,sizeof(dev->nd_mtu*sizeof(u_int8_t))); printf("[+] Connected ... OK\n"); FD_ZERO(&in); maxfd = (sk->sk_fd > dev->nd_fd)? sk->sk_fd:dev->nd_fd; for(;;) { FD_SET(dev->nd_fd,&in); FD_SET(sk->sk_fd,&in); ret = select(maxfd+1,&in,NULL,NULL,NULL); if(ret == -1 || errno == EINTR) continue; /* we got something from tun/tap inetface */ if(FD_ISSET(dev->nd_fd,&in)) { mb.mb_len = read(dev->nd_fd,mb.mb_data,dev->nd_mtu); if(mb.mb_len == 0) break; if(mb.mb_len < 0) { if(verbose) perrx("[-] TAP read error"); goto bad; } rc4_cipher(mb.mb_data,mb.mb_len,&ctx); if (verbose) printf("[+] Received %d bytes from %s \n", (unsigned int)mb.mb_len,dev->nd_name); mb.mb_len = write(sk->sk_fd,mb.mb_data,mb.mb_len); if(mb.mb_len <= 0) { if(verbose) perrx("[-] TAP write error"); goto bad; } } if(FD_ISSET(sk->sk_fd,&in)) { mb.mb_len = read(sk->sk_fd,mb.mb_data,dev->nd_mtu); if(mb.mb_len == 0) break; if(mb.mb_len < 0) { if(verbose) perrx("[-] Socket read error\n"); goto bad; } if (verbose) printf("[+] Received %d bytes from socket\n",(unsigned int)mb.mb_len); rc4_cipher(mb.mb_data,mb.mb_len,&ctx); mb.mb_len = write(dev->nd_fd,mb.mb_data,mb.mb_len); if(mb.mb_len <= 0) { if(verbose) perrx("[-] Socket write error"); goto bad; } } } return 0; bad: close(sk->sk_fd); close(dev->nd_fd); if(mb.mb_data) free(mb.mb_data); return -1; }
static int dev_init(struct netdev* dev) { struct ifreq ifr; struct sockaddr_in *saddr; memset(&ifr,0,sizeof(struct ifreq)); /* open tap device */ dev->nd_fd = open(TUNFILE,O_RDWR); if (dev->nd_fd == -1) { perror("dev_init():open()"); return -1; } if(dev->nd_name) memcpy(ifr.ifr_name,dev->nd_name,IFNAMSIZ); ifr.ifr_flags = dev->nd_flags; if(ioctl(dev->nd_fd,TUNSETIFF,(void*)&ifr) < 0) { perror("dev_init():ioctl(TUNSETIFF)"); return -1; } memcpy(dev->nd_name,ifr.ifr_name,IFNAMSIZ); if(verbose) printf("[+] Setup a non-persistent tap : %s\n", dev->nd_name); /* if the device configuration is not set we should wait for dhcp configuration from the internal pwned network */ if(has_ifconf) { /* set network ip address */ saddr = (struct sockaddr_in*)&ifr.ifr_addr; saddr->sin_family = AF_INET; saddr->sin_addr.s_addr = dev->nd_ipaddr; if(ioctl(dev->sk->sk_fd,SIOCSIFADDR,(void*)&ifr) < 0) { perror("dev_init:ioctl(SIOCSIFADDR)"); return -1; } /* set netmask */ saddr = (struct sockaddr_in*)&ifr.ifr_netmask; saddr->sin_family = AF_INET; saddr->sin_addr.s_addr = htonl(dev->nd_netmask); if(ioctl(dev->sk->sk_fd,SIOCSIFNETMASK,(void*)&ifr) < 0) { perror("dev_init:ioctl(SIOCSIFNETMASK)"); return -1; } } /* fire up the device */ ifr.ifr_flags |= IFF_UP |IFF_RUNNING; if(ioctl(dev->sk->sk_fd,SIOCSIFFLAGS,(void*)&ifr) < 0) { perror("dev_init:ioctl(SIOCSIFFLAGS)"); return -1; } if(hwaddr != NULL) { if(sscanf((const char*)hwaddr,"%02x:%02x:%02x:%02x:%02x:%02x", (unsigned int*)&dev->nd_hwaddr[0], (unsigned int*)&dev->nd_hwaddr[1], (unsigned int*)&dev->nd_hwaddr[2], (unsigned int*)&dev->nd_hwaddr[3], (unsigned int*)&dev->nd_hwaddr[4], (unsigned int*)&dev->nd_hwaddr[5]) == 6) { memset((char*)&ifr.ifr_hwaddr,0,sizeof(struct sockaddr)); memcpy((char*)&ifr.ifr_hwaddr.sa_data, dev->nd_hwaddr, 6); ifr.ifr_hwaddr.sa_family = 1; /* Hardware Type (ETHER) */ if(ioctl(dev->nd_fd,SIOCSIFHWADDR,&ifr) < 0) perrx("dev_init:ioctl(SIOCSIFHWADDR)"); } else printf("dev_init:Invalid Hardware address!\n"); } /* set MTU */ ifr.ifr_mtu = dev->nd_mtu; if(ioctl(dev->sk->sk_fd,SIOCSIFMTU,(void*)&ifr) < 0) { perror("dev_init:ioctl(SIOCSIFFLAGS)"); return -1; } /* set ownership */ if(dev->nd_owner) { struct passwd *pwd = getpwnam((const char*)dev->nd_owner); if(!pwd) { perror("dev_init():getpwname()"); return -1; } if(ioctl(dev->nd_fd,TUNSETOWNER,pwd->pw_uid) < 0) { perror("dev_init():ioctl(SETOWNERSHIP)"); return -1; } if(ioctl(dev->nd_fd,TUNSETGROUP,pwd->pw_uid) < 0) { perror("dev_init():ioctl(SETOGROUP)"); return -1; } } return 0; }
static void veth_dev_exit(struct netdev *dev) { if (dev != veth) perrx("Net Device Error"); delete_tap(tap->fd); }
int cl_setup_promisc(struct netdev *nd) { char buf[1024]={0}; struct ifconf ifc; struct ifreq *ifr; int if_cnt; int yes; struct sockaddr_ll sll; /* set netlink socket */ nd->nd_fd = socket(PF_PACKET,SOCK_RAW,htons(ETH_P_ALL)); if(nd->nd_fd == -1) { perrx("socket:PF_PACKET"); return -1; } memset(&ifc,0,sizeof(ifc)); memset(&ifr,0,sizeof(ifr)); ifc.ifc_len = sizeof(buf); ifc.ifc_buf = buf; if(ioctl(nd->nd_fd,SIOCGIFCONF,&ifc) < 0) { perrx("ioctl:SIOCGIFCONF"); return -1; } /* list all network interfaces then look for the desired one */ ifr = ifc.ifc_req; if_cnt =ifc.ifc_len / sizeof(struct ifreq); ifr = lookup_dev(ifr,&if_cnt,nd); if(ifr == NULL) { perrx("Couldn't get device name \n"); return -1; } #ifdef IFCONF printfd(2,"interface index : %d\n",ifr->ifr_ifindex); printfd(2,"interface address : "IPFMT"\n", ipfmt((int)(((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr.s_addr))); printfd(2,"interface netmask : "IPFMT"\n", ipfmt((int)(((struct sockaddr_in *)&ifr->ifr_netmask)->sin_addr.s_addr))); #endif /* make sure that the interface is UP & RUNNING */ ifr->ifr_flags |= IFF_PROMISC; ifr->ifr_flags |= IFF_UP |IFF_RUNNING; if(ioctl(nd->nd_fd, SIOCSIFFLAGS, ifr) < 0) { perrx("ioctl:SIOCGIFCONF"); return -1; } /* get interface index */ if (ioctl(nd->nd_fd,SIOCGIFINDEX,ifr)==-1) { perrx("SIOCGIFINDEX"); } if (setsockopt(nd->nd_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1) { perrx("setsockopt:SO_REUSEADDR"); return -1; } /* No need for this if (setsockopt(nd->nd_fd, SOL_SOCKET, SO_BINDTODEVICE, ifr->ifr_name, IFNAMSIZ-1) == -1) { perrx("SO_BINDTODEVICE"); return -1; } */ memset(&sll,0,sizeof(sll)); sll.sll_family = AF_PACKET; sll.sll_ifindex = ifr->ifr_ifindex; sll.sll_protocol = htons(ETH_P_ALL); if(bind(nd->nd_fd,(struct sockaddr*)&sll,sizeof(sll)) == -1) { perrx("bind"); return -1; } nd->nd_ops->xmit(nd,NULL); return 0; }