LINUX.ORG.RU

Получение списка интерфейсов через netlink

 ,


0

1

Всем привет, есть такой код:

Создаю сокет (groups == 0):

int open_netlink_socket(unsigned groups)
{
    int sock;
    struct sockaddr_nl nla;

    /* open netlink socket */
    sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
    if(sock < 0) {
        rec_log("socket(): %s", strerror(errno));
        exit(1);
    }

    /* initialization */
    memset(&nla, 0, sizeof(nla));

    /* set & bind local address */
    nla.nl_family = AF_NETLINK;
    nla.nl_pid = getpid();
    nla.nl_groups = groups;
    bind(sock, (struct sockaddr *)&nla, sizeof(nla));

    return(sock);
}

Посылаю реквест:

int send_request(int sock, int type, int family)
{
    struct msghdr msg;
    struct iovec iov;
    struct sockaddr_nl nla;
    struct {
        struct nlmsghdr nlm;
        struct rtgenmsg rtgm;
    } req;
    int err;

    /* initialization */
    memset(&msg, 0, sizeof(msg));
    memset(&iov, 0, sizeof(iov));
    memset(&nla, 0, sizeof(nla));
    memset(&req, 0, sizeof(req));

    /* set remote address */
    nla.nl_family = AF_NETLINK;

    /* set netlink message header */
    req.nlm.nlmsg_len = NLMSG_LENGTH(sizeof(req.rtgm));
    req.nlm.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
    req.nlm.nlmsg_type = type;
    /* set routing message header */
    req.rtgm.rtgen_family = family;

    /* set message header */
    iov.iov_base = (void *)&req;
    iov.iov_len = sizeof(req);

    msg.msg_name = (void *)&nla;
    msg.msg_namelen = sizeof(nla);
    msg.msg_iov = (void *)&iov;
    msg.msg_iovlen = 1;

    /* send request message */
    err = sendmsg(sock, &msg, 0);
    if(err < 0) {
        rec_log("[%-12s] %s: sendmsg(): %s", "ERROR", __func__, strerror(errno));
        return(1);
    }

    return(0);

Считываю ответ:

int recv_reply(int sock, int type)
{
    struct msghdr msg;
    struct iovec iov;
    struct sockaddr_nl nla;
    char buf[16384];
    int err, len;

    /* initialization */
    memset(&msg, 0, sizeof(msg));
    memset(&iov, 0, sizeof(iov));
    memset(&nla, 0, sizeof(nla));
    memset(buf, 0, sizeof(buf));

    /* set message header */
    msg.msg_name = (void *)&nla;
    msg.msg_namelen = sizeof(nla);
    msg.msg_iov = (void *)&iov;
    msg.msg_iovlen = 1;

    iov.iov_base = buf;
    iov.iov_len = sizeof(buf);

    /* receive loop */
    while(1) {
        memset(buf, 0, sizeof(buf));
        len = recvmsg(sock, &msg, 0);
        if(len < 0) {
            if(errno == EINTR || errno == EAGAIN)
                continue;
            rec_log("[%-12s] %s: recvmsg(): %s", "ERROR", __func__, strerror(errno));
            return(1);
        } else if(len == 0) {
            rec_log("[%-12s] %s: recvmsg(): receive EOF", "ERROR", __func__);
            return(1);
        }

        if(type == RTM_GETLINK) {
            /* create interface list */
            err = create_iflist(&msg);
            if(err > 0)
                break;
            else if(err < 0)
                return(1);
        } else if(type == RTM_GETNEIGH) {
            /* create neighbor discovery list */
            err = create_ndlist(&msg);
            if(err)
                break;
            else if(err < 0)
                return(1);
        }
    }

    return(0);
}

В итоге при получении ответа выходит список из трёх интерфейсов: lo, eth0, eth1. Если включить vpn, то tun0 тоже туда попадает. Но если я создаю второй loopback, то он туда не попадает, однако в ifconfig он виден:

lo:1      Link encap:Local Loopback  
          inet addr:127.0.0.2  Mask:255.255.255.255
          UP LOOPBACK RUNNING  MTU:16436  Metric:1

Что мне надо сделать, чтобы получать интерфейсы такие, как в моём примере с lo:1, через netlink socket?

PS: есличо код не мой, а из nield, который я пытаюсь использовать в качестве либы.

☆☆☆☆☆

Последнее исправление: DELIRIUM (всего исправлений: 2)

это, а нормально через ioctl SIOCGIFCONF уже не сделоц?

anonymous
()

Но если я создаю второй loopback, то он туда не попадает, однако в ifconfig он виден:

Интерфейс тот же - lo. Ты просто добавил ему второй IP-адрес с меткой «lo:1». ifconfig показывает его как альяс, так как он не умеет несколько IP на одном интерфейсе.

Deleted
()

Как уже сказали, lo:1 это алиас, интерфейс lo. Алиас существует в виде флага у адреса на интерфейсе. То есть получаете список интерфейсов, потом через RTM_GETADDR список адресов по каждому интерфейсу, и те адреса, у которых флаг IFA_F_SECONDAR, будут представлены алиасами в выводе ifconfig.

Посмотрите код ipaddress.c команды ip из пакета iproute2 в районе этого флага.

mky ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.