Print one record only - addition
From: Tomáš Macek <hidden>
Date: 2005-06-22 13:53:54
On Sat, 18 Jun 2005, Thomas Graf wrote:
* Tom?? Macek [ref] 2005-06-18 20:55quoted
The 'rtm_dst_len = 16' should mean the mask of the route I'm looking for, correct?Yes.quoted
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