302Found
302Found

Reputation: 512

How to find whether an IP address is a link-local address or not

I'm using this program to find all IP addresses of my Debian machine. Although I can remove my loopback address by using the ifa_name field of the 'ifaddrs' structure, something like

  struct ifaddrs * ifAddrsStruct=NULL;
  getifaddrs(&ifAddrsStruct);
  if (!strcmp(ifAddrIterator->ifa_name,"lo"))
   // Filter these addresses

I wanted to know is there any way I can find out, from the list of IP addresses, whether an IP address is a link-local (a network address that is intended and valid only for communications within a network segment) or not. Thanks in advance.

Upvotes: 0

Views: 3484

Answers (3)

mwarning
mwarning

Reputation: 771

This code checks if a IP4 address is a link local address.

#include <stdio.h>
#include <arpa/inet.h>

int main(int argc, char **argv)
{
    struct in_addr addr = {0};
    char str[INET_ADDRSTRLEN];

    if (1 == inet_pton(AF_INET, "169.254.40.203", &addr)) {
        // 169.254.0.0 translates to 0x0000fea9
        if ((addr.s_addr & 0x0000ffff) == 0x0000fea9) {
            printf("is link local\n");
        } else {
            printf("not link local\n");
        }
    }

    return 0;
}

This might only work on little endian systems (x86, AMD64)

Upvotes: 1

akw
akw

Reputation: 2110

The following snippet can be used to determine if an ip is a link-local ipv4 address:

const char* str = "169.254.1.2";
uint32_t ipv4;

struct in_addr addrp;
if (0 != inet_aton(str, &addrp)) {
  ipv4 = addrp.s_addr;
} else {
  ipv4 = 0;
}


if ((ipv4 & 0xa9fe0000) == 0xa9fe0000) {
  // .. This ip is link-local
}

Upvotes: 0

Lightness Races in Orbit
Lightness Races in Orbit

Reputation: 385088

Start with:

sockaddr* addr = ifAddrsStruct->ifa_addr;

Now, link-local addresses for IPv4 are defined in the address block 169.254.0.0/16, so:

  • if addr->sa_family == AF_INET
  • compare static_cast<sockaddr_in*>(addr)->sin_addr against that range.

In IPv6, they are assigned with the fe80::/64 prefix, so:

  • if addr->sa_family == AF_INET6
  • compare static_cast<sockaddr_in6*>(addr)->sin6_addr against that prefix.

Upvotes: 0

Related Questions