1 1.23 nat /* $NetBSD: af_inetany.c,v 1.23 2022/08/17 23:36:48 nat Exp $ */ 2 1.1 dyoung 3 1.7 dyoung /*- 4 1.7 dyoung * Copyright (c) 2008 David Young. All rights reserved. 5 1.1 dyoung * 6 1.1 dyoung * Redistribution and use in source and binary forms, with or without 7 1.1 dyoung * modification, are permitted provided that the following conditions 8 1.1 dyoung * are met: 9 1.1 dyoung * 1. Redistributions of source code must retain the above copyright 10 1.1 dyoung * notice, this list of conditions and the following disclaimer. 11 1.1 dyoung * 2. Redistributions in binary form must reproduce the above copyright 12 1.1 dyoung * notice, this list of conditions and the following disclaimer in the 13 1.1 dyoung * documentation and/or other materials provided with the distribution. 14 1.1 dyoung * 15 1.7 dyoung * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 1.1 dyoung * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 1.1 dyoung * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 1.7 dyoung * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 1.1 dyoung * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 1.1 dyoung * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 1.1 dyoung * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 1.1 dyoung * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 1.1 dyoung * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 1.7 dyoung * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 1.1 dyoung * SUCH DAMAGE. 26 1.1 dyoung */ 27 1.1 dyoung 28 1.1 dyoung #include <sys/cdefs.h> 29 1.1 dyoung #ifndef lint 30 1.23 nat __RCSID("$NetBSD: af_inetany.c,v 1.23 2022/08/17 23:36:48 nat Exp $"); 31 1.1 dyoung #endif /* not lint */ 32 1.1 dyoung 33 1.18 msaitoh #include <sys/param.h> 34 1.18 msaitoh #include <sys/ioctl.h> 35 1.1 dyoung #include <sys/socket.h> 36 1.1 dyoung 37 1.18 msaitoh #include <net/if.h> 38 1.1 dyoung #include <netinet/in.h> 39 1.1 dyoung #include <netinet/in_var.h> 40 1.1 dyoung #include <netinet6/nd6.h> 41 1.1 dyoung 42 1.1 dyoung #include <arpa/inet.h> 43 1.1 dyoung 44 1.1 dyoung #include <assert.h> 45 1.1 dyoung #include <err.h> 46 1.1 dyoung #include <errno.h> 47 1.1 dyoung #include <ifaddrs.h> 48 1.1 dyoung #include <netdb.h> 49 1.1 dyoung #include <string.h> 50 1.1 dyoung #include <stdlib.h> 51 1.1 dyoung #include <stdio.h> 52 1.1 dyoung #include <util.h> 53 1.1 dyoung 54 1.1 dyoung #include "env.h" 55 1.1 dyoung #include "extern.h" 56 1.5 dyoung #include "af_inetany.h" 57 1.13 pooka #include "prog_ops.h" 58 1.2 dyoung 59 1.1 dyoung static void * 60 1.12 dyoung loadbuf(const struct apbuf *b, const struct paddr_prefix *pfx) 61 1.1 dyoung { 62 1.1 dyoung return memcpy(b->buf, &pfx->pfx_addr, 63 1.1 dyoung MIN(b->buflen, pfx->pfx_addr.sa_len)); 64 1.1 dyoung } 65 1.1 dyoung 66 1.1 dyoung void 67 1.5 dyoung commit_address(prop_dictionary_t env, prop_dictionary_t oenv, 68 1.12 dyoung const struct afparam *param) 69 1.1 dyoung { 70 1.1 dyoung const char *ifname; 71 1.1 dyoung int af, rc, s; 72 1.4 dyoung bool alias, delete, replace; 73 1.1 dyoung prop_data_t d; 74 1.1 dyoung const struct paddr_prefix *addr, *brd, *dst, *mask; 75 1.1 dyoung unsigned short flags; 76 1.1 dyoung 77 1.1 dyoung if ((af = getaf(env)) == -1) 78 1.1 dyoung af = AF_INET; 79 1.1 dyoung 80 1.1 dyoung if ((s = getsock(af)) == -1) 81 1.1 dyoung err(EXIT_FAILURE, "%s: getsock", __func__); 82 1.1 dyoung 83 1.16 christos if ((ifname = getifname(env)) == NULL) 84 1.17 christos err(EXIT_FAILURE, "%s: getifname", __func__); 85 1.1 dyoung 86 1.9 dyoung strlcpy(param->name[0].buf, ifname, param->name[0].buflen); 87 1.9 dyoung strlcpy(param->name[1].buf, ifname, param->name[1].buflen); 88 1.9 dyoung 89 1.1 dyoung if ((d = (prop_data_t)prop_dictionary_get(env, "address")) != NULL) 90 1.19 thorpej addr = prop_data_value(d); 91 1.23 nat else if (!prop_dictionary_get_bool(env, "alias", &alias) || alias || 92 1.23 nat param->gifaddr.cmd == 0) 93 1.21 nat return; 94 1.13 pooka else if (prog_ioctl(s, param->gifaddr.cmd, param->dgreq.buf) == -1) 95 1.14 joerg err(EXIT_FAILURE, "%s", param->gifaddr.desc); 96 1.13 pooka else if (prog_ioctl(s, param->difaddr.cmd, param->dgreq.buf) == -1) 97 1.14 joerg err(EXIT_FAILURE, "%s", param->difaddr.desc); 98 1.1 dyoung else 99 1.1 dyoung return; 100 1.1 dyoung 101 1.1 dyoung if ((d = (prop_data_t)prop_dictionary_get(env, "dst")) != NULL) 102 1.19 thorpej dst = prop_data_value(d); 103 1.1 dyoung else 104 1.1 dyoung dst = NULL; 105 1.1 dyoung 106 1.1 dyoung if ((d = (prop_data_t)prop_dictionary_get(env, "netmask")) != NULL) 107 1.19 thorpej mask = prop_data_value(d); 108 1.1 dyoung else 109 1.1 dyoung mask = NULL; 110 1.1 dyoung 111 1.1 dyoung if ((d = (prop_data_t)prop_dictionary_get(env, "broadcast")) != NULL) 112 1.19 thorpej brd = prop_data_value(d); 113 1.1 dyoung else 114 1.1 dyoung brd = NULL; 115 1.1 dyoung 116 1.4 dyoung if (!prop_dictionary_get_bool(env, "alias", &alias)) { 117 1.1 dyoung delete = false; 118 1.2 dyoung replace = (param->gifaddr.cmd != 0); 119 1.1 dyoung } else { 120 1.1 dyoung replace = false; 121 1.4 dyoung delete = !alias; 122 1.1 dyoung } 123 1.1 dyoung 124 1.1 dyoung loadbuf(¶m->addr, addr); 125 1.1 dyoung 126 1.1 dyoung /* TBD: read matching ifaddr from kernel, use the netmask as default 127 1.1 dyoung * TBD: handle preference 128 1.1 dyoung */ 129 1.16 christos if (getifflags(env, oenv, &flags) == -1) 130 1.16 christos err(EXIT_FAILURE, "%s: getifflags", __func__); 131 1.16 christos 132 1.1 dyoung switch (flags & (IFF_BROADCAST|IFF_POINTOPOINT)) { 133 1.8 dyoung case IFF_BROADCAST: 134 1.8 dyoung if (brd != NULL) 135 1.8 dyoung loadbuf(¶m->brd, brd); 136 1.10 dyoung /*FALLTHROUGH*/ 137 1.1 dyoung case 0: 138 1.1 dyoung break; 139 1.1 dyoung case IFF_POINTOPOINT: 140 1.1 dyoung if (brd != NULL) { 141 1.1 dyoung errx(EXIT_FAILURE, "%s is not a broadcast interface", 142 1.1 dyoung ifname); 143 1.1 dyoung } 144 1.12 dyoung if (dst != NULL) 145 1.12 dyoung loadbuf(¶m->dst, dst); 146 1.1 dyoung break; 147 1.1 dyoung case IFF_BROADCAST|IFF_POINTOPOINT: 148 1.1 dyoung errx(EXIT_FAILURE, "unsupported interface flags"); 149 1.1 dyoung } 150 1.12 dyoung if (param->mask.buf == NULL) { 151 1.12 dyoung if (mask != NULL) 152 1.12 dyoung errx(EXIT_FAILURE, "netmask not supported"); 153 1.12 dyoung } else if (mask != NULL) 154 1.11 dyoung loadbuf(¶m->mask, mask); 155 1.11 dyoung else if (param->defmask.buf != NULL) { 156 1.11 dyoung memcpy(param->mask.buf, param->defmask.buf, 157 1.11 dyoung MIN(param->mask.buflen, param->defmask.buflen)); 158 1.11 dyoung } 159 1.1 dyoung if (replace) { 160 1.13 pooka if (prog_ioctl(s, param->gifaddr.cmd, param->dgreq.buf) == 0) { 161 1.13 pooka rc = prog_ioctl(s, param->difaddr.cmd, param->dgreq.buf); 162 1.1 dyoung if (rc == -1) 163 1.14 joerg err(EXIT_FAILURE, "%s", param->difaddr.desc); 164 1.1 dyoung } else if (errno == EADDRNOTAVAIL) 165 1.1 dyoung ; /* No address was assigned yet. */ 166 1.1 dyoung else 167 1.14 joerg err(EXIT_FAILURE, "%s", param->gifaddr.desc); 168 1.1 dyoung } else if (delete) { 169 1.1 dyoung loadbuf(¶m->dgaddr, addr); 170 1.13 pooka if (prog_ioctl(s, param->difaddr.cmd, param->dgreq.buf) == -1) 171 1.14 joerg err(EXIT_FAILURE, "%s", param->difaddr.desc); 172 1.1 dyoung return; 173 1.1 dyoung } 174 1.2 dyoung if (param->pre_aifaddr != NULL && 175 1.2 dyoung (*param->pre_aifaddr)(env, param) == -1) 176 1.2 dyoung err(EXIT_FAILURE, "pre-%s", param->aifaddr.desc); 177 1.13 pooka if (prog_ioctl(s, param->aifaddr.cmd, param->req.buf) == -1) 178 1.14 joerg err(EXIT_FAILURE, "%s", param->aifaddr.desc); 179 1.1 dyoung } 180