]>
Commit | Line | Data |
---|---|---|
f5da5f84 JR |
1 | /* |
2 | * Public Release 3 | |
3 | * | |
4 | * $Id$ | |
5 | */ | |
6 | ||
7 | /* | |
8 | * ------------------------------------------------------------------------ | |
9 | * | |
10 | * Copyright (c) 1996, 1997 The Regents of the University of Michigan | |
11 | * All Rights Reserved | |
12 | * | |
13 | * Royalty-free licenses to redistribute GateD Release | |
14 | * 3 in whole or in part may be obtained by writing to: | |
15 | * | |
16 | * Merit GateDaemon Project | |
17 | * 4251 Plymouth Road, Suite C | |
18 | * Ann Arbor, MI 48105 | |
19 | * | |
20 | * THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER | |
21 | * EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION WARRANTIES OF | |
22 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE REGENTS OF THE | |
23 | * UNIVERSITY OF MICHIGAN AND MERIT DO NOT WARRANT THAT THE | |
24 | * FUNCTIONS CONTAINED IN THE SOFTWARE WILL MEET LICENSEE'S REQUIREMENTS OR | |
25 | * THAT OPERATION WILL BE UNINTERRUPTED OR ERROR FREE. The Regents of the | |
26 | * University of Michigan and Merit shall not be liable for | |
27 | * any special, indirect, incidental or consequential damages with respect | |
28 | * to any claim by Licensee or any third party arising from use of the | |
29 | * software. GateDaemon was originated and developed through release 3.0 | |
30 | * by Cornell University and its collaborators. | |
31 | * | |
32 | * Please forward bug fixes, enhancements and questions to the | |
33 | * gated mailing list: gated-people@gated.merit.edu. | |
34 | * | |
35 | * ------------------------------------------------------------------------ | |
36 | * | |
37 | * Copyright (c) 1990,1991,1992,1993,1994,1995 by Cornell University. | |
38 | * All rights reserved. | |
39 | * | |
40 | * THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY | |
41 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT | |
42 | * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY | |
43 | * AND FITNESS FOR A PARTICULAR PURPOSE. | |
44 | * | |
45 | * GateD is based on Kirton's EGP, UC Berkeley's routing | |
46 | * daemon (routed), and DCN's HELLO routing Protocol. | |
47 | * Development of GateD has been supported in part by the | |
48 | * National Science Foundation. | |
49 | * | |
50 | * ------------------------------------------------------------------------ | |
51 | * | |
52 | * Portions of this software may fall under the following | |
53 | * copyrights: | |
54 | * | |
55 | * Copyright (c) 1988 Regents of the University of California. | |
56 | * All rights reserved. | |
57 | * | |
58 | * Redistribution and use in source and binary forms are | |
59 | * permitted provided that the above copyright notice and | |
60 | * this paragraph are duplicated in all such forms and that | |
61 | * any documentation, advertising materials, and other | |
62 | * materials related to such distribution and use | |
63 | * acknowledge that the software was developed by the | |
64 | * University of California, Berkeley. The name of the | |
65 | * University may not be used to endorse or promote | |
66 | * products derived from this software without specific | |
67 | * prior written permission. THIS SOFTWARE IS PROVIDED | |
68 | * ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, | |
69 | * INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF | |
70 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
71 | */ | |
72 | ||
73 | ||
74 | #define INCLUDE_IOCTL | |
75 | #define INCLUDE_IF | |
76 | #define INCLUDE_ISO_VAR | |
77 | #include "include.h" | |
78 | #ifdef PROTO_INET | |
79 | #include "inet.h" | |
80 | #endif /* PROTO_INET */ | |
81 | #ifdef PROTO_ISO | |
82 | #include "iso.h" | |
83 | #endif /* PROTO_ISO */ | |
84 | #include "krt.h" | |
85 | #include "krt_var.h" | |
86 | ||
87 | ||
88 | #if IFNAMSIZ > IFL_NAMELEN | |
89 | error - IFL_NAMELEN not compatible with IFNAMESIZ | |
90 | #endif | |
91 | ||
92 | /* Make some assumptions about interface MTU */ | |
93 | static inline mtu_t | |
94 | krt_mtu __PF1(state, flag_t) | |
95 | { | |
96 | switch (BIT_TEST(state, IFS_POINTOPOINT|IFS_LOOPBACK|IFS_BROADCAST)) { | |
97 | case IFS_POINTOPOINT: | |
98 | /* Compressed SLIP interfaces use 256, it can't really hurt to specify it */ | |
99 | /* too low. */ | |
100 | return 256; | |
101 | ||
102 | case IFS_LOOPBACK: | |
103 | /* Loopback interfaces use more */ | |
104 | return 1536; | |
105 | ||
106 | case IFS_BROADCAST: | |
107 | /* Assume an Ethernet */ | |
108 | return 1500; | |
109 | } | |
110 | ||
111 | /* A safe assumption? */ | |
112 | return 576; | |
113 | } | |
114 | ||
115 | ||
116 | int | |
117 | krt_ifread __PF1(save_task_state, flag_t) | |
118 | { | |
119 | u_int indx = 0; | |
120 | caddr_t limit; | |
121 | struct ifreq *ifrp; | |
122 | if_link *ifl = (if_link *) 0; | |
123 | #ifdef PROTO_ISO | |
124 | static struct iso_ifreq iso_ifreq; | |
125 | static struct ifreq *ifr = (struct ifreq *) &iso_ifreq; | |
126 | #else /* PROTO_ISO */ | |
127 | static struct ifreq ifreq; | |
128 | static struct ifreq *ifr = &ifreq; | |
129 | #endif /* PROTO_ISO */ | |
130 | register task *tp = krt_task; | |
131 | static int s_in = -1; | |
132 | #ifdef ISOPROTO_RAW | |
133 | static int s_iso = -1; | |
134 | #endif /* ISOPROTO_RAW */ | |
135 | ||
136 | if (tp->task_socket < 0) { | |
137 | return EBADF; | |
138 | } | |
139 | ||
140 | if (!task_send_buffer) { | |
141 | /* We need a send buffer */ | |
142 | ||
143 | task_alloc_send(tp, task_pagesize); | |
144 | } | |
145 | ||
146 | do { | |
147 | int rc; | |
148 | size_t size; | |
149 | ||
150 | #if defined(USE_STREAMIO) && !defined(SUNOS5_0) | |
151 | struct strioctl si; | |
152 | ||
153 | si.ic_cmd = SIOCGIFCONF; | |
154 | si.ic_timout = 0; | |
155 | si.ic_len = task_send_buffer_len; | |
156 | si.ic_dp = (caddr_t) task_send_buffer; | |
157 | ||
158 | NON_INTR(rc, ioctl(tp->task_socket, I_STR, &si)); | |
159 | ||
160 | limit = si.ic_dp + (size = si.ic_len); | |
161 | ||
162 | #else /* defined(USE_STREAMIO) && !defined(SUNOS5_0) */ | |
163 | static struct ifconf ifconf_req; | |
164 | ||
165 | ifconf_req.ifc_buf = (caddr_t) task_send_buffer; | |
166 | ifconf_req.ifc_len = task_send_buffer_len; | |
167 | ||
168 | #if defined(SUNOS5_0) || defined(HPSTREAMS) | |
169 | NON_INTR(rc, ioctl(tp->task_socket, | |
170 | SIOCGIFCONF, | |
171 | &ifconf_req)); | |
172 | #else /* SUNOS5_0 || HPSTREAMS */ | |
173 | rc = task_ioctl(tp->task_socket, | |
174 | (u_long) SIOCGIFCONF, | |
175 | (void_t) &ifconf_req, | |
176 | ifconf_req.ifc_len); | |
177 | #endif /* SUNOS5_0 || HPSTREAMS */ | |
178 | ||
179 | limit = ifconf_req.ifc_buf + (size = ifconf_req.ifc_len); | |
180 | ||
181 | #endif /* defined(USE_STREAMIO) && !defined(SUNOS5_0) */ | |
182 | if (rc != 0) { | |
183 | /* Something is wrong */ | |
184 | ||
185 | if (errno == EFAULT) { | |
186 | /* Hopefully this means that the buffer is not big enough */ | |
187 | ||
188 | continue; | |
189 | } | |
190 | ||
191 | trace_log_tp(tp, | |
192 | 0, | |
193 | LOG_ERR, | |
194 | ("krt_ifread: ioctl SIOCGIFCONF: %m")); | |
195 | return errno; | |
196 | } else if (size | |
197 | && task_send_buffer_len - size > sizeof *ifr) { | |
198 | /* It appears we have read the complete list */ | |
199 | ||
200 | break; | |
201 | } | |
202 | } while (task_alloc_send(tp, task_send_buffer_len << 1), TRUE) ; | |
203 | ||
204 | trace_tp(tp, | |
205 | TR_KRT_IFLIST, | |
206 | TRC_NL_BEFORE, | |
207 | ("krt_iflist: SIOCGIFCONF returns %u bytes", | |
208 | limit - (caddr_t) task_send_buffer)); | |
209 | ||
210 | /* Tell the IF code that we are passing complete knowledge */ | |
211 | if_conf_open(tp, TRUE); | |
212 | ||
213 | #define ifr_size(x) ((unix_socksize(&(x)->ifr_addr) > sizeof((x)->ifr_addr)) ? \ | |
214 | sizeof(*(x)) + unix_socksize(&(x)->ifr_addr) - sizeof((x)->ifr_addr) : sizeof(*(x))) | |
215 | #define ifr_bump(x) ((struct ifreq *) ((void_t) ((caddr_t) (x) + ifr_size(x)))) | |
216 | ||
217 | for (ifrp = (struct ifreq *) task_send_buffer; | |
218 | (caddr_t) ifrp < limit; | |
219 | ifrp = ifr_bump(ifrp)) { | |
220 | if_info ifi; | |
221 | int s = -1; | |
222 | u_long siocgifdstaddr = 0; | |
223 | #ifdef SIOCGIFNETMASK | |
224 | u_long siocgifnetmask = 0; | |
225 | #endif /* SIOCGIFNETMASK */ | |
226 | u_long siocgifbrdaddr = 0; | |
227 | char if_name[IFNAMSIZ+1]; | |
228 | ||
229 | if (TRACE_TP(tp, TR_KRT_IFLIST)) { | |
230 | int size = unix_socksize(&ifrp->ifr_addr); | |
231 | const char *cp = trace_value(task_domain_bits, ifrp->ifr_addr.sa_family); | |
232 | ||
233 | tracef("krt_ifread: name %.*s length %u family %u", | |
234 | IFNAMSIZ, ifrp->ifr_name, | |
235 | size, | |
236 | ifrp->ifr_addr.sa_family); | |
237 | if (cp) { | |
238 | tracef("(%s)", | |
239 | cp); | |
240 | } | |
241 | ||
242 | switch (ifrp->ifr_addr.sa_family) { | |
243 | #ifdef PROTO_INET | |
244 | case AF_INET: | |
245 | { | |
246 | struct sockaddr_in *sinp = (struct sockaddr_in *) ((void_t) &ifrp->ifr_addr); | |
247 | ||
248 | tracef(" port %u addr %A", | |
249 | ntohs(sinp->sin_port), | |
250 | sockbuild_in(0, sinp->sin_addr.s_addr)); | |
251 | } | |
252 | break; | |
253 | #endif /* PROTO_INET */ | |
254 | ||
255 | #ifdef PROTO_ISO | |
256 | case AF_ISO: | |
257 | { | |
258 | struct sockaddr_iso *siso = (struct sockaddr_iso *) &ifrp->ifr_addr; | |
259 | byte *dp = (byte *) siso->siso_pad; | |
260 | ||
261 | tracef(" addr %A", | |
262 | siso->siso_addr.isoa_genaddr, | |
263 | siso->siso_addr.isoa_len); | |
264 | ||
265 | if (siso->siso_plen) { | |
266 | tracef(" psel %A", | |
267 | sockbuild_ll(0, dp, siso->siso_plen)); | |
268 | dp += siso->siso_plen; | |
269 | } | |
270 | if (siso->siso_slen) { | |
271 | tracef(" ssel %A", | |
272 | sockbuild_ll(0, dp, siso->siso_slen)); | |
273 | dp += siso->siso_slen; | |
274 | } | |
275 | if (siso->siso_tlen) { | |
276 | tracef(" tsel %A", | |
277 | sockbuild_ll(0, dp, siso->siso_tlen)); | |
278 | } | |
279 | } | |
280 | break; | |
281 | #endif /* PROTO_ISO */ | |
282 | ||
283 | #ifdef SOCKADDR_DL | |
284 | case AF_LINK: | |
285 | { | |
286 | struct sockaddr_dl *sdl = (struct sockaddr_dl *) &ifrp->ifr_addr; | |
287 | byte *dp = (byte *) sdl->sdl_data; | |
288 | ||
289 | tracef(" index %u type %u", | |
290 | sdl->sdl_index, | |
291 | sdl->sdl_type); | |
292 | if (sdl->sdl_nlen) { | |
293 | tracef(" name %.*s", | |
294 | sdl->sdl_nlen, dp); | |
295 | dp += sdl->sdl_nlen; | |
296 | } | |
297 | if (sdl->sdl_alen) { | |
298 | tracef(" addr %A", | |
299 | sockbuild_ll(0, dp, sdl->sdl_alen)); | |
300 | dp += sdl->sdl_alen; | |
301 | } | |
302 | if (sdl->sdl_slen) { | |
303 | tracef(" selector %A", | |
304 | sockbuild_ll(0, dp, sdl->sdl_slen)); | |
305 | } | |
306 | } | |
307 | break; | |
308 | #endif /* SOCKADDR_DL */ | |
309 | ||
310 | default: | |
311 | tracef(" addr %A", | |
312 | sockbuild_ll(0, | |
313 | (byte *) ifrp->ifr_addr.sa_data, | |
314 | (size_t) (size - ((byte *) ifrp->ifr_addr.sa_data - (byte *) &ifrp->ifr_addr)))); | |
315 | } | |
316 | trace_only_tp(tp, | |
317 | TRC_NL_BEFORE, | |
318 | (NULL)); | |
319 | } | |
320 | ||
321 | bzero((caddr_t) &ifi, sizeof (ifi)); | |
322 | ||
323 | bcopy(ifrp->ifr_name, if_name, IFNAMSIZ); | |
324 | if_name[IFNAMSIZ] = (char) 0; | |
325 | #if defined(SUNOS5_0) || defined(HPSTREAMS) | |
326 | { | |
327 | register char *cp = index(if_name, ':'); | |
328 | ||
329 | /* Remove the :n extension from the name */ | |
330 | if (cp) { | |
331 | *cp = (char) 0; | |
332 | } | |
333 | } | |
334 | #endif /* SUNOS5_0 || HPSTREAMS */ | |
335 | ||
336 | if (!ifl | |
337 | || strncmp(if_name, ifl->ifl_name, IFNAMSIZ)) { | |
338 | flag_t state; | |
339 | metric_t metric; | |
340 | mtu_t mtu; | |
341 | ||
342 | /* And save for ioctls */ | |
343 | (void) strncpy(ifr->ifr_name, ifrp->ifr_name, IFNAMSIZ); | |
344 | ||
345 | #if defined(SUNOS5_0) || defined(HPSTREAMS) | |
346 | /* State, MTU and metric are associated with addresses, not the interface */ | |
347 | state = mtu = metric = 0; | |
348 | ||
349 | #else /* SUNOS5_0 || HPSTREAMS */ | |
350 | /* Get interface flags */ | |
351 | bzero ((caddr_t) &ifr->ifr_ifru, sizeof (ifr->ifr_ifru)); | |
352 | if (task_ioctl(tp->task_socket, | |
353 | (u_long) SIOCGIFFLAGS, | |
354 | (char *) ifr, | |
355 | sizeof (*ifr)) < 0) { | |
356 | trace_log_tp(tp, | |
357 | 0, | |
358 | LOG_ERR, | |
359 | ("krt_ifread: %s: ioctl SIOCGIFFLAGS: %m", | |
360 | ifr->ifr_name)); | |
361 | goto Continue; | |
362 | } | |
363 | state = krt_if_flags(ifr->ifr_flags); | |
364 | ||
365 | /* Get a resonable default */ | |
366 | mtu = krt_mtu(state); | |
367 | ||
368 | #ifdef SIOCGIFMTU | |
369 | /* Get interface MTU */ | |
370 | bzero ((caddr_t) &ifr->ifr_ifru, sizeof (ifr->ifr_ifru)); | |
371 | if (task_ioctl(tp->task_socket, | |
372 | (u_long) SIOCGIFMTU, | |
373 | (char *) ifr, | |
374 | sizeof (*ifr)) < 0) { | |
375 | #ifdef notdef | |
376 | trace_tp(tp, | |
377 | TR_ALL, | |
378 | ("krt_ifread: %s: ioctl SIOCGIFMTU: %m", | |
379 | ifr->ifr_name)); | |
380 | #endif /* notdef */ | |
381 | } else { | |
382 | mtu = ifr->KRT_IFR_MTU; | |
383 | } | |
384 | #endif /* SIOCGIFMTU */ | |
385 | ||
386 | /* Get interface metric */ | |
387 | #if defined(SIOCGIFMETRIC) && defined(ifr_metric) | |
388 | bzero ((caddr_t) &ifr->ifr_ifru, sizeof (ifr->ifr_ifru)); | |
389 | if (task_ioctl(tp->task_socket, | |
390 | (u_long) SIOCGIFMETRIC, | |
391 | (caddr_t) | |
392 | ifr, | |
393 | sizeof (*ifr)) < 0) { | |
394 | trace_log_tp(tp, | |
395 | 0, | |
396 | LOG_ERR, | |
397 | ("krt_ifread: %s: ioctl SIOCGIFMETRIC: %m", | |
398 | ifr->ifr_name)); | |
399 | goto Continue; | |
400 | } | |
401 | metric = (ifr->ifr_metric >= 0) ? ifr->ifr_metric : 0; | |
402 | #else /* defined(SIOCGIFMETRIC) && defined(ifr_metric) */ | |
403 | metric = 0; | |
404 | #endif /* defined(SIOCGIFMETRIC) && defined(ifr_metric) */ | |
405 | #endif /* SUNOS5_0 || HPSTREAMS */ | |
406 | ||
407 | ||
408 | { | |
409 | #ifdef SOCKADDR_DL | |
410 | register struct ifreq *ifrl = ifrp; | |
411 | ||
412 | /* Search for an AF_LINK entry because it has */ | |
413 | /* the index and sometimes the physical address. */ | |
414 | /* On ``normal'' systems this is the first address, */ | |
415 | /* but on DEC OSF/1 systems the AF_LINK has been */ | |
416 | /* observed not to be. */ | |
417 | for (ifrl = ifrp; | |
418 | (caddr_t) ifrl < limit; | |
419 | ifrl = ifr_bump(ifrl)) { | |
420 | if (strncmp(ifrl->ifr_name, ifrp->ifr_name, IFNAMSIZ)) { | |
421 | /* Did not find one in the records for this interface */ | |
422 | ||
423 | ifrl = (struct ifreq *) 0; | |
424 | break; | |
425 | } | |
426 | ||
427 | if (ifrl->ifr_addr.sa_family == AF_LINK) { | |
428 | /* Found the AF_LINK entry */ | |
429 | ||
430 | break; | |
431 | } | |
432 | } | |
433 | ||
434 | if (ifrl && ((caddr_t) ifrl < limit)) { | |
435 | struct sockaddr_dl *sdl = (struct sockaddr_dl *) &ifrl->ifr_addr; | |
436 | sockaddr_un *lladdr; | |
437 | ||
438 | if (sdl->sdl_alen) { | |
439 | /* We have an address */ | |
440 | ||
441 | lladdr = sockbuild_ll(krt_type_to_ll(sdl->sdl_type), | |
442 | (byte *) (sdl->sdl_data + sdl->sdl_nlen), | |
443 | (size_t) sdl->sdl_alen); | |
444 | } else { | |
445 | /* This system may not supply link-level addresses, */ | |
446 | /* or this interface may not have one. Just to be sure */ | |
447 | /* try to look one up */ | |
448 | ||
449 | lladdr = krt_lladdr(ifr); | |
450 | } | |
451 | ||
452 | ifl = ifl_addup(tp, | |
453 | ifl_locate_index(sdl->sdl_index), | |
454 | (indx = sdl->sdl_index), | |
455 | state, | |
456 | metric, | |
457 | mtu, | |
458 | sdl->sdl_data, | |
459 | (size_t) sdl->sdl_nlen, | |
460 | lladdr); | |
461 | } else { | |
462 | #endif /* SOCKADDR_DL */ | |
463 | size_t n_len = strlen(if_name); | |
464 | ||
465 | ifl = ifl_addup(tp, | |
466 | ifl_locate_name(if_name, n_len), | |
467 | ++indx, | |
468 | state, | |
469 | metric, | |
470 | mtu, | |
471 | if_name, | |
472 | n_len, | |
473 | krt_lladdr(ifr)); | |
474 | } | |
475 | #ifdef SOCKADDR_DL | |
476 | } | |
477 | #endif /* SOCKADDR_DL */ | |
478 | ||
479 | if (TRACE_TP(tp, TR_KRT_IFLIST)) { | |
480 | trace_only_tp(tp, | |
481 | 0, | |
482 | ("krt_ifread: %s index %d address %A", | |
483 | ifl->ifl_name, | |
484 | ifl->ifl_index, | |
485 | ifl->ifl_addr)); | |
486 | trace_only_tp(tp, | |
487 | 0, | |
488 | ("krt_ifread: %s metric %u mtu %u state <%s>", | |
489 | ifl->ifl_name, | |
490 | ifl->ifl_metric, | |
491 | ifl->ifl_mtu, | |
492 | trace_bits(if_state_bits, ifl->ifl_state))); | |
493 | } | |
494 | #if defined(SUNOS5_0) || defined(HPSTREAMS) | |
495 | } else { | |
496 | /* Always copy the interface name to get address selector */ | |
497 | ||
498 | (void) strncpy(ifr->ifr_name, ifrp->ifr_name, IFNAMSIZ); | |
499 | #endif /* SUNOS5_0 || HPSTREAMS */ | |
500 | } | |
501 | ||
502 | bzero((caddr_t) &ifi, sizeof (ifi)); | |
503 | ifi.ifi_link = ifl; | |
504 | ||
505 | /* Reject unknown families */ | |
506 | switch (ifrp->ifr_addr.sa_family) { | |
507 | #ifdef PROTO_INET | |
508 | case AF_INET: | |
509 | break; | |
510 | #endif /* PROTO_INET */ | |
511 | ||
512 | #ifdef PROTO_ISO | |
513 | case AF_ISO: | |
514 | break; | |
515 | #endif /* PROTO_ISO */ | |
516 | ||
517 | default: | |
518 | /* Bogus address */ | |
519 | goto Continue; | |
520 | } | |
521 | ||
522 | /* Copy the interface address */ | |
523 | ifi.ifi_addr_local = ifi.ifi_addr = sockdup(sock2gated(&ifrp->ifr_addr, unix_socksize(&ifrp->ifr_addr))); | |
524 | ||
525 | #if defined(SUNOS5_0) || defined(HPSTREAMS) | |
526 | /* Get interface flags */ | |
527 | bzero ((caddr_t) &ifr->ifr_ifru, sizeof (ifr->ifr_ifru)); | |
528 | if (task_ioctl(tp->task_socket, | |
529 | (u_long) SIOCGIFFLAGS, | |
530 | (char *) ifr, | |
531 | sizeof (*ifr)) < 0) { | |
532 | trace_log_tp(tp, | |
533 | 0, | |
534 | LOG_ERR, | |
535 | ("krt_ifread: %s: ioctl SIOCGIFFLAGS: %m", | |
536 | ifr->ifr_name)); | |
537 | goto Continue; | |
538 | } | |
539 | ifi.ifi_state = krt_if_flags(ifr->ifr_flags); | |
540 | if (BIT_TEST(ifi.ifi_state, IFS_LOOPBACK)) { | |
541 | /* Indicate this is a loopback interface */ | |
542 | ||
543 | BIT_SET(ifl->ifl_state, IFS_LOOPBACK); | |
544 | } | |
545 | ||
546 | /* Get interface MTU */ | |
547 | bzero ((caddr_t) &ifr->ifr_ifru, sizeof (ifr->ifr_ifru)); | |
548 | if (task_ioctl(tp->task_socket, | |
549 | (u_long) SIOCGIFMTU, | |
550 | (char *) ifr, | |
551 | sizeof (*ifr)) < 0) { | |
552 | #ifdef notdef | |
553 | trace_log_tp(tp, | |
554 | 0, | |
555 | LOG_INFO, | |
556 | ("krt_ifread: %s: ioctl SIOCGIFMTU: %m", | |
557 | ifr->ifr_name)); | |
558 | #endif /* notdef */ | |
559 | ||
560 | /* Figure out a default */ | |
561 | ifi.ifi_mtu = krt_mtu(ifi.ifi_state); | |
562 | } else { | |
563 | ifi.ifi_mtu = ifr->KRT_IFR_MTU; | |
564 | } | |
565 | ||
566 | /* Get interface metric */ | |
567 | bzero ((caddr_t) &ifr->ifr_ifru, sizeof (ifr->ifr_ifru)); | |
568 | if (task_ioctl(tp->task_socket, | |
569 | (u_long) SIOCGIFMETRIC, | |
570 | (caddr_t) ifr, | |
571 | sizeof (*ifr)) < 0) { | |
572 | trace_log_tp(tp, | |
573 | 0, | |
574 | LOG_ERR, | |
575 | ("krt_ifread: %s: ioctl SIOCGIFMETRIC: %m", | |
576 | ifr->ifr_name)); | |
577 | goto Continue; | |
578 | } | |
579 | ifi.ifi_metric = (ifr->ifr_metric >= 0) ? ifr->ifr_metric : 0; | |
580 | #else /* SUNOS5_0 || HPSTREAMS */ | |
581 | /* Inherit parameters from physical interface */ | |
582 | ||
583 | ifi.ifi_state = ifl->ifl_state; | |
584 | ifi.ifi_metric = ifl->ifl_metric; | |
585 | ifi.ifi_mtu = ifl->ifl_mtu; | |
586 | #endif /* SUNOS5_0 || HPSTREAMS */ | |
587 | ||
588 | /* What we do next depends on the family */ | |
589 | switch (ifrp->ifr_addr.sa_family) { | |
590 | #ifdef PROTO_INET | |
591 | case AF_INET: | |
592 | /* Specify the right socket for this family */ | |
593 | if (s_in < 0) { | |
594 | BIT_RESET(task_state, TASKS_INIT|TASKS_TEST); | |
595 | s_in = task_floating_socket(tp, | |
596 | task_get_socket(tp, PF_INET, SOCK_DGRAM, 0), | |
597 | "ifread.inet"); | |
598 | task_state = save_task_state; | |
599 | } | |
600 | s = s_in; | |
601 | if (BIT_TEST(ifi.ifi_state, IFS_POINTOPOINT)) { | |
602 | siocgifdstaddr = (u_long) SIOCGIFDSTADDR; | |
603 | } | |
604 | #ifdef SIOCGIFNETMASK | |
605 | if (!BIT_TEST(ifi.ifi_state, IFS_LOOPBACK)) { | |
606 | siocgifnetmask = (u_long) SIOCGIFNETMASK; | |
607 | #endif /* SIOCGIFNETMASK */ | |
608 | } | |
609 | if (BIT_TEST(ifi.ifi_state, IFS_BROADCAST)) { | |
610 | siocgifbrdaddr = (u_long) SIOCGIFBRDADDR; | |
611 | } | |
612 | break; | |
613 | #endif /* PROTO_INET */ | |
614 | ||
615 | #ifdef PROTO_ISO | |
616 | case AF_ISO: | |
617 | /* Specify the right socket for this family */ | |
618 | if (s_iso < 0) { | |
619 | BIT_RESET(task_state, TASKS_INIT|TASKS_TEST); | |
620 | s_iso = task_floating_socket(tp, | |
621 | task_get_socket(tp, PF_ISO, SOCK_DGRAM, 0), | |
622 | "ifread.iso"); | |
623 | task_state = save_task_state; | |
624 | } | |
625 | s = s_iso; | |
626 | if (BIT_TEST(ifi.ifi_state, IFS_POINTOPOINT)) { | |
627 | siocgifdstaddr = SIOCGIFDSTADDR_ISO; | |
628 | } else if (!BIT_TEST(ifi.ifi_state, IFS_LOOPBACK)) { | |
629 | siocgifnetmask = SIOCGIFNETMASK_ISO; | |
630 | } | |
631 | break; | |
632 | #endif /* PROTO_ISO */ | |
633 | ||
634 | default: | |
635 | goto Continue; | |
636 | } | |
637 | ||
638 | if (siocgifdstaddr) { | |
639 | /* Get the destination address for point-to-point interfaces */ | |
640 | ||
641 | size_t a_len; | |
642 | ||
643 | bzero ((caddr_t) &ifr->ifr_ifru, sizeof (ifr->ifr_ifru)); | |
644 | if (task_ioctl(s, | |
645 | siocgifdstaddr, | |
646 | (caddr_t) ifr, | |
647 | sizeof (*ifr)) < 0) { | |
648 | trace_log_tp(tp, | |
649 | 0, | |
650 | LOG_ERR, | |
651 | ("krt_ifread: %s: ioctl SIOCGIFDSTADDR: %m", | |
652 | ifr->ifr_name)); | |
653 | goto Continue; | |
654 | } | |
655 | if ((a_len = unix_socksize(&ifr->ifr_dstaddr)) | |
656 | && (ifi.ifi_addr = sock2gated(&ifr->ifr_dstaddr, a_len))) { | |
657 | ifi.ifi_addr = sockdup(ifi.ifi_addr); | |
658 | } else { | |
659 | ifi.ifi_addr = (sockaddr_un *) 0; | |
660 | } | |
661 | } | |
662 | #ifdef SIOCGIFNETMASK | |
663 | if (siocgifnetmask) { | |
664 | bzero ((caddr_t) &ifr->ifr_ifru, sizeof (ifr->ifr_ifru)); | |
665 | if (task_ioctl(s, | |
666 | siocgifnetmask, | |
667 | (caddr_t) ifr, | |
668 | sizeof (*ifr)) < 0) { | |
669 | trace_log_tp(tp, | |
670 | 0, | |
671 | LOG_ERR, | |
672 | ("krt_ifread: %s: ioctl SIOCGIFNETMASK: %m", | |
673 | ifr->ifr_name)); | |
674 | goto Continue; | |
675 | } | |
676 | #ifdef SOCKET_LENGTHS | |
677 | /* A zero mask would have a length of zero */ | |
678 | if (ifr->ifr_addr.sa_len < 2) { | |
679 | ifr->ifr_addr.sa_len = 2; /* Enough for address and family */ | |
680 | } | |
681 | /* Masks don't have an address family specified */ | |
682 | if (ifr->ifr_addr.sa_family == AF_UNSPEC | |
683 | && ifi.ifi_addr) { | |
684 | ifr->ifr_addr.sa_family = socktype(ifi.ifi_addr); | |
685 | } | |
686 | #endif /* SOCKET_LENGTHS */ | |
687 | /* Convert the mask */ | |
688 | ifi.ifi_netmask = sock2gated(&ifr->ifr_addr, unix_socksize(&ifr->ifr_addr)); | |
689 | ||
690 | if (ifi.ifi_netmask) { | |
691 | /* We have a mask, get pointer to right one */ | |
692 | ifi.ifi_netmask = mask_locate(ifi.ifi_netmask); | |
693 | } | |
694 | } | |
695 | #else /* SIOCGIFNETMASK */ | |
696 | ifi.ifi_netmask = (sockaddr_un *) 0; | |
697 | #endif /* SIOCGIFNETMASK */ | |
698 | ||
699 | /* Get the broadcast address for broadcast interfaces */ | |
700 | if (siocgifbrdaddr) { | |
701 | #ifdef SIOCGIFBRDADDR | |
702 | /* Some systems (SunOS 3.x where x > 2) do not define ifr_broadaddr */ | |
703 | #ifndef ifr_broadaddr | |
704 | #define ifr_broadaddr ifr_addr | |
705 | #endif /* ifr_broadaddr */ | |
706 | bzero ((caddr_t) &ifr->ifr_ifru, sizeof (ifr->ifr_ifru)); | |
707 | if (task_ioctl(s, | |
708 | siocgifbrdaddr, | |
709 | (caddr_t) ifr, | |
710 | sizeof (*ifr)) < 0) { | |
711 | trace_log_tp(tp, | |
712 | 0, | |
713 | LOG_ERR, | |
714 | ("krt_ifread: %s: ioctl SIOGIFBRDADDR: %m", | |
715 | ifr->ifr_name)); | |
716 | goto Continue; | |
717 | } | |
718 | ifi.ifi_addr_broadcast = sock2gated(&ifr->ifr_broadaddr, unix_socksize(&ifr->ifr_broadaddr)); | |
719 | if (ifi.ifi_addr_broadcast) { | |
720 | ifi.ifi_addr_broadcast = sockdup(ifi.ifi_addr_broadcast); | |
721 | } else { | |
722 | trace_log_tp(tp, | |
723 | 0, | |
724 | LOG_ERR, | |
725 | ("krt_ifread: no broadcast address for %A (%s)", | |
726 | ifi.ifi_addr_local, | |
727 | ifrp->ifr_name)); | |
728 | goto Continue; | |
729 | } | |
730 | #else /* !SIOCGIFBRDADDR */ | |
731 | /* Assume a 4.2 based system with a zeros broadcast */ | |
732 | ifi.ifi_addr_broadcast = (sockaddr_un *) 0; | |
733 | #endif /* SIOCGIFBRDADDR */ | |
734 | } | |
735 | ||
736 | if (TRACE_TP(tp, TR_KRT_IFLIST)) { | |
737 | tracef("krt_ifread: %s %A", | |
738 | ifl->ifl_name, | |
739 | ifi.ifi_addr_local); | |
740 | if (ifi.ifi_netmask) { | |
741 | tracef("/%A", | |
742 | ifi.ifi_netmask); | |
743 | } | |
744 | if (ifi.ifi_addr_broadcast) { | |
745 | tracef(" -> %A", | |
746 | ifi.ifi_addr_broadcast); | |
747 | } else if (ifi.ifi_addr != ifi.ifi_addr_local) { | |
748 | tracef(" -> %A", | |
749 | ifi.ifi_addr); | |
750 | } | |
751 | trace_only_tp(tp, | |
752 | 0, | |
753 | (NULL)); | |
754 | trace_only_tp(tp, | |
755 | 0, | |
756 | ("krt_ifread: %s metric %u mtu %u state <%s>", | |
757 | ifl->ifl_name, | |
758 | ifi.ifi_metric, | |
759 | ifi.ifi_mtu, | |
760 | trace_bits(if_state_bits, ifi.ifi_state))); | |
761 | } | |
762 | ||
763 | /* And add the interface */ | |
764 | if_conf_addaddr(tp, &ifi); | |
765 | continue; | |
766 | ||
767 | Continue: | |
768 | /* Free any allocated addresses */ | |
769 | ifi_addr_free(&ifi); | |
770 | } | |
771 | ||
772 | trace_tp(tp, | |
773 | TR_KRT_IFLIST, | |
774 | 0, | |
775 | (NULL)); | |
776 | ||
777 | if_conf_close(tp, FALSE); | |
778 | ||
779 | return 0; | |
780 | } |