netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* receive only one record from the routing table
@ 2005-06-17 13:51 Tomáš Macek
  2005-06-17 14:15 ` Thomas Graf
  0 siblings, 1 reply; 8+ messages in thread
From: Tomáš Macek @ 2005-06-17 13:51 UTC (permalink / raw)
  To: netdev

Hi, I have this program (see below), and I want him to find a certain route record in the kernel routing table. I copied this somewhere from the internet and add the NetlinkAddAttr() function, that should add an request on the destination address. But the program prints always the WHOLE routing table.

But I would like to have a program, that would RECEIVE only one route from the kernel routing table for certain destination address only. Is it possible to do in rtnetlink?
I wasn't able to find the answer on google and my tries all failed.

Any help will be very appreciated!

Tomas


==================================================================================

#include <asm/types.h>
#include <netinet/ether.h>
#include <netinet/in.h>
#include <net/if.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <sys/types.h>

#define BUFSIZE 8192

struct route_info {
     u_int dstAddr;
     u_int dstMask;
     u_int srcAddr;
     u_int gateWay;
     char ifName[IF_NAMESIZE];
};

int NetlinkAddAttr(struct nlmsghdr *n, int maxlen, int type, void *data, int alen) {
         int len = RTA_LENGTH(alen);
         struct rtattr *rta;

         if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen)
                 return -1;
         rta = (struct rtattr *)(((char *)n) + NLMSG_ALIGN(n->nlmsg_len));
         rta->rta_type = type;
         rta->rta_len = len;
         memcpy(RTA_DATA(rta), data, alen);
         n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len;
         return 0;
}

int readNlSock(int sockFd, char *bufPtr, int seqNum, int pId) {
     struct nlmsghdr *nlHdr;
     int readLen = 0, msgLen = 0;

     do {
         /* Recieve response from the kernel */
         if((readLen = recv(sockFd, bufPtr, BUFSIZE - msgLen, 0)) < 0){
             perror("SOCK READ: ");
             return -1;
         }
         nlHdr = (struct nlmsghdr *)bufPtr;

         /* Check if the header is valid */
         if((NLMSG_OK(nlHdr, readLen) == 0) || (nlHdr->nlmsg_type == NLMSG_ERROR)) {
             perror("Error in recieved packet");
             return -1;
         }

         /* Check if the its the last message */
         if(nlHdr->nlmsg_type == NLMSG_DONE){
             break;
         } else{
             /* Else move the pointer to buffer appropriately */
             bufPtr += readLen;
             msgLen += readLen;
         }

         /* Check if its a multi part message */
         if((nlHdr->nlmsg_flags & NLM_F_MULTI) == 0){
             /* return if its not */
             break;
         }
     } while((nlHdr->nlmsg_seq != seqNum) || (nlHdr->nlmsg_pid != pId));

     return msgLen;
}

unsigned long netmask_from_bitcount(unsigned int bits) {
     return 0xffffffff << (32 - bits);
}

/* For printing the routes. */
void printRoute(struct route_info *rtInfo) {
     char tempBuf[512];

     /* Print Destination address */
     if(rtInfo->dstAddr != 0)
         strcpy(tempBuf, (char *)inet_ntoa(rtInfo->dstAddr));
     else
         sprintf(tempBuf,"*.*.*.*\t\t");
     fprintf(stdout,"%s\t\t", tempBuf);

     /* Print Gateway address */
     if(rtInfo->gateWay != 0)
         strcpy(tempBuf, (char *)inet_ntoa(rtInfo->gateWay));
     else
         sprintf(tempBuf,"*.*.*.*\t\t");
     fprintf(stdout,"%s\t\t", tempBuf);

     /* Print Interface Name*/
     fprintf(stdout,"%s\t\t", rtInfo->ifName);

     /* Print Source address */
     if (rtInfo->srcAddr != 0)
         strcpy(tempBuf, (char *)inet_ntoa(rtInfo->srcAddr));
     else
         sprintf(tempBuf,"*.*.*.*\t\t");

     if (rtInfo->dstMask != 0) {
         struct in_addr ia;
         ia.s_addr = htonl(netmask_from_bitcount(rtInfo->dstMask));
         sprintf(tempBuf, "%s\t", inet_ntoa(ia));
     } else {
         sprintf(tempBuf, "0.0.0.0\t");
     }

     fprintf(stdout,"%s\n", tempBuf);
}

void parseRoutes(struct nlmsghdr *nlHdr, struct route_info *rtInfo, char *find) {
     struct rtmsg *rtMsg;
     struct rtattr *rtAttr;
     int rtLen;
     char *tempBuf = NULL;
     struct in_addr ai;

     if (!inet_aton(find, &ai)) {
         return;
     }

     tempBuf = (char *)malloc(100);
     rtMsg = (struct rtmsg *)NLMSG_DATA(nlHdr);

     /* If the route is not for AF_INET or does not belong to main routing table
     then return. */
     if((rtMsg->rtm_family != AF_INET) || (rtMsg->rtm_table != RT_TABLE_MAIN))
         return;

     /* get the rtattr field */
     rtAttr = (struct rtattr *)RTM_RTA(rtMsg);
     rtLen = RTM_PAYLOAD(nlHdr);

     rtInfo->dstMask = rtMsg->rtm_dst_len; /* Netmask */

     for( ; RTA_OK(rtAttr,rtLen);rtAttr = RTA_NEXT(rtAttr,rtLen)) {
         switch(rtAttr->rta_type){
             case RTA_OIF:
                 if_indextoname(*(int *)RTA_DATA(rtAttr), rtInfo->ifName);
                 break;
             case RTA_GATEWAY:
                 rtInfo->gateWay = *(u_int *)RTA_DATA(rtAttr);
                 break;
             case RTA_PREFSRC:
                 rtInfo->srcAddr = *(u_int *)RTA_DATA(rtAttr);
                 break;
             case RTA_DST:
                 rtInfo->dstAddr = *(u_int *)RTA_DATA(rtAttr);
                 break;
         }
     }

/*
     if (rtInfo->dstAddr == ai.s_addr) {
         printf("match %s\n", inet_ntoa(rtInfo->dstAddr));
         return;
     }
*/
     printRoute(rtInfo);

     free(tempBuf);
     return;
}

int main(int argc, char *argv[]) {
     struct nlmsghdr *nlMsg;
     struct rtmsg *rtMsg;
     struct route_info *rtInfo;
     char msgBuf[BUFSIZE];

     int sock, len, msgSeq = 0;
     char buff[1024];

     /* Create Socket */
     if((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0)
         perror("Socket Creation: ");

     /* Initialize the buffer */
     memset(msgBuf, 0, BUFSIZE);

     /* point the header and the msg structure pointers into the buffer */
     nlMsg = (struct nlmsghdr *)msgBuf;
     rtMsg = (struct rtmsg *)NLMSG_DATA(nlMsg);

     /* Fill in the nlmsg header*/
     nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); // Length of message.
     nlMsg->nlmsg_type = RTM_GETROUTE;   // Get the routes from kernel routing table .

     nlMsg->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;   // The message is a request for dump.
     nlMsg->nlmsg_seq = msgSeq++;   // Sequence of the message packet.
     nlMsg->nlmsg_pid = getpid();   // PID of process sending the request.

     char *cp;
     unsigned int xx[4]; int i = 0;
     unsigned char *ap = (unsigned char *)xx;
     for (cp = argv[1], i = 0; *cp; cp++) {
         if (*cp <= '9' && *cp >= '0') {
             ap[i] = 10*ap[i] + (*cp-'0');
             continue;
         }
         if (*cp == '.' && ++i <= 3)
             continue;
         return -1;
     }

     NetlinkAddAttr(nlMsg, sizeof(nlMsg), RTA_DST, &xx, 4);

     /* Send the request */
     if(send(sock, nlMsg, nlMsg->nlmsg_len, 0) < 0){
         printf("Write To Socket Failed...\n");
         return -1;
     }

     /* Read the response */
     if((len = readNlSock(sock, msgBuf, msgSeq, getpid())) < 0) {
         printf("Read From Socket Failed...\n");
         return -1;
     }

/* Parse and print the response */
     rtInfo = (struct route_info *)malloc(sizeof(struct route_info));
     fprintf(stdout, "Destination\t\tGateway\t\tInterface\t\tSource\t\tNetmask\n");

     for( ; NLMSG_OK(nlMsg,len); nlMsg = NLMSG_NEXT(nlMsg,len)) {
         memset(rtInfo, 0, sizeof(struct route_info));
         parseRoutes(nlMsg, rtInfo, argv[1]);
     }

     free(rtInfo);
     close(sock);
     return 0;
}

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: receive only one record from the routing table
  2005-06-17 13:51 receive only one record from the routing table Tomáš Macek
@ 2005-06-17 14:15 ` Thomas Graf
  2005-06-17 18:57   ` Tomáš Macek
  0 siblings, 1 reply; 8+ messages in thread
From: Thomas Graf @ 2005-06-17 14:15 UTC (permalink / raw)
  To: Tomá? Macek; +Cc: netdev

* Tom?? Macek <Pine.LNX.4.61.0506171359490.31631@localhost.localdomain> 2005-06-17 14:51
>      nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); // Length of message.
>      nlMsg->nlmsg_type = RTM_GETROUTE;   // Get the routes from kernel routing table .
> 
>      nlMsg->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;   // The message is a request for dump.

Omit NLM_F_DUMP and you'll be fine, see rfc3549.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: receive only one record from the routing table
  2005-06-17 14:15 ` Thomas Graf
