• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re(2): Ethernet address format question - part 2
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re(2): Ethernet address format question - part 2


  • Subject: Re(2): Ethernet address format question - part 2
  • From: "Peter Lovell" <email@hidden>
  • Date: Thu, 2 Jun 2005 06:50:45 -0400




/* interface list routines */


//what follows is for *nix only, not win32
#ifndef WIN32

#include "/config.h" /* the configure script results */

#include <limits.h>

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif
#ifdef HAVE_SYS_SOCKIO_H
#include <sys/sockio.h>
#endif
#ifdef HAVE_NET_IF_H
#include <net/if.h>
#endif
#ifdef HAVE_NETINET_IN_H
#include <netinet/in.h>
#endif
#ifdef HAVE_NET_IF_DL_H
#include <net/if_dl.h>
#endif

#ifdef HAVE_STROPTS_H
#include <stropts.h>
#endif

#include <net/if_arp.h>
#include <arpa/inet.h>
#include <errno.h>

#ifndef max
#define max(a,b)    ((a) > (b) ? (a) : (b))
#endif

struct ifi_list* get_ifi_list(void)
{
    struct ifi_list*    ifi;
    struct ifi_list*    ifi_head = NULL;
    struct ifi_list**   ifi_pnext;
    struct ifi_list     ifi_zero;       //prototype zero entry
    struct ifi_list     ifi_curr;
    struct ifconf       ifc;
    struct ifreq*       ifr;
    struct ifreq        ifr_work;
    struct ifreq        ifr_zero;
    char*               ifr_ptr;    //important !! char*, not struct*
#ifdef SIOCGARP
    struct arpreq       arp_req;
#endif
    int                 sd;
    int                 oldsize;
    int                 newsize;
    int                 len;
    char                isAlias;
    char*               buf;
    char*               cptr;
    char*               temp;
    int                 dp;

    dp = 1 ;


