int main(int argc, char *argv[]) { int sd, status, bytes; struct ifreq *ifr; /* Will hold interface information later */ struct sockaddr_ll device; /* Specifies the interface to use for sending packets */ struct pcap_pkthdr *pkthdr; /* Will store packet metadata */ struct arp_hdr *recv_arp; /* Will store a received ARP msg */ const unsigned char *packet=NULL; /* Buffer for received packets */ bpf_u_int32 netaddr=0, mask=0; /* To Store network address and netmask */ struct bpf_program filter; /* Place to store the BPF filter program */ char errbuf[PCAP_ERRBUF_SIZE]; /* Error buffer */ pcap_t *descr = NULL; /* Network interface handler */ char *my_mac = malloc(6); /* Our MAC address to be used in eth_hdr and arp_hdr*/ char *interface = malloc(40); /* Interface name, provided by the user */ char *spoofed_IP = malloc(4); /* IP to be spoofed, provided by the user */ char *msg = malloc(sizeof(struct arp_hdr) + sizeof(struct eth_hdr)); /* Will hold the final message */ uint8_t *spoofed_IP_network = malloc(4); /* IP to be spoofed in network byte order */ strcpy(interface, argv[1]); /*Copy user input*/ strcpy(spoofed_IP,argv[2]); /* Get spoofed IP network byte order */ if ((status = inet_pton (AF_INET, spoofed_IP, spoofed_IP_network)) != 1) { fprintf (stderr, "inet_pton() failed for source IP address.\nError message: %s", strerror (status)); exit (EXIT_FAILURE); } ifr = populateIfreq(interface); /* Get interface information */ memset (&device, 0, sizeof (device)); /* Get the interface index */ if ((device.sll_ifindex = if_nametoindex (interface)) == 0) { perror ("if_nametoindex() failed to obtain interface index "); exit (EXIT_FAILURE); } /* Get our MAC address */ memcpy(my_mac,ifr->ifr_hwaddr.sa_data,6); /* Open network device for packet capture */ if ((descr = pcap_open_live(interface, 2048, 0, 512, errbuf))==NULL){ fprintf(stderr, "ERROR: %s\n", errbuf); exit(1); } /* Look up info from the capture device. */ if( pcap_lookupnet( interface , &netaddr, &mask, errbuf) == -1){ fprintf(stderr, "ERROR: %s\n", errbuf); exit(1); } /* Compiles the filter expression into a BPF filter program */ if ( pcap_compile(descr, &filter, "arp", 1, mask) == -1){ fprintf(stderr, "ERROR: %s\n", pcap_geterr(descr) ); exit(1); } /* Load the filter program into the packet capture device. */ if (pcap_setfilter(descr,&filter) == -1){ fprintf(stderr, "ERROR: %s\n", pcap_geterr(descr) ); exit(1); } signal(SIGINT, &sig_handler); /* Open the socket to send */ if ((sd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0) { printf("%s\n",strerror(errno)); return(1); } /* Main loop */ while(g_running){ int status = pcap_next_ex(descr,&pkthdr, &packet); if( status == -1){ pcap_perror(descr,"ERROR: "); } /* 0 means we timed out, so just repeat */ if(status == 0){ continue; } /* Cast the incoming packet into our arp_hdr struct. Skip the eth_hdr */ /* NOTE that contents in recv_arp are still in network byte order! */ recv_arp = (struct arp_hdr *)(packet+sizeof(struct eth_hdr)); /* If the message is an ARP request (opcode 1), do stuff..*/ if(ntohs(recv_arp->opcode) != 1) continue; printf("received arp request\n"); /* Set up ethernet and ARP hdr for our ARP reply */ struct eth_hdr *eth_rsp = setupEthHdr(recv_arp->src_mac,my_mac); struct arp_hdr *arp_rsp = setupArpHdr(my_mac,spoofed_IP_network,recv_arp->src_mac, recv_arp->src_ip); /* Paste them together into our final message */ memcpy(msg,eth_rsp,sizeof(struct eth_hdr)); memcpy(msg + sizeof(struct eth_hdr), arp_rsp, sizeof(struct arp_hdr)); /* Send */ if ((bytes = sendto (sd, msg, ETH_HDRLEN + ARP_HDRLEN, 0, (struct sockaddr *) &device, sizeof (device))) <= 0) { perror ("sendto() failed"); exit (EXIT_FAILURE); } free(eth_rsp); free(arp_rsp); } free(my_mac); free(interface); free(spoofed_IP); free(spoofed_IP_network); free(msg); free(ifr); return(0); }
static int _intf_get_noalias(intf_t *intf, struct intf_entry *entry) { struct ifreq ifr; /* Get interface index. */ entry->intf_index = if_nametoindex(entry->intf_name); if (entry->intf_index == 0) return (-1); strlcpy(ifr.ifr_name, entry->intf_name, sizeof(ifr.ifr_name)); /* Get interface flags. */ if (ioctl(intf->fd, SIOCGIFFLAGS, &ifr) < 0) return (-1); entry->intf_flags = intf_iff_to_flags(ifr.ifr_flags); _intf_set_type(entry); /* Get interface MTU. */ #ifdef SIOCGIFMTU if (ioctl(intf->fd, SIOCGIFMTU, &ifr) < 0) #endif return (-1); entry->intf_mtu = ifr.ifr_mtu; entry->intf_addr.addr_type = entry->intf_dst_addr.addr_type = entry->intf_link_addr.addr_type = ADDR_TYPE_NONE; /* Get primary interface address. */ if (ioctl(intf->fd, SIOCGIFADDR, &ifr) == 0) { addr_ston(&ifr.ifr_addr, &entry->intf_addr); if (ioctl(intf->fd, SIOCGIFNETMASK, &ifr) < 0) return (-1); addr_stob(&ifr.ifr_addr, &entry->intf_addr.addr_bits); } /* Get other addresses. */ if (entry->intf_type == INTF_TYPE_TUN) { if (ioctl(intf->fd, SIOCGIFDSTADDR, &ifr) == 0) { if (addr_ston(&ifr.ifr_addr, &entry->intf_dst_addr) < 0) return (-1); } } else if (entry->intf_type == INTF_TYPE_ETH) { #if defined(SIOCGIFHWADDR) if (ioctl(intf->fd, SIOCGIFHWADDR, &ifr) < 0) return (-1); if (addr_ston(&ifr.ifr_addr, &entry->intf_link_addr) < 0) return (-1); #elif defined(SIOCRPHYSADDR) /* Tru64 */ struct ifdevea *ifd = (struct ifdevea *)𝔦 /* XXX */ if (ioctl(intf->fd, SIOCRPHYSADDR, ifd) < 0) return (-1); addr_pack(&entry->intf_link_addr, ADDR_TYPE_ETH, ETH_ADDR_BITS, ifd->current_pa, ETH_ADDR_LEN); #else eth_t *eth; if ((eth = eth_open(entry->intf_name)) != NULL) { if (!eth_get(eth, &entry->intf_link_addr.addr_eth)) { entry->intf_link_addr.addr_type = ADDR_TYPE_ETH; entry->intf_link_addr.addr_bits = ETH_ADDR_BITS; } eth_close(eth); } #endif } return (0); }
void ProcessInterfaceWatchNotify(int s) { char buffer[4096]; struct iovec iov; struct msghdr hdr; struct nlmsghdr *nlhdr; struct ifinfomsg *ifi; struct ifaddrmsg *ifa; int len; struct rtattr *rth; // int rtl; unsigned int ext_if_name_index = 0; iov.iov_base = buffer; iov.iov_len = sizeof(buffer); memset(&hdr, 0, sizeof(hdr)); hdr.msg_iov = &iov; hdr.msg_iovlen = 1; len = recvmsg(s, &hdr, 0); if (len < 0) { syslog(LOG_ERR, "recvmsg(s, &hdr, 0): %m"); return; } if(ext_if_name) { ext_if_name_index = if_nametoindex(ext_if_name); } for (nlhdr = (struct nlmsghdr *) buffer; NLMSG_OK (nlhdr, (unsigned int)len); nlhdr = NLMSG_NEXT (nlhdr, len)) { if (nlhdr->nlmsg_type == NLMSG_DONE) break; switch(nlhdr->nlmsg_type) { case RTM_DELLINK: ifi = (struct ifinfomsg *) NLMSG_DATA(nlhdr); /*if (ProcessInterfaceDown(ifi) < 0) syslog(LOG_ERR, "ProcessInterfaceDown(ifi) failed");*/ break; case RTM_NEWLINK: ifi = (struct ifinfomsg *) NLMSG_DATA(nlhdr); /*if (ProcessInterfaceUp(ifi) < 0) syslog(LOG_ERR, "ProcessInterfaceUp(ifi) failed");*/ break; case RTM_NEWADDR: /* see /usr/include/linux/netlink.h * and /usr/include/linux/rtnetlink.h */ ifa = (struct ifaddrmsg *) NLMSG_DATA(nlhdr); syslog(LOG_DEBUG, "ProcessInterfaceWatchNotify RTM_NEWADDR"); for(rth = IFA_RTA(ifa), rtl = IFA_PAYLOAD(nlhdr); rtl && RTA_OK(rth, rtl); rth = RTA_NEXT(rth, rtl)) { syslog(LOG_DEBUG, " - %u - %s type=%d", ifa->ifa_index, inet_ntoa(*((struct in_addr *)RTA_DATA(rth))), rth->rta_type); } if(ifa->ifa_index == ext_if_name_index) { should_send_public_address_change_notif = 1; } break; case RTM_DELADDR: ifa = (struct ifaddrmsg *) NLMSG_DATA(nlhdr); syslog(LOG_DEBUG, "ProcessInterfaceWatchNotify RTM_DELADDR"); if(ifa->ifa_index == ext_if_name_index) { should_send_public_address_change_notif = 1; } break; default: syslog(LOG_DEBUG, "ProcessInterfaceWatchNotify type %d ignored", nlhdr->nlmsg_type); } } }
static int execute_nl_interface_cmd(const char *iface, enum nl80211_iftype type, uint8_t cmd) { struct nl_cb *cb; struct nl_msg *msg; int devidx = 0; int err; int add_interface = (cmd == NL80211_CMD_NEW_INTERFACE); if (add_interface) { devidx = phy_lookup(); } else { devidx = if_nametoindex(iface); if (devidx == 0) { ALOGE("failed to translate ifname to idx"); return -errno; } } msg = nlmsg_alloc(); if (!msg) { ALOGE("failed to allocate netlink message"); return 2; } cb = nl_cb_alloc(NL_CB_DEFAULT); if (!cb) { ALOGE("failed to allocate netlink callbacks"); err = 2; goto out_free_msg; } genlmsg_put(msg, 0, 0, genl_family_get_id(nl80211), 0, 0, cmd, 0); if (add_interface) { NLA_PUT_U32(msg, NL80211_ATTR_WIPHY, devidx); } else { NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, devidx); } if (add_interface) { NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, iface); NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, type); } err = nl_send_auto_complete(nl_soc, msg); if (err < 0) goto out; err = 1; nl_cb_err(cb, NL_CB_CUSTOM, nl_error_handler, &err); nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, nl_finish_handler, &err); nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, nl_ack_handler, &err); while (err > 0) nl_recvmsgs(nl_soc, cb); out: nl_cb_put(cb); out_free_msg: nlmsg_free(msg); return err; nla_put_failure: ALOGW("building message failed"); return 2; }
static int gaih_inet(const char *name, const struct gaih_service *service, const struct addrinfo *req, struct addrinfo **pai) { struct gaih_servtuple nullserv; const struct gaih_typeproto *tp; struct gaih_servtuple *st; struct gaih_addrtuple *at; int rc; int v4mapped = (req->ai_family == PF_UNSPEC || req->ai_family == PF_INET6) && (req->ai_flags & AI_V4MAPPED); unsigned seen = 0; if (req->ai_flags & AI_ADDRCONFIG) { /* "seen" is only used when AI_ADDRCONFIG is specified. Avoid unnecessary call to __check_pf() otherwise since it can be costly especially when RSBAC-Net is enabled. */ seen = __check_pf(); } memset(&nullserv, 0, sizeof(nullserv)); tp = gaih_inet_typeproto; if (req->ai_protocol || req->ai_socktype) { ++tp; while (tp->name[0]) { if ((req->ai_socktype == 0 || req->ai_socktype == tp->socktype) && (req->ai_protocol == 0 || req->ai_protocol == tp->protocol || (tp->protoflag & GAI_PROTO_PROTOANY)) ) { goto found; } ++tp; } if (req->ai_socktype) return (GAIH_OKIFUNSPEC | -EAI_SOCKTYPE); return (GAIH_OKIFUNSPEC | -EAI_SERVICE); found: ; } st = &nullserv; if (service != NULL) { if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0) return (GAIH_OKIFUNSPEC | -EAI_SERVICE); if (service->num < 0) { if (tp->name[0]) { st = alloca(sizeof(struct gaih_servtuple)); rc = gaih_inet_serv(service->name, tp, req, st); if (rc) return rc; } else { struct gaih_servtuple **pst = &st; for (tp++; tp->name[0]; tp++) { struct gaih_servtuple *newp; if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0) continue; if (req->ai_socktype != 0 && req->ai_socktype != tp->socktype) continue; if (req->ai_protocol != 0 && !(tp->protoflag & GAI_PROTO_PROTOANY) && req->ai_protocol != tp->protocol) continue; newp = alloca(sizeof(struct gaih_servtuple)); rc = gaih_inet_serv(service->name, tp, req, newp); if (rc) { if (rc & GAIH_OKIFUNSPEC) continue; return rc; } *pst = newp; pst = &(newp->next); } if (st == &nullserv) return (GAIH_OKIFUNSPEC | -EAI_SERVICE); } } else { st = alloca(sizeof(struct gaih_servtuple)); st->next = NULL; st->socktype = tp->socktype; st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY) ? req->ai_protocol : tp->protocol); st->port = htons(service->num); } } else if (req->ai_socktype || req->ai_protocol) { st = alloca(sizeof(struct gaih_servtuple)); st->next = NULL; st->socktype = tp->socktype; st->protocol = ((tp->protoflag & GAI_PROTO_PROTOANY) ? req->ai_protocol : tp->protocol); st->port = 0; } else { /* * Neither socket type nor protocol is set. Return all socket types * we know about. */ struct gaih_servtuple **lastp = &st; for (++tp; tp->name[0]; ++tp) { struct gaih_servtuple *newp; newp = alloca(sizeof(struct gaih_servtuple)); newp->next = NULL; newp->socktype = tp->socktype; newp->protocol = tp->protocol; newp->port = 0; *lastp = newp; lastp = &newp->next; } } at = NULL; if (name != NULL) { at = alloca(sizeof(struct gaih_addrtuple)); at->family = AF_UNSPEC; at->scopeid = 0; at->next = NULL; if (inet_pton(AF_INET, name, at->addr) > 0) { if (req->ai_family != AF_UNSPEC && req->ai_family != AF_INET && !v4mapped) return -EAI_FAMILY; at->family = AF_INET; } #if defined __UCLIBC_HAS_IPV6__ if (at->family == AF_UNSPEC) { char *namebuf = strdupa(name); char *scope_delim; scope_delim = strchr(namebuf, SCOPE_DELIMITER); if (scope_delim != NULL) *scope_delim = '\0'; if (inet_pton(AF_INET6, namebuf, at->addr) > 0) { if (req->ai_family != AF_UNSPEC && req->ai_family != AF_INET6) return -EAI_FAMILY; at->family = AF_INET6; if (scope_delim != NULL) { int try_numericscope = 0; uint32_t *a32 = (uint32_t*)at->addr; if (IN6_IS_ADDR_LINKLOCAL(a32) || IN6_IS_ADDR_MC_LINKLOCAL(at->addr)) { at->scopeid = if_nametoindex(scope_delim + 1); if (at->scopeid == 0) try_numericscope = 1; } else try_numericscope = 1; if (try_numericscope != 0) { char *end; assert(sizeof(uint32_t) <= sizeof(unsigned long)); at->scopeid = (uint32_t)strtoul(scope_delim + 1, &end, 10); if (*end != '\0') return (GAIH_OKIFUNSPEC | -EAI_NONAME); } } } } #endif if (at->family == AF_UNSPEC && !(req->ai_flags & AI_NUMERICHOST)) { struct hostent *h; struct gaih_addrtuple **pat = &at; int no_data = 0; int no_inet6_data; /* * If we are looking for both IPv4 and IPv6 address we don't want * the lookup functions to automatically promote IPv4 addresses to * IPv6 addresses. */ #if defined __UCLIBC_HAS_IPV6__ if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6) if (!(req->ai_flags & AI_ADDRCONFIG) || (seen & SEEN_IPV6)) gethosts(AF_INET6, struct in6_addr); #endif no_inet6_data = no_data; if (req->ai_family == AF_INET || (!v4mapped && req->ai_family == AF_UNSPEC) || (v4mapped && (no_inet6_data != 0 || (req->ai_flags & AI_ALL))) ) { if (!(req->ai_flags & AI_ADDRCONFIG) || (seen & SEEN_IPV4)) gethosts(AF_INET, struct in_addr); } if (no_data != 0 && no_inet6_data != 0) { /* If both requests timed out report this. */ if (no_data == EAI_AGAIN && no_inet6_data == EAI_AGAIN) return -EAI_AGAIN; /* * We made requests but they turned out no data. * The name is known, though. */ return (GAIH_OKIFUNSPEC | -EAI_AGAIN); } } if (at->family == AF_UNSPEC) return (GAIH_OKIFUNSPEC | -EAI_NONAME); } else { struct gaih_addrtuple *atr; atr = at = alloca(sizeof(struct gaih_addrtuple)); memset(at, '\0', sizeof(struct gaih_addrtuple)); if (req->ai_family == 0) { at->next = alloca(sizeof(struct gaih_addrtuple)); memset(at->next, '\0', sizeof(struct gaih_addrtuple)); } #if defined __UCLIBC_HAS_IPV6__ if (req->ai_family == 0 || req->ai_family == AF_INET6) { at->family = AF_INET6; if ((req->ai_flags & AI_PASSIVE) == 0) memcpy(at->addr, &in6addr_loopback, sizeof(struct in6_addr)); atr = at->next; } #endif if (req->ai_family == 0 || req->ai_family == AF_INET) { atr->family = AF_INET; if ((req->ai_flags & AI_PASSIVE) == 0) { uint32_t *a = (uint32_t*)atr->addr; *a = htonl(INADDR_LOOPBACK); } } } if (pai == NULL) return 0; { const char *c = NULL; struct gaih_servtuple *st2; struct gaih_addrtuple *at2 = at; size_t socklen, namelen; sa_family_t family; /* * buffer is the size of an unformatted IPv6 address in * printable format. */ char buffer[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")]; while (at2 != NULL) { c = inet_ntop(at2->family, at2->addr, buffer, sizeof(buffer)); if (c) { namelen = strlen(c) + 1; } else if (req->ai_flags & AI_CANONNAME) { struct hostent *h = NULL; int herrno; struct hostent th; size_t tmpbuflen = 512; char *tmpbuf; /* Hint says numeric, but address is not */ if (req->ai_flags & AI_NUMERICHOST) return -EAI_NONAME; do { tmpbuflen *= 2; tmpbuf = alloca(tmpbuflen); rc = gethostbyaddr_r(at2->addr, #ifdef __UCLIBC_HAS_IPV6__ ((at2->family == AF_INET6) ? sizeof(struct in6_addr) : sizeof(struct in_addr)), #else sizeof(struct in_addr), #endif at2->family, &th, tmpbuf, tmpbuflen, &h, &herrno); } while (rc == ERANGE && herrno == NETDB_INTERNAL); if (rc != 0 && herrno == NETDB_INTERNAL) { __set_h_errno(herrno); return -EAI_SYSTEM; } if (h != NULL) c = h->h_name; if (c == NULL) return (GAIH_OKIFUNSPEC | -EAI_NONAME); namelen = strlen(c) + 1; } else namelen = 0; #if defined __UCLIBC_HAS_IPV6__ if (at2->family == AF_INET6 || v4mapped) { family = AF_INET6; socklen = sizeof(struct sockaddr_in6); } #endif #if defined __UCLIBC_HAS_IPV4__ && defined __UCLIBC_HAS_IPV6__ else #endif #if defined __UCLIBC_HAS_IPV4__ { family = AF_INET; socklen = sizeof(struct sockaddr_in); } #endif for (st2 = st; st2 != NULL; st2 = st2->next) { if (req->ai_flags & AI_ADDRCONFIG) { if (family == AF_INET && !(seen & SEEN_IPV4)) break; #if defined __UCLIBC_HAS_IPV6__ else if (family == AF_INET6 && !(seen & SEEN_IPV6)) break; #endif } *pai = malloc(sizeof(struct addrinfo) + socklen + namelen); if (*pai == NULL) return -EAI_MEMORY; (*pai)->ai_flags = req->ai_flags; (*pai)->ai_family = family; (*pai)->ai_socktype = st2->socktype; (*pai)->ai_protocol = st2->protocol; (*pai)->ai_addrlen = socklen; (*pai)->ai_addr = (void *) (*pai) + sizeof(struct addrinfo); #if defined SALEN (*pai)->ai_addr->sa_len = socklen; #endif (*pai)->ai_addr->sa_family = family; #if defined __UCLIBC_HAS_IPV6__ if (family == AF_INET6) { struct sockaddr_in6 *sin6p = (struct sockaddr_in6 *) (*pai)->ai_addr; sin6p->sin6_flowinfo = 0; if (at2->family == AF_INET6) { memcpy(&sin6p->sin6_addr, at2->addr, sizeof(struct in6_addr)); } else { sin6p->sin6_addr.s6_addr32[0] = 0; sin6p->sin6_addr.s6_addr32[1] = 0; sin6p->sin6_addr.s6_addr32[2] = htonl(0x0000ffff); memcpy(&sin6p->sin6_addr.s6_addr32[3], at2->addr, sizeof(sin6p->sin6_addr.s6_addr32[3])); } sin6p->sin6_port = st2->port; sin6p->sin6_scope_id = at2->scopeid; } #endif #if defined __UCLIBC_HAS_IPV4__ && defined __UCLIBC_HAS_IPV6__ else #endif #if defined __UCLIBC_HAS_IPV4__ { struct sockaddr_in *sinp = (struct sockaddr_in *) (*pai)->ai_addr; memcpy(&sinp->sin_addr, at2->addr, sizeof(struct in_addr)); sinp->sin_port = st2->port; memset(sinp->sin_zero, '\0', sizeof(sinp->sin_zero)); } #endif if (c) { (*pai)->ai_canonname = ((void *) (*pai) + sizeof(struct addrinfo) + socklen); strcpy((*pai)->ai_canonname, c); } else { (*pai)->ai_canonname = NULL; } (*pai)->ai_next = NULL; pai = &((*pai)->ai_next); } at2 = at2->next; } } return 0; }
//******************************************************* // Take supplied filename and open it, then parse the contents. // Upon return following set: // // OR we failed -1. int readConfig(char *configFileName) { char linein[256]; int len; const char delimiters[] = "="; char *lefttoken, *righttoken; char *cp; // Used if building white/blacklist struct in6_addr listEntry; strncpy( interfacestr, NPDAEMON_WAN_IF_NAME, sizeof(interfacestr)); flog(LOG_INFO, "Supplied interface is %s", interfacestr); listType = NOLIST; if (tRoot != NULL) { tdestroy(tRoot, free); tEntries = 0; } tRoot = NULL; collectTargets = 100; naLinkOptFlag = 0; nsIgnoreLocal = 1; naRouter = 1; maxHops = 255; interfaceIdx = if_nametoindex(interfacestr); if (!interfaceIdx) { flog(LOG_ERR, "Could not get ifIndex for interface %s", interfacestr); return 1; } while (getLinkaddress( interfacestr, linkAddr) ) { flog(LOG_ERR, "failed to convert interface specified to a link-level address continue."); sleep(1); } return 0; if ((configFileFD = fopen(configFileName, "r")) == NULL) { fprintf(stderr, "Can't open %s: %s\n", configFileName, strerror(errno)); flog(LOG_ERR, "Can't open config file %s: %s", configFileName, strerror(errno)); } // This is real simple config file parsing... do { int strToken, strIdx; len = 0; if (fgets(linein, 128, configFileFD) == NULL) break; // Tidy it up stripwhitespace(linein); // Special mega-hacky thing for blank lines: len = strlen(linein); if (len==0) { len=1; continue; } // Tokenize cp = strdupa(linein); lefttoken = strtok(cp, delimiters); righttoken = strtok(NULL, delimiters); if ( (lefttoken == NULL) || (righttoken == NULL) ) { continue; } // Match token strIdx = -1; for(strToken = 0; strToken < CONFIGTOTAL; strToken++) { if( !strcmp(lefttoken, configStrs[strToken]) ) { strIdx = strToken; // Matched, so drop to next step break; } } flog(LOG_DEBUG2, "Matched config item index: %d", strIdx); // If config params are being added, it should only be required // to update the strings in npd6config.h and then insert a // case XXXXXXX: here with self-contined code inside. switch (strIdx) { case NOMATCH: flog(LOG_DEBUG2, "Found noise in config file. Skipping."); continue; case NPD6PREFIX: strncpy( prefixaddrstr, righttoken, sizeof(prefixaddrstr)); flog(LOG_DEBUG, "Raw prefix: %s", prefixaddrstr); // We need to pad it up and record the length in bits prefixaddrlen = prefixset(prefixaddrstr); flog(LOG_INFO, "Padded prefix: %s, length = %d", prefixaddrstr, prefixaddrlen); if ( prefixaddrlen <= 0 ) { flog(LOG_ERR, "Invalid prefix."); } // Build a binary image of it build_addr(prefixaddrstr, &prefixaddr); break; case NPD6INTERFACE: if ( strlen( righttoken) > INTERFACE_STRLEN ) { flog(LOG_ERR, "Invalid length interface name"); return 1; } strncpy( interfacestr, righttoken, sizeof(interfacestr)); flog(LOG_INFO, "Supplied interface is %s", interfacestr); break; case NPD6OPTFLAG: if ( !strcmp( righttoken, SET ) ) { flog(LOG_INFO, "linkOption flag SET"); naLinkOptFlag = 1; } else if ( !strcmp( righttoken, UNSET ) ) { flog(LOG_INFO, "linkOption flag UNSET"); naLinkOptFlag = 0; } else { flog(LOG_ERR, "linkOption flag - Bad value"); return 1; } break; case NPD6LOCALIG: if ( !strcmp( righttoken, SET ) ) { flog(LOG_INFO, "ignoreLocal flag SET"); nsIgnoreLocal = 1; } else if ( !strcmp( righttoken, UNSET ) ) { flog(LOG_INFO, "ignoreLocal flag UNSET"); nsIgnoreLocal = 0; } else { flog(LOG_ERR, "ignoreLocal flag - Bad value"); return 1; } break; case NPD6ROUTERNA: if ( !strcmp( righttoken, SET ) ) { flog(LOG_INFO, "routerNA flag SET"); naRouter = 1; } else if ( !strcmp( righttoken, UNSET ) ) { flog(LOG_INFO, "routerNA flag UNSET"); naRouter = 0; } else { flog(LOG_ERR, "routerNA flag - Bad value"); return 1; } break; case NPD6MAXHOPS: maxHops = -1; maxHops = atoi(righttoken); if ( (maxHops < 0) || (maxHops > MAXMAXHOPS) ) { flog(LOG_ERR, "maxHops - invalid value specified in config."); return 1; } else { flog(LOG_INFO, "maxHops set to %d", maxHops); } break; case NPD6TARGETS: // If we arrive here and the tRoot tree already exists, // then we're re-reading the config and so need to zap // the tRoot data first. if (tRoot != NULL) { tdestroy(tRoot, free); tEntries = 0; } collectTargets = -1; tRoot = NULL; collectTargets = atoi(righttoken); if ( (collectTargets < 0) || (collectTargets > MAXTARGETS) ) { flog(LOG_ERR, "collectTargets - invalid value specified in config."); return 1; } else { flog(LOG_INFO, "collectTargets set to %d", collectTargets); } break; case NPD6LISTTYPE: if ( !strcmp( righttoken, NPD6NONE ) ) { flog(LOG_INFO, "List-type = NONE"); listType = NOLIST; } else if ( !strcmp( righttoken, NPD6BLACK ) ) { flog(LOG_INFO, "List-type = BLACK"); listType = BLACKLIST; } else if( !strcmp( righttoken, NPD6WHITE ) ) { flog(LOG_INFO, "List-type = WHITE"); listType = WHITELIST; } else { flog(LOG_ERR, "List-type = <invalid value> - Setting to NONE"); listType = NOLIST; } break; case NPD6LISTADDR: if (build_addr( righttoken, &listEntry) ) { flog(LOG_DEBUG, "Address %s valid.", righttoken); storeListEntry(&listEntry); } else { flog(LOG_ERR, "Address %s invalid.", righttoken); } break; } } while (len); // Now do some final checks to ensure all required params were supplied if ( ! strcmp(prefixaddrstr, NULLSTR) ) { flog(LOG_ERR, "Prefix not defined in config file."); return 1; } if ( ! strcmp(interfacestr, NULLSTR) ) { flog(LOG_ERR, "interface not defined in config file."); return 1; } // Work out the interface index interfaceIdx = if_nametoindex(interfacestr); if (!interfaceIdx) { flog(LOG_ERR, "Could not get ifIndex for interface %s", interfacestr); return 1; } if (getLinkaddress( interfacestr, linkAddr) ) { flog(LOG_ERR, "failed to convert interface specified to a link-level address."); return 1; } return 0; }
int main(int argc, char*argv[]) { int s; int ret; int on = 1; int size; int ttl = 255; int loop = 1; int times = 0; char buffer[2048]; struct sockaddr_in localaddr, fromaddr; struct ip_mreqn addr; s = socket(AF_INET, SOCK_DGRAM, 0); if(s < 0){ perror("socket error"); return -1; } //多播的地址結構 localaddr.sin_family = AF_INET; localaddr.sin_port = htons(PORT); localaddr.sin_addr.s_addr = htonl(INADDR_ANY); //綁定地址結構到套接字 ret = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) ); if(ret < 0){ perror("bind1 error"); return -1; } ret = bind(s, (struct sockaddr*)&localaddr, sizeof(localaddr));//客戶端需要綁定端口,用來接收服務器的數據,得指定接收端口,因為數據先從服務器發送過來的 if(ret < 0){ perror("bind error"); return -1; } //設置多播的TTL值 if(setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &ttl,sizeof(ttl)) < 0){ perror("IP_MULTICAST_TTL"); return -1; } addr.imr_ifindex = if_nametoindex("eth0"); //addr.imr_ifindex = if_nametoindex("eth0"); setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &addr, sizeof(addr)); if(ret < 0){ perror("IP_MULTICAST_IF error"); return -1; } //設置數據是否發送到本地迴環接口 if(setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP,&loop,sizeof(loop))<0){ perror("IP_MULTICAST_LOOP"); return -1; } //客戶端加入多播組 struct ip_mreq mreq; mreq.imr_multiaddr.s_addr = inet_addr(MCAST); mreq.imr_interface.s_addr = htonl(INADDR_ANY); if(setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0){ perror("IP_ADD_MEMBERSHIP"); return -1; } //循環接收多播組的消息 for(times = 0; times < 20; times++){ int len = sizeof(fromaddr); memset(buffer, 0, sizeof(buffer)); size = recvfrom(s, buffer, 1024, 0, (struct sockaddr*)&fromaddr, &len); if(size < 0){ perror("recvfrom "); return -1; } printf("times is: %d\n", times); printf("receive message: %s\n", buffer); printf("Port is: %d\n", fromaddr.sin_port); printf("IP is: %s\n", inet_ntoa(fromaddr.sin_addr)); fflush(stdout); size = sendto(s, "OK", 2, 0, (struct sockaddr*)&fromaddr, sizeof(fromaddr)); } //離開多播組 ret = setsockopt(s, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq)); if(ret < 0){ perror("IP_DROP_MEMBERSHIP"); return -1; } close(s); return 0; }
int test_udp_runner() { test_udp_addr addr; char ifname[IF_NAMESIZE + 1]; char ipv4[SVX_INETADDR_STR_IP_LEN]; char ipv6[SVX_INETADDR_STR_IP_LEN]; char ipv6_grp[SVX_INETADDR_STR_IP_LEN]; if(test_udp_interface_selector(ifname, sizeof(ifname), ipv4, sizeof(ipv4), ipv6, sizeof(ipv6))) { SVX_LOG_ERR("UDP test failed.\n" "We need an interface which support the following features:\n" "1. IPv4 address (unicast & multicast)\n" "2. IPv6 link-local address (unicast & multicast)\n"); exit(1); } addr.ifindex = if_nametoindex(ifname); snprintf(ipv6_grp, sizeof(ipv6_grp), "ff02::7:8:9%%%s", ifname); /* unicast, IPv4 */ addr.server_ip = "127.0.0.1"; addr.server_port = 30000; addr.client_ip = NULL; addr.client_port = 0; test_udp_do(&addr); /* unicast, IPv6 */ addr.server_ip = "::1"; addr.server_port = 30000; addr.client_ip = NULL; addr.client_port = 0; test_udp_do(&addr); /* multicast, IPv4 */ addr.server_ip = "239.7.8.9"; addr.server_port = 30000; addr.client_ip = NULL; addr.client_port = 0; test_udp_do(&addr); /* multicast, IPv6 */ addr.server_ip = ipv6_grp; addr.server_port = 30000; addr.client_ip = NULL; addr.client_port = 0; test_udp_do(&addr); /* source specific multicast IPv4 */ addr.server_ip = "239.7.8.9"; addr.server_port = 30000; addr.client_ip = ipv4; addr.client_port = 40000; test_udp_do(&addr); /* source specific multicast IPv6 */ addr.server_ip = ipv6_grp; addr.server_port = 30000; addr.client_ip = ipv6; addr.client_port = 40000; test_udp_do(&addr); fclose(stdin); fclose(stdout); fclose(stderr); return 0; }
static void * wpa_driver_wired_init(void *ctx, const char *ifname) { struct wpa_driver_wired_data *drv; int flags; drv = os_zalloc(sizeof(*drv)); if (drv == NULL) return NULL; os_strlcpy(drv->ifname, ifname, sizeof(drv->ifname)); drv->ctx = ctx; #ifdef __linux__ drv->pf_sock = socket(PF_PACKET, SOCK_DGRAM, 0); if (drv->pf_sock < 0) perror("socket(PF_PACKET)"); #else /* __linux__ */ drv->pf_sock = -1; #endif /* __linux__ */ if (wpa_driver_wired_get_ifflags(ifname, &flags) == 0 && !(flags & IFF_UP) && wpa_driver_wired_set_ifflags(ifname, flags | IFF_UP) == 0) { drv->iff_up = 1; } if (wired_multicast_membership(drv->pf_sock, if_nametoindex(drv->ifname), pae_group_addr, 1) == 0) { wpa_printf(MSG_DEBUG, "%s: Added multicast membership with " "packet socket", __func__); drv->membership = 1; } else if (wpa_driver_wired_multi(ifname, pae_group_addr, 1) == 0) { wpa_printf(MSG_DEBUG, "%s: Added multicast membership with " "SIOCADDMULTI", __func__); drv->multi = 1; } else if (wpa_driver_wired_get_ifflags(ifname, &flags) < 0) { wpa_printf(MSG_INFO, "%s: Could not get interface " "flags", __func__); os_free(drv); return NULL; } else if (flags & IFF_ALLMULTI) { wpa_printf(MSG_DEBUG, "%s: Interface is already configured " "for multicast", __func__); } else if (wpa_driver_wired_set_ifflags(ifname, flags | IFF_ALLMULTI) < 0) { wpa_printf(MSG_INFO, "%s: Failed to enable allmulti", __func__); os_free(drv); return NULL; } else { wpa_printf(MSG_DEBUG, "%s: Enabled allmulti mode", __func__); drv->iff_allmulti = 1; } #if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) { int status; wpa_printf(MSG_DEBUG, "%s: waiting for link to become active", __func__); while (wpa_driver_wired_get_ifstatus(ifname, &status) == 0 && status == 0) sleep(1); } #endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(FreeBSD_kernel__) */ return drv; }
static int gre_parse_opt(struct link_util *lu, int argc, char **argv, struct nlmsghdr *n) { struct { struct nlmsghdr n; struct ifinfomsg i; char buf[16384]; } req; struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1); struct rtattr *tb[IFLA_MAX + 1]; struct rtattr *linkinfo[IFLA_INFO_MAX+1]; struct rtattr *greinfo[IFLA_GRE_MAX + 1]; __u16 iflags = 0; __u16 oflags = 0; unsigned int ikey = 0; unsigned int okey = 0; unsigned int saddr = 0; unsigned int daddr = 0; unsigned int link = 0; __u8 pmtudisc = 1; __u8 ttl = 0; __u8 tos = 0; int len; __u16 encaptype = 0; __u16 encapflags = 0; __u16 encapsport = 0; __u16 encapdport = 0; __u8 metadata = 0; if (!(n->nlmsg_flags & NLM_F_CREATE)) { memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)); req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = RTM_GETLINK; req.i.ifi_family = preferred_family; req.i.ifi_index = ifi->ifi_index; if (rtnl_talk(&rth, &req.n, &req.n, sizeof(req)) < 0) { get_failed: fprintf(stderr, "Failed to get existing tunnel info.\n"); return -1; } len = req.n.nlmsg_len; len -= NLMSG_LENGTH(sizeof(*ifi)); if (len < 0) goto get_failed; parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len); if (!tb[IFLA_LINKINFO]) goto get_failed; parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]); if (!linkinfo[IFLA_INFO_DATA]) goto get_failed; parse_rtattr_nested(greinfo, IFLA_GRE_MAX, linkinfo[IFLA_INFO_DATA]); if (greinfo[IFLA_GRE_IKEY]) ikey = rta_getattr_u32(greinfo[IFLA_GRE_IKEY]); if (greinfo[IFLA_GRE_OKEY]) okey = rta_getattr_u32(greinfo[IFLA_GRE_OKEY]); if (greinfo[IFLA_GRE_IFLAGS]) iflags = rta_getattr_u16(greinfo[IFLA_GRE_IFLAGS]); if (greinfo[IFLA_GRE_OFLAGS]) oflags = rta_getattr_u16(greinfo[IFLA_GRE_OFLAGS]); if (greinfo[IFLA_GRE_LOCAL]) saddr = rta_getattr_u32(greinfo[IFLA_GRE_LOCAL]); if (greinfo[IFLA_GRE_REMOTE]) daddr = rta_getattr_u32(greinfo[IFLA_GRE_REMOTE]); if (greinfo[IFLA_GRE_PMTUDISC]) pmtudisc = rta_getattr_u8( greinfo[IFLA_GRE_PMTUDISC]); if (greinfo[IFLA_GRE_TTL]) ttl = rta_getattr_u8(greinfo[IFLA_GRE_TTL]); if (greinfo[IFLA_GRE_TOS]) tos = rta_getattr_u8(greinfo[IFLA_GRE_TOS]); if (greinfo[IFLA_GRE_LINK]) link = rta_getattr_u8(greinfo[IFLA_GRE_LINK]); if (greinfo[IFLA_GRE_ENCAP_TYPE]) encaptype = rta_getattr_u16(greinfo[IFLA_GRE_ENCAP_TYPE]); if (greinfo[IFLA_GRE_ENCAP_FLAGS]) encapflags = rta_getattr_u16(greinfo[IFLA_GRE_ENCAP_FLAGS]); if (greinfo[IFLA_GRE_ENCAP_SPORT]) encapsport = rta_getattr_u16(greinfo[IFLA_GRE_ENCAP_SPORT]); if (greinfo[IFLA_GRE_ENCAP_DPORT]) encapdport = rta_getattr_u16(greinfo[IFLA_GRE_ENCAP_DPORT]); if (greinfo[IFLA_GRE_COLLECT_METADATA]) metadata = 1; } while (argc > 0) { if (!matches(*argv, "key")) { unsigned int uval; NEXT_ARG(); iflags |= GRE_KEY; oflags |= GRE_KEY; if (strchr(*argv, '.')) uval = get_addr32(*argv); else { if (get_unsigned(&uval, *argv, 0) < 0) { fprintf(stderr, "Invalid value for \"key\": \"%s\"; it should be an unsigned integer\n", *argv); exit(-1); } uval = htonl(uval); } ikey = okey = uval; } else if (!matches(*argv, "ikey")) { unsigned int uval; NEXT_ARG(); iflags |= GRE_KEY; if (strchr(*argv, '.')) uval = get_addr32(*argv); else { if (get_unsigned(&uval, *argv, 0) < 0) { fprintf(stderr, "invalid value for \"ikey\": \"%s\"; it should be an unsigned integer\n", *argv); exit(-1); } uval = htonl(uval); } ikey = uval; } else if (!matches(*argv, "okey")) { unsigned int uval; NEXT_ARG(); oflags |= GRE_KEY; if (strchr(*argv, '.')) uval = get_addr32(*argv); else { if (get_unsigned(&uval, *argv, 0) < 0) { fprintf(stderr, "invalid value for \"okey\": \"%s\"; it should be an unsigned integer\n", *argv); exit(-1); } uval = htonl(uval); } okey = uval; } else if (!matches(*argv, "seq")) { iflags |= GRE_SEQ; oflags |= GRE_SEQ; } else if (!matches(*argv, "iseq")) { iflags |= GRE_SEQ; } else if (!matches(*argv, "oseq")) { oflags |= GRE_SEQ; } else if (!matches(*argv, "csum")) { iflags |= GRE_CSUM; oflags |= GRE_CSUM; } else if (!matches(*argv, "icsum")) { iflags |= GRE_CSUM; } else if (!matches(*argv, "ocsum")) { oflags |= GRE_CSUM; } else if (!matches(*argv, "nopmtudisc")) { pmtudisc = 0; } else if (!matches(*argv, "pmtudisc")) { pmtudisc = 1; } else if (!matches(*argv, "remote")) { NEXT_ARG(); if (strcmp(*argv, "any")) daddr = get_addr32(*argv); } else if (!matches(*argv, "local")) { NEXT_ARG(); if (strcmp(*argv, "any")) saddr = get_addr32(*argv); } else if (!matches(*argv, "dev")) { NEXT_ARG(); link = if_nametoindex(*argv); if (link == 0) { fprintf(stderr, "Cannot find device \"%s\"\n", *argv); exit(-1); } } else if (!matches(*argv, "ttl") || !matches(*argv, "hoplimit")) { unsigned int uval; NEXT_ARG(); if (strcmp(*argv, "inherit") != 0) { if (get_unsigned(&uval, *argv, 0)) invarg("invalid TTL\n", *argv); if (uval > 255) invarg("TTL must be <= 255\n", *argv); ttl = uval; } } else if (!matches(*argv, "tos") || !matches(*argv, "tclass") || !matches(*argv, "dsfield")) { __u32 uval; NEXT_ARG(); if (strcmp(*argv, "inherit") != 0) { if (rtnl_dsfield_a2n(&uval, *argv)) invarg("bad TOS value", *argv); tos = uval; } else tos = 1; } else if (strcmp(*argv, "noencap") == 0) { encaptype = TUNNEL_ENCAP_NONE; } else if (strcmp(*argv, "encap") == 0) { NEXT_ARG(); if (strcmp(*argv, "fou") == 0) encaptype = TUNNEL_ENCAP_FOU; else if (strcmp(*argv, "gue") == 0) encaptype = TUNNEL_ENCAP_GUE; else if (strcmp(*argv, "none") == 0) encaptype = TUNNEL_ENCAP_NONE; else invarg("Invalid encap type.", *argv); } else if (strcmp(*argv, "encap-sport") == 0) { NEXT_ARG(); if (strcmp(*argv, "auto") == 0) encapsport = 0; else if (get_u16(&encapsport, *argv, 0)) invarg("Invalid source port.", *argv); } else if (strcmp(*argv, "encap-dport") == 0) { NEXT_ARG(); if (get_u16(&encapdport, *argv, 0)) invarg("Invalid destination port.", *argv); } else if (strcmp(*argv, "encap-csum") == 0) { encapflags |= TUNNEL_ENCAP_FLAG_CSUM; } else if (strcmp(*argv, "noencap-csum") == 0) { encapflags &= ~TUNNEL_ENCAP_FLAG_CSUM; } else if (strcmp(*argv, "encap-udp6-csum") == 0) { encapflags |= TUNNEL_ENCAP_FLAG_CSUM6; } else if (strcmp(*argv, "noencap-udp6-csum") == 0) { encapflags |= ~TUNNEL_ENCAP_FLAG_CSUM6; } else if (strcmp(*argv, "encap-remcsum") == 0) { encapflags |= TUNNEL_ENCAP_FLAG_REMCSUM; } else if (strcmp(*argv, "noencap-remcsum") == 0) { encapflags |= ~TUNNEL_ENCAP_FLAG_REMCSUM; } else if (strcmp(*argv, "external") == 0) { metadata = 1; } else usage(); argc--; argv++; } if (!ikey && IN_MULTICAST(ntohl(daddr))) { ikey = daddr; iflags |= GRE_KEY; } if (!okey && IN_MULTICAST(ntohl(daddr))) { okey = daddr; oflags |= GRE_KEY; } if (IN_MULTICAST(ntohl(daddr)) && !saddr) { fprintf(stderr, "A broadcast tunnel requires a source address.\n"); return -1; } addattr32(n, 1024, IFLA_GRE_IKEY, ikey); addattr32(n, 1024, IFLA_GRE_OKEY, okey); addattr_l(n, 1024, IFLA_GRE_IFLAGS, &iflags, 2); addattr_l(n, 1024, IFLA_GRE_OFLAGS, &oflags, 2); addattr_l(n, 1024, IFLA_GRE_LOCAL, &saddr, 4); addattr_l(n, 1024, IFLA_GRE_REMOTE, &daddr, 4); addattr_l(n, 1024, IFLA_GRE_PMTUDISC, &pmtudisc, 1); if (link) addattr32(n, 1024, IFLA_GRE_LINK, link); addattr_l(n, 1024, IFLA_GRE_TTL, &ttl, 1); addattr_l(n, 1024, IFLA_GRE_TOS, &tos, 1); addattr16(n, 1024, IFLA_GRE_ENCAP_TYPE, encaptype); addattr16(n, 1024, IFLA_GRE_ENCAP_FLAGS, encapflags); addattr16(n, 1024, IFLA_GRE_ENCAP_SPORT, htons(encapsport)); addattr16(n, 1024, IFLA_GRE_ENCAP_DPORT, htons(encapdport)); if (metadata) addattr_l(n, 1024, IFLA_GRE_COLLECT_METADATA, NULL, 0); return 0; }
static int parse_args(int argc, char **argv, int cmd, struct ip_tunnel_parm *p) { int count = 0; char medium[IFNAMSIZ]; int isatap = 0; memset(p, 0, sizeof(*p)); memset(&medium, 0, sizeof(medium)); p->iph.version = 4; p->iph.ihl = 5; #ifndef IP_DF #define IP_DF 0x4000 /* Flag: "Don't Fragment" */ #endif p->iph.frag_off = htons(IP_DF); while (argc > 0) { if (strcmp(*argv, "mode") == 0) { NEXT_ARG(); if (strcmp(*argv, "ipip") == 0 || strcmp(*argv, "ip/ip") == 0) { if (p->iph.protocol && p->iph.protocol != IPPROTO_IPIP) { fprintf(stderr,"You managed to ask for more than one tunnel mode.\n"); exit(-1); } p->iph.protocol = IPPROTO_IPIP; } else if (strcmp(*argv, "gre") == 0 || strcmp(*argv, "gre/ip") == 0) { if (p->iph.protocol && p->iph.protocol != IPPROTO_GRE) { fprintf(stderr,"You managed to ask for more than one tunnel mode.\n"); exit(-1); } p->iph.protocol = IPPROTO_GRE; } else if (strcmp(*argv, "sit") == 0 || strcmp(*argv, "ipv6/ip") == 0) { if (p->iph.protocol && p->iph.protocol != IPPROTO_IPV6) { fprintf(stderr,"You managed to ask for more than one tunnel mode.\n"); exit(-1); } p->iph.protocol = IPPROTO_IPV6; } else if (strcmp(*argv, "isatap") == 0) { if (p->iph.protocol && p->iph.protocol != IPPROTO_IPV6) { fprintf(stderr, "You managed to ask for more than one tunnel mode.\n"); exit(-1); } p->iph.protocol = IPPROTO_IPV6; isatap++; } else if (strcmp(*argv, "vti") == 0) { if (p->iph.protocol && p->iph.protocol != IPPROTO_IPIP) { fprintf(stderr, "You managed to ask for more than one tunnel mode.\n"); exit(-1); } p->iph.protocol = IPPROTO_IPIP; p->i_flags |= VTI_ISVTI; } else { fprintf(stderr,"Cannot guess tunnel mode.\n"); exit(-1); } } else if (strcmp(*argv, "key") == 0) { unsigned uval; NEXT_ARG(); p->i_flags |= GRE_KEY; p->o_flags |= GRE_KEY; if (strchr(*argv, '.')) p->i_key = p->o_key = get_addr32(*argv); else { if (get_unsigned(&uval, *argv, 0)<0) { fprintf(stderr, "invalid value of \"key\"\n"); exit(-1); } p->i_key = p->o_key = htonl(uval); } } else if (strcmp(*argv, "ikey") == 0) { unsigned uval; NEXT_ARG(); p->i_flags |= GRE_KEY; if (strchr(*argv, '.')) p->i_key = get_addr32(*argv); else { if (get_unsigned(&uval, *argv, 0)<0) { fprintf(stderr, "invalid value of \"ikey\"\n"); exit(-1); } p->i_key = htonl(uval); } } else if (strcmp(*argv, "okey") == 0) { unsigned uval; NEXT_ARG(); p->o_flags |= GRE_KEY; if (strchr(*argv, '.')) p->o_key = get_addr32(*argv); else { if (get_unsigned(&uval, *argv, 0)<0) { fprintf(stderr, "invalid value of \"okey\"\n"); exit(-1); } p->o_key = htonl(uval); } } else if (strcmp(*argv, "seq") == 0) { p->i_flags |= GRE_SEQ; p->o_flags |= GRE_SEQ; } else if (strcmp(*argv, "iseq") == 0) { p->i_flags |= GRE_SEQ; } else if (strcmp(*argv, "oseq") == 0) { p->o_flags |= GRE_SEQ; } else if (strcmp(*argv, "csum") == 0) { p->i_flags |= GRE_CSUM; p->o_flags |= GRE_CSUM; } else if (strcmp(*argv, "icsum") == 0) { p->i_flags |= GRE_CSUM; } else if (strcmp(*argv, "ocsum") == 0) { p->o_flags |= GRE_CSUM; } else if (strcmp(*argv, "nopmtudisc") == 0) { p->iph.frag_off = 0; } else if (strcmp(*argv, "pmtudisc") == 0) { p->iph.frag_off = htons(IP_DF); } else if (strcmp(*argv, "remote") == 0) { NEXT_ARG(); if (strcmp(*argv, "any")) p->iph.daddr = get_addr32(*argv); } else if (strcmp(*argv, "local") == 0) { NEXT_ARG(); if (strcmp(*argv, "any")) p->iph.saddr = get_addr32(*argv); } else if (strcmp(*argv, "dev") == 0) { NEXT_ARG(); strncpy(medium, *argv, IFNAMSIZ-1); } else if (strcmp(*argv, "ttl") == 0 || strcmp(*argv, "hoplimit") == 0) { unsigned uval; NEXT_ARG(); if (strcmp(*argv, "inherit") != 0) { if (get_unsigned(&uval, *argv, 0)) invarg("invalid TTL\n", *argv); if (uval > 255) invarg("TTL must be <=255\n", *argv); p->iph.ttl = uval; } } else if (strcmp(*argv, "tos") == 0 || strcmp(*argv, "tclass") == 0 || matches(*argv, "dsfield") == 0) { __u32 uval; NEXT_ARG(); if (strcmp(*argv, "inherit") != 0) { if (rtnl_dsfield_a2n(&uval, *argv)) invarg("bad TOS value", *argv); p->iph.tos = uval; } else p->iph.tos = 1; } else { if (strcmp(*argv, "name") == 0) { NEXT_ARG(); } else if (matches(*argv, "help") == 0) usage(); if (p->name[0]) duparg2("name", *argv); strncpy(p->name, *argv, IFNAMSIZ); if (cmd == SIOCCHGTUNNEL && count == 0) { struct ip_tunnel_parm old_p; memset(&old_p, 0, sizeof(old_p)); if (tnl_get_ioctl(*argv, &old_p)) return -1; *p = old_p; } } count++; argc--; argv++; } if (p->iph.protocol == 0) { if (memcmp(p->name, "gre", 3) == 0) p->iph.protocol = IPPROTO_GRE; else if (memcmp(p->name, "ipip", 4) == 0) p->iph.protocol = IPPROTO_IPIP; else if (memcmp(p->name, "sit", 3) == 0) p->iph.protocol = IPPROTO_IPV6; else if (memcmp(p->name, "isatap", 6) == 0) { p->iph.protocol = IPPROTO_IPV6; isatap++; } else if (memcmp(p->name, "vti", 3) == 0) { p->iph.protocol = IPPROTO_IPIP; p->i_flags |= VTI_ISVTI; } } if (p->iph.protocol == IPPROTO_IPIP || p->iph.protocol == IPPROTO_IPV6) { if ((p->i_flags & GRE_KEY) || (p->o_flags & GRE_KEY)) { fprintf(stderr, "Keys are not allowed with ipip and sit.\n"); return -1; } } if (medium[0]) { p->link = if_nametoindex(medium); if (p->link == 0) return -1; } if (p->i_key == 0 && IN_MULTICAST(ntohl(p->iph.daddr))) { p->i_key = p->iph.daddr; p->i_flags |= GRE_KEY; } if (p->o_key == 0 && IN_MULTICAST(ntohl(p->iph.daddr))) { p->o_key = p->iph.daddr; p->o_flags |= GRE_KEY; } if (IN_MULTICAST(ntohl(p->iph.daddr)) && !p->iph.saddr) { fprintf(stderr, "Broadcast tunnel requires a source address.\n"); return -1; } if (isatap) p->i_flags |= SIT_ISATAP; return 0; }
static int _intf_get_noalias(intf_t *intf, struct intf_entry *entry) { struct ifreq ifr; #ifdef HAVE_GETKERNINFO int size; struct kinfo_ndd *nddp; void *end; #endif /* Get interface index. */ entry->intf_index = if_nametoindex(entry->intf_name); if (entry->intf_index == 0) return (-1); strlcpy(ifr.ifr_name, entry->intf_name, sizeof(ifr.ifr_name)); /* Get interface flags. */ if (ioctl(intf->fd, SIOCGIFFLAGS, &ifr) < 0) return (-1); entry->intf_flags = intf_iff_to_flags(ifr.ifr_flags); _intf_set_type(entry); /* Get interface MTU. */ #ifdef SIOCGIFMTU if (ioctl(intf->fd, SIOCGIFMTU, &ifr) < 0) #endif return (-1); entry->intf_mtu = ifr.ifr_mtu; entry->intf_addr.addr_type = entry->intf_dst_addr.addr_type = entry->intf_link_addr.addr_type = ADDR_TYPE_NONE; /* Get primary interface address. */ if (ioctl(intf->fd, SIOCGIFADDR, &ifr) == 0) { addr_ston(&ifr.ifr_addr, &entry->intf_addr); if (ioctl(intf->fd, SIOCGIFNETMASK, &ifr) < 0) return (-1); addr_stob(&ifr.ifr_addr, &entry->intf_addr.addr_bits); } /* Get other addresses. */ if (entry->intf_type == INTF_TYPE_TUN) { if (ioctl(intf->fd, SIOCGIFDSTADDR, &ifr) == 0) { if (addr_ston(&ifr.ifr_addr, &entry->intf_dst_addr) < 0) return (-1); } } else if (entry->intf_type == INTF_TYPE_ETH) { #if defined(HAVE_GETKERNINFO) /* AIX also defines SIOCGIFHWADDR, but it fails silently? * This is the method IBM recommends here: * http://www-01.ibm.com/support/knowledgecenter/ssw_aix_53/com.ibm.aix.progcomm/doc/progcomc/skt_sndother_ex.htm%23ssqinc2joyc?lang=en */ /* How many bytes will be returned? */ size = getkerninfo(KINFO_NDD, 0, 0, 0); if (size <= 0) { return -1; } nddp = (struct kinfo_ndd *)malloc(size); if (!nddp) { return -1; } /* Get all Network Device Driver (NDD) info */ if (getkerninfo(KINFO_NDD, nddp, &size, 0) < 0) { free(nddp); return -1; } /* Loop over the returned values until we find a match */ end = (void *)nddp + size; while ((void *)nddp < end) { if (!strcmp(nddp->ndd_alias, entry->intf_name) || !strcmp(nddp->ndd_name, entry->intf_name)) { addr_pack(&entry->intf_link_addr, ADDR_TYPE_ETH, ETH_ADDR_BITS, nddp->ndd_addr, ETH_ADDR_LEN); break; } else nddp++; } free(nddp); #elif defined(SIOCGIFHWADDR) if (ioctl(intf->fd, SIOCGIFHWADDR, &ifr) < 0) return (-1); if (addr_ston(&ifr.ifr_addr, &entry->intf_link_addr) < 0) return (-1); #elif defined(SIOCRPHYSADDR) /* Tru64 */ struct ifdevea *ifd = (struct ifdevea *)𝔦 /* XXX */ if (ioctl(intf->fd, SIOCRPHYSADDR, ifd) < 0) return (-1); addr_pack(&entry->intf_link_addr, ADDR_TYPE_ETH, ETH_ADDR_BITS, ifd->current_pa, ETH_ADDR_LEN); #else eth_t *eth; if ((eth = eth_open(entry->intf_name)) != NULL) { if (!eth_get(eth, &entry->intf_link_addr.addr_eth)) { entry->intf_link_addr.addr_type = ADDR_TYPE_ETH; entry->intf_link_addr.addr_bits = ETH_ADDR_BITS; } eth_close(eth); } #endif } return (0); }
//*********************************** // command execution //*********************************** void bandwidth_pid(pid_t pid, const char *command, const char *dev, int down, int up) { EUID_ASSERT(); //************************ // verify sandbox //************************ EUID_ROOT(); char *comm = pid_proc_comm(pid); EUID_USER(); if (!comm) { fprintf(stderr, "Error: cannot find sandbox\n"); exit(1); } // check for firejail sandbox if (strcmp(comm, "firejail") != 0) { fprintf(stderr, "Error: cannot find sandbox\n"); exit(1); } free(comm); // check network namespace char *name; if (asprintf(&name, "/run/firejail/network/%d-netmap", pid) == -1) errExit("asprintf"); struct stat s; if (stat(name, &s) == -1) { fprintf(stderr, "Error: the sandbox doesn't use a new network namespace\n"); exit(1); } //************************ // join the network namespace //************************ pid_t child; if (find_child(pid, &child) == -1) { fprintf(stderr, "Error: cannot join the network namespace\n"); exit(1); } EUID_ROOT(); if (join_namespace(child, "net")) { fprintf(stderr, "Error: cannot join the network namespace\n"); exit(1); } // set run file if (strcmp(command, "set") == 0) bandwidth_set(pid, dev, down, up); else if (strcmp(command, "clear") == 0) bandwidth_remove(pid, dev); //************************ // build command //************************ char *devname = NULL; if (dev) { // read network map file char *fname; if (asprintf(&fname, "%s/%d-netmap", RUN_FIREJAIL_NETWORK_DIR, (int) pid) == -1) errExit("asprintf"); FILE *fp = fopen(fname, "r"); if (!fp) { fprintf(stderr, "Error: cannot read network map file %s\n", fname); exit(1); } char buf[1024]; int len = strlen(dev); while (fgets(buf, 1024, fp)) { // remove '\n' char *ptr = strchr(buf, '\n'); if (ptr) *ptr = '\0'; if (*buf == '\0') break; if (strncmp(buf, dev, len) == 0 && buf[len] == ':') { devname = strdup(buf + len + 1); if (!devname) errExit("strdup"); // check device in namespace if (if_nametoindex(devname) == 0) { fprintf(stderr, "Error: cannot find network device %s\n", devname); exit(1); } break; } } free(fname); fclose(fp); } // build fshaper.sh command char *cmd = NULL; if (devname) { if (strcmp(command, "set") == 0) { if (asprintf(&cmd, "%s/firejail/fshaper.sh --%s %s %d %d", LIBDIR, command, devname, down, up) == -1) errExit("asprintf"); } else { if (asprintf(&cmd, "%s/firejail/fshaper.sh --%s %s", LIBDIR, command, devname) == -1) errExit("asprintf"); } } else { if (asprintf(&cmd, "%s/firejail/fshaper.sh --%s", LIBDIR, command) == -1) errExit("asprintf"); } assert(cmd); // wipe out environment variables environ = NULL; //************************ // build command //************************ // elevate privileges if (setreuid(0, 0)) errExit("setreuid"); if (setregid(0, 0)) errExit("setregid"); char *arg[4]; arg[0] = "/bin/sh"; arg[1] = "-c"; arg[2] = cmd; arg[3] = NULL; clearenv(); execvp(arg[0], arg); // it will never get here errExit("execvp"); }
/* upnpDiscover() : * return a chained list of all devices found or NULL if * no devices was found. * It is up to the caller to free the chained list * delay is in millisecond (poll) */ LIBSPEC struct UPNPDev * upnpDiscover(int delay, const char * multicastif, const char * minissdpdsock, int sameport, int ipv6, int * error) { struct UPNPDev * tmp; struct UPNPDev * devlist = 0; int opt = 1; static const char MSearchMsgFmt[] = "M-SEARCH * HTTP/1.1\r\n" "HOST: %s:" XSTR(PORT) "\r\n" "ST: %s\r\n" "MAN: \"ssdp:discover\"\r\n" "MX: %u\r\n" "\r\n"; static const char * const deviceList[] = { #if 0 "urn:schemas-upnp-org:device:InternetGatewayDevice:2", "urn:schemas-upnp-org:service:WANIPConnection:2", #endif "urn:schemas-upnp-org:device:InternetGatewayDevice:1", "urn:schemas-upnp-org:service:WANIPConnection:1", "urn:schemas-upnp-org:service:WANPPPConnection:1", "upnp:rootdevice", 0 }; int deviceIndex = 0; char bufr[1536]; /* reception and emission buffer */ int sudp; int n; struct sockaddr_storage sockudp_r; unsigned int mx; #ifdef NO_GETADDRINFO struct sockaddr_storage sockudp_w; #else int rv; struct addrinfo hints, *servinfo, *p; #endif #ifdef WIN32 MIB_IPFORWARDROW ip_forward; #endif if(error) *error = UPNPDISCOVER_UNKNOWN_ERROR; #if !defined(WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) /* first try to get infos from minissdpd ! */ if(!minissdpdsock) minissdpdsock = "/var/run/minissdpd.sock"; while(!devlist && deviceList[deviceIndex]) { devlist = getDevicesFromMiniSSDPD(deviceList[deviceIndex], minissdpdsock); /* We return what we have found if it was not only a rootdevice */ if(devlist && !strstr(deviceList[deviceIndex], "rootdevice")) { if(error) *error = UPNPDISCOVER_SUCCESS; return devlist; } deviceIndex++; } deviceIndex = 0; #endif /* fallback to direct discovery */ #ifdef WIN32 sudp = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, IPPROTO_UDP); #else sudp = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, 0); #endif if(sudp < 0) { if(error) *error = UPNPDISCOVER_SOCKET_ERROR; PRINT_SOCKET_ERROR("socket"); return NULL; } /* reception */ memset(&sockudp_r, 0, sizeof(struct sockaddr_storage)); if(ipv6) { struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_r; p->sin6_family = AF_INET6; if(sameport) p->sin6_port = htons(PORT); p->sin6_addr = in6addr_any; /* in6addr_any is not available with MinGW32 3.4.2 */ } else { struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_r; p->sin_family = AF_INET; if(sameport) p->sin_port = htons(PORT); p->sin_addr.s_addr = INADDR_ANY; } #ifdef WIN32 /* This code could help us to use the right Network interface for * SSDP multicast traffic */ /* Get IP associated with the index given in the ip_forward struct * in order to give this ip to setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF) */ if(!ipv6 && (GetBestRoute(inet_addr("223.255.255.255"), 0, &ip_forward) == NO_ERROR)) { DWORD dwRetVal = 0; PMIB_IPADDRTABLE pIPAddrTable; DWORD dwSize = 0; #ifdef DEBUG IN_ADDR IPAddr; #endif int i; #ifdef DEBUG printf("ifIndex=%lu nextHop=%lx \n", ip_forward.dwForwardIfIndex, ip_forward.dwForwardNextHop); #endif pIPAddrTable = (MIB_IPADDRTABLE *) malloc(sizeof (MIB_IPADDRTABLE)); if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) { free(pIPAddrTable); pIPAddrTable = (MIB_IPADDRTABLE *) malloc(dwSize); } if(pIPAddrTable) { dwRetVal = GetIpAddrTable( pIPAddrTable, &dwSize, 0 ); #ifdef DEBUG printf("\tNum Entries: %ld\n", pIPAddrTable->dwNumEntries); #endif for (i=0; i < (int) pIPAddrTable->dwNumEntries; i++) { #ifdef DEBUG printf("\n\tInterface Index[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwIndex); IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwAddr; printf("\tIP Address[%d]: \t%s\n", i, inet_ntoa(IPAddr) ); IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwMask; printf("\tSubnet Mask[%d]: \t%s\n", i, inet_ntoa(IPAddr) ); IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwBCastAddr; printf("\tBroadCast[%d]: \t%s (%ld)\n", i, inet_ntoa(IPAddr), pIPAddrTable->table[i].dwBCastAddr); printf("\tReassembly size[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwReasmSize); printf("\tType and State[%d]:", i); printf("\n"); #endif if (pIPAddrTable->table[i].dwIndex == ip_forward.dwForwardIfIndex) { /* Set the address of this interface to be used */ struct in_addr mc_if; memset(&mc_if, 0, sizeof(mc_if)); mc_if.s_addr = pIPAddrTable->table[i].dwAddr; if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) { PRINT_SOCKET_ERROR("setsockopt"); } ((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = pIPAddrTable->table[i].dwAddr; #ifndef DEBUG break; #endif } } free(pIPAddrTable); pIPAddrTable = NULL; } } #endif #ifdef WIN32 if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof (opt)) < 0) #else if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)) < 0) #endif { if(error) *error = UPNPDISCOVER_SOCKET_ERROR; PRINT_SOCKET_ERROR("setsockopt"); return NULL; } if(multicastif) { if(ipv6) { #if !defined(WIN32) /* according to MSDN, if_nametoindex() is supported since * MS Windows Vista and MS Windows Server 2008. * http://msdn.microsoft.com/en-us/library/bb408409%28v=vs.85%29.aspx */ unsigned int ifindex = if_nametoindex(multicastif); /* eth0, etc. */ if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(&ifindex)) < 0) { PRINT_SOCKET_ERROR("setsockopt"); } #else #ifdef DEBUG printf("Setting of multicast interface not supported in IPv6 under Windows.\n"); #endif #endif } else { struct in_addr mc_if; mc_if.s_addr = inet_addr(multicastif); /* ex: 192.168.x.x */ ((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = mc_if.s_addr; if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) { PRINT_SOCKET_ERROR("setsockopt"); } } } /* Avant d'envoyer le paquet on bind pour recevoir la reponse */ if (bind(sudp, (const struct sockaddr *)&sockudp_r, ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) != 0) { if(error) *error = UPNPDISCOVER_SOCKET_ERROR; PRINT_SOCKET_ERROR("bind"); closesocket(sudp); return NULL; } /* Calculating maximum response time in seconds */ mx = ((unsigned int)delay) / 1000u; /* receiving SSDP response packet */ for(n = 0;;) { if(n == 0) { /* sending the SSDP M-SEARCH packet */ n = snprintf(bufr, sizeof(bufr), MSearchMsgFmt, ipv6 ? "[" UPNP_MCAST_LL_ADDR "]" : UPNP_MCAST_ADDR, deviceList[deviceIndex++], mx); #ifdef DEBUG printf("Sending %s", bufr); #endif #ifdef NO_GETADDRINFO /* the following code is not using getaddrinfo */ /* emission */ memset(&sockudp_w, 0, sizeof(struct sockaddr_storage)); if(ipv6) { struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_w; p->sin6_family = AF_INET6; p->sin6_port = htons(PORT); inet_pton(AF_INET6, UPNP_MCAST_LL_ADDR, &(p->sin6_addr)); } else { struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_w; p->sin_family = AF_INET; p->sin_port = htons(PORT); p->sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR); } n = sendto(sudp, bufr, n, 0, &sockudp_w, ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)); if (n < 0) { if(error) *error = UPNPDISCOVER_SOCKET_ERROR; PRINT_SOCKET_ERROR("sendto"); closesocket(sudp); return devlist; } #else /* #ifdef NO_GETADDRINFO */ memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; // AF_INET6 or AF_INET hints.ai_socktype = SOCK_DGRAM; /*hints.ai_flags = */ if ((rv = getaddrinfo(ipv6 ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_ADDR, XSTR(PORT), &hints, &servinfo)) != 0) { if(error) *error = UPNPDISCOVER_SOCKET_ERROR; #ifdef WIN32 fprintf(stderr, "getaddrinfo() failed: %d\n", rv); #else fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); #endif return devlist; } for(p = servinfo; p; p = p->ai_next) { n = sendto(sudp, bufr, n, 0, p->ai_addr, p->ai_addrlen); if (n < 0) { PRINT_SOCKET_ERROR("sendto"); continue; } } freeaddrinfo(servinfo); if(n < 0) { if(error) *error = UPNPDISCOVER_SOCKET_ERROR; closesocket(sudp); return devlist; } #endif /* #ifdef NO_GETADDRINFO */ } /* Waiting for SSDP REPLY packet to M-SEARCH */ n = receivedata(sudp, bufr, sizeof(bufr), delay); if (n < 0) { /* error */ if(error) *error = UPNPDISCOVER_SOCKET_ERROR; closesocket(sudp); return devlist; } else if (n == 0) { /* no data or Time Out */ if (devlist || (deviceList[deviceIndex] == 0)) { /* no more device type to look for... */ if(error) *error = UPNPDISCOVER_SUCCESS; closesocket(sudp); return devlist; } } else { const char * descURL=NULL; int urlsize=0; const char * st=NULL; int stsize=0; /*printf("%d byte(s) :\n%s\n", n, bufr);*/ /* affichage du message */ parseMSEARCHReply(bufr, n, &descURL, &urlsize, &st, &stsize); if(st&&descURL) { #ifdef DEBUG printf("M-SEARCH Reply:\nST: %.*s\nLocation: %.*s\n", stsize, st, urlsize, descURL); #endif for(tmp=devlist; tmp; tmp = tmp->pNext) { if(memcmp(tmp->descURL, descURL, urlsize) == 0 && tmp->descURL[urlsize] == '\0' && memcmp(tmp->st, st, stsize) == 0 && tmp->st[stsize] == '\0') break; } /* at the exit of the loop above, tmp is null if * no duplicate device was found */ if(tmp) continue; tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize); if(!tmp) { /* memory allocation error */ if(error) *error = UPNPDISCOVER_MEMORY_ERROR; return devlist; } tmp->pNext = devlist; tmp->descURL = tmp->buffer; tmp->st = tmp->buffer + 1 + urlsize; memcpy(tmp->buffer, descURL, urlsize); tmp->buffer[urlsize] = '\0'; memcpy(tmp->buffer + urlsize + 1, st, stsize); tmp->buffer[urlsize+1+stsize] = '\0'; devlist = tmp; } } } }
int main(int argc, char **argv) { struct nl80211_state nlstate; int devidx = 0; char *devname; int err; unsigned int surveys = 10; /* strip off self */ argc--; argv0 = *argv++; if (argc > 0 && strcmp(*argv, "--debug") == 0) { nl_debug = 1; argc--; argv++; } if (argc > 0 && strcmp(*argv, "--version") == 0) { version(); return 0; } /* need to treat "help" command specially so it works w/o nl80211 */ if (argc == 0 || strcmp(*argv, "help") == 0) { usage(); return 0; } err = nl80211_init(&nlstate); if (err) return 1; if (argc <= 0) { return 1; } devidx = if_nametoindex(*argv); if (devidx == 0) devidx = -1; devname = *argv; argc--; argv++; if (devidx < 0) return -errno; if (!is_link_up(devname)) { err = -ENOLINK; printf("Link for %s must be up to use acs\n", devname); goto nl_cleanup; } /* * XXX: we should probably get channel list properly here * but I'm lazy. THIS IS A REQUIREMENT, given that if a device * is down and comes up we won't have any survey data to study. */ err = get_freq_list(&nlstate, devidx); if (err) return err; while (surveys--) { err = study_freqs(&nlstate, devidx); if (err) return err; } parse_freq_list(); parse_freq_int_factor(); nl_cleanup: nl80211_cleanup(&nlstate); clear_offchan_ops_list(); clean_freq_list(); return err; }
static void packet_input(int fd) #endif { rt_table_t *fwd_rt, *rev_rt, *repair_rt, *next_hop_rt; u_int32_t dest_addr, src_addr; u_int8_t rreq_flags = 0; unsigned int ifindex; struct ip_data *ipd = NULL; #ifdef NS_PORT ifindex = NS_IFINDEX; // Always use ns interface fwd_rt = NULL; // In case of broadcast we provide no next hop ipd = NULL; // No ICMP messaging struct hdr_cmn *ch = HDR_CMN(p); struct hdr_ip *ih = HDR_IP(p); src_addr = ih->saddr(); dest_addr = ih->daddr(); /* Any packets with our IP address as destination arriving here are packets that weren't caught by any agent attached to the node. Throw away those. */ if (dest_addr == DEV_IFINDEX(ifindex).ipaddr) { DEBUG(LOG_WARNING, 0, "processPacket: Received orphan packet. Throwing it away."); Packet::free(p); return; } /* If this is a TCP packet and we don't have a route, we should set the gratuituos flag in the RREQ. */ if (ch->ptype() == PT_TCP) { rreq_flags |= RREQ_GRATUITOUS; } #else int status; char buf[BUFSIZE], *dev_name; ipq_packet_msg_t *pkt; struct iphdr *ip; struct udphdr *udp; struct icmphdr *icmp = NULL; ipq_read(h, buf, BUFSIZE, 0); status = ipq_message_type(buf); if (status == NLMSG_ERROR) { fprintf(stderr, "ERROR packet_input: Check that the ip_queue.o module is loaded.\n"); die(h); } pkt = ipq_get_packet(buf); #ifdef DEBUG_PACKET DEBUG(LOG_DEBUG, 0, "Protocol %u indev=%s outdev=%s\n", pkt->hw_protocol, pkt->indev_name, pkt->outdev_name); #endif if (pkt->hook == 0) dev_name = pkt->indev_name; else if (pkt->hook == 3) dev_name = pkt->outdev_name; else dev_name = NULL; /* We know from kaodv.c that this is an IP packet */ ip = (struct iphdr *) pkt->payload; dest_addr = ntohl(ip->daddr); src_addr = ntohl(ip->saddr); switch (ip->protocol) { /* Don't process AODV control packets (UDP on port 654). They are accounted for on the aodv socket */ case IPPROTO_UDP: udp = (struct udphdr *) ((char *) ip + (ip->ihl << 2)); if (ntohs(udp->dest) == AODV_PORT || ntohs(udp->source) == AODV_PORT) goto accept; break; /* If this is a TCP packet and we don't have a route, we should set the gratuituos flag in the RREQ. */ case IPPROTO_TCP: rreq_flags |= RREQ_GRATUITOUS; break; /* We set the gratuitous flag also on ICMP ECHO requests, since the destination will also need a route back for the reply... */ case IPPROTO_ICMP: icmp = (struct icmphdr *) ((char *) ip + (ip->ihl << 2)); if (icmp->type == ICMP_ECHO) rreq_flags |= RREQ_GRATUITOUS; #ifdef DEBUG_PACKET DEBUG(LOG_INFO, 0, "packet_input: setting G flag for RREQ to %s", ip_to_str(dest_addr)); #endif break; default: } #ifdef DEBUG_PACKET DEBUG(LOG_INFO, 0, "packet_input: pkt to %s", ip_to_str(dest_addr)); #endif if (dev_name) ifindex = if_nametoindex(dev_name); else ifindex = 0; #endif /* NS_PORT */ /* If the packet is not interesting we just let it go through... */ if ((dest_addr == AODV_BROADCAST) || (dest_addr == DEV_IFINDEX(ifindex).ipaddr) || (dest_addr == DEV_IFINDEX(ifindex).broadcast) || ((internet_gw_mode && this_host.gateway_mode) && ((dest_addr & DEV_IFINDEX(ifindex).netmask) != DEV_IFINDEX(ifindex).broadcast))) goto accept; /* Find the entry of the neighboring node and the destination (if any). */ rev_rt = rt_table_find_active(src_addr); fwd_rt = rt_table_find_active(dest_addr); /* If a packet is received on the NF_IP_PRE_ROUTING hook, i.e. inbound on the interface and we don't have a route to the destination, we should send an RERR to the source and then drop the package... */ /* NF_IP_PRE_ROUTING = 0 */ #ifdef NS_PORT #define PACKET_IS_INBOUND ch->direction() == hdr_cmn::UP #else #define PACKET_IS_INBOUND pkt->hook == 0 #endif if ((dest_addr != DEV_IFINDEX(ifindex).ipaddr) && (!fwd_rt && PACKET_IS_INBOUND)) { rt_table_t *rt_entry; u_int32_t rerr_dest; RERR *rerr; DEBUG(LOG_DEBUG, 0, "packet_input: Sending RERR for unknown dest %s", ip_to_str(dest_addr)); /* There is an expired entry in the routing table we want to send along the seqno in the RERR... */ rt_entry = rt_table_find(dest_addr); if (rt_entry) { rerr = rerr_create(0, rt_entry->dest_addr, rt_entry->dest_seqno); rt_table_update_timeout(rt_entry, DELETE_PERIOD); } else rerr = rerr_create(0, dest_addr, 0); /* Unicast the RERR to the source of the data transmission if * possible, otherwise we broadcast it. */ if (rev_rt) rerr_dest = rev_rt->next_hop; else rerr_dest = AODV_BROADCAST; aodv_socket_send((AODV_msg *) rerr, rerr_dest, RERR_CALC_SIZE(rerr), 1, &DEV_IFINDEX(ifindex)); if (wait_on_reboot) { DEBUG(LOG_DEBUG, 0, "packet_input: Wait on reboot timer reset."); timer_add_msec(&worb_timer, DELETE_PERIOD); } #ifdef NS_PORT drop(p, DROP_RTR_NO_ROUTE); #else status = ipq_set_verdict(h, pkt->packet_id, NF_DROP, 0, NULL); if (status < 0) die(h); #endif return; } /* Check if the route is currently in repair. In that case just buffer the packet */ repair_rt = rt_table_find(dest_addr); if (repair_rt && (repair_rt->flags & LREPAIR)) { #ifdef NS_PORT packet_queue_add(p, dest_addr); #else packet_queue_add(pkt->packet_id, dest_addr); #endif return; } /* update_timers: */ /* When forwarding a packet, we update the lifetime of the destination's routing table entry, as well as the entry for the next hop neighbor (if not the same). AODV draft 10, section 6.2. */ if (fwd_rt && dest_addr != DEV_IFINDEX(ifindex).ipaddr) { rt_table_update_timeout(fwd_rt, ACTIVE_ROUTE_TIMEOUT); next_hop_rt = rt_table_find_active(fwd_rt->next_hop); if (next_hop_rt && next_hop_rt->dest_addr != fwd_rt->dest_addr) rt_table_update_timeout(next_hop_rt, ACTIVE_ROUTE_TIMEOUT); } /* Also update the reverse route and reverse next hop along the path back, since routes between originators and the destination are expected to be symmetric. */ if (rev_rt) { rt_table_update_timeout(rev_rt, ACTIVE_ROUTE_TIMEOUT); next_hop_rt = rt_table_find_active(rev_rt->next_hop); if (next_hop_rt && next_hop_rt->dest_addr != fwd_rt->dest_addr) rt_table_update_timeout(next_hop_rt, ACTIVE_ROUTE_TIMEOUT); } #ifdef DEBUG_PACKET DEBUG(LOG_INFO, 0, "packet_input: d=%s s=%s", ip_to_str(dest_addr), ip_to_str(src_addr)); #endif /* DEBUG_PACKET */ if (!fwd_rt || (fwd_rt->hcnt == 1 && (fwd_rt->flags & UNIDIR))) { /* Buffer packets... Packets are queued by the ip_queue_aodv.o module already. We only need to save the handle id, and return the proper verdict when we know what to do... */ #ifdef NS_PORT packet_queue_add(p, dest_addr); #else packet_queue_add(pkt->packet_id, dest_addr); /* If the request is generated locally by an application, we save the IP header + 64 bits of data for sending an ICMP Destination Host Unreachable in case we don't find a route... */ if (src_addr == DEV_IFINDEX(ifindex).ipaddr) { ipd = (struct ip_data *) malloc(sizeof(struct ip_data)); if (ipd < 0) { perror("Malloc for IP data failed!"); exit(-1); } ipd->len = (ip->ihl << 2) + 8; /* IP header + 64 bits data (8 bytes) */ memcpy(ipd->data, ip, ipd->len); } else ipd = NULL; #endif rreq_route_discovery(dest_addr, rreq_flags, ipd); return; } accept: #ifdef NS_PORT if (fwd_rt) sendPacket(p, fwd_rt->next_hop, 0.0); else drop(p, DROP_RTR_NO_ROUTE); #else status = ipq_set_verdict(h, pkt->packet_id, NF_ACCEPT, 0, NULL); if (status < 0) die(h); #endif return; }
int main(int argc, char **argv){ extern char *optarg; fd_set sset, rset; struct timeval timeout; int r, sel; time_t curtime, start, lastfrag1=0; /* Arrays for storing the Flow ID samples */ u_int32_t test1[NSAMPLES], test2[NSAMPLES]; unsigned int ntest1=0, ntest2=0; unsigned char testtype; static struct option longopts[] = { {"interface", required_argument, 0, 'i'}, {"src-address", required_argument, 0, 's'}, {"dst-address", required_argument, 0, 'd'}, {"hop-limit", required_argument, 0, 'A'}, {"link-src-addr", required_argument, 0, 'S'}, {"link-dst-addr", required_argument, 0, 'D'}, {"protocol", required_argument, 0, 'P'}, {"dst-port", no_argument, 0, 'p'}, {"flow-label-policy", no_argument, 0, 'W'}, {"verbose", no_argument, 0, 'v'}, {"help", no_argument, 0, 'h'} }; char shortopts[]= "i:s:d:A:S:D:P:p:Wvh"; char option; if(argc<=1){ usage(); exit(EXIT_FAILURE); } srandom(time(NULL)); hoplimit=64+random()%180; if(init_iface_data(&idata) == FAILURE){ puts("Error initializing internal data structure"); exit(EXIT_FAILURE); } while((r=getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) { option= r; switch(option) { case 'i': /* Interface */ strncpy(idata.iface, optarg, IFACE_LENGTH-1); idata.iface[IFACE_LENGTH-1]=0; idata.ifindex= if_nametoindex(idata.iface); idata.iface_f=TRUE; break; case 's': /* IPv6 Source Address */ if((charptr = strtok_r(optarg, "/", &lasts)) == NULL){ puts("Error in Source Address"); exit(EXIT_FAILURE); } if ( inet_pton(AF_INET6, charptr, &(idata.srcaddr)) <= 0){ puts("inet_pton(): Source Address not valid"); exit(EXIT_FAILURE); } idata.srcaddr_f = 1; if((charptr = strtok_r(NULL, " ", &lasts)) != NULL){ srcpreflen = atoi(charptr); if(srcpreflen>128){ puts("Prefix length error in IPv6 Source Address"); exit(EXIT_FAILURE); } sanitize_ipv6_prefix(&(idata.srcaddr), srcpreflen); srcprefix_f=1; } break; case 'd': /* IPv6 Destination Address */ if( inet_pton(AF_INET6, optarg, &(idata.dstaddr)) <= 0){ puts("inet_pton(): address not valid"); exit(EXIT_FAILURE); } idata.dstaddr_f = 1; break; case 'A': /* Hop Limit */ hoplimit= atoi(optarg); hoplimit_f=1; break; case 'S': /* Source Ethernet address */ if(ether_pton(optarg, &(idata.hsrcaddr), sizeof(idata.hsrcaddr)) == 0){ puts("Error in Source link-layer address."); exit(EXIT_FAILURE); } idata.hsrcaddr_f = 1; break; case 'D': /* Destination Ethernet Address */ if(ether_pton(optarg, &(idata.hdstaddr), sizeof(idata.hdstaddr)) == 0){ puts("Error in Source link-layer address."); exit(EXIT_FAILURE); } idata.hdstaddr_f = 1; break; case 'P': /* Protocol */ if(strncmp(optarg, "tcp", MAX_STRING_SIZE) == 0 || \ strncmp(optarg, "TCP", MAX_STRING_SIZE) == 0){ protocol= IPPROTO_TCP; } else if(strncmp(optarg, "udp", MAX_STRING_SIZE) == 0 || \ strncmp(optarg, "UDP", MAX_STRING_SIZE) == 0){ protocol= IPPROTO_UDP; } else{ puts("Unknown protocol type (valid types: 'tcp', 'udp')"); exit(EXIT_FAILURE); } protocol_f= 1; break; case 'p': /* Destination port */ dstport= atoi(optarg); dstport_f=1; break; case 'W': /* Assess the Flow Label generation policy of the target */ flowidp_f= 1; break; case 'v': /* Be verbose */ idata.verbose_f++; break; case 'h': /* Help */ print_help(); exit(EXIT_FAILURE); break; default: usage(); exit(EXIT_FAILURE); break; } /* switch */ } /* while(getopt) */ if(geteuid()) { puts("flow6 needs root privileges to run."); exit(EXIT_FAILURE); } if(!idata.iface_f){ if(idata.dstaddr_f && IN6_IS_ADDR_LINKLOCAL(&(idata.dstaddr))){ puts("Must specify a network interface for link-local destinations"); exit(EXIT_FAILURE); } } if(load_dst_and_pcap(&idata, LOAD_SRC_NXT_HOP) == FAILURE){ puts("Error while learning Souce Address and Next Hop"); exit(EXIT_FAILURE); } release_privileges(); if( !fragh_f && dstoptuhdr_f){ puts("Dst. Options Header (Unfragmentable Part) set, but Fragmentation not specified"); exit(EXIT_FAILURE); } if(idata.verbose_f){ print_attack_info(); } if(!idata.dstaddr_f){ puts("Error: Nothing to send! (Destination Address left unspecified)"); exit(EXIT_FAILURE); } /* Assess the Flow ID generation policy */ if(flowidp_f){ if(dstport_f && !protocol_f){ puts("Error: Must specify a protocol if the port number is specified"); exit(EXIT_FAILURE); } if(!protocol_f){ protocol= IPPROTO_TCP; dstport= 80; } else if(!dstport_f){ if(protocol == IPPROTO_TCP) dstport= 80; else dstport= 53; } puts("Identifying the 'Flow ID' generation policy of the target node...."); if(protocol == IPPROTO_TCP){ tcpwin= ((u_int16_t) random() + 1500) & (u_int16_t)0x7f00; tcpseq= random(); baseport= 50000+ random()%10000; lastport= baseport; } /* Set filter for receiving Neighbor Solicitations, and TCP segments */ if(pcap_compile(idata.pfd, &pcap_filter, PCAP_NSTCP_FILTER, PCAP_OPT, PCAP_NETMASK_UNKNOWN) == -1){ printf("pcap_compile(): %s", pcap_geterr(idata.pfd)); exit(EXIT_FAILURE); } if(pcap_setfilter(idata.pfd, &pcap_filter) == -1){ printf("pcap_setfilter(): %s", pcap_geterr(idata.pfd)); exit(EXIT_FAILURE); } pcap_freecode(&pcap_filter); FD_ZERO(&sset); FD_SET(idata.fd, &sset); start= time(NULL); lastfrag1=0; ntest1=0; ntest2=0; testtype= FIXED_ORIGIN; if(srcprefix_f){ randprefix= idata.srcaddr; randpreflen=srcpreflen; } else{ randprefix= idata.srcaddr; randpreflen=64; sanitize_ipv6_prefix(&randprefix, randpreflen); } while(1){ curtime=time(NULL); if( testtype==FIXED_ORIGIN && ((curtime - start) >= ID_ASSESS_TIMEOUT || ntest1 >= NSAMPLES)){ testtype= MULTI_ORIGIN; addr_sig= random(); addr_key= random(); start= curtime; continue; } else if( testtype==MULTI_ORIGIN && ((curtime - start) >= ID_ASSESS_TIMEOUT || ntest2 >= NSAMPLES)){ break; } if((curtime - lastfrag1) >= 1){ if(testtype == FIXED_ORIGIN){ for(i=0; i<NSAMPLES; i++){ if(send_fid_probe() == -1){ puts("Error while sending packet"); exit(EXIT_FAILURE); } lastport++; } } else{ for(i=0; i<NSAMPLES; i++){ randomize_ipv6_addr(&(idata.srcaddr), &randprefix, randpreflen); /* * Two words of the Source IPv6 Address are specially encoded such that we only respond * to Neighbor Solicitations that target those addresses, and accept ICMPv6 Echo Replies * only if they are destined to those addresses */ idata.srcaddr.s6_addr16[5]= addr_sig; idata.srcaddr.s6_addr16[7] = idata.srcaddr.s6_addr16[6] ^ addr_key; if(send_neighbor_solicit(&idata, &(idata.dstaddr)) == -1){ puts("Error while sending Neighbor Solicitation"); exit(EXIT_FAILURE); } if(send_fid_probe() == -1){ puts("Error while sending packet"); exit(EXIT_FAILURE); } lastport++; } } lastfrag1=curtime; continue; } rset= sset; timeout.tv_usec=0; timeout.tv_sec= 1; if((sel=select(idata.fd+1, &rset, NULL, NULL, &timeout)) == -1){ if(errno == EINTR){ continue; } else{ puts("Error in select()"); exit(EXIT_FAILURE); } } if(sel == 0) continue; /* Read a packet (Echo Reply, or Neighbor Solicitation) */ if((r=pcap_next_ex(idata.pfd, &pkthdr, &pktdata)) == -1){ printf("pcap_next_ex(): %s", pcap_geterr(idata.pfd)); exit(EXIT_FAILURE); } else if(r == 0){ continue; /* Should never happen */ } pkt_ether = (struct ether_header *) pktdata; pkt_ipv6 = (struct ip6_hdr *)((char *) pkt_ether + idata.linkhsize); pkt_icmp6 = (struct icmp6_hdr *) ((char *) pkt_ipv6 + sizeof(struct ip6_hdr)); pkt_end = (unsigned char *) pktdata + pkthdr->caplen; if( (pkt_end - pktdata) < (idata.linkhsize + MIN_IPV6_HLEN)) continue; if(pkt_ipv6->ip6_nxt == IPPROTO_ICMPV6 && pkt_icmp6->icmp6_type == ND_NEIGHBOR_SOLICIT){ pkt_ns= (struct nd_neighbor_solicit *) pkt_icmp6; if( (pkt_end - (unsigned char *) pkt_ns) < sizeof(struct nd_neighbor_solicit)) continue; /* If the addresses that we're using are not actually configured on the local system (i.e., they are "spoofed", we must check whether it is a Neighbor Solicitation for one of our addresses, and respond with a Neighbor Advertisement. Otherwise, the kernel will take care of that. */ if(testtype==FIXED_ORIGIN){ if(!localaddr_f && is_eq_in6_addr(&(pkt_ns->nd_ns_target), &(idata.srcaddr))){ if(send_neighbor_advert(&idata, idata.pfd, pktdata) == -1){ puts("Error sending Neighbor Advertisement"); exit(EXIT_FAILURE); } } } else{ if(pkt_ns->nd_ns_target.s6_addr16[5] != addr_sig || \ pkt_ns->nd_ns_target.s6_addr16[7] != (pkt_ns->nd_ns_target.s6_addr16[6] ^ addr_key)) continue; if(send_neighbor_advert(&idata, idata.pfd, pktdata) == -1){ puts("Error sending Neighbor Advertisement"); exit(EXIT_FAILURE); } } } else if(pkt_ipv6->ip6_nxt == protocol){ /* Perform TCP-specific validation checks */ if(protocol == IPPROTO_TCP){ if( (pkt_end - (unsigned char *) pkt_ipv6) < \ (sizeof(struct ip6_hdr) + sizeof(struct tcp_hdr))) continue; pkt_tcp= (struct tcp_hdr *) ((unsigned char *)pkt_ipv6 + sizeof(struct ip6_hdr)); /* * The TCP Destination Port must correspond to one of the ports that we have used as * TCP Source Port */ if(ntohs(pkt_tcp->th_dport) < baseport || ntohs(pkt_tcp->th_dport) > lastport) continue; /* The Source Port must be that to which we're sending our TCP segments */ if(ntohs(pkt_tcp->th_sport) != dstport) continue; /* The TCP Acknowledgement Number must ack our SYN */ if(ntohl(pkt_tcp->th_ack) != tcpseq+1) continue; /* We sample Flow ID's only on SYN/ACKs */ if( (pkt_tcp->th_flags & ~TH_SYN) == 0 || (pkt_tcp->th_flags & TH_ACK) == 0) continue; /* The TCP checksum must be valid */ if(in_chksum(pkt_ipv6, pkt_tcp, pkt_end-((unsigned char *)pkt_tcp), IPPROTO_TCP) != 0) continue; } /* Perform UDP-specific validation checks */ else if(protocol == IPPROTO_UDP){ if( (pkt_end - (unsigned char *) pkt_ipv6) < \ (sizeof(struct ip6_hdr) + sizeof(struct udp_hdr))) continue; pkt_udp= (struct udp_hdr *) ((unsigned char *)pkt_ipv6 + sizeof(struct ip6_hdr)); /* * The UDP Destination Port must correspond to one of the ports that we have used as * the UDP Source Port */ if(ntohs(pkt_udp->uh_dport) < baseport || ntohs(pkt_udp->uh_dport) > lastport) continue; /* The Source Port must be that to which we're sending our UDP datagrams */ if(ntohs(pkt_udp->uh_sport) != dstport) continue; /* The UDP checksum must be valid */ if(in_chksum(pkt_ipv6, pkt_udp, pkt_end-((unsigned char *)pkt_udp), IPPROTO_UDP) != 0) continue; } if(testtype==FIXED_ORIGIN){ if(!is_eq_in6_addr(&(pkt_ipv6->ip6_dst), &(idata.srcaddr))){ continue; } if(ntest1 >= NSAMPLES) continue; test1[ntest1]= ntohl(pkt_ipv6->ip6_flow) & 0x000fffff; ntest1++; } else{ if(pkt_ipv6->ip6_dst.s6_addr16[5] != addr_sig || \ pkt_ipv6->ip6_dst.s6_addr16[7] != (pkt_ipv6->ip6_dst.s6_addr16[6] ^ addr_key)){ continue; } if(ntest2 >= NSAMPLES) continue; test2[ntest2]= ntohl(pkt_ipv6->ip6_flow) & 0x000fffff; ntest2++; } } } if(idata.verbose_f > 1){ printf("Sampled %u Flow Labels from single-origin probes\n", ntest1); for(i=0; i<ntest1; i++) printf("#%02u: %05x\n", (i+1), test1[i]); printf("\nSampled %u Flow Labels from multi-origin probes\n", ntest2); for(i=0; i<ntest2; i++) printf("#%02u: %05x\n", (i+1), test2[i]); puts(""); } if(ntest1 < 10 || ntest2 < 10){ puts("Error: Didn't receive enough response packets"); exit(EXIT_FAILURE); } if(predict_flow_id(test1, ntest1, test2, ntest2) == -1){ puts("Error in predict_flow_id()"); exit(EXIT_FAILURE); } exit(EXIT_SUCCESS); } exit(EXIT_SUCCESS); }
void reader_tpacketv3_init(char *UNUSED(name)) { int i; int blocksize = moloch_config_int(NULL, "tpacketv3BlockSize", 1<<21, 1<<16, 1<<31); numThreads = moloch_config_int(NULL, "tpacketv3NumThreads", 2, 1, 6); if (blocksize % getpagesize() != 0) { LOGEXIT("block size %d not divisible by pagesize %d", blocksize, getpagesize()); } if (blocksize % config.snapLen != 0) { LOGEXIT("block size %d not divisible by %d", blocksize, config.snapLen); } moloch_packet_set_linksnap(1, config.snapLen); pcap_t *dpcap = pcap_open_dead(pcapFileHeader.linktype, pcapFileHeader.snaplen); if (config.bpf) { if (pcap_compile(dpcap, &bpf, config.bpf, 1, PCAP_NETMASK_UNKNOWN) == -1) { LOGEXIT("ERROR - Couldn't compile filter: '%s' with %s", config.bpf, pcap_geterr(dpcap)); } } for (i = 0; i < MAX_INTERFACES && config.interface[i]; i++) { MOLOCH_LOCK_INIT(infos[i].lock); int ifindex = if_nametoindex(config.interface[i]); infos[i].fd = socket(AF_PACKET, SOCK_RAW, 0); int version = TPACKET_V3; if (setsockopt(infos[i].fd, SOL_PACKET, PACKET_VERSION, &version, sizeof(version)) < 0) LOGEXIT("Error setting TPACKET_V3, might need a newer kernel: %s", strerror(errno)); memset(&infos[i].req, 0, sizeof(infos[i].req)); infos[i].req.tp_block_size = blocksize; infos[i].req.tp_block_nr = numThreads*64; infos[i].req.tp_frame_size = config.snapLen; infos[i].req.tp_frame_nr = (blocksize * infos[i].req.tp_block_nr) / infos[i].req.tp_frame_size; infos[i].req.tp_retire_blk_tov = 60; infos[i].req.tp_feature_req_word = 0; if (setsockopt(infos[i].fd, SOL_PACKET, PACKET_RX_RING, &infos[i].req, sizeof(infos[i].req)) < 0) LOGEXIT("Error setting PACKET_RX_RING: %s", strerror(errno)); struct packet_mreq mreq; memset(&mreq, 0, sizeof(mreq)); mreq.mr_ifindex = ifindex; mreq.mr_type = PACKET_MR_PROMISC; if (setsockopt(infos[i].fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) LOGEXIT("Error setting PROMISC: %s", strerror(errno)); if (config.bpf) { struct sock_fprog fcode; fcode.len = bpf.bf_len; fcode.filter = (struct sock_filter *)bpf.bf_insns; if (setsockopt(infos[i].fd, SOL_SOCKET, SO_ATTACH_FILTER, &fcode, sizeof(fcode)) < 0) LOGEXIT("Error setting SO_ATTACH_FILTER: %s", strerror(errno)); } infos[i].map = mmap64(NULL, infos[i].req.tp_block_size * infos[i].req.tp_block_nr, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED, infos[i].fd, 0); if (unlikely(infos[i].map == MAP_FAILED)) { LOGEXIT("ERROR - MMap64 failure in reader_tpacketv3_init, %d: %s",errno, strerror(errno)); } infos[i].rd = malloc(infos[i].req.tp_block_nr * sizeof(struct iovec)); uint16_t j; for (j = 0; j < infos[i].req.tp_block_nr; j++) { infos[i].rd[j].iov_base = infos[i].map + (j * infos[i].req.tp_block_size); infos[i].rd[j].iov_len = infos[i].req.tp_block_size; } struct sockaddr_ll ll; memset(&ll, 0, sizeof(ll)); ll.sll_family = PF_PACKET; ll.sll_protocol = htons(ETH_P_ALL); ll.sll_ifindex = ifindex; if (bind(infos[i].fd, (struct sockaddr *) &ll, sizeof(ll)) < 0) LOGEXIT("Error binding %s: %s", config.interface[i], strerror(errno)); } if (i == MAX_INTERFACES) { LOGEXIT("Only support up to %d interfaces", MAX_INTERFACES); } moloch_reader_start = reader_tpacketv3_start; moloch_reader_stop = reader_tpacketv3_stop; moloch_reader_stats = reader_tpacketv3_stats; }
static int iptunnel_parse_opt(struct link_util *lu, int argc, char **argv, struct nlmsghdr *n) { struct { struct nlmsghdr n; struct ifinfomsg i; char buf[2048]; } req; struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1); struct rtattr *tb[IFLA_MAX + 1]; struct rtattr *linkinfo[IFLA_INFO_MAX+1]; struct rtattr *iptuninfo[IFLA_IPTUN_MAX + 1]; int len; __u32 link = 0; __u32 laddr = 0; __u32 raddr = 0; __u8 ttl = 0; __u8 tos = 0; __u8 pmtudisc = 1; __u16 iflags = 0; __u8 proto = 0; struct in6_addr ip6rdprefix; __u16 ip6rdprefixlen = 0; __u32 ip6rdrelayprefix = 0; __u16 ip6rdrelayprefixlen = 0; memset(&ip6rdprefix, 0, sizeof(ip6rdprefix)); if (!(n->nlmsg_flags & NLM_F_CREATE)) { memset(&req, 0, sizeof(req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)); req.n.nlmsg_flags = NLM_F_REQUEST; req.n.nlmsg_type = RTM_GETLINK; req.i.ifi_family = preferred_family; req.i.ifi_index = ifi->ifi_index; if (rtnl_talk(&rth, &req.n, 0, 0, &req.n) < 0) { get_failed: fprintf(stderr, "Failed to get existing tunnel info.\n"); return -1; } len = req.n.nlmsg_len; len -= NLMSG_LENGTH(sizeof(*ifi)); if (len < 0) goto get_failed; parse_rtattr(tb, IFLA_MAX, IFLA_RTA(&req.i), len); if (!tb[IFLA_LINKINFO]) goto get_failed; parse_rtattr_nested(linkinfo, IFLA_INFO_MAX, tb[IFLA_LINKINFO]); if (!linkinfo[IFLA_INFO_DATA]) goto get_failed; parse_rtattr_nested(iptuninfo, IFLA_IPTUN_MAX, linkinfo[IFLA_INFO_DATA]); if (iptuninfo[IFLA_IPTUN_LOCAL]) laddr = rta_getattr_u32(iptuninfo[IFLA_IPTUN_LOCAL]); if (iptuninfo[IFLA_IPTUN_REMOTE]) raddr = rta_getattr_u32(iptuninfo[IFLA_IPTUN_REMOTE]); if (iptuninfo[IFLA_IPTUN_TTL]) ttl = rta_getattr_u8(iptuninfo[IFLA_IPTUN_TTL]); if (iptuninfo[IFLA_IPTUN_TOS]) tos = rta_getattr_u8(iptuninfo[IFLA_IPTUN_TOS]); if (iptuninfo[IFLA_IPTUN_PMTUDISC]) pmtudisc = rta_getattr_u8(iptuninfo[IFLA_IPTUN_PMTUDISC]); if (iptuninfo[IFLA_IPTUN_FLAGS]) iflags = rta_getattr_u16(iptuninfo[IFLA_IPTUN_FLAGS]); if (iptuninfo[IFLA_IPTUN_LINK]) link = rta_getattr_u32(iptuninfo[IFLA_IPTUN_LINK]); if (iptuninfo[IFLA_IPTUN_PROTO]) proto = rta_getattr_u8(iptuninfo[IFLA_IPTUN_PROTO]); if (iptuninfo[IFLA_IPTUN_6RD_PREFIX]) memcpy(&ip6rdprefix, RTA_DATA(iptuninfo[IFLA_IPTUN_6RD_PREFIX]), sizeof(laddr)); if (iptuninfo[IFLA_IPTUN_6RD_PREFIXLEN]) ip6rdprefixlen = rta_getattr_u16(iptuninfo[IFLA_IPTUN_6RD_PREFIXLEN]); if (iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIX]) ip6rdrelayprefix = rta_getattr_u32(iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIX]); if (iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]) ip6rdrelayprefixlen = rta_getattr_u16(iptuninfo[IFLA_IPTUN_6RD_RELAY_PREFIXLEN]); } while (argc > 0) { if (strcmp(*argv, "remote") == 0) { NEXT_ARG(); if (strcmp(*argv, "any")) raddr = get_addr32(*argv); else raddr = 0; } else if (strcmp(*argv, "local") == 0) { NEXT_ARG(); if (strcmp(*argv, "any")) laddr = get_addr32(*argv); else laddr = 0; } else if (matches(*argv, "dev") == 0) { NEXT_ARG(); link = if_nametoindex(*argv); if (link == 0) invarg("\"dev\" is invalid", *argv); } else if (strcmp(*argv, "ttl") == 0 || strcmp(*argv, "hoplimit") == 0) { NEXT_ARG(); if (strcmp(*argv, "inherit") != 0) { if (get_u8(&ttl, *argv, 0)) invarg("invalid TTL\n", *argv); } else ttl = 0; } else if (strcmp(*argv, "tos") == 0 || strcmp(*argv, "tclass") == 0 || matches(*argv, "dsfield") == 0) { __u32 uval; NEXT_ARG(); if (strcmp(*argv, "inherit") != 0) { if (rtnl_dsfield_a2n(&uval, *argv)) invarg("bad TOS value", *argv); tos = uval; } else tos = 1; } else if (strcmp(*argv, "nopmtudisc") == 0) { pmtudisc = 0; } else if (strcmp(*argv, "pmtudisc") == 0) { pmtudisc = 1; } else if (strcmp(lu->id, "sit") == 0 && strcmp(*argv, "isatap") == 0) { iflags |= SIT_ISATAP; } else if (strcmp(lu->id, "sit") == 0 && strcmp(*argv, "mode") == 0) { NEXT_ARG(); if (strcmp(*argv, "ipv6/ipv4") == 0 || strcmp(*argv, "ip6ip") == 0) proto = IPPROTO_IPV6; else if (strcmp(*argv, "ipv4/ipv4") == 0 || strcmp(*argv, "ipip") == 0 || strcmp(*argv, "ip4ip4") == 0) proto = IPPROTO_IPIP; else if (strcmp(*argv, "any/ipv4") == 0 || strcmp(*argv, "any") == 0) proto = 0; else invarg("Cannot guess tunnel mode.", *argv); } else if (strcmp(*argv, "6rd-prefix") == 0) { inet_prefix prefix; NEXT_ARG(); if (get_prefix(&prefix, *argv, AF_INET6)) invarg("invalid 6rd_prefix\n", *argv); memcpy(&ip6rdprefix, prefix.data, 16); ip6rdprefixlen = prefix.bitlen; } else if (strcmp(*argv, "6rd-relay_prefix") == 0) { inet_prefix prefix; NEXT_ARG(); if (get_prefix(&prefix, *argv, AF_INET)) invarg("invalid 6rd-relay_prefix\n", *argv); memcpy(&ip6rdrelayprefix, prefix.data, 4); ip6rdrelayprefixlen = prefix.bitlen; } else if (strcmp(*argv, "6rd-reset") == 0) { inet_prefix prefix; get_prefix(&prefix, "2002::", AF_INET6); memcpy(&ip6rdprefix, prefix.data, 16); ip6rdprefixlen = 16; ip6rdrelayprefix = 0; ip6rdrelayprefixlen = 0; } else usage(strcmp(lu->id, "sit") == 0); argc--, argv++; } if (ttl && pmtudisc == 0) { fprintf(stderr, "ttl != 0 and noptmudisc are incompatible\n"); exit(-1); } addattr32(n, 1024, IFLA_IPTUN_LINK, link); addattr32(n, 1024, IFLA_IPTUN_LOCAL, laddr); addattr32(n, 1024, IFLA_IPTUN_REMOTE, raddr); addattr8(n, 1024, IFLA_IPTUN_TTL, ttl); addattr8(n, 1024, IFLA_IPTUN_TOS, tos); addattr8(n, 1024, IFLA_IPTUN_PMTUDISC, pmtudisc); if (strcmp(lu->id, "sit") == 0) { addattr16(n, 1024, IFLA_IPTUN_FLAGS, iflags); addattr8(n, 1024, IFLA_IPTUN_PROTO, proto); if (ip6rdprefixlen) { addattr_l(n, 1024, IFLA_IPTUN_6RD_PREFIX, &ip6rdprefix, sizeof(ip6rdprefix)); addattr16(n, 1024, IFLA_IPTUN_6RD_PREFIXLEN, ip6rdprefixlen); addattr32(n, 1024, IFLA_IPTUN_6RD_RELAY_PREFIX, ip6rdrelayprefix); addattr16(n, 1024, IFLA_IPTUN_6RD_RELAY_PREFIXLEN, ip6rdrelayprefixlen); } } return 0; }
/* upnpDiscoverDevices() : * return a chained list of all devices found or NULL if * no devices was found. * It is up to the caller to free the chained list * delay is in millisecond (poll). * UDA v1.1 says : * The TTL for the IP packet SHOULD default to 2 and * SHOULD be configurable. */ MINIUPNP_LIBSPEC struct UPNPDev * upnpDiscoverDevices(const char * const deviceTypes[], int delay, const char * multicastif, const char * minissdpdsock, int sameport, int ipv6, unsigned char ttl, int * error, int searchalltypes) { struct UPNPDev * tmp; struct UPNPDev * devlist = 0; unsigned int scope_id = 0; int opt = 1; static const char MSearchMsgFmt[] = "M-SEARCH * HTTP/1.1\r\n" "HOST: %s:" XSTR(PORT) "\r\n" "ST: %s\r\n" "MAN: \"ssdp:discover\"\r\n" "MX: %u\r\n" "\r\n"; int deviceIndex; char bufr[1536]; /* reception and emission buffer */ int sudp; int n; struct sockaddr_storage sockudp_r; unsigned int mx; #ifdef NO_GETADDRINFO struct sockaddr_storage sockudp_w; #else int rv; struct addrinfo hints, *servinfo, *p; #endif #ifdef _WIN32 MIB_IPFORWARDROW ip_forward; #endif int linklocal = 1; if(error) *error = UPNPDISCOVER_UNKNOWN_ERROR; #if !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) /* first try to get infos from minissdpd ! */ if(!minissdpdsock) minissdpdsock = "/var/run/minissdpd.sock"; for(deviceIndex = 0; deviceTypes[deviceIndex]; deviceIndex++) { struct UPNPDev * minissdpd_devlist; int only_rootdevice = 1; minissdpd_devlist = getDevicesFromMiniSSDPD(deviceTypes[deviceIndex], minissdpdsock, 0); if(minissdpd_devlist) { #ifdef DEBUG printf("returned by MiniSSDPD: %s\t%s\n", minissdpd_devlist->st, minissdpd_devlist->descURL); #endif /* DEBUG */ if(!strstr(minissdpd_devlist->st, "rootdevice")) only_rootdevice = 0; for(tmp = minissdpd_devlist; tmp->pNext != NULL; tmp = tmp->pNext) { #ifdef DEBUG printf("returned by MiniSSDPD: %s\t%s\n", tmp->pNext->st, tmp->pNext->descURL); #endif /* DEBUG */ if(!strstr(tmp->st, "rootdevice")) only_rootdevice = 0; } tmp->pNext = devlist; devlist = minissdpd_devlist; if(!searchalltypes && !only_rootdevice) break; } } for(tmp = devlist; tmp != NULL; tmp = tmp->pNext) { /* We return what we have found if it was not only a rootdevice */ if(!strstr(tmp->st, "rootdevice")) { if(error) *error = UPNPDISCOVER_SUCCESS; return devlist; } } #endif /* !defined(_WIN32) && !defined(__amigaos__) && !defined(__amigaos4__) */ /* direct discovery if minissdpd responses are not sufficient */ #ifdef _WIN32 sudp = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, IPPROTO_UDP); #else sudp = socket(ipv6 ? PF_INET6 : PF_INET, SOCK_DGRAM, 0); #endif if(sudp < 0) { if(error) *error = UPNPDISCOVER_SOCKET_ERROR; PRINT_SOCKET_ERROR("socket"); return NULL; } /* reception */ memset(&sockudp_r, 0, sizeof(struct sockaddr_storage)); if(ipv6) { struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_r; p->sin6_family = AF_INET6; if(sameport) p->sin6_port = htons(PORT); p->sin6_addr = in6addr_any; /* in6addr_any is not available with MinGW32 3.4.2 */ } else { struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_r; p->sin_family = AF_INET; if(sameport) p->sin_port = htons(PORT); p->sin_addr.s_addr = INADDR_ANY; } #ifdef _WIN32 /* This code could help us to use the right Network interface for * SSDP multicast traffic */ /* Get IP associated with the index given in the ip_forward struct * in order to give this ip to setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF) */ if(!ipv6 && (GetBestRoute(inet_addr("223.255.255.255"), 0, &ip_forward) == NO_ERROR)) { DWORD dwRetVal = 0; PMIB_IPADDRTABLE pIPAddrTable; DWORD dwSize = 0; #ifdef DEBUG IN_ADDR IPAddr; #endif int i; #ifdef DEBUG printf("ifIndex=%lu nextHop=%lx \n", ip_forward.dwForwardIfIndex, ip_forward.dwForwardNextHop); #endif pIPAddrTable = (MIB_IPADDRTABLE *) malloc(sizeof (MIB_IPADDRTABLE)); if(pIPAddrTable) { if (GetIpAddrTable(pIPAddrTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) { free(pIPAddrTable); pIPAddrTable = (MIB_IPADDRTABLE *) malloc(dwSize); } } if(pIPAddrTable) { dwRetVal = GetIpAddrTable( pIPAddrTable, &dwSize, 0 ); #ifdef DEBUG printf("\tNum Entries: %ld\n", pIPAddrTable->dwNumEntries); #endif for (i=0; i < (int) pIPAddrTable->dwNumEntries; i++) { #ifdef DEBUG printf("\n\tInterface Index[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwIndex); IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwAddr; printf("\tIP Address[%d]: \t%s\n", i, inet_ntoa(IPAddr) ); IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwMask; printf("\tSubnet Mask[%d]: \t%s\n", i, inet_ntoa(IPAddr) ); IPAddr.S_un.S_addr = (u_long) pIPAddrTable->table[i].dwBCastAddr; printf("\tBroadCast[%d]: \t%s (%ld)\n", i, inet_ntoa(IPAddr), pIPAddrTable->table[i].dwBCastAddr); printf("\tReassembly size[%d]:\t%ld\n", i, pIPAddrTable->table[i].dwReasmSize); printf("\tType and State[%d]:", i); printf("\n"); #endif if (pIPAddrTable->table[i].dwIndex == ip_forward.dwForwardIfIndex) { /* Set the address of this interface to be used */ struct in_addr mc_if; memset(&mc_if, 0, sizeof(mc_if)); mc_if.s_addr = pIPAddrTable->table[i].dwAddr; if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) { PRINT_SOCKET_ERROR("setsockopt"); } ((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = pIPAddrTable->table[i].dwAddr; #ifndef DEBUG break; #endif } } free(pIPAddrTable); pIPAddrTable = NULL; } } #endif /* _WIN32 */ #ifdef _WIN32 if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, (const char *)&opt, sizeof (opt)) < 0) #else if (setsockopt(sudp, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)) < 0) #endif { if(error) *error = UPNPDISCOVER_SOCKET_ERROR; PRINT_SOCKET_ERROR("setsockopt(SO_REUSEADDR,...)"); return NULL; } if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0) { /* not a fatal error */ PRINT_SOCKET_ERROR("setsockopt(IP_MULTICAST_TTL,...)"); } if(multicastif) { if(ipv6) { #if !defined(_WIN32) /* according to MSDN, if_nametoindex() is supported since * MS Windows Vista and MS Windows Server 2008. * http://msdn.microsoft.com/en-us/library/bb408409%28v=vs.85%29.aspx */ unsigned int ifindex = if_nametoindex(multicastif); /* eth0, etc. */ if(setsockopt(sudp, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex)) < 0) { PRINT_SOCKET_ERROR("setsockopt"); } #else #ifdef DEBUG printf("Setting of multicast interface not supported in IPv6 under Windows.\n"); #endif #endif } else { struct in_addr mc_if; mc_if.s_addr = inet_addr(multicastif); /* ex: 192.168.x.x */ if(mc_if.s_addr != INADDR_NONE) { ((struct sockaddr_in *)&sockudp_r)->sin_addr.s_addr = mc_if.s_addr; if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&mc_if, sizeof(mc_if)) < 0) { PRINT_SOCKET_ERROR("setsockopt"); } } else { #ifdef HAS_IP_MREQN /* was not an ip address, try with an interface name */ struct ip_mreqn reqn; /* only defined with -D_BSD_SOURCE or -D_GNU_SOURCE */ memset(&reqn, 0, sizeof(struct ip_mreqn)); reqn.imr_ifindex = if_nametoindex(multicastif); if(setsockopt(sudp, IPPROTO_IP, IP_MULTICAST_IF, (const char *)&reqn, sizeof(reqn)) < 0) { PRINT_SOCKET_ERROR("setsockopt"); } #else #ifdef DEBUG printf("Setting of multicast interface not supported with interface name.\n"); #endif #endif } } } /* Before sending the packed, we first "bind" in order to be able * to receive the response */ if (bind(sudp, (const struct sockaddr *)&sockudp_r, ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)) != 0) { if(error) *error = UPNPDISCOVER_SOCKET_ERROR; PRINT_SOCKET_ERROR("bind"); closesocket(sudp); return NULL; } if(error) *error = UPNPDISCOVER_SUCCESS; /* Calculating maximum response time in seconds */ mx = ((unsigned int)delay) / 1000u; if(mx == 0) { mx = 1; delay = 1000; } /* receiving SSDP response packet */ for(deviceIndex = 0; deviceTypes[deviceIndex]; deviceIndex++) { /* sending the SSDP M-SEARCH packet */ n = snprintf(bufr, sizeof(bufr), MSearchMsgFmt, ipv6 ? (linklocal ? "[" UPNP_MCAST_LL_ADDR "]" : "[" UPNP_MCAST_SL_ADDR "]") : UPNP_MCAST_ADDR, deviceTypes[deviceIndex], mx); #ifdef DEBUG /*printf("Sending %s", bufr);*/ printf("Sending M-SEARCH request to %s with ST: %s\n", ipv6 ? (linklocal ? "[" UPNP_MCAST_LL_ADDR "]" : "[" UPNP_MCAST_SL_ADDR "]") : UPNP_MCAST_ADDR, deviceTypes[deviceIndex]); #endif #ifdef NO_GETADDRINFO /* the following code is not using getaddrinfo */ /* emission */ memset(&sockudp_w, 0, sizeof(struct sockaddr_storage)); if(ipv6) { struct sockaddr_in6 * p = (struct sockaddr_in6 *)&sockudp_w; p->sin6_family = AF_INET6; p->sin6_port = htons(PORT); inet_pton(AF_INET6, linklocal ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_SL_ADDR, &(p->sin6_addr)); } else { struct sockaddr_in * p = (struct sockaddr_in *)&sockudp_w; p->sin_family = AF_INET; p->sin_port = htons(PORT); p->sin_addr.s_addr = inet_addr(UPNP_MCAST_ADDR); } n = sendto(sudp, bufr, n, 0, &sockudp_w, ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in)); if (n < 0) { if(error) *error = UPNPDISCOVER_SOCKET_ERROR; PRINT_SOCKET_ERROR("sendto"); break; } #else /* #ifdef NO_GETADDRINFO */ memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; /* AF_INET6 or AF_INET */ hints.ai_socktype = SOCK_DGRAM; /*hints.ai_flags = */ if ((rv = getaddrinfo(ipv6 ? (linklocal ? UPNP_MCAST_LL_ADDR : UPNP_MCAST_SL_ADDR) : UPNP_MCAST_ADDR, XSTR(PORT), &hints, &servinfo)) != 0) { if(error) *error = UPNPDISCOVER_SOCKET_ERROR; #ifdef _WIN32 fprintf(stderr, "getaddrinfo() failed: %d\n", rv); #else fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); #endif break; } for(p = servinfo; p; p = p->ai_next) { n = sendto(sudp, bufr, n, 0, p->ai_addr, p->ai_addrlen); if (n < 0) { #ifdef DEBUG char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV]; if (getnameinfo(p->ai_addr, p->ai_addrlen, hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) == 0) { fprintf(stderr, "host:%s port:%s\n", hbuf, sbuf); } #endif PRINT_SOCKET_ERROR("sendto"); continue; } } freeaddrinfo(servinfo); if(n < 0) { if(error) *error = UPNPDISCOVER_SOCKET_ERROR; break; } #endif /* #ifdef NO_GETADDRINFO */ /* Waiting for SSDP REPLY packet to M-SEARCH * if searchalltypes is set, enter the loop only * when the last deviceType is reached */ if(!searchalltypes || !deviceTypes[deviceIndex + 1]) do { n = receivedata(sudp, bufr, sizeof(bufr), delay, &scope_id); if (n < 0) { /* error */ if(error) *error = UPNPDISCOVER_SOCKET_ERROR; goto error; } else if (n == 0) { /* no data or Time Out */ #ifdef DEBUG printf("NODATA or TIMEOUT\n"); #endif /* DEBUG */ if (devlist && !searchalltypes) { /* found some devices, stop now*/ if(error) *error = UPNPDISCOVER_SUCCESS; goto error; } } else { const char * descURL=NULL; int urlsize=0; const char * st=NULL; int stsize=0; const char * usn=NULL; int usnsize=0; parseMSEARCHReply(bufr, n, &descURL, &urlsize, &st, &stsize, &usn, &usnsize); if(st&&descURL) { #ifdef DEBUG printf("M-SEARCH Reply:\n ST: %.*s\n USN: %.*s\n Location: %.*s\n", stsize, st, usnsize, (usn?usn:""), urlsize, descURL); #endif /* DEBUG */ for(tmp=devlist; tmp; tmp = tmp->pNext) { if(memcmp(tmp->descURL, descURL, urlsize) == 0 && tmp->descURL[urlsize] == '\0' && memcmp(tmp->st, st, stsize) == 0 && tmp->st[stsize] == '\0' && (usnsize == 0 || memcmp(tmp->usn, usn, usnsize) == 0) && tmp->usn[usnsize] == '\0') break; } /* at the exit of the loop above, tmp is null if * no duplicate device was found */ if(tmp) continue; tmp = (struct UPNPDev *)malloc(sizeof(struct UPNPDev)+urlsize+stsize+usnsize); if(!tmp) { /* memory allocation error */ if(error) *error = UPNPDISCOVER_MEMORY_ERROR; goto error; } tmp->pNext = devlist; tmp->descURL = tmp->buffer; tmp->st = tmp->buffer + 1 + urlsize; tmp->usn = tmp->st + 1 + stsize; memcpy(tmp->buffer, descURL, urlsize); tmp->buffer[urlsize] = '\0'; memcpy(tmp->st, st, stsize); tmp->buffer[urlsize+1+stsize] = '\0'; if(usn != NULL) memcpy(tmp->usn, usn, usnsize); tmp->buffer[urlsize+1+stsize+1+usnsize] = '\0'; tmp->scope_id = scope_id; devlist = tmp; } } } while(n > 0); if(ipv6) { /* switch linklocal flag */ if(linklocal) { linklocal = 0; --deviceIndex; } else { linklocal = 1; } } } error: closesocket(sudp); return devlist; }
static QNetworkInterfacePrivate *findInterface(int socket, QList<QNetworkInterfacePrivate *> &interfaces, struct ifreq &req) { QNetworkInterfacePrivate *iface = 0; int ifindex = 0; #ifndef QT_NO_IPV6IFNAME // Get the interface index ifindex = if_nametoindex(req.ifr_name); // find the interface data QList<QNetworkInterfacePrivate *>::Iterator if_it = interfaces.begin(); for ( ; if_it != interfaces.end(); ++if_it) if ((*if_it)->index == ifindex) { // existing interface iface = *if_it; break; } #else // Search by name QList<QNetworkInterfacePrivate *>::Iterator if_it = interfaces.begin(); for ( ; if_it != interfaces.end(); ++if_it) if ((*if_it)->name == QLatin1String(req.ifr_name)) { // existing interface iface = *if_it; break; } #endif if (!iface) { // new interface, create data: iface = new QNetworkInterfacePrivate; iface->index = ifindex; interfaces << iface; #ifdef SIOCGIFNAME // Get the canonical name QByteArray oldName = req.ifr_name; if (qt_safe_ioctl(socket, SIOCGIFNAME, &req) >= 0) { iface->name = QString::fromLatin1(req.ifr_name); // reset the name: memcpy(req.ifr_name, oldName, qMin<int>(oldName.length() + 1, sizeof(req.ifr_name) - 1)); } else #endif { // use this name anyways iface->name = QString::fromLatin1(req.ifr_name); } // Get interface flags if (qt_safe_ioctl(socket, SIOCGIFFLAGS, &req) >= 0) { iface->flags = convertFlags(req.ifr_flags); } #ifdef SIOCGIFHWADDR // Get the HW address if (qt_safe_ioctl(socket, SIOCGIFHWADDR, &req) >= 0) { uchar *addr = (uchar *)req.ifr_addr.sa_data; iface->hardwareAddress = iface->makeHwAddress(6, addr); } #endif } return iface; }
static void ping(const char *host) { char packet[datalen + MAXIPLEN + MAXICMPLEN]; char buf[INET6_ADDRSTRLEN]; int sockopt; struct msghdr msg; struct sockaddr_in6 from; struct iovec iov; char control_buf[CMSG_SPACE(36)]; pingsock = create_icmp6_socket(); memset(&pingaddr, 0, sizeof(struct sockaddr_in)); pingaddr.sin6_family = AF_INET6; hostent = xgethostbyname2(host, AF_INET6); if (hostent->h_addrtype != AF_INET6) bb_error_msg_and_die("unknown address type; only AF_INET6 is currently supported."); memcpy(&pingaddr.sin6_addr, hostent->h_addr, sizeof(pingaddr.sin6_addr)); #ifdef ICMP6_FILTER { struct icmp6_filter filt; if (!(options & O_VERBOSE)) { ICMP6_FILTER_SETBLOCKALL(&filt); #if 0 if ((options & F_FQDN) || (options & F_FQDNOLD) || (options & F_NODEADDR) || (options & F_SUPTYPES)) ICMP6_FILTER_SETPASS(ICMP6_NI_REPLY, &filt); else #endif ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &filt); } else { ICMP6_FILTER_SETPASSALL(&filt); } if (setsockopt(pingsock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt, sizeof(filt)) < 0) bb_error_msg_and_die("setsockopt(ICMP6_FILTER)"); } #endif /*ICMP6_FILTER*/ /* enable broadcast pings */ sockopt = 1; setsockopt(pingsock, SOL_SOCKET, SO_BROADCAST, (char *) &sockopt, sizeof(sockopt)); /* set recv buf for broadcast pings */ sockopt = 48 * 1024; setsockopt(pingsock, SOL_SOCKET, SO_RCVBUF, (char *) &sockopt, sizeof(sockopt)); sockopt = offsetof(struct icmp6_hdr, icmp6_cksum); setsockopt(pingsock, SOL_RAW, IPV6_CHECKSUM, (char *) &sockopt, sizeof(sockopt)); sockopt = 1; setsockopt(pingsock, SOL_IPV6, IPV6_HOPLIMIT, (char *) &sockopt, sizeof(sockopt)); if (ifname) { if ((pingaddr.sin6_scope_id = if_nametoindex(ifname)) == 0) bb_error_msg_and_die("%s: invalid interface name", ifname); } printf("PING %s (%s): %d data bytes\n", hostent->h_name, inet_ntop(AF_INET6, (struct in_addr6 *) &pingaddr.sin6_addr, buf, sizeof(buf)), datalen); signal(SIGINT, pingstats); /* start the ping's going ... */ sendping(0); /* listen for replies */ msg.msg_name=&from; msg.msg_namelen=sizeof(from); msg.msg_iov=&iov; msg.msg_iovlen=1; msg.msg_control=control_buf; iov.iov_base=packet; iov.iov_len=sizeof(packet); while (1) { int c; struct cmsghdr *cmsgptr = NULL; int hoplimit=-1; msg.msg_controllen=sizeof(control_buf); if ((c = recvmsg(pingsock, &msg, 0)) < 0) { if (errno == EINTR) continue; bb_perror_msg("recvfrom"); continue; } for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) { if (cmsgptr->cmsg_level == SOL_IPV6 && cmsgptr->cmsg_type == IPV6_HOPLIMIT ) { hoplimit=*(int*)CMSG_DATA(cmsgptr); } } unpack(packet, c, &from, hoplimit); if (pingcount > 0 && nreceived >= pingcount) break; } pingstats(0); }
int main(void) { sd_netlink *rtnl; sd_netlink_message *m; sd_netlink_message *r; const char *string_data; int if_loopback; uint16_t type; test_match(); test_multiple(); assert_se(sd_netlink_open(&rtnl) >= 0); assert_se(rtnl); test_route(rtnl); test_message(rtnl); test_container(rtnl); if_loopback = (int) if_nametoindex("lo"); assert_se(if_loopback > 0); test_async(if_loopback); test_pipe(if_loopback); test_event_loop(if_loopback); test_link_configure(rtnl, if_loopback); test_get_addresses(rtnl); test_message_link_bridge(rtnl); assert_se(sd_rtnl_message_new_link(rtnl, &m, RTM_GETLINK, if_loopback) >= 0); assert_se(m); assert_se(sd_netlink_message_get_type(m, &type) >= 0); assert_se(type == RTM_GETLINK); assert_se(sd_netlink_message_read_string(m, IFLA_IFNAME, &string_data) == -EPERM); assert_se(sd_netlink_call(rtnl, m, 0, &r) == 1); assert_se(sd_netlink_message_get_type(r, &type) >= 0); assert_se(type == RTM_NEWLINK); assert_se((r = sd_netlink_message_unref(r)) == NULL); assert_se(sd_netlink_call(rtnl, m, -1, &r) == -EPERM); assert_se((m = sd_netlink_message_unref(m)) == NULL); assert_se((r = sd_netlink_message_unref(r)) == NULL); test_link_get(rtnl, if_loopback); test_address_get(rtnl, if_loopback); assert_se((m = sd_netlink_message_unref(m)) == NULL); assert_se((r = sd_netlink_message_unref(r)) == NULL); assert_se((rtnl = sd_netlink_unref(rtnl)) == NULL); return EXIT_SUCCESS; }
static isc_result_t internal_current4(isc_interfaceiter_t *iter) { struct ifreq *ifrp; struct ifreq ifreq; int family; char strbuf[BUFSIZ]; #if !defined(HAVE_STRUCT_IF_LADDRREQ) && defined(SIOCGLIFADDR) struct lifreq lifreq; #else char sabuf[256]; #endif int i, bits, prefixlen; REQUIRE(VALID_IFITER(iter)); if (iter->ifc.ifc_len == 0 || iter->pos == (unsigned int)iter->ifc.ifc_len) { #ifdef __linux return (linux_if_inet6_current(iter)); #else return (ISC_R_NOMORE); #endif } INSIST( iter->pos < (unsigned int) iter->ifc.ifc_len); ifrp = (void *)((char *) iter->ifc.ifc_req + iter->pos); memset(&ifreq, 0, sizeof(ifreq)); memcpy(&ifreq, ifrp, sizeof(ifreq)); family = ifreq.ifr_addr.sa_family; if (family != AF_INET && family != AF_INET6) return (ISC_R_IGNORE); memset(&iter->current, 0, sizeof(iter->current)); iter->current.af = family; INSIST(sizeof(ifreq.ifr_name) <= sizeof(iter->current.name)); memset(iter->current.name, 0, sizeof(iter->current.name)); memcpy(iter->current.name, ifreq.ifr_name, sizeof(ifreq.ifr_name)); get_addr(family, &iter->current.address, (struct sockaddr *)&ifrp->ifr_addr, ifreq.ifr_name); /* * If the interface does not have a address ignore it. */ switch (family) { case AF_INET: if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY)) return (ISC_R_IGNORE); break; case AF_INET6: if (memcmp(&iter->current.address.type.in6, &in6addr_any, sizeof(in6addr_any)) == 0) return (ISC_R_IGNORE); break; } /* * Get interface flags. */ iter->current.flags = 0; /* * Ignore the HP/UX warning about "integer overflow during * conversion. It comes from its own macro definition, * and is really hard to shut up. */ if (isc_ioctl(iter->socket, SIOCGIFFLAGS, (char *) &ifreq) < 0) { strerror_r(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "%s: getting interface flags: %s", ifreq.ifr_name, strbuf); return (ISC_R_IGNORE); } if ((ifreq.ifr_flags & IFF_UP) != 0) iter->current.flags |= INTERFACE_F_UP; #ifdef IFF_POINTOPOINT if ((ifreq.ifr_flags & IFF_POINTOPOINT) != 0) iter->current.flags |= INTERFACE_F_POINTTOPOINT; #endif if ((ifreq.ifr_flags & IFF_LOOPBACK) != 0) iter->current.flags |= INTERFACE_F_LOOPBACK; if ((ifreq.ifr_flags & IFF_BROADCAST) != 0) iter->current.flags |= INTERFACE_F_BROADCAST; #ifdef IFF_MULTICAST if ((ifreq.ifr_flags & IFF_MULTICAST) != 0) iter->current.flags |= INTERFACE_F_MULTICAST; #endif if (family == AF_INET) goto inet; #if !defined(HAVE_STRUCT_IF_LADDRREQ) && defined(SIOCGLIFADDR) memset(&lifreq, 0, sizeof(lifreq)); memcpy(lifreq.lifr_name, iter->current.name, sizeof(lifreq.lifr_name)); memcpy(&lifreq.lifr_addr, &iter->current.address.type.in6, sizeof(iter->current.address.type.in6)); if (isc_ioctl(iter->socket, SIOCGLIFADDR, &lifreq) < 0) { strerror_r(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "%s: getting interface address: %s", ifreq.ifr_name, strbuf); return (ISC_R_IGNORE); } prefixlen = lifreq.lifr_addrlen; #else isc_netaddr_format(&iter->current.address, sabuf, sizeof(sabuf)); isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_INTERFACE, ISC_LOG_INFO, "prefix length for %s is unknown (assume 128)", sabuf); prefixlen = 128; #endif /* * Netmask already zeroed. */ iter->current.netmask.family = family; for (i = 0; i < 16; i++) { if (prefixlen > 8) { bits = 0; prefixlen -= 8; } else { bits = 8 - prefixlen; prefixlen = 0; } iter->current.netmask.type.in6.s6_addr[i] = (~0 << bits) & 0xff; } iter->current.ifindex = if_nametoindex(iter->current.name); return (ISC_R_SUCCESS); inet: if (family != AF_INET) return (ISC_R_IGNORE); #ifdef IFF_POINTOPOINT /* * If the interface is point-to-point, get the destination address. */ if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) { /* * Ignore the HP/UX warning about "integer overflow during * conversion. It comes from its own macro definition, * and is really hard to shut up. */ if (isc_ioctl(iter->socket, SIOCGIFDSTADDR, (char *)&ifreq) < 0) { strerror_r(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "%s: getting destination address: %s", ifreq.ifr_name, strbuf); return (ISC_R_IGNORE); } get_addr(family, &iter->current.dstaddress, (struct sockaddr *)&ifreq.ifr_dstaddr, ifreq.ifr_name); } #endif if ((iter->current.flags & INTERFACE_F_BROADCAST) != 0) { /* * Ignore the HP/UX warning about "integer overflow during * conversion. It comes from its own macro definition, * and is really hard to shut up. */ if (isc_ioctl(iter->socket, SIOCGIFBRDADDR, (char *)&ifreq) < 0) { strerror_r(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "%s: getting broadcast address: %s", ifreq.ifr_name, strbuf); return (ISC_R_IGNORE); } get_addr(family, &iter->current.broadcast, (struct sockaddr *)&ifreq.ifr_broadaddr, ifreq.ifr_name); } /* * Get the network mask. */ memset(&ifreq, 0, sizeof(ifreq)); memcpy(&ifreq, ifrp, sizeof(ifreq)); /* * Ignore the HP/UX warning about "integer overflow during * conversion. It comes from its own macro definition, * and is really hard to shut up. */ if (isc_ioctl(iter->socket, SIOCGIFNETMASK, (char *)&ifreq) < 0) { strerror_r(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "%s: getting netmask: %s", ifreq.ifr_name, strbuf); return (ISC_R_IGNORE); } get_addr(family, &iter->current.netmask, (struct sockaddr *)&ifreq.ifr_addr, ifreq.ifr_name); iter->current.ifindex = if_nametoindex(iter->current.name); return (ISC_R_SUCCESS); }
int _intf_get_noalias(intf_t *intf, struct intf_entry *entry) { struct lifreq lifr; int fd; /* Get interface index. */ entry->intf_index = if_nametoindex(entry->intf_name); if (entry->intf_index == 0) return (-1); strlcpy(lifr.lifr_name, entry->intf_name, sizeof(lifr.lifr_name)); /* Get interface flags. Here he also check whether we need to use fd or * fd6 in the rest of the function. Using the wrong address family in * the ioctls gives ENXIO on Solaris. */ if (ioctl(intf->fd, SIOCGLIFFLAGS, &lifr) >= 0) fd = intf->fd; else if (intf->fd6 != -1 && ioctl(intf->fd6, SIOCGLIFFLAGS, &lifr) >= 0) fd = intf->fd6; else return (-1); entry->intf_flags = intf_iff_to_flags(lifr.lifr_flags); _intf_set_type(entry); /* Get interface MTU. */ #ifdef SIOCGLIFMTU if (ioctl(fd, SIOCGLIFMTU, &lifr) < 0) #endif return (-1); entry->intf_mtu = lifr.lifr_mtu; entry->intf_addr.addr_type = entry->intf_dst_addr.addr_type = entry->intf_link_addr.addr_type = ADDR_TYPE_NONE; /* Get primary interface address. */ if (ioctl(fd, SIOCGLIFADDR, &lifr) == 0) { addr_ston((struct sockaddr *)&lifr.lifr_addr, &entry->intf_addr); if (ioctl(fd, SIOCGLIFNETMASK, &lifr) < 0) return (-1); addr_stob((struct sockaddr *)&lifr.lifr_addr, &entry->intf_addr.addr_bits); } /* Get other addresses. */ if (entry->intf_type == INTF_TYPE_TUN) { if (ioctl(fd, SIOCGLIFDSTADDR, &lifr) == 0) { if (addr_ston((struct sockaddr *)&lifr.lifr_addr, &entry->intf_dst_addr) < 0) return (-1); } } else if (entry->intf_type == INTF_TYPE_ETH) { eth_t *eth; if ((eth = eth_open(entry->intf_name)) != NULL) { if (!eth_get(eth, &entry->intf_link_addr.addr_eth)) { entry->intf_link_addr.addr_type = ADDR_TYPE_ETH; entry->intf_link_addr.addr_bits = ETH_ADDR_BITS; } eth_close(eth); } } return (0); }
static isc_result_t internal_current6(isc_interfaceiter_t *iter) { struct LIFREQ *ifrp; struct LIFREQ lifreq; int family; char strbuf[BUFSIZ]; int fd; REQUIRE(VALID_IFITER(iter)); if (iter->result6 != ISC_R_SUCCESS) return (iter->result6); REQUIRE(iter->pos6 < (unsigned int) iter->lifc.lifc_len); ifrp = (void *)((char *)iter->lifc.lifc_req + iter->pos6); memset(&lifreq, 0, sizeof(lifreq)); memcpy(&lifreq, ifrp, sizeof(lifreq)); family = lifreq.lifr_addr.ss_family; if (family != AF_INET && family != AF_INET6) return (ISC_R_IGNORE); memset(&iter->current, 0, sizeof(iter->current)); iter->current.af = family; INSIST(sizeof(lifreq.lifr_name) <= sizeof(iter->current.name)); memset(iter->current.name, 0, sizeof(iter->current.name)); memcpy(iter->current.name, lifreq.lifr_name, sizeof(lifreq.lifr_name)); get_addr(family, &iter->current.address, (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name); if (isc_netaddr_islinklocal(&iter->current.address)) isc_netaddr_setzone(&iter->current.address, (uint32_t)lifreq.lifr_index); /* * If the interface does not have a address ignore it. */ switch (family) { case AF_INET: if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY)) return (ISC_R_IGNORE); break; case AF_INET6: if (memcmp(&iter->current.address.type.in6, &in6addr_any, sizeof(in6addr_any)) == 0) return (ISC_R_IGNORE); break; } /* * Get interface flags. */ iter->current.flags = 0; if (family == AF_INET6) fd = iter->socket6; else fd = iter->socket; /* * Ignore the HP/UX warning about "integer overflow during * conversion. It comes from its own macro definition, * and is really hard to shut up. */ if (isc_ioctl(fd, SIOCGLIFFLAGS, (char *) &lifreq) < 0) { strerror_r(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "%s: getting interface flags: %s", lifreq.lifr_name, strbuf); return (ISC_R_IGNORE); } if ((lifreq.lifr_flags & IFF_UP) != 0) iter->current.flags |= INTERFACE_F_UP; #ifdef IFF_POINTOPOINT if ((lifreq.lifr_flags & IFF_POINTOPOINT) != 0) iter->current.flags |= INTERFACE_F_POINTTOPOINT; #endif if ((lifreq.lifr_flags & IFF_LOOPBACK) != 0) iter->current.flags |= INTERFACE_F_LOOPBACK; if ((lifreq.lifr_flags & IFF_BROADCAST) != 0) { iter->current.flags |= INTERFACE_F_BROADCAST; } #ifdef IFF_MULTICAST if ((lifreq.lifr_flags & IFF_MULTICAST) != 0) { iter->current.flags |= INTERFACE_F_MULTICAST; } #endif #ifdef IFF_POINTOPOINT /* * If the interface is point-to-point, get the destination address. */ if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) { /* * Ignore the HP/UX warning about "integer overflow during * conversion. It comes from its own macro definition, * and is really hard to shut up. */ if (isc_ioctl(fd, SIOCGLIFDSTADDR, (char *)&lifreq) < 0) { strerror_r(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "%s: getting destination address: %s", lifreq.lifr_name, strbuf); return (ISC_R_IGNORE); } get_addr(family, &iter->current.dstaddress, (struct sockaddr *)&lifreq.lifr_dstaddr, lifreq.lifr_name); } #endif #ifdef SIOCGLIFBRDADDR if ((iter->current.flags & INTERFACE_F_BROADCAST) != 0) { /* * Ignore the HP/UX warning about "integer overflow during * conversion. It comes from its own macro definition, * and is really hard to shut up. */ if (isc_ioctl(iter->socket, SIOCGLIFBRDADDR, (char *)&lifreq) < 0) { strerror_r(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "%s: getting broadcast address: %s", lifreq.lifr_name, strbuf); return (ISC_R_IGNORE); } get_addr(family, &iter->current.broadcast, (struct sockaddr *)&lifreq.lifr_broadaddr, lifreq.lifr_name); } #endif /* SIOCGLIFBRDADDR */ /* * Get the network mask. Netmask already zeroed. */ memset(&lifreq, 0, sizeof(lifreq)); memcpy(&lifreq, ifrp, sizeof(lifreq)); #ifdef lifr_addrlen /* * Special case: if the system provides lifr_addrlen member, the * netmask of an IPv6 address can be derived from the length, since * an IPv6 address always has a contiguous mask. */ if (family == AF_INET6) { int i, bits; iter->current.netmask.family = family; for (i = 0; i < lifreq.lifr_addrlen; i += 8) { bits = lifreq.lifr_addrlen - i; bits = (bits < 8) ? (8 - bits) : 0; iter->current.netmask.type.in6.s6_addr[i / 8] = (~0 << bits) & 0xff; } iter->current.ifindex = if_nametoindex(iter->current.name); return (ISC_R_SUCCESS); } #endif /* * Ignore the HP/UX warning about "integer overflow during * conversion. It comes from its own macro definition, * and is really hard to shut up. */ if (isc_ioctl(fd, SIOCGLIFNETMASK, (char *)&lifreq) < 0) { strerror_r(errno, strbuf, sizeof(strbuf)); UNEXPECTED_ERROR(__FILE__, __LINE__, "%s: getting netmask: %s", lifreq.lifr_name, strbuf); return (ISC_R_IGNORE); } get_addr(family, &iter->current.netmask, (struct sockaddr *)&lifreq.lifr_addr, lifreq.lifr_name); iter->current.ifindex = if_nametoindex(iter->current.name); return (ISC_R_SUCCESS); }
static int vxlan_parse_opt(struct link_util *lu, int argc, char **argv, struct nlmsghdr *n) { __u32 vni = 0; __u32 gaddr = 0; __u32 daddr = 0; struct in6_addr gaddr6 = IN6ADDR_ANY_INIT; struct in6_addr daddr6 = IN6ADDR_ANY_INIT; __u8 learning = 1; __u16 dstport = 0; __u8 metadata = 0; __u64 attrs = 0; bool set_op = (n->nlmsg_type == RTM_NEWLINK && !(n->nlmsg_flags & NLM_F_CREATE)); while (argc > 0) { if (!matches(*argv, "id") || !matches(*argv, "vni")) { /* We will add ID attribute outside of the loop since we * need to consider metadata information as well. */ NEXT_ARG(); check_duparg(&attrs, IFLA_VXLAN_ID, "id", *argv); if (get_u32(&vni, *argv, 0) || vni >= 1u << 24) invarg("invalid id", *argv); } else if (!matches(*argv, "group")) { if (daddr || !IN6_IS_ADDR_UNSPECIFIED(&daddr6)) { fprintf(stderr, "vxlan: both group and remote"); fprintf(stderr, " cannot be specified\n"); return -1; } NEXT_ARG(); check_duparg(&attrs, IFLA_VXLAN_GROUP, "group", *argv); if (!inet_get_addr(*argv, &gaddr, &gaddr6)) { fprintf(stderr, "Invalid address \"%s\"\n", *argv); return -1; } if (!IN6_IS_ADDR_MULTICAST(&gaddr6) && !IN_MULTICAST(ntohl(gaddr))) invarg("invalid group address", *argv); } else if (!matches(*argv, "remote")) { if (gaddr || !IN6_IS_ADDR_UNSPECIFIED(&gaddr6)) { fprintf(stderr, "vxlan: both group and remote"); fprintf(stderr, " cannot be specified\n"); return -1; } NEXT_ARG(); check_duparg(&attrs, IFLA_VXLAN_GROUP, "remote", *argv); if (!inet_get_addr(*argv, &daddr, &daddr6)) { fprintf(stderr, "Invalid address \"%s\"\n", *argv); return -1; } if (IN6_IS_ADDR_MULTICAST(&daddr6) || IN_MULTICAST(ntohl(daddr))) invarg("invalid remote address", *argv); } else if (!matches(*argv, "local")) { __u32 saddr = 0; struct in6_addr saddr6 = IN6ADDR_ANY_INIT; NEXT_ARG(); check_duparg(&attrs, IFLA_VXLAN_LOCAL, "local", *argv); if (strcmp(*argv, "any")) { if (!inet_get_addr(*argv, &saddr, &saddr6)) { fprintf(stderr, "Invalid address \"%s\"\n", *argv); return -1; } } if (IN_MULTICAST(ntohl(saddr)) || IN6_IS_ADDR_MULTICAST(&saddr6)) invarg("invalid local address", *argv); if (saddr) addattr_l(n, 1024, IFLA_VXLAN_LOCAL, &saddr, 4); else if (!IN6_IS_ADDR_UNSPECIFIED(&saddr6)) addattr_l(n, 1024, IFLA_VXLAN_LOCAL6, &saddr6, sizeof(struct in6_addr)); } else if (!matches(*argv, "dev")) { unsigned int link; NEXT_ARG(); check_duparg(&attrs, IFLA_VXLAN_LINK, "dev", *argv); link = if_nametoindex(*argv); if (link == 0) { fprintf(stderr, "Cannot find device \"%s\"\n", *argv); exit(-1); } addattr32(n, 1024, IFLA_VXLAN_LINK, link); } else if (!matches(*argv, "ttl") || !matches(*argv, "hoplimit")) { unsigned int uval; __u8 ttl = 0; NEXT_ARG(); check_duparg(&attrs, IFLA_VXLAN_TTL, "ttl", *argv); if (strcmp(*argv, "inherit") != 0) { if (get_unsigned(&uval, *argv, 0)) invarg("invalid TTL", *argv); if (uval > 255) invarg("TTL must be <= 255", *argv); ttl = uval; } addattr8(n, 1024, IFLA_VXLAN_TTL, ttl); } else if (!matches(*argv, "tos") || !matches(*argv, "dsfield")) { __u32 uval; __u8 tos; NEXT_ARG(); check_duparg(&attrs, IFLA_VXLAN_TOS, "tos", *argv); if (strcmp(*argv, "inherit") != 0) { if (rtnl_dsfield_a2n(&uval, *argv)) invarg("bad TOS value", *argv); tos = uval; } else tos = 1; addattr8(n, 1024, IFLA_VXLAN_TOS, tos); } else if (!matches(*argv, "label") || !matches(*argv, "flowlabel")) { __u32 uval; NEXT_ARG(); check_duparg(&attrs, IFLA_VXLAN_LABEL, "flowlabel", *argv); if (get_u32(&uval, *argv, 0) || (uval & ~LABEL_MAX_MASK)) invarg("invalid flowlabel", *argv); addattr32(n, 1024, IFLA_VXLAN_LABEL, htonl(uval)); } else if (!matches(*argv, "ageing")) { __u32 age; NEXT_ARG(); check_duparg(&attrs, IFLA_VXLAN_AGEING, "ageing", *argv); if (strcmp(*argv, "none") == 0) age = 0; else if (get_u32(&age, *argv, 0)) invarg("ageing timer", *argv); addattr32(n, 1024, IFLA_VXLAN_AGEING, age); } else if (!matches(*argv, "maxaddress")) { __u32 maxaddr; NEXT_ARG(); check_duparg(&attrs, IFLA_VXLAN_LIMIT, "maxaddress", *argv); if (strcmp(*argv, "unlimited") == 0) maxaddr = 0; else if (get_u32(&maxaddr, *argv, 0)) invarg("max addresses", *argv); addattr32(n, 1024, IFLA_VXLAN_LIMIT, maxaddr); } else if (!matches(*argv, "port") || !matches(*argv, "srcport")) { struct ifla_vxlan_port_range range = { 0, 0 }; NEXT_ARG(); check_duparg(&attrs, IFLA_VXLAN_PORT_RANGE, "srcport", *argv); if (get_be16(&range.low, *argv, 0)) invarg("min port", *argv); NEXT_ARG(); if (get_be16(&range.high, *argv, 0)) invarg("max port", *argv); if (range.low || range.high) { addattr_l(n, 1024, IFLA_VXLAN_PORT_RANGE, &range, sizeof(range)); } } else if (!matches(*argv, "dstport")) { NEXT_ARG(); check_duparg(&attrs, IFLA_VXLAN_PORT, "dstport", *argv); if (get_u16(&dstport, *argv, 0)) invarg("dst port", *argv); } else if (!matches(*argv, "nolearning")) { check_duparg(&attrs, IFLA_VXLAN_LEARNING, *argv, *argv); learning = 0; } else if (!matches(*argv, "learning")) { check_duparg(&attrs, IFLA_VXLAN_LEARNING, *argv, *argv); learning = 1; } else if (!matches(*argv, "noproxy")) { check_duparg(&attrs, IFLA_VXLAN_PROXY, *argv, *argv); addattr8(n, 1024, IFLA_VXLAN_PROXY, 0); } else if (!matches(*argv, "proxy")) { check_duparg(&attrs, IFLA_VXLAN_PROXY, *argv, *argv); addattr8(n, 1024, IFLA_VXLAN_PROXY, 1); } else if (!matches(*argv, "norsc")) { check_duparg(&attrs, IFLA_VXLAN_RSC, *argv, *argv); addattr8(n, 1024, IFLA_VXLAN_RSC, 0); } else if (!matches(*argv, "rsc")) { check_duparg(&attrs, IFLA_VXLAN_RSC, *argv, *argv); addattr8(n, 1024, IFLA_VXLAN_RSC, 1); } else if (!matches(*argv, "nol2miss")) { check_duparg(&attrs, IFLA_VXLAN_L2MISS, *argv, *argv); addattr8(n, 1024, IFLA_VXLAN_L2MISS, 0); } else if (!matches(*argv, "l2miss")) { check_duparg(&attrs, IFLA_VXLAN_L2MISS, *argv, *argv); addattr8(n, 1024, IFLA_VXLAN_L2MISS, 1); } else if (!matches(*argv, "nol3miss")) { check_duparg(&attrs, IFLA_VXLAN_L3MISS, *argv, *argv); addattr8(n, 1024, IFLA_VXLAN_L3MISS, 0); } else if (!matches(*argv, "l3miss")) { check_duparg(&attrs, IFLA_VXLAN_L3MISS, *argv, *argv); addattr8(n, 1024, IFLA_VXLAN_L3MISS, 1); } else if (!matches(*argv, "udpcsum")) { check_duparg(&attrs, IFLA_VXLAN_UDP_CSUM, *argv, *argv); addattr8(n, 1024, IFLA_VXLAN_UDP_CSUM, 1); } else if (!matches(*argv, "noudpcsum")) { check_duparg(&attrs, IFLA_VXLAN_UDP_CSUM, *argv, *argv); addattr8(n, 1024, IFLA_VXLAN_UDP_CSUM, 0); } else if (!matches(*argv, "udp6zerocsumtx")) { check_duparg(&attrs, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, *argv, *argv); addattr8(n, 1024, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, 1); } else if (!matches(*argv, "noudp6zerocsumtx")) { check_duparg(&attrs, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, *argv, *argv); addattr8(n, 1024, IFLA_VXLAN_UDP_ZERO_CSUM6_TX, 0); } else if (!matches(*argv, "udp6zerocsumrx")) { check_duparg(&attrs, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, *argv, *argv); addattr8(n, 1024, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, 1); } else if (!matches(*argv, "noudp6zerocsumrx")) { check_duparg(&attrs, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, *argv, *argv); addattr8(n, 1024, IFLA_VXLAN_UDP_ZERO_CSUM6_RX, 0); } else if (!matches(*argv, "remcsumtx")) { check_duparg(&attrs, IFLA_VXLAN_REMCSUM_TX, *argv, *argv); addattr8(n, 1024, IFLA_VXLAN_REMCSUM_TX, 1); } else if (!matches(*argv, "noremcsumtx")) { check_duparg(&attrs, IFLA_VXLAN_REMCSUM_TX, *argv, *argv); addattr8(n, 1024, IFLA_VXLAN_REMCSUM_TX, 0); } else if (!matches(*argv, "remcsumrx")) { check_duparg(&attrs, IFLA_VXLAN_REMCSUM_RX, *argv, *argv); addattr8(n, 1024, IFLA_VXLAN_REMCSUM_RX, 1); } else if (!matches(*argv, "noremcsumrx")) { check_duparg(&attrs, IFLA_VXLAN_REMCSUM_RX, *argv, *argv); addattr8(n, 1024, IFLA_VXLAN_REMCSUM_RX, 0); } else if (!matches(*argv, "external")) { check_duparg(&attrs, IFLA_VXLAN_COLLECT_METADATA, *argv, *argv); metadata = 1; learning = 0; /* we will add LEARNING attribute outside of the loop */ addattr8(n, 1024, IFLA_VXLAN_COLLECT_METADATA, metadata); } else if (!matches(*argv, "noexternal")) { check_duparg(&attrs, IFLA_VXLAN_COLLECT_METADATA, *argv, *argv); metadata = 0; addattr8(n, 1024, IFLA_VXLAN_COLLECT_METADATA, metadata); } else if (!matches(*argv, "gbp")) { check_duparg(&attrs, IFLA_VXLAN_GBP, *argv, *argv); addattr_l(n, 1024, IFLA_VXLAN_GBP, NULL, 0); } else if (!matches(*argv, "gpe")) { check_duparg(&attrs, IFLA_VXLAN_GPE, *argv, *argv); addattr_l(n, 1024, IFLA_VXLAN_GPE, NULL, 0); } else if (matches(*argv, "help") == 0) { explain(); return -1; } else { fprintf(stderr, "vxlan: unknown command \"%s\"?\n", *argv); explain(); return -1; } argc--, argv++; } if (metadata && VXLAN_ATTRSET(attrs, IFLA_VXLAN_ID)) { fprintf(stderr, "vxlan: both 'external' and vni cannot be specified\n"); return -1; } if (!metadata && !VXLAN_ATTRSET(attrs, IFLA_VXLAN_ID)) { fprintf(stderr, "vxlan: missing virtual network identifier\n"); return -1; } if ((gaddr || !IN6_IS_ADDR_UNSPECIFIED(&gaddr6)) && !VXLAN_ATTRSET(attrs, IFLA_VXLAN_LINK)) { fprintf(stderr, "vxlan: 'group' requires 'dev' to be specified\n"); return -1; } if (!VXLAN_ATTRSET(attrs, IFLA_VXLAN_PORT) && VXLAN_ATTRSET(attrs, IFLA_VXLAN_GPE)) { dstport = 4790; } else if (!VXLAN_ATTRSET(attrs, IFLA_VXLAN_PORT) && !set_op) { fprintf(stderr, "vxlan: destination port not specified\n" "Will use Linux kernel default (non-standard value)\n"); fprintf(stderr, "Use 'dstport 4789' to get the IANA assigned value\n" "Use 'dstport 0' to get default and quiet this message\n"); } addattr32(n, 1024, IFLA_VXLAN_ID, vni); if (gaddr) addattr_l(n, 1024, IFLA_VXLAN_GROUP, &gaddr, 4); else if (daddr) addattr_l(n, 1024, IFLA_VXLAN_GROUP, &daddr, 4); else if (!IN6_IS_ADDR_UNSPECIFIED(&gaddr6)) addattr_l(n, 1024, IFLA_VXLAN_GROUP6, &gaddr6, sizeof(struct in6_addr)); else if (!IN6_IS_ADDR_UNSPECIFIED(&daddr6)) addattr_l(n, 1024, IFLA_VXLAN_GROUP6, &daddr6, sizeof(struct in6_addr)); else if (preferred_family == AF_INET) addattr_l(n, 1024, IFLA_VXLAN_GROUP, &daddr, 4); else if (preferred_family == AF_INET6) addattr_l(n, 1024, IFLA_VXLAN_GROUP6, &daddr6, sizeof(struct in6_addr)); if (!set_op || VXLAN_ATTRSET(attrs, IFLA_VXLAN_LEARNING)) addattr8(n, 1024, IFLA_VXLAN_LEARNING, learning); if (dstport) addattr16(n, 1024, IFLA_VXLAN_PORT, htons(dstport)); return 0; }
static int parseURL(const char * url, char * hostname, unsigned short * port, char * * path, unsigned int * scope_id) { char * p1, *p2, *p3; if(!url) return 0; p1 = strstr(url, "://"); if(!p1) return 0; p1 += 3; if( (url[0]!='h') || (url[1]!='t') ||(url[2]!='t') || (url[3]!='p')) return 0; memset(hostname, 0, MAXHOSTNAMELEN + 1); if(*p1 == '[') { /* IP v6 : http://[2a00:1450:8002::6a]/path/abc */ char * scope; scope = strchr(p1, '%'); p2 = strchr(p1, ']'); if(p2 && scope && scope < p2 && scope_id) { /* parse scope */ #ifdef IF_NAMESIZE char tmp[IF_NAMESIZE]; int l; scope++; /* "%25" is just '%' in URL encoding */ if(scope[0] == '2' && scope[1] == '5') scope += 2; /* skip "25" */ l = p2 - scope; if(l >= IF_NAMESIZE) l = IF_NAMESIZE - 1; memcpy(tmp, scope, l); tmp[l] = '\0'; *scope_id = if_nametoindex(tmp); if(*scope_id == 0) { *scope_id = (unsigned int)strtoul(tmp, NULL, 10); } #else /* IF_NAMESIZE */ /* under windows, scope is numerical */ char tmp[8]; int l; scope++; /* "%25" is just '%' in URL encoding */ if(scope[0] == '2' && scope[1] == '5') scope += 2; /* skip "25" */ l = p2 - scope; if(l >= (int)sizeof(tmp)) l = sizeof(tmp) - 1; memcpy(tmp, scope, l); tmp[l] = '\0'; *scope_id = (unsigned int)strtoul(tmp, NULL, 10); #endif /* IF_NAMESIZE */ } p3 = strchr(p1, '/'); if(p2 && p3) { p2++; strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p2-p1))); if(*p2 == ':') { *port = 0; p2++; while( (*p2 >= '0') && (*p2 <= '9')) { *port *= 10; *port += (unsigned short)(*p2 - '0'); p2++; } } else { *port = 80; } *path = p3; return 1; } } p2 = strchr(p1, ':'); p3 = strchr(p1, '/'); if(!p3) return 0; if(!p2 || (p2>p3)) { strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p3-p1))); *port = 80; } else { strncpy(hostname, p1, MIN(MAXHOSTNAMELEN, (int)(p2-p1))); *port = 0; p2++; while( (*p2 >= '0') && (*p2 <= '9')) { *port *= 10; *port += (unsigned short)(*p2 - '0'); p2++; } } *path = p3; return 1; }
int main(int argc, char* argv[]) { int sock; int status; struct addrinfo sainfo, *psinfo; struct sockaddr_in6 sin6; int sin6len; char buffer[MAXBUF]; uint32_t if_index = 0; sin6len = sizeof(struct sockaddr_in6); sock = socket(PF_INET6, SOCK_DGRAM,0); memset(&sin6, 0, sizeof(struct sockaddr_in6)); sin6.sin6_port = htons(4936); sin6.sin6_family = AF_INET6; sin6.sin6_addr = in6addr_any; status = bind(sock, (struct sockaddr *)&sin6, sin6len); if(-1 == status) perror("bind"), exit(1); memset(&sainfo, 0, sizeof(struct addrinfo)); memset(&sin6, 0, sin6len); sainfo.ai_flags = 0; sainfo.ai_family = PF_INET6; sainfo.ai_socktype = SOCK_DGRAM; sainfo.ai_protocol = IPPROTO_UDP; status = getaddrinfo("ff02::150", "4936", &sainfo, &psinfo); switch (status) { case EAI_FAMILY: printf("family\n"); break; case EAI_SOCKTYPE: printf("stype\n"); break; case EAI_BADFLAGS: printf("flag\n"); break; case EAI_NONAME: printf("noname\n"); break; case EAI_SERVICE: printf("service\n"); break; } if_index = if_nametoindex("eth2"); printf("\nIf_index %d", if_index); sprintf(buffer,"Hello World"); setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, &if_index, sizeof(if_index)); while (1) { status = sendto(sock, buffer, strlen(buffer), 0, (struct sockaddr *)psinfo->ai_addr, sin6len); printf("buffer : %s \t%d\n", buffer, status); sleep(2); } // free memory freeaddrinfo(psinfo); psinfo = NULL; shutdown(sock, 2); close(sock); return 0; }
enum nss_status _nss_myhostname_gethostbyname4_r( const char *name, struct gaih_addrtuple **pat, char *buffer, size_t buflen, int *errnop, int *h_errnop, int32_t *ttlp) { unsigned lo_ifi; char hn[HOST_NAME_MAX+1] = {}; const char *canonical = NULL; size_t l, idx, ms; char *r_name; struct gaih_addrtuple *r_tuple, *r_tuple_prev = NULL; struct address *addresses = NULL, *a; unsigned n_addresses = 0, n; uint32_t local_address_ipv4; if (strcasecmp(name, "localhost") == 0) { /* We respond to 'localhost', so that /etc/hosts * is optional */ canonical = "localhost"; local_address_ipv4 = htonl(INADDR_LOOPBACK); } else { /* We respond to our local host name */ if (gethostname(hn, sizeof(hn)-1) < 0) { *errnop = errno; *h_errnop = NO_RECOVERY; return NSS_STATUS_UNAVAIL; } if (strcasecmp(name, hn) != 0) { *errnop = ENOENT; *h_errnop = HOST_NOT_FOUND; return NSS_STATUS_NOTFOUND; } /* If this fails, n_addresses is 0. Which is fine */ ifconf_acquire_addresses(&addresses, &n_addresses); canonical = hn; local_address_ipv4 = LOCALADDRESS_IPV4; } /* If this call fails we fill in 0 as scope. Which is fine */ lo_ifi = n_addresses <= 0 ? if_nametoindex(LOOPBACK_INTERFACE) : 0; l = strlen(canonical); ms = ALIGN(l+1)+ALIGN(sizeof(struct gaih_addrtuple))*(n_addresses > 0 ? n_addresses : 2); if (buflen < ms) { *errnop = ENOMEM; *h_errnop = NO_RECOVERY; free(addresses); return NSS_STATUS_TRYAGAIN; } /* First, fill in hostname */ r_name = buffer; memcpy(r_name, canonical, l+1); idx = ALIGN(l+1); if (n_addresses <= 0) { /* Second, fill in IPv6 tuple */ r_tuple = (struct gaih_addrtuple*) (buffer + idx); r_tuple->next = r_tuple_prev; r_tuple->name = r_name; r_tuple->family = AF_INET6; memcpy(r_tuple->addr, LOCALADDRESS_IPV6, 16); r_tuple->scopeid = (uint32_t) lo_ifi; idx += ALIGN(sizeof(struct gaih_addrtuple)); r_tuple_prev = r_tuple; /* Third, fill in IPv4 tuple */ r_tuple = (struct gaih_addrtuple*) (buffer + idx); r_tuple->next = r_tuple_prev; r_tuple->name = r_name; r_tuple->family = AF_INET; *(uint32_t*) r_tuple->addr = local_address_ipv4; r_tuple->scopeid = (uint32_t) lo_ifi; idx += ALIGN(sizeof(struct gaih_addrtuple)); r_tuple_prev = r_tuple; } /* Fourth, fill actual addresses in, but in backwards order */ for (a = addresses + n_addresses - 1, n = 0; n < n_addresses; n++, a--) { r_tuple = (struct gaih_addrtuple*) (buffer + idx); r_tuple->next = r_tuple_prev; r_tuple->name = r_name; r_tuple->family = a->family; r_tuple->scopeid = a->ifindex; memcpy(r_tuple->addr, a->address, 16); idx += ALIGN(sizeof(struct gaih_addrtuple)); r_tuple_prev = r_tuple; } /* Verify the size matches */ assert(idx == ms); /* Nscd expects us to store the first record in **pat. */ if (*pat) **pat = *r_tuple_prev; else *pat = r_tuple_prev; if (ttlp) *ttlp = 0; free(addresses); return NSS_STATUS_SUCCESS; }