Date: Fri, 28 Mar 2008 15:39:05 GMT From: Dmitry <hanabana@mail.ru> To: freebsd-gnats-submit@FreeBSD.org Subject: ports/122197: patch to lookup for interface and src ip Message-ID: <200803281539.m2SFd5xZ031072@www.freebsd.org> Resent-Message-ID: <200803281540.m2SFe2gx076873@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 122197 >Category: ports >Synopsis: patch to lookup for interface and src ip >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-ports-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Fri Mar 28 15:40:01 UTC 2008 >Closed-Date: >Last-Modified: >Originator: Dmitry >Release: FreeBSD 6.3, FreeBSD 7.0 >Organization: home >Environment: FreeBSD gatenew.aphn 6.3-STABLE FreeBSD 6.3-STABLE #0: Thu Feb 28 22:35:03 MSK 2008 root@gatenew.aphn:/var/tmp/obj/usr/src/sys/SRV i386 >Description: This patch adds arping ability to find himself interface name and source IP for specified destination IP. >How-To-Repeat: >Fix: Patch attached with submission follows: --- arping-2/arping.c.orig 2007-09-13 20:43:37.000000000 +0400 +++ arping-2/arping.c 2008-03-28 18:23:02.000000000 +0300 @@ -48,6 +48,17 @@ #include <libnet.h> #endif +#ifdef __FreeBSD__ +#include <errno.h> +#include <string.h> +#include <sys/sysctl.h> +#include <net/if.h> +#include <net/if_dl.h> +#include <net/route.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#endif + #ifdef WIN32 #include <win32/libnet.h> #endif @@ -232,6 +243,132 @@ } #endif +#ifdef __FreeBSD__ +static const char* +FBSD_lookupIface(in_addr_t dstip, char* ebuf, in_addr_t *ifce_ip) { + int mib[6] = { + CTL_NET, + PF_ROUTE, + 0, /* Protocol */ + 0, /* Address family */ + NET_RT_IFLIST, + 0 + }; + char *buf, *lim; + int bufSize; + int c; + static char ifName[IFNAMSIZ]; + + + for(c=0;;) { + if( sysctl(mib,6,NULL,&bufSize,NULL,0) < 0 ) { + strcpy(ebuf,"sysctl: get buffer size error"); + return NULL; + } + if( (buf = malloc(bufSize)) == NULL ) { + strcpy(ebuf, "malloc: error"); + return NULL; + } + if( sysctl(mib,6,buf,&bufSize,NULL,0) == 0 ) + break; + if( errno != ENOMEM || ++c >= 10 ) { + strcpy(ebuf,"sysctl: get ifaces error"); + return NULL; + } + fprintf(stderr,"sysctl: buffer size changed"); + free(buf); + sleep(1); + } + + lim = buf + bufSize; + + while( buf < lim ) { + struct sockaddr_dl *sdl; + int i; + + struct if_msghdr * ifh = (struct if_msghdr *)buf; + if( ifh->ifm_type != RTM_IFINFO ) { + strcpy(ebuf,"Wrong data in NET_RT_IFLIST"); + return NULL; + } + if( ifh->ifm_data.ifi_datalen == 0 ) + ifh->ifm_data.ifi_datalen = sizeof(struct if_data); + sdl = + (struct sockaddr_dl *)( + buf + + sizeof(struct if_msghdr) - + sizeof(struct if_data) + + ifh->ifm_data.ifi_datalen + ); + + i = sdl->sdl_nlen < sizeof(ifName)?sdl->sdl_nlen:(sizeof(ifName)-1); + memcpy(ifName,sdl->sdl_data,i); + ifName[i] = 0; + + buf += ifh->ifm_msglen; + i = 0; + while( buf < lim ) { + struct ifa_msghdr *ifht = (struct ifa_msghdr *)buf; + char* addrPtr; + int c; + struct sockaddr_in *if_addr = NULL; + struct sockaddr_in *if_nmsk = NULL; + struct sockaddr_in *if_bcst = NULL; + + if( ifht->ifam_type != RTM_NEWADDR ) + break; + + addrPtr = buf + sizeof(struct ifa_msghdr); + buf += ifht->ifam_msglen; + + if( ifh->ifm_flags & (IFF_LOOPBACK|IFF_POINTOPOINT) ) + continue; + + for(c=1;c<(1<<RTAX_MAX);c<<=1) { + switch(c & ifht->ifam_addrs) { + case 0: + continue; + case RTA_NETMASK: + if_nmsk = (struct sockaddr_in *)addrPtr; + break; + case RTA_IFA: + if_addr = (struct sockaddr_in *)addrPtr; + break; + case RTA_BRD: + if_bcst = (struct sockaddr_in *)addrPtr; + break; + } + addrPtr += SA_SIZE((struct sockaddr *)addrPtr); + } + + + if( if_addr && if_addr->sin_family == AF_INET ) { + if( + ( dstip & if_nmsk->sin_addr.s_addr ) + == + ( if_addr->sin_addr.s_addr & if_nmsk->sin_addr.s_addr ) + ) { + if( verbose ) + printf( + "Specified addr matches interface %s,\n" + "ifce addr %s, mask %s, brcast %s\n", + ifName, + inet_ntoa(if_addr->sin_addr), + inet_ntoa(if_nmsk->sin_addr), + inet_ntoa(if_bcst->sin_addr) + ); + if( ifce_ip != 0 ) + *ifce_ip = if_addr->sin_addr.s_addr; + return ifName; + } + } + } + } + strcpy(ebuf,"Network not found"); + return NULL; +} +#endif + #ifdef WIN32 static BOOL WINAPI arping_console_ctrl_handler(DWORD dwCtrlType) @@ -1143,7 +1280,18 @@ if (dont_use_arping_lookupdev) { ifname = arping_lookupdev_default(srcip,dstip,ebuf); } else { +#ifndef __FreeBSD__ ifname = arping_lookupdev(srcip,dstip,ebuf); +#else + { + in_addr_t ifce_ip = 0; + ifname = FBSD_lookupIface(dstip,ebuf,&ifce_ip); + if( !srcip_given ) { + srcip = ifce_ip; + srcip_given = 1; + } + } +#endif } if (!ifname) { fprintf(stderr, "arping: arping_lookupdev(): %s\n", >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200803281539.m2SFd5xZ031072>