static int resolve_host(sd_bus *bus, const char *name) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *req = NULL, *reply = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; const char *canonical = NULL; char ifname[IF_NAMESIZE] = ""; unsigned c = 0; int r; uint64_t flags; usec_t ts; assert(name); if (arg_ifindex > 0 && !if_indextoname(arg_ifindex, ifname)) return log_error_errno(errno, "Failed to resolve interface name for index %i: %m", arg_ifindex); log_debug("Resolving %s (family %s, interface %s).", name, af_to_name(arg_family) ?: "*", isempty(ifname) ? "*" : ifname); r = sd_bus_message_new_method_call( bus, &req, "org.freedesktop.resolve1", "/org/freedesktop/resolve1", "org.freedesktop.resolve1.Manager", "ResolveHostname"); if (r < 0) return bus_log_create_error(r); r = sd_bus_message_append(req, "isit", arg_ifindex, name, arg_family, arg_flags); if (r < 0) return bus_log_create_error(r); ts = now(CLOCK_MONOTONIC); r = sd_bus_call(bus, req, DNS_CALL_TIMEOUT_USEC, &error, &reply); if (r < 0) return log_error_errno(r, "%s: resolve call failed: %s", name, bus_error_message(&error, r)); ts = now(CLOCK_MONOTONIC) - ts; r = sd_bus_message_enter_container(reply, 'a', "(iiay)"); if (r < 0) return bus_log_parse_error(r); while ((r = sd_bus_message_enter_container(reply, 'r', "iiay")) > 0) { _cleanup_free_ char *pretty = NULL; int ifindex, family; const void *a; size_t sz; assert_cc(sizeof(int) == sizeof(int32_t)); r = sd_bus_message_read(reply, "ii", &ifindex, &family); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_read_array(reply, 'y', &a, &sz); if (r < 0) return bus_log_parse_error(r); r = sd_bus_message_exit_container(reply); if (r < 0) return bus_log_parse_error(r); if (!IN_SET(family, AF_INET, AF_INET6)) { log_debug("%s: skipping entry with family %d (%s)", name, family, af_to_name(family) ?: "unknown"); continue; } if (sz != FAMILY_ADDRESS_SIZE(family)) { log_error("%s: systemd-resolved returned address of invalid size %zu for family %s", name, sz, af_to_name(family) ?: "unknown"); return -EINVAL; }
//****************************************************************************** //****************************************************************************** // FUNCTION: Usb0IpWatchTask // // DESCRIPTION: This task is responsible for receiving messages from the kernel // relative to the reconn network interfaces. The task will also // check to see if USB0's link is up or down. // At present we are only concerned about USB0 events. // As such, this task only pays attention to USB0 events and in // particular; IP address changes. When an IP // address change event is received and the event is for a new IP // address a message is sent to the iPhone application informing it // of the new IP. At which point the iPhone application sends an IP // address request message to the embedded software. // //****************************************************************************** void *Usb0IpWatchTask(void *args) { FILE *theLinkStatusFd; struct sockaddr_nl addr; struct timeval waitTime; struct nlmsghdr *netLinkHeader; static int state = 1; fd_set theFileDescriptor; unsigned int len; int sock; int messageSent = FALSE; int retCode; uint32_t ipaddr; char headerBuf[1024]; char name[IFNAMSIZ]; LINKSTATUS_e theValue = LINK_DOWN; LINKSTATUS_e oldLinkState = LINK_DOWN; ReconnResponsePacket theResponsePkt; ReconnResponsePacket *theResponsePktPtr = &theResponsePkt; UNUSED_PARAM(args); reconnDebugPrint("%s: ****** Task started\n", __FUNCTION__); if ((sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1) { reconnDebugPrint("%s: socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE) failed %d (%s)", __FUNCTION__, errno, strerror(errno)); } else { memset(&addr, 0, sizeof(addr)); addr.nl_family = AF_NETLINK; addr.nl_groups = RTMGRP_IPV4_IFADDR; if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) { reconnDebugPrint("%s: couldn't bind %d (%s)\n", __FUNCTION__, errno , strerror(errno)); } else { netLinkHeader = (struct nlmsghdr *)headerBuf; while(1) { /* * If there is a master client connected check USB link status */ if((masterClientSocketFd != -1) || (insertedMasterSocketFd != -1)) { FD_ZERO(&theFileDescriptor); FD_SET(sock, &theFileDescriptor); waitTime.tv_sec = 0; waitTime.tv_usec = IPWATCHSLEEPTIME; if((retCode = select(sock + 1, &theFileDescriptor, NULL, NULL, &waitTime)) < 0) { reconnDebugPrint("%s: select failed %d(%s)\n",__FUNCTION__, errno, strerror(errno)); break; } else if(retCode == 0) { /* * We have timed out so check to see if USB0 link is up or down. */ if((theLinkStatusFd = fopen(USB_CARRIER_FILENAME, "r")) == NULL) { reconnDebugPrint("%s: fopen(%s) failed %d (%s)\n", __FUNCTION__, USB_CARRIER_FILENAME, errno, strerror(errno)); } else { /* * If USB0 is brought down via ifconfig usb0 down, USB_CARRIER_FILENAME can be opened * but any read of that file results in EINVAL. Treat EINVAL as link down. */ if(((fread(&theValue, 1, 1, theLinkStatusFd)) != 1) && (errno != EINVAL)) { reconnDebugPrint("%s: fread() failed %d (%s)\n", __FUNCTION__, errno, strerror(errno)); } else { if(errno == EINVAL) { theValue = LINK_DOWN; } errno = 0; #ifdef DEBUG_NETWORK reconnDebugPrint("%s: oldLinkState = %d theValue = %d messageSent = %d\n", __FUNCTION__, oldLinkState, theValue, messageSent); #endif if((oldLinkState != theValue) || (messageSent == FALSE)) { oldLinkState = theValue; /* * Send message to the master client informing it of the link transition. */ memset(theResponsePktPtr, 0, sizeof(theResponsePkt)); ADD_RSPID_TO_PACKET(GENERIC_RESPONSE, theResponsePktPtr); ADD_MSGID_TO_PACKET(RECONN_LINK_STATUS_NOTIF, theResponsePktPtr); ADD_DATA_LENGTH_TO_PACKET(1, theResponsePktPtr); theResponsePktPtr->dataPayload[0] = (theValue == '1') ? LINK_UP : LINK_DOWN; if(insertedMasterSocketFd != -1) { libiphoned_tx((unsigned char *)theResponsePktPtr, RECONN_RSPPACKET_HEADER_SIZE + 1); } else { sendSocket(masterClientSocketFd, (unsigned char *)theResponsePktPtr, RECONN_RSPPACKET_HEADER_SIZE + 1, 0); } messageSent = TRUE; } } if(fclose(theLinkStatusFd) != 0) { #ifdef DEBUG_NETWORK reconnDebugPrint("%s: fclose() failed %d (%s)\n", __FUNCTION__, errno, strerror(errno)); #endif } } } else { if(FD_ISSET(sock, &theFileDescriptor)) { if ((len = recv(sock, netLinkHeader, 1024, 0)) > 0) { #ifdef DEBUG_NETWORK reconnDebugPrint("%s: Message received len = %d netLinkHeader->nlmsg_type = %d\n", __FUNCTION__, len, netLinkHeader->nlmsg_type); #endif while ((NLMSG_OK(netLinkHeader, len)) && ((netLinkHeader->nlmsg_type) != NLMSG_DONE)) { if (netLinkHeader->nlmsg_type == RTM_NEWADDR) { #ifdef DEBUG_NETWORK reconnDebugPrint("%s: RTM_NEWADDR received \n", __FUNCTION__); #endif struct ifaddrmsg *ifa = (struct ifaddrmsg *) NLMSG_DATA(netLinkHeader); struct rtattr *rth = IFA_RTA(ifa); int rtl = IFA_PAYLOAD(netLinkHeader); while (rtl && RTA_OK(rth, rtl)) { if (rth->rta_type == IFA_ADDRESS) { ipaddr = htonl(*((uint32_t *)RTA_DATA(rth))); if_indextoname(ifa->ifa_index, name); /* * Send message to the master client informing it of the link transition. */ memset(theResponsePktPtr, 0, sizeof(theResponsePkt)); ADD_RSPID_TO_PACKET(GENERIC_RESPONSE, theResponsePktPtr); ADD_MSGID_TO_PACKET(RECONN_LINK_STATUS_NOTIF, theResponsePktPtr); ADD_DATA_LENGTH_TO_PACKET(1, theResponsePktPtr); theResponsePktPtr->dataPayload[0] = IP_CHANGE; if(insertedMasterSocketFd != -1) { libiphoned_tx((unsigned char *)theResponsePktPtr, RECONN_RSPPACKET_HEADER_SIZE + 1); } else { sendSocket(masterClientSocketFd, (unsigned char *)theResponsePktPtr, RECONN_RSPPACKET_HEADER_SIZE + 1, 0); } #ifdef DEBUG_NETWORK reconnDebugPrint("%s: %s is now %d.%d.%d.%d\n", __FUNCTION__, name, (ipaddr >> 24) & 0xff, (ipaddr >> 16) & 0xff, (ipaddr >> 8) & 0xff, ipaddr & 0xff); #endif } rth = RTA_NEXT(rth, rtl); } } else { reconnDebugPrint("%s: netLinkHeader->nlmsg_type = 0x%x received \n", __FUNCTION__, netLinkHeader->nlmsg_type); } netLinkHeader = NLMSG_NEXT(netLinkHeader, len); } } else { reconnDebugPrint("%s: recv() failed %d(%s)\n",__FUNCTION__, errno, strerror(errno)); } }
void runFailure1() { char buf[1]; if_indextoname(anyuint(), buf); }
int mcast_set_if(int sockfd, const char *ifname, u_int ifindex) { switch (sockfd_to_family(sockfd)) { case AF_INET: { struct in_addr inaddr; struct ifreq ifreq; if (ifindex > 0) { if (if_indextoname(ifindex, ifreq.ifr_name) == NULL) { errno = ENXIO; /* i/f index not found */ return(-1); } goto doioctl; } else if (ifname != NULL) { strncpy(ifreq.ifr_name, ifname, IFNAMSIZ); doioctl: if (ioctl(sockfd, SIOCGIFADDR, &ifreq) < 0) return(-1); memcpy(&inaddr, &((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr, sizeof(struct in_addr)); } else inaddr.s_addr = htonl(INADDR_ANY); /* remove prev. set default */ return(setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_IF, &inaddr, sizeof(struct in_addr))); } #ifdef IPV6 case AF_INET6: { u_int idx; if ( (idx = ifindex) == 0) { if (ifname == NULL) { errno = EINVAL; /* must supply either index or name */ return(-1); } if ( (idx = if_nametoindex(ifname)) == 0) { errno = ENXIO; /* i/f name not found */ return(-1); } } return(setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &idx, sizeof(idx))); } #endif default: errno = EAFNOSUPPORT; return(-1); } }
/* * getnameinfo * * We handle some "trival" cases locally. If the caller passes * NI_NUMERICHOST (only), then this call turns into a getservbyport * to get the service name + inet_pton() to create a host string. * If the caller passes NI_NUMERICSERV (only), then we zero out the port * number, complete the getnameinfo, and use printf() to create a service * string. If the caller specifies both NI_NUMERICHOST and NI_NUMERICSERV, * we inet_ntop() and printf() and return the results. */ si_item_t * si_nameinfo(si_mod_t *si, const struct sockaddr *sa, int flags, const char *interface, uint32_t *err) { si_item_t *out = NULL; const struct sockaddr *lookup_sa; struct sockaddr_in s4; struct in_addr a4; struct in6_addr a6; const uint32_t unused = 0; void *addr = NULL; char *host = NULL; char *serv = NULL; uint32_t ifnum = 0; uint16_t port = 0; int do_host_lookup = ((flags & NI_NUMERICHOST) == 0); int do_serv_lookup = ((flags & NI_NUMERICSERV) == 0); /* check input */ if ((si == NULL) || (sa == NULL)) { if (err != NULL) *err = SI_STATUS_EAI_FAIL; return NULL; } if (err != NULL) *err = SI_STATUS_NO_ERROR; lookup_sa = sa; if (sa->sa_family == AF_INET) { struct sockaddr_in *s4 = (struct sockaddr_in *)sa; memcpy(&a4, &s4->sin_addr, sizeof(a4)); port = s4->sin_port; addr = &a4; } else if (sa->sa_family == AF_INET6) { struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)sa; memcpy(&a6, &s6->sin6_addr, sizeof(a6)); port = s6->sin6_port; /* Look for scope id in IPv6 Link Local, Multicast Node Local, and Multicast Link Local */ if (IN6_IS_ADDR_LINKLOCAL(&s6->sin6_addr) || IN6_IS_ADDR_MC_NODELOCAL(&s6->sin6_addr) || IN6_IS_ADDR_MC_LINKLOCAL(&s6->sin6_addr)) { ifnum = ntohs(a6.__u6_addr.__u6_addr16[1]); if (ifnum == 0) { ifnum = s6->sin6_scope_id; a6.__u6_addr.__u6_addr16[1] = htons(ifnum); } if ((ifnum != s6->sin6_scope_id) && (s6->sin6_scope_id != 0)) { if (err != NULL) *err = SI_STATUS_EAI_FAIL; return NULL; } } /* v4 mapped and compat addresses are converted to plain v4 */ if (IN6_IS_ADDR_V4MAPPED(&s6->sin6_addr) || IN6_IS_ADDR_V4COMPAT(&s6->sin6_addr)) { memcpy(&a4, &s6->sin6_addr.s6_addr[12], sizeof(a4)); addr = &a4; memset(&s4, 0, sizeof(s4)); s4.sin_len = sizeof(s4); s4.sin_family = AF_INET; s4.sin_port = port; memcpy(&s4.sin_addr, &a4, sizeof(s4.sin_addr)); lookup_sa = (const struct sockaddr *)&s4; } else { addr = &a6; } } else { if (err != NULL) *err = SI_STATUS_EAI_FAMILY; return NULL; } if (do_host_lookup == 1) { si_item_t *item = si_host_byaddr(si, addr, lookup_sa->sa_family, interface, NULL); if (item != NULL) { struct hostent *h; h = (struct hostent *)((uintptr_t)item + sizeof(si_item_t)); host = strdup(h->h_name); si_item_release(item); if (host == NULL) { if (err != NULL) *err = SI_STATUS_EAI_MEMORY; return NULL; } } } if ((do_serv_lookup == 1) && (port != 0)) { si_item_t *item = si_service_byport(si, port, NULL); if (item != NULL) { struct servent *s; s = (struct servent *)((uintptr_t)item + sizeof(si_item_t)); serv = strdup(s->s_name); si_item_release(item); if (serv == NULL) { free(host); if (err != NULL) *err = SI_STATUS_EAI_MEMORY; return NULL; } } } /* * Return numeric host name for NI_NUMERICHOST or if lookup failed, but not * if NI_NAMEREQD is specified (so that we later fail with EAI_NONAME). */ if ((host == NULL) && ((flags & NI_NAMEREQD) == 0)) { char tmp[INET6_ADDRSTRLEN + 1 + IF_NAMESIZE + 1]; tmp[0] = '\0'; if (sa->sa_family == AF_INET) { char buf[INET_ADDRSTRLEN]; if (inet_ntop(AF_INET, &a4, buf, sizeof(buf)) != 0) { host = strdup(buf); } } else if (sa->sa_family == AF_INET6) { char buf[INET6_ADDRSTRLEN]; /* zero the embedded scope ID */ if (ifnum != 0) { a6.__u6_addr.__u6_addr16[1] = 0; } if (inet_ntop(AF_INET6, &a6, buf, sizeof(buf)) != 0) { if (ifnum != 0) { char ifname[IF_NAMESIZE]; if (if_indextoname(ifnum, ifname) != NULL) { asprintf(&host, "%s%%%s", buf, ifname); } else { /* ENXIO */ if (err != NULL) *err = SI_STATUS_EAI_FAIL; return NULL; } } else { host = strdup(buf); } } } } /* Return numeric service name for NI_NUMERICSERV or if lookup failed. */ if (serv == NULL) { asprintf(&serv, "%hu", ntohs(port)); } if ((host == NULL) || (serv == NULL)) { if (err != NULL) { if ((flags & NI_NAMEREQD) != 0) { *err = SI_STATUS_EAI_NONAME; } else { *err = SI_STATUS_EAI_MEMORY; } } } else { out = (si_item_t *)LI_ils_create("L4444ss", (unsigned long)si, CATEGORY_NAMEINFO, 1, unused, unused, host, serv); } free(host); free(serv); return out; }
/* * Parse a RTM_NEWADDR or RTM_DELADDR message. */ bool NetlinkEvent::parseIfAddrMessage(int type, struct ifaddrmsg *ifaddr, int rtasize) { struct rtattr *rta; struct ifa_cacheinfo *cacheinfo = NULL; char addrstr[INET6_ADDRSTRLEN] = ""; // Sanity check. if (type != RTM_NEWADDR && type != RTM_DELADDR) { SLOGE("parseIfAddrMessage on incorrect message type 0x%x\n", type); return false; } // For log messages. const char *msgtype = (type == RTM_NEWADDR) ? "RTM_NEWADDR" : "RTM_DELADDR"; for (rta = IFA_RTA(ifaddr); RTA_OK(rta, rtasize); rta = RTA_NEXT(rta, rtasize)) { if (rta->rta_type == IFA_ADDRESS) { // Only look at the first address, because we only support notifying // one change at a time. if (*addrstr != '\0') { SLOGE("Multiple IFA_ADDRESSes in %s, ignoring\n", msgtype); continue; } // Convert the IP address to a string. if (ifaddr->ifa_family == AF_INET) { struct in_addr *addr4 = (struct in_addr *) RTA_DATA(rta); if (RTA_PAYLOAD(rta) < sizeof(*addr4)) { SLOGE("Short IPv4 address (%zu bytes) in %s", RTA_PAYLOAD(rta), msgtype); continue; } inet_ntop(AF_INET, addr4, addrstr, sizeof(addrstr)); } else if (ifaddr->ifa_family == AF_INET6) { struct in6_addr *addr6 = (struct in6_addr *) RTA_DATA(rta); if (RTA_PAYLOAD(rta) < sizeof(*addr6)) { SLOGE("Short IPv6 address (%zu bytes) in %s", RTA_PAYLOAD(rta), msgtype); continue; } inet_ntop(AF_INET6, addr6, addrstr, sizeof(addrstr)); } else { SLOGE("Unknown address family %d\n", ifaddr->ifa_family); continue; } // Find the interface name. char ifname[IFNAMSIZ + 1]; if (!if_indextoname(ifaddr->ifa_index, ifname)) { SLOGE("Unknown ifindex %d in %s", ifaddr->ifa_index, msgtype); return false; } // Fill in interface information. mAction = (type == RTM_NEWADDR) ? NlActionAddressUpdated : NlActionAddressRemoved; mSubsystem = strdup("net"); asprintf(&mParams[0], "ADDRESS=%s/%d", addrstr, ifaddr->ifa_prefixlen); asprintf(&mParams[1], "INTERFACE=%s", ifname); asprintf(&mParams[2], "FLAGS=%u", ifaddr->ifa_flags); asprintf(&mParams[3], "SCOPE=%u", ifaddr->ifa_scope); } else if (rta->rta_type == IFA_CACHEINFO) { // Address lifetime information. if (cacheinfo) { // We only support one address. SLOGE("Multiple IFA_CACHEINFOs in %s, ignoring\n", msgtype); continue; } if (RTA_PAYLOAD(rta) < sizeof(*cacheinfo)) { SLOGE("Short IFA_CACHEINFO (%zu vs. %zu bytes) in %s", RTA_PAYLOAD(rta), sizeof(cacheinfo), msgtype); continue; } cacheinfo = (struct ifa_cacheinfo *) RTA_DATA(rta); asprintf(&mParams[4], "PREFERRED=%u", cacheinfo->ifa_prefered); asprintf(&mParams[5], "VALID=%u", cacheinfo->ifa_valid); asprintf(&mParams[6], "CSTAMP=%u", cacheinfo->cstamp); asprintf(&mParams[7], "TSTAMP=%u", cacheinfo->tstamp); } } if (addrstr[0] == '\0') { SLOGE("No IFA_ADDRESS in %s\n", msgtype); return false; } return true; }
static int neighbor6(neighbor_action_t action, int32_t port_id, struct in6_addr *addr, struct ether_addr *lladdr, uint8_t flags, __rte_unused uint16_t vlan_id, void *args) { // if port_id is not handled // ignore, return immediatly // if neighbor add // lookup neighbor // if exists // update lladdr, set flag as REACHABLE/STALE/DELAY // else // // This should not happen // insert new nexthop // set insert date=now, refcount = 0, flag=REACHABLE/STALE/DELAY // if neighbor delete // lookup neighbor // if exists // if refcount != 0 // set nexthop as invalid // else // set flag empty // else // do nothing // // this should not happen struct control_handle *handle = args; assert(handle != NULL); int s; uint8_t nexthop_id, find_id; int32_t socket_id = handle->socket_id; assert(neighbor6_struct != NULL); if (addr == NULL) return -1; // FIXME must check that state is not NUD_FAILED or NUD_INVALID if (action == NEIGHBOR_ADD) { if (lladdr == NULL) return -1; char ibuf[IFNAMSIZ]; unsigned kni_vlan; if_indextoname(port_id, ibuf); s = sscanf(ibuf, "dpdk%10u.%10u", &port_id, &kni_vlan); if (s <= 0) { RTE_LOG(ERR, PKTJ_CTRL1, "received a neighbor " "announce for an unmanaged " "iface %s\n", ibuf); return -1; } s = neighbor6_lookup_nexthop(neighbor6_struct[socket_id], addr, &nexthop_id); if (s < 0) { if (flags != NUD_NONE && flags != NUD_NOARP && flags != NUD_STALE) { RTE_LOG(ERR, PKTJ_CTRL1, "failed to change state in neighbor6 " "table (state %d)...\n", flags); return -1; } RTE_LOG(DEBUG, PKTJ_CTRL1, "adding ipv6 neighbor with port_id %d " "vlan_id %d...\n", port_id, kni_vlan); s = neighbor6_add_nexthop(neighbor6_struct[socket_id], addr, &nexthop_id, NEI_ACTION_FWD); if (s < 0) { RTE_LOG(ERR, PKTJ_CTRL1, "failed to add a " "nexthop in neighbor " "table...\n"); return -1; } // apply rate limit rule if next hop neighbor is in the // table apply_rate_limit_ipv6(addr, nexthop_id, socket_id); if (rte_lpm6_lookup(ipv6_pktj_lookup_struct[socket_id], addr->s6_addr, &find_id) == 0) { s = rte_lpm6_add( ipv6_pktj_lookup_struct[socket_id], addr->s6_addr, 128, nexthop_id); if (s < 0) { lpm6_stats[socket_id].nb_add_ko++; RTE_LOG(ERR, PKTJ_CTRL1, "failed to add a route in " "lpm during neighbor " "adding...\n"); return -1; } lpm6_stats[socket_id].nb_add_ok++; } } if (flags == NUD_FAILED) { neighbor6_set_action(neighbor6_struct[socket_id], nexthop_id, NEI_ACTION_KNI); } else { neighbor6_set_action(neighbor6_struct[socket_id], nexthop_id, NEI_ACTION_FWD); } RTE_LOG(DEBUG, PKTJ_CTRL1, "set neighbor6 with port_id %d state %d \n", port_id, flags); neighbor6_set_lladdr_port(neighbor6_struct[socket_id], nexthop_id, &ports_eth_addr[port_id], lladdr, port_id, kni_vlan); neighbor6_set_state(neighbor6_struct[socket_id], nexthop_id, flags); } if (action == NEIGHBOR_DELETE) { if (flags != NUD_FAILED && flags != NUD_STALE) { RTE_LOG( DEBUG, PKTJ_CTRL1, "neighbor6 delete ope failed, bad NUD state: %d \n", flags); return -1; } RTE_LOG(DEBUG, PKTJ_CTRL1, "deleting ipv6 neighbor...\n"); s = neighbor6_lookup_nexthop(neighbor6_struct[socket_id], addr, &nexthop_id); if (s < 0) { RTE_LOG(ERR, PKTJ_CTRL1, "failed to find a nexthop to " "delete in neighbor " "table...\n"); return 0; } neighbor6_delete(neighbor6_struct[socket_id], nexthop_id); // FIXME not thread safe if (neighbor6_struct[socket_id] ->entries.t6[nexthop_id] .neighbor.refcnt == 0) { s = rte_lpm6_delete(ipv6_pktj_lookup_struct[socket_id], addr->s6_addr, 128); if (s < 0) { lpm6_stats[socket_id].nb_del_ko++; RTE_LOG(ERR, PKTJ_CTRL1, "failed to delete route...\n"); return -1; } // reset rate limit for this id rlimit6_max[socket_id][nexthop_id] = UINT32_MAX; lpm6_stats[socket_id].nb_del_ok++; } } RTE_LOG(DEBUG, PKTJ_CTRL1, "neigh ope success\n"); return 0; }
static char * build_absolute_url(const char * baseurl, const char * descURL, const char * url, unsigned int scope_id) { int l, n; char * s; const char * base; char * p; #if defined(IF_NAMESIZE) && !defined(_WIN32) char ifname[IF_NAMESIZE]; #else /* defined(IF_NAMESIZE) && !defined(_WIN32) */ char scope_str[8]; #endif /* defined(IF_NAMESIZE) && !defined(_WIN32) */ if( (url[0] == 'h') &&(url[1] == 't') &&(url[2] == 't') &&(url[3] == 'p') &&(url[4] == ':') &&(url[5] == '/') &&(url[6] == '/')) return strdup(url); base = (baseurl[0] == '\0') ? descURL : baseurl; n = strlen(base); if(n > 7) { p = strchr(base + 7, '/'); if(p) n = p - base; } l = n + strlen(url) + 1; if(url[0] != '/') l++; if(scope_id != 0) { #if defined(IF_NAMESIZE) && !defined(_WIN32) if(if_indextoname(scope_id, ifname)) { l += 3 + strlen(ifname); /* 3 == strlen(%25) */ } #else /* defined(IF_NAMESIZE) && !defined(_WIN32) */ /* under windows, scope is numerical */ l += 3 + snprintf(scope_str, sizeof(scope_str), "%u", scope_id); #endif /* defined(IF_NAMESIZE) && !defined(_WIN32) */ } s = malloc(l); if(s == NULL) return NULL; memcpy(s, base, n); if(scope_id != 0) { s[n] = '\0'; if(0 == memcmp(s, "http://[fe80:", 13)) { /* this is a linklocal IPv6 address */ p = strchr(s, ']'); if(p) { /* insert %25<scope> into URL */ #ifdef IF_NAMESIZE memmove(p + 3 + strlen(ifname), p, strlen(p) + 1); memcpy(p, "%25", 3); memcpy(p + 3, ifname, strlen(ifname)); n += 3 + strlen(ifname); #else memmove(p + 3 + strlen(scope_str), p, strlen(p) + 1); memcpy(p, "%25", 3); memcpy(p + 3, scope_str, strlen(scope_str)); n += 3 + strlen(scope_str); #endif } } } if(url[0] != '/') s[n++] = '/'; memcpy(s + n, url, l - n); return s; }
int main(int argc OVS_UNUSED, char *argv[]) { uint64_t buf_stub[4096 / 64]; struct nl_sock *sock; struct ofpbuf buf; int error; set_program_name(argv[0]); vlog_set_levels(NULL, VLF_ANY_FACILITY, VLL_DBG); error = nl_sock_create(NETLINK_ROUTE, &sock); if (error) { ovs_fatal(error, "could not create rtnetlink socket"); } error = nl_sock_join_mcgroup(sock, RTNLGRP_LINK); if (error) { ovs_fatal(error, "could not join RTNLGRP_LINK multicast group"); } ofpbuf_use_stub(&buf, buf_stub, sizeof buf_stub); for (;;) { error = nl_sock_recv(sock, &buf, false); if (error == EAGAIN) { /* Nothing to do. */ } else if (error == ENOBUFS) { ovs_error(0, "network monitor socket overflowed"); } else if (error) { ovs_fatal(error, "error on network monitor socket"); } else { struct iff_flag { unsigned int flag; const char *name; }; static const struct iff_flag flags[] = { { IFF_UP, "UP", }, { IFF_BROADCAST, "BROADCAST", }, #ifndef _WIN32 { IFF_DEBUG, "DEBUG", }, #endif { IFF_LOOPBACK, "LOOPBACK", }, #ifndef _WIN32 { IFF_POINTOPOINT, "POINTOPOINT", }, { IFF_NOTRAILERS, "NOTRAILERS", }, #endif { IFF_RUNNING, "RUNNING", }, #ifndef _WIN32 { IFF_NOARP, "NOARP", }, #endif { IFF_PROMISC, "PROMISC", }, #ifndef _WIN32 { IFF_ALLMULTI, "ALLMULTI", }, { IFF_MASTER, "MASTER", }, { IFF_SLAVE, "SLAVE", }, #endif { IFF_MULTICAST, "MULTICAST", }, #ifndef _WIN32 { IFF_PORTSEL, "PORTSEL", }, { IFF_AUTOMEDIA, "AUTOMEDIA", }, { IFF_DYNAMIC, "DYNAMIC", }, #endif }; struct nlattr *attrs[ARRAY_SIZE(rtnlgrp_link_policy)]; struct nlmsghdr *nlh; struct ifinfomsg *iim; int i; nlh = ofpbuf_at(&buf, 0, NLMSG_HDRLEN); iim = ofpbuf_at(&buf, NLMSG_HDRLEN, sizeof *iim); if (!iim) { ovs_error(0, "received bad rtnl message (no ifinfomsg)"); continue; } if (!nl_policy_parse(&buf, NLMSG_HDRLEN + sizeof(struct ifinfomsg), rtnlgrp_link_policy, attrs, ARRAY_SIZE(rtnlgrp_link_policy))) { ovs_error(0, "received bad rtnl message (policy)"); continue; } printf("netdev %s changed (%s):\n", nl_attr_get_string(attrs[IFLA_IFNAME]), (nlh->nlmsg_type == RTM_NEWLINK ? "RTM_NEWLINK" #ifndef _WIN32 : nlh->nlmsg_type == RTM_DELLINK ? "RTM_DELLINK" #endif : nlh->nlmsg_type == RTM_GETLINK ? "RTM_GETLINK" #ifndef _WIN32 : nlh->nlmsg_type == RTM_SETLINK ? "RTM_SETLINK" #endif : "other")); printf("\tflags:"); for (i = 0; i < ARRAY_SIZE(flags); i++) { if (iim->ifi_flags & flags[i].flag) { printf(" %s", flags[i].name); } } printf("\n"); if (attrs[IFLA_MASTER]) { uint32_t idx = nl_attr_get_u32(attrs[IFLA_MASTER]); char ifname[IFNAMSIZ]; #ifndef _WIN32 if (!if_indextoname(idx, ifname)) { strcpy(ifname, "unknown"); } #endif printf("\tmaster=%"PRIu32" (%s)\n", idx, ifname); } } nl_sock_wait(sock, POLLIN); poll_block(); } }
static int __ef_pd_alloc(ef_pd* pd, ef_driver_handle pd_dh, int ifindex, enum ef_pd_flags flags, int vlan_id) { ci_resource_alloc_t ra; const char* s; int rc; if( (s = getenv("EF_VI_PD_FLAGS")) != NULL ) { if( ! strcmp(s, "vf") ) flags = EF_PD_VF; else if( ! strcmp(s, "phys") ) flags = EF_PD_PHYS_MODE; else if( ! strcmp(s, "default") ) flags = 0; } if( flags & EF_PD_VF ) flags |= EF_PD_PHYS_MODE; memset(&ra, 0, sizeof(ra)); ef_vi_set_intf_ver(ra.intf_ver, sizeof(ra.intf_ver)); ra.ra_type = EFRM_RESOURCE_PD; ra.u.pd.in_ifindex = ifindex; ra.u.pd.in_flags = 0; if( flags & EF_PD_VF ) ra.u.pd.in_flags |= EFCH_PD_FLAG_VF; if( flags & EF_PD_PHYS_MODE ) ra.u.pd.in_flags |= EFCH_PD_FLAG_PHYS_ADDR; if( flags & EF_PD_RX_PACKED_STREAM ) ra.u.pd.in_flags |= EFCH_PD_FLAG_RX_PACKED_STREAM; if( flags & EF_PD_VPORT ) ra.u.pd.in_flags |= EFCH_PD_FLAG_VPORT; if( flags & EF_PD_MCAST_LOOP ) ra.u.pd.in_flags |= EFCH_PD_FLAG_MCAST_LOOP; if( flags & EF_PD_MEMREG_64KiB ) /* FIXME: We're overloading the packed-stream flag here. The only * effect it has is to force ef_memreg to use at least 64KiB buffer * table entries. Unfortunately this won't work if the adapter is not * in packed-stream mode. */ ra.u.pd.in_flags |= EFCH_PD_FLAG_RX_PACKED_STREAM; ra.u.pd.in_vlan_id = vlan_id; rc = ci_resource_alloc(pd_dh, &ra); if( rc < 0 ) { LOGVV(ef_log("ef_pd_alloc: ci_resource_alloc %d", rc)); return rc; } pd->pd_flags = flags; pd->pd_resource_id = ra.out_id.index; pd->pd_intf_name = malloc(IF_NAMESIZE); if( pd->pd_intf_name == NULL ) { LOGVV(ef_log("ef_pd_alloc: malloc failed")); return -ENOMEM; } if( if_indextoname(ifindex, pd->pd_intf_name) == NULL ) { free(pd->pd_intf_name); LOGVV(ef_log("ef_pd_alloc: if_indextoname failed %d", errno)); return -errno; } pd->pd_cluster_name = NULL; pd->pd_cluster_sock = -1; pd->pd_cluster_dh = 0; pd->pd_cluster_viset_resource_id = 0; return 0; }
int mcast_join(int sockfd, const struct sockaddr *grp, socklen_t grplen, const char *ifname, u_int ifindex) { #ifdef MCAST_JOIN_GROUP struct group_req req; if (ifindex > 0) { req.gr_interface = ifindex; } else if (ifname != NULL) { if ( (req.gr_interface = if_nametoindex(ifname)) == 0) { errno = ENXIO; /* i/f name not found */ return -1; } } else req.gr_interface = 0; if (grplen > sizeof(req.gr_group)) { errno = EINVAL; return -1; } memcpy(&req.gr_group, grp, grplen); return setsockopt(sockfd, family_to_level(grp->sa_family), MCAST_JOIN_GROUP, &req, sizeof(req)); #else /* end mcast_join1 */ /* include mcast_join2 */ switch (grp->sa_family) { case AF_INET: struct ip_mreqn mreq; struct ifreq ifreq; memcpy(&mreq.imr_multiaddr,\ &((const struct sockaddr_in *) grp)->sin_addr,\ sizeof(struct in_addr)); if (ifindex > 0) { if (if_indextoname(ifindex, ifreq.ifr_name) == NULL) { errno = ENXIO; /* i/f index not found */ return -1; } goto doioctl; } else if (ifname != NULL) { strncpy(ifreq.ifr_name, ifname, IFNAMSIZ); doioctl: if (ioctl(sockfd, SIOCGIFADDR, &ifreq) < 0) return -1; memcpy(&mreq.imr_interface,\ &((struct sockaddr_in *) &ifreq.ifr_addr)->sin_addr,\ sizeof(struct in_addr)); } else mreq.imr_interface.s_addr = htonl(INADDR_ANY); return setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)); /* end mcast_join2 */ /* include mcast_join3 */ #ifdef IPV6 #ifndef IPV6_JOIN_GROUP /* APIv0 compatibility */ #define IPV6_JOIN_GROUP IPV6_ADD_MEMBERSHIP #endif case AF_INET6: struct ipv6_mreq mreq6; memcpy(&mreq6.ipv6mr_multiaddr,\ &((const struct sockaddr_in6 *) grp)->sin6_addr,\ sizeof(struct in6_addr)); if (ifindex > 0) mreq6.ipv6mr_interface = ifindex; else if (ifname != NULL) { if ( (mreq6.ipv6mr_interface = if_nametoindex(ifname)) == 0) { errno = ENXIO; /* i/f name not found */ return -1; } } else mreq6.ipv6mr_interface = 0; return setsockopt(sockfd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq6, sizeof(mreq6)); #endif default: errno = EAFNOSUPPORT; return -1; } #endif }
static void bond_print_opt(struct link_util *lu, FILE *f, struct rtattr *tb[]) { unsigned ifindex; if (!tb) return; if (tb[IFLA_BOND_MODE]) { const char *mode = get_name(mode_tbl, rta_getattr_u8(tb[IFLA_BOND_MODE])); fprintf(f, "mode %s ", mode); } if (tb[IFLA_BOND_ACTIVE_SLAVE] && (ifindex = rta_getattr_u32(tb[IFLA_BOND_ACTIVE_SLAVE]))) { char buf[IFNAMSIZ]; const char *n = if_indextoname(ifindex, buf); if (n) fprintf(f, "active_slave %s ", n); else fprintf(f, "active_slave %u ", ifindex); } if (tb[IFLA_BOND_MIIMON]) fprintf(f, "miimon %u ", rta_getattr_u32(tb[IFLA_BOND_MIIMON])); if (tb[IFLA_BOND_UPDELAY]) fprintf(f, "updelay %u ", rta_getattr_u32(tb[IFLA_BOND_UPDELAY])); if (tb[IFLA_BOND_DOWNDELAY]) fprintf(f, "downdelay %u ", rta_getattr_u32(tb[IFLA_BOND_DOWNDELAY])); if (tb[IFLA_BOND_USE_CARRIER]) fprintf(f, "use_carrier %u ", rta_getattr_u8(tb[IFLA_BOND_USE_CARRIER])); if (tb[IFLA_BOND_ARP_INTERVAL]) fprintf(f, "arp_interval %u ", rta_getattr_u32(tb[IFLA_BOND_ARP_INTERVAL])); if (tb[IFLA_BOND_ARP_IP_TARGET]) { struct rtattr *iptb[BOND_MAX_ARP_TARGETS + 1]; char buf[INET_ADDRSTRLEN]; int i; parse_rtattr_nested(iptb, BOND_MAX_ARP_TARGETS, tb[IFLA_BOND_ARP_IP_TARGET]); if (iptb[0]) fprintf(f, "arp_ip_target "); for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) { if (iptb[i]) fprintf(f, "%s", rt_addr_n2a(AF_INET, RTA_PAYLOAD(iptb[i]), RTA_DATA(iptb[i]), buf, INET_ADDRSTRLEN)); if (i < BOND_MAX_ARP_TARGETS-1 && iptb[i+1]) fprintf(f, ","); } if (iptb[0]) fprintf(f, " "); } if (tb[IFLA_BOND_ARP_VALIDATE]) { const char *arp_validate = get_name(arp_validate_tbl, rta_getattr_u32(tb[IFLA_BOND_ARP_VALIDATE])); fprintf(f, "arp_validate %s ", arp_validate); } if (tb[IFLA_BOND_ARP_ALL_TARGETS]) { const char *arp_all_targets = get_name(arp_all_targets_tbl, rta_getattr_u32(tb[IFLA_BOND_ARP_ALL_TARGETS])); fprintf(f, "arp_all_targets %s ", arp_all_targets); } if (tb[IFLA_BOND_PRIMARY] && (ifindex = rta_getattr_u32(tb[IFLA_BOND_PRIMARY]))) { char buf[IFNAMSIZ]; const char *n = if_indextoname(ifindex, buf); if (n) fprintf(f, "primary %s ", n); else fprintf(f, "primary %u ", ifindex); } if (tb[IFLA_BOND_PRIMARY_RESELECT]) { const char *primary_reselect = get_name(primary_reselect_tbl, rta_getattr_u8(tb[IFLA_BOND_PRIMARY_RESELECT])); fprintf(f, "primary_reselect %s ", primary_reselect); } if (tb[IFLA_BOND_FAIL_OVER_MAC]) { const char *fail_over_mac = get_name(fail_over_mac_tbl, rta_getattr_u8(tb[IFLA_BOND_FAIL_OVER_MAC])); fprintf(f, "fail_over_mac %s ", fail_over_mac); } if (tb[IFLA_BOND_XMIT_HASH_POLICY]) { const char *xmit_hash_policy = get_name(xmit_hash_policy_tbl, rta_getattr_u8(tb[IFLA_BOND_XMIT_HASH_POLICY])); fprintf(f, "xmit_hash_policy %s ", xmit_hash_policy); } if (tb[IFLA_BOND_RESEND_IGMP]) fprintf(f, "resend_igmp %u ", rta_getattr_u32(tb[IFLA_BOND_RESEND_IGMP])); if (tb[IFLA_BOND_NUM_PEER_NOTIF]) fprintf(f, "num_grat_arp %u ", rta_getattr_u8(tb[IFLA_BOND_NUM_PEER_NOTIF])); if (tb[IFLA_BOND_ALL_SLAVES_ACTIVE]) fprintf(f, "all_slaves_active %u ", rta_getattr_u8(tb[IFLA_BOND_ALL_SLAVES_ACTIVE])); if (tb[IFLA_BOND_MIN_LINKS]) fprintf(f, "min_links %u ", rta_getattr_u32(tb[IFLA_BOND_MIN_LINKS])); if (tb[IFLA_BOND_LP_INTERVAL]) fprintf(f, "lp_interval %u ", rta_getattr_u32(tb[IFLA_BOND_LP_INTERVAL])); if (tb[IFLA_BOND_PACKETS_PER_SLAVE]) fprintf(f, "packets_per_slave %u ", rta_getattr_u32(tb[IFLA_BOND_PACKETS_PER_SLAVE])); if (tb[IFLA_BOND_AD_LACP_RATE]) { const char *lacp_rate = get_name(lacp_rate_tbl, rta_getattr_u8(tb[IFLA_BOND_AD_LACP_RATE])); fprintf(f, "lacp_rate %s ", lacp_rate); } if (tb[IFLA_BOND_AD_SELECT]) { const char *ad_select = get_name(ad_select_tbl, rta_getattr_u8(tb[IFLA_BOND_AD_SELECT])); fprintf(f, "ad_select %s ", ad_select); } if (tb[IFLA_BOND_AD_INFO]) { struct rtattr *adtb[IFLA_BOND_AD_INFO_MAX + 1]; parse_rtattr_nested(adtb, IFLA_BOND_AD_INFO_MAX, tb[IFLA_BOND_AD_INFO]); if (adtb[IFLA_BOND_AD_INFO_AGGREGATOR]) fprintf(f, "ad_aggregator %d ", rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_AGGREGATOR])); if (adtb[IFLA_BOND_AD_INFO_NUM_PORTS]) fprintf(f, "ad_num_ports %d ", rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_NUM_PORTS])); if (adtb[IFLA_BOND_AD_INFO_ACTOR_KEY]) fprintf(f, "ad_actor_key %d ", rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_ACTOR_KEY])); if (adtb[IFLA_BOND_AD_INFO_PARTNER_KEY]) fprintf(f, "ad_partner_key %d ", rta_getattr_u16(adtb[IFLA_BOND_AD_INFO_PARTNER_KEY])); if (adtb[IFLA_BOND_AD_INFO_PARTNER_MAC]) { unsigned char *p = RTA_DATA(adtb[IFLA_BOND_AD_INFO_PARTNER_MAC]); SPRINT_BUF(b); fprintf(f, "ad_partner_mac %s ", ll_addr_n2a(p, ETH_ALEN, 0, b, sizeof(b))); } } }
int main(int argc, char **argv) { struct sockaddr_in6 sin6; int rc, fd, i, opt; time_t expiry_time, source_expiry_time, kernel_dump_time; const char **config_files = NULL; int num_config_files = 0; void *vrc; unsigned int seed; struct interface *ifp; gettime(&now); rc = read_random_bytes(&seed, sizeof(seed)); if(rc < 0) { perror("read(random)"); seed = 42; } seed ^= (now.tv_sec ^ now.tv_usec); srandom(seed); parse_address("ff02:0:0:0:0:0:1:6", protocol_group, NULL); protocol_port = 6696; change_smoothing_half_life(4); while(1) { opt = getopt(argc, argv, "m:p:h:H:i:k:A:sruS:d:g:lwz:M:t:T:c:C:DL:I:"); if(opt < 0) break; switch(opt) { case 'm': rc = parse_address(optarg, protocol_group, NULL); if(rc < 0) goto usage; if(protocol_group[0] != 0xff) { fprintf(stderr, "%s is not a multicast address\n", optarg); goto usage; } if(protocol_group[1] != 2) { fprintf(stderr, "Warning: %s is not a link-local multicast address\n", optarg); } break; case 'p': protocol_port = parse_nat(optarg); if(protocol_port <= 0 || protocol_port > 0xFFFF) goto usage; break; case 'h': default_wireless_hello_interval = parse_thousands(optarg); if(default_wireless_hello_interval <= 0 || default_wireless_hello_interval > 0xFFFF * 10) goto usage; break; case 'H': default_wired_hello_interval = parse_thousands(optarg); if(default_wired_hello_interval <= 0 || default_wired_hello_interval > 0xFFFF * 10) goto usage; break; case 'k': kernel_metric = parse_nat(optarg); if(kernel_metric < 0 || kernel_metric > 0xFFFF) goto usage; break; case 'A': allow_duplicates = parse_nat(optarg); if(allow_duplicates < 0 || allow_duplicates > 0xFFFF) goto usage; break; case 's': split_horizon = 0; break; case 'r': random_id = 1; break; case 'u': keep_unfeasible = 1; break; case 'S': state_file = optarg; break; case 'd': debug = parse_nat(optarg); if(debug < 0) goto usage; break; case 'g': #ifdef NO_LOCAL_INTERFACE fprintf(stderr, "Warning: no local interface in this version.\n"); #else local_server_port = parse_nat(optarg); if(local_server_port <= 0 || local_server_port > 0xFFFF) goto usage; #endif break; case 'l': link_detect = 1; break; case 'w': all_wireless = 1; break; case 'z': { char *comma; diversity_kind = (int)strtol(optarg, &comma, 0); if(*comma == '\0') diversity_factor = 128; else if(*comma == ',') diversity_factor = parse_nat(comma + 1); else goto usage; if(diversity_factor <= 0 || diversity_factor > 256) goto usage; } break; case 'M': { int l = parse_nat(optarg); if(l < 0 || l > 3600) goto usage; change_smoothing_half_life(l); break; } case 't': export_table = parse_nat(optarg); if(export_table < 0 || export_table > 0xFFFF) goto usage; break; case 'T': if(add_import_table(parse_nat(optarg))) goto usage; break; case 'c': config_files = realloc(config_files, (num_config_files + 1) * sizeof(char*)); if(config_files == NULL) { fprintf(stderr, "Couldn't allocate config file.\n"); exit(1); } config_files[num_config_files++] = optarg; break; case 'C': rc = parse_config_from_string(optarg); if(rc < 0) { fprintf(stderr, "Couldn't parse configuration from command line.\n"); exit(1); } break; case 'D': do_daemonise = 1; break; case 'L': logfile = optarg; break; case 'I': pidfile = optarg; break; default: goto usage; } } if(num_config_files == 0) { if(access("/etc/babeld.conf", F_OK) >= 0) { config_files = malloc(sizeof(char*)); if(config_files == NULL) { fprintf(stderr, "Couldn't allocate config file.\n"); exit(1); } config_files[num_config_files++] = "/etc/babeld.conf"; } } for(i = 0; i < num_config_files; i++) { int line; rc = parse_config_from_file(config_files[i], &line); if(rc < 0) { fprintf(stderr, "Couldn't parse configuration from file %s " "(error at line %d).\n", config_files[i], line); exit(1); } } free(config_files); if(default_wireless_hello_interval <= 0) default_wireless_hello_interval = 4000; default_wireless_hello_interval = MAX(default_wireless_hello_interval, 5); if(default_wired_hello_interval <= 0) default_wired_hello_interval = 4000; default_wired_hello_interval = MAX(default_wired_hello_interval, 5); resend_delay = 2000; resend_delay = MIN(resend_delay, default_wireless_hello_interval / 2); resend_delay = MIN(resend_delay, default_wired_hello_interval / 2); resend_delay = MAX(resend_delay, 20); if(do_daemonise) { if(logfile == NULL) logfile = "/var/log/babeld.log"; } rc = reopen_logfile(); if(rc < 0) { perror("reopen_logfile()"); exit(1); } fd = open("/dev/null", O_RDONLY); if(fd < 0) { perror("open(null)"); exit(1); } rc = dup2(fd, 0); if(rc < 0) { perror("dup2(null, 0)"); exit(1); } close(fd); if(do_daemonise) { rc = daemonise(); if(rc < 0) { perror("daemonise"); exit(1); } } if(pidfile && pidfile[0] != '\0') { int pfd, len; char buf[100]; len = snprintf(buf, 100, "%lu", (unsigned long)getpid()); if(len < 0 || len >= 100) { perror("snprintf(getpid)"); exit(1); } pfd = open(pidfile, O_WRONLY | O_CREAT | O_EXCL, 0644); if(pfd < 0) { char buf[40]; snprintf(buf, 40, "creat(%s)", pidfile); buf[39] = '\0'; perror(buf); exit(1); } rc = write(pfd, buf, len); if(rc < len) { perror("write(pidfile)"); goto fail_pid; } close(pfd); } rc = kernel_setup(1); if(rc < 0) { fprintf(stderr, "kernel_setup failed.\n"); goto fail_pid; } rc = kernel_setup_socket(1); if(rc < 0) { fprintf(stderr, "kernel_setup_socket failed.\n"); kernel_setup(0); goto fail_pid; } rc = finalise_config(); if(rc < 0) { fprintf(stderr, "Couldn't finalise configuration.\n"); goto fail; } for(i = optind; i < argc; i++) { vrc = add_interface(argv[i], NULL); if(vrc == NULL) goto fail; } if(interfaces == NULL) { fprintf(stderr, "Eek... asked to run on no interfaces!\n"); goto fail; } if(random_id) goto random_id; FOR_ALL_INTERFACES(ifp) { /* ifp->ifindex is not necessarily valid at this point */ int ifindex = if_nametoindex(ifp->name); if(ifindex > 0) { unsigned char eui[8]; rc = if_eui64(ifp->name, ifindex, eui); if(rc < 0) continue; memcpy(myid, eui, 8); goto have_id; } } /* We failed to get a global EUI64 from the interfaces we were given. Let's try to find an interface with a MAC address. */ for(i = 1; i < 256; i++) { char buf[IF_NAMESIZE], *ifname; unsigned char eui[8]; ifname = if_indextoname(i, buf); if(ifname == NULL) continue; rc = if_eui64(ifname, i, eui); if(rc < 0) continue; memcpy(myid, eui, 8); goto have_id; } fprintf(stderr, "Warning: couldn't find router id -- using random value.\n"); random_id: rc = read_random_bytes(myid, 8); if(rc < 0) { perror("read(random)"); goto fail; } /* Clear group and global bits */ myid[0] &= ~3; have_id: myseqno = (random() & 0xFFFF); fd = open(state_file, O_RDONLY); if(fd < 0 && errno != ENOENT) perror("open(babel-state)"); rc = unlink(state_file); if(fd >= 0 && rc < 0) { perror("unlink(babel-state)"); /* If we couldn't unlink it, it's probably stale. */ close(fd); fd = -1; } if(fd >= 0) { char buf[100]; char buf2[100]; int s; long t; rc = read(fd, buf, 99); if(rc < 0) { perror("read(babel-state)"); } else { buf[rc] = '\0'; rc = sscanf(buf, "%99s %d %ld\n", buf2, &s, &t); if(rc == 3 && s >= 0 && s <= 0xFFFF) { unsigned char sid[8]; rc = parse_eui64(buf2, sid); if(rc < 0) { fprintf(stderr, "Couldn't parse babel-state.\n"); } else { struct timeval realnow; debugf("Got %s %d %ld from babel-state.\n", format_eui64(sid), s, t); gettimeofday(&realnow, NULL); if(memcmp(sid, myid, 8) == 0) myseqno = seqno_plus(s, 1); else if(!random_id) fprintf(stderr, "ID mismatch in babel-state.\n"); } } else { fprintf(stderr, "Couldn't parse babel-state.\n"); } } close(fd); fd = -1; } protocol_socket = babel_socket(protocol_port); if(protocol_socket < 0) { perror("Couldn't create link local socket"); goto fail; } #ifndef NO_LOCAL_INTERFACE if(local_server_port >= 0) { local_server_socket = tcp_server_socket(local_server_port, 1); if(local_server_socket < 0) { perror("local_server_socket"); goto fail; } } #endif init_signals(); rc = resize_receive_buffer(1500); if(rc < 0) goto fail; if(receive_buffer == NULL) goto fail; check_interfaces(); rc = check_xroutes(0); if(rc < 0) fprintf(stderr, "Warning: couldn't check exported routes.\n"); kernel_routes_changed = 0; kernel_link_changed = 0; kernel_addr_changed = 0; kernel_dump_time = now.tv_sec + roughly(30); schedule_neighbours_check(5000, 1); schedule_interfaces_check(30000, 1); expiry_time = now.tv_sec + roughly(30); source_expiry_time = now.tv_sec + roughly(300); /* Make some noise so that others notice us, and send retractions in case we were restarted recently */ FOR_ALL_INTERFACES(ifp) { if(!if_up(ifp)) continue; /* Apply jitter before we send the first message. */ usleep(roughly(10000)); gettime(&now); send_hello(ifp); send_wildcard_retraction(ifp); } FOR_ALL_INTERFACES(ifp) { if(!if_up(ifp)) continue; usleep(roughly(10000)); gettime(&now); send_hello(ifp); send_wildcard_retraction(ifp); send_self_update(ifp); send_request(ifp, NULL, 0); flushupdates(ifp); flushbuf(ifp); } debugf("Entering main loop.\n"); while(1) { struct timeval tv; fd_set readfds; gettime(&now); tv = check_neighbours_timeout; timeval_min(&tv, &check_interfaces_timeout); timeval_min_sec(&tv, expiry_time); timeval_min_sec(&tv, source_expiry_time); timeval_min_sec(&tv, kernel_dump_time); timeval_min(&tv, &resend_time); FOR_ALL_INTERFACES(ifp) { if(!if_up(ifp)) continue; timeval_min(&tv, &ifp->flush_timeout); timeval_min(&tv, &ifp->hello_timeout); timeval_min(&tv, &ifp->update_timeout); timeval_min(&tv, &ifp->update_flush_timeout); } timeval_min(&tv, &unicast_flush_timeout); FD_ZERO(&readfds); if(timeval_compare(&tv, &now) > 0) { int maxfd = 0; timeval_minus(&tv, &tv, &now); FD_SET(protocol_socket, &readfds); maxfd = MAX(maxfd, protocol_socket); if(kernel_socket < 0) kernel_setup_socket(1); if(kernel_socket >= 0) { FD_SET(kernel_socket, &readfds); maxfd = MAX(maxfd, kernel_socket); } #ifndef NO_LOCAL_INTERFACE if(local_server_socket >= 0 && num_local_sockets < MAX_LOCAL_SOCKETS) { FD_SET(local_server_socket, &readfds); maxfd = MAX(maxfd, local_server_socket); } for(i = 0; i < num_local_sockets; i++) { FD_SET(local_sockets[i], &readfds); maxfd = MAX(maxfd, local_sockets[i]); } #endif rc = select(maxfd + 1, &readfds, NULL, NULL, &tv); if(rc < 0) { if(errno != EINTR) { perror("select"); sleep(1); } rc = 0; FD_ZERO(&readfds); } } gettime(&now); if(exiting) break; if(kernel_socket >= 0 && FD_ISSET(kernel_socket, &readfds)) kernel_callback(kernel_routes_callback, NULL); if(FD_ISSET(protocol_socket, &readfds)) { rc = babel_recv(protocol_socket, receive_buffer, receive_buffer_size, (struct sockaddr*)&sin6, sizeof(sin6)); if(rc < 0) { if(errno != EAGAIN && errno != EINTR) { perror("recv"); sleep(1); } } else { FOR_ALL_INTERFACES(ifp) { if(!if_up(ifp)) continue; if(ifp->ifindex == sin6.sin6_scope_id) { parse_packet((unsigned char*)&sin6.sin6_addr, ifp, receive_buffer, rc); VALGRIND_MAKE_MEM_UNDEFINED(receive_buffer, receive_buffer_size); break; } } } } #ifndef NO_LOCAL_INTERFACE accept_local_connections(&readfds); i = 0; while(i < num_local_sockets) { if(FD_ISSET(local_sockets[i], &readfds)) { rc = local_read(local_sockets[i]); if(rc <= 0) { if(rc < 0) { if(errno == EINTR) continue; perror("read(local_socket)"); } close(local_sockets[i]); local_sockets[i] = local_sockets[--num_local_sockets]; continue; } } i++; } #endif if(reopening) { kernel_dump_time = now.tv_sec; check_neighbours_timeout = now; expiry_time = now.tv_sec; rc = reopen_logfile(); if(rc < 0) { perror("reopen_logfile"); break; } reopening = 0; } if(kernel_link_changed || kernel_addr_changed) { check_interfaces(); kernel_link_changed = 0; } if(kernel_routes_changed || kernel_addr_changed || now.tv_sec >= kernel_dump_time) { rc = check_xroutes(1); if(rc < 0) fprintf(stderr, "Warning: couldn't check exported routes.\n"); kernel_routes_changed = kernel_addr_changed = 0; if(kernel_socket >= 0) kernel_dump_time = now.tv_sec + roughly(300); else kernel_dump_time = now.tv_sec + roughly(30); } if(timeval_compare(&check_neighbours_timeout, &now) < 0) { int msecs; msecs = check_neighbours(); /* Multiply by 3/2 to allow neighbours to expire. */ msecs = MAX(3 * msecs / 2, 10); schedule_neighbours_check(msecs, 1); } if(timeval_compare(&check_interfaces_timeout, &now) < 0) { check_interfaces(); schedule_interfaces_check(30000, 1); } if(now.tv_sec >= expiry_time) { expire_routes(); expire_resend(); expiry_time = now.tv_sec + roughly(30); } if(now.tv_sec >= source_expiry_time) { expire_sources(); source_expiry_time = now.tv_sec + roughly(300); } FOR_ALL_INTERFACES(ifp) { if(!if_up(ifp)) continue; if(timeval_compare(&now, &ifp->hello_timeout) >= 0) send_hello(ifp); if(timeval_compare(&now, &ifp->update_timeout) >= 0) send_update(ifp, 0, NULL, 0); if(timeval_compare(&now, &ifp->update_flush_timeout) >= 0) flushupdates(ifp); } if(resend_time.tv_sec != 0) { if(timeval_compare(&now, &resend_time) >= 0) do_resend(); } if(unicast_flush_timeout.tv_sec != 0) { if(timeval_compare(&now, &unicast_flush_timeout) >= 0) flush_unicast(1); } FOR_ALL_INTERFACES(ifp) { if(!if_up(ifp)) continue; if(ifp->flush_timeout.tv_sec != 0) { if(timeval_compare(&now, &ifp->flush_timeout) >= 0) flushbuf(ifp); } } if(UNLIKELY(debug || dumping)) { dump_tables(stdout); dumping = 0; } }
void mroute6pr(u_long mfcaddr, u_long mifaddr) { struct mf6c *mf6ctable[MF6CTBLSIZ], *mfcp; struct mif6 mif6table[MAXMIFS]; struct mf6c mfc; struct rtdetq rte, *rtep; struct mif6 *mifp; mifi_t mifi; int i; int banner_printed; int saved_numeric_addr; mifi_t maxmif = 0; long int waitings; size_t len; len = sizeof(mif6table); if (live) { if (sysctlbyname("net.inet6.ip6.mif6table", mif6table, &len, NULL, 0) < 0) { warn("sysctl: net.inet6.ip6.mif6table"); return; } } else kread(mifaddr, (char *)mif6table, sizeof(mif6table)); saved_numeric_addr = numeric_addr; numeric_addr = 1; banner_printed = 0; for (mifi = 0, mifp = mif6table; mifi < MAXMIFS; ++mifi, ++mifp) { struct ifnet ifnet; char ifname[IFNAMSIZ]; if (mifp->m6_ifp == NULL) continue; /* XXX KVM */ kread((u_long)mifp->m6_ifp, (char *)&ifnet, sizeof(ifnet)); maxmif = mifi; if (!banner_printed) { printf("\nIPv6 Multicast Interface Table\n" " Mif Rate PhyIF " "Pkts-In Pkts-Out\n"); banner_printed = 1; } printf(" %2u %4d", mifi, mifp->m6_rate_limit); printf(" %5s", (mifp->m6_flags & MIFF_REGISTER) ? "reg0" : if_indextoname(ifnet.if_index, ifname)); printf(" %9ju %9ju\n", (uintmax_t)mifp->m6_pkt_in, (uintmax_t)mifp->m6_pkt_out); } if (!banner_printed) printf("\nIPv6 Multicast Interface Table is empty\n"); len = sizeof(mf6ctable); if (live) { if (sysctlbyname("net.inet6.ip6.mf6ctable", mf6ctable, &len, NULL, 0) < 0) { warn("sysctl: net.inet6.ip6.mf6ctable"); return; } } else kread(mfcaddr, (char *)mf6ctable, sizeof(mf6ctable)); banner_printed = 0; for (i = 0; i < MF6CTBLSIZ; ++i) { mfcp = mf6ctable[i]; while(mfcp) { kread((u_long)mfcp, (char *)&mfc, sizeof(mfc)); if (!banner_printed) { printf ("\nIPv6 Multicast Forwarding Cache\n"); printf(" %-*.*s %-*.*s %s", WID_ORG, WID_ORG, "Origin", WID_GRP, WID_GRP, "Group", " Packets Waits In-Mif Out-Mifs\n"); banner_printed = 1; } printf(" %-*.*s", WID_ORG, WID_ORG, routename6(&mfc.mf6c_origin)); printf(" %-*.*s", WID_GRP, WID_GRP, routename6(&mfc.mf6c_mcastgrp)); printf(" %9ju", (uintmax_t)mfc.mf6c_pkt_cnt); for (waitings = 0, rtep = mfc.mf6c_stall; rtep; ) { waitings++; /* XXX KVM */ kread((u_long)rtep, (char *)&rte, sizeof(rte)); rtep = rte.next; } printf(" %3ld", waitings); if (mfc.mf6c_parent == MF6C_INCOMPLETE_PARENT) printf(" --- "); else printf(" %3d ", mfc.mf6c_parent); for (mifi = 0; mifi <= maxmif; mifi++) { if (IF_ISSET(mifi, &mfc.mf6c_ifset)) printf(" %u", mifi); } printf("\n"); mfcp = mfc.mf6c_next; } } if (!banner_printed) printf("\nIPv6 Multicast Forwarding Table is empty\n"); printf("\n"); numeric_addr = saved_numeric_addr; }
static int link_addr(struct nlmsghdr *nlm) { int len; struct rtattr *rta; struct ifaddrmsg *ifa; char ifn[IF_NAMESIZE + 1]; struct interface *iface; #ifdef INET struct in_addr addr, net, dest; #endif #ifdef INET6 struct in6_addr addr6; #endif if (nlm->nlmsg_type != RTM_DELADDR && nlm->nlmsg_type != RTM_NEWADDR) return 0; len = nlm->nlmsg_len - sizeof(*nlm); if ((size_t)len < sizeof(*ifa)) { errno = EBADMSG; return -1; } // if (nlm->nlmsg_pid == (uint32_t)getpid()) // return 1; ifa = NLMSG_DATA(nlm); if (if_indextoname(ifa->ifa_index, ifn) == NULL) return -1; iface = find_interface(ifn); if (iface == NULL) return 1; rta = (struct rtattr *) IFA_RTA(ifa); len = NLMSG_PAYLOAD(nlm, sizeof(*ifa)); switch (ifa->ifa_family) { #ifdef INET case AF_INET: addr.s_addr = dest.s_addr = INADDR_ANY; dest.s_addr = INADDR_ANY; inet_cidrtoaddr(ifa->ifa_prefixlen, &net); while (RTA_OK(rta, len)) { switch (rta->rta_type) { case IFA_ADDRESS: if (iface->flags & IFF_POINTOPOINT) { memcpy(&dest.s_addr, RTA_DATA(rta), sizeof(addr.s_addr)); } break; case IFA_LOCAL: memcpy(&addr.s_addr, RTA_DATA(rta), sizeof(addr.s_addr)); break; } rta = RTA_NEXT(rta, len); } ipv4_handleifa(nlm->nlmsg_type, NULL, ifn, &addr, &net, &dest); break; #endif #ifdef INET6 case AF_INET6: memset(&addr6, 0, sizeof(addr6)); while (RTA_OK(rta, len)) { switch (rta->rta_type) { case IFA_ADDRESS: memcpy(&addr6.s6_addr, RTA_DATA(rta), sizeof(addr6.s6_addr)); break; } rta = RTA_NEXT(rta, len); } ipv6_handleifa(nlm->nlmsg_type, NULL, ifn, &addr6, ifa->ifa_flags); break; #endif } return 1; }
static int dump_msg(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { FILE *fp = arg; struct ifinfomsg *ifi = NLMSG_DATA(n); struct rtattr * tb[IFLA_MAX + 1]; int len = n->nlmsg_len; char b1[IFNAMSIZ]; int af_family = ifi->ifi_family; bool newlink; int br_index; if(n->nlmsg_type == NLMSG_DONE) return 0; len -= NLMSG_LENGTH(sizeof(*ifi)); if(len < 0) { return -1; } if(af_family != AF_BRIDGE && af_family != AF_UNSPEC) return 0; if(n->nlmsg_type != RTM_NEWLINK && n->nlmsg_type != RTM_DELLINK) return 0; parse_rtattr(tb, IFLA_MAX, IFLA_RTA(ifi), len); /* Check if we got this from bonding */ if(tb[IFLA_MASTER] && af_family != AF_BRIDGE) return 0; if(tb[IFLA_IFNAME] == NULL) { fprintf(stderr, "BUG: nil ifname\n"); return -1; } if(n->nlmsg_type == RTM_DELLINK) fprintf(fp, "Deleted "); fprintf(fp, "%d: %s ", ifi->ifi_index, (char*)RTA_DATA(tb[IFLA_IFNAME])); if(tb[IFLA_OPERSTATE]) { int state = *(int*)RTA_DATA(tb[IFLA_OPERSTATE]); switch (state) { case IF_OPER_UNKNOWN: fprintf(fp, "Unknown "); break; case IF_OPER_NOTPRESENT: fprintf(fp, "Not Present "); break; case IF_OPER_DOWN: fprintf(fp, "Down "); break; case IF_OPER_LOWERLAYERDOWN: fprintf(fp, "Lowerlayerdown "); break; case IF_OPER_TESTING: fprintf(fp, "Testing "); break; case IF_OPER_DORMANT: fprintf(fp, "Dormant "); break; case IF_OPER_UP: fprintf(fp, "Up "); break; default: fprintf(fp, "State(%d) ", state); } } if(tb[IFLA_MTU]) fprintf(fp, "mtu %u ", *(int*)RTA_DATA(tb[IFLA_MTU])); if(tb[IFLA_MASTER]) { fprintf(fp, "master %s ", if_indextoname(*(int*)RTA_DATA(tb[IFLA_MASTER]), b1)); } if(tb[IFLA_PROTINFO]) { uint8_t state = *(uint8_t *)RTA_DATA(tb[IFLA_PROTINFO]); if(state <= BR_STATE_BLOCKING) fprintf(fp, "state %s", port_states[state]); else fprintf(fp, "state (%d)", state); } fprintf(fp, "\n"); fflush(fp); newlink = (n->nlmsg_type == RTM_NEWLINK); if(tb[IFLA_MASTER]) br_index = *(int*)RTA_DATA(tb[IFLA_MASTER]); else if(is_bridge((char*)RTA_DATA(tb[IFLA_IFNAME]))) br_index = ifi->ifi_index; else br_index = -1; bridge_notify(br_index, ifi->ifi_index, newlink, ifi->ifi_flags); return 0; }
/* * Parse a RTM_NEWNDUSEROPT message. */ bool NetlinkEvent::parseNdUserOptMessage(struct nduseroptmsg *msg, int len) { // Check the length is valid. if (msg->nduseropt_opts_len > len) { SLOGE("RTM_NEWNDUSEROPT invalid length %d > %d\n", msg->nduseropt_opts_len, len); return false; } len = msg->nduseropt_opts_len; // Check address family and packet type. if (msg->nduseropt_family != AF_INET6) { SLOGE("RTM_NEWNDUSEROPT message for unknown family %d\n", msg->nduseropt_family); return false; } if (msg->nduseropt_icmp_type != ND_ROUTER_ADVERT || msg->nduseropt_icmp_code != 0) { SLOGE("RTM_NEWNDUSEROPT message for unknown ICMPv6 type/code %d/%d\n", msg->nduseropt_icmp_type, msg->nduseropt_icmp_code); return false; } // Find the interface name. char ifname[IFNAMSIZ + 1]; if (!if_indextoname(msg->nduseropt_ifindex, ifname)) { SLOGE("RTM_NEWNDUSEROPT on unknown ifindex %d\n", msg->nduseropt_ifindex); return false; } // The kernel sends a separate netlink message for each ND option in the RA. // So only parse the first ND option in the message. struct nd_opt_hdr *opthdr = (struct nd_opt_hdr *) (msg + 1); // The length is in multiples of 8 octets. uint16_t optlen = opthdr->nd_opt_len; if (optlen * 8 > len) { SLOGE("Invalid option length %d > %d for ND option %d\n", optlen * 8, len, opthdr->nd_opt_type); return false; } if (opthdr->nd_opt_type == ND_OPT_RDNSS) { // DNS Servers (RFC 6106). // Each address takes up 2*8 octets, and the header takes up 8 octets. // So for a valid option with one or more addresses, optlen must be // odd and greater than 1. if ((optlen < 3) || !(optlen & 0x1)) { SLOGE("Invalid optlen %d for RDNSS option\n", optlen); return false; } int numaddrs = (optlen - 1) / 2; // Find the lifetime. struct nd_opt_rdnss *rndss_opt = (struct nd_opt_rdnss *) opthdr; uint32_t lifetime = ntohl(rndss_opt->nd_opt_rdnss_lifetime); // Construct "SERVERS=<comma-separated string of DNS addresses>". // Reserve (INET6_ADDRSTRLEN + 1) chars for each address: all but the // the last address are followed by ','; the last is followed by '\0'. static const char kServerTag[] = "SERVERS="; static const int kTagLength = sizeof(kServerTag) - 1; int bufsize = kTagLength + numaddrs * (INET6_ADDRSTRLEN + 1); char *buf = (char *) malloc(bufsize); if (!buf) { SLOGE("RDNSS option: out of memory\n"); return false; } strcpy(buf, kServerTag); int pos = kTagLength; struct in6_addr *addrs = (struct in6_addr *) (rndss_opt + 1); for (int i = 0; i < numaddrs; i++) { if (i > 0) { buf[pos++] = ','; } inet_ntop(AF_INET6, addrs + i, buf + pos, bufsize - pos); pos += strlen(buf + pos); } buf[pos] = '\0'; mAction = NlActionRdnss; mSubsystem = strdup("net"); asprintf(&mParams[0], "INTERFACE=%s", ifname); asprintf(&mParams[1], "LIFETIME=%u", lifetime); mParams[2] = buf; } else { SLOGD("Unknown ND option type %d\n", opthdr->nd_opt_type); return false; } return true; }
size_t acl_inet_ntop(const struct sockaddr *sa, char *buf, size_t size) { if (sa->sa_family == AF_INET) { int port; char ip[IPLEN]; struct sockaddr_in *in = (struct sockaddr_in*) sa; if (!inet_ntop(sa->sa_family, &in->sin_addr, ip, IPLEN)) { return 0; } port = ntohs(in->sin_port); if (port > 0) { snprintf(buf, size, "%s:%d", ip, port); } else { snprintf(buf, size, "%s", ip); } return sizeof(struct sockaddr_in); #ifdef AF_INET6 } else if (sa->sa_family == AF_INET6) { int port; char ip[IPLEN], ifname[IF_NAMESIZE], *ptr; struct sockaddr_in6 *in6 = (struct sockaddr_in6*) sa; if (!inet_ntop(sa->sa_family, &in6->sin6_addr, ip, IPLEN)) { return 0; } ptr = if_indextoname(in6->sin6_scope_id, ifname); if (ptr == NULL) { ifname[0] = 0; } port = ntohs(in6->sin6_port); if (port <= 0) { if (strcmp(ip, "::1") == 0) { snprintf(buf, size, "%s", ip); } else if (ifname[0] != 0) { snprintf(buf, size, "%s%%%s", ip, ifname); } else { snprintf(buf, size, "%s", ip); } } else if (strcmp(ip, "::1") == 0) { /* for local IPV6 */ snprintf(buf, size, "%s%c%d", ip, ACL_ADDR_SEP, port); } else if (ifname[0] != 0) { snprintf(buf, size, "%s%%%s%c%d", ip, ifname, ACL_ADDR_SEP, port); } else { snprintf(buf, size, "%s%c%d", ip, ACL_ADDR_SEP, port); } return sizeof(struct sockaddr_in6); #endif #ifdef ACL_UNIX } else if (sa->sa_family == AF_UNIX) { struct sockaddr_un *un = (struct sockaddr_un *) sa; ACL_SAFE_STRNCPY(buf, un->sun_path, size); return sizeof(struct sockaddr_un); #endif } else { return 0; } }
/* * Handle an incoming RIP packet. */ static void rip_input(struct sockaddr_in *from, int size, uint_t ifindex) { struct netinfo *n, *lim; struct in_addr in; const char *name; char net_buf[80]; uchar_t hash[RIP_AUTH_MD5_LEN]; MD5_CTX md5_ctx; uchar_t md5_authed = 0; in_addr_t mask, dmask; struct in_addr tmp_addr; char *sp; char ifname[IF_NAMESIZE+1]; int i; struct hostent *hp; struct netent *np; struct netauth *na; char srcaddr[MAXHOSTNAMELEN + sizeof (" (123.123.123.123)") + 1]; char ifstring[IF_NAMESIZE + 3*sizeof (ifindex) + sizeof (" ()") + 1]; if (!nflag && (hp = gethostbyaddr((char *)&from->sin_addr, sizeof (struct in_addr), AF_INET)) != NULL) { (void) snprintf(srcaddr, sizeof (srcaddr), "%s (%s)", hp->h_name, inet_ntoa(from->sin_addr)); } else { /* safe; cannot overflow destination */ (void) strcpy(srcaddr, inet_ntoa(from->sin_addr)); } if (ifindex == 0) { (void) printf("%s:", srcaddr); } else { if (if_indextoname(ifindex, ifname) != NULL) (void) snprintf(ifstring, sizeof (ifstring), "%s (%d)", ifname, ifindex); else (void) snprintf(ifstring, sizeof (ifstring), "%d", ifindex); (void) printf(gettext("%1$s received on interface %2$s:"), srcaddr, ifstring); } if (IMSG.rip_cmd != RIPCMD_RESPONSE) { (void) printf(gettext("\n unexpected response type %d\n"), IMSG.rip_cmd); return; } (void) printf(gettext(" RIPv%1$d%2$s %3$d bytes\n"), IMSG.rip_vers, (IMSG.rip_vers != RIPv1 && IMSG.rip_vers != RIPv2) ? " ?" : "", size); if (size > MAXPACKETSIZE) { if (size > sizeof (imsg_buf) - sizeof (*n)) { (void) printf( gettext(" at least %d bytes too long\n"), size-MAXPACKETSIZE); size = sizeof (imsg_buf) - sizeof (*n); } else { (void) printf(gettext(" %d bytes too long\n"), size-MAXPACKETSIZE); } } else if (size%sizeof (*n) != sizeof (struct rip)%sizeof (*n)) { (void) printf(gettext(" response of bad length=%d\n"), size); } n = IMSG.rip_nets; lim = n + (size - 4) / sizeof (struct netinfo); for (; n < lim; n++) { name = ""; if (n->n_family == RIP_AF_INET) { in.s_addr = n->n_dst; (void) strlcpy(net_buf, inet_ntoa(in), sizeof (net_buf)); tmp_addr.s_addr = (n->n_mask); mask = ntohl(n->n_mask); dmask = mask & -mask; if (mask != 0) { sp = &net_buf[strlen(net_buf)]; if (IMSG.rip_vers == RIPv1) { (void) snprintf(sp, (sizeof (net_buf) - strlen(net_buf)), gettext(" mask=%s ? "), inet_ntoa(tmp_addr)); mask = 0; } else if (mask + dmask == 0) { i = ffs(mask) - 1; (void) snprintf(sp, (sizeof (net_buf) - strlen(net_buf)), "/%d", 32-i); } else { (void) snprintf(sp, (sizeof (net_buf) - strlen(net_buf)), gettext(" (mask %s)"), inet_ntoa(tmp_addr)); } } if (!nflag) { if (mask == 0) { mask = std_mask(in.s_addr); if ((ntohl(in.s_addr) & ~mask) != 0) mask = 0; } /* * Without a netmask, do not worry about * whether the destination is a host or a * network. Try both and use the first name * we get. * * If we have a netmask we can make a * good guess. */ if ((in.s_addr & ~mask) == 0) { np = getnetbyaddr((long)in.s_addr, AF_INET); if (np != NULL) name = np->n_name; else if (in.s_addr == 0) name = "default"; } if (name[0] == '\0' && ((in.s_addr & ~mask) != 0 || mask == 0xffffffff)) { hp = gethostbyaddr((char *)&in, sizeof (in), AF_INET); if (hp != NULL) name = hp->h_name; } } } else if (n->n_family == RIP_AF_AUTH) { na = (struct netauth *)n; if (na->a_type == RIP_AUTH_PW && n == IMSG.rip_nets) { (void) printf( gettext(" Password Authentication:" " \"%s\"\n"), qstring(na->au.au_pw, RIP_AUTH_PW_LEN)); continue; } if (na->a_type == RIP_AUTH_MD5 && n == IMSG.rip_nets) { (void) printf(gettext(" MD5 Auth" " len=%1$d KeyID=%2$d" " auth_len=%3$d" " seqno=%4$#x" " rsvd=%5$#x,%6$#x\n"), ntohs(na->au.a_md5.md5_pkt_len), na->au.a_md5.md5_keyid, na->au.a_md5.md5_auth_len, (int)ntohl(na->au.a_md5.md5_seqno), na->au.a_md5.rsvd[0], na->au.a_md5.rsvd[1]); md5_authed = 1; continue; } (void) printf(gettext(" Authentication type %d: "), ntohs(na->a_type)); for (i = 0; i < sizeof (na->au.au_pw); i++) (void) printf("%02x ", na->au.au_pw[i]); (void) putchar('\n'); if (md5_authed && n+1 > lim && na->a_type == RIP_AUTH_TRAILER) { MD5Init(&md5_ctx); MD5Update(&md5_ctx, (uchar_t *)&IMSG, (char *)na-(char *)&IMSG); MD5Update(&md5_ctx, (uchar_t *)passwd, RIP_AUTH_MD5_LEN); MD5Final(hash, &md5_ctx); (void) printf(gettext(" %s hash\n"), memcmp(hash, na->au.au_pw, sizeof (hash)) ? gettext("WRONG") : gettext("correct")); } else if (md5_authed && n+1 > lim && na->a_type != RIP_AUTH_TRAILER) { (void) printf(gettext("Error -" "authentication entry missing hash\n")); } continue; } else { tmp_addr.s_addr = n->n_dst; (void) snprintf(net_buf, sizeof (net_buf), gettext("(address family %1$u) %2$s"), ntohs(n->n_family), inet_ntoa(tmp_addr)); } (void) printf(gettext(" %1$-18s metric %2$2lu %3$-10s"), net_buf, ntohl(n->n_metric), name); if (n->n_nhop != 0) { in.s_addr = n->n_nhop; if (nflag) hp = NULL; else hp = gethostbyaddr((char *)&in, sizeof (in), AF_INET); (void) printf(gettext(" nhop=%1$-15s%2$s"), (hp != NULL) ? hp->h_name : inet_ntoa(in), (IMSG.rip_vers == RIPv1) ? " ?" : ""); } if (n->n_tag != 0) (void) printf(gettext(" tag=%1$#x%2$s"), n->n_tag, (IMSG.rip_vers == RIPv1) ? " ?" : ""); (void) putchar('\n'); } }
/* Parse one route */ static int rt_parse(const struct nlmsghdr *nlhdr, struct net_rt *rt) { struct rtmsg *rtmsg; struct rtattr *rtattr; int len; rtmsg = (struct rtmsg *)NLMSG_DATA(nlhdr); /* If the route does not belong to main routing table then return. */ if (RT_TABLE_MAIN != rtmsg->rtm_table) return EINVAL; sa_init(&rt->dst, rtmsg->rtm_family); rt->dstlen = rtmsg->rtm_dst_len; /* get the rtattr field */ rtattr = (struct rtattr *)RTM_RTA(rtmsg); len = RTM_PAYLOAD(nlhdr); for (;RTA_OK(rtattr, len); rtattr = RTA_NEXT(rtattr, len)) { switch (rtattr->rta_type) { case RTA_OIF: if_indextoname(*(int *)RTA_DATA(rtattr), rt->ifname); break; case RTA_GATEWAY: switch (rtmsg->rtm_family) { case AF_INET: sa_init(&rt->gw, AF_INET); rt->gw.u.in.sin_addr.s_addr = *(uint32_t *)RTA_DATA(rtattr); break; #ifdef HAVE_INET6 case AF_INET6: sa_set_in6(&rt->gw, RTA_DATA(rtattr), 0); break; #endif default: DEBUG_WARNING("RTA_DST: unknown family %d\n", rtmsg->rtm_family); break; } break; #if 0 case RTA_PREFSRC: rt->srcaddr = *(uint32_t *)RTA_DATA(rtattr); break; #endif case RTA_DST: switch (rtmsg->rtm_family) { case AF_INET: sa_init(&rt->dst, AF_INET); rt->dst.u.in.sin_addr.s_addr = *(uint32_t *)RTA_DATA(rtattr); break; #ifdef HAVE_INET6 case AF_INET6: sa_set_in6(&rt->dst, RTA_DATA(rtattr), 0); break; #endif default: DEBUG_WARNING("RTA_DST: unknown family %d\n", rtmsg->rtm_family); break; } break; } } return 0; }
void updateNioCounters(HSP *sp) { // don't do anything if we already refreshed the numbers less than a second ago if(sp->adaptorNIOList.last_update == sp->clk) { return; } sp->adaptorNIOList.last_update = sp->clk; static int mib[] = { CTL_NET, PF_ROUTE, 0, 0, /* address family */ NET_RT_IFLIST, 0 }; /* ifIndex */ size_t needed = 0; if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) { myLog(LOG_ERR, "sysctl for interface list failed"); return; } char *buf = my_calloc(needed); if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { myLog(LOG_ERR, "sysctl for interface list failed (2nd time)"); } else { char *lim = buf + needed; char *next = buf; while (next < lim) { struct if_msghdr *ifm = (struct if_msghdr *)next; if (ifm->ifm_type != RTM_IFINFO) { myLog(LOG_ERR, "out of sync parsing NET_RT_IFLIST\n"); break; } next += ifm->ifm_msglen; while (next < lim) { struct if_msghdr *nextifm = (struct if_msghdr *)next; if (nextifm->ifm_type != RTM_NEWADDR) break; next += nextifm->ifm_msglen; } if (!(ifm->ifm_flags & IFF_LOOPBACK) && (ifm->ifm_flags & IFF_UP)) { char deviceName[IFNAMSIZ]; uint32_t index = ifm->ifm_index; if(if_indextoname(index, deviceName)) { char *str = deviceName; trimWhitespace(str); HSPAdaptorNIO *adaptor = getAdaptorNIO(&sp->adaptorNIOList, str); if(adaptor) { uint64_t bytes_in = ifm->ifm_data.ifi_ibytes; uint64_t pkts_in = ifm->ifm_data.ifi_ipackets; uint64_t errs_in = ifm->ifm_data.ifi_ierrors; uint64_t drops_in = ifm->ifm_data.ifi_iqdrops; uint64_t bytes_out = ifm->ifm_data.ifi_obytes; uint64_t pkts_out = ifm->ifm_data.ifi_opackets; uint64_t errs_out = ifm->ifm_data.ifi_oerrors; uint64_t drops_out = (uint64_t)-1; /* unsupported */ // have to detect discontinuities here, so use a full // set of latched counters and accumulators. int accumulate = adaptor->last_update ? YES : NO; adaptor->last_update = sp->clk; uint64_t maxDeltaBytes = HSP_MAX_NIO_DELTA64; SFLHost_nio_counters delta; #define NIO_COMPUTE_DELTA(field) delta.field = field - adaptor->last_nio.field NIO_COMPUTE_DELTA(pkts_in); NIO_COMPUTE_DELTA(errs_in); NIO_COMPUTE_DELTA(drops_in); NIO_COMPUTE_DELTA(pkts_out); NIO_COMPUTE_DELTA(errs_out); NIO_COMPUTE_DELTA(drops_out); if(sp->adaptorNIOList.polling_secs == 0) { // 64-bit byte counters NIO_COMPUTE_DELTA(bytes_in); NIO_COMPUTE_DELTA(bytes_out); } else { // for case where byte counters are 32-bit, we need // to use 32-bit unsigned arithmetic to avoid spikes delta.bytes_in = (uint32_t)bytes_in - adaptor->last_bytes_in32; delta.bytes_out = (uint32_t)bytes_out - adaptor->last_bytes_out32; adaptor->last_bytes_in32 = bytes_in; adaptor->last_bytes_out32 = bytes_out; maxDeltaBytes = HSP_MAX_NIO_DELTA32; // if we detect that the OS is using 64-bits then we can turn off the faster // NIO polling. This should probably be done based on the kernel version or some // other include-file definition, but it's not expensive to do it here like this: if(bytes_in > 0xFFFFFFFF || bytes_out > 0xFFFFFFFF) { myLog(LOG_INFO, "detected 64-bit counters in /proc/net/dev"); sp->adaptorNIOList.polling_secs = 0; } } if(accumulate) { // sanity check in case the counters were reset under out feet. // normally we leave this to the upstream collector, but these // numbers might be getting passed through from the hardware(?) // so we treat them with particular distrust. if(delta.bytes_in > maxDeltaBytes || delta.bytes_out > maxDeltaBytes || delta.pkts_in > HSP_MAX_NIO_DELTA32 || delta.pkts_out > HSP_MAX_NIO_DELTA32) { myLog(LOG_ERR, "detected counter discontinuity in /proc/net/dev"); accumulate = NO; } } if(accumulate) { #define NIO_ACCUMULATE(field) adaptor->nio.field += delta.field NIO_ACCUMULATE(bytes_in); NIO_ACCUMULATE(pkts_in); NIO_ACCUMULATE(errs_in); NIO_ACCUMULATE(drops_in); NIO_ACCUMULATE(bytes_out); NIO_ACCUMULATE(pkts_out); NIO_ACCUMULATE(errs_out); NIO_ACCUMULATE(drops_out); } #define NIO_LATCH(field) adaptor->last_nio.field = field NIO_LATCH(bytes_in); NIO_LATCH(pkts_in); NIO_LATCH(errs_in); NIO_LATCH(drops_in); NIO_LATCH(bytes_out); NIO_LATCH(pkts_out); NIO_LATCH(errs_out); NIO_LATCH(drops_out); } } } } } my_free(buf); }
int print_linkinfo(const struct sockaddr_nl *who, struct nlmsghdr *n, void *arg) { FILE *fp = arg; int len = n->nlmsg_len; struct ifinfomsg *ifi = NLMSG_DATA(n); struct rtattr * tb[IFLA_MAX+1]; char b1[IFNAMSIZ]; len -= NLMSG_LENGTH(sizeof(*ifi)); if (len < 0) { fprintf(stderr, "Message too short!\n"); return -1; } if (!(ifi->ifi_family == AF_BRIDGE || ifi->ifi_family == AF_UNSPEC)) return 0; if (filter_index && filter_index != ifi->ifi_index) return 0; parse_rtattr_flags(tb, IFLA_MAX, IFLA_RTA(ifi), len, NLA_F_NESTED); if (tb[IFLA_IFNAME] == NULL) { fprintf(stderr, "BUG: nil ifname\n"); return -1; } if (n->nlmsg_type == RTM_DELLINK) fprintf(fp, "Deleted "); fprintf(fp, "%d: %s ", ifi->ifi_index, tb[IFLA_IFNAME] ? rta_getattr_str(tb[IFLA_IFNAME]) : "<nil>"); if (tb[IFLA_OPERSTATE]) print_operstate(fp, rta_getattr_u8(tb[IFLA_OPERSTATE])); if (tb[IFLA_LINK]) { SPRINT_BUF(b1); int iflink = rta_getattr_u32(tb[IFLA_LINK]); if (iflink == 0) fprintf(fp, "@NONE: "); else fprintf(fp, "@%s: ", if_indextoname(iflink, b1)); } else fprintf(fp, ": "); print_link_flags(fp, ifi->ifi_flags); if (tb[IFLA_MTU]) fprintf(fp, "mtu %u ", rta_getattr_u32(tb[IFLA_MTU])); if (tb[IFLA_MASTER]) fprintf(fp, "master %s ", if_indextoname(rta_getattr_u32(tb[IFLA_MASTER]), b1)); if (tb[IFLA_PROTINFO]) { if (tb[IFLA_PROTINFO]->rta_type & NLA_F_NESTED) { struct rtattr *prtb[IFLA_BRPORT_MAX+1]; parse_rtattr_nested(prtb, IFLA_BRPORT_MAX, tb[IFLA_PROTINFO]); if (prtb[IFLA_BRPORT_STATE]) print_portstate(fp, rta_getattr_u8(prtb[IFLA_BRPORT_STATE])); if (prtb[IFLA_BRPORT_PRIORITY]) fprintf(fp, "priority %hu ", rta_getattr_u16(prtb[IFLA_BRPORT_PRIORITY])); if (prtb[IFLA_BRPORT_COST]) fprintf(fp, "cost %u ", rta_getattr_u32(prtb[IFLA_BRPORT_COST])); if (show_details) { fprintf(fp, "%s ", _SL_); if (prtb[IFLA_BRPORT_MODE]) print_onoff(fp, "hairpin", rta_getattr_u8(prtb[IFLA_BRPORT_MODE])); if (prtb[IFLA_BRPORT_GUARD]) print_onoff(fp, "guard", rta_getattr_u8(prtb[IFLA_BRPORT_GUARD])); if (prtb[IFLA_BRPORT_PROTECT]) print_onoff(fp, "root_block", rta_getattr_u8(prtb[IFLA_BRPORT_PROTECT])); if (prtb[IFLA_BRPORT_FAST_LEAVE]) print_onoff(fp, "fastleave", rta_getattr_u8(prtb[IFLA_BRPORT_FAST_LEAVE])); if (prtb[IFLA_BRPORT_LEARNING]) print_onoff(fp, "learning", rta_getattr_u8(prtb[IFLA_BRPORT_LEARNING])); if (prtb[IFLA_BRPORT_LEARNING_SYNC]) print_onoff(fp, "learning_sync", rta_getattr_u8(prtb[IFLA_BRPORT_LEARNING_SYNC])); if (prtb[IFLA_BRPORT_UNICAST_FLOOD]) print_onoff(fp, "flood", rta_getattr_u8(prtb[IFLA_BRPORT_UNICAST_FLOOD])); } } else print_portstate(fp, rta_getattr_u8(tb[IFLA_PROTINFO])); } if (tb[IFLA_AF_SPEC]) { /* This is reported by HW devices that have some bridging * capabilities. */ struct rtattr *aftb[IFLA_BRIDGE_MAX+1]; parse_rtattr_nested(aftb, IFLA_BRIDGE_MAX, tb[IFLA_AF_SPEC]); if (aftb[IFLA_BRIDGE_MODE]) print_hwmode(fp, rta_getattr_u16(aftb[IFLA_BRIDGE_MODE])); } fprintf(fp, "\n"); fflush(fp); return 0; }
static int gre_parse_opt(struct link_util *lu, int argc, char **argv, struct nlmsghdr *n) { struct ifinfomsg *ifi = (struct ifinfomsg *)(n + 1); struct { struct nlmsghdr n; struct ifinfomsg i; char buf[16384]; } req = { .n.nlmsg_len = NLMSG_LENGTH(sizeof(*ifi)), .n.nlmsg_flags = NLM_F_REQUEST, .n.nlmsg_type = RTM_GETLINK, .i.ifi_family = preferred_family, .i.ifi_index = ifi->ifi_index, }; 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; __u8 ignore_df = 0; __u32 fwmark = 0; __u32 erspan_idx = 0; __u8 keepalive_ret = 0; __u32 keepalive_interv = 0; if (!(n->nlmsg_flags & NLM_F_CREATE)) { 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; if (greinfo[IFLA_GRE_IGNORE_DF]) ignore_df = !!rta_getattr_u8(greinfo[IFLA_GRE_IGNORE_DF]); if (greinfo[IFLA_GRE_FWMARK]) fwmark = rta_getattr_u32(greinfo[IFLA_GRE_FWMARK]); if (greinfo[IFLA_GRE_ERSPAN_INDEX]) erspan_idx = rta_getattr_u32(greinfo[IFLA_GRE_ERSPAN_INDEX]); } 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 if (strcmp(*argv, "ignore-df") == 0) { ignore_df = 1; } else if (strcmp(*argv, "noignore-df") == 0) { /* *only the lsb is significant, use 2 for presence */ ignore_df = 2; } else if (strcmp(*argv, "fwmark") == 0) { NEXT_ARG(); if (get_u32(&fwmark, *argv, 0)) invarg("invalid fwmark\n", *argv); } else if (strcmp(*argv, "erspan") == 0) { NEXT_ARG(); if (get_u32(&erspan_idx, *argv, 0)) invarg("invalid erspan index\n", *argv); if (erspan_idx & ~((1<<20) - 1) || erspan_idx == 0) invarg("erspan index must be > 0 and <= 20-bit\n", *argv); } else if (!matches(*argv, "keepalive")) { __u64 interv; __u32 ret; NEXT_ARG(); if (strcmp(*argv, "auto") != 0) { if (get_u32(&interv, *argv, 0)) invarg("invalid KeepAlive time interval\n", *argv); keepalive_interv = interv; } NEXT_ARG(); if (strcmp(*argv, "auto") != 0) { if (get_unsigned(&ret, *argv, 0)) invarg("invalid KeepAlive retries\n", *argv); if (ret > 255) invarg("KeepAlive retries must be <= 255\n", *argv); keepalive_ret = ret; } } 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; } if (!metadata) { 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); addattr32(n, 1024, IFLA_GRE_FWMARK, fwmark); if (erspan_idx != 0) addattr32(n, 1024, IFLA_GRE_ERSPAN_INDEX, erspan_idx); if (keepalive_interv) { addattr32(n, 1024, IFLA_GRE_KEEPALIVE_INTERVAL, keepalive_interv); addattr8(n, 1024, IFLA_GRE_KEEPALIVE_RETRIES, keepalive_ret); } } else { addattr_l(n, 1024, IFLA_GRE_COLLECT_METADATA, NULL, 0); } 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 (ignore_df) addattr8(n, 1024, IFLA_GRE_IGNORE_DF, ignore_df & 1); return 0; } static void gre_print_direct_opt(FILE *f, struct rtattr *tb[]) { char s2[64]; const char *local = "any"; const char *remote = "any"; unsigned int iflags = 0; unsigned int oflags = 0; if (tb[IFLA_GRE_REMOTE]) { unsigned int addr = rta_getattr_u32(tb[IFLA_GRE_REMOTE]); if (addr) remote = format_host(AF_INET, 4, &addr); } print_string(PRINT_ANY, "remote", "remote %s ", remote); if (tb[IFLA_GRE_LOCAL]) { unsigned int addr = rta_getattr_u32(tb[IFLA_GRE_LOCAL]); if (addr) local = format_host(AF_INET, 4, &addr); } print_string(PRINT_ANY, "local", "local %s ", local); if (tb[IFLA_GRE_LINK] && rta_getattr_u32(tb[IFLA_GRE_LINK])) { unsigned int link = rta_getattr_u32(tb[IFLA_GRE_LINK]); const char *n = if_indextoname(link, s2); if (n) print_string(PRINT_ANY, "link", "dev %s ", n); else print_uint(PRINT_ANY, "link_index", "dev %u ", link); } if (tb[IFLA_GRE_TTL]) { __u8 ttl = rta_getattr_u8(tb[IFLA_GRE_TTL]); if (ttl) print_int(PRINT_ANY, "ttl", "ttl %d ", ttl); else print_int(PRINT_JSON, "ttl", NULL, ttl); } else { print_string(PRINT_FP, NULL, "ttl %s ", "inherit"); } if (tb[IFLA_GRE_TOS] && rta_getattr_u8(tb[IFLA_GRE_TOS])) { int tos = rta_getattr_u8(tb[IFLA_GRE_TOS]); if (is_json_context()) { SPRINT_BUF(b1); snprintf(b1, sizeof(b1), "0x%x", tos); print_string(PRINT_JSON, "tos", NULL, b1); } else { fputs("tos ", f); if (tos == 1) fputs("inherit ", f); else fprintf(f, "0x%x ", tos); } } if (tb[IFLA_GRE_KEEPALIVE_INTERVAL]) { unsigned long interval; unsigned int retries; interval = rta_getattr_u64(tb[IFLA_GRE_KEEPALIVE_INTERVAL]); retries = rta_getattr_u8(tb[IFLA_GRE_KEEPALIVE_RETRIES]); if (interval) { print_int(PRINT_ANY, "keepalive", "keepalive interval %d ", interval); print_int(PRINT_ANY, "keepalive", "retries %d ", retries); } else { print_int(PRINT_JSON, "keepalive", NULL, interval); } } else { print_string(PRINT_FP, NULL, "keepalive %s ", "auto"); } if (tb[IFLA_GRE_PMTUDISC]) { if (!rta_getattr_u8(tb[IFLA_GRE_PMTUDISC])) print_bool(PRINT_ANY, "pmtudisc", "nopmtudisc ", false); else print_bool(PRINT_JSON, "pmtudisc", NULL, true); } if (tb[IFLA_GRE_IFLAGS]) iflags = rta_getattr_u16(tb[IFLA_GRE_IFLAGS]); if (tb[IFLA_GRE_OFLAGS]) oflags = rta_getattr_u16(tb[IFLA_GRE_OFLAGS]); if ((iflags & GRE_KEY) && tb[IFLA_GRE_IKEY]) { inet_ntop(AF_INET, RTA_DATA(tb[IFLA_GRE_IKEY]), s2, sizeof(s2)); print_string(PRINT_ANY, "ikey", "ikey %s ", s2); } if ((oflags & GRE_KEY) && tb[IFLA_GRE_OKEY]) { inet_ntop(AF_INET, RTA_DATA(tb[IFLA_GRE_OKEY]), s2, sizeof(s2)); print_string(PRINT_ANY, "okey", "okey %s ", s2); } if (iflags & GRE_SEQ) print_bool(PRINT_ANY, "iseq", "iseq ", true); if (oflags & GRE_SEQ) print_bool(PRINT_ANY, "oseq", "oseq ", true); if (iflags & GRE_CSUM) print_bool(PRINT_ANY, "icsum", "icsum ", true); if (oflags & GRE_CSUM) print_bool(PRINT_ANY, "ocsum", "ocsum ", true); if (tb[IFLA_GRE_FWMARK]) { __u32 fwmark = rta_getattr_u32(tb[IFLA_GRE_FWMARK]); if (fwmark) { snprintf(s2, sizeof(s2), "0x%x", fwmark); print_string(PRINT_ANY, "fwmark", "fwmark %s ", s2); } } }
static int filter_addresses(struct nlmsghdr *nh, void *data) { int rc; int maxroutes = 0; struct kernel_route *routes = NULL; struct in6_addr addr; int *found = NULL; int len; struct ifaddrmsg *ifa; char ifname[IFNAMSIZ]; int ifindex = 0; int ll = 0; if (data) { void **args = (void **)data; maxroutes = *(int *)args[0]; routes = (struct kernel_route*)args[1]; found = (int *)args[2]; ifindex = args[3] ? *(int*)args[3] : 0; ll = args[4] ? !!*(int*)args[4] : 0; } len = nh->nlmsg_len; if (data && *found >= maxroutes) return 0; if (nh->nlmsg_type != RTM_NEWADDR && (data || nh->nlmsg_type != RTM_DELADDR)) return 0; ifa = (struct ifaddrmsg *)NLMSG_DATA(nh); len -= NLMSG_LENGTH(0); rc = parse_addr_rta(ifa, len, &addr); if (rc < 0) return 0; if (ll == !IN6_IS_ADDR_LINKLOCAL(&addr)) return 0; if (ifindex && ifa->ifa_index != ifindex) return 0; kdebugf("found address on interface %s(%d): %s\n", if_indextoname(ifa->ifa_index, ifname), ifa->ifa_index, format_address(addr.s6_addr)); if (data) { struct kernel_route *route = &routes[*found]; memcpy(route->prefix, addr.s6_addr, 16); route->plen = 128; route->metric = 0; route->ifindex = ifa->ifa_index; route->proto = RTPROT_BABEL_LOCAL; memset(route->gw, 0, 16); *found = (*found)+1; } return 1; }
/* Prepare the Urls for usage... */ LIBSPEC void GetUPNPUrls(struct UPNPUrls * urls, struct IGDdatas * data, const char * descURL, unsigned int scope_id) { char * p; int n1, n2, n3, n4; #ifdef IF_NAMESIZE char ifname[IF_NAMESIZE]; #else char scope_str[8]; #endif n1 = strlen(data->urlbase); if(n1==0) n1 = strlen(descURL); if(scope_id != 0) { #ifdef IF_NAMESIZE if(if_indextoname(scope_id, ifname)) { n1 += 3 + strlen(ifname); /* 3 == strlen(%25) */ } #else /* under windows, scope is numerical */ snprintf(scope_str, sizeof(scope_str), "%u", scope_id); #endif } n1 += 2; /* 1 byte more for Null terminator, 1 byte for '/' if needed */ n2 = n1; n3 = n1; n4 = n1; n1 += strlen(data->first.scpdurl); n2 += strlen(data->first.controlurl); n3 += strlen(data->CIF.controlurl); n4 += strlen(data->IPv6FC.controlurl); /* allocate memory to store URLs */ urls->ipcondescURL = (char *)malloc(n1); urls->controlURL = (char *)malloc(n2); urls->controlURL_CIF = (char *)malloc(n3); urls->controlURL_6FC = (char *)malloc(n4); /* strdup descURL */ urls->rootdescURL = strdup(descURL); /* get description of WANIPConnection */ if(data->urlbase[0] != '\0') strncpy(urls->ipcondescURL, data->urlbase, n1); else strncpy(urls->ipcondescURL, descURL, n1); p = strchr(urls->ipcondescURL+7, '/'); if(p) p[0] = '\0'; if(scope_id != 0) { if(0 == memcmp(urls->ipcondescURL, "http://[fe80:", 13)) { /* this is a linklocal IPv6 address */ p = strchr(urls->ipcondescURL, ']'); if(p) { /* insert %25<scope> into URL */ #ifdef IF_NAMESIZE memmove(p + 3 + strlen(ifname), p, strlen(p) + 1); memcpy(p, "%25", 3); memcpy(p + 3, ifname, strlen(ifname)); #else memmove(p + 3 + strlen(scope_str), p, strlen(p) + 1); memcpy(p, "%25", 3); memcpy(p + 3, scope_str, strlen(scope_str)); #endif } } } strncpy(urls->controlURL, urls->ipcondescURL, n2); strncpy(urls->controlURL_CIF, urls->ipcondescURL, n3); strncpy(urls->controlURL_6FC, urls->ipcondescURL, n4); url_cpy_or_cat(urls->ipcondescURL, data->first.scpdurl, n1); url_cpy_or_cat(urls->controlURL, data->first.controlurl, n2); url_cpy_or_cat(urls->controlURL_CIF, data->CIF.controlurl, n3); url_cpy_or_cat(urls->controlURL_6FC, data->IPv6FC.controlurl, n4); #ifdef DEBUG printf("urls->ipcondescURL='%s' %u n1=%d\n", urls->ipcondescURL, (unsigned)strlen(urls->ipcondescURL), n1); printf("urls->controlURL='%s' %u n2=%d\n", urls->controlURL, (unsigned)strlen(urls->controlURL), n2); printf("urls->controlURL_CIF='%s' %u n3=%d\n", urls->controlURL_CIF, (unsigned)strlen(urls->controlURL_CIF), n3); printf("urls->controlURL_6FC='%s' %u n4=%d\n", urls->controlURL_6FC, (unsigned)strlen(urls->controlURL_6FC), n4); #endif }
static boolean_t addRoute(route_entry_t *entry) { static int skfd = -1; #if !defined(freebsd8) struct rtentry rt; #else struct ortentry rt; #endif if (entry) { memset((char *) &rt, 0, sizeof (rt)); rt.rt_flags |= RTF_UP; if (entry->mask == 0xffffffff) { rt.rt_flags |= RTF_HOST; } #if !defined(freebsd8) rt.rt_metric = 0; ((struct sockaddr_in *) &rt.rt_genmask)->sin_addr.s_addr = entry->mask; ((struct sockaddr_in *) &rt.rt_genmask)->sin_family = AF_INET; if (entry->iface[0] != '\0') { rt.rt_dev = entry->iface; } #else #endif ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr = entry->dst; ((struct sockaddr_in *) &rt.rt_dst)->sin_family = AF_INET; ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = entry->gateway; ((struct sockaddr_in *) &rt.rt_gateway)->sin_family = AF_INET; rt.rt_flags |= RTF_GATEWAY; #if !defined(freebsd8) if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { #else if ((skfd = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) { #endif DEBUGP(DERROR, "addRoute", "socket: %s", strerror(errno)); return FALSE; } #if !defined(freebsd8) if (ioctl(skfd, SIOCADDRT, &rt) < 0) { DEBUGP(DERROR, "addRoute", "ioctl: %s", strerror(errno)); close(skfd); return FALSE; } #else struct { struct rt_msghdr rtm; struct sockaddr addrs[RTAX_MAX]; } r; memset(&r, 0, sizeof (r)); r.rtm.rtm_version = RTM_VERSION; r.rtm.rtm_type = RTM_ADD; r.rtm.rtm_pid = getpid(); r.rtm.rtm_seq = 0; struct sockaddr_in dst = {.sin_addr.s_addr = entry->dst, .sin_family = AF_INET, .sin_len = sizeof (struct sockaddr_in)}; struct sockaddr_in gw = {.sin_addr.s_addr = entry->gateway, .sin_family = AF_INET, .sin_len = sizeof (struct sockaddr_in)}; struct sockaddr_in mask = {.sin_addr.s_addr = entry->mask, .sin_family = AF_INET, .sin_len = sizeof (struct sockaddr_in)}; memcpy(&r.addrs[RTAX_DST], &dst, dst.sin_len); memcpy(&r.addrs[RTAX_GATEWAY], &gw, gw.sin_len); memcpy(&r.addrs[RTAX_NETMASK], &mask, mask.sin_len); r.rtm.rtm_addrs = RTA_DST | RTA_GATEWAY; r.rtm.rtm_flags = RTF_STATIC | RTF_GATEWAY; r.rtm.rtm_msglen = sizeof (r); if (entry->mask != 0xffffffff) { r.rtm.rtm_addrs |= RTA_NETMASK; } else { r.rtm.rtm_flags |= (RTF_HOST); } if (write(skfd, &r, r.rtm.rtm_msglen) != r.rtm.rtm_msglen) { DEBUGP(DERROR, "addRoute", "write: %s", strerror(errno)); close(skfd); return FALSE; } #endif close(skfd); return TRUE; } return FALSE; } static boolean_t delRoute(route_entry_t * entry) { static int skfd = -1; #if !defined(freebsd8) struct rtentry rt; #else struct ortentry rt; #endif if (entry) { memset((char *) &rt, 0, sizeof (rt)); rt.rt_flags |= RTF_UP; if (entry->mask == 0xffffffff) { rt.rt_flags |= RTF_HOST; } #if !defined(freebsd8) rt.rt_metric = 0; ((struct sockaddr_in *) &rt.rt_genmask)->sin_addr.s_addr = entry->mask; ((struct sockaddr_in *) &rt.rt_genmask)->sin_family = AF_INET; if (entry->iface[0] != '\0') { rt.rt_dev = entry->iface; } #else #endif ((struct sockaddr_in *) &rt.rt_dst)->sin_addr.s_addr = entry->dst; ((struct sockaddr_in *) &rt.rt_dst)->sin_family = AF_INET; ((struct sockaddr_in *) &rt.rt_gateway)->sin_addr.s_addr = entry->gateway; ((struct sockaddr_in *) &rt.rt_gateway)->sin_family = AF_INET; rt.rt_flags |= RTF_GATEWAY; #if !defined(freebsd8) if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { #else if ((skfd = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) { #endif DEBUGP(DERROR, "delRoute", "socket: %s", strerror(errno)); return FALSE; } #if !defined(freebsd8) if (ioctl(skfd, SIOCDELRT, &rt) < 0) { DEBUGP(DERROR, "delRoute", "ioctl: %s", strerror(errno)); close(skfd); return FALSE; } #else struct { struct rt_msghdr rtm; struct sockaddr addrs[RTAX_MAX]; } r; memset(&r, 0, sizeof (r)); r.rtm.rtm_version = RTM_VERSION; r.rtm.rtm_type = RTM_DELETE; r.rtm.rtm_pid = getpid(); r.rtm.rtm_seq = 0; struct sockaddr_in dst = {.sin_addr.s_addr = entry->dst, .sin_family = AF_INET, .sin_len = sizeof (struct sockaddr_in)}; struct sockaddr_in gw = {.sin_addr.s_addr = entry->gateway, .sin_family = AF_INET, .sin_len = sizeof (struct sockaddr_in)}; struct sockaddr_in mask = {.sin_addr.s_addr = entry->mask, .sin_family = AF_INET, .sin_len = sizeof (struct sockaddr_in)}; memcpy(&r.addrs[RTAX_DST], &dst, dst.sin_len); memcpy(&r.addrs[RTAX_GATEWAY], &gw, gw.sin_len); memcpy(&r.addrs[RTAX_NETMASK], &mask, mask.sin_len); r.rtm.rtm_addrs = RTA_DST | RTA_GATEWAY; r.rtm.rtm_flags = RTF_DONE; r.rtm.rtm_msglen = sizeof (r); if (entry->mask != 0xffffffff) { r.rtm.rtm_addrs |= RTA_NETMASK; } else { r.rtm.rtm_flags |= (RTF_HOST); } if (write(skfd, &r, r.rtm.rtm_msglen) != r.rtm.rtm_msglen) { DEBUGP(DERROR, "delRoute", "write: %s", strerror(errno)); close(skfd); return FALSE; } #endif close(skfd); return TRUE; } return FALSE; } static list_t *routeLookup(route_entry_t *key) { list_t *result = NULL; int skfd = -1; if (key) { #ifdef freebsd8 struct ortentry rt; memset((char *) &rt, 0, sizeof (rt)); rt.rt_flags |= RTF_UP; if (key->mask == 0xffffffff) { rt.rt_flags |= RTF_HOST; } rt.rt_flags |= RTF_GATEWAY; if ((skfd = socket(PF_ROUTE, SOCK_RAW, 0)) < 0) { DEBUGP(DERROR, "routeLookup", "socket: %s", strerror(errno)); return result; } struct { struct rt_msghdr rtm; struct sockaddr addrs[RTAX_MAX]; } r; memset(&r, 0, sizeof (r)); r.rtm.rtm_version = RTM_VERSION; r.rtm.rtm_type = RTM_GET; r.rtm.rtm_pid = getpid(); r.rtm.rtm_seq = 0; struct sockaddr_in dst = {.sin_addr.s_addr = key->dst, .sin_family = AF_INET, .sin_len = sizeof (struct sockaddr_in)}; struct sockaddr_in mask = {.sin_addr.s_addr = key->mask, .sin_family = AF_INET, .sin_len = sizeof (struct sockaddr_in)}; memcpy(&r.addrs[RTAX_DST], &dst, dst.sin_len); memcpy(&r.addrs[RTAX_NETMASK], &mask, mask.sin_len); r.rtm.rtm_addrs = RTA_DST; r.rtm.rtm_flags = RTF_DONE; r.rtm.rtm_msglen = sizeof (r); if (key->mask != 0xffffffff) { r.rtm.rtm_addrs |= RTA_NETMASK; } else { r.rtm.rtm_flags |= (RTF_HOST); } if (write(skfd, &r, r.rtm.rtm_msglen) != r.rtm.rtm_msglen) { DEBUGP(DERROR, "routeLookup", "write: %s", strerror(errno)); close(skfd); return result; } result = I(List)->new(); while (1) { if (read(skfd, (struct rt_msghdr *) &r, sizeof (r)) < 0) { DEBUGP(DERROR, "routeLookup", "read: %s", strerror(errno)); close(skfd); break; } route_entry_t *e = calloc(1, sizeof (route_entry_t)); e->gateway = ((struct sockaddr_in*) &r.addrs[RTAX_GATEWAY])->sin_addr.s_addr; I(List)->insert(result, I(ListItem)->new(e)); if (r.rtm.rtm_flags & RTF_DONE) { break; } } #endif #ifdef linux struct { struct nlmsghdr n; struct rtmsg r; char buf[1024]; } req; struct nhop { in_addr_t gw; char dev[IFNAMSIZ]; }; list_t *nhops = NULL; struct nlmsghdr *h; struct rtmsg *rtmp; struct rtattr *rtatp; int rtattrlen; int rval = -1; char buf[4096]; char dev[IFNAMSIZ]; in_addr_t src = 0; in_addr_t dst = 0; in_addr_t mask = 0; in_addr_t gw = 0; if ((skfd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0) { DEBUGP(DERROR, "routeLookup", "socket: %s", strerror(errno)); return FALSE; } memset(&req, 0, sizeof (req)); req.n.nlmsg_len = NLMSG_LENGTH(sizeof (struct rtmsg)); req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP; req.n.nlmsg_type = RTM_GETROUTE; req.n.nlmsg_len = NLMSG_ALIGN(req.n.nlmsg_len); if (send(skfd, &req, req.n.nlmsg_len, 0) < 0) { DEBUGP(DERROR, "routeLookup", "send: %s", strerror(errno)); close(skfd); return result; } if ((rval = recv(skfd, buf, sizeof (buf), 0)) < 0) { DEBUGP(DERROR, "routeLookup", "recv: %s", strerror(errno)); close(skfd); return result; } for (h = (struct nlmsghdr *) buf; NLMSG_OK(h, rval); h = NLMSG_NEXT(h, rval)) { rtmp = (struct rtmsg *) NLMSG_DATA(h); rtatp = (struct rtattr *) RTM_RTA(rtmp); rtattrlen = RTM_PAYLOAD(h); src = 0; dst = 0; mask = 0; gw = 0; if (result == NULL) { result = I(List)->new(); } for (; RTA_OK(rtatp, rtattrlen); rtatp = RTA_NEXT(rtatp, rtattrlen)) { switch (rtatp->rta_type) { case RTA_OIF: { int oif_index = *(int *) RTA_DATA(rtatp); if_indextoname(oif_index, dev); break; } case RTA_PREFSRC: src = *((in_addr_t *) RTA_DATA(rtatp)); break; case RTA_DST: dst = *((in_addr_t *) RTA_DATA(rtatp)); mask = rtmp->rtm_dst_len != 0 ? htonl(~0 << (32 - rtmp->rtm_dst_len)) : 0; break; case RTA_GATEWAY: gw = *((in_addr_t *) RTA_DATA(rtatp)); break; case RTA_MULTIPATH: { nhops = I(List)->new(); struct rtnexthop *nh = NULL; struct rtattr *nhrtattr = NULL; int nh_len = RTA_PAYLOAD(rtatp); for (nh = RTA_DATA(rtatp); RTNH_OK(nh, nh_len); nh = RTNH_NEXT(nh)) { struct nhop *hop = calloc(1, sizeof (struct nhop)); int attr_len = nh->rtnh_len - sizeof (*nh); if (nh_len < sizeof (*nh)) break; if (nh->rtnh_len > nh_len) break; if (nh->rtnh_len > sizeof (*nh)) { if_indextoname(nh->rtnh_ifindex, hop->dev); for (nhrtattr = RTNH_DATA(nh); RTA_OK(nhrtattr, attr_len); nhrtattr = RTA_NEXT(nhrtattr, attr_len)) { switch (nhrtattr->rta_type) { case RTA_GATEWAY: hop->gw = *((in_addr_t *) RTA_DATA(nhrtattr)); break; } } I(List)->insert(nhops, I(ListItem)->new(hop)); } nh_len -= NLMSG_ALIGN(nh->rtnh_len); } break; } } } if (nhops == NULL) { if (key && ((key->dst != dst) || (key->iface[0] != '\0' && strcmp(key->iface, dev) != 0))) { continue; } route_entry_t *r = calloc(1, sizeof (route_entry_t)); r->gateway = gw; r->mask = mask; r->dst = dst; r->src = src; strcpy(r->iface, dev); I(List)->insert(result, I(ListItem)->new(r)); } else { struct nhop *h = NULL; list_item_t *item = NULL; while (item = I(List)->pop(nhops)) { h = item->data; if (key && ((key->dst != dst) || (key->iface[0] != '\0' && strcmp(key->iface, h->dev) != 0))) { I(ListItem)->destroy(&item); free(h); continue; } route_entry_t *r = calloc(1, sizeof (route_entry_t)); r->gateway = h->gw; r->mask = mask; r->dst = dst; r->src = src; strcpy(r->iface, h->dev); I(List)->insert(result, I(ListItem)->new(r)); I(ListItem)->destroy(&item); free(h); } I(List)->destroy(&nhops); } } #endif close(skfd); return result; } return result; } static list_t * cacheLookup(route_entry_t * dest) { list_t *result = NULL; #if defined(linux) FILE *f = fopen("/proc/net/rt_cache", "r"); if (f) { char buf[512]; result = I(List)->new(); fgets(buf, sizeof (buf), f); // skip header while (!feof(f)) { if (fgets(buf, sizeof (buf), f)) { list_t *fields = I(String)->tokenize(buf, "\t"); int i = 0; list_item_t *item; route_entry_t *entry = calloc(1, sizeof (route_entry_t)); while ((item = I(List)->pop(fields))) { switch (i) { case 0: strcpy(entry->iface, (char*) item->data); break; case 1: sscanf((char*) item->data, "%X", &entry->dst); break; case 2: sscanf((char*) item->data, "%X", &entry->gateway); break; case 7: sscanf((char*) item->data, "%X", &entry->src); break; } free(item->data); I(ListItem)->destroy(&item); i++; } I(List)->destroy(&fields); if (dest) { if (dest->dst && dest->dst != entry->dst) { free(entry); continue; } } I(List)->insert(result, I(ListItem)->new(entry)); } } fclose(f); } #endif return result; } static boolean_t addHostRoute(in_addr_t dst, in_addr_t gw, char *iface) { route_entry_t route = {.dst = dst, .src = 0, .gateway = gw, .mask = 0xffffffff}; boolean_t result = FALSE; if (iface) strcpy(route.iface, iface); else route.iface[0] = '\0'; result = addRoute(&route); return result; } static boolean_t delHostRoute(in_addr_t dst, in_addr_t gw, char *iface) { route_entry_t route = {.dst = dst, .src = 0, .gateway = gw, .mask = 0xffffffff}; boolean_t result = FALSE; if (iface) strcpy(route.iface, iface); else route.iface[0] = '\0'; result = delRoute(&route); return result; } static in_addr_t getIfIP(char *iface) { in_addr_t result = 0; if (iface) { struct ifreq req; int sock = socket(AF_INET, SOCK_DGRAM, 0); memset(&req, 0, sizeof (struct ifreq)); strcpy(req.ifr_name, iface); if (ioctl(sock, SIOCGIFADDR, &req) >= 0) { result = ((struct sockaddr_in *) &req.ifr_addr)->sin_addr.s_addr; } else { DEBUGP(DERROR, "getIfIP", "ioctl: %s", strerror(errno)); } close(sock); } return result; } static in_addr_t getIfGW(char *iface) { route_entry_t route = {.dst = 0, .src = 0, .gateway = 0, .mask = 0}; list_t *routes = NULL; in_addr_t result = 0; if (iface) strcpy(route.iface, iface); else route.iface[0] = '\0'; routes = routeLookup(&route); if (routes) { if (I(List)->count(routes) > 0) { list_item_t *e = I(List)->pop(routes); route_entry_t *entry = (route_entry_t *) e->data; result = entry->gateway; free(entry); I(ListItem)->destroy(&e); } I(List)->clear(routes, TRUE); I(List)->destroy(&routes); } return result; } IMPLEMENT_INTERFACE(Route) = { .addRoute = addRoute, .delRoute = delRoute, .cacheLookup = cacheLookup, .addHostRoute = addHostRoute, .delHostRoute = delHostRoute, .getIfGW = getIfGW, .getIfIP = getIfIP };
void printsock(struct tcb *tcp, long addr, int addrlen) { union { char pad[128]; struct sockaddr sa; struct sockaddr_in sin; struct sockaddr_un sau; #ifdef HAVE_INET_NTOP struct sockaddr_in6 sa6; #endif #if defined(AF_IPX) struct sockaddr_ipx sipx; #endif #ifdef AF_PACKET struct sockaddr_ll ll; #endif #ifdef AF_NETLINK struct sockaddr_nl nl; #endif #ifdef HAVE_BLUETOOTH_BLUETOOTH_H struct sockaddr_hci hci; struct sockaddr_l2 l2; struct sockaddr_rc rc; struct sockaddr_sco sco; #endif } addrbuf; char string_addr[100]; if (addr == 0) { tprints("NULL"); return; } if (!verbose(tcp)) { tprintf("%#lx", addr); return; } if (addrlen < 2 || addrlen > (int) sizeof(addrbuf)) addrlen = sizeof(addrbuf); memset(&addrbuf, 0, sizeof(addrbuf)); if (umoven(tcp, addr, addrlen, addrbuf.pad) < 0) { tprints("{...}"); return; } addrbuf.pad[sizeof(addrbuf.pad) - 1] = '\0'; tprints("{sa_family="); printxval(addrfams, addrbuf.sa.sa_family, "AF_???"); tprints(", "); switch (addrbuf.sa.sa_family) { case AF_UNIX: if (addrlen == 2) { tprints("NULL"); } else if (addrbuf.sau.sun_path[0]) { tprints("sun_path="); print_quoted_string(addrbuf.sau.sun_path, sizeof(addrbuf.sau.sun_path) + 1, QUOTE_0_TERMINATED); } else { tprints("sun_path=@"); print_quoted_string(addrbuf.sau.sun_path + 1, sizeof(addrbuf.sau.sun_path), QUOTE_0_TERMINATED); } break; case AF_INET: tprintf("sin_port=htons(%u), sin_addr=inet_addr(\"%s\")", ntohs(addrbuf.sin.sin_port), inet_ntoa(addrbuf.sin.sin_addr)); break; #ifdef HAVE_INET_NTOP case AF_INET6: inet_ntop(AF_INET6, &addrbuf.sa6.sin6_addr, string_addr, sizeof(string_addr)); tprintf("sin6_port=htons(%u), inet_pton(AF_INET6, \"%s\", &sin6_addr), sin6_flowinfo=%u", ntohs(addrbuf.sa6.sin6_port), string_addr, addrbuf.sa6.sin6_flowinfo); #ifdef HAVE_STRUCT_SOCKADDR_IN6_SIN6_SCOPE_ID { #if defined(HAVE_IF_INDEXTONAME) && defined(IN6_IS_ADDR_LINKLOCAL) && defined(IN6_IS_ADDR_MC_LINKLOCAL) int numericscope = 0; if (IN6_IS_ADDR_LINKLOCAL(&addrbuf.sa6.sin6_addr) || IN6_IS_ADDR_MC_LINKLOCAL(&addrbuf.sa6.sin6_addr)) { char scopebuf[IFNAMSIZ + 1]; if (if_indextoname(addrbuf.sa6.sin6_scope_id, scopebuf) == NULL) numericscope++; else { tprints(", sin6_scope_id=if_nametoindex("); print_quoted_string(scopebuf, sizeof(scopebuf), QUOTE_0_TERMINATED); tprints(")"); } } else numericscope++; if (numericscope) #endif tprintf(", sin6_scope_id=%u", addrbuf.sa6.sin6_scope_id); } #endif break; #endif #if defined(AF_IPX) case AF_IPX: { int i; tprintf("sipx_port=htons(%u), ", ntohs(addrbuf.sipx.sipx_port)); /* Yes, I know, this does not look too * strace-ish, but otherwise the IPX * addresses just look monstrous... * Anyways, feel free if you don't like * this way.. :) */ tprintf("%08lx:", (unsigned long)ntohl(addrbuf.sipx.sipx_network)); for (i = 0; i < IPX_NODE_LEN; i++) tprintf("%02x", addrbuf.sipx.sipx_node[i]); tprintf("/[%02x]", addrbuf.sipx.sipx_type); } break; #endif /* AF_IPX */ #ifdef AF_PACKET case AF_PACKET: { int i; tprintf("proto=%#04x, if%d, pkttype=", ntohs(addrbuf.ll.sll_protocol), addrbuf.ll.sll_ifindex); printxval(af_packet_types, addrbuf.ll.sll_pkttype, "PACKET_???"); tprintf(", addr(%d)={%d, ", addrbuf.ll.sll_halen, addrbuf.ll.sll_hatype); for (i = 0; i < addrbuf.ll.sll_halen; i++) tprintf("%02x", addrbuf.ll.sll_addr[i]); } break; #endif /* AF_PACKET */ #ifdef AF_NETLINK case AF_NETLINK: tprintf("pid=%d, groups=%08x", addrbuf.nl.nl_pid, addrbuf.nl.nl_groups); break; #endif /* AF_NETLINK */ #if defined(AF_BLUETOOTH) && defined(HAVE_BLUETOOTH_BLUETOOTH_H) case AF_BLUETOOTH: tprintf("{sco_bdaddr=%02X:%02X:%02X:%02X:%02X:%02X} or " "{rc_bdaddr=%02X:%02X:%02X:%02X:%02X:%02X, rc_channel=%d} or " "{l2_psm=htobs(%d), l2_bdaddr=%02X:%02X:%02X:%02X:%02X:%02X, l2_cid=htobs(%d)} or " "{hci_dev=htobs(%d)}", addrbuf.sco.sco_bdaddr.b[0], addrbuf.sco.sco_bdaddr.b[1], addrbuf.sco.sco_bdaddr.b[2], addrbuf.sco.sco_bdaddr.b[3], addrbuf.sco.sco_bdaddr.b[4], addrbuf.sco.sco_bdaddr.b[5], addrbuf.rc.rc_bdaddr.b[0], addrbuf.rc.rc_bdaddr.b[1], addrbuf.rc.rc_bdaddr.b[2], addrbuf.rc.rc_bdaddr.b[3], addrbuf.rc.rc_bdaddr.b[4], addrbuf.rc.rc_bdaddr.b[5], addrbuf.rc.rc_channel, btohs(addrbuf.l2.l2_psm), addrbuf.l2.l2_bdaddr.b[0], addrbuf.l2.l2_bdaddr.b[1], addrbuf.l2.l2_bdaddr.b[2], addrbuf.l2.l2_bdaddr.b[3], addrbuf.l2.l2_bdaddr.b[4], addrbuf.l2.l2_bdaddr.b[5], btohs(addrbuf.l2.l2_cid), btohs(addrbuf.hci.hci_dev)); break; #endif /* AF_BLUETOOTH && HAVE_BLUETOOTH_BLUETOOTH_H */ /* AF_AX25 AF_APPLETALK AF_NETROM AF_BRIDGE AF_AAL5 AF_X25 AF_ROSE etc. still need to be done */ default: tprints("sa_data="); print_quoted_string(addrbuf.sa.sa_data, sizeof(addrbuf.sa.sa_data), 0); break; } tprints("}"); }
static int link_route(struct nlmsghdr *nlm) { int len, idx, metric; struct rtattr *rta; struct rtmsg *rtm; struct rt rt; char ifn[IF_NAMESIZE + 1]; if (nlm->nlmsg_type != RTM_DELROUTE) return 0; len = nlm->nlmsg_len - sizeof(*nlm); if ((size_t)len < sizeof(*rtm)) { errno = EBADMSG; return -1; } rtm = NLMSG_DATA(nlm); if (rtm->rtm_type != RTN_UNICAST || rtm->rtm_table != RT_TABLE_MAIN || rtm->rtm_family != AF_INET || nlm->nlmsg_pid == (uint32_t)getpid()) return 1; rta = (struct rtattr *)(void *)((char *)rtm +NLMSG_ALIGN(sizeof(*rtm))); len = NLMSG_PAYLOAD(nlm, sizeof(*rtm)); memset(&rt, 0, sizeof(rt)); rt.dest.s_addr = INADDR_ANY; rt.net.s_addr = INADDR_ANY; rt.gate.s_addr = INADDR_ANY; metric = 0; while (RTA_OK(rta, len)) { switch (rta->rta_type) { case RTA_DST: memcpy(&rt.dest.s_addr, RTA_DATA(rta), sizeof(rt.dest.s_addr)); break; case RTA_GATEWAY: memcpy(&rt.gate.s_addr, RTA_DATA(rta), sizeof(rt.gate.s_addr)); break; case RTA_OIF: idx = *(int *)RTA_DATA(rta); if (if_indextoname(idx, ifn)) rt.iface = find_interface(ifn); break; case RTA_PRIORITY: metric = *(int *)RTA_DATA(rta); break; } rta = RTA_NEXT(rta, len); } if (rt.iface != NULL) { if (metric == rt.iface->metric) { #ifdef INET inet_cidrtoaddr(rtm->rtm_dst_len, &rt.net); ipv4_routedeleted(&rt); #endif } } return 1; }
void runSuccess() { char buf[IF_NAMESIZE]; if_indextoname(anyuint(), buf); }
static void browse_record_callback_v6(AvahiRecordBrowser *b, AvahiIfIndex intf, AvahiProtocol proto, AvahiBrowserEvent event, const char *hostname, uint16_t clazz, uint16_t type, const void *rdata, size_t size, AvahiLookupResultFlags flags, void *userdata) { char address[INET6_ADDRSTRLEN + IF_NAMESIZE + 1]; char ifname[IF_NAMESIZE]; struct in6_addr addr; struct mdns_record_browser *rb_data; int ll; int len; int ret; rb_data = (struct mdns_record_browser *)userdata; switch (event) { case AVAHI_BROWSER_NEW: if (size != sizeof(addr.s6_addr)) { DPRINTF(E_WARN, L_MDNS, "Got RR type AAAA size %ld (should be %ld)\n", (long)size, (long)sizeof(addr.s6_addr)); return; } memcpy(&addr.s6_addr, rdata, sizeof(addr.s6_addr)); ll = is_v6ll(&addr); if (ll && !(rb_data->mb->flags & MDNS_WANT_V6LL)) { DPRINTF(E_DBG, L_MDNS, "Discarding IPv6 LL, not interested (service %s)\n", rb_data->name); return; } else if (!ll && !(rb_data->mb->flags & MDNS_WANT_V6)) { DPRINTF(E_DBG, L_MDNS, "Discarding IPv6, not interested (service %s)\n", rb_data->name); return; } if (!inet_ntop(AF_INET6, &addr.s6_addr, address, sizeof(address))) { DPRINTF(E_LOG, L_MDNS, "Could not print IPv6 address: %s\n", strerror(errno)); return; } if (ll) { if (!if_indextoname(intf, ifname)) { DPRINTF(E_LOG, L_MDNS, "Could not map interface index %d to a name\n", intf); return; } len = strlen(address); ret = snprintf(address + len, sizeof(address) - len, "%%%s", ifname); if ((ret < 0) || (ret > sizeof(address) - len)) { DPRINTF(E_LOG, L_MDNS, "Buffer too short for scoped IPv6 LL\n"); return; } } DPRINTF(E_DBG, L_MDNS, "Service %s, hostname %s resolved to %s\n", rb_data->name, hostname, address); /* Execute callback (mb->cb) with all the data */ rb_data->mb->cb(rb_data->name, rb_data->mb->type, rb_data->domain, hostname, AF_INET6, address, rb_data->port, &rb_data->txt_kv); /* Got a suitable address, stop record browser */ break; case AVAHI_BROWSER_REMOVE: /* Not handled - record browser lifetime too short for this to happen */ return; case AVAHI_BROWSER_CACHE_EXHAUSTED: case AVAHI_BROWSER_ALL_FOR_NOW: DPRINTF(E_DBG, L_MDNS, "Avahi Record Browser (%s v6): no more results (%s)\n", hostname, (event == AVAHI_BROWSER_CACHE_EXHAUSTED) ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW"); break; case AVAHI_BROWSER_FAILURE: DPRINTF(E_LOG, L_MDNS, "Avahi Record Browser (%s v6) failure: %s\n", hostname, avahi_strerror(avahi_client_errno(avahi_record_browser_get_client(b)))); break; } /* Cleanup when done/error */ keyval_clear(&rb_data->txt_kv); free(rb_data->name); free(rb_data->domain); free(rb_data); avahi_record_browser_free(b); }