/* File: $Source: /usr/drwho/vault/cvs/topsy/MipsSim/ethertap.c,v $ Affiliation: ETH Zuerich, TIK Version: $Revision: 1.1 $ Creation Date: December 1996 Last Date of Change: $Date: 2000/04/05 14:33:16 $ by: $Author: gfa $ $Log: ethertap.c,v $ Revision 1.1 2000/04/05 14:33:16 gfa *** empty log message *** Usage: if [[ ! -c /dev/tap0 ]]; then mknod /dev/tap0 c 36 16 chmod go+rw /dev/tap0 fi modprobe ethertap ifconfig tap0 192.168.2.1/24 arp */ #include #include #include #include #include #include #include #include #include #include int setuptap(char *name); int setupserver(int port); int setupclient(int sockt); int setuplog(char *name); ssize_t sendpacket(int, int, int); ssize_t recvpacket(int, int, int); main(int argc, char **argv) { int port, sockt; int tapfd, clientfd, maxfd; int taplog=0, clientlog=0; fd_set fdset; struct timeval tv; ssize_t len; if(argc<3) { fprintf(stderr,"Syntax: ethertap tapdevice port [tap-log-file] [client-log-file]\n"); exit(1); } port = atoi(argv[2]); printf("Starting Ethertap server (v1.1) on port %d.\n", port); /* Open tap device */ tapfd = setuptap(argv[1]); /* Open socket */ sockt = setupserver(port); /* Open log files */ if(argc>3) taplog = setuplog(argv[3]); if(argc>4) clientlog = setuplog(argv[4]); while(1) { /* Wait for client */ clientfd = setupclient(sockt); if(tapfd>clientfd) maxfd=tapfd+1; else maxfd=clientfd+1; while(1) { FD_ZERO(&fdset); FD_SET(tapfd, &fdset); FD_SET(clientfd, &fdset); tv.tv_sec = 0; tv.tv_usec = 1000; if(select(maxfd, &fdset, NULL, NULL, &tv)) { if(FD_ISSET(tapfd, &fdset)) { /* fputc('>',stdout); fflush(stdout); */ len=sendpacket(tapfd,clientfd,taplog); if(len<=0) break; printf("tap -> client (%d)\n",len); } if(FD_ISSET(clientfd, &fdset)) { /* fputc('<',stdout); fflush(stdout); */ len=recvpacket(clientfd,tapfd,clientlog); if(len<=0) break; printf("tap <- client (%d)\n",len); } } } close(clientfd); } close(sockt); close(tapfd); exit(0); } int setuptap(char *name) { int fd; fd = open(name, O_RDWR); if(fd < 0) { perror(name); exit(1); } return fd; } int setuplog(char *name) { int fd; fd = open(name, O_WRONLY|O_CREAT); if(fd < 0) { perror(name); exit(1); } return fd; } int setupserver(int port) { int s, n=INADDR_ANY; int len = sizeof(struct sockaddr_in); struct sockaddr_in name; /* open socket */ s = socket(AF_INET, SOCK_STREAM, 0); if(s < 0) { perror("socket"); exit(1); } /* address */ memset(&name, 0, sizeof(struct sockaddr_in)); name.sin_family=AF_INET; name.sin_port=htons(port); memcpy(&name.sin_addr, &n, sizeof(long)); /* bind */ if(bind(s,(struct sockaddr *)&name, len)<0) { perror("bind"); exit(1); } /* listen */ if(listen(s, 5)<0) { perror("listen"); exit(1); } return s; } int setupclient(int s) { int fd; int len = sizeof(struct sockaddr_in); struct sockaddr_in name; puts("Waiting for a client."); if((fd = accept(s, (struct sockaddr *) &name, &len)) < 0) { perror("accept"); exit(1); } puts("Client connected."); return fd; } ssize_t sendpacket(int from, int to, int log) { char buf[2000]; ssize_t len; int n; len=read(from,buf,sizeof(buf)); if(len > 0) { n = write(to,buf+2,len-2); /* What is this 2-bytes-junk at the beginning? */ if(log) write(log,buf+2,len-2); if(n!=len-2) { printf("warning: wanted to write: %d, written: %d\n", len-2, n); } } return len-2; } ssize_t recvpacket(int from, int to, int log) { char buf[2000]; ssize_t len; len=read(from,buf+2,sizeof(buf)); buf[0]=0; buf[1]=0; if(len > 0) { len=write(to,buf,len+2); if(log) write(log,buf,len); if(len>2) len-=2; } return len; }