int main(int argc, char *argv[]) { in_addr_t dst_ip; unsigned char *mac; in_addr_t ip; int chkip; if ( argc < 2 ) { printf("too few argument\n"); exit(-1); } dst_ip = inet_addr(argv[1]); mac = (char*)malloc(16); get_if_info("eth0", mac, &ip); chkip = check_ip("eth0", dst_ip); if ( chkip < 0 ){ printf("check_ip error\n"); return -1; }else if ( chkip == 0 ) printf("IP free\n"); else printf("IP has been used\n"); return 0; }
int mcast::get_if_list(if_info* ifi,int nifi) { int s=socket(PF_INET,SOCK_DGRAM,0); int n=0; if(s!=-1) { int l=sizeof(ifreq)*nifi; ifreq* ifr=(ifreq*)MALLOC(l); if(ifi) { ifconf ifc; memset((char*)&ifc,0,sizeof(ifc)); ifc.ifc_buf=(char*)ifr; ifc.ifc_len=l; if(ioctl(s,SIOCGIFCONF,&ifc)!=-1) { n=ifc.ifc_len/sizeof(ifreq); if(n>nifi) n=nifi; for(int i=0;i<n;i++) { #ifdef __FreeBSD__ get_if_info(ifr[i].ifr_name,ifi+i); #else get_if_info(ifr[i].ifr_ifrn.ifrn_name,ifi+i); #endif /* __FreeBSD__ */ } } FREE(ifr); } close(s); } return n; }
/* ARGSUSED */ static void show_link(void *arg, const char *name) { dladm_attr_t dlattr; boolean_t legacy = B_TRUE; show_link_state_t *state = (show_link_state_t *)arg; if (get_if_info(name, &dlattr, &legacy) < 0) { (void) fprintf(stderr, gettext("%s: invalid device '%s'\n"), progname, name); exit(1); } if (state->ls_parseable) { print_link_parseable(name, &dlattr, legacy); } else { print_link(name, &dlattr, legacy); } }
/* ARGSUSED */ static void link_stats(const char *link, uint32_t interval) { dladm_attr_t dlattr; boolean_t legacy; show_link_state_t state; if (link != NULL && get_if_info(link, &dlattr, &legacy) < 0) { (void) fprintf(stderr, gettext("%s: invalid device '%s'\n"), progname, link); exit(1); } bzero(&state, sizeof (state)); /* * If an interval is specified, continuously show the stats * only for the first MAC port. */ state.ls_firstonly = (interval != 0); for (;;) { (void) printf("\t\tipackets rbytes ierrors "); (void) printf("opackets obytes oerrors\n"); state.ls_donefirst = B_FALSE; if (link == NULL) (void) dladm_walk(show_link_stats, &state); else show_link_stats(&state, link); if (interval == 0) break; (void) sleep(interval); } }
void host_init(char *ifname) { struct sockaddr_in *ina; char buf[1024], tmp_ifname[IFNAMSIZ], ifnames[(IFNAMSIZ + 1) * MAX_NR_INTERFACES], *iface; struct ifconf ifc; struct ifreq ifreq, *ifr; int i, iw_sock, if_sock = 0; memset(&this_host, 0, sizeof(struct host_info)); memset(dev_indices, 0, sizeof(unsigned int) * MAX_NR_INTERFACES); if (!ifname) { /* No interface was given... search for first wireless. */ iw_sock = socket(PF_INET, SOCK_DGRAM, 0); ifc.ifc_len = sizeof(buf); ifc.ifc_buf = buf; if (ioctl(iw_sock, SIOCGIFCONF, &ifc) < 0) { fprintf(stderr, "Could not get wireless info\n"); exit(-1); } ifr = ifc.ifc_req; for (i = ifc.ifc_len / sizeof(struct ifreq); i >= 0; i--, ifr++) { struct iwreq req; strcpy(req.ifr_name, ifr->ifr_name); if (ioctl(iw_sock, SIOCGIWNAME, &req) >= 0) { strcpy(tmp_ifname, ifr->ifr_name); break; } } /* Did we find a wireless interface? */ if (!strlen(tmp_ifname)) { fprintf(stderr, "\nCould not find a wireless interface!\n"); fprintf(stderr, "Use -i <interface> to override...\n\n"); exit(-1); } strcpy(ifreq.ifr_name, tmp_ifname); if (ioctl(iw_sock, SIOCGIFINDEX, &ifreq) < 0) { alog(LOG_ERR, errno, __FUNCTION__, "Could not get index of %s", tmp_ifname); close(if_sock); exit(-1); } close(iw_sock); ifname = tmp_ifname; alog(LOG_NOTICE, 0, __FUNCTION__, "Attaching to %s, override with -i <if1,if2,...>.", tmp_ifname); } strcpy(ifnames, ifname); /* Intitialize the local sequence number an rreq_id to zero */ this_host.seqno = 1; this_host.rreq_id = 0; /* Zero interfaces enabled so far... */ this_host.nif = 0; gettimeofday(&this_host.bcast_time, NULL); /* Find the indices of all interfaces to broadcast on... */ if_sock = socket(AF_INET, SOCK_DGRAM, 0); iface = strtok(ifname, ","); /* OK, now lookup interface information, and store it... */ do { strcpy(ifreq.ifr_name, iface); if (ioctl(if_sock, SIOCGIFINDEX, &ifreq) < 0) { alog(LOG_ERR, errno, __FUNCTION__, "Could not get index of %s", iface); close(if_sock); exit(-1); } this_host.devs[this_host.nif].ifindex = ifreq.ifr_ifindex; dev_indices[this_host.nif++] = ifreq.ifr_ifindex; strcpy(DEV_IFINDEX(ifreq.ifr_ifindex).ifname, iface); /* Get IP-address of interface... */ ina = get_if_info(iface, SIOCGIFADDR); if (ina == NULL) exit(-1); DEV_IFINDEX(ifreq.ifr_ifindex).ipaddr = ina->sin_addr; /* Get netmask of interface... */ ina = get_if_info(iface, SIOCGIFNETMASK); if (ina == NULL) exit(-1); DEV_IFINDEX(ifreq.ifr_ifindex).netmask = ina->sin_addr; ina = get_if_info(iface, SIOCGIFBRDADDR); if (ina == NULL) exit(-1); DEV_IFINDEX(ifreq.ifr_ifindex).broadcast = ina->sin_addr; DEV_IFINDEX(ifreq.ifr_ifindex).enabled = 1; if (this_host.nif >= MAX_NR_INTERFACES) break; } while ((iface = strtok(NULL, ","))); close(if_sock); /* Load kernel modules */ load_modules(ifnames); /* Enable IP forwarding and set other kernel options... */ if (set_kernel_options() < 0) { fprintf(stderr, "Could not set kernel options!\n"); exit(-1); } }
PRIVATE_EXTERN void inet6_addrlist_copy(inet6_addrlist_t * addr_list_p, int if_index) { int addr_index = 0; char * buf = NULL; char * buf_end; int buf_len; int count; int error; int i; char ifname[IFNAMSIZ + 1]; inet6_addrinfo_t * linklocal = NULL; inet6_addrinfo_t * list = NULL; char * scan; struct rt_msghdr * rtm; int s = -1; buf = get_if_info(if_index, AF_INET6, &buf_len); if (buf == NULL) { goto done; } buf_end = buf + buf_len; /* figure out how many IPv6 addresses there are */ count = 0; ifname[0] = '\0'; for (scan = buf; scan < buf_end; scan += rtm->rtm_msglen) { struct if_msghdr * ifm; /* ALIGN: buf aligned (from calling get_if_info), scan aligned, * cast ok. */ rtm = (struct rt_msghdr *)(void *)scan; if (rtm->rtm_version != RTM_VERSION) { continue; } switch (rtm->rtm_type) { case RTM_IFINFO: ifm = (struct if_msghdr *)rtm; if (ifm->ifm_addrs & RTA_IFP) { struct sockaddr_dl * dl_p; dl_p = (struct sockaddr_dl *)(ifm + 1); if (dl_p->sdl_nlen == 0 || dl_p->sdl_nlen >= sizeof(ifname)) { goto done; } bcopy(dl_p->sdl_data, ifname, dl_p->sdl_nlen); ifname[dl_p->sdl_nlen] = '\0'; } break; case RTM_NEWADDR: count++; break; default: break; } } if (ifname[0] == '\0') { goto done; } if (count == 0) { goto done; } if (count > INET6_ADDRLIST_N_STATIC) { list = (inet6_addrinfo_t *)malloc(sizeof(*list) * count); if (list == NULL) { goto done; } } else { list = addr_list_p->list_static; } for (scan = buf; scan < buf_end; scan += rtm->rtm_msglen) { boolean_t got_address = FALSE; struct ifa_msghdr * ifam; struct rt_addrinfo info; rtm = (struct rt_msghdr *)(void *)scan; if (rtm->rtm_version != RTM_VERSION) { continue; } if (rtm->rtm_type == RTM_NEWADDR) { ifam = (struct ifa_msghdr *)rtm; info.rti_addrs = ifam->ifam_addrs; error = rt_xaddrs((char *)(ifam + 1), ((char *)ifam) + ifam->ifam_msglen, &info); if (error) { fprintf(stderr, "couldn't extract rt_addrinfo %s (%d)\n", strerror(error), error); goto done; } for (i = 0; i < RTAX_MAX; i++) { struct sockaddr_in6 * sin6_p; /* ALIGN: info.rti_info aligned (sockaddr), cast ok. */ sin6_p = (struct sockaddr_in6 *)(void *)info.rti_info[i]; if (sin6_p == NULL || sin6_p->sin6_len < sizeof(struct sockaddr_in6)) { continue; } switch (i) { case RTAX_NETMASK: list[addr_index].prefix_length = count_prefix_bits(&sin6_p->sin6_addr, sizeof(sin6_p->sin6_addr)); break; case RTAX_IFA: list[addr_index].addr = sin6_p->sin6_addr; got_address = TRUE; break; default: break; } } if (got_address) { if (s < 0) { s = inet6_dgram_socket(); } if (s >= 0) { siocgifaflag_in6(s, ifname, &list[addr_index].addr, &list[addr_index].addr_flags); siocgifalifetime_in6(s, ifname, &list[addr_index].addr, &list[addr_index].valid_lifetime, &list[addr_index].preferred_lifetime); } /* Mask the v6 LL scope id */ if (IN6_IS_ADDR_LINKLOCAL(&list[addr_index].addr)) { list[addr_index].addr.s6_addr16[1] = 0; if (linklocal == NULL) { linklocal = &list[addr_index]; } } addr_index++; } } } if (addr_index == 0) { if (list != addr_list_p->list_static) { free(list); } list = NULL; } done: if (s >= 0) { close(s); } if (buf != NULL) { free(buf); } addr_list_p->list = list; addr_list_p->count = addr_index; addr_list_p->linklocal = linklocal; return; }
// 1419 is the mtu using a 1500 byte ethernet mtu - ipv4 header - udp - dtls with default ciphersuite (I think) // TODO: read mtu from interface on each OS instead of hard coding 1419 (also have installer set sensible interface MTU) tuntap::tuntap() : mtu(1419) { // TODO: use configuration parameters for registry key names instead of hard coded values // TODO: package TAP-Windows and change component ID or otherwise figure out how to make it not collide with what OpenVPN uses // see comment in %PROGRAMFILES%\TAP-Windows\driver\OemWin2k.inf after installing OpenVPN TAP driver #ifdef WINDOWS sent_sync = true; // no async send in progress received_sync = 0; memset(&recv_overlapped, 0, sizeof(OVERLAPPED)); memset(&send_overlapped, 0, sizeof(OVERLAPPED)); recv_event = CreateEvent(nullptr, FALSE, FALSE, nullptr); if(recv_event == INVALID_HANDLE_VALUE) throw check_err_exception("CreateEvent failed for tuntap recv_event"); recv_overlapped.hEvent = recv_event; // default callback emits error read_ready_cb = []() { eout() << "BUG: tuntap read ready callback called but not set"; }; if(RegisterWaitForSingleObject(&recv_wait, recv_event, &tuntap::read_event_cb, this, INFINITE, WT_EXECUTEINWAITTHREAD) == FALSE) throw check_err_exception("RegisterWaitForSingleObject on tuntap read event"); adapter_GUID = snow::conf[snow::VIRTUAL_INTERFACE]; if(adapter_GUID == "auto") { try { // open registry key for all network adapters registry_key adapters(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Class\\{4D36E972-E325-11CE-BFC1-08002BE10318}", KEY_READ); for(auto &it : adapters.subkeys()) { try { registry_key adapter = it.get(KEY_READ); // TODO: change ComponentId from "tap0901" to some other string to remove possible namespace collision with OpenVPN (this has to occur in the driver too) if(adapter.values().get_value_string("ComponentId") == "tap0901") { adapter_GUID = adapter.values().get_value_string("NetCfgInstanceId"); break; } } catch(const registry_exception &re) { dout() << "Failed to access registry subkey: " << re; } } } catch (const registry_exception &re) { eout() << "FATAL: Failed to open network adapters registry key, cannot determine TUN adapter to use: " << re; throw; } } dout() << "Adapter GUID: " << adapter_GUID; if(adapter_GUID == "auto") throw e_not_found("no usable tuntap interface"); // [at this point GUID is value of NetCfgInstanceId, although there could be more than one interface: check all against something else? (interface name?)] // TODO: probably the thing to do is: on install, create a TAP-Windows interface and set its name to 'snow tunnel interface' or so, // then set the GUID in the configuration file [or registry setting], and GUI config program can list interfaces by name and allow user to choose // then the configured GUID is the interface we use and all of this mess doesn't even need to go here -- it just goes once on install and in the config editor // what would then really be useful would be a way (other than changing the ComponentId) to tell other software (e.g. OpenVPN) not to use a particular interface // two possible solutions may be to either make sure that snow starts before the other service [somehow] and gets there first, // or setting permissions [somehow] so that only snow process has access std::string tap_filename("\\\\.\\Global\\"); tap_filename += adapter_GUID + ".tap"; fd = CreateFile(tap_filename.c_str(), GENERIC_READ | GENERIC_WRITE, 0/*no shared access*/, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM | FILE_FLAG_OVERLAPPED, nullptr); if(fd == INVALID_HANDLE_VALUE) throw check_err_exception("Failed to open Windows TUN/TAP device"); // name of specific instance of adapter as shown in control panel can be found in: // "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}\\" + adapter_GUID + "\\Connection" // value is "Name" // set to TUN mode // TAP_WIN_IOCTL_CONFIG_TUN takes three args: interface IP addr, network addr and netmask if_info ifinfo = get_if_info(); uint32_t tun_addrs[3] = { ifinfo.if_addr, ifinfo.if_addr & ifinfo.netmask, ifinfo.netmask }; DWORD rsize; if(DeviceIoControl(fd, TAP_WINDOWS_IOCTL_CONFIG_TUN, tun_addrs, sizeof(tun_addrs), tun_addrs, sizeof(tun_addrs), &rsize, nullptr)) dout() << "TAP-Windows CONFIG_TUN success: " << ss_ipaddr(tun_addrs[0]) << " " << ss_ipaddr(tun_addrs[1]) << " " << ss_ipaddr(tun_addrs[2]); else eout() << "TAP-Windows CONFIG_TUN FAIL: " << ss_ipaddr(tun_addrs[0]) << " " << ss_ipaddr(tun_addrs[1]) << " " << ss_ipaddr(tun_addrs[2]); // set media status as connected ULONG connected = TRUE; if(DeviceIoControl(fd, TAP_WINDOWS_IOCTL_SET_MEDIA_STATUS, &connected, sizeof(connected), &connected, sizeof(connected), &rsize, nullptr) == FALSE) wout() << "Failed to set TAP-Windows media status to connected"; ULONG ifmtu; if(DeviceIoControl(fd, TAP_WINDOWS_IOCTL_GET_MTU, &ifmtu, sizeof(ifmtu), &ifmtu, sizeof(ifmtu), &rsize, nullptr)) { dout() << "Read mtu from TAP-Windows interface: " << ifmtu; if(ifmtu > MIN_PMTU) mtu = ifmtu; } else { wout() << "Failed to get Tap-Windows MTU, assuming default"; } // [flush ARP cache? -> probably unnecessary with tun, but maybe do it anyway? certainly don't want invalid ARP cache entries for pool addrs from before interface startup] // ... also (may) need to undo whatever configuration (remove addrs from if, routes, etc.) on destruction, CloseHandle on fd, set media status to disconnected, etc. #else check_err((fd = open(snow::conf[snow::CLONE_DEVICE].c_str(), O_RDWR)), "opening tun/tap clone device"); ifreq ifr; memset(&ifr, 0, sizeof(ifr)); // check size manually instead of using strncpy: strncpy fails silently and doesn't null terminate if there is insufficient space if(snow::conf[snow::VIRTUAL_INTERFACE].size() >= IFNAMSIZ) throw check_err_exception("VIRTUAL_INTERFACE name is too long", false); strcpy(ifr.ifr_name, snow::conf[snow::VIRTUAL_INTERFACE].c_str()); check_err(fcntl(fd, F_SETFL, O_NONBLOCK), "setting tuntap socket to non-blocking"); #ifdef __linux__ ifr.ifr_flags = IFF_TUN | IFF_NO_PI; check_err(ioctl(fd, TUNSETIFF, (void*) &ifr), "opening tun/tap interface"); #endif // note: Mac and BSD require a stupid hack to make tun behave properly because they insist on a single destination address being specified // solution is to exclude an address from the address pool and specify it as the destination when configuring the interface // then set a route specifying that address as the gateway for the entire snow subnet so OS will send them all to the tun interface // TODO: write code to do that programmatically for Mac/BSD // existing code seems to work on BSD if you set CLONE_DEVICE to e.g. /dev/tun0 and VIRTUAL_INTERFACE to e.g. tun0 and configure the tun interface manually, e.g.: // # ifconfig tun0 create 172.16.0.1 netmask 255.240.0.0 172.31.255.254 mtu 1419 // # route add -net 172.16.0.0 172.31.255.254 255.240.0.0 // (note: this must be done each time you start the daemon, when the daemon exits the interface remains but configuration is forgotten; same two commands w/o "create") // (note: 'ifconfig tun create' will create next tun# necessary, see if there is any simple way to replicate with API) // doing this programmatically requires call to ioctl passing SIOCSIFPHYADDR with in_aliasreq struct as follows: // ifra_name = "tun[#]" // ifra_addr as local interface addr // ifra_dstaddr as fake addr // ifra_mask as subnet mask // and then adding the route via some call to the BSD routing API csocket sock(AF_INET, SOCK_DGRAM); // need ordinary socket for SIOC[GS]*, can't use tun fd check_err(ioctl(sock.fd(), SIOCGIFFLAGS, (void*) &ifr), "getting tuntap interface flags"); if((ifr.ifr_flags & IFF_UP) == 0) { dout() << "tuntap interface was not up, trying to bring it up"; ifr.ifr_flags |= IFF_UP; // make sure interface is up check_err(ioctl(sock.fd(), SIOCSIFFLAGS, (void*) &ifr), "setting tuntap interface flags"); } else { dout() << "tuntap interface was up"; } // there are two possible ways of doing this which are both supported: either snow launches as root or with CAP_NET_ADMIN and sets these here, // or the interface is persistent and configured ahead of time, in which case only ownership of the interface is necessary // so what we do is check that everything is configured correctly and try to fix it if it isn't // that way everything is fine as long as the interface is correctly preconfigured -or- it isn't but we have rights to fix it in_addr addr, netmask; inet_pton(AF_INET, snow::conf[snow::NATPOOL_NETWORK].c_str(), &addr.s_addr); addr.s_addr = htonl(ntohl(addr.s_addr) + 1); netmask.s_addr = ~htonl((1 << (32 - snow::conf[snow::NATPOOL_NETMASK_BITS])) - 1); ifr.ifr_addr.sa_family = AF_INET; // EADDRNOTAVAIL is returned if no address is assigned which just means we have to assign the address, so then ifr_addr will be zero and not match addr int rv = ioctl(sock.fd(), SIOCGIFADDR, &ifr); if(rv < 0 && errno != EADDRNOTAVAIL) throw check_err_exception("getting tun/tap interface IP address"); sockaddrunion su; su.s = ifr.ifr_addr; dout() << "Got tuntap ifaddr " << ss_ipaddr(su.sa.sin_addr.s_addr); if(su.sa.sin_addr.s_addr != addr.s_addr) { dout() << "Virtual interface IP addr was " << ss_ipaddr(su.sa.sin_addr.s_addr) << ", should be " << ss_ipaddr(addr.s_addr) << ", trying to fix"; su.sa.sin_addr = addr; ifr.ifr_addr = su.s; check_err(ioctl(sock.fd(), SIOCSIFADDR, &ifr), "setting tun/tap interface IP address"); } check_err(ioctl(sock.fd(), SIOCGIFNETMASK, &ifr), "getting tun/tap interface netmask"); su.s = ifr.ifr_addr; dout() << "Got tuntap netmask " << ss_ipaddr(su.sa.sin_addr.s_addr); if(su.sa.sin_addr.s_addr != netmask.s_addr) { dout() << "Virtual interface netmask was " << ss_ipaddr(su.sa.sin_addr.s_addr) << ", should be " << ss_ipaddr(netmask.s_addr) << ", trying to fix"; su.sa.sin_addr = netmask; ifr.ifr_addr = su.s; check_err(ioctl(sock.fd(), SIOCSIFNETMASK, &ifr), "setting tun/tap interface netmask"); } mtu = snow::conf[snow::VIRTUAL_INTERFACE_MTU]; check_err(ioctl(sock.fd(), SIOCGIFMTU, (void*) &ifr), "getting tun/tap interface MTU"); dout() << "Existing tuntap interface MTU: " << ifr.ifr_mtu; if(ifr.ifr_mtu < MIN_PMTU || mtu != static_cast<unsigned>(ifr.ifr_mtu)) { dout() << "Virtual interface mtu was " << ifr.ifr_mtu << ", should be " << mtu << ", trying to fix"; ifr.ifr_mtu = mtu; check_err(ioctl(sock.fd(), SIOCSIFMTU, (void*) &ifr), "setting tun/tap interface MTU"); } iout() << "Virtual interface configured with network " << ss_ipaddr(addr.s_addr&netmask.s_addr) << " netmask " << ss_ipaddr(netmask.s_addr) << " address " << ss_ipaddr(addr.s_addr) << " MTU " << mtu; #endif }
void host_init(char *ifname) { static struct local_host_info host_info; struct sockaddr_in *ina; char buf[1024]; struct ifconf ifc; struct ifreq *ifr; int i, iw_sock; /* Make sure the global "this_host" pointer points to the info structure so that the information can be accessed from outside this function... */ memset(&host_info, '\0', sizeof(struct local_host_info)); this_host = &host_info; /* Find the first wireless interface */ if(ifname != NULL) strcpy(host_info.ifname, ifname); else { iw_sock= socket(AF_INET, SOCK_DGRAM, 0); ifc.ifc_len = sizeof(buf); ifc.ifc_buf = buf; if(ioctl(iw_sock, SIOCGIFCONF, &ifc) < 0) { fprintf(stderr, "Could not get wireless info\n"); exit(-1); } ifr = ifc.ifc_req; for(i = ifc.ifc_len / sizeof(struct ifreq); i >= 0; i--, ifr++) { struct iwreq req; strcpy(req.ifr_name, ifr->ifr_name); if (ioctl(iw_sock, SIOCGIWNAME, &req) >= 0) { strcpy(host_info.ifname, ifr->ifr_name); break; } } close(iw_sock); /* Did we find a wireless interface? */ if(host_info.ifname[0] == '\0') { fprintf(stderr, "Could not find a wireless interface!\n"); fprintf(stderr, "Use -i <interface> to override...\n"); exit(-1); } } /* Load required kernel modules */ load_modules(host_info.ifname); /* Get IP-address of interface... */ ina = get_if_info(host_info.ifname, SIOCGIFADDR); if(ina == NULL) exit(-1); /* Remember our host IP address... */ host_info.ipaddr = ntohl(ina->sin_addr.s_addr); /* printf("Address of interface %s is %s\n", host_info.ifname, */ /* ip_to_str(host_info.ipaddr)); */ /* Get netmask of interface... */ ina = get_if_info(host_info.ifname, SIOCGIFNETMASK); if(ina == NULL) exit(-1); /* Remember the netmask */ host_info.netmask = ntohl(ina->sin_addr.s_addr); /* printf("Netmask of interface %s is %s\n", host_info.ifname, */ /* ip_to_str(host_info.netmask)); */ ina = get_if_info(host_info.ifname, SIOCGIFBRDADDR); if(ina == NULL) exit(-1); host_info.broadcast = ntohl(ina->sin_addr.s_addr); /* printf("Broadcast address is %s\n", ip_to_str(host_info.broadcast)); */ /* Enable IP forwarding and set other kernel options... */ if(set_kernel_options(host_info.ifname) < 0) { fprintf(stderr, "Could not set kernel options!\n"); exit(-1); } /* Add broadcast route (255.255.255.255) */ k_add_rte(AODV_BROADCAST, 0, 0, 0); /* Intitialize the local sequence number an flood_id to zero */ host_info.seqno = 0; host_info.flood_id = 0; }
static void do_show_dev(int argc, char *argv[]) { int option; char *dev = NULL; boolean_t s_arg = B_FALSE; boolean_t i_arg = B_FALSE; uint32_t interval = 0; show_mac_state_t state; char *endp = NULL; state.ms_parseable = B_FALSE; opterr = 0; while ((option = getopt_long(argc, argv, ":psi:", longopts, NULL)) != -1) { switch (option) { case 'p': state.ms_parseable = B_TRUE; break; case 's': if (s_arg) { (void) fprintf(stderr, gettext( "%s: the option -s cannot be specified " "more than once\n"), progname); usage(); } s_arg = B_TRUE; break; case 'i': if (i_arg) { (void) fprintf(stderr, gettext( "%s: the option -i cannot be specified " "more than once\n"), progname); usage(); } i_arg = B_TRUE; errno = 0; interval = (int)strtol(optarg, &endp, 10); if (errno != 0 || interval == 0 || *endp != '\0') { (void) fprintf(stderr, gettext("%s: invalid interval value" " '%d'\n"), progname, interval); exit(1); } break; case ':': (void) fprintf(stderr, gettext("%s: option requires a value '-%c'\n"), progname, optopt); exit(1); /*NOTREACHED*/ case '?': default: (void) fprintf(stderr, gettext("%s: unrecognized option '-%c'\n"), progname, optopt); exit(1); } } if (i_arg && !s_arg) { (void) fprintf(stderr, gettext("%s: the option -i " "can be used only with -s\n"), progname); usage(); } /* get dev name (optional last argument) */ if (optind == (argc-1)) dev = argv[optind]; else if (optind != argc) usage(); if (dev != NULL) { int index; char drv[LIFNAMSIZ]; dladm_attr_t dlattr; boolean_t legacy; /* * Check for invalid devices. * aggregations and vlans are not considered devices. */ if (strncmp(dev, "aggr", 4) == 0 || dlpi_if_parse(dev, drv, &index) < 0 || index >= 1000 || get_if_info(dev, &dlattr, &legacy) < 0) { (void) fprintf(stderr, gettext("%s: invalid device '%s'\n"), progname, dev); exit(1); } } if (s_arg) { dev_stats(dev, interval); return; } if (dev == NULL) (void) macadm_walk(show_dev, &state, B_TRUE); else show_dev(&state, dev); }
/* * check_ip * check if our ip own by other host * though sending arp package * * Input * interface - interface used to send pkg * dst_ip - IP addr which will be check * * Return Value * 0 - if IP addr not been used * 1 - if IP addr has been used * -1 - error */ int check_ip(char *interface/*, in_addr_t dst_ip*/) { int exist = 0; /* is it dst_ip already exist? */ int fd; int optval = 1; unsigned char s_macaddr[6]; /* our MAC addr */ in_addr_t s_ipaddr; /* our IP addr */ arp_pkg_t arp_req; struct sockaddr sa; fd_set read_fds; struct timeval tm; time_t prev_time; int timeout = MAX_TIMEOUT; /* acquire own addr */ if ( get_if_info(interface, s_macaddr, &s_ipaddr) != 0 ) { fprintf(stderr, "Couldn't acquire MAC & IP addr\n"); return -1; } /* open socket */ fd = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP)); if ( fd < 0 ) /* open socket failed */ return -1; if ( setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)) < 0 ) return -1; /* fill the packet header */ memset(&arp_req, 0, sizeof(arp_pkg_t)); memcpy(arp_req.ethhdr.h_dest, MAC_BROADCAST_ADDR, 6); memcpy(arp_req.ethhdr.h_source, s_macaddr, 6); arp_req.ethhdr.h_proto = htons(ETH_P_ARP); /* protocol type */ arp_req.htype = htons(ARPHRD_ETHER); /* hardware type */ arp_req.ptype = htons(ETH_P_IP); /* protocol type (ARP message) */ arp_req.hlen = 6; /* hardware addr length */ arp_req.plen = 4; /* protocol address length */ arp_req.operation = htons(ARPOP_REQUEST); /* ARP op code */ memcpy(arp_req.sHaddr, s_macaddr, 6); /* source MAC addr */ memcpy(arp_req.tInaddr, &s_ipaddr, 4); *(in_addr_t *)arp_req.sInaddr = 0; /* set to 0 for IP conflict dect */ //*(in_addr_t *)arp_req.sInaddr = s_ipaddr; /* source IP addr */ //*(in_addr_t *)arp_req.tInaddr = s_ipaddr; /* target IP addr */ /* send the request */ memset(&sa, 0, sizeof(sa)); strcpy(sa.sa_data, interface); if ( sendto(fd, &arp_req, sizeof(arp_req), 0, &sa, sizeof(sa)) < 0 ) { fprintf(stderr, "NETWORK: send arp request failed\n"); return -1; } /* wait for reply */ tm.tv_usec = 0; time(&prev_time); /* get current time */ while (timeout > 0) { tm.tv_sec = timeout; /* wait for sock ready */ FD_ZERO(&read_fds); FD_SET(fd, &read_fds); if ( select( fd+1, &read_fds, NULL, NULL, &tm) < 0 ) { fprintf(stderr, "NETWORK: error occur while wait for reply\n"); return -1; } /* receive reply */ if ( recv(fd, &arp_req, sizeof(arp_req), 0) < 0 ) { fprintf(stderr, "NETWORK: recv arp request failed\n"); return -1; } /* check if the right reply we expected */ if ( arp_req.operation == htons(ARPOP_REPLY) && /* it's a arp reply */ bcmp(arp_req.tHaddr, s_macaddr, 6) == 0 && /* and it's to us */ /* TODO I think we should check if the sender's mac addr different from us */ *((in_addr_t*)arp_req.sInaddr) == s_ipaddr) { /* and it's from right place */ exist = 1; break; } timeout = timeout - (time(NULL) - prev_time); time(&prev_time); } close(fd); return exist; }
int mcast::mcast_grp::init(const char* addr,const char* iface,int ttl,int loop) { if(!iface) iface=""; mcast_ttl=ttl; mcast_loop=loop; mcast_sin.sin_family=AF_INET; mcast_sin.sin_port=0; mcast_sin.sin_addr.s_addr=INADDR_ANY; #ifdef __FreeBSD__ mcast_sin.sin_len=sizeof(mcast_sin); #endif /* __FreeBSD__ */ mcast_if_sin.sin_family=AF_INET; mcast_if_sin.sin_port=0; mcast_if_sin.sin_addr.s_addr=INADDR_ANY; #ifdef __FreeBSD__ mcast_if_sin.sin_len=sizeof(mcast_if_sin); #endif /* __FreeBSD__ */ *interface=0; char tmp[256]; strcpy(tmp,addr); if(mcast_ttl<1) mcast_ttl=1; char* port=strchr(tmp,':'); if(port) { *port=0; mcast_sin.sin_port=htons(atoi(port+1)); } mcast_sin.sin_addr.s_addr=inet_addr(tmp); int if_by_name=0; for(const char* p=iface;*p;p++) if(isalpha(*p)) { if_by_name=1; break; } if(*iface) { if(if_by_name) { if(verb_fp) fprintf(verb_fp,"find multicast interface address by name '%s'\n",iface); if_info ifi; get_if_info(iface,&ifi); memcpy((char*)&mcast_if_sin,&ifi.if_sin,sizeof(sockaddr_in)); }else mcast_if_sin.sin_addr.s_addr=inet_addr(iface); } if(mcast_if_sin.sin_addr.s_addr==INADDR_ANY) { if(verb_fp) fprintf(verb_fp,"find multicast default interface address\n"); mcast_if_sin.sin_addr=get_best_mcast_if_addr(); } if(verb_fp) { fprintf(verb_fp,"multicast interface address: '%s'\n",mcast_if_sin.sin_addr.s_addr==INADDR_ANY?"any":inet_ntoa(mcast_if_sin.sin_addr)); fprintf(verb_fp,"multicast group address: '%s:%i'\n",inet_ntoa(mcast_sin.sin_addr),ntohs(mcast_sin.sin_port)); } snprintf(interface,sizeof(interface),"%s",inet_ntoa(mcast_if_sin.sin_addr)); return 0; }