37
37
#include "ifconf.h"
41
static int read_reply(int fd, struct address **list, unsigned *n_list) {
46
uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred))];
49
struct ifaddrmsg ifaddrmsg;
50
uint8_t payload[16*1024];
54
.iov_len = sizeof(resp),
61
.msg_control = cred_buffer,
62
.msg_controllen = sizeof(cred_buffer),
69
bytes = recvmsg(fd, &msg, 0);
73
cmsg = CMSG_FIRSTHDR(&msg);
74
if (!cmsg || cmsg->cmsg_type != SCM_CREDENTIALS)
77
ucred = (struct ucred*) CMSG_DATA(cmsg);
78
if (ucred->uid != 0 || ucred->pid != 0)
81
for (p = &resp.hdr; bytes > 0; p = NLMSG_NEXT(p, bytes)) {
82
struct ifaddrmsg *ifaddrmsg;
85
void *local = NULL, *address = NULL;
87
if (!NLMSG_OK(p, (size_t) bytes))
90
if (p->nlmsg_seq != SEQ)
93
if (p->nlmsg_type == NLMSG_DONE)
96
if (p->nlmsg_type == NLMSG_ERROR) {
97
struct nlmsgerr *nlmsgerr;
99
nlmsgerr = NLMSG_DATA(p);
100
return -nlmsgerr->error;
103
if (p->nlmsg_type != RTM_NEWADDR)
106
ifaddrmsg = NLMSG_DATA(p);
108
if (ifaddrmsg->ifa_family != AF_INET &&
109
ifaddrmsg->ifa_family != AF_INET6)
112
if (ifaddrmsg->ifa_scope == RT_SCOPE_HOST ||
113
ifaddrmsg->ifa_scope == RT_SCOPE_NOWHERE)
116
if (ifaddrmsg->ifa_flags & IFA_F_DEPRECATED)
119
l = NLMSG_PAYLOAD(p, sizeof(struct ifaddrmsg));
120
a = IFA_RTA(ifaddrmsg);
122
while (RTA_OK(a, l)) {
124
if (a->rta_type == IFA_ADDRESS)
125
address = RTA_DATA(a);
126
else if (a->rta_type == IFA_LOCAL)
138
*list = realloc(*list, (*n_list+1) * sizeof(struct address));
142
(*list)[*n_list].family = ifaddrmsg->ifa_family;
143
(*list)[*n_list].scope = ifaddrmsg->ifa_scope;
144
memcpy((*list)[*n_list].address,
145
address, ifaddrmsg->ifa_family == AF_INET ? 4 : 16);
146
(*list)[*n_list].ifindex = ifaddrmsg->ifa_index;
39
155
int ifconf_acquire_addresses(struct address **_list, unsigned *_n_list) {
42
158
struct nlmsghdr hdr;
43
159
struct rtgenmsg gen;
161
.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg)),
162
.nlmsg_type = RTM_GETADDR,
163
.nlmsg_flags = NLM_F_REQUEST|NLM_F_DUMP|NLM_F_ACK,
167
.rtgen_family = AF_UNSPEC,
48
171
struct address *list = NULL;
49
172
unsigned n_list = 0;
51
175
fd = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);
60
memset(&req, 0, sizeof(req));
61
req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
62
req.hdr.nlmsg_type = RTM_GETADDR;
63
req.hdr.nlmsg_flags = NLM_F_REQUEST|NLM_F_DUMP|NLM_F_ACK;
64
req.hdr.nlmsg_seq = seq;
65
req.hdr.nlmsg_pid = 0;
67
gen = NLMSG_DATA(&req.hdr);
68
gen->rtgen_family = AF_UNSPEC;
70
184
if (send(fd, &req, req.hdr.nlmsg_len, 0) < 0) {
82
uint8_t cred_buffer[CMSG_SPACE(sizeof(struct ucred))];
85
struct ifaddrmsg ifaddrmsg;
86
uint8_t payload[16*1024];
89
memset(&iov, 0, sizeof(iov));
91
iov.iov_len = sizeof(resp);
93
memset(&msg, 0, sizeof(msg));
98
msg.msg_control = cred_buffer;
99
msg.msg_controllen = sizeof(cred_buffer);
102
bytes = recvmsg(fd, &msg, 0);
108
cmsg = CMSG_FIRSTHDR(&msg);
109
if (!cmsg || cmsg->cmsg_type != SCM_CREDENTIALS) {
114
ucred = (struct ucred*) CMSG_DATA(cmsg);
115
if (ucred->uid != 0 || ucred->pid != 0)
118
for (p = &resp.hdr; bytes > 0; p = NLMSG_NEXT(p, bytes)) {
119
struct ifaddrmsg *ifaddrmsg;
122
void *local = NULL, *address = NULL;
124
if (!NLMSG_OK(p, (size_t) bytes)) {
129
if (p->nlmsg_seq != seq)
132
if (p->nlmsg_type == NLMSG_DONE) {
137
if (p->nlmsg_type == NLMSG_ERROR) {
138
struct nlmsgerr *nlmsgerr;
140
nlmsgerr = NLMSG_DATA(p);
141
r = -nlmsgerr->error;
145
if (p->nlmsg_type != RTM_NEWADDR)
148
ifaddrmsg = NLMSG_DATA(p);
150
if (ifaddrmsg->ifa_family != AF_INET &&
151
ifaddrmsg->ifa_family != AF_INET6)
154
if (ifaddrmsg->ifa_scope == RT_SCOPE_HOST ||
155
ifaddrmsg->ifa_scope == RT_SCOPE_NOWHERE)
158
if (ifaddrmsg->ifa_flags & IFA_F_DEPRECATED)
161
l = NLMSG_PAYLOAD(p, sizeof(struct ifaddrmsg));
162
a = IFA_RTA(ifaddrmsg);
164
while (RTA_OK(a, l)) {
166
if (a->rta_type == IFA_ADDRESS)
167
address = RTA_DATA(a);
168
else if (a->rta_type == IFA_LOCAL)
180
list = realloc(list, (n_list+1) * sizeof(struct address));
186
list[n_list].family = ifaddrmsg->ifa_family;
187
list[n_list].scope = ifaddrmsg->ifa_scope;
188
memcpy(list[n_list].address, address, ifaddrmsg->ifa_family == AF_INET ? 4 : 16);
189
list[n_list].ifindex = ifaddrmsg->ifa_index;
189
while((r = read_reply(fd, &list, &n_list)) == 0)
201
qsort(list, n_list, sizeof(struct address), address_compare);
200
qsort(list, n_list, sizeof(struct address), address_compare);