| 46 | #define RTA_MASKS (RTA_GATEWAY | RTA_IFP | RTA_IFA) |
| 47 | |
| 48 | int |
| 49 | getifmaddrs(struct ifmaddrs **pif) |
| 50 | { |
| 51 | int icnt = 1; |
| 52 | int dcnt = 0; |
| 53 | int ntry = 0; |
| 54 | size_t len; |
| 55 | size_t needed; |
| 56 | int mib[6]; |
| 57 | int i; |
| 58 | char *buf; |
| 59 | char *data; |
| 60 | char *next; |
| 61 | char *p; |
| 62 | struct ifma_msghdr *ifmam; |
| 63 | struct ifmaddrs *ifa, *ift; |
| 64 | struct rt_msghdr *rtm; |
| 65 | struct sockaddr *sa; |
| 66 | |
| 67 | mib[0] = CTL_NET; |
| 68 | mib[1] = PF_ROUTE; |
| 69 | mib[2] = 0; /* protocol */ |
| 70 | mib[3] = 0; /* wildcard address family */ |
| 71 | mib[4] = NET_RT_IFMALIST; |
| 72 | mib[5] = 0; /* no flags */ |
| 73 | do { |
| 74 | if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) |
| 75 | return (-1); |
| 76 | if ((buf = malloc(needed)) == NULL) |
| 77 | return (-1); |
| 78 | if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) { |
| 79 | if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) { |
| 80 | free(buf); |
| 81 | return (-1); |
| 82 | } |
| 83 | free(buf); |
| 84 | buf = NULL; |
| 85 | } |
| 86 | } while (buf == NULL); |
| 87 | |
| 88 | for (next = buf; next < buf + needed; next += rtm->rtm_msglen) { |
| 89 | rtm = (struct rt_msghdr *)(void *)next; |
| 90 | if (rtm->rtm_version != RTM_VERSION) |
| 91 | continue; |
| 92 | switch (rtm->rtm_type) { |
| 93 | case RTM_NEWMADDR: |
| 94 | ifmam = (struct ifma_msghdr *)(void *)rtm; |
| 95 | if ((ifmam->ifmam_addrs & RTA_IFA) == 0) |
| 96 | break; |
| 97 | icnt++; |
| 98 | p = (char *)(ifmam + 1); |
| 99 | for (i = 0; i < RTAX_MAX; i++) { |
| 100 | if ((RTA_MASKS & ifmam->ifmam_addrs & |
| 101 | (1 << i)) == 0) |
| 102 | continue; |
| 103 | sa = (struct sockaddr *)(void *)p; |
| 104 | len = SA_RLEN(sa); |
| 105 | dcnt += len; |