Date: Thu, 14 Jan 2010 21:49:25 GMT From: Alex Deiter <alex.deiter@gmail.com> To: freebsd-gnats-submit@FreeBSD.org Subject: ports/142840: [PATCH] net/udpxy: allow to listen on interface Message-ID: <201001142149.o0ELnPKd007276@www.freebsd.org> Resent-Message-ID: <201001142150.o0ELo023059521@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 142840 >Category: ports >Synopsis: [PATCH] net/udpxy: allow to listen on interface >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-ports-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: maintainer-update >Submitter-Id: current-users >Arrival-Date: Thu Jan 14 21:50:00 UTC 2010 >Closed-Date: >Last-Modified: >Originator: Alex Deiter >Release: 9.0-CURRENT >Organization: N/A >Environment: FreeBSD blackbox.deiter.net.ru 9.0-CURRENT FreeBSD 9.0-CURRENT #0: Sat Dec 19 19:24:58 MSK 2009 root@blackbox.deiter.net.ru:/usr/obj/usr/src/sys/BLACKBOX i386 >Description: net/udpxy has command line params: -a : (IPv4) address/interface to listen on [default = 0.0.0.0] -m : (IPv4) address/interface of (multicast) source [default = 0.0.0.0] Examples: udpxy -p 4022 listen for HTTP requests on port 4022, all network interfaces udpxy -a lan0 -p 4022 -m lan1 listen for HTTP requests on interface lan0, port 4022; subscribe to multicast groups on interface lan1 but when i try to use interface name - it hang: # udpxy -T -v -p 9999 -a vge1 > nothing After reading source code i resolved issue with small patch. Please review attachment. After patching: # udpxy -T -v -p 9999 -a vge1 2010-01-15 00:40:24.208315 MSK 8750 udpxy 1.0-Chipmunk (build 14) standard: udpxy -T -v -p 9999 -a vge1 2010-01-15 00:40:24.229827 MSK 8750 Starting server [8750]; capacity=[3] clients 2010-01-15 00:40:24.233689 MSK 8750 Setting up listener for [10.50.2.1:9999] 2010-01-15 00:40:24.240288 MSK 8750 Server socket=[7] is set up 2010-01-15 00:40:24.245772 MSK 8750 Entering server loop Thanks a lot! >How-To-Repeat: # cd /usr/ports/net/udpxy && make install >Fix: replace code for function if2addr (retrieve IPv4 address of the given network interface): int if2addr( const char* ifname, struct sockaddr_in *addr, size_t addrlen ) { int rc = -1; struct ifaddrs *ifr, *ifc; struct sockaddr_in *sin; assert( ifname && addr && addrlen ); getifaddrs(&ifr); for (ifc = ifr; ifc != NULL; ifc = ifc->ifa_next) { if (strcmp(ifc->ifa_name, ifname) != 0) continue; if (ifc->ifa_addr == NULL) continue; sin = (struct sockaddr_in *)ifc->ifa_addr; if (sin->sin_family != AF_INET) continue; memcpy(addr, sin, addrlen); rc = 0; } freeifaddrs(ifr); return rc; } Patch attached with submission follows: --- net/udpxy/files/patch-ifaddr.h.orig 2010-01-15 00:43:29.651340980 +0300 +++ net/udpxy/files/patch-ifaddr.h 2010-01-15 00:16:43.151207509 +0300 @@ -0,0 +1,11 @@ +--- ifaddr.h.orig 2010-01-14 23:49:31.288490434 +0300 ++++ ifaddr.h 2010-01-14 23:49:56.636770433 +0300 +@@ -21,7 +21,7 @@ + */ + int + if2addr( const char* ifname, +- struct sockaddr *addr, size_t addrlen ); ++ struct sockaddr_in *addr, size_t addrlen ); + + + /* convert input parameter into an IPv4-address string --- net/udpxy/files/patch-ifaddr.c.orig 2010-01-15 00:43:29.659342424 +0300 +++ net/udpxy/files/patch-ifaddr.c 2010-01-15 00:16:52.727321532 +0300 @@ -0,0 +1,149 @@ +--- ifaddr.c.orig 2010-01-14 23:49:24.515378502 +0300 ++++ ifaddr.c 2010-01-14 23:50:07.723908032 +0300 +@@ -10,6 +10,7 @@ + #include <stdlib.h> + #include <netinet/in.h> + #include <arpa/inet.h> ++#include <ifaddrs.h> + + #include <assert.h> + #include <limits.h> +@@ -21,114 +22,29 @@ + */ + int + if2addr( const char* ifname, +- struct sockaddr *addr, size_t addrlen ) ++ struct sockaddr_in *addr, size_t addrlen ) + { +- int rc, sockfd; +- char *buf, *rec; +- size_t buflen, sa_len; +- int last_len; +- struct ifconf ifc; +- struct ifreq ifr; +- +- static size_t IFC_TABLE_SIZE; +- +- static const size_t IFC_ENTRIES = 32; +- static const size_t MAX_IFCBUF_SIZE = (1024 * 256); +- +- IFC_TABLE_SIZE = sizeof(struct ifreq) * IFC_ENTRIES; ++ int rc = -1; ++ struct ifaddrs *ifr, *ifc; ++ struct sockaddr_in *sin; + + assert( ifname && addr && addrlen ); +- rc = 0; +- +- /* acquire the list of network interfaces */ +- +- sockfd = socket( AF_INET, SOCK_DGRAM, 0 ); +- if( -1 == sockfd ) return -1; +- +- buf = NULL; buflen = IFC_TABLE_SIZE; last_len = 0; +- for( ; buflen < MAX_IFCBUF_SIZE; buflen += IFC_TABLE_SIZE ) { +- if( NULL == (buf = malloc( buflen )) ) { +- rc = -1; +- break; +- } +- +- ifc.ifc_len = buflen; +- ifc.ifc_buf = buf; +- if( ioctl( sockfd, SIOCGIFCONF, &ifc ) < 0 ) { +- if( (EINVAL != errno) || (last_len != 0) ) { +- rc = errno; +- break; +- } +- } +- else { +- if( ifc.ifc_len == last_len ) +- break; +- else +- last_len = ifc.ifc_len; +- } +- +- free( buf ); +- buf = NULL; +- } /* for */ +- +- (void) close( sockfd ); +- if( buflen > MAX_IFCBUF_SIZE ) rc = -1; +- +- if( 0 != rc ) { +- if( NULL != buf ) free( buf ); +- return rc; +- } + +- assert( ifc.ifc_buf ); ++ getifaddrs(&ifr); + +- /* look for ifname in the list */ +- +- for( rec = ifc.ifc_buf; rec < (ifc.ifc_buf + ifc.ifc_len); ) { +- (void) memcpy( &ifr, rec, sizeof(struct ifreq) ); +- +- #ifdef NO_SOCKADDR_SA_LEN +- switch( ifr.ifr_addr.sa_family ) +- { +- case AF_INET: +- sa_len = sizeof(struct sockaddr); break; +-#ifndef NO_INET6_SUPPORT +- case AF_INET6: +- sa_len = sizeof(struct sockaddr_in6); break; +-#endif +- default: +- rc = -1; break; +- } +- #else +- sa_len = ifr.ifr_addr.sa_len; +- #endif +- if( 0 != rc ) break; +- +- if( ifr.ifr_addr.sa_family != AF_INET ) ++ for (ifc = ifr; ifc != NULL; ifc = ifc->ifa_next) { ++ if (strcmp(ifc->ifa_name, ifname) != 0) + continue; +- +- if( 0 == strncmp(ifname, ifr.ifr_name, sizeof(struct ifreq)) ) { +- if( addrlen < sa_len ) { +- rc = -1; +- break; +- } +- +- (void) memcpy( addr, &(ifr.ifr_addr), sa_len ); +- break; +- } +- else { +- /* rec += (sa_len + sizeof( ifr.ifr_name )); */ +- /**** the above is per R. Stevens' book and not working +- **** on 64-bit Linux */ +- +- rec += sizeof(ifr); +- } +- } /* for */ +- +- if( rec >= (buf + ifc.ifc_len) ) { +- rc = -1; ++ if (ifc->ifa_addr == NULL) ++ continue; ++ sin = (struct sockaddr_in *)ifc->ifa_addr; ++ if (sin->sin_family != AF_INET) ++ continue; ++ memcpy(addr, sin, addrlen); ++ rc = 0; + } + +- free( buf ); ++ freeifaddrs(ifr); + return rc; + } + +@@ -147,7 +63,7 @@ + (void) strncpy( buf, s, len ); + } + else { +- rc = if2addr( s, (struct sockaddr*)&saddr, sizeof(saddr) ); ++ rc = if2addr( s, (struct sockaddr_in *)&saddr, sizeof(saddr) ); + if( 0 != rc ) return rc; + + (void) strncpy( buf, inet_ntoa(saddr.sin_addr), len ); >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201001142149.o0ELnPKd007276>