@ 2005-06-17 18:57   ` Tomáš Macek
  2005-06-17 19:13     ` Thomas Graf
  0 siblings, 1 reply; 8+ messages in thread
From: Tomáš Macek @ 2005-06-17 18:57 UTC (permalink / raw)
  To: netdev

Part of my routing table is here:

3.3.0.0         *               255.255.0.0     U     0      0        0 eth1
default         meric           0.0.0.0         UG    0      0        0 eth0

Ommiting NLM_F_DUMP and typing './a.out 3.3.0.0' gives

Error in recieved packet: Success
Read From Socket Failed...

and I don't see the reason why... I think, it should write something with the 3.3.0.0 destination, but writes the error above instead


On Fri, 17 Jun 2005, Thomas Graf wrote:

> * Tom?? Macek <Pine.LNX.4.61.0506171359490.31631@localhost.localdomain> 2005-06-17 14:51
>>      nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); // Length of message.
>>      nlMsg->nlmsg_type = RTM_GETROUTE;   // Get the routes from kernel routing table .
>>
>>      nlMsg->nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;   // The message is a request for dump.
>
> Omit NLM_F_DUMP and you'll be fine, see rfc3549.
>
>
>
>
>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: receive only one record from the routing table
  2005-06-17 18:57   ` Tomáš Macek
@ 2005-06-17 19:13     ` Thomas Graf
  2005-06-18 18:55       ` Tomáš Macek
  0 siblings, 1 reply; 8+ messages in thread
From: Thomas Graf @ 2005-06-17 19:13 UTC (permalink / raw)
  To: Tomá? Macek; +Cc: netdev

* Tom?? Macek <Pine.LNX.4.61.0506172057240.26739@localhost.localdomain> 2005-06-17 20:57
> Part of my routing table is here:
> 
> 3.3.0.0         *               255.255.0.0     U     0      0        0 eth1
> default         meric           0.0.0.0         UG    0      0        0 eth0
> 
> Ommiting NLM_F_DUMP and typing './a.out 3.3.0.0' gives
> 
> Error in recieved packet: Success
> Read From Socket Failed...

Bcause you don't set rtm_dst_len to the prefix length or 32,
and rtm_family (AF_INET). You could also use libnl, probably
easier to use.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: receive only one record from the routing table
  2005-06-17 19:13     ` Thomas Graf
@ 2005-06-18 18:55       ` Tomáš Macek
  2005-06-18 20:23         ` Thomas Graf
  0 siblings, 1 reply; 8+ messages in thread
From: Tomáš Macek @ 2005-06-18 18:55 UTC (permalink / raw)
  To: netdev

Thanks for your answers.
I just tried to compile the libnl, but some errors occured, so I'm just continuing without it.
But I've looked at the html documentation and it seems to be very good.

I repaired the main() function by adding the

rtMsg->rtm_family = AF_INET;
rtMsg->rtm_dst_len = 16;

but every request on any dst address in the routing table gives me this output:
Destination             Gateway         Interface               Source          Netmask
127.0.0.1               *.*.*.*                         lo              255.255.255.255

The 'rtm_dst_len = 16' should mean the mask of the route I'm looking for, correct? The whole code before sending the packet is below:


     /* Create Socket */
     if((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0)
         perror("Socket Creation: ");

     /* Initialize the buffer */
     memset(msgBuf, 0, BUFSIZE);

     /* point the header and the msg structure pointers into the buffer */
     nlMsg = (struct nlmsghdr *)msgBuf;
     rtMsg = (struct rtmsg *)NLMSG_DATA(nlMsg);
     rtMsg->rtm_family = AF_INET;
     rtMsg->rtm_dst_len = 16;

     /* Fill in the nlmsg header*/
     nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); // Length of message.
     nlMsg->nlmsg_type = RTM_GETROUTE;   // Get the routes from kernel routing table .
     nlMsg->nlmsg_flags = NLM_F_REQUEST;   // The message is a request for dump.
     nlMsg->nlmsg_seq = msgSeq++;   // Sequence of the message packet.
     nlMsg->nlmsg_pid = getpid();   // PID of process sending the request.

     char *cp;
     unsigned int xx[4]; int i = 0;
     unsigned char *ap = (unsigned char *)xx;
     for (cp = argv[1], i = 0; *cp; cp++) {
         if (*cp <= '9' && *cp >= '0') {
             ap[i] = 10*ap[i] + (*cp-'0');
             continue;
         }
         if (*cp == '.' && ++i <= 3)
             continue;
         return -1;
     }

     NetlinkAddAttr(nlMsg, sizeof(nlMsg), RTA_DST, &xx, 4);




