next up previous contents
Next: What happens in the Up: Illustration of the usage Previous: Utility function for adding   Contents

Adding a new route

Now as an example, we can see what parameters are required for adding a new route to the kernel routing table.

The initialisations include

    memset(&request, 0, sizeof(request));
    request.netlink_header.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
    request.netlink_header.nlmsg_flags = NLM_F_REQUEST|NLM_F_CREATE;
    request.netlink_header.nlmsg_type = RTM_NEWROUTE;
    request.rt_message.rtm_family = AF_INET;
    request.rt_message.rtm_table = RT_TABLE_MAIN;

    if (cmd != RTM_DELROUTE) 
        request.rt_message.rtm_protocol = RTPROT_BOOT;
        request.rt_message.rtm_scope = RT_SCOPE_UNIVERSE;
        request.rt_message.rtm_type = RTN_UNICAST;

Initially the netlink_header->nlmsg_len contains the length of the structures nlmsghdr and rtmsg before adding any parameter, so for the first parameter we can go to the beginning of the character buffer in the packet. The family is set as AF_INET so that we could index the inet_rtnetlink_table in the kernel by the command RTM_NEWROUTE to get to the function inet_rtm_newroute, this function in the kernel adds the new route to the kernel routing table. Also note the RT_TABLE_MAIN whose significance will be explained later.

For ipv4, The ipaddress of both the destination and the gateway needs to filled in as an unsigned integer array of 4 bytes, then the packaging into the netlink packet is done by calling the function addattr_l()

addattr_l(&request.netlink_header, sizeof(request), RTA_GATEWAY, &gw,4); 
addattr_l(&request.netlink_header, sizeof(request), RTA_DST, &dst,4); 
addattr32 (&request.netlink_header, sizeof(request), RTA_OIF, index);

The outgoing interface is denoted by index. Note that the parameters and the names to be filled such as RTA_GATEWAY, RTA_DST etc are defined in include/linux/rtnetlink.h, for each type of operation intended, different parameters have to be filled.

For adding a route, the gateway, destination address and the interface will suffice, now the netlink packet is all set to go to the kernel.

To send the packet to the kernel, look at the following code.

	int status;
    struct sockaddr_nl nladdr;
    struct iovec iov = { (void*)netlink_header, netlink_header->nlmsg_len };
    char   buf[8192];
    struct msghdr msg = {
        (void*)&nladdr, sizeof(nladdr),
        &iov,   1,
        NULL,   0,

    memset(&nladdr, 0, sizeof(nladdr));
    nladdr.nl_family = AF_NETLINK;
    nladdr.nl_pid = 0;
    nladdr.nl_groups = 0;

    n->nlmsg_seq = ++rtnl->seq;
    if (answer == NULL)
        n->nlmsg_flags |= NLM_F_ACK;

    status = sendmsg(rtnl->fd, &msg, 0);

The family is set as AF_NETLINK. The iovector is formed and the message formed and sendmsg is called. The success/failure is returned as the status.

next up previous contents
Next: What happens in the Up: Illustration of the usage Previous: Utility function for adding   Contents
Gowri Dhandapani