]> git.sur5r.net Git - i3/i3status/blob - src/print_ip_addr.c
Simplify the algorithm used to determine the IP address
[i3/i3status] / src / print_ip_addr.c
1 // vim:ts=4:sw=4:expandtab
2 #include <sys/types.h>
3 #include <sys/socket.h>
4 #include <netinet/in.h>
5
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <string.h>
9 #include <netdb.h>
10 #include <ifaddrs.h>
11 #include <net/if.h>
12
13 #include "i3status.h"
14
15 /*
16  * Return the IP address for the given interface or "no IP" if the
17  * interface is up and running but hasn't got an IP address yet
18  *
19  */
20 const char *get_ip_addr(const char *interface, int family) {
21     static char part[512];
22     socklen_t len = 0;
23     if (family == AF_INET)
24         len = sizeof(struct sockaddr_in);
25     else if (family == AF_INET6)
26         len = sizeof(struct sockaddr_in6);
27
28     memset(part, 0, sizeof(part));
29
30     struct ifaddrs *ifaddr, *addrp;
31     bool found = false;
32     int interface_len = strlen(interface);
33
34     getifaddrs(&ifaddr);
35
36     if (ifaddr == NULL)
37         return NULL;
38
39     /* Skip until we are at the input family address of interface */
40     for (addrp = ifaddr; addrp != NULL; addrp = addrp->ifa_next) {
41         if (strncmp(addrp->ifa_name, interface, interface_len) != 0) {
42             /* The interface does not have the right name, skip it. */
43             continue;
44         }
45
46         if (addrp->ifa_addr != NULL && addrp->ifa_addr->sa_family == family) {
47             /* We found the right interface with the right address. */
48             break;
49         }
50
51         /* Check if the interface is down. If it is, no need to look any
52          * further. */
53         if ((addrp->ifa_flags & IFF_RUNNING) == 0) {
54             freeifaddrs(ifaddr);
55             return NULL;
56         }
57
58         found = true;
59     }
60
61     if (addrp == NULL) {
62         freeifaddrs(ifaddr);
63         return (found ? "no IP" : NULL);
64     }
65
66     int ret;
67     if ((ret = getnameinfo(addrp->ifa_addr, len, part, sizeof(part), NULL, 0, NI_NUMERICHOST)) != 0) {
68         fprintf(stderr, "i3status: getnameinfo(): %s\n", gai_strerror(ret));
69         freeifaddrs(ifaddr);
70         return "no IP";
71     }
72
73     freeifaddrs(ifaddr);
74     return part;
75 }