[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [bug-inetutils] route

From: Jeff Bailey
Subject: Re: [bug-inetutils] route
Date: Mon, 18 Aug 2008 22:04:47 -0700

Does the linux kernel guarantee those as v4 only addresses?  If its easy, it would be nice to see a couple TODOs listed for v6 support.

V6 shouldn't block a commit, though.

On Aug 18, 2008 10:01 PM, "Jeff Bailey" <address@hidden> wrote:

Is there a

On Aug 18, 2008 9:25 PM, "Debarshi Ray" <address@hidden> wrote:

Here is a proof-of-concept for implementing route for Inetutils.
Unlike some route implementations for GNU/Linux, this does not indulge
in parsing /proc/net/... or using SIOCxxxx ioctl commands. Instead I
have used the PF_NETLINK socket interface provided by the Linux
kernel. I also plan to make this work with the *BSD kernels, since
atleast FreeBSD and NetBSD seem to have a similar socket driven

Please note that all uses of malloc and realloc will be replaced by
xmalloc and xrealloc once the code moves into Inetutils.

#include <errno.h>
#include <error.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h> // malloc, realloc, free
#include <string.h>
#include <unistd.h>

#include <asm/types.h>
#include <net/if.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
struct _msghdr_t
 struct nlmsghdr nlmsghdr;
 struct rtmsg rtmsg;
typedef struct _msghdr_t msghdr_t;

struct _rtinfo_t
 char dest[16];
 char gateway[16];
 char iface[IFNAMSIZ];
 int metrics;
 int ref;
 int use;
typedef struct _rtinfo_t rtinfo_t;

uint32_t seqn = 0;

void print_header (void);
void print_route (const rtinfo_t *const rtinfo);
void rtinfo_init (rtinfo_t *const rtinfo);
void linux_route (void);
size_t linux_recvnl (int sockfd, void **buffer);
size_t linux_sendnl (int sockfd);
void linux_parsenl (void *buffer, size_t size);
size_t recvbuf (int sockfd, void **buffer, size_t *size);

main (int argc, char *argv[])
 print_header ();
 linux_route ();
 return 0;

print_header (void)
 puts ("Kernel IP routing table");
 printf ("%-15s %-15s %-6s %-6s %-6s %-15s\n",

print_route (const rtinfo_t *const rtinfo)
 printf ("%-15s %-15s %-6d %-6d %-6d %-15s\n",

void rtinfo_init (rtinfo_t *const rtinfo)
 strcpy (rtinfo->dest, "");
 strcpy (rtinfo->gateway, "");
 strcpy (rtinfo->iface, "");
 rtinfo->metrics = 0;
 rtinfo->ref = 0;
 rtinfo->use = 0;

linux_route (void)
 int sockfd;
 size_t nread;
 void *buffer = NULL;

 if (sockfd == -1)
   error (EXIT_FAILURE, errno, "socket");

 linux_sendnl (sockfd);
 nread = linux_recvnl (sockfd, &buffer);
 linux_parsenl (buffer, nread);

 close (sockfd);
 free (buffer);

linux_parsenl (void *buffer, size_t nread)
 unsigned int size;
 msghdr_t *msghdr;
 rtinfo_t rtinfo;
 struct rtattr *attr;

 for (msghdr = (msghdr_t *) buffer;
      NLMSG_OK (&msghdr->nlmsghdr, nread) != 0;
      msghdr = (msghdr_t *) NLMSG_NEXT (&msghdr->nlmsghdr, nread))
     if ((msghdr->rtmsg.rtm_family != AF_INET)
         || (msghdr->rtmsg.rtm_table != RT_TABLE_MAIN))

     rtinfo_init (&rtinfo);

     attr = (struct rtattr *) RTM_RTA (&msghdr->rtmsg);
     size = RTM_PAYLOAD (&msghdr->nlmsghdr);
     while (RTA_OK (attr, size))
           case RTA_DST:
             inet_ntop(AF_INET, RTA_DATA (attr), rtinfo.dest,
                       sizeof (rtinfo.dest));

           case RTA_GATEWAY:
             inet_ntop(AF_INET, RTA_DATA (attr), rtinfo.gateway,
                       sizeof (rtinfo.gateway));

           case RTA_OIF:
             if_indextoname (*(int *) RTA_DATA (attr), rtinfo.iface);

           case RTA_METRICS:
             rtinfo.metrics = *(int *) RTA_DATA (attr);


         attr = RTA_NEXT (attr, size);

     print_route (&rtinfo);

linux_recvnl (int sockfd, void **buffer)
 msghdr_t *msghdr;
 size_t nread = 0;
 size_t size = 0;

 if (*buffer != NULL)
   return -1;

 nread = recvbuf (sockfd, buffer, &size);

 size = nread;
 for (msghdr = (msghdr_t *) *buffer; NLMSG_OK (&msghdr->nlmsghdr, size);
      msghdr = (msghdr_t *) NLMSG_NEXT (&msghdr->nlmsghdr, size))
     if (msghdr->nlmsghdr.nlmsg_type == NLMSG_ERROR)
       error (EXIT_FAILURE, 0,
              "netlink message truncated and can not be parsed");

     if (msghdr->nlmsghdr.nlmsg_type == NLMSG_DONE)

     if ((msghdr->nlmsghdr.nlmsg_flags & NLM_F_MULTI) == 0)

 return nread;

linux_sendnl (int sockfd)
 size_t nsent;
 msghdr_t msghdr;

 memset ((void *) &msghdr, 0, sizeof (msghdr));
 msghdr.nlmsghdr.nlmsg_len = NLMSG_LENGTH (sizeof (msghdr.rtmsg));
 msghdr.nlmsghdr.nlmsg_type = RTM_GETROUTE;
 msghdr.nlmsghdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
 msghdr.nlmsghdr.nlmsg_seq = seqn;
 msghdr.nlmsghdr.nlmsg_pid = getpid();

 nsent = send (sockfd, (void *) &msghdr, sizeof (msghdr), 0);
 if (nsent == -1)
   error (EXIT_FAILURE, errno, "send");

 return nsent;

recvbuf (int sockfd, void **buffer, size_t *size)
 size_t count = 0;
 size_t nread;

 if (*buffer == NULL)
   *size = BUFSIZ;

 for (;;)
     *buffer = realloc (*buffer, *size);
     nread = recv (sockfd, *buffer + count, BUFSIZ, 0);

     if (nread == -1)
       error (EXIT_FAILURE, errno, "recv");

     count += nread;

     if (nread < BUFSIZ)
       *size += BUFSIZ;

 return count;


Happy hacking,

bug-inetutils mailing list

reply via email to

[Prev in Thread] Current Thread [Next in Thread]