    memset( &ifi_zero, 0, sizeof(struct ifi_list) );
    memset( &ifr_zero, 0, sizeof(struct ifreq) );
    memset( &ifi_curr, 0, sizeof(struct ifi_list) );
    sd = socket( AF_INET, SOCK_DGRAM, 0 );
    if ( sd < 0 )
    {
        fprintf(stderr,"%s:%d ERROR: get_ifi_list failed to open socket,
errno = %d\n",__FILE__, __LINE__, errno );
        return ifi_head;    //return empty list if error
    }

    oldsize = 0;
    newsize = 20 * sizeof(struct ifreq);

    for ( ; ; )
    {
        buf = malloc( newsize );
        if ( buf == NULL )
        {
            fprintf(stderr,"%s:%d ERROR: malloc failed, errno =
%d\n",__FILE__, __LINE__, errno );
            return NULL;    //return empty list if error
        }
        ifc.ifc_len = newsize;
        ifc.ifc_buf = buf;

        if ( ioctl( sd, SIOCGIFCONF, &ifc ) < 0 )
        {
            if ( errno != EINVAL || oldsize > 0 )
            {
                fprintf(stderr,"%s:%d ERROR: SIOCGIFCONF failed, errno =
%d\n",__FILE__, __LINE__, errno );
                if ( buf != NULL )
                    free( buf);
                return NULL;    //return empty list if error
            }
        }
        else    // ioctl succeeded - do we have them all
        {
            if ( ifc.ifc_len == oldsize )
                break;      //same size means it was big enuff
        }
        //otherwise
        oldsize = ifc.ifc_len;
        newsize = 2 * oldsize;
        free( buf );
    }

if ( dp ) fprintf( stderr, "get_ifi_list: ifc.ifc_len %d\n", ifc.ifc_len);
    // We have a buffer with all the interfaces
    // Now walk the list and extract what we need
    ifi_pnext = &ifi_head;
    ifr_ptr = buf;
    for ( ; ; )
    {
        // if this is out-of-range, i.e. we've done the final one,
        // point at the zero entry to cause the final one to be added to
the list
        if ( ifr_ptr >= buf + ifc.ifc_len )
            ifr_ptr = (char*)&ifr_zero;
        // Point at the current one, then calculate the pointer to the
next
        ifr = (struct ifreq*)ifr_ptr;
#ifdef HAVE_SOCKADDR_SA_LEN
        len = max( sizeof(struct sockaddr), ifr->ifr_addr.sa_len );
#else
        switch ( ifr->ifr_addr.sa_family )      //otherwise size depends
upon family
        {
#ifdef AF_INET6
            case AF_INET6:
                len = sizeof( struct sockaddr_in6 );
                break;
#endif
            case AF_INET:
            default:
                len = sizeof( struct sockaddr_in );
                break;
        }
#endif  // HAVE_SOCKADDR_SA_LEN
if ( dp ) fprintf( stderr, "get_ifi_list: ifr 0x%p name %s sa_len %d\n",
ifr, ifr->ifr_name, len);
        ifr_ptr += sizeof( ifr->ifr_name ) + len;

        cptr = strchr( ifr->ifr_name, ':' );
        isAlias = (cptr != NULL);
        if ( cptr != NULL )
            cptr = '\0';             // break an alias back to the parent
interface

        if ( strcmp( ifr->ifr_name, ifi_curr.ifi_name ) != 0 )      //
different interface
        {
if ( dp ) fprintf( stderr, "get_ifi_list: ifr 0x%p name %s oldname %s\n",
ifr, ifr->ifr_name, ifi_curr.ifi_name);
            //this is a different interface, so save the existing entry
if appropriate
            if ( strcmp( ifi_curr.ifi_name, "" ) != 0 )     //did we
actually have an entry - skip if not
            {
                // We do have a name, but what else
                // If no IPv4 then try for it
#ifdef SIOCGIFADDR
                if ( memcmp( &ifi_curr.ifi_v4addr, &ifi_zero.ifi_v4addr,
sizeof(ifi_curr.ifi_v4addr) ) == 0 )
                {
if ( dp ) fprintf( stderr, "get_ifi_list: name %s try for IPv4\n",
ifi_curr.ifi_name);
                    strncpy(ifr_work.ifr_name, ifi_curr.ifi_name, IFNAMSIZ);
                    if ( ioctl(sd, SIOCGIFADDR, &ifr_work) >= 0 )
                        memcpy( &ifi_curr.ifi_v4addr, &(((struct
sockaddr_in*)&(ifr_work.ifr_addr))->sin_addr.s_addr), sizeof(struct
in_addr) );
                }
#endif


                // We have a name, but is there an enet address?
                if ( memcmp( ifi_curr.ifi_haddr, ifi_zero.ifi_haddr,
sizeof(ifi_curr.ifi_haddr) ) == 0 )
                {
if ( dp ) fprintf( stderr, "get_ifi_list: name %s try for enet\n",
ifi_curr.ifi_name);
                    // Lo - let me count the ways ....
                    // There are several ioctls for fetching the address
but we assume that
                    // if it's defined then it will work, and we don't
have to try the others
                    strncpy( ifr_work.ifr_name, ifi_curr.ifi_name, IFNAMSIZ );
#ifdef SIOCGIFHWADDR
                    if ( ioctl(sd, SIOCGIFHWADDR, &ifr_work) >= 0 )
                        memcpy( ifi_curr.ifi_haddr,
&ifr_work.ifr_hwaddr.sa_data, sizeof(ifi_curr.ifi_haddr) );
#elif defined SIOCGENADDR
                    if ( ioctl(sd, SIOCGENADDR, &ifr_work) >= 0 )
                        memcpy( ifi_curr.ifi_haddr, ifr_work.ifr_enaddr,
sizeof(ifi_curr.ifi_haddr) );
#endif
                }

                // If not but we do have IPv4 then try to get the enet from it
#ifdef SIOCGARP
if ( dp ) fprintf( stderr, "get_ifi_list: name %s try for enet from
IPv4\n", ifi_curr.ifi_name);
                if ( (memcmp( ifi_curr.ifi_haddr, ifi_zero.ifi_haddr,
sizeof(ifi_curr.ifi_haddr) ) == 0) &&
                     (memcmp( &ifi_curr.ifi_v4addr, &ifi_zero.ifi_v4addr,
sizeof(ifi_curr.ifi_v4addr) ) != 0) )
                {
                    memcpy( &arp_req.arp_pa, &ifi_curr.ifi_v4addr,
sizeof(struct sockaddr_in) );
                    if ( ioctl( sd, SIOCGARP, &arp_req ) >= 0 )
                        memcpy( ifi_curr.ifi_haddr,
arp_req.arp_ha.sa_data, ETHER_ADDR_LEN );      //assume ethernet for now
-- how to check??
                }
#endif

if ( dp ) fprintf( stderr, "get_ifi_list: add name %s to list inet %x
haddr %x:%x:%x:%x:%x:%x\n", ifi_curr.ifi_name, ifi_curr.ifi_v4addr,
ifi_curr.ifi_haddr[0], ifi_curr.ifi_haddr[1], ifi_curr.ifi_haddr[2],
ifi_curr.ifi_haddr[3], ifi_curr.ifi_haddr[4], ifi_curr.ifi_haddr[5] );
                if ( memcmp( ifi_curr.ifi_haddr, ifi_zero.ifi_haddr,
sizeof(ifi_curr.ifi_haddr) ) != 0)
                {
                    //this has a name and enet address, so save it and
get ready for the next entry
                    temp = malloc( sizeof(ifi_curr) );
                    if ( temp == NULL )
                    {
                        fprintf(stderr,"%s:%d ERROR: malloc failed, errno
= %d\n",__FILE__, __LINE__, errno );
                        // ?? free some existing list??
                        return NULL;    //return empty list if error
                    }
                    ifi = (struct ifi_list*)temp;
                    memcpy( ifi, &ifi_curr, sizeof(ifi_curr) );
                    *ifi_pnext = ifi;
                    ifi_pnext = &ifi->ifi_next;
                }
            }
            memset( &ifi_curr, 0, sizeof(struct ifi_list) );
            memcpy( ifi_curr.ifi_name, ifr->ifr_name,
sizeof(ifi_curr.ifi_name) );
        }
        if ( ifr == &ifr_zero )
            break;      //we're done

        if ( isAlias )
            continue;       //we're not interested in aliases

#ifdef HAVE_SOCKADDR_DL_STRUCT
        if ( ifr->ifr_addr.sa_family == AF_LINK     /* or is equal to an
equivalent, for AIX I think */ )
        {
if ( dp ) fprintf( stderr, "get_ifi_list: ifr 0x%p name %s try for
AF_LINK\n", ifr, ifr->ifr_name);
            struct sockaddr_dl* sdl = (struct sockaddr_dl*) &ifr->ifr_addr;
            // think about how to restrict this to just ethernet
            if ( sdl->sdl_alen == ETHER_ADDR_LEN )
                memcpy( ifi_curr.ifi_haddr, sdl->sdl_data + sdl-
>sdl_nlen, ETHER_ADDR_LEN );
        }
#endif

        if ( ifr->ifr_addr.sa_family == AF_INET )
        {
            memcpy( &ifi_curr.ifi_v4addr, &(((struct sockaddr_in*)&(ifr-
>ifr_addr))->sin_addr.s_addr), sizeof(struct in_addr) );
if ( dp ) fprintf( stderr, "get_ifi_list: ifr 0x%p name %s AF_INET %s\n",
ifr, ifr->ifr_name, inet_ntoa(((struct sockaddr_in*)&(ifr->ifr_addr))-
>sin_addr) );
        }
    }
    return ifi_head;
}


#endif      // WIN32



 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Macnetworkprog mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:

This email sent to email@hidden

  • Prev by Date: Re(2): Ethernet address format question
  • Next by Date: Preference file reading by using FindFolder()
  • Previous by thread: Re(2): Ethernet address format question
  • Next by thread: Preference file reading by using FindFolder()
  • Index(es):
    • Date
    • Thread