【问题标题】:Netlink sockets does not add routes to routing table for IPv6Netlink 套接字不会将路由添加到 IPv6 的路由表
【发布时间】:2014-04-30 01:04:06
【问题描述】:

我希望能够添加一个新的 IPv6 地址,但到目前为止还没有。程序运行成功,但路由表中没有任何反映。

#include <sys/socket.h>


 #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <linux/netlink.h>
    #include <linux/rtnetlink.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <net/if.h>
    #include <sys/types.h>


    #define BUFSIZE 4095

    struct route_info
    {
    char*       dst_addr;
    char*       src_addr;
    char*       gateway;
    char        ifName[IF_NAMESIZE];

    };


    void fillRoutes(struct route_info* rinfo, const char* dst_addr, const char* src_addr, const char* gateway, const char* ifname)
    {
    int pton_fd;

    pton_fd = inet_pton(AF_INET6, "2001::4", (struct in_addr *)&rinfo->dst_addr);
    if (pton_fd <= 0)
    {
        perror("pton errror at dst_addr");
        exit(EXIT_FAILURE);
    }

    pton_fd = inet_pton(AF_INET6, "2001::3", (struct in_addr *)&rinfo->gateway);
    if (pton_fd <= 0)
    {
        perror("gateway error");
        exit(EXIT_FAILURE);
    }

    }

    int addAttr(struct nlmsghdr *nl, int maxlen, int type, void *data, int attr_len )
    {
    struct rtattr *rta;
    int len = RTA_LENGTH(attr_len);
    if(NLMSG_ALIGN(nl->nlmsg_len) + len > maxlen)
    {
        perror("inside attr()");
        exit(EXIT_FAILURE);
    } 

    nl->nlmsg_len = NLMSG_ALIGN(nl->nlmsg_len) + len;
    rta = (struct rtattr *)((char *)nl + NLMSG_ALIGN(nl->nlmsg_len));
    rta->rta_type = type;
    rta->rta_len = len;
    memcpy(RTA_DATA(rta), data, attr_len);
    //nl->nlmsg_len = NLMSG_ALIGN(nl->nlmsg_len) + len;
    fprintf(stderr, "attr len=%d\n",nl->nlmsg_len);
    return 0;
   }
    int main (int argc, char **argv)
    {
    int             bytes_sent;
    int             msg_seq =1;
    int             rtnetlink_socket = -1;
    struct sockaddr_nl  addr;
    struct rtmsg        *raddr;
    struct nlmsghdr     *nl;
    struct iovec        iov;
    struct msghdr       msg;
    char            dst_addr[30];
    char            src_addr[30];
    char            gateway[30];
    char            ifname[30];
    char            msgbuf[BUFSIZE];
    struct route_info   rinfo;

    memset(&addr, 0, sizeof(addr));
        memset(msgbuf, 0, BUFSIZE);

    if ((rtnetlink_socket = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0)
    {
        perror("socket");
        exit(EXIT_FAILURE);
    }
    nl = (struct nlmsghdr *)msgbuf;
    raddr = (struct rtmsg*)NLMSG_DATA(nl);

    nl->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
    nl->nlmsg_type = RTM_NEWROUTE;
    nl->nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
    nl->nlmsg_seq = msg_seq++;
    nl->nlmsg_pid = getpid();

    //fill entries for routing table

    raddr->rtm_family = AF_INET6;
        raddr->rtm_dst_len = 128;
        raddr->rtm_src_len = 0;
        raddr->rtm_table = RT_TABLE_MAIN;
        raddr->rtm_protocol = RTPROT_STATIC;
        raddr->rtm_scope = RT_SCOPE_UNIVERSE;
        raddr->rtm_type = RTN_UNICAST;
    raddr->rtm_flags = RTM_F_NOTIFY;
    raddr->rtm_tos = 0;

    fillRoutes(&rinfo, dst_addr, src_addr, gateway, ifname);

    addAttr(nl, BUFSIZE, RTA_DST, &rinfo.dst_addr, 16);
    addAttr(nl, BUFSIZE, RTA_GATEWAY, &rinfo.gateway, 16);

    if((bytes_sent = send(rtnetlink_socket, nl, nl->nlmsg_len, 0)) < 0)
    {
        perror("failed to write to socket");
        exit(EXIT_FAILURE);
    }

    printf("No of bytes sent :%d\n", bytes_sent);

    return 0;
}

这给了我在 RTA_DST 时的属性值 48 和在 RTA_GATEWAY 时的属性值 68。我在哪里犯错了。我似乎没有找到错误。任何帮助表示赞赏!

【问题讨论】:

  • 你找到答案了吗?
  • 没有@purpletech。我通过使用 system() 并将 route 命令作为参数传递给 system() 完成了同样的壮举。你可以查看更多link
  • 我不想调用 system(..) 。我用过ioctl
  • 是的,这也是另一种方式。但由于我正在研究 POC,因此不需要进入 ioctl。
  • 我在这里看到了一个小问题,在你的代码中你设置了nl-&gt;nlmsg_pid = getpid(); 在我看来,这应该设置为接收者的PID,即内核的0

标签: c sockets network-programming ipv6 netlink


【解决方案1】:

您通过在 nlmsghdr 中设置错误的 PID 将 NEWROUTE 请求发送到您自己的进程。

nl->nlmsg_pid = getpid(); /* 这是你自己的进程 ID*/

您需要send it to kernel,PID 为 0,因此将其替换为

nl->nlmsg_pid = 0;

将其发送给内核,然后内核才能将其合并到路由表中。

另外一点,对于通过 netlink 套接字发送数据/控制信息,sendmsg() 是首选方式。我不确定send() 是如何在这里工作的,因为它打算在连接状态下工作。见man pages。据说send()只针对本地错误返回-1,不检测远程错误,这可能是以后的另一个问题。

【讨论】:

  • 好的,我知道 send 在这里是如何工作的,但 sendmsg 仍然是首选方式。
【解决方案2】:

我搬家了

nl-&gt;nlmsg_len = NLMSG_ALIGN(nl-&gt;nlmsg_len) + len;

之后

rta = (struct rtattr *) ((char *) nl + NLMSG_ALIGN(nl-&gt;nlmsg_len));

这有帮助(实际上它已经在原始代码中注释了)

【讨论】:

    猜你喜欢
    • 2017-10-02
    • 1970-01-01
    • 2016-06-08
    • 1970-01-01
    • 2016-08-16
    • 1970-01-01
    • 1970-01-01
    • 2018-12-06
    • 2014-07-25
    相关资源
    最近更新 更多