Home | History | Annotate | Line # | Download | only in common
      1 /*	$NetBSD: socket.c,v 1.5 2022/04/03 01:10:58 christos Exp $	*/
      2 
      3 /* socket.c
      4 
      5    BSD socket interface code... */
      6 
      7 /*
      8  * Copyright (C) 2004-2022 Internet Systems Consortium, Inc. ("ISC")
      9  * Copyright (c) 1995-2003 by Internet Software Consortium
     10  *
     11  * This Source Code Form is subject to the terms of the Mozilla Public
     12  * License, v. 2.0. If a copy of the MPL was not distributed with this
     13  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
     16  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     17  * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
     18  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     19  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     20  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
     21  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     22  *
     23  *   Internet Systems Consortium, Inc.
     24  *   PO Box 360
     25  *   Newmarket, NH 03857 USA
     26  *   <info (at) isc.org>
     27  *   https://www.isc.org/
     28  *
     29  */
     30 
     31 #include <sys/cdefs.h>
     32 __RCSID("$NetBSD: socket.c,v 1.5 2022/04/03 01:10:58 christos Exp $");
     33 
     34 /* SO_BINDTODEVICE support added by Elliot Poger (poger (at) leland.stanford.edu).
     35  * This sockopt allows a socket to be bound to a particular interface,
     36  * thus enabling the use of DHCPD on a multihomed host.
     37  * If SO_BINDTODEVICE is defined in your system header files, the use of
     38  * this sockopt will be automatically enabled.
     39  * I have implemented it under Linux; other systems should be doable also.
     40  */
     41 
     42 #include "dhcpd.h"
     43 #include <isc/util.h>
     44 #include <errno.h>
     45 #include <sys/ioctl.h>
     46 #include <sys/uio.h>
     47 #include <sys/uio.h>
     48 
     49 #if defined(sun) && defined(USE_V4_PKTINFO)
     50 #include <sys/sysmacros.h>
     51 #include <net/if.h>
     52 #include <sys/sockio.h>
     53 #include <net/if_dl.h>
     54 #include <sys/dlpi.h>
     55 #endif
     56 
     57 #ifdef USE_SOCKET_FALLBACK
     58 # if !defined (USE_SOCKET_SEND)
     59 #  define if_register_send if_register_fallback
     60 #  define send_packet send_fallback
     61 #  define if_reinitialize_send if_reinitialize_fallback
     62 # endif
     63 #endif
     64 
     65 #if defined(DHCPv6)
     66 /*
     67  * XXX: this is gross.  we need to go back and overhaul the API for socket
     68  * handling.
     69  */
     70 static int no_global_v6_socket = 0;
     71 static unsigned int global_v6_socket_references = 0;
     72 static int global_v6_socket = -1;
     73 #if defined(RELAY_PORT)
     74 static unsigned int relay_port_v6_socket_references = 0;
     75 static int relay_port_v6_socket = -1;
     76 #endif
     77 
     78 static void if_register_multicast(struct interface_info *info);
     79 #endif
     80 
     81 /*
     82  * We can use a single socket for AF_INET (similar to AF_INET6) on all
     83  * interfaces configured for DHCP if the system has support for IP_PKTINFO
     84  * and IP_RECVPKTINFO (for example Solaris 11).
     85  */
     86 #if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO)
     87 static unsigned int global_v4_socket_references = 0;
     88 static int global_v4_socket = -1;
     89 #endif
     90 
     91 /*
     92  * If we can't bind() to a specific interface, then we can only have
     93  * a single socket. This variable insures that we don't try to listen
     94  * on two sockets.
     95  */
     96 #if !defined(SO_BINDTODEVICE) && !defined(USE_FALLBACK)
     97 static int once = 0;
     98 #endif /* !defined(SO_BINDTODEVICE) && !defined(USE_FALLBACK) */
     99 
    100 /* Reinitializes the specified interface after an address change.   This
    101    is not required for packet-filter APIs. */
    102 
    103 #if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_FALLBACK)
    104 void if_reinitialize_send (info)
    105 	struct interface_info *info;
    106 {
    107 #if 0
    108 #ifndef USE_SOCKET_RECEIVE
    109 	once = 0;
    110 	close (info -> wfdesc);
    111 #endif
    112 	if_register_send (info);
    113 #endif
    114 }
    115 #endif
    116 
    117 #ifdef USE_SOCKET_RECEIVE
    118 void if_reinitialize_receive (info)
    119 	struct interface_info *info;
    120 {
    121 #if 0
    122 	once = 0;
    123 	close (info -> rfdesc);
    124 	if_register_receive (info);
    125 #endif
    126 }
    127 #endif
    128 
    129 #if defined (USE_SOCKET_SEND) || \
    130 	defined (USE_SOCKET_RECEIVE) || \
    131 		defined (USE_SOCKET_FALLBACK)
    132 /* Generic interface registration routine... */
    133 int
    134 if_register_socket(struct interface_info *info, int family,
    135 		   int *do_multicast, struct in6_addr *linklocal6)
    136 {
    137 	struct sockaddr_storage name;
    138 	int name_len;
    139 	int sock;
    140 	int flag;
    141 	int domain;
    142 #ifdef DHCPv6
    143 	struct sockaddr_in6 *addr6;
    144 #endif
    145 	struct sockaddr_in *addr;
    146 
    147 	/* INSIST((family == AF_INET) || (family == AF_INET6)); */
    148 
    149 #if !defined(SO_BINDTODEVICE) && !defined(USE_FALLBACK)
    150 	/* Make sure only one interface is registered. */
    151 	if (once) {
    152 		log_fatal ("The standard socket API can only support %s",
    153 		       "hosts with a single network interface.");
    154 	}
    155 	once = 1;
    156 #endif
    157 
    158 	/*
    159 	 * Set up the address we're going to bind to, depending on the
    160 	 * address family.
    161 	 */
    162 	memset(&name, 0, sizeof(name));
    163 	switch (family) {
    164 #ifdef DHCPv6
    165 	case AF_INET6:
    166 		addr6 = (struct sockaddr_in6 *)&name;
    167 		addr6->sin6_family = AF_INET6;
    168 		addr6->sin6_port = *libdhcp_callbacks.local_port;
    169 #if defined(RELAY_PORT)
    170 		if (relay_port &&
    171 		    ((info->flags & INTERFACE_STREAMS) == INTERFACE_UPSTREAM))
    172 			addr6->sin6_port = relay_port;
    173 #endif
    174 		/* A server feature */
    175 		if (bind_local_address6) {
    176 			memcpy(&addr6->sin6_addr,
    177 			       &local_address6,
    178 			       sizeof(addr6->sin6_addr));
    179 		}
    180 		/* A client feature */
    181 		if (linklocal6) {
    182 			memcpy(&addr6->sin6_addr,
    183 			       linklocal6,
    184 			       sizeof(addr6->sin6_addr));
    185 		}
    186 		if (IN6_IS_ADDR_LINKLOCAL(&addr6->sin6_addr)) {
    187 			addr6->sin6_scope_id = if_nametoindex(info->name);
    188 		}
    189 #ifdef HAVE_SA_LEN
    190 		addr6->sin6_len = sizeof(*addr6);
    191 #endif
    192 		name_len = sizeof(*addr6);
    193 		domain = PF_INET6;
    194 		if ((info->flags & INTERFACE_STREAMS) == INTERFACE_UPSTREAM) {
    195 			*do_multicast = 0;
    196 		}
    197 		break;
    198 #endif /* DHCPv6 */
    199 
    200 	case AF_INET:
    201 	default:
    202 		addr = (struct sockaddr_in *)&name;
    203 		addr->sin_family = AF_INET;
    204 		addr->sin_port = relay_port ? relay_port : *libdhcp_callbacks.local_port;
    205 		memcpy(&addr->sin_addr,
    206 		       &local_address,
    207 		       sizeof(addr->sin_addr));
    208 #ifdef HAVE_SA_LEN
    209 		addr->sin_len = sizeof(*addr);
    210 #endif
    211 		name_len = sizeof(*addr);
    212 		domain = PF_INET;
    213 		break;
    214 	}
    215 
    216 	/* Make a socket... */
    217 	sock = socket(domain, SOCK_DGRAM, IPPROTO_UDP);
    218 	if (sock < 0) {
    219 		log_fatal("Can't create dhcp socket for %s: %m", info->name);
    220 	}
    221 
    222 	/* Set the REUSEADDR option so that we don't fail to start if
    223 	   we're being restarted. */
    224 	flag = 1;
    225 	if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
    226 			(char *)&flag, sizeof(flag)) < 0) {
    227 		log_fatal("Can't set SO_REUSEADDR on dhcp socket for"
    228 			  " %s: %m", info->name);
    229 	}
    230 
    231 	/* Set the BROADCAST option so that we can broadcast DHCP responses.
    232 	   We shouldn't do this for fallback devices, and we can detect that
    233 	   a device is a fallback because it has no ifp structure. */
    234 	if (info->ifp &&
    235 	    (setsockopt(sock, SOL_SOCKET, SO_BROADCAST,
    236 			 (char *)&flag, sizeof(flag)) < 0)) {
    237 		log_fatal("Can't set SO_BROADCAST on dhcp socket for"
    238 			  " %s: %m", info->name);
    239 	}
    240 
    241 #if defined(DHCPv6) && defined(SO_REUSEPORT)
    242 	/*
    243 	 * We only set SO_REUSEPORT on AF_INET6 sockets, so that multiple
    244 	 * daemons can bind to their own sockets and get data for their
    245 	 * respective interfaces.  This does not (and should not) affect
    246 	 * DHCPv4 sockets; we can't yet support BSD sockets well, much
    247 	 * less multiple sockets. Make sense only with multicast.
    248 	 * RedHat defines SO_REUSEPORT with a kernel which does not support
    249 	 * it and returns ENOPROTOOPT so in this case ignore the error.
    250 	 */
    251 	if ((local_family == AF_INET6) && *do_multicast) {
    252 		flag = 1;
    253 		if ((setsockopt(sock, SOL_SOCKET, SO_REUSEPORT,
    254 			        (char *)&flag, sizeof(flag)) < 0) &&
    255 		    (errno != ENOPROTOOPT)) {
    256 			log_fatal("Can't set SO_REUSEPORT on dhcp socket for"
    257 				  " %s: %m", info->name);
    258 		}
    259 	}
    260 #endif
    261 
    262 	/* Bind the socket to this interface's IP address. */
    263 	if (bind(sock, (struct sockaddr *)&name, name_len) < 0) {
    264 		log_error("Can't bind to dhcp address: %m");
    265 		log_error("Please make sure there is no other dhcp server");
    266 		log_error("running and that there's no entry for dhcp or");
    267 		log_error("bootp in /etc/inetd.conf.   Also make sure you");
    268 		log_error("are not running HP JetAdmin software, which");
    269 		log_fatal("includes a bootp server.");
    270 	}
    271 
    272 #if defined(SO_BINDTODEVICE)
    273 	/* Bind this socket to this interface. */
    274 	if ((local_family != AF_INET6) && (info->ifp != NULL) &&
    275 	    setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE,
    276 		       (char *)(info -> ifp), sizeof(*(info -> ifp))) < 0) {
    277 		log_fatal("Can't set SO_BINDTODEVICE on dhcp socket for"
    278 			  " %s : %m", (char *)(info->ifp));
    279 	}
    280 #endif
    281 
    282 	/* IP_BROADCAST_IF instructs the kernel which interface to send
    283 	 * IP packets whose destination address is 255.255.255.255.  These
    284 	 * will be treated as subnet broadcasts on the interface identified
    285 	 * by ip address (info -> primary_address).  This is only known to
    286 	 * be defined in SCO system headers, and may not be defined in all
    287 	 * releases.
    288 	 */
    289 #if defined(SCO) && defined(IP_BROADCAST_IF)
    290         if (info->address_count &&
    291 	    setsockopt(sock, IPPROTO_IP, IP_BROADCAST_IF, &info->addresses[0],
    292 		       sizeof(info->addresses[0])) < 0)
    293 		log_fatal("Can't set IP_BROADCAST_IF on dhcp socket for"
    294 			  " %s: %m", info->name);
    295 #endif
    296 
    297 #if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO)  && defined(USE_V4_PKTINFO)
    298 	/*
    299 	 * If we turn on IP_RECVPKTINFO we will be able to receive
    300 	 * the interface index information of the received packet.
    301 	 */
    302 	if (family == AF_INET) {
    303 		int on = 1;
    304 		if (setsockopt(sock, IPPROTO_IP, IP_RECVPKTINFO,
    305 		               &on, sizeof(on)) != 0) {
    306 			log_fatal("Can't set IP_RECVPTKINFO on dhcp socket for"
    307 				  " %s: %m", info->name);
    308 		}
    309 	}
    310 #endif
    311 
    312 #ifdef DHCPv6
    313 	/*
    314 	 * If we turn on IPV6_PKTINFO, we will be able to receive
    315 	 * additional information, such as the destination IP address.
    316 	 * We need this to spot unicast packets.
    317 	 */
    318 	if (family == AF_INET6) {
    319 		int on = 1;
    320 #ifdef IPV6_RECVPKTINFO
    321 		/* RFC3542 */
    322 		if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO,
    323 		               &on, sizeof(on)) != 0) {
    324 			log_fatal("setsockopt: IPV6_RECVPKTINFO for %s: %m",
    325 				  info->name);
    326 		}
    327 #else
    328 		/* RFC2292 */
    329 		if (setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO,
    330 		               &on, sizeof(on)) != 0) {
    331 			log_fatal("setsockopt: IPV6_PKTINFO for %s: %m",
    332 				  info->name);
    333 		}
    334 #endif
    335 	}
    336 
    337 #endif /* DHCPv6 */
    338 
    339 	return sock;
    340 }
    341 
    342 #ifdef DHCPv6
    343 void set_multicast_hop_limit(struct interface_info* info, int hop_limit) {
    344 	if (setsockopt(info->wfdesc, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
    345 		       &hop_limit, sizeof(int)) < 0) {
    346 		log_fatal("setsockopt: IPV6_MULTICAST_HOPS for %s: %m",
    347 			  info->name);
    348 	}
    349 
    350 	log_debug("Setting hop count limit to %d for interface %s",
    351 		  hop_limit, info->name);
    352 
    353 }
    354 #endif /* DHCPv6 */
    355 
    356 #endif /* USE_SOCKET_SEND || USE_SOCKET_RECEIVE || USE_SOCKET_FALLBACK */
    357 
    358 #if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_FALLBACK)
    359 void if_register_send (info)
    360 	struct interface_info *info;
    361 {
    362 #ifndef USE_SOCKET_RECEIVE
    363 	info->wfdesc = if_register_socket(info, AF_INET, 0, NULL);
    364 	/* If this is a normal IPv4 address, get the hardware address. */
    365 	if (strcmp(info->name, "fallback") != 0)
    366 		get_hw_addr(info->name, &info->hw_address);
    367 #if defined (USE_SOCKET_FALLBACK)
    368 	/* Fallback only registers for send, but may need to receive as
    369 	   well. */
    370 	info->rfdesc = info->wfdesc;
    371 #endif
    372 #else
    373 	info->wfdesc = info->rfdesc;
    374 #endif
    375 	if (!quiet_interface_discovery)
    376 		log_info ("Sending on   Socket/%s%s%s",
    377 		      info->name,
    378 		      (info->shared_network ? "/" : ""),
    379 		      (info->shared_network ?
    380 		       info->shared_network->name : ""));
    381 }
    382 
    383 #if defined (USE_SOCKET_SEND)
    384 void if_deregister_send (info)
    385 	struct interface_info *info;
    386 {
    387 #ifndef USE_SOCKET_RECEIVE
    388 	close (info -> wfdesc);
    389 #endif
    390 	info -> wfdesc = -1;
    391 
    392 	if (!quiet_interface_discovery)
    393 		log_info ("Disabling output on Socket/%s%s%s",
    394 		      info -> name,
    395 		      (info -> shared_network ? "/" : ""),
    396 		      (info -> shared_network ?
    397 		       info -> shared_network -> name : ""));
    398 }
    399 #endif /* USE_SOCKET_SEND */
    400 #endif /* USE_SOCKET_SEND || USE_SOCKET_FALLBACK */
    401 
    402 #ifdef USE_SOCKET_RECEIVE
    403 void if_register_receive (info)
    404 	struct interface_info *info;
    405 {
    406 
    407 #if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO)
    408 	if (global_v4_socket_references == 0) {
    409 		global_v4_socket = if_register_socket(info, AF_INET, 0, NULL);
    410 		if (global_v4_socket < 0) {
    411 			/*
    412 			 * if_register_socket() fatally logs if it fails to
    413 			 * create a socket, this is just a sanity check.
    414 			 */
    415 			log_fatal("Failed to create AF_INET socket %s:%d",
    416 				  MDL);
    417 		}
    418 	}
    419 
    420 	info->rfdesc = global_v4_socket;
    421 	global_v4_socket_references++;
    422 #else
    423 	/* If we're using the socket API for sending and receiving,
    424 	   we don't need to register this interface twice. */
    425 	info->rfdesc = if_register_socket(info, AF_INET, 0, NULL);
    426 #endif /* IP_PKTINFO... */
    427 	/* If this is a normal IPv4 address, get the hardware address. */
    428 	if (strcmp(info->name, "fallback") != 0)
    429 		get_hw_addr(info->name, &info->hw_address);
    430 
    431 	if (!quiet_interface_discovery)
    432 		log_info ("Listening on Socket/%s%s%s",
    433 		      info->name,
    434 		      (info->shared_network ? "/" : ""),
    435 		      (info->shared_network ?
    436 		       info->shared_network->name : ""));
    437 }
    438 
    439 void if_deregister_receive (info)
    440 	struct interface_info *info;
    441 {
    442 #if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO)
    443 	/* Dereference the global v4 socket. */
    444 	if ((info->rfdesc == global_v4_socket) &&
    445 	    (global_v4_socket_references > 0)) {
    446 		global_v4_socket_references--;
    447 		info->rfdesc = -1;
    448 	} else {
    449 		log_fatal("Impossible condition at %s:%d", MDL);
    450 	}
    451 
    452 	if (global_v4_socket_references == 0) {
    453 		close(global_v4_socket);
    454 		global_v4_socket = -1;
    455 	}
    456 #else
    457 	close(info->rfdesc);
    458 	info->rfdesc = -1;
    459 #endif /* IP_PKTINFO... */
    460 	if (!quiet_interface_discovery)
    461 		log_info ("Disabling input on Socket/%s%s%s",
    462 		      info -> name,
    463 		      (info -> shared_network ? "/" : ""),
    464 		      (info -> shared_network ?
    465 		       info -> shared_network -> name : ""));
    466 }
    467 #endif /* USE_SOCKET_RECEIVE */
    468 
    469 
    470 #ifdef DHCPv6
    471 /*
    472  * This function joins the interface to DHCPv6 multicast groups so we will
    473  * receive multicast messages.
    474  */
    475 static void
    476 if_register_multicast(struct interface_info *info) {
    477 	int sock = info->rfdesc;
    478 	struct ipv6_mreq mreq;
    479 
    480 	if (inet_pton(AF_INET6, All_DHCP_Relay_Agents_and_Servers,
    481 		      &mreq.ipv6mr_multiaddr) <= 0) {
    482 		log_fatal("inet_pton: unable to convert '%s'",
    483 			  All_DHCP_Relay_Agents_and_Servers);
    484 	}
    485 	mreq.ipv6mr_interface = if_nametoindex(info->name);
    486 	if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
    487 		       &mreq, sizeof(mreq)) < 0) {
    488 		log_fatal("setsockopt: IPV6_JOIN_GROUP for %s: %m",
    489 			  info->name);
    490 	}
    491 
    492 	/*
    493 	 * The relay agent code sets the streams so you know which way
    494 	 * is up and down.  But a relay agent shouldn't join to the
    495 	 * Server address, or else you get fun loops.  So up or down
    496 	 * doesn't matter, we're just using that config to sense this is
    497 	 * a relay agent.
    498 	 */
    499 	if ((info->flags & INTERFACE_STREAMS) == 0) {
    500 		if (inet_pton(AF_INET6, All_DHCP_Servers,
    501 			      &mreq.ipv6mr_multiaddr) <= 0) {
    502 			log_fatal("inet_pton: unable to convert '%s'",
    503 				  All_DHCP_Servers);
    504 		}
    505 		mreq.ipv6mr_interface = if_nametoindex(info->name);
    506 		if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
    507 			       &mreq, sizeof(mreq)) < 0) {
    508 			log_fatal("setsockopt: IPV6_JOIN_GROUP for %s: %m",
    509 				  info->name);
    510 		}
    511 	}
    512 }
    513 
    514 void
    515 if_register6(struct interface_info *info, int do_multicast) {
    516 	/* Bounce do_multicast to a stack variable because we may change it. */
    517 	int req_multi = do_multicast;
    518 
    519 	if (no_global_v6_socket) {
    520 		log_fatal("Impossible condition at %s:%d", MDL);
    521 	}
    522 
    523 #if defined(RELAY_PORT)
    524 	if (!relay_port ||
    525 	    ((info->flags & INTERFACE_STREAMS) == INTERFACE_DOWNSTREAM)) {
    526 #endif
    527 	if (global_v6_socket_references == 0) {
    528 		global_v6_socket = if_register_socket(info, AF_INET6,
    529 						      &req_multi, NULL);
    530 		if (global_v6_socket < 0) {
    531 			/*
    532 			 * if_register_socket() fatally logs if it fails to
    533 			 * create a socket, this is just a sanity check.
    534 			 */
    535 			log_fatal("Impossible condition at %s:%d", MDL);
    536 		} else if (bind_local_address6) {
    537 			char addr6_str[INET6_ADDRSTRLEN];
    538 
    539 			if (inet_ntop(AF_INET6,
    540 				      &local_address6,
    541 				      addr6_str,
    542 				      sizeof(addr6_str)) == NULL) {
    543 				log_fatal("inet_ntop: unable to convert "
    544 					  "local-address6");
    545 			}
    546 			log_info("Bound to [%s]:%d",
    547 				 addr6_str,
    548 				 (int) ntohs(*libdhcp_callbacks.local_port));
    549 		} else {
    550 			log_info("Bound to *:%d", (int) ntohs(*libdhcp_callbacks.local_port));
    551 		}
    552 	}
    553 
    554 	info->rfdesc = global_v6_socket;
    555 	info->wfdesc = global_v6_socket;
    556 	global_v6_socket_references++;
    557 
    558 #if defined(RELAY_PORT)
    559 	} else {
    560 	/*
    561 	 * If relay port is defined, we need to register one
    562 	 * IPv6 UPD socket to handle upstream server or relay agent
    563 	 * with a non-547 UDP local port.
    564 	 */
    565 	if ((relay_port_v6_socket_references == 0) &&
    566 	    ((info->flags & INTERFACE_STREAMS) == INTERFACE_UPSTREAM)) {
    567 		relay_port_v6_socket = if_register_socket(info, AF_INET6,
    568 							  &req_multi, NULL);
    569 		if (relay_port_v6_socket < 0) {
    570 			log_fatal("Impossible condition at %s:%d", MDL);
    571 		} else {
    572 			log_info("Bound to relay port *:%d",
    573 				 (int) ntohs(relay_port));
    574 		}
    575 	}
    576 	info->rfdesc = relay_port_v6_socket;
    577 	info->wfdesc = relay_port_v6_socket;
    578 	relay_port_v6_socket_references++;
    579 	}
    580 #endif
    581 
    582 	if (req_multi)
    583 		if_register_multicast(info);
    584 
    585 	get_hw_addr(info->name, &info->hw_address);
    586 
    587 	if (!quiet_interface_discovery) {
    588 		if (info->shared_network != NULL) {
    589 			log_info("Listening on Socket/%d/%s/%s",
    590 				 global_v6_socket, info->name,
    591 				 info->shared_network->name);
    592 			log_info("Sending on   Socket/%d/%s/%s",
    593 				 global_v6_socket, info->name,
    594 				 info->shared_network->name);
    595 		} else {
    596 			log_info("Listening on Socket/%s", info->name);
    597 			log_info("Sending on   Socket/%s", info->name);
    598 		}
    599 	}
    600 }
    601 
    602 /*
    603  * Register an IPv6 socket bound to the link-local address of
    604  * the argument interface (used by clients on a multiple interface box,
    605  * vs. a server or a relay using the global IPv6 socket and running
    606  * *only* in a single instance).
    607  */
    608 void
    609 if_register_linklocal6(struct interface_info *info) {
    610 	int sock;
    611 	int count;
    612 	struct in6_addr *addr6 = NULL;
    613 	int req_multi = 0;
    614 
    615 	if (global_v6_socket >= 0) {
    616 		log_fatal("Impossible condition at %s:%d", MDL);
    617 	}
    618 
    619 	no_global_v6_socket = 1;
    620 
    621 	/* get the (?) link-local address */
    622 	for (count = 0; count < info->v6address_count; count++) {
    623 		addr6 = &info->v6addresses[count];
    624 		if (IN6_IS_ADDR_LINKLOCAL(addr6))
    625 			break;
    626 	}
    627 
    628 	if (!addr6) {
    629 		log_fatal("no link-local IPv6 address for %s", info->name);
    630 	}
    631 
    632 	sock = if_register_socket(info, AF_INET6, &req_multi, addr6);
    633 
    634 	if (sock < 0) {
    635 		log_fatal("if_register_socket for %s fails", info->name);
    636 	}
    637 
    638 	info->rfdesc = sock;
    639 	info->wfdesc = sock;
    640 
    641 	get_hw_addr(info->name, &info->hw_address);
    642 
    643 	if (!quiet_interface_discovery) {
    644 		if (info->shared_network != NULL) {
    645 			log_info("Listening on Socket/%d/%s/%s",
    646 				 global_v6_socket, info->name,
    647 				 info->shared_network->name);
    648 			log_info("Sending on   Socket/%d/%s/%s",
    649 				 global_v6_socket, info->name,
    650 				 info->shared_network->name);
    651 		} else {
    652 			log_info("Listening on Socket/%s", info->name);
    653 			log_info("Sending on   Socket/%s", info->name);
    654 		}
    655 	}
    656 }
    657 
    658 void
    659 if_deregister6(struct interface_info *info) {
    660 	/* client case */
    661 	if (no_global_v6_socket) {
    662 		close(info->rfdesc);
    663 		info->rfdesc = -1;
    664 		info->wfdesc = -1;
    665 	} else if ((info->rfdesc == global_v6_socket) &&
    666 		   (info->wfdesc == global_v6_socket) &&
    667 		   (global_v6_socket_references > 0)) {
    668 		/* Dereference the global v6 socket. */
    669 		global_v6_socket_references--;
    670 		info->rfdesc = -1;
    671 		info->wfdesc = -1;
    672 #if defined(RELAY_PORT)
    673 	} else if (relay_port &&
    674 		   (info->rfdesc == relay_port_v6_socket) &&
    675 		   (info->wfdesc == relay_port_v6_socket) &&
    676 		   (relay_port_v6_socket_references > 0)) {
    677 		/* Dereference the relay port v6 socket. */
    678 		relay_port_v6_socket_references--;
    679 		info->rfdesc = -1;
    680 		info->wfdesc = -1;
    681 #endif
    682 	} else {
    683 		log_fatal("Impossible condition at %s:%d", MDL);
    684 	}
    685 
    686 	if (!quiet_interface_discovery) {
    687 		if (info->shared_network != NULL) {
    688 			log_info("Disabling input on  Socket/%s/%s", info->name,
    689 		       		 info->shared_network->name);
    690 			log_info("Disabling output on Socket/%s/%s", info->name,
    691 		       		 info->shared_network->name);
    692 		} else {
    693 			log_info("Disabling input on  Socket/%s", info->name);
    694 			log_info("Disabling output on Socket/%s", info->name);
    695 		}
    696 	}
    697 
    698 	if (!no_global_v6_socket) {
    699 		if (global_v6_socket_references == 0) {
    700 			close(global_v6_socket);
    701 			global_v6_socket = -1;
    702 
    703 			log_info("Unbound from *:%d",
    704 				 (int) ntohs(*libdhcp_callbacks.local_port));
    705 		}
    706 #if defined(RELAY_PORT)
    707 		if (relay_port && (relay_port_v6_socket_references == 0)) {
    708 			close(relay_port_v6_socket);
    709 			relay_port_v6_socket = -1;
    710 
    711 			log_info("Unbound from relay port *:%d",
    712 				 (int) ntohs(relay_port));
    713 		}
    714 #endif
    715 	}
    716 }
    717 #endif /* DHCPv6 */
    718 
    719 #if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_FALLBACK)
    720 ssize_t send_packet (interface, packet, raw, len, from, to, hto)
    721 	struct interface_info *interface;
    722 	struct packet *packet;
    723 	struct dhcp_packet *raw;
    724 	size_t len;
    725 	struct in_addr from;
    726 	struct sockaddr_in *to;
    727 	struct hardware *hto;
    728 {
    729 	int result;
    730 #ifdef IGNORE_HOSTUNREACH
    731 	int retry = 0;
    732 	do {
    733 #endif
    734 #if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO)
    735 		struct in_pktinfo pktinfo;
    736 
    737 		if (interface->ifp != NULL) {
    738 			memset(&pktinfo, 0, sizeof (pktinfo));
    739 			pktinfo.ipi_ifindex = interface->ifp->ifr_index;
    740 			if (setsockopt(interface->wfdesc, IPPROTO_IP,
    741 				       IP_PKTINFO, (char *)&pktinfo,
    742 				       sizeof(pktinfo)) < 0)
    743 				log_fatal("setsockopt: IP_PKTINFO for %s: %m",
    744 					  (char*)(interface->ifp));
    745 		}
    746 #endif
    747 		result = sendto (interface -> wfdesc, (char *)raw, len, 0,
    748 				 (struct sockaddr *)to, sizeof *to);
    749 #ifdef IGNORE_HOSTUNREACH
    750 	} while (to -> sin_addr.s_addr == htonl (INADDR_BROADCAST) &&
    751 		 result < 0 &&
    752 		 (errno == EHOSTUNREACH ||
    753 		  errno == ECONNREFUSED) &&
    754 		 retry++ < 10);
    755 #endif
    756 	if (result < 0) {
    757 		log_error ("send_packet: %m");
    758 		if (errno == ENETUNREACH)
    759 			log_error ("send_packet: please consult README file%s",
    760 				   " regarding broadcast address.");
    761 	}
    762 	return result;
    763 }
    764 
    765 #endif /* USE_SOCKET_SEND || USE_SOCKET_FALLBACK */
    766 
    767 #ifdef DHCPv6
    768 /*
    769  * Solaris 9 is missing the CMSG_LEN and CMSG_SPACE macros, so we will
    770  * synthesize them (based on the BIND 9 technique).
    771  */
    772 
    773 #ifndef CMSG_LEN
    774 static size_t CMSG_LEN(size_t len) {
    775 	size_t hdrlen;
    776 	/*
    777 	 * Cast NULL so that any pointer arithmetic performed by CMSG_DATA
    778 	 * is correct.
    779 	 */
    780 	hdrlen = (size_t)CMSG_DATA(((struct cmsghdr *)NULL));
    781 	return hdrlen + len;
    782 }
    783 #endif /* !CMSG_LEN */
    784 
    785 #ifndef CMSG_SPACE
    786 static size_t CMSG_SPACE(size_t len) {
    787 	struct msghdr msg;
    788 	struct cmsghdr *cmsgp;
    789 
    790 	/*
    791 	 * XXX: The buffer length is an ad-hoc value, but should be enough
    792 	 * in a practical sense.
    793 	 */
    794 	union {
    795 		struct cmsghdr cmsg_sizer;
    796 		u_int8_t pktinfo_sizer[sizeof(struct cmsghdr) + 1024];
    797 	} dummybuf;
    798 
    799 	memset(&msg, 0, sizeof(msg));
    800 	msg.msg_control = &dummybuf;
    801 	msg.msg_controllen = sizeof(dummybuf);
    802 
    803 	cmsgp = (struct cmsghdr *)&dummybuf;
    804 	cmsgp->cmsg_len = CMSG_LEN(len);
    805 
    806 	cmsgp = CMSG_NXTHDR(&msg, cmsgp);
    807 	if (cmsgp != NULL) {
    808 		return (char *)cmsgp - (char *)msg.msg_control;
    809 	} else {
    810 		return 0;
    811 	}
    812 }
    813 #endif /* !CMSG_SPACE */
    814 
    815 #endif /* DHCPv6 */
    816 
    817 #if defined(DHCPv6) || \
    818 	(defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && \
    819 	 defined(USE_V4_PKTINFO))
    820 /*
    821  * For both send_packet6() and receive_packet6() we need to allocate
    822  * space for the cmsg header information.  We do this once and reuse
    823  * the buffer.  We also need the control buf for send_packet() and
    824  * receive_packet() when we use a single socket and IP_PKTINFO to
    825  * send the packet out the correct interface.
    826  */
    827 static void   *control_buf = NULL;
    828 static size_t  control_buf_len = 0;
    829 
    830 static void
    831 allocate_cmsg_cbuf(void) {
    832 	control_buf_len = CMSG_SPACE(sizeof(struct in6_pktinfo));
    833 	control_buf = dmalloc(control_buf_len, MDL);
    834 	return;
    835 }
    836 #endif /* DHCPv6, IP_PKTINFO ... */
    837 
    838 #ifdef DHCPv6
    839 /*
    840  * For both send_packet6() and receive_packet6() we need to use the
    841  * sendmsg()/recvmsg() functions rather than the simpler send()/recv()
    842  * functions.
    843  *
    844  * In the case of send_packet6(), we need to do this in order to insure
    845  * that the reply packet leaves on the same interface that it arrived
    846  * on.
    847  *
    848  * In the case of receive_packet6(), we need to do this in order to
    849  * get the IP address the packet was sent to. This is used to identify
    850  * whether a packet is multicast or unicast.
    851  *
    852  * Helpful man pages: recvmsg, readv (talks about the iovec stuff), cmsg.
    853  *
    854  * Also see the sections in RFC 3542 about IPV6_PKTINFO.
    855  */
    856 
    857 /* Send an IPv6 packet */
    858 ssize_t send_packet6(struct interface_info *interface,
    859 		     const unsigned char *raw, size_t len,
    860 		     struct sockaddr_in6 *to) {
    861 	struct msghdr m;
    862 	struct iovec v;
    863 	struct sockaddr_in6 dst;
    864 	int result;
    865 	struct in6_pktinfo *pktinfo;
    866 	struct cmsghdr *cmsg;
    867 	unsigned int ifindex;
    868 
    869 	/*
    870 	 * If necessary allocate space for the control message header.
    871 	 * The space is common between send and receive.
    872 	 */
    873 
    874 	if (control_buf == NULL) {
    875 		allocate_cmsg_cbuf();
    876 		if (control_buf == NULL) {
    877 			log_error("send_packet6: unable to allocate cmsg header");
    878 			return(ENOMEM);
    879 		}
    880 	}
    881 	memset(control_buf, 0, control_buf_len);
    882 
    883 	/*
    884 	 * Initialize our message header structure.
    885 	 */
    886 	memset(&m, 0, sizeof(m));
    887 
    888 	/*
    889 	 * Set the target address we're sending to.
    890 	 * Enforce the scope ID for bogus BSDs.
    891 	 */
    892 	memcpy(&dst, to, sizeof(dst));
    893 	m.msg_name = &dst;
    894 	m.msg_namelen = sizeof(dst);
    895 	ifindex = if_nametoindex(interface->name);
    896 
    897 // Per OpenBSD patch-common_socket_c,v 1.7 2018/03/06 08:37:39 sthen Exp
    898 // always set the scope id.  We'll leave the test for no global socket
    899 // in place for all others.
    900 #ifndef __OpenBSD__
    901 	if (no_global_v6_socket)
    902 #endif
    903 		dst.sin6_scope_id = ifindex;
    904 
    905 	/*
    906 	 * Set the data buffer we're sending. (Using this wacky
    907 	 * "scatter-gather" stuff... we only have a single chunk
    908 	 * of data to send, so we declare a single vector entry.)
    909 	 */
    910 	v.iov_base = (char *)raw;
    911 	v.iov_len = len;
    912 	m.msg_iov = &v;
    913 	m.msg_iovlen = 1;
    914 
    915 	/*
    916 	 * Setting the interface is a bit more involved.
    917 	 *
    918 	 * We have to create a "control message", and set that to
    919 	 * define the IPv6 packet information. We could set the
    920 	 * source address if we wanted, but we can safely let the
    921 	 * kernel decide what that should be.
    922 	 */
    923 	m.msg_control = control_buf;
    924 	m.msg_controllen = control_buf_len;
    925 	cmsg = CMSG_FIRSTHDR(&m);
    926 	INSIST(cmsg != NULL);
    927 	cmsg->cmsg_level = IPPROTO_IPV6;
    928 	cmsg->cmsg_type = IPV6_PKTINFO;
    929 	cmsg->cmsg_len = CMSG_LEN(sizeof(*pktinfo));
    930 	pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg);
    931 	memset(pktinfo, 0, sizeof(*pktinfo));
    932 	pktinfo->ipi6_addr = local_address6;
    933 	pktinfo->ipi6_ifindex = ifindex;
    934 
    935 	result = sendmsg(interface->wfdesc, &m, 0);
    936 	if (result < 0) {
    937 		log_error("send_packet6: %m");
    938 	}
    939 	return result;
    940 }
    941 #endif /* DHCPv6 */
    942 
    943 #ifdef USE_SOCKET_RECEIVE
    944 ssize_t receive_packet (interface, buf, len, from, hfrom)
    945 	struct interface_info *interface;
    946 	unsigned char *buf;
    947 	size_t len;
    948 	struct sockaddr_in *from;
    949 	struct hardware *hfrom;
    950 {
    951 #if !(defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO))
    952 	SOCKLEN_T flen = sizeof *from;
    953 #endif
    954 	int result;
    955 
    956 	/*
    957 	 * The normal Berkeley socket interface doesn't give us any way
    958 	 * to know what hardware interface we received the message on,
    959 	 * but we should at least make sure the structure is emptied.
    960 	 */
    961 	memset(hfrom, 0, sizeof(*hfrom));
    962 
    963 #ifdef IGNORE_HOSTUNREACH
    964 	int retry = 0;
    965 	do {
    966 #endif
    967 
    968 #if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO)
    969 	struct msghdr m;
    970 	struct iovec v;
    971 	struct cmsghdr *cmsg;
    972 	struct in_pktinfo *pktinfo;
    973 	unsigned int ifindex;
    974 
    975 	/*
    976 	 * If necessary allocate space for the control message header.
    977 	 * The space is common between send and receive.
    978 	 */
    979 	if (control_buf == NULL) {
    980 		allocate_cmsg_cbuf();
    981 		if (control_buf == NULL) {
    982 			log_error("receive_packet: unable to allocate cmsg "
    983 				  "header");
    984 			return(ENOMEM);
    985 		}
    986 	}
    987 	memset(control_buf, 0, control_buf_len);
    988 
    989 	/*
    990 	 * Initialize our message header structure.
    991 	 */
    992 	memset(&m, 0, sizeof(m));
    993 
    994 	/*
    995 	 * Point so we can get the from address.
    996 	 */
    997 	m.msg_name = from;
    998 	m.msg_namelen = sizeof(*from);
    999 
   1000 	/*
   1001 	 * Set the data buffer we're receiving. (Using this wacky
   1002 	 * "scatter-gather" stuff... but we that doesn't really make
   1003 	 * sense for us, so we use a single vector entry.)
   1004 	 */
   1005 	v.iov_base = buf;
   1006 	v.iov_len = len;
   1007 	m.msg_iov = &v;
   1008 	m.msg_iovlen = 1;
   1009 
   1010 	/*
   1011 	 * Getting the interface is a bit more involved.
   1012 	 *
   1013 	 * We set up some space for a "control message". We have
   1014 	 * previously asked the kernel to give us packet
   1015 	 * information (when we initialized the interface), so we
   1016 	 * should get the interface index from that.
   1017 	 */
   1018 	m.msg_control = control_buf;
   1019 	m.msg_controllen = control_buf_len;
   1020 
   1021 	result = recvmsg(interface->rfdesc, &m, 0);
   1022 
   1023 	if (result >= 0) {
   1024 		/*
   1025 		 * If we did read successfully, then we need to loop
   1026 		 * through the control messages we received and
   1027 		 * find the one with our inteface index.
   1028 		 */
   1029 		cmsg = CMSG_FIRSTHDR(&m);
   1030 		while (cmsg != NULL) {
   1031 			if ((cmsg->cmsg_level == IPPROTO_IP) &&
   1032 			    (cmsg->cmsg_type == IP_PKTINFO)) {
   1033 				pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg);
   1034 				ifindex = pktinfo->ipi_ifindex;
   1035 				/*
   1036 				 * We pass the ifindex back to the caller
   1037 				 * using the unused hfrom parameter avoiding
   1038 				 * interface changes between sockets and
   1039 				 * the discover code.
   1040 				 */
   1041 				memcpy(hfrom->hbuf, &ifindex, sizeof(ifindex));
   1042 				return (result);
   1043 			}
   1044 			cmsg = CMSG_NXTHDR(&m, cmsg);
   1045 		}
   1046 
   1047 		/*
   1048 		 * We didn't find the necessary control message
   1049 		 * flag it as an error
   1050 		 */
   1051 		result = -1;
   1052 		errno = EIO;
   1053 	}
   1054 #else
   1055 		result = recvfrom(interface -> rfdesc, (char *)buf, len, 0,
   1056 				  (struct sockaddr *)from, &flen);
   1057 #endif /* IP_PKTINFO ... */
   1058 #ifdef IGNORE_HOSTUNREACH
   1059 	} while (result < 0 &&
   1060 		 (errno == EHOSTUNREACH ||
   1061 		  errno == ECONNREFUSED) &&
   1062 		 retry++ < 10);
   1063 #endif
   1064 	return (result);
   1065 }
   1066 
   1067 #endif /* USE_SOCKET_RECEIVE */
   1068 
   1069 #ifdef DHCPv6
   1070 ssize_t
   1071 receive_packet6(struct interface_info *interface,
   1072 		unsigned char *buf, size_t len,
   1073 		struct sockaddr_in6 *from, struct in6_addr *to_addr,
   1074 		unsigned int *if_idx)
   1075 {
   1076 	struct msghdr m;
   1077 	struct iovec v;
   1078 	int result;
   1079 	struct cmsghdr *cmsg;
   1080 	struct in6_pktinfo *pktinfo;
   1081 
   1082 	/*
   1083 	 * If necessary allocate space for the control message header.
   1084 	 * The space is common between send and receive.
   1085 	 */
   1086 	if (control_buf == NULL) {
   1087 		allocate_cmsg_cbuf();
   1088 		if (control_buf == NULL) {
   1089 			log_error("receive_packet6: unable to allocate cmsg "
   1090 				  "header");
   1091 			return(ENOMEM);
   1092 		}
   1093 	}
   1094 	memset(control_buf, 0, control_buf_len);
   1095 
   1096 	/*
   1097 	 * Initialize our message header structure.
   1098 	 */
   1099 	memset(&m, 0, sizeof(m));
   1100 
   1101 	/*
   1102 	 * Point so we can get the from address.
   1103 	 */
   1104 	m.msg_name = from;
   1105 	m.msg_namelen = sizeof(*from);
   1106 
   1107 	/*
   1108 	 * Set the data buffer we're receiving. (Using this wacky
   1109 	 * "scatter-gather" stuff... but we that doesn't really make
   1110 	 * sense for us, so we use a single vector entry.)
   1111 	 */
   1112 	v.iov_base = buf;
   1113 	v.iov_len = len;
   1114 	m.msg_iov = &v;
   1115 	m.msg_iovlen = 1;
   1116 
   1117 	/*
   1118 	 * Getting the interface is a bit more involved.
   1119 	 *
   1120 	 * We set up some space for a "control message". We have
   1121 	 * previously asked the kernel to give us packet
   1122 	 * information (when we initialized the interface), so we
   1123 	 * should get the destination address from that.
   1124 	 */
   1125 	m.msg_control = control_buf;
   1126 	m.msg_controllen = control_buf_len;
   1127 
   1128 	result = recvmsg(interface->rfdesc, &m, 0);
   1129 
   1130 	if (result >= 0) {
   1131 		/*
   1132 		 * If we did read successfully, then we need to loop
   1133 		 * through the control messages we received and
   1134 		 * find the one with our destination address.
   1135 		 */
   1136 		cmsg = CMSG_FIRSTHDR(&m);
   1137 		while (cmsg != NULL) {
   1138 			if ((cmsg->cmsg_level == IPPROTO_IPV6) &&
   1139 			    (cmsg->cmsg_type == IPV6_PKTINFO)) {
   1140 				pktinfo = (struct in6_pktinfo *)CMSG_DATA(cmsg);
   1141 				*to_addr = pktinfo->ipi6_addr;
   1142 				*if_idx = pktinfo->ipi6_ifindex;
   1143 
   1144 				return (result);
   1145 			}
   1146 			cmsg = CMSG_NXTHDR(&m, cmsg);
   1147 		}
   1148 
   1149 		/*
   1150 		 * We didn't find the necessary control message
   1151 		 * flag is as an error
   1152 		 */
   1153 		result = -1;
   1154 		errno = EIO;
   1155 	}
   1156 
   1157 	return (result);
   1158 }
   1159 #endif /* DHCPv6 */
   1160 
   1161 #if defined (USE_SOCKET_FALLBACK)
   1162 /* This just reads in a packet and silently discards it. */
   1163 
   1164 isc_result_t fallback_discard (object)
   1165 	omapi_object_t *object;
   1166 {
   1167 	char buf [1540];
   1168 	struct sockaddr_in from;
   1169 	SOCKLEN_T flen = sizeof from;
   1170 	int status;
   1171 	struct interface_info *interface;
   1172 
   1173 	if (object -> type != dhcp_type_interface)
   1174 		return DHCP_R_INVALIDARG;
   1175 	interface = (struct interface_info *)object;
   1176 
   1177 	status = recvfrom (interface -> wfdesc, buf, sizeof buf, 0,
   1178 			   (struct sockaddr *)&from, &flen);
   1179 #if defined (DEBUG)
   1180 	/* Only report fallback discard errors if we're debugging. */
   1181 	if (status < 0) {
   1182 		log_error ("fallback_discard: %m");
   1183 		return ISC_R_UNEXPECTED;
   1184 	}
   1185 #else
   1186         /* ignore the fact that status value is never used */
   1187         IGNORE_UNUSED(status);
   1188 #endif
   1189 	return ISC_R_SUCCESS;
   1190 }
   1191 #endif /* USE_SOCKET_FALLBACK */
   1192 
   1193 #if defined (USE_SOCKET_SEND)
   1194 int can_unicast_without_arp (ip)
   1195 	struct interface_info *ip;
   1196 {
   1197 	return 0;
   1198 }
   1199 
   1200 int can_receive_unicast_unconfigured (ip)
   1201 	struct interface_info *ip;
   1202 {
   1203 #if defined (SOCKET_CAN_RECEIVE_UNICAST_UNCONFIGURED)
   1204 	return 1;
   1205 #else
   1206 	return 0;
   1207 #endif
   1208 }
   1209 
   1210 int supports_multiple_interfaces (ip)
   1211 	struct interface_info *ip;
   1212 {
   1213 #if defined(SO_BINDTODEVICE) || \
   1214 	(defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && \
   1215 	 defined(USE_V4_PKTINFO))
   1216 	return(1);
   1217 #else
   1218 	return(0);
   1219 #endif
   1220 }
   1221 
   1222 /* If we have SO_BINDTODEVICE, set up a fallback interface; otherwise,
   1223    do not. */
   1224 
   1225 void maybe_setup_fallback ()
   1226 {
   1227 #if defined (USE_SOCKET_FALLBACK)
   1228 	isc_result_t status;
   1229 	struct interface_info *fbi = (struct interface_info *)0;
   1230 	if (setup_fallback (&fbi, MDL)) {
   1231 		fbi -> wfdesc = if_register_socket (fbi, AF_INET, 0, NULL);
   1232 		fbi -> rfdesc = fbi -> wfdesc;
   1233 		log_info ("Sending on   Socket/%s%s%s",
   1234 		      fbi -> name,
   1235 		      (fbi -> shared_network ? "/" : ""),
   1236 		      (fbi -> shared_network ?
   1237 		       fbi -> shared_network -> name : ""));
   1238 
   1239 		status = omapi_register_io_object ((omapi_object_t *)fbi,
   1240 						   if_readsocket, 0,
   1241 						   fallback_discard, 0, 0);
   1242 		if (status != ISC_R_SUCCESS)
   1243 			log_fatal ("Can't register I/O handle for %s: %s",
   1244 				   fbi -> name, isc_result_totext (status));
   1245 		interface_dereference (&fbi, MDL);
   1246 	}
   1247 #endif
   1248 }
   1249 
   1250 
   1251 #if defined(sun) && defined(USE_V4_PKTINFO)
   1252 /* This code assumes the existence of SIOCGLIFHWADDR */
   1253 void
   1254 get_hw_addr(const char *name, struct hardware *hw) {
   1255 	struct sockaddr_dl *dladdrp;
   1256 	int sock, i;
   1257 	struct lifreq lifr;
   1258 
   1259 	memset(&lifr, 0, sizeof (lifr));
   1260 	(void) strlcpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
   1261 	/*
   1262 	 * Check if the interface is a virtual or IPMP interface - in those
   1263 	 * cases it has no hw address, so generate a random one.
   1264 	 */
   1265 	if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ||
   1266 	    ioctl(sock, SIOCGLIFFLAGS, &lifr) < 0) {
   1267 		if (sock != -1)
   1268 			(void) close(sock);
   1269 
   1270 #ifdef DHCPv6
   1271 		/*
   1272 		 * If approrpriate try this with an IPv6 socket
   1273 		 */
   1274 		if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) >= 0 &&
   1275 		    ioctl(sock, SIOCGLIFFLAGS, &lifr) >= 0) {
   1276 			goto flag_check;
   1277 		}
   1278 		if (sock != -1)
   1279 			(void) close(sock);
   1280 #endif
   1281 		log_fatal("Couldn't get interface flags for %s: %m", name);
   1282 
   1283 	}
   1284 
   1285  flag_check:
   1286 	if (lifr.lifr_flags & (IFF_VIRTUAL|IFF_IPMP)) {
   1287 		hw->hlen = sizeof (hw->hbuf);
   1288 		srandom((long)gethrtime());
   1289 
   1290 		hw->hbuf[0] = HTYPE_IPMP;
   1291 		for (i = 1; i < hw->hlen; ++i) {
   1292 			hw->hbuf[i] = random() % 256;
   1293 		}
   1294 
   1295 		if (sock != -1)
   1296 			(void) close(sock);
   1297 		return;
   1298 	}
   1299 
   1300 	if (ioctl(sock, SIOCGLIFHWADDR, &lifr) < 0)
   1301 		log_fatal("Couldn't get interface hardware address for %s: %m",
   1302 			  name);
   1303 	dladdrp = (struct sockaddr_dl *)&lifr.lifr_addr;
   1304 	hw->hlen = dladdrp->sdl_alen+1;
   1305 	switch (dladdrp->sdl_type) {
   1306 		case DL_CSMACD: /* IEEE 802.3 */
   1307 		case DL_ETHER:
   1308 			hw->hbuf[0] = HTYPE_ETHER;
   1309 			break;
   1310 		case DL_TPR:
   1311 			hw->hbuf[0] = HTYPE_IEEE802;
   1312 			break;
   1313 		case DL_FDDI:
   1314 			hw->hbuf[0] = HTYPE_FDDI;
   1315 			break;
   1316 		case DL_IB:
   1317 			hw->hbuf[0] = HTYPE_INFINIBAND;
   1318 			break;
   1319 		default:
   1320 			log_fatal("%s: unsupported DLPI MAC type %lu", name,
   1321 				  (unsigned long)dladdrp->sdl_type);
   1322 	}
   1323 
   1324 	memcpy(hw->hbuf+1, LLADDR(dladdrp), hw->hlen-1);
   1325 
   1326 	if (sock != -1)
   1327 		(void) close(sock);
   1328 }
   1329 #endif /* defined(sun) */
   1330 
   1331 #endif /* USE_SOCKET_SEND */
   1332