示例#1
0
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;
        }
示例#2
0
文件: network.c 项目: mcarrier/RECONN
//******************************************************************************
//******************************************************************************
// 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));
                            }
                        }
示例#3
0
void runFailure1() {
    char buf[1];
    if_indextoname(anyuint(), buf);
}
示例#4
0
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);
    }
}
示例#5
0
/*
 * 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;
}
示例#7
0
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;
}
示例#8
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;
}
示例#9
0
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();
    }
}
示例#10
0
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;
}
示例#11
0
文件: cute.c 项目: psvz/cute
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
}
示例#12
0
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)));
		}
	}
}
示例#13
0
文件: babeld.c 项目: ajres/babeld
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;
        }
    }
示例#14
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;
}
示例#15
0
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;
}
示例#16
0
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;
}
示例#18
0
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;
	}
}
示例#19
0
文件: rtquery.c 项目: andreiw/polaris
/*
 * 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');
	}
}
示例#20
0
/* 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;
}
示例#21
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);
  }
示例#22
0
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;
}
示例#23
0
文件: link_gre.c 项目: 6WIND/iproute2
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);
		}
	}
}
示例#24
0
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;
}
示例#25
0
/* 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
}
示例#26
0
文件: route.c 项目: hashyuan/corenova
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

};
示例#27
0
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("}");
}
示例#28
0
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;
}
示例#29
0
void runSuccess() {
    char buf[IF_NAMESIZE];
    if_indextoname(anyuint(), buf);
}
示例#30
0
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);
}