On Fri, 17 Jun 2005, Thomas Graf wrote:

> * Tom?? Macek <Pine.LNX.4.61.0506172057240.26739@localhost.localdomain> 2005-06-17 20:57
>> Part of my routing table is here:
>>
>> 3.3.0.0         *               255.255.0.0     U     0      0        0 eth1
>> default         meric           0.0.0.0         UG    0      0        0 eth0
>>
>> Ommiting NLM_F_DUMP and typing './a.out 3.3.0.0' gives
>>
>> Error in recieved packet: Success
>> Read From Socket Failed...
>
> Bcause you don't set rtm_dst_len to the prefix length or 32,
> and rtm_family (AF_INET). You could also use libnl, probably
> easier to use.
>
>
>
>
>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: receive only one record from the routing table
  2005-06-18 18:55       ` Tomáš Macek
@ 2005-06-18 20:23         ` Thomas Graf
  2005-06-22 10:07           ` Tomáš Macek
  2005-06-22 13:53           ` Print one record only - addition Tomáš Macek
  0 siblings, 2 replies; 8+ messages in thread
From: Thomas Graf @ 2005-06-18 20:23 UTC (permalink / raw)
  To: Tomá? Macek; +Cc: netdev

* Tom?? Macek <Pine.LNX.4.61.0506182042540.29813@localhost.localdomain> 2005-06-18 20:55
> The 'rtm_dst_len = 16' should mean the mask of the route I'm looking for, correct?

