On Thu, Feb 08, 2001 at 08:32:21PM +0800, Li Peng wrote: > hi,all > I try to write a program to send packets to different hosts based on > the routing table, but i don't know how to access the routing table. i > mean given a certain destination address, how can i know which device > should i send to? Here is a small function I wrote a few years ago to replace the barf bag waranting variant of this in the nmap code. The ugly interface is caused by the nmap callers. It needs librtnetlink from iproute2 or the libnetlink.rpm in newer suse releases. -Andi #include <sys/types.h> #include <sys/ioctl.h> #include <netinet/in.h> #include <stdio.h> #include <sys/socket.h> #include "libnetlink.h" #include <string.h> #include <stdlib.h> #include <net/if.h> static int inet_socket; static int iif_to_name(int iif, char *buf) { struct ifreq ifr; int sk; if (inet_socket <= 0) { inet_socket = socket(AF_INET, SOCK_DGRAM, 0); if (inet_socket < 0) return -1; } ifr.ifr_ifindex = iif; if (ioctl(inet_socket, SIOCGIFNAME, &ifr) < 0) return -1; strcpy(buf, ifr.ifr_name); return 0; } /* Find the interface a packet would travel out on. * * Needs librtnetlink * * Limits: when multiple interfaces are valid (e.g. for equal cost multipath * routing) only the first is returned. * Only queries the main routing table. * Caller must free the interface name afterwards. * (nmap uses silly calling conventions) */ char *routethrough(struct in_addr source, struct in_addr dst) { static struct rtnl_handle hnd; static int seq; static int hnd_init; struct { struct nlmsghdr msg; struct rtmsg rt; char buf[512]; } req; struct rtattr *rta; int len; if (hnd_init++ == 0 && (rtnl_open(&hnd,0) < 0)) { /* Could try the old stupid function here. */ return NULL; } memset(&req,0,sizeof req); req.rt.rtm_family = AF_INET; req.rt.rtm_table = RT_TABLE_MAIN; req.rt.rtm_protocol = RTPROT_BOOT; /*?*/ req.rt.rtm_scope = RT_SCOPE_UNIVERSE; req.rt.rtm_type = RTN_UNICAST; len = sizeof(req.buf); rta = (struct rtattr *)(&req.buf); rta_addattr32(rta,len,RTA_SRC,source.s_addr); rta = RTA_NEXT(rta, len); rta_addattr32(rta,len,RTA_DST, dst.s_addr); req.msg.nlmsg_len = NLMSG_LENGTH(sizeof req); req.msg.nlmsg_type = RTM_GETROUTE; req.msg.nlmsg_flags = NLM_F_REQUEST; req.msg.nlmsg_seq = ++seq; if (rtnl_talk(&hnd, &req.msg, 0, 0, &req.msg, NULL, NULL) < 0) return NULL; len = sizeof(req.buf); for (rta = (struct rtattr *)(&req.buf); RTA_OK(rta, len); rta = RTA_NEXT(rta, len)) { if (rta->rta_type == RTA_OIF) { unsigned if_ind; char *buf; memcpy(&if_ind, RTA_DATA(rta), sizeof(unsigned)); buf = malloc(IFNAMSIZ); if (buf && (iif_to_name(if_ind, buf) < 0)) { free(buf); buf = NULL; } return buf; } } return NULL; } - : send the line "unsubscribe linux-net" in the body of a message to majordomo@vger.kernel.org