Re: Access routing table

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

 



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


[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux 802.1Q VLAN]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Git]     [Bugtraq]     [Yosemite News and Information]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux PCI]     [Linux Admin]     [Samba]

  Powered by Linux