📄 uml_netjig.c
字号:
"\t--exitonempty (-e) exit when no more packets to read\n" "\t--playpublic (-p) <file> pcap(3) file to feed into public side\n" "\t--recordpublic (-r) <file> pcap(3) file to write from public side\n" "\t--playprivate (-P) <file> pcap(3) file to feed into private side\n" "\t--recordprivate (-R) <file> pcap(3) file to write from private side\n" "\t--unix (-u) <dir> directory to put sockets (default $TMPDIR)\n" "\t--startup (-s) <script> script to run after sockets are setup.\n"#ifdef NETDISSECT "\t--tcpdump (-t) dump packets with tcpdump-dissector\n"#else "\t--tcpdump (-t) (not available - dissector not built in)\n"#endif#ifdef ARP_PROCESS "\t--arpreply (-a) respond to ARP requests\n"#else "\t--arpreply (-a) (not available - arp replies disabled)\n"#endif "\t--help this message\n\n"); exit(1);}#ifdef NETDISSECT/* Like default_print() but data need not be aligned */voiddefault_print_unaligned(struct netdissect_options *ipdo, register const u_char *cp, register u_int length){ register u_int i, s; register int nshorts; if (ipdo->ndo_Xflag) { ascii_print(ipdo, cp, length); return; } nshorts = (u_int) length / sizeof(u_short); i = 0; while (--nshorts >= 0) { if ((i++ % 8) == 0) (void)printf("\n\t\t\t"); s = *cp++; (void)printf(" %02x%02x", s, *cp++); } if (length & 1) { if ((i % 8) == 0) (void)printf("\n\t\t\t"); (void)printf(" %02x", *cp); }}/* * By default, print the packet out in hex. */voiddefault_print(struct netdissect_options *ndo, register const u_char *bp, register u_int length){ default_print_unaligned(ndo, bp, length);}#endifvoid init_nethub(struct nethub *nh, char *base, char *type){ int one; char *env; one = 1; memset(nh, 0, sizeof(*nh)); TAILQ_INIT(&nh->connections); nh->nh_name = strdup(type); /* setup ARP stuff */ nh->nh_allarp = 0; nh->nh_defaultgate.s_addr = 0; nh->nh_defaultether[0]=0x10; nh->nh_defaultether[1]=0x00; nh->nh_defaultether[2]=0x00; nh->nh_defaultether[3]=type[0]; nh->nh_defaultether[4]=type[1]; nh->nh_defaultether[5]=type[2]; /* cons up the names, and stick them in the environment */ env = xmalloc(sizeof("UML_")+strlen(type)+sizeof("CTL=")+ strlen(base)+sizeof("/ctl")+1); sprintf(env, "UML_%s_CTL=%s/ctl", type, base); nh->ctl_socket_name = strchr(env, '=')+1; putenv(env); env = xmalloc(sizeof("UML_")+strlen(type)+sizeof("DATA=")+ strlen(base)+sizeof("/data")+1); sprintf(env, "UML_%s_DATA=%s/data", type, base); nh->data_socket_name = strchr(env, '=')+1; putenv(env); if((nh->ctl_listen_fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0){ perror("socket"); exit(1); } if(setsockopt(nh->ctl_listen_fd, SOL_SOCKET, SO_REUSEADDR, (char *) &one, sizeof(one)) < 0){ perror("setsockopt"); exit(1); } if(fcntl(nh->ctl_listen_fd, F_SETFL, O_NONBLOCK) < 0){ perror("Setting O_NONBLOCK on connection fd"); exit(1); } if((nh->data_fd = socket(PF_UNIX, SOCK_DGRAM, 0)) < 0){ perror("socket"); exit(1); } if(fcntl(nh->data_fd, F_SETFL, O_NONBLOCK) < 0){ perror("Setting O_NONBLOCK on data fd"); exit(1); } bind_sockets(nh); if(listen(nh->ctl_listen_fd, 15) < 0){ perror("listen"); exit(1); } }static int debug=0;int main(int argc, char **argv){ int n, done; int exitonempty; char *publicbase, *privatebase; char *basedir, *startup; char *playprivatefile, *recordprivatefile; char *playpublicfile, *recordpublicfile; int publicturn; char errbuf[256]; int opt; int arpreply; static struct option long_options[] = { {"help", no_argument, 0, 'h'}, {"arpreply", no_argument, 0, 'a'}, {"debug", no_argument, 0, 'd'}, {"exitonempty", no_argument, 0, 'e'}, {"tcpdump", no_argument, 0, 't'}, {"playpublic", required_argument, 0, 'p'}, {"playprivate",required_argument, 0, 'P'}, {"recordpublic", required_argument, 0, 'r'}, {"recordprivate", required_argument, 0, 'R'}, {"unix", required_argument, 0, 'u'}, {"startup", required_argument, 0, 's'}, }; basedir = NULL; publicbase = NULL; privatebase= NULL; startup = NULL; arpreply = 0; exitonempty= 0; playpublicfile = playprivatefile = NULL; recordpublicfile= recordprivatefile = NULL; progname = argv[0]; if(strrchr(progname, '/')) { progname=strrchr(progname, '/')+1; } while((opt = getopt_long(argc, argv, "adehp:P:r:R:s:tu:", long_options, NULL)) != EOF) { switch(opt) { case 'a': arpreply++; break; case 'd': debug++; break; case 'e': exitonempty++; break; case 'u': basedir = optarg; break; case 's': startup = optarg; break; case 't': fprintf(stderr, "tcpdump dissector not available\n");#ifdef NETDISSECT tcpdump_print = 1;#endif break; case 'p': playpublicfile = optarg; break; case 'P': playprivatefile = optarg; break; case 'r': recordpublicfile= optarg; break; case 'R': recordprivatefile= optarg; break; case 'h': default: Usage(); } } if(basedir == NULL) { n=1000; while(n>0) { basedir=tempnam(NULL, "uml"); if(mkdir(basedir, 0700) == 0) { break; } n--; } if(n==0) { fprintf(stderr, "failed to make tmpdir (last=%s)\n", basedir); exit(1); } } if(!publicbase) { publicbase=xmalloc(strlen(basedir)+sizeof("/public")+1); sprintf(publicbase, "%s/public", basedir); if(mkdir(publicbase, 0700) != 0 && errno!=EEXIST) { perror(publicbase); exit(1); } } if(!privatebase) { privatebase=xmalloc(strlen(basedir)+sizeof("/private")+1); sprintf(privatebase, "%s/private", basedir); if(mkdir(privatebase, 0700) != 0 && errno!=EEXIST) { perror(privatebase); exit(1); } } #ifdef NETDISSECT memset(&gndo, 0, sizeof(gndo)); gndo.ndo_default_print = default_print; /* dump ethernet headers */ gndo.ndo_eflag = 1; /* avoid DNS lookups */ gndo.ndo_nflag = 0;#endif init_nethub(&public, publicbase, "public"); init_nethub(&private,privatebase,"private"); public.nh_allarp = arpreply; private.nh_allarp= arpreply; if(recordpublicfile) { pcap_t *pt; printf("%s: will record to %s from public interface\n", progname, recordpublicfile); public.nh_outputFile = recordpublicfile; pt = pcap_open_dead(DLT_EN10MB, 1536); public.nh_output = pcap_dump_open(pt, recordpublicfile); if(public.nh_output == NULL) { fprintf(stderr, "pcap_dump_open failed to open %s\n", recordpublicfile); exit(1); } } if(recordprivatefile) { pcap_t *pt; printf("%s: will record to %s from private interface\n", progname, recordprivatefile); private.nh_outputFile = recordprivatefile; pt = pcap_open_dead(DLT_EN10MB, 1536); private.nh_output = pcap_dump_open(pt, recordprivatefile); if(private.nh_output == NULL) { fprintf(stderr, "pcap_dump_open failed to open %s\n", recordprivatefile); exit(1); } } if(playpublicfile) { printf("%s: will play %s to public interface\n", progname, playpublicfile); public.nh_inputFile = playpublicfile; public.nh_input = pcap_open_offline(playpublicfile, errbuf); if(public.nh_input == NULL) { fprintf(stderr, "pcap_open_offline: %s\n", errbuf); exit(1); } } if(playprivatefile) { printf("%s: will play %s to private interface\n", progname, playprivatefile); private.nh_inputFile = playprivatefile; private.nh_input = pcap_open_offline(playprivatefile, errbuf); if(private.nh_input == NULL) { fprintf(stderr, "pcap_open_offline: %s\n", errbuf); exit(1); } } printf("%s: will exit on empty: %s\n", progname, exitonempty ? "yes" : "no "); if(signal(SIGINT, sig_handler) < 0) perror("Setting handler for SIGINT"); if(startup) { system(startup); } printf("%s attached to unix sockets \n\t'%s,%s'\n and \n\t'%s,%s'\n", progname, public.ctl_socket_name, public.data_socket_name, private.ctl_socket_name, private.data_socket_name); FD_ZERO(&perm_fds); if(isatty(0)) FD_SET(0, &perm_fds); FD_SET(public.ctl_listen_fd, &perm_fds); FD_SET(private.ctl_listen_fd, &perm_fds); FD_SET(public.data_fd, &perm_fds); FD_SET(private.data_fd, &perm_fds); max_fd = -1; max_fd = MAX(max_fd, public.ctl_listen_fd); max_fd = MAX(max_fd, private.ctl_listen_fd); max_fd = MAX(max_fd, public.data_fd); max_fd = MAX(max_fd, private.data_fd); publicturn = 1; done = 0; while(!done) { fd_set temp; struct timeval tv, *waittime; char buf[128]; waittime=NULL; if(public.nh_input || private.nh_input) { tv.tv_sec = 0; tv.tv_usec = 500000; waittime = &tv; } temp = perm_fds; if(debug > 1) { printf("invoking select with %s %s %s", waittime ? "waittime" : "no wait", public.nh_input ? "public" : "no-public", private.nh_input ? "private" : "no-priv"); fflush(stdout); } n = select(max_fd + 1, &temp, NULL, NULL, waittime); if(debug > 1) { printf(" -> %d left %lu\n", n, tv.tv_usec); } if(n < 0){ perror("select"); done = 1; } if(waittime && tv.tv_usec == 0) { struct nethub *nh; /* timeout */ if(publicturn) { nh = &public; } else { nh = &private; } if(nh->nh_input) { struct pcap_pkthdr ph; const u_char *packet; memset(&ph, 0, sizeof(ph)); packet = pcap_next(nh->nh_input, &ph); if(packet == NULL) { nh->nh_input=NULL; } else { printf("%8s: inserting packet of len %d\n", nh->nh_name, ph.len); forward_data(nh, (struct packet *)packet, ph.len); } } publicturn = !publicturn; if(public.nh_input == NULL && private.nh_input == NULL && exitonempty) { done=1; } } if(n > 0) { if(FD_ISSET(0, &temp)){ n = read(0, buf, sizeof(buf)); if(n < 0){ perror("Reading from stdin"); break; } else if(n == 0){ printf("EOF on stdin, cleaning up and exiting\n"); break; } continue; } else if(FD_ISSET(public.ctl_listen_fd, &temp)){ accept_connection(&public); FD_CLR(public.ctl_listen_fd, &temp); } else if(FD_ISSET(private.ctl_listen_fd, &temp)){ accept_connection(&private); FD_CLR(private.ctl_listen_fd, &temp); } if(FD_ISSET(public.data_fd, &temp)){ handle_data(&public); FD_CLR(public.data_fd, &temp); } else if(FD_ISSET(private.data_fd, &temp)){ handle_data(&private); FD_CLR(private.data_fd, &temp); } handle_connections(&public, &temp, max_fd + 1); handle_connections(&private,&temp, max_fd + 1); } } cleanup(&public); cleanup(&private); return 0;}/* * $Log: uml_netjig.c,v $ * Revision 1.2 2002/11/05 01:51:44 ken * /testing tree from 1.99 * * Revision 1.8 2002/01/21 01:08:41 mcr * do not die if -t option is provided, but tcpdump compiled out. * * Revision 1.7 2002/01/12 04:01:36 mcr * another #ifdef NETDISSET for tcpdump_print access. * * Revision 1.6 2002/01/12 03:40:56 mcr * missing #ifdef for on NETDISSECT call. * * Revision 1.5 2002/01/12 02:52:46 mcr * added --debug option to replace #if 0. * * Revision 1.4 2001/10/23 16:34:12 mcr * use "progname" instead of "prog" * fixed public/private confused variables in printf(). * fixed bug in termination logic. * * Revision 1.3 2001/10/14 00:27:10 mcr * added code to play pcap files to both public and private sides. * updated usage. * * Revision 1.2 2001/10/12 20:54:02 mcr * documented environment variables * added arp replies * added --help and fixed Usage(). * * Revision 1.1 2001/10/08 22:54:05 mcr * uml_net program that handles two interfaces. * no support for pcap yet. * * * * Local variables: * c-file-style: "linux" * c-basic-offset: 2 * End: * */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -