Lines 47-52
Link Here
|
47 |
#include <sys/time.h> |
47 |
#include <sys/time.h> |
48 |
#include <sys/module.h> |
48 |
#include <sys/module.h> |
49 |
#include <sys/linker.h> |
49 |
#include <sys/linker.h> |
|
|
50 |
#include <sys/queue.h> |
50 |
|
51 |
|
51 |
#include <net/ethernet.h> |
52 |
#include <net/ethernet.h> |
52 |
#include <net/if.h> |
53 |
#include <net/if.h> |
Lines 110-115
Link Here
|
110 |
|
111 |
|
111 |
static struct option *opts = NULL; |
112 |
static struct option *opts = NULL; |
112 |
|
113 |
|
|
|
114 |
struct ifa_order_elt { |
115 |
int if_order; |
116 |
int af_orders[255]; |
117 |
struct ifaddrs *ifa; |
118 |
TAILQ_ENTRY(ifa_order_elt) link; |
119 |
}; |
120 |
|
121 |
TAILQ_HEAD(ifa_queue, ifa_order_elt); |
122 |
|
113 |
void |
123 |
void |
114 |
opt_register(struct option *p) |
124 |
opt_register(struct option *p) |
115 |
{ |
125 |
{ |
Lines 141-146
Link Here
|
141 |
exit(1); |
151 |
exit(1); |
142 |
} |
152 |
} |
143 |
|
153 |
|
|
|
154 |
static int |
155 |
calcorders(struct ifaddrs *ifa, struct ifa_queue *q) |
156 |
{ |
157 |
unsigned int ord, af, ifa_ord; |
158 |
struct ifaddrs *prev; |
159 |
struct ifa_order_elt *cur; |
160 |
|
161 |
prev = NULL; |
162 |
cur = NULL; |
163 |
ord = 0; |
164 |
ifa_ord = 0; |
165 |
|
166 |
while (ifa != NULL) { |
167 |
if (prev == NULL || strcmp(ifa->ifa_name, prev->ifa_name) != 0) { |
168 |
cur = calloc(1, sizeof(*cur)); |
169 |
|
170 |
if (cur == NULL) |
171 |
return (-1); |
172 |
|
173 |
TAILQ_INSERT_TAIL(q, cur, link); |
174 |
cur->if_order = ifa_ord ++; |
175 |
cur->ifa = ifa; |
176 |
ord = 0; |
177 |
} |
178 |
|
179 |
if (ifa->ifa_addr) { |
180 |
af = ifa->ifa_addr->sa_family; |
181 |
|
182 |
if (af < sizeof(cur->af_orders) / sizeof(cur->af_orders[0]) && |
183 |
cur->af_orders[af] == 0) |
184 |
cur->af_orders[af] = ++ord; |
185 |
} |
186 |
prev = ifa; |
187 |
ifa = ifa->ifa_next; |
188 |
} |
189 |
|
190 |
return (0); |
191 |
} |
192 |
|
193 |
static int |
194 |
cmpifaddrs(struct ifaddrs *a, struct ifaddrs *b, struct ifa_queue *q) |
195 |
{ |
196 |
int ret; |
197 |
unsigned int af1, af2; |
198 |
struct ifa_order_elt *cur, *e1, *e2; |
199 |
|
200 |
e1 = e2 = NULL; |
201 |
|
202 |
ret = strcmp(a->ifa_name, b->ifa_name); |
203 |
if (ret != 0) { |
204 |
/* We need to find elements corresponding to these different names */ |
205 |
TAILQ_FOREACH(cur, q, link) { |
206 |
if (e1 && e2) |
207 |
break; |
208 |
|
209 |
if (strcmp(cur->ifa->ifa_name, a->ifa_name) == 0) |
210 |
e1 = cur; |
211 |
else if (strcmp(cur->ifa->ifa_name, b->ifa_name) == 0) |
212 |
e2 = cur; |
213 |
} |
214 |
|
215 |
if (!e1 || !e2) |
216 |
return (0); |
217 |
else |
218 |
return (e1->if_order - e2->if_order); |
219 |
|
220 |
} else if (a->ifa_addr != NULL && b->ifa_addr != NULL) { |
221 |
TAILQ_FOREACH(cur, q, link) { |
222 |
if (strcmp(cur->ifa->ifa_name, a->ifa_name) == 0) { |
223 |
e1 = cur; |
224 |
break; |
225 |
} |
226 |
} |
227 |
|
228 |
if (!e1) |
229 |
return (0); |
230 |
|
231 |
af1 = a->ifa_addr->sa_family; |
232 |
af2 = b->ifa_addr->sa_family; |
233 |
|
234 |
if (af1 < sizeof(e1->af_orders) / sizeof(e1->af_orders[0]) && |
235 |
af2 < sizeof(e1->af_orders) / sizeof(e1->af_orders[0])) |
236 |
return (e1->af_orders[af2] - e1->af_orders[af1]); |
237 |
} |
238 |
|
239 |
return (0); |
240 |
} |
241 |
|
242 |
static struct ifaddrs * |
243 |
sortifaddrs(struct ifaddrs *list, |
244 |
int (*compare)(struct ifaddrs *, struct ifaddrs *, struct ifa_queue *), |
245 |
struct ifa_queue *q) |
246 |
{ |
247 |
|
248 |
struct ifaddrs *right, *temp, *last, *result, *next, *tail; |
249 |
|
250 |
right = list; |
251 |
temp = list; |
252 |
last = list; |
253 |
result = NULL; |
254 |
next = NULL; |
255 |
tail = NULL; |
256 |
|
257 |
if (!list || !list->ifa_next) |
258 |
return (list); |
259 |
|
260 |
while (temp && temp->ifa_next) { |
261 |
last = right; |
262 |
right = right->ifa_next; |
263 |
temp = temp->ifa_next->ifa_next; |
264 |
} |
265 |
|
266 |
last->ifa_next = NULL; |
267 |
|
268 |
list = sortifaddrs(list, compare, q); |
269 |
right = sortifaddrs(right, compare, q); |
270 |
|
271 |
while (list || right) { |
272 |
|
273 |
if (!right) { |
274 |
next = list; |
275 |
list = list->ifa_next; |
276 |
} else if (!list) { |
277 |
next = right; |
278 |
right = right->ifa_next; |
279 |
} else if (compare(list, right, q) <= 0) { |
280 |
next = list; |
281 |
list = list->ifa_next; |
282 |
} else { |
283 |
next = right; |
284 |
right = right->ifa_next; |
285 |
} |
286 |
|
287 |
if (!result) |
288 |
result = next; |
289 |
else |
290 |
tail->ifa_next = next; |
291 |
|
292 |
tail = next; |
293 |
} |
294 |
|
295 |
return (result); |
296 |
} |
297 |
|
144 |
int |
298 |
int |
145 |
main(int argc, char *argv[]) |
299 |
main(int argc, char *argv[]) |
146 |
{ |
300 |
{ |
Lines 147-156
Link Here
|
147 |
int c, all, namesonly, downonly, uponly; |
301 |
int c, all, namesonly, downonly, uponly; |
148 |
const struct afswtch *afp = NULL; |
302 |
const struct afswtch *afp = NULL; |
149 |
int ifindex; |
303 |
int ifindex; |
150 |
struct ifaddrs *ifap, *ifa; |
304 |
struct ifaddrs *ifap, *sifap, *ifa; |
151 |
struct ifreq paifr; |
305 |
struct ifreq paifr; |
152 |
const struct sockaddr_dl *sdl; |
306 |
const struct sockaddr_dl *sdl; |
153 |
char options[1024], *cp, *namecp = NULL; |
307 |
char options[1024], *cp, *namecp = NULL; |
|
|
308 |
struct ifa_queue q = TAILQ_HEAD_INITIALIZER(q); |
309 |
struct ifa_order_elt *cur, *tmp; |
154 |
const char *ifname; |
310 |
const char *ifname; |
155 |
struct option *p; |
311 |
struct option *p; |
156 |
size_t iflen; |
312 |
size_t iflen; |
Lines 285-293
Link Here
|
285 |
|
441 |
|
286 |
if (getifaddrs(&ifap) != 0) |
442 |
if (getifaddrs(&ifap) != 0) |
287 |
err(EXIT_FAILURE, "getifaddrs"); |
443 |
err(EXIT_FAILURE, "getifaddrs"); |
|
|
444 |
|
288 |
cp = NULL; |
445 |
cp = NULL; |
|
|
446 |
|
447 |
if (calcorders(ifap, &q) != 0) |
448 |
err(EXIT_FAILURE, "calcorders"); |
449 |
|
450 |
sifap = sortifaddrs(ifap, cmpifaddrs, &q); |
451 |
|
452 |
TAILQ_FOREACH_SAFE(cur, &q, link, tmp) |
453 |
free(cur); |
454 |
|
289 |
ifindex = 0; |
455 |
ifindex = 0; |
290 |
for (ifa = ifap; ifa; ifa = ifa->ifa_next) { |
456 |
for (ifa = sifap; ifa; ifa = ifa->ifa_next) { |
291 |
memset(&paifr, 0, sizeof(paifr)); |
457 |
memset(&paifr, 0, sizeof(paifr)); |
292 |
strncpy(paifr.ifr_name, ifa->ifa_name, sizeof(paifr.ifr_name)); |
458 |
strncpy(paifr.ifr_name, ifa->ifa_name, sizeof(paifr.ifr_name)); |
293 |
if (sizeof(paifr.ifr_addr) >= ifa->ifa_addr->sa_len) { |
459 |
if (sizeof(paifr.ifr_addr) >= ifa->ifa_addr->sa_len) { |