Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 1 Apr 2008 13:53:43 GMT
From:      Dmitry <hanabana@mail.ru>
To:        freebsd-gnats-submit@FreeBSD.org
Subject:   misc/122333: net/arping - patch to lookup for interface and src ip, second variant
Message-ID:  <200804011353.m31Drhqj021481@www.freebsd.org>
Resent-Message-ID: <200804011400.m31E0AGx036383@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         122333
>Category:       misc
>Synopsis:       net/arping - patch to lookup for interface and src ip, second variant
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Apr 01 14:00:09 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 bugreport substitutes ports/122197. I've sent 3 followups to that port but freebsd.org definitly filters mail.ru.

This patch adds arping ability to find himself interface name and source
 IP for specified destination IP.

Also I've fixed choosing the incorrect interface when destination IP matches different netwoks with different prefix length.
>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-29 10:27:14.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,154 @@
 }
 #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;
+    int			ifCnt = 0;
+    in_addr_t		ifMaskH = 0;
+    struct in_addr	ifAddr;
+    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;
+	char  tmpIfName[IFNAMSIZ];
+	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(tmpIfName)-1);
+	memcpy(tmpIfName,sdl->sdl_data,i);
+	tmpIfName[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 )
+		) {
+		    in_addr_t mask = ntohl(if_nmsk->sin_addr.s_addr);
+		    if( verbose )
+			printf(
+			    "Specified addr matches interface '%s' ("
+			    "IP addr %s, mask %s, bcast %s).\n",
+			    tmpIfName,
+			    inet_ntoa(if_addr->sin_addr),
+			    inet_ntoa(if_nmsk->sin_addr),
+			    inet_ntoa(if_bcst->sin_addr)
+			);
+		    ifCnt ++;
+		    if( mask > ifMaskH ) {
+			memcpy(ifName,tmpIfName,sizeof(ifName));
+			ifMaskH = mask;
+			ifAddr  = if_addr->sin_addr;
+		    }
+		}
+	    }
+	}
+    }
+
+    if( ifCnt == 0 ) {
+	strcpy(ebuf,"No interface found that matches specified IP");
+	return NULL;
+    }
+
+    if( verbose && ifCnt > 1 )
+	printf(
+	    "Using interface '%s' with src IP %s due to longer mask.\n",
+	    ifName,
+	    inet_ntoa(ifAddr)
+	);
+
+    if( ifce_ip != 0 )
+	*ifce_ip = ifAddr.s_addr;
+    return ifName;
+}
+#endif
+
 
 #ifdef WIN32
 static BOOL WINAPI arping_console_ctrl_handler(DWORD dwCtrlType)
@@ -1143,7 +1302,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?200804011353.m31Drhqj021481>