static int allocif(int unit, struct shmif_sc **scp) { uint8_t enaddr[ETHER_ADDR_LEN] = { 0xb2, 0xa0, 0x00, 0x00, 0x00, 0x00 }; struct shmif_sc *sc; struct ifnet *ifp; uint32_t randnum; int error; randnum = cprng_fast32(); memcpy(&enaddr[2], &randnum, sizeof(randnum)); sc = kmem_zalloc(sizeof(*sc), KM_SLEEP); sc->sc_memfd = -1; sc->sc_unit = unit; sc->sc_uuid = cprng_fast64(); ifp = &sc->sc_ec.ec_if; snprintf(ifp->if_xname, sizeof(ifp->if_xname), "shmif%d", unit); ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_init = shmif_init; ifp->if_ioctl = shmif_ioctl; ifp->if_start = shmif_start; ifp->if_stop = shmif_stop; ifp->if_mtu = ETHERMTU; ifp->if_dlt = DLT_EN10MB; mutex_init(&sc->sc_mtx, MUTEX_DEFAULT, IPL_NONE); cv_init(&sc->sc_cv, "shmifcv"); if_initialize(ifp); ether_ifattach(ifp, enaddr); if_register(ifp); aprint_verbose("shmif%d: Ethernet address %s\n", unit, ether_sprintf(enaddr)); if (scp) *scp = sc; error = 0; if (rump_threads) { error = kthread_create(PRI_NONE, KTHREAD_MPSAFE | KTHREAD_MUSTJOIN, NULL, shmif_rcv, ifp, &sc->sc_rcvl, "shmif"); } else { printf("WARNING: threads not enabled, shmif NOT working\n"); } if (error) { shmif_unclone(ifp); } return error; }
void tap_attach(device_t parent, device_t self, void *aux) { struct tap_softc *sc = device_private(self); struct ifnet *ifp; const struct sysctlnode *node; int error; uint8_t enaddr[ETHER_ADDR_LEN] = { 0xf2, 0x0b, 0xa4, 0xff, 0xff, 0xff }; char enaddrstr[3 * ETHER_ADDR_LEN]; sc->sc_dev = self; sc->sc_sih = NULL; getnanotime(&sc->sc_btime); sc->sc_atime = sc->sc_mtime = sc->sc_btime; sc->sc_flags = 0; selinit(&sc->sc_rsel); /* * Initialize the two locks for the device. * * We need a lock here because even though the tap device can be * opened only once, the file descriptor might be passed to another * process, say a fork(2)ed child. * * The Giant saves us from most of the hassle, but since the read * operation can sleep, we don't want two processes to wake up at * the same moment and both try and dequeue a single packet. * * The queue for event listeners (used by kqueue(9), see below) has * to be protected too, so use a spin lock. */ mutex_init(&sc->sc_rdlock, MUTEX_DEFAULT, IPL_NONE); mutex_init(&sc->sc_kqlock, MUTEX_DEFAULT, IPL_VM); if (!pmf_device_register(self, NULL, NULL)) aprint_error_dev(self, "couldn't establish power handler\n"); /* * In order to obtain unique initial Ethernet address on a host, * do some randomisation. It's not meant for anything but avoiding * hard-coding an address. */ cprng_fast(&enaddr[3], 3); aprint_verbose_dev(self, "Ethernet address %s\n", ether_snprintf(enaddrstr, sizeof(enaddrstr), enaddr)); /* * Why 1000baseT? Why not? You can add more. * * Note that there are 3 steps: init, one or several additions to * list of supported media, and in the end, the selection of one * of them. */ ifmedia_init(&sc->sc_im, 0, tap_mediachange, tap_mediastatus); ifmedia_add(&sc->sc_im, IFM_ETHER|IFM_1000_T, 0, NULL); ifmedia_add(&sc->sc_im, IFM_ETHER|IFM_1000_T|IFM_FDX, 0, NULL); ifmedia_add(&sc->sc_im, IFM_ETHER|IFM_100_TX, 0, NULL); ifmedia_add(&sc->sc_im, IFM_ETHER|IFM_100_TX|IFM_FDX, 0, NULL); ifmedia_add(&sc->sc_im, IFM_ETHER|IFM_10_T, 0, NULL); ifmedia_add(&sc->sc_im, IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL); ifmedia_add(&sc->sc_im, IFM_ETHER|IFM_AUTO, 0, NULL); ifmedia_set(&sc->sc_im, IFM_ETHER|IFM_AUTO); /* * One should note that an interface must do multicast in order * to support IPv6. */ ifp = &sc->sc_ec.ec_if; strcpy(ifp->if_xname, device_xname(self)); ifp->if_softc = sc; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_ioctl = tap_ioctl; ifp->if_start = tap_start; ifp->if_stop = tap_stop; ifp->if_init = tap_init; IFQ_SET_READY(&ifp->if_snd); sc->sc_ec.ec_capabilities = ETHERCAP_VLAN_MTU | ETHERCAP_JUMBO_MTU; /* Those steps are mandatory for an Ethernet driver. */ if_initialize(ifp); ether_ifattach(ifp, enaddr); if_register(ifp); /* * Add a sysctl node for that interface. * * The pointer transmitted is not a string, but instead a pointer to * the softc structure, which we can use to build the string value on * the fly in the helper function of the node. See the comments for * tap_sysctl_handler for details. * * Usually sysctl_createv is called with CTL_CREATE as the before-last * component. However, we can allocate a number ourselves, as we are * the only consumer of the net.link.<iface> node. In this case, the * unit number is conveniently used to number the node. CTL_CREATE * would just work, too. */ if ((error = sysctl_createv(NULL, 0, NULL, &node, CTLFLAG_READWRITE, CTLTYPE_STRING, device_xname(self), NULL, tap_sysctl_handler, 0, (void *)sc, 18, CTL_NET, AF_LINK, tap_node, device_unit(sc->sc_dev), CTL_EOL)) != 0) aprint_error_dev(self, "sysctl_createv returned %d, ignoring\n", error); }
int main( int argc, char *argv[] ) { int fd; #if HAVE_SIGNAL_H struct sigaction signalaction; #endif #ifdef WIN32 WSADATA wsadata; WSAStartup(WINSOCK_VERSION, &wsadata); #endif E_init(); wack_alarm_set( PRINT | EXIT ); Usage( argc, argv ); Wackamole_init(); if(Debug) { wack_alarm_enable_timestamp(NULL); wack_alarm_set( PRINT | ARPING | WACK_DEBUG | EXIT ); } else { char pidstring[10]; wack_alarm_set(PRINT | EXIT); wack_alarm_enable_syslog("wackamole"); #ifndef WIN32 if(fork()) exit(0); setsid(); if(fork()) exit(0); #endif if( chdir("/") != 0 ){ wack_alarm(PRINT,"chdir to root failed"); } umask(0027); pid = getpid(); fd = open(_PATH_WACKAMOLE_PIDDIR "/wackamole.pid", O_WRONLY|O_CREAT|O_TRUNC, 0644); if(fd < 0) { wack_alarm(EXIT, "Cannot write PID file " _PATH_WACKAMOLE_PIDDIR "/wackamole.pid"); } snprintf(pidstring, 10, "%d\n", pid); #ifdef BROKEN_SNPRINTF if(pidstring[9] != '\0') { pidstring[8] = '\n'; pidstring[9] = '\0'; } #endif write(fd, pidstring, strlen(pidstring)); close(fd); #ifndef WIN32 fd = open("/dev/null", O_RDWR); if(fd <= 2) { wack_alarm(EXIT, "Cannot open /dev/null\n"); } close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); dup2(fd,STDIN_FILENO); dup2(fd,STDOUT_FILENO); dup2(fd,STDERR_FILENO); close(fd); #endif } #if HAVE_SIGNAL_H signalaction.sa_handler = Sig_handler; sigemptyset(&signalaction.sa_mask); signalaction.sa_flags = 0; if(sigaction(SIGINT, &signalaction, NULL)) { wack_alarm(EXIT, "An error occured while registering a SIGINT handler"); } if(sigaction(SIGTERM, &signalaction, NULL)) { wack_alarm(EXIT, "An error occured while registering a SIGTERM handler"); } if(sigaction(SIGBUS, &signalaction, NULL)) { wack_alarm(EXIT, "An error occured while registering a SIGBUS handler"); } if(sigaction(SIGQUIT, &signalaction, NULL)) { wack_alarm(EXIT, "An error occured while registering a SIGQUIT handler"); } if(sigaction(SIGSEGV, &signalaction, NULL)) { wack_alarm(EXIT, "An error occured while registering a SIGSEGV handler"); } #elif defined(WIN32) SetConsoleCtrlHandler(ConsoleEventHandlerRoutine, TRUE); #endif if_initialize(); /* connecting to the relevant Spread daemon, asking for group info */ Spread_reconnect(-8); Send_local_arp_cache_repeat(); E_handle_events(); return -1; }
int main (int argc, char *argv[]) { int A,B,C,D, i, ic; struct interface req, myips[300]; int state; #ifdef WIN32 WSADATA wsadata; WSAStartup(WINSOCK_VERSION, &wsadata); #endif i=1; if(argc < 2) goto usage_error; if(argv[i][0] != '-') goto usage_error; switch(argv[i++][1]) { case 'r': state=ARPLIST; break; case 'l': state=LIST; break; case 'a': state=ADD; strcpy(req.ifname, argv[i++]); sscanf(argv[i++], "%d.%d.%d.%d", &A,&B,&C,&D); req.ipaddr.s_addr = htonl((A << 24) | (B << 16) | (C << 8) | D); sscanf(argv[i++], "%d.%d.%d.%d", &A,&B,&C,&D); req.bcast.s_addr = htonl((A << 24) | (B << 16) | (C << 8) | D); sscanf(argv[i++], "%d.%d.%d.%d", &A,&B,&C,&D); req.netmask.s_addr = htonl((A << 24) | (B << 16) | (C << 8) | D); break; case 'd': state=DELETE; sscanf(argv[i++], "%d.%d.%d.%d", &A,&B,&C,&D); req.ifname[0] = '\0'; req.ipaddr.s_addr = htonl((A << 24) | (B << 16) | (C << 8) | D); break; case 's': state=SPOOF; strcpy(req.ifname, argv[i++]); sscanf(argv[i++], "%d.%d.%d.%d", &A,&B,&C,&D); req.ipaddr.s_addr = htonl((A << 24) | (B << 16) | (C << 8) | D); sscanf(argv[i++], "%d.%d.%d.%d", &A,&B,&C,&D); req.bcast.s_addr = htonl((A << 24) | (B << 16) | (C << 8) | D); break; usage_error: default: fprintf(stderr, "%s:\n\tUsage:\n\t\t-l\t\t\t\t\tlist interfaces\n\t\t-a <interface> <ip> <bcast> <netmask>\tAdd this VIP\n\t\t-d <IP>\t\t\t\t\tDelete this VIP\n\t\t-s interface VIP destinationIP\n", argv[0]); exit(-1); } if_initialize(); if(state&ARPLIST) { arp_entry *ad, *ac; fprintf(stderr, "Sampling and printing local arp-cache\n"); sample_arp_cache(); sample_arp_cache(); ac = ad = fetch_shared_arp_cache(); while(ad && ad->ip) { struct in_addr iad; iad.s_addr = ad->ip; fprintf(stderr, "\t%s\n", inet_ntoa(iad)); ad++; } free(ac); } if(state&ADD) { ic = if_up(&req); if(ic) { perror("ioctl"); fprintf(stderr, "%s\n", if_error()); } else { fprintf(stderr, "if_up: %s\t%s", req.ifname, inet_ntoa(req.ipaddr)); fprintf(stderr, "\t%s", inet_ntoa(req.bcast)); fprintf(stderr, "\t%s\n", inet_ntoa(req.netmask)); } } if(state&DELETE) { ic = if_down(&req); if(ic) fprintf(stderr, "%s\n", if_error()); else { fprintf(stderr, "if_down: %s\t%s", req.ifname, inet_ntoa(req.ipaddr)); fprintf(stderr, "\t%s", inet_ntoa(req.bcast)); fprintf(stderr, "\t%s\n", inet_ntoa(req.netmask)); } } if(state&SPOOF) { ic = if_send_spoof_request(req.ifname, req.ipaddr.s_addr, req.bcast.s_addr, NULL, 5, 0); if(ic) fprintf(stderr, "%s\n", if_error()); else { fprintf(stderr, "if_spoofed: %s\t%s\n",req.ifname, inet_ntoa(req.ipaddr)); } } if(state) { ic = if_list_ips(myips, 300); fprintf(stderr, "Found %d IPs:\n", ic); for(i=0; i<ic; i++) { fprintf(stderr, "%s\t[%02x:%02x:%02x:%02x:%02x:%02x]", myips[i].ifname, myips[i].mac[0], myips[i].mac[1], myips[i].mac[2], myips[i].mac[3], myips[i].mac[4], myips[i].mac[5]); fprintf(stderr, "\t%s", inet_ntoa(myips[i].ipaddr)); fprintf(stderr, "\t%s", inet_ntoa(myips[i].bcast)); fprintf(stderr, "\t%s\n", inet_ntoa(myips[i].netmask)); } } return 0; }