int nozzle_set_mtu(nozzle_t nozzle, const int mtu) { int err = 0, savederrno = 0; struct nozzle_ip *tmp_ip; struct ifreq ifr; if (!mtu) { errno = EINVAL; return -1; } savederrno = pthread_mutex_lock(&config_mutex); if (savederrno) { errno = savederrno; return -1; } if (!is_valid_nozzle(nozzle)) { savederrno = EINVAL; err = -1; goto out_clean; } err = nozzle->current_mtu = get_iface_mtu(nozzle); if (err < 0) { savederrno = errno; goto out_clean; } memset(&ifr, 0, sizeof(struct ifreq)); strncpy(ifname, nozzle->name, IFNAMSIZ); ifr.ifr_mtu = mtu; err = ioctl(lib_cfg.ioctlfd, SIOCSIFMTU, &ifr); if (err) { savederrno = errno; goto out_clean; } if ((nozzle->current_mtu < 1280) && (mtu >= 1280)) { tmp_ip = nozzle->ip; while(tmp_ip) { if (tmp_ip->domain == AF_INET6) { err = _set_ip(nozzle, IP_ADD, tmp_ip->ipaddr, tmp_ip->prefix, 0); if (err) { savederrno = errno; err = -1; goto out_clean; } } tmp_ip = tmp_ip->next; } } out_clean: pthread_mutex_unlock(&config_mutex); errno = savederrno; return err; }
int nozzle_del_ip(nozzle_t nozzle, const char *ipaddr, const char *prefix) { int err = 0, savederrno = 0; int found = 0; struct nozzle_ip *ip = NULL, *ip_prev = NULL; if ((!ipaddr) || (!prefix)) { errno = EINVAL; return -1; } savederrno = pthread_mutex_lock(&config_mutex); if (savederrno) { errno = savederrno; return -1; } if (!is_valid_nozzle(nozzle)) { savederrno = EINVAL; err = -1; goto out_clean; } found = find_ip(nozzle, ipaddr, prefix, &ip, &ip_prev); if (!found) { goto out_clean; } /* * if user asks for an IPv6 address, but MTU < 1280 * the IP might not be configured on the interface and we only need to * remove it from our internal database */ if ((ip->domain == AF_INET6) && (get_iface_mtu(nozzle) < 1280)) { err = 0; } else { err = _set_ip(nozzle, IP_DEL, ipaddr, prefix, 0); savederrno = errno; } if (!err) { if (ip == ip_prev) { nozzle->ip = ip->next; } else { ip_prev->next = ip->next; } free(ip); } out_clean: pthread_mutex_unlock(&config_mutex); errno = savederrno; return err; }
int nozzle_get_mtu(const nozzle_t nozzle) { int err = 0, savederrno = 0; savederrno = pthread_mutex_lock(&config_mutex); if (savederrno) { errno = savederrno; return -1; } if (!is_valid_nozzle(nozzle)) { savederrno = EINVAL; err = -1; goto out_clean; } err = get_iface_mtu(nozzle); savederrno = errno; out_clean: pthread_mutex_unlock(&config_mutex); errno = savederrno; return err; }
void get_hw_info(void) { u_long ip; struct libnet_ether_addr *ea; bpf_u_int32 network, netmask; char pcap_errbuf[PCAP_ERRBUF_SIZE]; /* dont touch the interface reading from file */ if (!GBL_LNET->lnet || GBL_OPTIONS->read) { DEBUG_MSG("get_hw_info: skipping... (not initialized)"); return; } DEBUG_MSG("get_hw_info"); /* get the ip address */ ip = libnet_get_ipaddr4(GBL_LNET->lnet); /* if ip is equal to -1 there was an error */ if (ip != (u_long)~0) { /* the interface has an ip address */ if (ip != 0) GBL_IFACE->configured = 1; /* save the ip address */ ip_addr_init(&GBL_IFACE->ip, AF_INET, (char *)&ip); if (pcap_lookupnet(GBL_OPTIONS->iface, &network, &netmask, pcap_errbuf) == -1) ERROR_MSG("%s", pcap_errbuf); ip_addr_init(&GBL_IFACE->network, AF_INET, (char *)&network); /* the user has specified a different netmask, use it */ if (GBL_OPTIONS->netmask) { struct in_addr net; /* sanity check */ if (inet_aton(GBL_OPTIONS->netmask, &net) == 0) FATAL_ERROR("Invalid netmask %s", GBL_OPTIONS->netmask); ip_addr_init(&GBL_IFACE->netmask, AF_INET, (char *)&net); } else ip_addr_init(&GBL_IFACE->netmask, AF_INET, (char *)&netmask); } else DEBUG_MSG("get_hw_info: NO IP on %s", GBL_OPTIONS->iface); /* get the mac address */ ea = libnet_get_hwaddr(GBL_LNET->lnet); if (ea != NULL) memcpy(GBL_IFACE->mac, ea->ether_addr_octet, MEDIA_ADDR_LEN); else DEBUG_MSG("get_hw_info: NO MAC for %s", GBL_OPTIONS->iface); /* get the MTU */ GBL_IFACE->mtu = get_iface_mtu(GBL_OPTIONS->iface); /* check the mtu */ if (GBL_IFACE->mtu > INT16_MAX) FATAL_ERROR("MTU too large"); USER_MSG("%6s ->\t%s ", GBL_OPTIONS->iface, mac_addr_ntoa(GBL_IFACE->mac, pcap_errbuf)); USER_MSG("%16s ", ip_addr_ntoa(&GBL_IFACE->ip, pcap_errbuf)); USER_MSG("%16s\n\n", ip_addr_ntoa(&GBL_IFACE->netmask, pcap_errbuf) ); /* if not in bridged sniffing, return */ if (GBL_SNIFF->type != SM_BRIDGED) return; ip = libnet_get_ipaddr4(GBL_LNET->lnet_bridge); /* if ip is equal to -1 there was an error */ if (ip != (u_long)~0) { ip_addr_init(&GBL_BRIDGE->ip, AF_INET, (char *)&ip); if (pcap_lookupnet(GBL_OPTIONS->iface_bridge, &network, &netmask, pcap_errbuf) == -1) ERROR_MSG("%s", pcap_errbuf); ip_addr_init(&GBL_BRIDGE->network, AF_INET, (char *)&network); ip_addr_init(&GBL_BRIDGE->netmask, AF_INET, (char *)&netmask); } else DEBUG_MSG("get_hw_info: NO IP on %s", GBL_OPTIONS->iface_bridge); ea = libnet_get_hwaddr(GBL_LNET->lnet_bridge); if (ea != NULL) memcpy(GBL_BRIDGE->mac, ea->ether_addr_octet, MEDIA_ADDR_LEN); else DEBUG_MSG("get_hw_info: NO MAC for %s", GBL_OPTIONS->iface_bridge); /* get the MTU */ GBL_BRIDGE->mtu = get_iface_mtu(GBL_OPTIONS->iface_bridge); if (GBL_BRIDGE->mtu > INT16_MAX) FATAL_ERROR("MTU too large"); USER_MSG("%6s ->\t%s ", GBL_OPTIONS->iface_bridge, mac_addr_ntoa(GBL_BRIDGE->mac, pcap_errbuf)); USER_MSG("%16s ", ip_addr_ntoa(&GBL_BRIDGE->ip, pcap_errbuf)); USER_MSG("%16s\n\n", ip_addr_ntoa(&GBL_BRIDGE->netmask, pcap_errbuf) ); /* some sanity checks */ if (GBL_BRIDGE->mtu != GBL_IFACE->mtu) FATAL_ERROR("The two interfaces must have the same MTU."); if (!memcmp(GBL_BRIDGE->mac, GBL_IFACE->mac, MEDIA_ADDR_LEN)) FATAL_ERROR("The two bridged interfaces must be phisically different"); }
nozzle_t nozzle_open(char *devname, size_t devname_size, const char *updownpath) { int savederrno = 0; nozzle_t nozzle = NULL; char *temp_mac = NULL; #ifdef KNET_LINUX struct ifreq ifr; #endif #ifdef KNET_BSD uint16_t i; long int nozzlenum = 0; char curnozzle[IFNAMSIZ]; #endif if (devname == NULL) { errno = EINVAL; return NULL; } if (devname_size < IFNAMSIZ) { errno = EINVAL; return NULL; } if (strlen(devname) > IFNAMSIZ) { errno = E2BIG; return NULL; } #ifdef KNET_BSD /* * BSD does not support named devices like Linux * but it is possible to force a nozzleX device number * where X is 0 to 255. */ if (strlen(devname)) { if (strncmp(devname, "tap", 3)) { errno = EINVAL; return NULL; } errno = 0; nozzlenum = strtol(devname+3, NULL, 10); if (errno) { errno = EINVAL; return NULL; } if ((nozzlenum < 0) || (nozzlenum > 255)) { errno = EINVAL; return NULL; } } #endif if (updownpath) { /* only absolute paths */ if (updownpath[0] != '/') { errno = EINVAL; return NULL; } if (strlen(updownpath) >= UPDOWN_PATH_MAX) { errno = E2BIG; return NULL; } } savederrno = pthread_mutex_lock(&config_mutex); if (savederrno) { errno = savederrno; return NULL; } if (!lib_init) { lib_cfg.head = NULL; #ifdef KNET_LINUX lib_cfg.nlsock = nl_socket_alloc(); if (!lib_cfg.nlsock) { savederrno = errno; goto out_error; } if (nl_connect(lib_cfg.nlsock, NETLINK_ROUTE) < 0) { savederrno = EBUSY; goto out_error; } lib_cfg.ioctlfd = socket(AF_INET, SOCK_STREAM, 0); #endif #ifdef KNET_BSD lib_cfg.ioctlfd = socket(AF_LOCAL, SOCK_DGRAM, 0); #endif if (lib_cfg.ioctlfd < 0) { savederrno = errno; goto out_error; } lib_init = 1; } nozzle = malloc(sizeof(struct nozzle_iface)); if (!nozzle) { savederrno = ENOMEM; goto out_error; } memset(nozzle, 0, sizeof(struct nozzle_iface)); #ifdef KNET_BSD if (!strlen(devname)) { for (i = 0; i < 256; i++) { snprintf(curnozzle, sizeof(curnozzle) - 1, "/dev/tap%u", i); nozzle->fd = open(curnozzle, O_RDWR); savederrno = errno; if (nozzle->fd > 0) { break; } } snprintf(curnozzle, sizeof(curnozzle) -1 , "tap%u", i); } else { snprintf(curnozzle, sizeof(curnozzle) - 1, "/dev/%s", devname); nozzle->fd = open(curnozzle, O_RDWR); savederrno = errno; snprintf(curnozzle, sizeof(curnozzle) - 1, "%s", devname); } if (nozzle->fd < 0) { savederrno = EBUSY; goto out_error; } strncpy(devname, curnozzle, IFNAMSIZ); strncpy(nozzle->name, curnozzle, IFNAMSIZ); #endif #ifdef KNET_LINUX if ((nozzle->fd = open("/dev/net/tun", O_RDWR)) < 0) { savederrno = errno; goto out_error; } memset(&ifr, 0, sizeof(struct ifreq)); memmove(ifname, devname, IFNAMSIZ); ifr.ifr_flags = IFF_TAP | IFF_NO_PI; if (ioctl(nozzle->fd, TUNSETIFF, &ifr) < 0) { savederrno = errno; goto out_error; } if ((strlen(devname) > 0) && (strcmp(devname, ifname) != 0)) { savederrno = EBUSY; goto out_error; } strncpy(devname, ifname, IFNAMSIZ); strncpy(nozzle->name, ifname, IFNAMSIZ); #endif nozzle->default_mtu = get_iface_mtu(nozzle); if (nozzle->default_mtu < 0) { savederrno = errno; goto out_error; } if (get_iface_mac(nozzle, &temp_mac) < 0) { savederrno = errno; goto out_error; } strncpy(nozzle->default_mac, temp_mac, 18); free(temp_mac); if (updownpath) { int len = strlen(updownpath); strcpy(nozzle->updownpath, updownpath); if (nozzle->updownpath[len-1] != '/') { nozzle->updownpath[len] = '/'; } nozzle->hasupdown = 1; } nozzle->next = lib_cfg.head; lib_cfg.head = nozzle; pthread_mutex_unlock(&config_mutex); errno = savederrno; return nozzle; out_error: destroy_iface(nozzle); pthread_mutex_unlock(&config_mutex); errno = savederrno; return NULL; }
int nozzle_add_ip(nozzle_t nozzle, const char *ipaddr, const char *prefix) { int err = 0, savederrno = 0; int found = 0; struct nozzle_ip *ip = NULL, *ip_prev = NULL, *ip_last = NULL; int secondary = 0; if ((!ipaddr) || (!prefix)) { errno = EINVAL; return -1; } savederrno = pthread_mutex_lock(&config_mutex); if (savederrno) { errno = savederrno; return -1; } if (!is_valid_nozzle(nozzle)) { savederrno = EINVAL; err = -1; goto out_clean; } found = find_ip(nozzle, ipaddr, prefix, &ip, &ip_prev); if (found) { goto out_clean; } ip = malloc(sizeof(struct nozzle_ip)); if (!ip) { savederrno = errno; err = -1 ; goto out_clean; } memset(ip, 0, sizeof(struct nozzle_ip)); strncpy(ip->ipaddr, ipaddr, IPADDR_CHAR_MAX); strncpy(ip->prefix, prefix, PREFIX_CHAR_MAX); if (!strchr(ip->ipaddr, ':')) { ip->domain = AF_INET; } else { ip->domain = AF_INET6; } /* * if user asks for an IPv6 address, but MTU < 1280 * store the IP and bring it up later if and when MTU > 1280 */ if ((ip->domain == AF_INET6) && (get_iface_mtu(nozzle) < 1280)) { err = 0; } else { if (nozzle->ip) { secondary = 1; } err = _set_ip(nozzle, IP_ADD, ipaddr, prefix, secondary); savederrno = errno; } if (err) { free(ip); goto out_clean; } if (nozzle->ip) { ip_last = nozzle->ip; while (ip_last->next != NULL) { ip_last = ip_last->next; } ip_last->next = ip; } else { nozzle->ip = ip; } out_clean: pthread_mutex_unlock(&config_mutex); errno = savederrno; return err; }