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