Yes.

> The whole code before sending the packet is below:
> 
> 
>      /* Create Socket */
>      if((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0)
>          perror("Socket Creation: ");
> 
>      /* Initialize the buffer */
>      memset(msgBuf, 0, BUFSIZE);
> 
>      /* point the header and the msg structure pointers into the buffer */
>      nlMsg = (struct nlmsghdr *)msgBuf;
>      rtMsg = (struct rtmsg *)NLMSG_DATA(nlMsg);
>      rtMsg->rtm_family = AF_INET;
>      rtMsg->rtm_dst_len = 16;
> 
>      /* Fill in the nlmsg header*/
>      nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); // Length of message.
>      nlMsg->nlmsg_type = RTM_GETROUTE;   // Get the routes from kernel routing table .
>      nlMsg->nlmsg_flags = NLM_F_REQUEST;   // The message is a request for dump.
>      nlMsg->nlmsg_seq = msgSeq++;   // Sequence of the message packet.
>      nlMsg->nlmsg_pid = getpid();   // PID of process sending the request.
> 
>      char *cp;
>      unsigned int xx[4]; int i = 0;
>      unsigned char *ap = (unsigned char *)xx;
>      for (cp = argv[1], i = 0; *cp; cp++) {
>          if (*cp <= '9' && *cp >= '0') {
>              ap[i] = 10*ap[i] + (*cp-'0');
>              continue;
>          }
>          if (*cp == '.' && ++i <= 3)
>              continue;
>          return -1;
>      }
> 
>      NetlinkAddAttr(nlMsg, sizeof(nlMsg), RTA_DST, &xx, 4);

This looks good but your NetlinkAddAttr is bogus, it should
be something like this:

int nl_msg_append_tlv(struct nlmsghdr *n, int type, void *data, size_t len)
{
	int tlen;
	struct rtattr *rta;
	
	tlen = NLMSG_ALIGN(n->nlmsg_len) + RTA_LENGTH(NLMSG_ALIGN(len));

	rta = (struct rtattr *) NLMSG_TAIL(n);
	rta->rta_type = type;
	rta->rta_len = RTA_LENGTH(NLMSG_ALIGN(len));
	memcpy(RTA_DATA(rta), data, len);
	n->nlmsg_len = tlen;
	
	return 0;
}

