Obtaining interface information via an ioctl call

Discussion in 'Linux Networking' started by Will, Jun 25, 2003.

  1. Will

    Will Guest

    I'm trying to obtain a list of all the network interfaces on a
    machine, from which the user will select an interface by name. I'm
    going to then use the name to obtain the address of the interface to
    select the appropriate interface to use when transmitting multicast
    messages (I'm trying to follow Juan-Mariano de Goyeneche's Multicast
    HOWTO).

    I try to obtain the number of interfaces, then retrieve the interface
    information into a pre-allocated buffer. As it is the code fails with
    the error
    ioctl(SIOCGIFCOUNT): Invalid Argument

    Also, if I comment out this code, and set the count to 1 (the number
    of interfaces in my machine) the interface name is returned as '@'.

    I've included my code below. Thanks in advance for any help!

    // general headers
    #include <stdio.h>
    #include <stdlib.h>
    // socket level information
    #include <sys/types.h>
    #include <sys/socket.h>
    // UDP protocol information
    #include <netinet/in.h>
    #include <arpa/inet.h>
    // NIC info
    #include <net/if.h>
    #include <linux/sockios.h>
    #include <sys/ioctl.h>

    // debugging
    #include <errno.h>

    const int SYSTEM_ERROR = -1;
    const char DEST_IP_ADDRESS[] = "239.192.2.1";
    const unsigned int DEST_PORT = 31000;

    const unsigned char ENABLE = 1;
    const unsigned char DISABLE = 0;

    int main()
    {
    // We will create a UDP socket, set the options to make
    // it multicast, then transmit away
    int the_socket;
    in_addr destination_ip_address;
    sockaddr_in destination_address;

    the_socket = socket( PF_INET, SOCK_DGRAM, 0);

    if( the_socket == SYSTEM_ERROR )
    {
    fprintf(stderr, "Failed to create socket.\n");
    }

    // set the default destination address
    inet_aton(DEST_IP_ADDRESS, &destination_ip_address);
    destination_address.sin_family = AF_INET;
    destination_address.sin_port = htons(DEST_PORT);
    // memcopy ip address structure in
    memcpy( &(destination_address.sin_addr), &destination_ip_address,
    sizeof(destination_ip_address) );
    connect( the_socket, (struct sockaddr*)(&destination_address),
    sizeof(destination_address) );

    // setup multicast options
    /////////////////////////////

    // stop packet loopback
    unsigned char option;
    option = DISABLE;
    setsockopt( the_socket, IPPROTO_IP, IP_MULTICAST_LOOP, &option,
    sizeof(option) );
    // set TTL to 2 (just to check we can)
    option = 2;
    setsockopt( the_socket, IPPROTO_IP, IP_MULTICAST_TTL, &option,
    sizeof(option));

    // get interface information
    int numifs;
    size_t bufsize;
    ifreq *reqbuf;

    // get count of the number of interfaces
    if( ioctl(the_socket, SIOCGIFCOUNT, &numifs) == -1 )
    {
    perror("ioctl(SIOCGIFCOUNT)");
    exit(EXIT_FAILURE);
    }

    bufsize = numifs * sizeof(ifreq);
    reqbuf = (struct ifreq *)malloc(bufsize);
    if( reqbuf == NULL )
    {
    fprintf(stderr, "Failed to allocate memory for interface
    information.\n");
    exit(EXIT_FAILURE);
    }

    if( ioctl( the_socket, SIOCGIFCONF, reqbuf ) == -1 )
    {
    perror("ioctl(SIOCGIFCONF)");
    exit(EXIT_FAILURE);
    }

    for( int i=0; i<numifs; i++ )
    printf("Interface no %d is named \"%s\"\n", i,
    reqbuf.ifr_name);

    return EXIT_SUCCESS;


    }
     
    Will, Jun 25, 2003
    #1
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.