/* dhcp4o6.c DHCPv4 over DHCPv6 shared code... */ /* * Copyright (C) 2016-2022 Internet Systems Consortium, Inc. ("ISC") * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. * * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Internet Systems Consortium, Inc. * PO Box 360 * Newmarket, NH 03857 USA * * https://www.isc.org/ * */ #include "dhcpd.h" #ifdef DHCP4o6 int dhcp4o6_fd = -1; omapi_object_t *dhcp4o6_object = NULL; omapi_object_type_t *dhcp4o6_type = NULL; static int dhcp4o6_readsocket(omapi_object_t *); /* * DHCPv4 over DHCPv6 Inter Process Communication setup * * A UDP socket is created between ::1 port and ::1 port + 1 * (port is given in network order, the DHCPv6 side is bound to port, * the DHCPv4 side to port + 1. The socket descriptor is stored into * dhcp4o6_fd and an OMAPI handler is registered. Any failure is fatal.) */ void dhcp4o6_setup(u_int16_t port) { struct sockaddr_in6 local6, remote6; int flag; isc_result_t status; /* Register DHCPv4 over DHCPv6 forwarding. */ memset(&local6, 0, sizeof(local6)); local6.sin6_family = AF_INET6; if (local_family == AF_INET6) local6.sin6_port = port; else local6.sin6_port = htons(ntohs(port) + 1); local6.sin6_addr.s6_addr[15] = 1; #ifdef HAVE_SA_LEN local6.sin6_len = sizeof(local6); #endif memset(&remote6, 0, sizeof(remote6)); remote6.sin6_family = AF_INET6; if (local_family == AF_INET6) remote6.sin6_port = htons(ntohs(port) + 1); else remote6.sin6_port = port; remote6.sin6_addr.s6_addr[15] = 1; #ifdef HAVE_SA_LEN remote6.sin6_len = sizeof(remote6); #endif dhcp4o6_fd = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP); if (dhcp4o6_fd < 0) log_fatal("Can't create dhcp4o6 socket: %m"); flag = 1; if (setsockopt(dhcp4o6_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&flag, sizeof(flag)) < 0) log_fatal("Can't set SO_REUSEADDR option " "on dhcp4o6 socket: %m"); if (bind(dhcp4o6_fd, (struct sockaddr *)&local6, sizeof(local6)) < 0) log_fatal("Can't bind dhcp4o6 socket: %m"); if (connect(dhcp4o6_fd, (struct sockaddr *)&remote6, sizeof(remote6)) < 0) log_fatal("Can't connect dhcp4o6 socket: %m"); /* Omapi stuff. */ /* TODO: add tracing support. */ status = omapi_object_type_register(&dhcp4o6_type, "dhcp4o6", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, sizeof(*dhcp4o6_object), 0, RC_MISC); if (status != ISC_R_SUCCESS) log_fatal("Can't register dhcp4o6 type: %s", isc_result_totext(status)); status = omapi_object_allocate(&dhcp4o6_object, dhcp4o6_type, 0, MDL); if (status != ISC_R_SUCCESS) log_fatal("Can't allocate dhcp4o6 object: %s", isc_result_totext(status)); status = omapi_register_io_object(dhcp4o6_object, dhcp4o6_readsocket, 0, dhcpv4o6_handler, 0, 0); if (status != ISC_R_SUCCESS) log_fatal("Can't register dhcp4o6 handle: %s", isc_result_totext(status)); } static int dhcp4o6_readsocket(omapi_object_t *h) { IGNORE_UNUSED(h); return dhcp4o6_fd; } #endif /* DHCP4o6 */