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@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@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)
if_reinitialize_send(info)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
if_reinitialize_receive(info)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
if_register_socket(struct interface_info * info,int family,int * do_multicast,struct in6_addr * linklocal6)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
set_multicast_hop_limit(struct interface_info * info,int hop_limit)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)
if_register_send(info)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)
if_deregister_send(info)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
if_register_receive(info)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
if_deregister_receive(info)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
if_register_multicast(struct interface_info * info)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
if_register6(struct interface_info * info,int do_multicast)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
if_register_linklocal6(struct interface_info * info)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
if_deregister6(struct interface_info * info)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)
send_packet(interface,packet,raw,len,from,to,hto)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
CMSG_LEN(size_t 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
CMSG_SPACE(size_t len)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
allocate_cmsg_cbuf(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 */
send_packet6(struct interface_info * interface,const unsigned char * raw,size_t len,struct sockaddr_in6 * to)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
receive_packet(interface,buf,len,from,hfrom)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
receive_packet6(struct interface_info * interface,unsigned char * buf,size_t len,struct sockaddr_in6 * from,struct in6_addr * to_addr,unsigned int * if_idx)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
fallback_discard(object)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)
can_unicast_without_arp(ip)1194 int can_unicast_without_arp (ip)
1195 struct interface_info *ip;
1196 {
1197 return 0;
1198 }
1199
can_receive_unicast_unconfigured(ip)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
supports_multiple_interfaces(ip)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
maybe_setup_fallback()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
get_hw_addr(const char * name,struct hardware * hw)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