wiki:TBR/UserManual/Obtaining_Interface_Information

Obtaining Interface Information

This is based on an answer posted to the RTEMS User's mailing list by ThomasRauscher? http://www.rtems.com/ml/rtems-users/2004/november/msg00255.html, updated with an answer posted by Arnout Vandecappelle? http://www.rtems.com/ml/rtems-users/2008/april/msg00177.html.

Question: What is the best way to obtain my IP address, MAC Address, Network Mask, and Default Gateway after the rtemsbsdnetinitializenetwork()_ call? I want to be able to access this information from software.

Answer: The following code retrieves the IP address for an interface. 'ifname' should contain the name of your interface, e.g. "eth0", 'addr' then contains the result. Replace _SIOCGIFADDR_ by _SIOCGIFBRDADDR_ for the broadcast address, _SIOCGIFNETMASK_ for the net mask, and _SIOCGIFDSTADDR_ for the other side of a point-to-point link.

#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <netinet/in.h>

int get_ifaddr(const char *ifname, struct in_addr *addr)
{
    int fd;
    int rc;
    struct ifreq ifreq;
    struct sockaddr_in *sockaddr;

    fd = socket(AF_INET, SOCK_DGRAM, 0);
    if(fd<0) {
        return -1;
    }

    strcpy(ifreq.ifr_name, ifname);

    rc = ioctl(fd, SIOCGIFADDR, &ifreq);
    if(rc == 0)
    {
        sockaddr = (struct sockaddr_in *) &ifreq.ifr_ifru.ifru_addr;
        memcpy(addr, &sockaddr->sin_addr, sizeof(*addr));
    }

    close(fd);
    return (rc==0) ? 0 : -1;
}

Finding the MAC address is a little more complex. The code below does the trick. 'ifname' should contain the name of your interface, e.g. "eth0", 'addr' then contains the result. 'addr' should be pre-allocated and large enough to store the Ethernet address (i.e. 6 bytes).

Note that it is necessary to hard-code the number 18 because the AF_LINK definition is not visible outside of the bsdnet kernel.

#include <sys/socket.h>  /* For sockaddr */
#include <net/if.h>      /* For struct ifreq, required by SIO* */
#include <net/if_types.h> /* For IFT_ETHER */
#include <net/if_dl.h>    /* For sockaddr_dl */
#include <sys/sockio.h>  /* For SIO* */

int get_macaddr(const char *ifname, char *addr)
{
  int i;
  char buf[1024];
  int sock;
  struct ifconf ifc;
  struct ifreq *ifr, *lifr;
  struct sockaddr_dl *sdl;

  ifc.ifc_buf = buf;
  ifc.ifc_len = sizeof(buf);

  if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
    return sock;
  }
  i =  ioctl(sock, SIOCGIFCONF, (char *)&ifc);
  close(sock);
  if (i < 0) {
    return i;
  }

  ifr = ifc.ifc_req;
  lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len];

  while (ifr < lifr) {
    struct sockaddr *sa;
    sa = &ifr->ifr_addr;
    if (!strcmp(ifr->ifr_name, ifname)) {
      sdl = (struct sockaddr_dl *)sa;
      if (sdl->sdl_family == 18) { /* AF_LINK is made invisiable in socket.h */
        memcpy (addr, LLADDR(sdl), sdl->sdl_alen);
        return sdl->sdl_alen;
      }
    }
    if (sa->sa_len < sizeof(*sa))
      ifr = (struct ifreq *)(((char *)sa) + sizeof(*sa));
    else
      ifr = (struct ifreq *)(((char *)sa) + sa->sa_len);
  }
  return -1;
}

For the default gateway, no simple solution is found yet.

Last modified on Apr 14, 2008 at 5:21:53 PM Last modified on Apr 14, 2008, 5:21:53 PM