Skip site navigation (1)Skip section navigation (2)
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>