Ejemplo n.º 1
0
char *
if_indextoname(unsigned int ifindex, char *ifname)
{
	struct ifaddrs *ifaddrs, *ifa;
	int error = 0;

	if (getifaddrs(&ifaddrs) < 0)
		return(NULL);	/* getifaddrs properly set errno */

	for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
		if (ifa->ifa_addr &&
		    ifa->ifa_addr->sa_family == AF_LINK &&
		    ifindex == LLINDEX((struct sockaddr_dl*)ifa->ifa_addr))
			break;
	}

	if (ifa == NULL) {
		error = ENXIO;
		ifname = NULL;
	}
	else
		strncpy(ifname, ifa->ifa_name, IFNAMSIZ);

	freeifaddrs(ifaddrs);

	errno = error;
	return(ifname);
}
Ejemplo n.º 2
0
/*
 * Internal: Map an IPv4 unicast address to an interface index.
 * This is quite inefficient so it is recommended applications use
 * the newer, more portable, protocol independent API.
 */
static uint32_t
__inaddr_to_index(in_addr_t ifaddr)
{
	struct ifaddrs	*ifa;
	struct ifaddrs	*ifaddrs;
	char		*ifname;
	int		 ifindex;
	sockunion_t	*psu;

	if (getifaddrs(&ifaddrs) < 0)
		return (0);

	ifindex = 0;
	ifname = NULL;

	/*
	 * Pass #1: Find the ifaddr entry corresponding to the
	 * supplied IPv4 address. We should really use the ifindex
	 * consistently for matches, however it is not available to
	 * us on this pass.
	 */
	for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
		psu = (sockunion_t *)ifa->ifa_addr;
		if (psu && psu->ss.ss_family == AF_INET &&
		    psu->sin.sin_addr.s_addr == ifaddr) {
			ifname = ifa->ifa_name;
			break;
		}
	}
	if (ifname == NULL)
		goto out;

	/*
	 * Pass #2: Find the index of the interface matching the name
	 * we obtained from looking up the IPv4 ifaddr in pass #1.
	 * There must be a better way of doing this.
	 */
	for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
		psu = (sockunion_t *)ifa->ifa_addr;
		if (psu && psu->ss.ss_family == AF_LINK &&
		    strcmp(ifa->ifa_name, ifname) == 0) {
			ifindex = LLINDEX(&psu->sdl);
			break;
		}
	}
	assert(ifindex != 0);

out:
	freeifaddrs(ifaddrs);
	return (ifindex);
}
qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxSize, QIpPacketHeader *header,
                                                         QAbstractSocketEngine::PacketHeaderOptions options)
{
    // we use quintptr to force the alignment
    quintptr cbuf[(CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int))
#if !defined(IP_PKTINFO) && defined(IP_RECVIF) && defined(Q_OS_BSD4)
                   + CMSG_SPACE(sizeof(sockaddr_dl))
#endif
                   + sizeof(quintptr) - 1) / sizeof(quintptr)];

    struct msghdr msg;
    struct iovec vec;
    qt_sockaddr aa;
    char c;
    memset(&msg, 0, sizeof(msg));
    memset(&aa, 0, sizeof(aa));

    // we need to receive at least one byte, even if our user isn't interested in it
    vec.iov_base = maxSize ? data : &c;
    vec.iov_len = maxSize ? maxSize : 1;
    msg.msg_iov = &vec;
    msg.msg_iovlen = 1;
    if (options & QAbstractSocketEngine::WantDatagramSender) {
        msg.msg_name = &aa;
        msg.msg_namelen = sizeof(aa);
    }
    if (options & (QAbstractSocketEngine::WantDatagramHopLimit | QAbstractSocketEngine::WantDatagramDestination)) {
        msg.msg_control = cbuf;
        msg.msg_controllen = sizeof(cbuf);
    }

    ssize_t recvResult = 0;
    do {
        recvResult = ::recvmsg(socketDescriptor, &msg, 0);
    } while (recvResult == -1 && errno == EINTR);

    if (recvResult == -1) {
        setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString);
        if (header)
            header->clear();
    } else if (options != QAbstractSocketEngine::WantNone) {
        Q_ASSERT(header);
        qt_socket_getPortAndAddress(&aa, &header->senderPort, &header->senderAddress);
        header->destinationPort = localPort;

        // parse the ancillary data
        struct cmsghdr *cmsgptr;
        for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL;
             cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
            if (cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_PKTINFO
                    && cmsgptr->cmsg_len >= CMSG_LEN(sizeof(in6_pktinfo))) {
                in6_pktinfo *info = reinterpret_cast<in6_pktinfo *>(CMSG_DATA(cmsgptr));

                header->destinationAddress.setAddress(reinterpret_cast<quint8 *>(&info->ipi6_addr));
                header->ifindex = info->ipi6_ifindex;
                if (header->ifindex)
                    header->destinationAddress.setScopeId(QString::number(info->ipi6_ifindex));
            }

#ifdef IP_PKTINFO
            if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_PKTINFO
                    && cmsgptr->cmsg_len >= CMSG_LEN(sizeof(in_pktinfo))) {
                in_pktinfo *info = reinterpret_cast<in_pktinfo *>(CMSG_DATA(cmsgptr));

                header->destinationAddress.setAddress(ntohl(info->ipi_addr.s_addr));
                header->ifindex = info->ipi_ifindex;
            }
#else
#  ifdef IP_RECVDSTADDR
            if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_RECVDSTADDR
                    && cmsgptr->cmsg_len >= CMSG_LEN(sizeof(in_addr))) {
                in_addr *addr = reinterpret_cast<in_addr *>(CMSG_DATA(cmsgptr));

                header->destinationAddress.setAddress(ntohl(addr->s_addr));
            }
#  endif
#  if defined(IP_RECVIF) && defined(Q_OS_BSD4)
            if (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_RECVIF
                    && cmsgptr->cmsg_len >= CMSG_LEN(sizeof(sockaddr_dl))) {
                sockaddr_dl *sdl = reinterpret_cast<sockaddr_dl *>(CMSG_DATA(cmsgptr));

                header->ifindex = LLINDEX(sdl);
            }
#  endif
#endif

            if (cmsgptr->cmsg_len == CMSG_LEN(sizeof(int))
                    && ((cmsgptr->cmsg_level == IPPROTO_IPV6 && cmsgptr->cmsg_type == IPV6_HOPLIMIT)
                        || (cmsgptr->cmsg_level == IPPROTO_IP && cmsgptr->cmsg_type == IP_TTL))) {
                header->hopLimit = *reinterpret_cast<int *>(CMSG_DATA(cmsgptr));
            }
        }
    }

#if defined (QNATIVESOCKETENGINE_DEBUG)
    qDebug("QNativeSocketEnginePrivate::nativeReceiveDatagram(%p \"%s\", %lli, %s, %i) == %lli",
           data, qt_prettyDebug(data, qMin(recvResult, ssize_t(16)), recvResult).data(), maxSize,
           (recvResult != -1 && options != QAbstractSocketEngine::WantNone)
           ? header->senderAddress.toString().toLatin1().constData() : "(unknown)",
           (recvResult != -1 && options != QAbstractSocketEngine::WantNone)
           ? header->senderPort : 0, (qint64) recvResult);
#endif

    return qint64(maxSize ? recvResult : recvResult == -1 ? -1 : 0);
}
Ejemplo n.º 4
0
struct if_nameindex *
if_nameindex(void)
{
	struct ifaddrs *ifaddrs, *ifa;
	unsigned int ni;
	int nbytes;
	struct if_nameindex *ifni, *ifni2;
	char *cp;

	if (getifaddrs(&ifaddrs) < 0)
		return(NULL);

	/*
	 * First, find out how many interfaces there are, and how
	 * much space we need for the string names.
	 */
	ni = 0;
	nbytes = 0;
	for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
		if (ifa->ifa_addr &&
		    ifa->ifa_addr->sa_family == AF_LINK) {
			nbytes += strlen(ifa->ifa_name) + 1;
			ni++;
		}
	}

	/*
	 * Next, allocate a chunk of memory, use the first part
	 * for the array of structures, and the last part for
	 * the strings.
	 */
	cp = malloc((ni + 1) * sizeof(struct if_nameindex) + nbytes);
	ifni = (struct if_nameindex *)cp;
	if (ifni == NULL)
		goto out;
	cp += (ni + 1) * sizeof(struct if_nameindex);

	/*
	 * Now just loop through the list of interfaces again,
	 * filling in the if_nameindex array and making copies
	 * of all the strings.
	 */
	ifni2 = ifni;
	for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
		if (ifa->ifa_addr &&
		    ifa->ifa_addr->sa_family == AF_LINK) {
			ifni2->if_index =
			    LLINDEX((struct sockaddr_dl*)ifa->ifa_addr);
			ifni2->if_name = cp;
			strcpy(cp, ifa->ifa_name);
			ifni2++;
			cp += strlen(cp) + 1;
		}
	}
	/*
	 * Finally, don't forget to terminate the array.
	 */
	ifni2->if_index = 0;
	ifni2->if_name = NULL;
out:
	freeifaddrs(ifaddrs);
	return(ifni);
}