bug-inetutils
[Top][All Lists]
Advanced

[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
interface.

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>
^L
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);

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

void
print_header (void)
{
 puts ("Kernel IP routing table");
 printf ("%-15s %-15s %-6s %-6s %-6s %-15s\n",
         "Destination",
         "Gateway",
         "Metric",
         "Ref",
         "Use",
         "Iface");
}

void
print_route (const rtinfo_t *const rtinfo)
{
 printf ("%-15s %-15s %-6d %-6d %-6d %-15s\n",
         rtinfo->dest,
         rtinfo->gateway,
         rtinfo->metrics,
         rtinfo->ref,
         rtinfo->use,
         rtinfo->iface);
}

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

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

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

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

 close (sockfd);
 free (buffer);
}

void
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))
       continue;

     rtinfo_init (&rtinfo);

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

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

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

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

           default:
             break;
           }

         attr = RTA_NEXT (attr, size);
       }

     print_route (&rtinfo);
   }
}

size_t
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)
       break;

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

 return nread;
}

size_t
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");

 seqn++;
 return nsent;
}

size_t
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)
       break;
     else
       *size += BUFSIZ;
   }

 return count;
}


Comments?

Happy hacking,
Debarshi


_______________________________________________
bug-inetutils mailing list
address@hidden
http://lists.gnu.org/mailman/listinfo/bug-inetutils


reply via email to

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