ioctl(SIOCGIFCONF)

Discussion in 'Linux Networking' started by AW, Sep 23, 2003.

  1. AW

    AW Guest

    Hello,
    I have a problem on my Suse 8.2 system: The ioctl(SIOCGIFCONF) call
    returns only 127.0.0.1, not the IP-numbers of the NICs. I use the
    openmosix-kernel 2.4.20. I need to get the ioctl working in order to
    boot lam-mpi.

    Any ideas?

    andreas
     
    AW, Sep 23, 2003
    #1
    1. Advertisements

  2. Post some code showing what you are doing. The ideal thing
    would be a small, complete, program which demonstrates your
    problem. It should be something everyone can compile to see
    what it does or doesn't do.

    That said, here is a demo program which shows how to get
    a variety of information about an interface.

    /*
    * display info about network interfaces
    */

    #define _BSD_SOURCE

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>
    #include <errno.h>
    #include <sys/ioctl.h>
    #include <sys/types.h>
    #include <net/if.h>
    #include <net/if_arp.h>
    #include <arpa/inet.h>

    #define inaddrr(x) (*(struct in_addr *) &ifr->x[sizeof sa.sin_port])
    #define IFRSIZE ((int)(size * sizeof (struct ifreq)))

    static int
    get_addr(int sock, char * ifname, struct sockaddr * ifaddr) {

    struct ifreq *ifr;
    struct ifreq ifrr;
    struct sockaddr_in sa;

    ifr = &ifrr;

    ifrr.ifr_addr.sa_family = AF_INET;

    strncpy(ifrr.ifr_name, ifname, sizeof(ifrr.ifr_name));

    if (ioctl(sock, SIOCGIFADDR, ifr) < 0) {
    printf("No %s interface.\n", ifname);
    return -1;
    }

    *ifaddr = ifrr.ifr_addr;
    printf("Address for %s: %s\n", ifname, inet_ntoa(inaddrr(ifr_addr.sa_data)));
    return 0;
    }

    int main(void)
    {
    unsigned char *u;
    int sockfd, size = 1;
    struct ifreq *ifr;
    struct ifconf ifc;
    struct sockaddr_in sa;


    if (0 > (sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP))) {
    fprintf(stderr, "Cannot open socket.\n");
    exit(EXIT_FAILURE);
    }

    ifc.ifc_len = IFRSIZE;
    ifc.ifc_req = NULL;

    do {
    ++size;
    /* realloc buffer size until no overflow occurs */
    if (NULL == (ifc.ifc_req = realloc(ifc.ifc_req, IFRSIZE))) {
    fprintf(stderr, "Out of memory.\n");
    exit(EXIT_FAILURE);
    }
    ifc.ifc_len = IFRSIZE;
    if (ioctl(sockfd, SIOCGIFCONF, &ifc)) {
    perror("ioctl SIOCFIFCONF");
    exit(EXIT_FAILURE);
    }
    } while (IFRSIZE <= ifc.ifc_len);

    /* this is an alternate way to get info... */
    {
    struct sockaddr ifa;
    get_addr(sockfd, "ppp0", &ifa);
    }

    ifr = ifc.ifc_req;
    for (;(char *) ifr < (char *) ifc.ifc_req + ifc.ifc_len; ++ifr) {

    if (ifr->ifr_addr.sa_data == (ifr+1)->ifr_addr.sa_data) {
    continue; /* duplicate, skip it */
    }

    if (ioctl(sockfd, SIOCGIFFLAGS, ifr)) {
    continue; /* failed to get flags, skip it */
    }

    printf("Interface: %s\n", ifr->ifr_name);
    printf("IP Address: %s\n", inet_ntoa(inaddrr(ifr_addr.sa_data)));

    /*
    This won't work on HP-UX 10.20 as there's no SIOCGIFHWADDR ioctl. You'll
    need to use DLPI or the NETSTAT ioctl on /dev/lan0, etc (and you'll need
    to be root to use the NETSTAT ioctl. Also this is deprecated and doesn't
    work on 11.00).

    On Digital Unix you can use the SIOCRPHYSADDR ioctl according to an old
    utility I have. Also on SGI I think you need to use a raw socket, e.g. s
    = socket(PF_RAW, SOCK_RAW, RAWPROTO_SNOOP)

    Dave

    From: David Peter <>
    */

    if (0 == ioctl(sockfd, SIOCGIFHWADDR, ifr)) {

    /* Select which hardware types to process.
    *
    * See list in system include file included from
    * /usr/include/net/if_arp.h (For example, on
    * Linux see file /usr/include/linux/if_arp.h to
    * get the list.)
    */
    switch (ifr->ifr_hwaddr.sa_family) {
    default:
    printf("\n");
    continue;
    case ARPHRD_NETROM: case ARPHRD_ETHER: case ARPHRD_PPP:
    case ARPHRD_EETHER: case ARPHRD_IEEE802: break;
    }

    u = (unsigned char *) &ifr->ifr_addr.sa_data;

    if (u[0] + u[1] + u[2] + u[3] + u[4] + u[5]) {
    printf("HW Address: %2.2x.%2.2x.%2.2x.%2.2x.%2.2x.%2.2x\n",
    u[0], u[1], u[2], u[3], u[4], u[5]);
    }
    }

    if (0 == ioctl(sockfd, SIOCGIFNETMASK, ifr) &&
    strcmp("255.255.255.255", inet_ntoa(inaddrr(ifr_addr.sa_data)))) {
    printf("Netmask: %s\n", inet_ntoa(inaddrr(ifr_addr.sa_data)));
    }

    if (ifr->ifr_flags & IFF_BROADCAST) {
    if (0 == ioctl(sockfd, SIOCGIFBRDADDR, ifr) &&
    strcmp("0.0.0.0", inet_ntoa(inaddrr(ifr_addr.sa_data)))) {
    printf("Broadcast: %s\n", inet_ntoa(inaddrr(ifr_addr.sa_data)));
    }
    }

    if (0 == ioctl(sockfd, SIOCGIFMTU, ifr)) {
    printf("MTU: %u\n", ifr->ifr_mtu);
    }

    if (0 == ioctl(sockfd, SIOCGIFMETRIC, ifr)) {
    printf("Metric: %u\n", ifr->ifr_metric);
    }
    printf("\n");
    }

    close(sockfd);
    return EXIT_SUCCESS;
    }
     
    Floyd Davidson, Sep 23, 2003
    #2
    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.