1

I'm reading a book about network programming in C. One of the sample programs (here: https://github.com/codeplea/Hands-On-Network-Programming-with-C/blob/master/chap01/unix_list.c) compares a sa_family type (which is an unsigned integer) to what I'm guessing is an enumerator, AF_INET and AF_INET6. How does this work?

I've been looking at socket.h and ifaddrs.h, but don't see any enums in there.

int main() {

    struct ifaddrs *addresses;

    if (getifaddrs(&addresses) == -1) {
        printf("getifaddrs call failed\n");
        return -1;
    }

    struct ifaddrs *address = addresses;
    while(address) {
        int family = address->ifa_addr->sa_family;
        if (family == AF_INET || family == AF_INET6) {

            printf("%s\t", address->ifa_name);
            printf("%s\t", family == AF_INET ? "IPv4" : "IPv6");

            char ap[100];
            const int family_size = family == AF_INET ?
                sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6);
            getnameinfo(address->ifa_addr,
                    family_size, ap, sizeof(ap), 0, 0, NI_NUMERICHOST);
            printf("\t%s\n", ap);

        }
        address = address->ifa_next;
    }


    freeifaddrs(addresses);
    return 0;
}

How does line 13 work? if (family == AF_INET || family == AF_INET6)

Thanks!

BenW
  • 737
  • 10
  • 41

3 Answers3

2

The reason you don't find any enumeration is because AF_INET and AF_INET6 are not "an enumerator".

But the header file you want to look at is sys/socket.h. In there, you will find:

#define AF_INET         2               /* internetwork: UDP, TCP, etc. */
...
#define AF_INET6        30              /* IPv6 */

In other words, AF_INET and AF_INET6 are numbers -- in fact, integers, just like the sa_family type.

Knowing that they are integers, I'm guessing you can now see exactly how

if (family == AF_INET || family == AF_INET6)

works.

landru27
  • 1,654
  • 12
  • 20
2

Define

Posix actually specifies that AF_INET is a macro, so on a particular platform, AF_INET could be defined as e.g.

#define AF_INET 16

So code like

 if (family == AF_INET) 

Will be converted after the preprocessor stage to literally the code if (family == 16)

Enum

It would not be much, if any, of a difference if it was an enum though.

An enum is just an integer, so you could compare that with a variable of integer type.

Suppose there's

enum SA_FAMILY {
   AF_INET,
   AF_INET6
   AF_UNIX
};

Here the the first enum constant will have the integer value 0, the next has the value 1, and so on.

This means you can compare one of the enumeration constans to a variable of integer type (And where the so called "usual arithemtic conversion" rules dictate how the values are converted in the various cases of whether you're using a short int, an unsigned int and so on.)

So if you have

unsigned int family = 0;

if (family == AF_INET) {
...
}

You're also just doing if (family == 0).

nos
  • 223,662
  • 58
  • 417
  • 506
0
if (family == AF_INET || family == AF_INET6)

means "if family is equal to AF_INET or if family is equal to AF_INET6". The equality operator has higher priority than the logical or operator.

the busybee
  • 10,755
  • 3
  • 13
  • 30