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 = 0, af, ifa_ord = 0; |
158 |
struct ifaddrs *prev = NULL; |
159 |
struct ifa_order_elt *cur = NULL; |
160 |
|
161 |
while (ifa != NULL) { |
162 |
if (prev == NULL || strcmp(ifa->ifa_name, prev->ifa_name) != 0) { |
163 |
cur = calloc(1, sizeof(*cur)); |
164 |
|
165 |
if (cur == NULL) |
166 |
return (-1); |
167 |
|
168 |
TAILQ_INSERT_TAIL(q, cur, link); |
169 |
cur->if_order = ifa_ord ++; |
170 |
cur->ifa = ifa; |
171 |
ord = 0; |
172 |
} |
173 |
|
174 |
if (ifa->ifa_addr) { |
175 |
af = ifa->ifa_addr->sa_family; |
176 |
if (af < sizeof(cur->af_orders) / sizeof(cur->af_orders[0]) && |
177 |
cur->af_orders[af] == 0) |
178 |
cur->af_orders[af] = ++ord; |
179 |
} |
180 |
prev = ifa; |
181 |
ifa = ifa->ifa_next; |
182 |
} |
183 |
|
184 |
return (0); |
185 |
} |
186 |
|
187 |
static int |
188 |
cmpifaddrs(struct ifaddrs *a, struct ifaddrs *b, struct ifa_queue *q) |
189 |
{ |
190 |
int ret; |
191 |
unsigned int af1, af2; |
192 |
struct ifa_order_elt *cur, *e1 = NULL, *e2 = NULL; |
193 |
|
194 |
ret = strcmp(a->ifa_name, b->ifa_name); |
195 |
if (ret != 0) { |
196 |
/* We need to find elements corresponding to these different names */ |
197 |
TAILQ_FOREACH(cur, q, link) { |
198 |
if (e1 && e2) |
199 |
break; |
200 |
|
201 |
if (strcmp(cur->ifa->ifa_name, a->ifa_name) == 0) |
202 |
e1 = cur; |
203 |
else if (strcmp(cur->ifa->ifa_name, b->ifa_name) == 0) |
204 |
e2 = cur; |
205 |
} |
206 |
|
207 |
if (!e1 || !e2) |
208 |
return (0); |
209 |
else |
210 |
return (e1->if_order - e2->if_order); |
211 |
} |
212 |
else if (a->ifa_addr != NULL && b->ifa_addr != NULL) { |
213 |
TAILQ_FOREACH(cur, q, link) { |
214 |
if (strcmp(cur->ifa->ifa_name, a->ifa_name) == 0) { |
215 |
e1 = cur; |
216 |
break; |
217 |
} |
218 |
} |
219 |
|
220 |
if (!e1) |
221 |
return (0); |
222 |
|
223 |
af1 = a->ifa_addr->sa_family; |
224 |
af2 = b->ifa_addr->sa_family; |
225 |
|
226 |
if (af1 < sizeof(e1->af_orders) / sizeof(e1->af_orders[0]) && |
227 |
af2 < sizeof(e1->af_orders) / sizeof(e1->af_orders[0])) |
228 |
return (e1->af_orders[af2] - e1->af_orders[af1]); |
229 |
} |
230 |
|
231 |
return (0); |
232 |
} |
233 |
|
234 |
static struct ifaddrs * |
235 |
sortifaddrs(struct ifaddrs *list, |
236 |
int (*compare)(struct ifaddrs *, struct ifaddrs *, struct ifa_queue *), |
237 |
struct ifa_queue *q) |
238 |
{ |
239 |
|
240 |
struct ifaddrs *right = list, |
241 |
*temp = list, |
242 |
*last = list, |
243 |
*result = NULL, |
244 |
*next = NULL, |
245 |
*tail = NULL; |
246 |
|
247 |
if (!list || !list->ifa_next) |
248 |
return (list); |
249 |
|
250 |
while (temp && temp->ifa_next) { |
251 |
last = right; |
252 |
right = right->ifa_next; |
253 |
temp = temp->ifa_next->ifa_next; |
254 |
} |
255 |
|
256 |
last->ifa_next = NULL; |
257 |
|
258 |
list = sortifaddrs(list, compare, q); |
259 |
right = sortifaddrs(right, compare, q); |
260 |
|
261 |
while (list || right) { |
262 |
|
263 |
if (!right) { |
264 |
next = list; |
265 |
list = list->ifa_next; |
266 |
} else if (!list) { |
267 |
next = right; |
268 |
right = right->ifa_next; |
269 |
} else if (compare(list, right, q) <= 0) { |
270 |
next = list; |
271 |
list = list->ifa_next; |
272 |
} else { |
273 |
next = right; |
274 |
right = right->ifa_next; |
275 |
} |
276 |
|
277 |
if (!result) |
278 |
result = next; |
279 |
else |
280 |
tail->ifa_next = next; |
281 |
|
282 |
tail = next; |
283 |
} |
284 |
|
285 |
return (result); |
286 |
} |
287 |
|
144 |
int |
288 |
int |
145 |
main(int argc, char *argv[]) |
289 |
main(int argc, char *argv[]) |
146 |
{ |
290 |
{ |
Lines 147-156
Link Here
|
147 |
int c, all, namesonly, downonly, uponly; |
291 |
int c, all, namesonly, downonly, uponly; |
148 |
const struct afswtch *afp = NULL; |
292 |
const struct afswtch *afp = NULL; |
149 |
int ifindex; |
293 |
int ifindex; |
150 |
struct ifaddrs *ifap, *ifa; |
294 |
struct ifaddrs *ifap, *sifap, *ifa; |
151 |
struct ifreq paifr; |
295 |
struct ifreq paifr; |
152 |
const struct sockaddr_dl *sdl; |
296 |
const struct sockaddr_dl *sdl; |
153 |
char options[1024], *cp, *namecp = NULL; |
297 |
char options[1024], *cp, *namecp = NULL; |
|
|
298 |
struct ifa_queue q = TAILQ_HEAD_INITIALIZER(q); |
299 |
struct ifa_order_elt *cur, *tmp; |
154 |
const char *ifname; |
300 |
const char *ifname; |
155 |
struct option *p; |
301 |
struct option *p; |
156 |
size_t iflen; |
302 |
size_t iflen; |
Lines 285-293
Link Here
|
285 |
|
431 |
|
286 |
if (getifaddrs(&ifap) != 0) |
432 |
if (getifaddrs(&ifap) != 0) |
287 |
err(EXIT_FAILURE, "getifaddrs"); |
433 |
err(EXIT_FAILURE, "getifaddrs"); |
|
|
434 |
|
288 |
cp = NULL; |
435 |
cp = NULL; |
|
|
436 |
|
437 |
if (calcorders(ifap, &q) != 0) |
438 |
err(EXIT_FAILURE, "calcorders"); |
439 |
|
440 |
sifap = sortifaddrs(ifap, cmpifaddrs, &q); |
441 |
|
442 |
TAILQ_FOREACH_SAFE(cur, &q, link, tmp) |
443 |
free(cur); |
444 |
|
289 |
ifindex = 0; |
445 |
ifindex = 0; |
290 |
for (ifa = ifap; ifa; ifa = ifa->ifa_next) { |
446 |
for (ifa = sifap; ifa; ifa = ifa->ifa_next) { |
291 |
memset(&paifr, 0, sizeof(paifr)); |
447 |
memset(&paifr, 0, sizeof(paifr)); |
292 |
strncpy(paifr.ifr_name, ifa->ifa_name, sizeof(paifr.ifr_name)); |
448 |
strncpy(paifr.ifr_name, ifa->ifa_name, sizeof(paifr.ifr_name)); |
293 |
if (sizeof(paifr.ifr_addr) >= ifa->ifa_addr->sa_len) { |
449 |
if (sizeof(paifr.ifr_addr) >= ifa->ifa_addr->sa_len) { |