8 * ------------------------------------------------------------------------
10 * Copyright (c) 1996, 1997 The Regents of the University of Michigan
13 * Royalty-free licenses to redistribute GateD Release
14 * 3 in whole or in part may be obtained by writing to:
16 * Merit GateDaemon Project
17 * 4251 Plymouth Road, Suite C
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.
32 * Please forward bug fixes, enhancements and questions to the
33 * gated mailing list: gated-people@gated.merit.edu.
35 * ------------------------------------------------------------------------
37 * Copyright (c) 1990,1991,1992,1993,1994,1995 by Cornell University.
38 * All rights reserved.
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.
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.
50 * ------------------------------------------------------------------------
52 * Portions of this software may fall under the following
55 * Copyright (c) 1988 Regents of the University of California.
56 * All rights reserved.
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.
76 #define INCLUDE_ISO_VAR
80 #endif /* PROTO_INET */
83 #endif /* PROTO_ISO */
88 #if IFNAMSIZ > IFL_NAMELEN
89 error - IFL_NAMELEN not compatible with IFNAMESIZ
92 /* Make some assumptions about interface MTU */
94 krt_mtu __PF1(state, flag_t)
96 switch (BIT_TEST(state, IFS_POINTOPOINT|IFS_LOOPBACK|IFS_BROADCAST)) {
98 /* Compressed SLIP interfaces use 256, it can't really hurt to specify it */
103 /* Loopback interfaces use more */
107 /* Assume an Ethernet */
111 /* A safe assumption? */
117 krt_ifread __PF1(save_task_state, flag_t)
122 if_link *ifl = (if_link *) 0;
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;
133 static int s_iso = -1;
134 #endif /* ISOPROTO_RAW */
136 if (tp->task_socket < 0) {
140 if (!task_send_buffer) {
141 /* We need a send buffer */
143 task_alloc_send(tp, task_pagesize);
150 #if defined(USE_STREAMIO) && !defined(SUNOS5_0)
153 si.ic_cmd = SIOCGIFCONF;
155 si.ic_len = task_send_buffer_len;
156 si.ic_dp = (caddr_t) task_send_buffer;
158 NON_INTR(rc, ioctl(tp->task_socket, I_STR, &si));
160 limit = si.ic_dp + (size = si.ic_len);
162 #else /* defined(USE_STREAMIO) && !defined(SUNOS5_0) */
163 static struct ifconf ifconf_req;
165 ifconf_req.ifc_buf = (caddr_t) task_send_buffer;
166 ifconf_req.ifc_len = task_send_buffer_len;
168 #if defined(SUNOS5_0) || defined(HPSTREAMS)
169 NON_INTR(rc, ioctl(tp->task_socket,
172 #else /* SUNOS5_0 || HPSTREAMS */
173 rc = task_ioctl(tp->task_socket,
174 (u_long) SIOCGIFCONF,
175 (void_t) &ifconf_req,
177 #endif /* SUNOS5_0 || HPSTREAMS */
179 limit = ifconf_req.ifc_buf + (size = ifconf_req.ifc_len);
181 #endif /* defined(USE_STREAMIO) && !defined(SUNOS5_0) */
183 /* Something is wrong */
185 if (errno == EFAULT) {
186 /* Hopefully this means that the buffer is not big enough */
194 ("krt_ifread: ioctl SIOCGIFCONF: %m"));
197 && task_send_buffer_len - size > sizeof *ifr) {
198 /* It appears we have read the complete list */
202 } while (task_alloc_send(tp, task_send_buffer_len << 1), TRUE) ;
207 ("krt_iflist: SIOCGIFCONF returns %u bytes",
208 limit - (caddr_t) task_send_buffer));
210 /* Tell the IF code that we are passing complete knowledge */
211 if_conf_open(tp, TRUE);
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))))
217 for (ifrp = (struct ifreq *) task_send_buffer;
218 (caddr_t) ifrp < limit;
219 ifrp = ifr_bump(ifrp)) {
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];
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);
233 tracef("krt_ifread: name %.*s length %u family %u",
234 IFNAMSIZ, ifrp->ifr_name,
236 ifrp->ifr_addr.sa_family);
242 switch (ifrp->ifr_addr.sa_family) {
246 struct sockaddr_in *sinp = (struct sockaddr_in *) ((void_t) &ifrp->ifr_addr);
248 tracef(" port %u addr %A",
249 ntohs(sinp->sin_port),
250 sockbuild_in(0, sinp->sin_addr.s_addr));
253 #endif /* PROTO_INET */
258 struct sockaddr_iso *siso = (struct sockaddr_iso *) &ifrp->ifr_addr;
259 byte *dp = (byte *) siso->siso_pad;
262 siso->siso_addr.isoa_genaddr,
263 siso->siso_addr.isoa_len);
265 if (siso->siso_plen) {
267 sockbuild_ll(0, dp, siso->siso_plen));
268 dp += siso->siso_plen;
270 if (siso->siso_slen) {
272 sockbuild_ll(0, dp, siso->siso_slen));
273 dp += siso->siso_slen;
275 if (siso->siso_tlen) {
277 sockbuild_ll(0, dp, siso->siso_tlen));
281 #endif /* PROTO_ISO */
286 struct sockaddr_dl *sdl = (struct sockaddr_dl *) &ifrp->ifr_addr;
287 byte *dp = (byte *) sdl->sdl_data;
289 tracef(" index %u type %u",
299 sockbuild_ll(0, dp, sdl->sdl_alen));
303 tracef(" selector %A",
304 sockbuild_ll(0, dp, sdl->sdl_slen));
308 #endif /* SOCKADDR_DL */
313 (byte *) ifrp->ifr_addr.sa_data,
314 (size_t) (size - ((byte *) ifrp->ifr_addr.sa_data - (byte *) &ifrp->ifr_addr))));
321 bzero((caddr_t) &ifi, sizeof (ifi));
323 bcopy(ifrp->ifr_name, if_name, IFNAMSIZ);
324 if_name[IFNAMSIZ] = (char) 0;
325 #if defined(SUNOS5_0) || defined(HPSTREAMS)
327 register char *cp = index(if_name, ':');
329 /* Remove the :n extension from the name */
334 #endif /* SUNOS5_0 || HPSTREAMS */
337 || strncmp(if_name, ifl->ifl_name, IFNAMSIZ)) {
342 /* And save for ioctls */
343 (void) strncpy(ifr->ifr_name, ifrp->ifr_name, IFNAMSIZ);
345 #if defined(SUNOS5_0) || defined(HPSTREAMS)
346 /* State, MTU and metric are associated with addresses, not the interface */
347 state = mtu = metric = 0;
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,
355 sizeof (*ifr)) < 0) {
359 ("krt_ifread: %s: ioctl SIOCGIFFLAGS: %m",
363 state = krt_if_flags(ifr->ifr_flags);
365 /* Get a resonable default */
366 mtu = krt_mtu(state);
369 /* Get interface MTU */
370 bzero ((caddr_t) &ifr->ifr_ifru, sizeof (ifr->ifr_ifru));
371 if (task_ioctl(tp->task_socket,
374 sizeof (*ifr)) < 0) {
378 ("krt_ifread: %s: ioctl SIOCGIFMTU: %m",
382 mtu = ifr->KRT_IFR_MTU;
384 #endif /* SIOCGIFMTU */
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,
393 sizeof (*ifr)) < 0) {
397 ("krt_ifread: %s: ioctl SIOCGIFMETRIC: %m",
401 metric = (ifr->ifr_metric >= 0) ? ifr->ifr_metric : 0;
402 #else /* defined(SIOCGIFMETRIC) && defined(ifr_metric) */
404 #endif /* defined(SIOCGIFMETRIC) && defined(ifr_metric) */
405 #endif /* SUNOS5_0 || HPSTREAMS */
410 register struct ifreq *ifrl = ifrp;
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. */
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 */
423 ifrl = (struct ifreq *) 0;
427 if (ifrl->ifr_addr.sa_family == AF_LINK) {
428 /* Found the AF_LINK entry */
434 if (ifrl && ((caddr_t) ifrl < limit)) {
435 struct sockaddr_dl *sdl = (struct sockaddr_dl *) &ifrl->ifr_addr;
439 /* We have an address */
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);
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 */
449 lladdr = krt_lladdr(ifr);
453 ifl_locate_index(sdl->sdl_index),
454 (indx = sdl->sdl_index),
459 (size_t) sdl->sdl_nlen,
462 #endif /* SOCKADDR_DL */
463 size_t n_len = strlen(if_name);
466 ifl_locate_name(if_name, n_len),
477 #endif /* SOCKADDR_DL */
479 if (TRACE_TP(tp, TR_KRT_IFLIST)) {
482 ("krt_ifread: %s index %d address %A",
488 ("krt_ifread: %s metric %u mtu %u state <%s>",
492 trace_bits(if_state_bits, ifl->ifl_state)));
494 #if defined(SUNOS5_0) || defined(HPSTREAMS)
496 /* Always copy the interface name to get address selector */
498 (void) strncpy(ifr->ifr_name, ifrp->ifr_name, IFNAMSIZ);
499 #endif /* SUNOS5_0 || HPSTREAMS */
502 bzero((caddr_t) &ifi, sizeof (ifi));
505 /* Reject unknown families */
506 switch (ifrp->ifr_addr.sa_family) {
510 #endif /* PROTO_INET */
515 #endif /* PROTO_ISO */
522 /* Copy the interface address */
523 ifi.ifi_addr_local = ifi.ifi_addr = sockdup(sock2gated(&ifrp->ifr_addr, unix_socksize(&ifrp->ifr_addr)));
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,
531 sizeof (*ifr)) < 0) {
535 ("krt_ifread: %s: ioctl SIOCGIFFLAGS: %m",
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 */
543 BIT_SET(ifl->ifl_state, IFS_LOOPBACK);
546 /* Get interface MTU */
547 bzero ((caddr_t) &ifr->ifr_ifru, sizeof (ifr->ifr_ifru));
548 if (task_ioctl(tp->task_socket,
551 sizeof (*ifr)) < 0) {
556 ("krt_ifread: %s: ioctl SIOCGIFMTU: %m",
560 /* Figure out a default */
561 ifi.ifi_mtu = krt_mtu(ifi.ifi_state);
563 ifi.ifi_mtu = ifr->KRT_IFR_MTU;
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,
571 sizeof (*ifr)) < 0) {
575 ("krt_ifread: %s: ioctl SIOCGIFMETRIC: %m",
579 ifi.ifi_metric = (ifr->ifr_metric >= 0) ? ifr->ifr_metric : 0;
580 #else /* SUNOS5_0 || HPSTREAMS */
581 /* Inherit parameters from physical interface */
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 */
588 /* What we do next depends on the family */
589 switch (ifrp->ifr_addr.sa_family) {
592 /* Specify the right socket for this family */
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),
598 task_state = save_task_state;
601 if (BIT_TEST(ifi.ifi_state, IFS_POINTOPOINT)) {
602 siocgifdstaddr = (u_long) SIOCGIFDSTADDR;
604 #ifdef SIOCGIFNETMASK
605 if (!BIT_TEST(ifi.ifi_state, IFS_LOOPBACK)) {
606 siocgifnetmask = (u_long) SIOCGIFNETMASK;
607 #endif /* SIOCGIFNETMASK */
609 if (BIT_TEST(ifi.ifi_state, IFS_BROADCAST)) {
610 siocgifbrdaddr = (u_long) SIOCGIFBRDADDR;
613 #endif /* PROTO_INET */
617 /* Specify the right socket for this family */
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),
623 task_state = save_task_state;
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;
632 #endif /* PROTO_ISO */
638 if (siocgifdstaddr) {
639 /* Get the destination address for point-to-point interfaces */
643 bzero ((caddr_t) &ifr->ifr_ifru, sizeof (ifr->ifr_ifru));
647 sizeof (*ifr)) < 0) {
651 ("krt_ifread: %s: ioctl SIOCGIFDSTADDR: %m",
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);
659 ifi.ifi_addr = (sockaddr_un *) 0;
662 #ifdef SIOCGIFNETMASK
663 if (siocgifnetmask) {
664 bzero ((caddr_t) &ifr->ifr_ifru, sizeof (ifr->ifr_ifru));
668 sizeof (*ifr)) < 0) {
672 ("krt_ifread: %s: ioctl SIOCGIFNETMASK: %m",
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 */
681 /* Masks don't have an address family specified */
682 if (ifr->ifr_addr.sa_family == AF_UNSPEC
684 ifr->ifr_addr.sa_family = socktype(ifi.ifi_addr);
686 #endif /* SOCKET_LENGTHS */
687 /* Convert the mask */
688 ifi.ifi_netmask = sock2gated(&ifr->ifr_addr, unix_socksize(&ifr->ifr_addr));
690 if (ifi.ifi_netmask) {
691 /* We have a mask, get pointer to right one */
692 ifi.ifi_netmask = mask_locate(ifi.ifi_netmask);
695 #else /* SIOCGIFNETMASK */
696 ifi.ifi_netmask = (sockaddr_un *) 0;
697 #endif /* SIOCGIFNETMASK */
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));
710 sizeof (*ifr)) < 0) {
714 ("krt_ifread: %s: ioctl SIOGIFBRDADDR: %m",
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);
725 ("krt_ifread: no broadcast address for %A (%s)",
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 */
736 if (TRACE_TP(tp, TR_KRT_IFLIST)) {
737 tracef("krt_ifread: %s %A",
740 if (ifi.ifi_netmask) {
744 if (ifi.ifi_addr_broadcast) {
746 ifi.ifi_addr_broadcast);
747 } else if (ifi.ifi_addr != ifi.ifi_addr_local) {
756 ("krt_ifread: %s metric %u mtu %u state <%s>",
760 trace_bits(if_state_bits, ifi.ifi_state)));
763 /* And add the interface */
764 if_conf_addaddr(tp, &ifi);
768 /* Free any allocated addresses */
777 if_conf_close(tp, FALSE);