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