Find the answer to your Linux question:
Results 1 to 2 of 2
I wrote a function to use netlink sockets to create secondary IP addresses on existing interfaces. The data appears correct and the sendmsg routine reports the correct amount of sent ...
  1. #1
    Just Joined!
    Join Date
    Jan 2009
    Posts
    1

    netlink socket add secondary interface question

    I wrote a function to use netlink sockets to create secondary IP addresses on existing interfaces. The data appears correct and the sendmsg routine reports the correct amount of sent data but no secondary IP addresses is added. The function I wrote is:

    #include <asm/types.h>

    #include <sys/socket.h>
    #include <unistd.h>
    #include <err.h>
    #include <stdio.h>
    #include <string.h>
    #include <netinet/in.h>

    #include <linux/netlink.h>
    #include <linux/rtnetlink.h>

    #define MYPROTO NETLINK_ROUTE

    typedef struct req {
    struct nlmsghdr nlh;
    struct ifaddrmsg ifmsg;
    char buffer[8192];
    } req;


    int send_netlink_msg()
    {
    int sock = socket(AF_NETLINK,SOCK_RAW,MYPROTO);
    struct sockaddr_nl addr;
    struct msghdr msg;
    struct iovec iov;
    char ifname[10]={0};
    char ip[8]={0};
    int size = 0,cnt=1;
    req rq;
    struct rtattr *rtap = (struct rtattr *)rq.buffer;
    ulong inaddr;

    if_indextoname(cnt,&ifname);

    while (strcmp(ifname,"eth0")) {
    cnt++;
    if_indextoname(cnt,&ifname);
    }

    printf("ETH0 index: %d\n",cnt);

    bzero(&rq,sizeof(rq));

    memset((void *)&addr, 0, sizeof(addr));

    if (sock<0)
    return sock;

    addr.nl_family = AF_NETLINK;
    addr.nl_pid = 0;
    addr.nl_groups = 0;

    if (bind(sock,(struct sockaddr *)&addr,sizeof(addr))<0)
    return -1;

    rq.ifmsg.ifa_family = AF_UNSPEC;
    rq.ifmsg.ifa_flags = IFA_F_SECONDARY;
    rq.ifmsg.ifa_scope = RT_SCOPE_HOST;
    rq.ifmsg.ifa_index = cnt;

    size = sizeof(struct ifaddrmsg);

    rtap = (struct rtattr *)rq.buffer;

    rtap->rta_len = sizeof(struct rtattr)+sizeof(ulong);
    rtap->rta_type = IFA_LOCAL;

    strcpy(ip,"1.2.3.10");

    if ((inet_pton(AF_INET,ip,((char *)rtap)+sizeof(struct rtattr)))<0) {
    printf("Error with inet_pton\n");
    return(-1);
    }

    {
    char *ptr=RTA_DATA(rtap);

    printf("%x\n",ptr[0]);
    printf("%x\n",ptr[1]);
    printf("%x\n",ptr[2]);
    printf("%x\n",ptr[3]);

    printf("payload size: %d\n",RTA_PAYLOAD(rtap));
    printf("ok: %d\n",RTA_OK(rtap,8 ));
    }

    size+=rtap->rta_len;

    rq.nlh.nlmsg_len = NLMSG_LENGTH(size);

    rq.nlh.nlmsg_type = RTM_NEWADDR;
    rq.nlh.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE;
    rq.nlh.nlmsg_seq = 0;
    rq.nlh.nlmsg_pid = getpid();

    bzero(&msg,sizeof(msg));

    msg.msg_name = (void *)&(addr);
    msg.msg_namelen = sizeof(addr);

    iov.iov_base = (void *)&rq;
    iov.iov_len = sizeof(struct nlmsghdr)+size;

    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;

    printf("Msg length: %d\n",rq.nlh.nlmsg_len);

    printf("Data sent : %d\n\n",sendmsg(sock,&msg,0));

    system("ifconfig eth0");

    return sock;
    }

    int main(int argc, char *argv[])
    {
    int nls = send_netlink_msg();

    return 0;
    }


    any help on this would be greatly appreciated.

    Scott

  2. #2
    Just Joined!
    Join Date
    Nov 2011
    Posts
    1
    #include <bits/sockaddr.h>
    #include <asm/types.h>
    #include <linux/rtnetlink.h>
    #include <sys/socket.h>
    #include <string.h>

    // buffer to hold the RTNETLINK request
    struct {
    struct nlmsghdr nl;
    struct ifaddrmsg rt;
    char buf[8192];
    } req;

    // variables used for
    // socket communications
    int fd;
    struct sockaddr_nl la;
    struct sockaddr_nl pa;
    struct msghdr msg;
    struct iovec iov;
    int rtn;

    // buffer to hold the RTNETLINK reply(ies)
    char buf[8192];

    // RTNETLINK message pointers & lengths
    // used when processing messages
    struct nlmsghdr *nlp;
    int nll;
    struct rtmsg *rtp;
    int ifal;
    struct rtattr *rtap;


    int main(int argc, char *argv[])
    {

    // open socket
    fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);

    // setup local address & bind using
    // this address
    bzero(&la, sizeof(la));
    la.nl_family = AF_NETLINK;
    la.nl_pid = getpid();
    bind(fd, (struct sockaddr*) &la, sizeof(la));


    // sub functions to create RTNETLINK message,
    // send over socket, reveive reply & process
    // message

    /*TODO*/
    char dsts[24] = "192.168.1.3";

    // initalize RTNETLINK request buffer
    bzero(&req, sizeof(req));

    // compute the initial length of the
    // service request
    ifal = sizeof(struct ifaddrmsg);
    // add first attrib:
    // set IP addr
    // RTNETLINK buffer size
    rtap = (struct rtattr *) req.buf;
    rtap->rta_type = IFA_ADDRESS;
    rtap->rta_len = sizeof(struct rtattr) + 4;
    inet_pton(AF_INET, dsts,
    ((char *)rtap) + sizeof(struct rtattr));
    ifal += rtap->rta_len;


    // add second attrib:
    // set ifc index and increment the size
    rtap = (struct rtattr *) (((char *)rtap)
    + rtap->rta_len);
    rtap->rta_type = IFA_LOCAL;
    rtap->rta_len = sizeof(struct rtattr) + 4;
    inet_pton(AF_INET, dsts,
    ((char *)rtap) + sizeof(struct rtattr));
    ifal += rtap->rta_len;

    // setup the NETLINK header
    req.nl.nlmsg_len = NLMSG_LENGTH(ifal);
    /* TODO: test with NLM_F_APPEND */
    req.nl.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_APPEND;
    req.nl.nlmsg_type = RTM_NEWADDR;

    // setup the service header (struct rtmsg)
    req.rt.ifa_family = AF_INET;
    req.rt.ifa_prefixlen = 32; /*hardcoded*/
    req.rt.ifa_flags = IFA_F_PERMANENT;
    req.rt.ifa_scope = RT_SCOPE_HOST;
    /*TODO: think how can you find out the ifa_index */
    req.rt.ifa_index = 3;

    // create the remote address
    // to communicate
    bzero(&pa, sizeof(pa));
    pa.nl_family = AF_NETLINK;

    // initialize & create the struct msghdr supplied
    // to the sendmsg() function
    bzero(&msg, sizeof(msg));
    msg.msg_name = (void *) &pa;
    msg.msg_namelen = sizeof(pa);

    // place the pointer & size of the RTNETLINK
    // message in the struct msghdr
    iov.iov_base = (void *) &req.nl;
    iov.iov_len = req.nl.nlmsg_len;
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;

    // send the RTNETLINK message to kernel
    rtn = sendmsg(fd, &msg, 0);
    // close socket
    close(fd);
    }

    I am posting here so late, because it might help someone in the future. The above code worked for me. I did not have time to play with all the flags, but this is a start point for you.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
...