Your code is missing various alignment requirements. I can't tell
whether this is the last bug. I recommend you to read ip/iproute.c
in the iproute2 source or give libnl a second chance.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: receive only one record from the routing table
  2005-06-18 20:23         ` Thomas Graf
@ 2005-06-22 10:07           ` Tomáš Macek
  2005-06-22 13:53           ` Print one record only - addition Tomáš Macek
  1 sibling, 0 replies; 8+ messages in thread
From: Tomáš Macek @ 2005-06-22 10:07 UTC (permalink / raw)
  To: netdev

>> ...or give libnl a second chance
I would like to give it second change, but when typing 'make', it outputs this:

...
Entering lib
   MAKE libnl.so.0.5.1
   CC helpers.c
helpers.c:417: error: `ARPHRD_EUI64' undeclared here (not in a function)
helpers.c:417: error: initializer element is not constant
helpers.c:417: error: (near initialization for `llprotos[13].i')
helpers.c:417: error: initializer element is not constant
helpers.c:417: error: (near initialization for `llprotos[13]')
helpers.c:418: error: initializer element is not constant
helpers.c:418: error: (near initialization for `llprotos[14]')
helpers.c:419: error: initializer element is not constant
helpers.c:419: error: (near initialization for `llprotos[15]')
helpers.c:420: error: initializer element is not constant
helpers.c:420: error: (near initialization for `llprotos[16]')
helpers.c:421: error: initializer element is not constant
helpers.c:421: error: (near initialization for `llprotos[17]')
...


On Sat, 18 Jun 2005, Thomas Graf wrote:

> * Tom?? Macek <Pine.LNX.4.61.0506182042540.29813@localhost.localdomain> 2005-06-18 20:55
>> The 'rtm_dst_len = 16' should mean the mask of the route I'm looking for, correct?
>
> Yes.
>
>> The whole code before sending the packet is below:
>>
>>
>>      /* Create Socket */
>>      if((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0)
>>          perror("Socket Creation: ");
>>
>>      /* Initialize the buffer */
>>      memset(msgBuf, 0, BUFSIZE);
>>
>>      /* point the header and the msg structure pointers into the buffer */
>>      nlMsg = (struct nlmsghdr *)msgBuf;
>>      rtMsg = (struct rtmsg *)NLMSG_DATA(nlMsg);
>>      rtMsg->rtm_family = AF_INET;
>>      rtMsg->rtm_dst_len = 16;
>>
>>      /* Fill in the nlmsg header*/
>>      nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); // Length of message.
>>      nlMsg->nlmsg_type = RTM_GETROUTE;   // Get the routes from kernel routing table .
>>      nlMsg->nlmsg_flags = NLM_F_REQUEST;   // The message is a request for dump.
>>      nlMsg->nlmsg_seq = msgSeq++;   // Sequence of the message packet.
>>      nlMsg->nlmsg_pid = getpid();   // PID of process sending the request.
>>
>>      char *cp;
>>      unsigned int xx[4]; int i = 0;
>>      unsigned char *ap = (unsigned char *)xx;
>>      for (cp = argv[1], i = 0; *cp; cp++) {
>>          if (*cp <= '9' && *cp >= '0') {
>>              ap[i] = 10*ap[i] + (*cp-'0');
>>              continue;
>>          }
>>          if (*cp == '.' && ++i <= 3)
>>              continue;
>>          return -1;
>>      }
>>
>>      NetlinkAddAttr(nlMsg, sizeof(nlMsg), RTA_DST, &xx, 4);
>
> This looks good but your NetlinkAddAttr is bogus, it should
> be something like this:
>
> int nl_msg_append_tlv(struct nlmsghdr *n, int type, void *data, size_t len)
> {
> 	int tlen;
> 	struct rtattr *rta;
>
> 	tlen = NLMSG_ALIGN(n->nlmsg_len) + RTA_LENGTH(NLMSG_ALIGN(len));
>
> 	rta = (struct rtattr *) NLMSG_TAIL(n);
> 	rta->rta_type = type;
> 	rta->rta_len = RTA_LENGTH(NLMSG_ALIGN(len));
> 	memcpy(RTA_DATA(rta), data, len);
> 	n->nlmsg_len = tlen;
>
> 	return 0;
> }
>
> Your code is missing various alignment requirements. I can't tell
> whether this is the last bug. I recommend you to read ip/iproute.c
> in the iproute2 source or give libnl a second chance.
>
>
>
>
>
>

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Print one record only - addition
  2005-06-18 20:23         ` Thomas Graf
  2005-06-22 10:07           ` Tomáš Macek
@ 2005-06-22 13:53           ` Tomáš Macek
  1 sibling, 0 replies; 8+ messages in thread
From: Tomáš Macek @ 2005-06-22 13:53 UTC (permalink / raw)
  To: netdev


On Sat, 18 Jun 2005, Thomas Graf wrote:

> * Tom?? Macek <Pine.LNX.4.61.0506182042540.29813@localhost.localdomain> 2005-06-18 20:55
>> The 'rtm_dst_len = 16' should mean the mask of the route I'm looking for, correct?
>
> Yes.
>
>> The whole code before sending the packet is below:
>>
>>
>>      /* Create Socket */
>>      if((sock = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE)) < 0)
>>          perror("Socket Creation: ");
>>
>>      /* Initialize the buffer */
>>      memset(msgBuf, 0, BUFSIZE);
>>
>>      /* point the header and the msg structure pointers into the buffer */
>>      nlMsg = (struct nlmsghdr *)msgBuf;
>>      rtMsg = (struct rtmsg *)NLMSG_DATA(nlMsg);
>>      rtMsg->rtm_family = AF_INET;
>>      rtMsg->rtm_dst_len = 16;
>>
>>      /* Fill in the nlmsg header*/
>>      nlMsg->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg)); // Length of message.
>>      nlMsg->nlmsg_type = RTM_GETROUTE;   // Get the routes from kernel routing table .
>>      nlMsg->nlmsg_flags = NLM_F_REQUEST;   // The message is a request for dump.
>>      nlMsg->nlmsg_seq = msgSeq++;   // Sequence of the message packet.
>>      nlMsg->nlmsg_pid = getpid();   // PID of process sending the request.
>>
>>      char *cp;
>>      unsigned int xx[4]; int i = 0;
>>      unsigned char *ap = (unsigned char *)xx;
>>      for (cp = argv[1], i = 0; *cp; cp++) {
>>          if (*cp <= '9' && *cp >= '0') {
>>              ap[i] = 10*ap[i] + (*cp-'0');
>>              continue;
>>          }
>>          if (*cp == '.' && ++i <= 3)
>>              continue;
>>          return -1;
>>      }
>>
>>      NetlinkAddAttr(nlMsg, sizeof(nlMsg), RTA_DST, &xx, 4);
>
> This looks good but your NetlinkAddAttr is bogus, it should
> be something like this:
>
> int nl_msg_append_tlv(struct nlmsghdr *n, int type, void *data, size_t len)
> {
> 	int tlen;
> 	struct rtattr *rta;
>
> 	tlen = NLMSG_ALIGN(n->nlmsg_len) + RTA_LENGTH(NLMSG_ALIGN(len));
>
> 	rta = (struct rtattr *) NLMSG_TAIL(n);
> 	rta->rta_type = type;
> 	rta->rta_len = RTA_LENGTH(NLMSG_ALIGN(len));
> 	memcpy(RTA_DATA(rta), data, len);
> 	n->nlmsg_len = tlen;
>
> 	return 0;
> }
>
> Your code is missing various alignment requirements. I can't tell
> whether this is the last bug. I recommend you to read ip/iproute.c
> in the iproute2 source or give libnl a second chance.
>

The code now works this way:
[root@localhost route]# route
1.1.1.0         *               255.255.255.0   U     0      0        0 eth0
3.3.0.0         *               255.255.0.0     U     0      0        0 eth1
default         meric           0.0.0.0         UG    0      0        0 eth0

[root@localhost route]# ./a.out 2.2.2.2 16
Destination             Gateway         Interface               Source          Netmask
2.2.2.2         213.250.192.33          eth0            255.255.255.255

[root@localhost route]# ./a.out 1.1.1.2 16
Destination             Gateway         Interface               Source          Netmask
1.1.1.2         *.*.*.*                         eth0            255.255.255.255

[root@localhost route]# ./a.out 3.3.3.2 16
Destination             Gateway         Interface               Source          Netmask
3.3.3.2         *.*.*.*                         eth1            255.255.255.255

so it returns the route, where the data would go, if their DST address would be the one given by the argv[1] with mask argv[2].
I don't know now, if we understood to each other and if this is you thought it should be. 
If I will write on the command line './a.out 3.3.0.0 16', it should print the line like this if the record is present:
3.3.0.0         *               255.255.0.0     U     0      0        0 eth1

if I would write './a.out 3.3.3.1 32' it MUST print nothing! :)

Thank you for help

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2005-06-22 13:53 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-06-17 13:51 receive only one record from the routing table Tomáš Macek
2005-06-17 14:15 ` Thomas Graf
2005-06-17 18:57   ` Tomáš Macek
2005-06-17 19:13     ` Thomas Graf
2005-06-18 18:55       ` Tomáš Macek
2005-06-18 20:23         ` Thomas Graf
2005-06-22 10:07           ` Tomáš Macek
2005-06-22 13:53           ` Print one record only - addition Tomáš Macek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).