From owner-freebsd-bugs@FreeBSD.ORG Tue Apr 1 14:00:10 2008 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 8B4001065677 for ; Tue, 1 Apr 2008 14:00:10 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 64D7F8FC34 for ; Tue, 1 Apr 2008 14:00:10 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.14.2/8.14.2) with ESMTP id m31E0Alh036384 for ; Tue, 1 Apr 2008 14:00:10 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.2/8.14.1/Submit) id m31E0AGx036383; Tue, 1 Apr 2008 14:00:10 GMT (envelope-from gnats) Resent-Date: Tue, 1 Apr 2008 14:00:10 GMT Resent-Message-Id: <200804011400.m31E0AGx036383@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Dmitry Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id EB1121065672 for ; Tue, 1 Apr 2008 13:53:44 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21]) by mx1.freebsd.org (Postfix) with ESMTP id DA6F08FC16 for ; Tue, 1 Apr 2008 13:53:44 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.14.2/8.14.2) with ESMTP id m31DrhMu021482 for ; Tue, 1 Apr 2008 13:53:43 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.14.2/8.14.1/Submit) id m31Drhqj021481; Tue, 1 Apr 2008 13:53:43 GMT (envelope-from nobody) Message-Id: <200804011353.m31Drhqj021481@www.freebsd.org> Date: Tue, 1 Apr 2008 13:53:43 GMT From: Dmitry To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Cc: Subject: misc/122333: net/arping - patch to lookup for interface and src ip, second variant X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 01 Apr 2008 14:00:10 -0000 >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 #endif +#ifdef __FreeBSD__ +#include +#include +#include +#include +#include +#include +#include +#include +#endif + #ifdef WIN32 #include #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<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: