Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 11 Dec 1996 12:16:05 -0800
From:      Julian Elischer <julian@whistle.com>
To:        Rodrigo Ormonde <ormonde@trem.cnt.org.br>
Cc:        hackers@FreeBSD.ORG
Subject:   Re: Discovering network interfaces
Message-ID:  <32AF1685.41C67EA6@whistle.com>
References:  <9612111740.AA13674@trem.cnt.org.br>

next in thread | previous in thread | raw e-mail | index | archive | help
Rodrigo Ormonde wrote:
> 
>   Helo.
> 
>   I have to write a program to show the user the names of the currently
> configured network interfaces. (something like netstat -in)
>   The problem is that I have no idea how this could be done inside a C program
> (I don't want to execute a external program like netstat to do this. It'd be
> nice if I could do it inside my C program).
> 
>   Does anybody know a function/system call which can be used to list the
> network interfaces ?
> 
>   Any help will be apreciated.
> 
>   Please send answers to me, I'm not on the list.
A
Here's a little program that dumps out interfaces and their addresses
(some of which you don't normally see)

alter to your heart's content.. :)


-cut here-
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/syslog.h>
#include <sys/param.h>
#include <net/if.h>
#include <net/if_dl.h>
#include <stdio.h>
#include <strings.h>
#include <ctype.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>



void showbytes(unsigned char *cptr,int len)
{
        int i,j;
        for (j = 0 ;len > 0 ;j++) {
                for ( i = 0; i < 16; i++) {
                        printf("0x%x ",*cptr++);
                        if (--len == 0) break;
                }
                printf("\n");
        }
}
void print_sa (struct sockaddr *sap)
{
        char    buf[128];

        printf("len=%d,",sap->sa_len);
        switch(sap->sa_family) {
                
        case    AF_LINK:
                printf(" family=LINK\n");
                {
                        char    *cptr;
                        struct sockaddr_dl *sdl = (struct sockaddr_dl
*)sap;
                        cptr = sdl->sdl_data;
                        printf("index=%u, type=%u ",
                                sdl->sdl_index,
                                sdl->sdl_type);
                        printf("nlen=%u, alen=%u, slen=%u\n",
                                sdl->sdl_nlen,
                                sdl->sdl_alen,
                                sdl->sdl_slen);
                        if(sdl->sdl_nlen) {
                                bcopy(cptr,buf,sdl->sdl_nlen);
                                buf[sdl->sdl_nlen] = 0;
                                printf(" name = %s\n",buf);
                                cptr += sdl->sdl_nlen;
                        }
                        if(sdl->sdl_alen) {
                                printf(" address = ");
                                showbytes(cptr,sdl->sdl_alen);
                                cptr += sdl->sdl_alen;
                        }
                        if(sdl->sdl_slen) {
                                printf(" selector = ");
                                showbytes(cptr,sdl->sdl_slen);
                                cptr += sdl->sdl_slen;
                        }
                }
                break;
        case    AF_INET:
        printf(" family=INET\n");
                printf("[%s]",
                   inet_ntoa(((struct sockaddr_in *)sap)->sin_addr));
                printf(".%hu\n",((struct sockaddr_in *)sap)->sin_port);
                break;
        default:
                printf(" family=%d\n",sap->sa_family);
                showbytes(sap->sa_data,sap->sa_len-2);
        }
}

/*
 * Get the configuration from the kernel. Only called if there's no
 * configuration.
 */

void getifconf( void )
{
    struct ifconf       ifc;
    struct ifreq        ifrs[ 64 ], *ifr, *nextifr;
    struct interface    *iface, *niface;
    int                 s;
    struct sockaddr     *sa_p;
    int ifrsize = 0;

    bzero(&ifc,sizeof(struct ifconf));
    bzero(ifrs,sizeof(struct ifreq) * 64);
    if (( s = socket( AF_INET, SOCK_DGRAM, 0 )) < 0 ) {
        perror( "socket" );
        exit( 1 );
    }

    ifc.ifc_len = sizeof( ifrs );
    ifc.ifc_buf = (caddr_t)ifrs;
    if ( ioctl( s, SIOCGIFCONF, &ifc ) < 0 ) {
        perror( "getifconf" );
        exit( 1 );
    }

    for ( ifr = ifc.ifc_req; ifc.ifc_len >= sizeof( struct ifreq );
                        ifr = nextifr, ifc.ifc_len -= ifrsize) {
        /*
         * in BSD4.4, this returns an entry for every address
         * Associated with the if. including physical.. they
         * include a sockaddr which is VARIABLE LENGTH!
         * 
         * Calculate the length of this entry.
         */
        sa_p = &(ifr->ifr_addr);
        print_sa(&(ifr->ifr_addr));
/*      print_sa(&(ifr->ifr_dstaddr));
        print_sa(&(ifr->ifr_broadaddr)); */
        ifrsize =  IFNAMSIZ + sa_p->sa_len;
        nextifr = (struct ifreq *)((caddr_t)ifr + ifrsize);
        
        /*
         * Now get it's flags
         */
        if ( ioctl( s, SIOCGIFFLAGS, ifr ) < 0 ) {
            perror( ifr->ifr_name );
            exit( 1 );
        }
        printf("FLAGS = 0x%x\n",(unsigned short)ifr->ifr_flags);

        printf("\n");

    }
    if ( ifc.ifc_len != 0 ) {
        fprintf( stderr, "Funky gifconf return.\n" );
        exit( 1 );
    }

    (void)close( s );
    return;
}

main()
{
        getifconf();
        exit(0);
}

/* EOF */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?32AF1685.41C67EA6>