dhcp4o6.c revision 1.3 1 1.2 christos /* $NetBSD: dhcp4o6.c,v 1.3 2022/04/03 01:10:58 christos Exp $ */
2 1.1 christos
3 1.1 christos /* dhcp4o6.c
4 1.1 christos
5 1.1 christos DHCPv4 over DHCPv6 shared code... */
6 1.1 christos
7 1.1 christos /*
8 1.3 christos * Copyright (C) 2016-2022 Internet Systems Consortium, Inc. ("ISC")
9 1.1 christos *
10 1.1 christos * This Source Code Form is subject to the terms of the Mozilla Public
11 1.1 christos * License, v. 2.0. If a copy of the MPL was not distributed with this
12 1.1 christos * file, You can obtain one at http://mozilla.org/MPL/2.0/.
13 1.1 christos *
14 1.1 christos * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
15 1.1 christos * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16 1.1 christos * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
17 1.1 christos * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 1.1 christos * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 1.1 christos * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
20 1.1 christos * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 1.1 christos *
22 1.1 christos * Internet Systems Consortium, Inc.
23 1.3 christos * PO Box 360
24 1.3 christos * Newmarket, NH 03857 USA
25 1.1 christos * <info (at) isc.org>
26 1.1 christos * https://www.isc.org/
27 1.1 christos *
28 1.1 christos */
29 1.1 christos
30 1.1 christos #include <sys/cdefs.h>
31 1.2 christos __RCSID("$NetBSD: dhcp4o6.c,v 1.3 2022/04/03 01:10:58 christos Exp $");
32 1.1 christos
33 1.1 christos #include "dhcpd.h"
34 1.1 christos
35 1.1 christos #ifdef DHCP4o6
36 1.1 christos
37 1.1 christos int dhcp4o6_fd = -1;
38 1.1 christos omapi_object_t *dhcp4o6_object = NULL;
39 1.1 christos omapi_object_type_t *dhcp4o6_type = NULL;
40 1.1 christos
41 1.1 christos static int dhcp4o6_readsocket(omapi_object_t *);
42 1.1 christos
43 1.1 christos /*
44 1.1 christos * DHCPv4 over DHCPv6 Inter Process Communication setup
45 1.1 christos *
46 1.1 christos * A UDP socket is created between ::1 port and ::1 port + 1
47 1.1 christos * (port is given in network order, the DHCPv6 side is bound to port,
48 1.1 christos * the DHCPv4 side to port + 1. The socket descriptor is stored into
49 1.1 christos * dhcp4o6_fd and an OMAPI handler is registered. Any failure is fatal.)
50 1.1 christos */
51 1.1 christos void dhcp4o6_setup(u_int16_t port) {
52 1.1 christos struct sockaddr_in6 local6, remote6;
53 1.1 christos int flag;
54 1.1 christos isc_result_t status;
55 1.1 christos
56 1.1 christos /* Register DHCPv4 over DHCPv6 forwarding. */
57 1.1 christos memset(&local6, 0, sizeof(local6));
58 1.1 christos local6.sin6_family = AF_INET6;
59 1.1 christos if (local_family == AF_INET6)
60 1.1 christos local6.sin6_port = port;
61 1.1 christos else
62 1.1 christos local6.sin6_port = htons(ntohs(port) + 1);
63 1.1 christos local6.sin6_addr.s6_addr[15] = 1;
64 1.1 christos #ifdef HAVE_SA_LEN
65 1.1 christos local6.sin6_len = sizeof(local6);
66 1.1 christos #endif
67 1.1 christos memset(&remote6, 0, sizeof(remote6));
68 1.1 christos remote6.sin6_family = AF_INET6;
69 1.1 christos if (local_family == AF_INET6)
70 1.1 christos remote6.sin6_port = htons(ntohs(port) + 1);
71 1.1 christos else
72 1.1 christos remote6.sin6_port = port;
73 1.1 christos remote6.sin6_addr.s6_addr[15] = 1;
74 1.1 christos #ifdef HAVE_SA_LEN
75 1.1 christos remote6.sin6_len = sizeof(remote6);
76 1.1 christos #endif
77 1.1 christos
78 1.1 christos dhcp4o6_fd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
79 1.1 christos if (dhcp4o6_fd < 0)
80 1.1 christos log_fatal("Can't create dhcp4o6 socket: %m");
81 1.1 christos flag = 1;
82 1.1 christos if (setsockopt(dhcp4o6_fd, SOL_SOCKET, SO_REUSEADDR,
83 1.1 christos (char *)&flag, sizeof(flag)) < 0)
84 1.1 christos log_fatal("Can't set SO_REUSEADDR option "
85 1.1 christos "on dhcp4o6 socket: %m");
86 1.1 christos if (bind(dhcp4o6_fd,
87 1.1 christos (struct sockaddr *)&local6,
88 1.1 christos sizeof(local6)) < 0)
89 1.1 christos log_fatal("Can't bind dhcp4o6 socket: %m");
90 1.1 christos if (connect(dhcp4o6_fd,
91 1.1 christos (struct sockaddr *)&remote6,
92 1.1 christos sizeof(remote6)) < 0)
93 1.1 christos log_fatal("Can't connect dhcp4o6 socket: %m");
94 1.1 christos
95 1.1 christos /* Omapi stuff. */
96 1.1 christos /* TODO: add tracing support. */
97 1.1 christos status = omapi_object_type_register(&dhcp4o6_type,
98 1.1 christos "dhcp4o6",
99 1.1 christos 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
100 1.1 christos sizeof(*dhcp4o6_object),
101 1.1 christos 0, RC_MISC);
102 1.1 christos if (status != ISC_R_SUCCESS)
103 1.1 christos log_fatal("Can't register dhcp4o6 type: %s",
104 1.1 christos isc_result_totext(status));
105 1.1 christos status = omapi_object_allocate(&dhcp4o6_object, dhcp4o6_type, 0, MDL);
106 1.1 christos if (status != ISC_R_SUCCESS)
107 1.1 christos log_fatal("Can't allocate dhcp4o6 object: %s",
108 1.1 christos isc_result_totext(status));
109 1.1 christos status = omapi_register_io_object(dhcp4o6_object,
110 1.1 christos dhcp4o6_readsocket, 0,
111 1.1 christos dhcpv4o6_handler, 0, 0);
112 1.1 christos if (status != ISC_R_SUCCESS)
113 1.1 christos log_fatal("Can't register dhcp4o6 handle: %s",
114 1.1 christos isc_result_totext(status));
115 1.1 christos }
116 1.1 christos
117 1.1 christos static int dhcp4o6_readsocket(omapi_object_t *h) {
118 1.1 christos IGNORE_UNUSED(h);
119 1.1 christos return dhcp4o6_fd;
120 1.1 christos }
121 1.1 christos #endif /* DHCP4o6 */
122