1*832dc76bSMariusz Zaborski /*- 2*832dc76bSMariusz Zaborski * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*832dc76bSMariusz Zaborski * 4*832dc76bSMariusz Zaborski * Copyright (c) 2020 Mariusz Zaborski <oshogbo@FreeBSD.org> 5*832dc76bSMariusz Zaborski * 6*832dc76bSMariusz Zaborski * Redistribution and use in source and binary forms, with or without 7*832dc76bSMariusz Zaborski * modification, are permitted provided that the following conditions 8*832dc76bSMariusz Zaborski * are met: 9*832dc76bSMariusz Zaborski * 1. Redistributions of source code must retain the above copyright 10*832dc76bSMariusz Zaborski * notice, this list of conditions and the following disclaimer. 11*832dc76bSMariusz Zaborski * 2. Redistributions in binary form must reproduce the above copyright 12*832dc76bSMariusz Zaborski * notice, this list of conditions and the following disclaimer in the 13*832dc76bSMariusz Zaborski * documentation and/or other materials provided with the distribution. 14*832dc76bSMariusz Zaborski * 15*832dc76bSMariusz Zaborski * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 16*832dc76bSMariusz Zaborski * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17*832dc76bSMariusz Zaborski * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18*832dc76bSMariusz Zaborski * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 19*832dc76bSMariusz Zaborski * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20*832dc76bSMariusz Zaborski * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21*832dc76bSMariusz Zaborski * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22*832dc76bSMariusz Zaborski * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23*832dc76bSMariusz Zaborski * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24*832dc76bSMariusz Zaborski * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25*832dc76bSMariusz Zaborski * SUCH DAMAGE. 26*832dc76bSMariusz Zaborski */ 27*832dc76bSMariusz Zaborski 28*832dc76bSMariusz Zaborski #include <sys/cdefs.h> 29*832dc76bSMariusz Zaborski __FBSDID("$FreeBSD$"); 30*832dc76bSMariusz Zaborski 31*832dc76bSMariusz Zaborski #include <sys/cnv.h> 32*832dc76bSMariusz Zaborski #include <sys/dnv.h> 33*832dc76bSMariusz Zaborski #include <sys/nv.h> 34*832dc76bSMariusz Zaborski #include <sys/socket.h> 35*832dc76bSMariusz Zaborski #include <netinet/in.h> 36*832dc76bSMariusz Zaborski 37*832dc76bSMariusz Zaborski #include <assert.h> 38*832dc76bSMariusz Zaborski #include <errno.h> 39*832dc76bSMariusz Zaborski #include <netdb.h> 40*832dc76bSMariusz Zaborski #include <stdio.h> 41*832dc76bSMariusz Zaborski #include <string.h> 42*832dc76bSMariusz Zaborski #include <unistd.h> 43*832dc76bSMariusz Zaborski 44*832dc76bSMariusz Zaborski #include <libcasper.h> 45*832dc76bSMariusz Zaborski #include <libcasper_service.h> 46*832dc76bSMariusz Zaborski 47*832dc76bSMariusz Zaborski #include "cap_net.h" 48*832dc76bSMariusz Zaborski 49*832dc76bSMariusz Zaborski #define CAPNET_MASK (CAPNET_ADDR2NAME | CAPNET_NAME2ADDR \ 50*832dc76bSMariusz Zaborski CAPNET_DEPRECATED_ADDR2NAME | CAPNET_DEPRECATED_NAME2ADDR | \ 51*832dc76bSMariusz Zaborski CAPNET_CONNECT | CAPNET_BIND | CAPNET_CONNECTDNS) 52*832dc76bSMariusz Zaborski 53*832dc76bSMariusz Zaborski /* 54*832dc76bSMariusz Zaborski * Defines for the names of the limits. 55*832dc76bSMariusz Zaborski * XXX: we should convert all string constats to this to avoid typos. 56*832dc76bSMariusz Zaborski */ 57*832dc76bSMariusz Zaborski #define LIMIT_NV_BIND "bind" 58*832dc76bSMariusz Zaborski #define LIMIT_NV_CONNECT "connect" 59*832dc76bSMariusz Zaborski #define LIMIT_NV_ADDR2NAME "addr2name" 60*832dc76bSMariusz Zaborski #define LIMIT_NV_NAME2ADDR "name2addr" 61*832dc76bSMariusz Zaborski 62*832dc76bSMariusz Zaborski struct cap_net_limit { 63*832dc76bSMariusz Zaborski cap_channel_t *cnl_chan; 64*832dc76bSMariusz Zaborski uint64_t cnl_mode; 65*832dc76bSMariusz Zaborski nvlist_t *cnl_addr2name; 66*832dc76bSMariusz Zaborski nvlist_t *cnl_name2addr; 67*832dc76bSMariusz Zaborski nvlist_t *cnl_connect; 68*832dc76bSMariusz Zaborski nvlist_t *cnl_bind; 69*832dc76bSMariusz Zaborski }; 70*832dc76bSMariusz Zaborski 71*832dc76bSMariusz Zaborski static struct hostent hent; 72*832dc76bSMariusz Zaborski 73*832dc76bSMariusz Zaborski static void 74*832dc76bSMariusz Zaborski hostent_free(struct hostent *hp) 75*832dc76bSMariusz Zaborski { 76*832dc76bSMariusz Zaborski unsigned int ii; 77*832dc76bSMariusz Zaborski 78*832dc76bSMariusz Zaborski free(hp->h_name); 79*832dc76bSMariusz Zaborski hp->h_name = NULL; 80*832dc76bSMariusz Zaborski if (hp->h_aliases != NULL) { 81*832dc76bSMariusz Zaborski for (ii = 0; hp->h_aliases[ii] != NULL; ii++) 82*832dc76bSMariusz Zaborski free(hp->h_aliases[ii]); 83*832dc76bSMariusz Zaborski free(hp->h_aliases); 84*832dc76bSMariusz Zaborski hp->h_aliases = NULL; 85*832dc76bSMariusz Zaborski } 86*832dc76bSMariusz Zaborski if (hp->h_addr_list != NULL) { 87*832dc76bSMariusz Zaborski for (ii = 0; hp->h_addr_list[ii] != NULL; ii++) 88*832dc76bSMariusz Zaborski free(hp->h_addr_list[ii]); 89*832dc76bSMariusz Zaborski free(hp->h_addr_list); 90*832dc76bSMariusz Zaborski hp->h_addr_list = NULL; 91*832dc76bSMariusz Zaborski } 92*832dc76bSMariusz Zaborski } 93*832dc76bSMariusz Zaborski 94*832dc76bSMariusz Zaborski static struct hostent * 95*832dc76bSMariusz Zaborski hostent_unpack(const nvlist_t *nvl, struct hostent *hp) 96*832dc76bSMariusz Zaborski { 97*832dc76bSMariusz Zaborski unsigned int ii, nitems; 98*832dc76bSMariusz Zaborski char nvlname[64]; 99*832dc76bSMariusz Zaborski int n; 100*832dc76bSMariusz Zaborski 101*832dc76bSMariusz Zaborski hostent_free(hp); 102*832dc76bSMariusz Zaborski 103*832dc76bSMariusz Zaborski hp->h_name = strdup(nvlist_get_string(nvl, "name")); 104*832dc76bSMariusz Zaborski if (hp->h_name == NULL) 105*832dc76bSMariusz Zaborski goto fail; 106*832dc76bSMariusz Zaborski hp->h_addrtype = (int)nvlist_get_number(nvl, "addrtype"); 107*832dc76bSMariusz Zaborski hp->h_length = (int)nvlist_get_number(nvl, "length"); 108*832dc76bSMariusz Zaborski 109*832dc76bSMariusz Zaborski nitems = (unsigned int)nvlist_get_number(nvl, "naliases"); 110*832dc76bSMariusz Zaborski hp->h_aliases = calloc(sizeof(hp->h_aliases[0]), nitems + 1); 111*832dc76bSMariusz Zaborski if (hp->h_aliases == NULL) 112*832dc76bSMariusz Zaborski goto fail; 113*832dc76bSMariusz Zaborski for (ii = 0; ii < nitems; ii++) { 114*832dc76bSMariusz Zaborski n = snprintf(nvlname, sizeof(nvlname), "alias%u", ii); 115*832dc76bSMariusz Zaborski assert(n > 0 && n < (int)sizeof(nvlname)); 116*832dc76bSMariusz Zaborski hp->h_aliases[ii] = 117*832dc76bSMariusz Zaborski strdup(nvlist_get_string(nvl, nvlname)); 118*832dc76bSMariusz Zaborski if (hp->h_aliases[ii] == NULL) 119*832dc76bSMariusz Zaborski goto fail; 120*832dc76bSMariusz Zaborski } 121*832dc76bSMariusz Zaborski hp->h_aliases[ii] = NULL; 122*832dc76bSMariusz Zaborski 123*832dc76bSMariusz Zaborski nitems = (unsigned int)nvlist_get_number(nvl, "naddrs"); 124*832dc76bSMariusz Zaborski hp->h_addr_list = calloc(sizeof(hp->h_addr_list[0]), nitems + 1); 125*832dc76bSMariusz Zaborski if (hp->h_addr_list == NULL) 126*832dc76bSMariusz Zaborski goto fail; 127*832dc76bSMariusz Zaborski for (ii = 0; ii < nitems; ii++) { 128*832dc76bSMariusz Zaborski hp->h_addr_list[ii] = malloc(hp->h_length); 129*832dc76bSMariusz Zaborski if (hp->h_addr_list[ii] == NULL) 130*832dc76bSMariusz Zaborski goto fail; 131*832dc76bSMariusz Zaborski n = snprintf(nvlname, sizeof(nvlname), "addr%u", ii); 132*832dc76bSMariusz Zaborski assert(n > 0 && n < (int)sizeof(nvlname)); 133*832dc76bSMariusz Zaborski bcopy(nvlist_get_binary(nvl, nvlname, NULL), 134*832dc76bSMariusz Zaborski hp->h_addr_list[ii], hp->h_length); 135*832dc76bSMariusz Zaborski } 136*832dc76bSMariusz Zaborski hp->h_addr_list[ii] = NULL; 137*832dc76bSMariusz Zaborski 138*832dc76bSMariusz Zaborski return (hp); 139*832dc76bSMariusz Zaborski fail: 140*832dc76bSMariusz Zaborski hostent_free(hp); 141*832dc76bSMariusz Zaborski h_errno = NO_RECOVERY; 142*832dc76bSMariusz Zaborski return (NULL); 143*832dc76bSMariusz Zaborski } 144*832dc76bSMariusz Zaborski 145*832dc76bSMariusz Zaborski static int 146*832dc76bSMariusz Zaborski request_cb(cap_channel_t *chan, const char *name, int s, 147*832dc76bSMariusz Zaborski const struct sockaddr *saddr, socklen_t len) 148*832dc76bSMariusz Zaborski { 149*832dc76bSMariusz Zaborski nvlist_t *nvl; 150*832dc76bSMariusz Zaborski int serrno; 151*832dc76bSMariusz Zaborski 152*832dc76bSMariusz Zaborski nvl = nvlist_create(0); 153*832dc76bSMariusz Zaborski nvlist_add_string(nvl, "cmd", name); 154*832dc76bSMariusz Zaborski nvlist_add_descriptor(nvl, "s", s); 155*832dc76bSMariusz Zaborski nvlist_add_binary(nvl, "saddr", saddr, len); 156*832dc76bSMariusz Zaborski 157*832dc76bSMariusz Zaborski nvl = cap_xfer_nvlist(chan, nvl); 158*832dc76bSMariusz Zaborski if (nvl == NULL) 159*832dc76bSMariusz Zaborski return (-1); 160*832dc76bSMariusz Zaborski 161*832dc76bSMariusz Zaborski if (nvlist_get_number(nvl, "error") != 0) { 162*832dc76bSMariusz Zaborski serrno = (int)nvlist_get_number(nvl, "error"); 163*832dc76bSMariusz Zaborski nvlist_destroy(nvl); 164*832dc76bSMariusz Zaborski errno = serrno; 165*832dc76bSMariusz Zaborski return (-1); 166*832dc76bSMariusz Zaborski } 167*832dc76bSMariusz Zaborski 168*832dc76bSMariusz Zaborski s = dup2(s, nvlist_get_descriptor(nvl, "s")); 169*832dc76bSMariusz Zaborski nvlist_destroy(nvl); 170*832dc76bSMariusz Zaborski 171*832dc76bSMariusz Zaborski return (s == -1 ? -1 : 0); 172*832dc76bSMariusz Zaborski } 173*832dc76bSMariusz Zaborski 174*832dc76bSMariusz Zaborski int 175*832dc76bSMariusz Zaborski cap_bind(cap_channel_t *chan, int s, const struct sockaddr *addr, 176*832dc76bSMariusz Zaborski socklen_t addrlen) 177*832dc76bSMariusz Zaborski { 178*832dc76bSMariusz Zaborski 179*832dc76bSMariusz Zaborski return (request_cb(chan, LIMIT_NV_BIND, s, addr, addrlen)); 180*832dc76bSMariusz Zaborski } 181*832dc76bSMariusz Zaborski 182*832dc76bSMariusz Zaborski int 183*832dc76bSMariusz Zaborski cap_connect(cap_channel_t *chan, int s, const struct sockaddr *name, 184*832dc76bSMariusz Zaborski socklen_t namelen) 185*832dc76bSMariusz Zaborski { 186*832dc76bSMariusz Zaborski 187*832dc76bSMariusz Zaborski return (request_cb(chan, LIMIT_NV_CONNECT, s, name, namelen)); 188*832dc76bSMariusz Zaborski } 189*832dc76bSMariusz Zaborski 190*832dc76bSMariusz Zaborski 191*832dc76bSMariusz Zaborski struct hostent * 192*832dc76bSMariusz Zaborski cap_gethostbyname(cap_channel_t *chan, const char *name) 193*832dc76bSMariusz Zaborski { 194*832dc76bSMariusz Zaborski 195*832dc76bSMariusz Zaborski return (cap_gethostbyname2(chan, name, AF_INET)); 196*832dc76bSMariusz Zaborski } 197*832dc76bSMariusz Zaborski 198*832dc76bSMariusz Zaborski struct hostent * 199*832dc76bSMariusz Zaborski cap_gethostbyname2(cap_channel_t *chan, const char *name, int af) 200*832dc76bSMariusz Zaborski { 201*832dc76bSMariusz Zaborski struct hostent *hp; 202*832dc76bSMariusz Zaborski nvlist_t *nvl; 203*832dc76bSMariusz Zaborski 204*832dc76bSMariusz Zaborski nvl = nvlist_create(0); 205*832dc76bSMariusz Zaborski nvlist_add_string(nvl, "cmd", "gethostbyname"); 206*832dc76bSMariusz Zaborski nvlist_add_number(nvl, "family", (uint64_t)af); 207*832dc76bSMariusz Zaborski nvlist_add_string(nvl, "name", name); 208*832dc76bSMariusz Zaborski nvl = cap_xfer_nvlist(chan, nvl); 209*832dc76bSMariusz Zaborski if (nvl == NULL) { 210*832dc76bSMariusz Zaborski h_errno = NO_RECOVERY; 211*832dc76bSMariusz Zaborski return (NULL); 212*832dc76bSMariusz Zaborski } 213*832dc76bSMariusz Zaborski if (nvlist_get_number(nvl, "error") != 0) { 214*832dc76bSMariusz Zaborski h_errno = (int)nvlist_get_number(nvl, "error"); 215*832dc76bSMariusz Zaborski nvlist_destroy(nvl); 216*832dc76bSMariusz Zaborski return (NULL); 217*832dc76bSMariusz Zaborski } 218*832dc76bSMariusz Zaborski 219*832dc76bSMariusz Zaborski hp = hostent_unpack(nvl, &hent); 220*832dc76bSMariusz Zaborski nvlist_destroy(nvl); 221*832dc76bSMariusz Zaborski return (hp); 222*832dc76bSMariusz Zaborski } 223*832dc76bSMariusz Zaborski 224*832dc76bSMariusz Zaborski struct hostent * 225*832dc76bSMariusz Zaborski cap_gethostbyaddr(cap_channel_t *chan, const void *addr, socklen_t len, 226*832dc76bSMariusz Zaborski int af) 227*832dc76bSMariusz Zaborski { 228*832dc76bSMariusz Zaborski struct hostent *hp; 229*832dc76bSMariusz Zaborski nvlist_t *nvl; 230*832dc76bSMariusz Zaborski 231*832dc76bSMariusz Zaborski nvl = nvlist_create(0); 232*832dc76bSMariusz Zaborski nvlist_add_string(nvl, "cmd", "gethostbyaddr"); 233*832dc76bSMariusz Zaborski nvlist_add_binary(nvl, "addr", addr, (size_t)len); 234*832dc76bSMariusz Zaborski nvlist_add_number(nvl, "family", (uint64_t)af); 235*832dc76bSMariusz Zaborski nvl = cap_xfer_nvlist(chan, nvl); 236*832dc76bSMariusz Zaborski if (nvl == NULL) { 237*832dc76bSMariusz Zaborski h_errno = NO_RECOVERY; 238*832dc76bSMariusz Zaborski return (NULL); 239*832dc76bSMariusz Zaborski } 240*832dc76bSMariusz Zaborski if (nvlist_get_number(nvl, "error") != 0) { 241*832dc76bSMariusz Zaborski h_errno = (int)nvlist_get_number(nvl, "error"); 242*832dc76bSMariusz Zaborski nvlist_destroy(nvl); 243*832dc76bSMariusz Zaborski return (NULL); 244*832dc76bSMariusz Zaborski } 245*832dc76bSMariusz Zaborski hp = hostent_unpack(nvl, &hent); 246*832dc76bSMariusz Zaborski nvlist_destroy(nvl); 247*832dc76bSMariusz Zaborski return (hp); 248*832dc76bSMariusz Zaborski } 249*832dc76bSMariusz Zaborski 250*832dc76bSMariusz Zaborski static struct addrinfo * 251*832dc76bSMariusz Zaborski addrinfo_unpack(const nvlist_t *nvl) 252*832dc76bSMariusz Zaborski { 253*832dc76bSMariusz Zaborski struct addrinfo *ai; 254*832dc76bSMariusz Zaborski const void *addr; 255*832dc76bSMariusz Zaborski size_t addrlen; 256*832dc76bSMariusz Zaborski const char *canonname; 257*832dc76bSMariusz Zaborski 258*832dc76bSMariusz Zaborski addr = nvlist_get_binary(nvl, "ai_addr", &addrlen); 259*832dc76bSMariusz Zaborski ai = malloc(sizeof(*ai) + addrlen); 260*832dc76bSMariusz Zaborski if (ai == NULL) 261*832dc76bSMariusz Zaborski return (NULL); 262*832dc76bSMariusz Zaborski ai->ai_flags = (int)nvlist_get_number(nvl, "ai_flags"); 263*832dc76bSMariusz Zaborski ai->ai_family = (int)nvlist_get_number(nvl, "ai_family"); 264*832dc76bSMariusz Zaborski ai->ai_socktype = (int)nvlist_get_number(nvl, "ai_socktype"); 265*832dc76bSMariusz Zaborski ai->ai_protocol = (int)nvlist_get_number(nvl, "ai_protocol"); 266*832dc76bSMariusz Zaborski ai->ai_addrlen = (socklen_t)addrlen; 267*832dc76bSMariusz Zaborski canonname = dnvlist_get_string(nvl, "ai_canonname", NULL); 268*832dc76bSMariusz Zaborski if (canonname != NULL) { 269*832dc76bSMariusz Zaborski ai->ai_canonname = strdup(canonname); 270*832dc76bSMariusz Zaborski if (ai->ai_canonname == NULL) { 271*832dc76bSMariusz Zaborski free(ai); 272*832dc76bSMariusz Zaborski return (NULL); 273*832dc76bSMariusz Zaborski } 274*832dc76bSMariusz Zaborski } else { 275*832dc76bSMariusz Zaborski ai->ai_canonname = NULL; 276*832dc76bSMariusz Zaborski } 277*832dc76bSMariusz Zaborski ai->ai_addr = (void *)(ai + 1); 278*832dc76bSMariusz Zaborski bcopy(addr, ai->ai_addr, addrlen); 279*832dc76bSMariusz Zaborski ai->ai_next = NULL; 280*832dc76bSMariusz Zaborski 281*832dc76bSMariusz Zaborski return (ai); 282*832dc76bSMariusz Zaborski } 283*832dc76bSMariusz Zaborski 284*832dc76bSMariusz Zaborski int 285*832dc76bSMariusz Zaborski cap_getaddrinfo(cap_channel_t *chan, const char *hostname, const char *servname, 286*832dc76bSMariusz Zaborski const struct addrinfo *hints, struct addrinfo **res) 287*832dc76bSMariusz Zaborski { 288*832dc76bSMariusz Zaborski struct addrinfo *firstai, *prevai, *curai; 289*832dc76bSMariusz Zaborski unsigned int ii; 290*832dc76bSMariusz Zaborski const nvlist_t *nvlai; 291*832dc76bSMariusz Zaborski char nvlname[64]; 292*832dc76bSMariusz Zaborski nvlist_t *nvl; 293*832dc76bSMariusz Zaborski int error, n; 294*832dc76bSMariusz Zaborski 295*832dc76bSMariusz Zaborski nvl = nvlist_create(0); 296*832dc76bSMariusz Zaborski nvlist_add_string(nvl, "cmd", "getaddrinfo"); 297*832dc76bSMariusz Zaborski if (hostname != NULL) 298*832dc76bSMariusz Zaborski nvlist_add_string(nvl, "hostname", hostname); 299*832dc76bSMariusz Zaborski if (servname != NULL) 300*832dc76bSMariusz Zaborski nvlist_add_string(nvl, "servname", servname); 301*832dc76bSMariusz Zaborski if (hints != NULL) { 302*832dc76bSMariusz Zaborski nvlist_add_number(nvl, "hints.ai_flags", 303*832dc76bSMariusz Zaborski (uint64_t)hints->ai_flags); 304*832dc76bSMariusz Zaborski nvlist_add_number(nvl, "hints.ai_family", 305*832dc76bSMariusz Zaborski (uint64_t)hints->ai_family); 306*832dc76bSMariusz Zaborski nvlist_add_number(nvl, "hints.ai_socktype", 307*832dc76bSMariusz Zaborski (uint64_t)hints->ai_socktype); 308*832dc76bSMariusz Zaborski nvlist_add_number(nvl, "hints.ai_protocol", 309*832dc76bSMariusz Zaborski (uint64_t)hints->ai_protocol); 310*832dc76bSMariusz Zaborski } 311*832dc76bSMariusz Zaborski nvl = cap_xfer_nvlist(chan, nvl); 312*832dc76bSMariusz Zaborski if (nvl == NULL) 313*832dc76bSMariusz Zaborski return (EAI_MEMORY); 314*832dc76bSMariusz Zaborski if (nvlist_get_number(nvl, "error") != 0) { 315*832dc76bSMariusz Zaborski error = (int)nvlist_get_number(nvl, "error"); 316*832dc76bSMariusz Zaborski nvlist_destroy(nvl); 317*832dc76bSMariusz Zaborski return (error); 318*832dc76bSMariusz Zaborski } 319*832dc76bSMariusz Zaborski 320*832dc76bSMariusz Zaborski nvlai = NULL; 321*832dc76bSMariusz Zaborski firstai = prevai = curai = NULL; 322*832dc76bSMariusz Zaborski for (ii = 0; ; ii++) { 323*832dc76bSMariusz Zaborski n = snprintf(nvlname, sizeof(nvlname), "res%u", ii); 324*832dc76bSMariusz Zaborski assert(n > 0 && n < (int)sizeof(nvlname)); 325*832dc76bSMariusz Zaborski if (!nvlist_exists_nvlist(nvl, nvlname)) 326*832dc76bSMariusz Zaborski break; 327*832dc76bSMariusz Zaborski nvlai = nvlist_get_nvlist(nvl, nvlname); 328*832dc76bSMariusz Zaborski curai = addrinfo_unpack(nvlai); 329*832dc76bSMariusz Zaborski if (curai == NULL) 330*832dc76bSMariusz Zaborski return (EAI_MEMORY); 331*832dc76bSMariusz Zaborski if (prevai != NULL) 332*832dc76bSMariusz Zaborski prevai->ai_next = curai; 333*832dc76bSMariusz Zaborski else 334*832dc76bSMariusz Zaborski firstai = curai; 335*832dc76bSMariusz Zaborski prevai = curai; 336*832dc76bSMariusz Zaborski } 337*832dc76bSMariusz Zaborski nvlist_destroy(nvl); 338*832dc76bSMariusz Zaborski if (curai == NULL && nvlai != NULL) { 339*832dc76bSMariusz Zaborski if (firstai == NULL) 340*832dc76bSMariusz Zaborski freeaddrinfo(firstai); 341*832dc76bSMariusz Zaborski return (EAI_MEMORY); 342*832dc76bSMariusz Zaborski } 343*832dc76bSMariusz Zaborski 344*832dc76bSMariusz Zaborski *res = firstai; 345*832dc76bSMariusz Zaborski return (0); 346*832dc76bSMariusz Zaborski } 347*832dc76bSMariusz Zaborski 348*832dc76bSMariusz Zaborski int 349*832dc76bSMariusz Zaborski cap_getnameinfo(cap_channel_t *chan, const struct sockaddr *sa, socklen_t salen, 350*832dc76bSMariusz Zaborski char *host, size_t hostlen, char *serv, size_t servlen, int flags) 351*832dc76bSMariusz Zaborski { 352*832dc76bSMariusz Zaborski nvlist_t *nvl; 353*832dc76bSMariusz Zaborski int error; 354*832dc76bSMariusz Zaborski 355*832dc76bSMariusz Zaborski nvl = nvlist_create(0); 356*832dc76bSMariusz Zaborski nvlist_add_string(nvl, "cmd", "getnameinfo"); 357*832dc76bSMariusz Zaborski nvlist_add_number(nvl, "hostlen", (uint64_t)hostlen); 358*832dc76bSMariusz Zaborski nvlist_add_number(nvl, "servlen", (uint64_t)servlen); 359*832dc76bSMariusz Zaborski nvlist_add_binary(nvl, "sa", sa, (size_t)salen); 360*832dc76bSMariusz Zaborski nvlist_add_number(nvl, "flags", (uint64_t)flags); 361*832dc76bSMariusz Zaborski nvl = cap_xfer_nvlist(chan, nvl); 362*832dc76bSMariusz Zaborski if (nvl == NULL) 363*832dc76bSMariusz Zaborski return (EAI_MEMORY); 364*832dc76bSMariusz Zaborski if (nvlist_get_number(nvl, "error") != 0) { 365*832dc76bSMariusz Zaborski error = (int)nvlist_get_number(nvl, "error"); 366*832dc76bSMariusz Zaborski nvlist_destroy(nvl); 367*832dc76bSMariusz Zaborski return (error); 368*832dc76bSMariusz Zaborski } 369*832dc76bSMariusz Zaborski 370*832dc76bSMariusz Zaborski if (host != NULL && nvlist_exists_string(nvl, "host")) 371*832dc76bSMariusz Zaborski strlcpy(host, nvlist_get_string(nvl, "host"), hostlen + 1); 372*832dc76bSMariusz Zaborski if (serv != NULL && nvlist_exists_string(nvl, "serv")) 373*832dc76bSMariusz Zaborski strlcpy(serv, nvlist_get_string(nvl, "serv"), servlen + 1); 374*832dc76bSMariusz Zaborski nvlist_destroy(nvl); 375*832dc76bSMariusz Zaborski return (0); 376*832dc76bSMariusz Zaborski } 377*832dc76bSMariusz Zaborski 378*832dc76bSMariusz Zaborski cap_net_limit_t * 379*832dc76bSMariusz Zaborski cap_net_limit_init(cap_channel_t *chan, uint64_t mode) 380*832dc76bSMariusz Zaborski { 381*832dc76bSMariusz Zaborski cap_net_limit_t *limit; 382*832dc76bSMariusz Zaborski 383*832dc76bSMariusz Zaborski limit = calloc(1, sizeof(*limit)); 384*832dc76bSMariusz Zaborski if (limit != NULL) { 385*832dc76bSMariusz Zaborski limit->cnl_mode = mode; 386*832dc76bSMariusz Zaborski limit->cnl_chan = chan; 387*832dc76bSMariusz Zaborski limit->cnl_addr2name = nvlist_create(0); 388*832dc76bSMariusz Zaborski limit->cnl_name2addr = nvlist_create(0); 389*832dc76bSMariusz Zaborski limit->cnl_connect = nvlist_create(0); 390*832dc76bSMariusz Zaborski limit->cnl_bind = nvlist_create(0); 391*832dc76bSMariusz Zaborski } 392*832dc76bSMariusz Zaborski 393*832dc76bSMariusz Zaborski return (limit); 394*832dc76bSMariusz Zaborski } 395*832dc76bSMariusz Zaborski 396*832dc76bSMariusz Zaborski static void 397*832dc76bSMariusz Zaborski pack_limit(nvlist_t *lnvl, const char *name, nvlist_t *limit) 398*832dc76bSMariusz Zaborski { 399*832dc76bSMariusz Zaborski 400*832dc76bSMariusz Zaborski if (!nvlist_empty(limit)) { 401*832dc76bSMariusz Zaborski nvlist_move_nvlist(lnvl, name, limit); 402*832dc76bSMariusz Zaborski } else { 403*832dc76bSMariusz Zaborski nvlist_destroy(limit); 404*832dc76bSMariusz Zaborski } 405*832dc76bSMariusz Zaborski } 406*832dc76bSMariusz Zaborski 407*832dc76bSMariusz Zaborski int 408*832dc76bSMariusz Zaborski cap_net_limit(cap_net_limit_t *limit) 409*832dc76bSMariusz Zaborski { 410*832dc76bSMariusz Zaborski nvlist_t *lnvl; 411*832dc76bSMariusz Zaborski cap_channel_t *chan; 412*832dc76bSMariusz Zaborski 413*832dc76bSMariusz Zaborski lnvl = nvlist_create(0); 414*832dc76bSMariusz Zaborski nvlist_add_number(lnvl, "mode", limit->cnl_mode); 415*832dc76bSMariusz Zaborski 416*832dc76bSMariusz Zaborski pack_limit(lnvl, LIMIT_NV_ADDR2NAME, limit->cnl_addr2name); 417*832dc76bSMariusz Zaborski pack_limit(lnvl, LIMIT_NV_NAME2ADDR, limit->cnl_name2addr); 418*832dc76bSMariusz Zaborski pack_limit(lnvl, LIMIT_NV_CONNECT, limit->cnl_connect); 419*832dc76bSMariusz Zaborski pack_limit(lnvl, LIMIT_NV_BIND, limit->cnl_bind); 420*832dc76bSMariusz Zaborski 421*832dc76bSMariusz Zaborski chan = limit->cnl_chan; 422*832dc76bSMariusz Zaborski free(limit); 423*832dc76bSMariusz Zaborski 424*832dc76bSMariusz Zaborski return (cap_limit_set(chan, lnvl)); 425*832dc76bSMariusz Zaborski } 426*832dc76bSMariusz Zaborski 427*832dc76bSMariusz Zaborski void 428*832dc76bSMariusz Zaborski cap_net_free(cap_net_limit_t *limit) 429*832dc76bSMariusz Zaborski { 430*832dc76bSMariusz Zaborski 431*832dc76bSMariusz Zaborski if (limit == NULL) 432*832dc76bSMariusz Zaborski return; 433*832dc76bSMariusz Zaborski 434*832dc76bSMariusz Zaborski nvlist_destroy(limit->cnl_addr2name); 435*832dc76bSMariusz Zaborski nvlist_destroy(limit->cnl_name2addr); 436*832dc76bSMariusz Zaborski nvlist_destroy(limit->cnl_connect); 437*832dc76bSMariusz Zaborski nvlist_destroy(limit->cnl_bind); 438*832dc76bSMariusz Zaborski 439*832dc76bSMariusz Zaborski free(limit); 440*832dc76bSMariusz Zaborski } 441*832dc76bSMariusz Zaborski 442*832dc76bSMariusz Zaborski static void 443*832dc76bSMariusz Zaborski pack_family(nvlist_t *nvl, int *family, size_t size) 444*832dc76bSMariusz Zaborski { 445*832dc76bSMariusz Zaborski size_t i; 446*832dc76bSMariusz Zaborski 447*832dc76bSMariusz Zaborski i = 0; 448*832dc76bSMariusz Zaborski if (!nvlist_exists_number_array(nvl, "family")) { 449*832dc76bSMariusz Zaborski uint64_t val; 450*832dc76bSMariusz Zaborski 451*832dc76bSMariusz Zaborski val = family[0]; 452*832dc76bSMariusz Zaborski nvlist_add_number_array(nvl, "family", &val, 1); 453*832dc76bSMariusz Zaborski i += 1; 454*832dc76bSMariusz Zaborski } 455*832dc76bSMariusz Zaborski 456*832dc76bSMariusz Zaborski for (; i < size; i++) { 457*832dc76bSMariusz Zaborski nvlist_append_number_array(nvl, "family", family[i]); 458*832dc76bSMariusz Zaborski } 459*832dc76bSMariusz Zaborski } 460*832dc76bSMariusz Zaborski 461*832dc76bSMariusz Zaborski static void 462*832dc76bSMariusz Zaborski pack_sockaddr(nvlist_t *res, const struct sockaddr *sa, socklen_t salen) 463*832dc76bSMariusz Zaborski { 464*832dc76bSMariusz Zaborski nvlist_t *nvl; 465*832dc76bSMariusz Zaborski 466*832dc76bSMariusz Zaborski if (!nvlist_exists_nvlist(res, "sockaddr")) { 467*832dc76bSMariusz Zaborski nvl = nvlist_create(NV_FLAG_NO_UNIQUE); 468*832dc76bSMariusz Zaborski } else { 469*832dc76bSMariusz Zaborski nvl = nvlist_take_nvlist(res, "sockaddr"); 470*832dc76bSMariusz Zaborski } 471*832dc76bSMariusz Zaborski 472*832dc76bSMariusz Zaborski nvlist_add_binary(nvl, "", sa, salen); 473*832dc76bSMariusz Zaborski nvlist_move_nvlist(res, "sockaddr", nvl); 474*832dc76bSMariusz Zaborski } 475*832dc76bSMariusz Zaborski 476*832dc76bSMariusz Zaborski cap_net_limit_t * 477*832dc76bSMariusz Zaborski cap_net_limit_addr2name_family(cap_net_limit_t *limit, int *family, size_t size) 478*832dc76bSMariusz Zaborski { 479*832dc76bSMariusz Zaborski 480*832dc76bSMariusz Zaborski pack_family(limit->cnl_addr2name, family, size); 481*832dc76bSMariusz Zaborski return (limit); 482*832dc76bSMariusz Zaborski } 483*832dc76bSMariusz Zaborski 484*832dc76bSMariusz Zaborski cap_net_limit_t * 485*832dc76bSMariusz Zaborski cap_net_limit_name2addr_family(cap_net_limit_t *limit, int *family, size_t size) 486*832dc76bSMariusz Zaborski { 487*832dc76bSMariusz Zaborski 488*832dc76bSMariusz Zaborski pack_family(limit->cnl_name2addr, family, size); 489*832dc76bSMariusz Zaborski return (limit); 490*832dc76bSMariusz Zaborski } 491*832dc76bSMariusz Zaborski 492*832dc76bSMariusz Zaborski cap_net_limit_t * 493*832dc76bSMariusz Zaborski cap_net_limit_name2addr(cap_net_limit_t *limit, const char *host, 494*832dc76bSMariusz Zaborski const char *serv) 495*832dc76bSMariusz Zaborski { 496*832dc76bSMariusz Zaborski nvlist_t *nvl; 497*832dc76bSMariusz Zaborski 498*832dc76bSMariusz Zaborski if (!nvlist_exists_nvlist(limit->cnl_name2addr, "hosts")) { 499*832dc76bSMariusz Zaborski nvl = nvlist_create(NV_FLAG_NO_UNIQUE); 500*832dc76bSMariusz Zaborski } else { 501*832dc76bSMariusz Zaborski nvl = nvlist_take_nvlist(limit->cnl_name2addr, "hosts"); 502*832dc76bSMariusz Zaborski } 503*832dc76bSMariusz Zaborski 504*832dc76bSMariusz Zaborski nvlist_add_string(nvl, 505*832dc76bSMariusz Zaborski host != NULL ? host : "", 506*832dc76bSMariusz Zaborski serv != NULL ? serv : ""); 507*832dc76bSMariusz Zaborski 508*832dc76bSMariusz Zaborski nvlist_move_nvlist(limit->cnl_name2addr, "hosts", nvl); 509*832dc76bSMariusz Zaborski return (limit); 510*832dc76bSMariusz Zaborski } 511*832dc76bSMariusz Zaborski 512*832dc76bSMariusz Zaborski cap_net_limit_t * 513*832dc76bSMariusz Zaborski cap_net_limit_addr2name(cap_net_limit_t *limit, const struct sockaddr *sa, 514*832dc76bSMariusz Zaborski socklen_t salen) 515*832dc76bSMariusz Zaborski { 516*832dc76bSMariusz Zaborski 517*832dc76bSMariusz Zaborski pack_sockaddr(limit->cnl_addr2name, sa, salen); 518*832dc76bSMariusz Zaborski return (limit); 519*832dc76bSMariusz Zaborski } 520*832dc76bSMariusz Zaborski 521*832dc76bSMariusz Zaborski 522*832dc76bSMariusz Zaborski cap_net_limit_t * 523*832dc76bSMariusz Zaborski cap_net_limit_connect(cap_net_limit_t *limit, const struct sockaddr *sa, 524*832dc76bSMariusz Zaborski socklen_t salen) 525*832dc76bSMariusz Zaborski { 526*832dc76bSMariusz Zaborski 527*832dc76bSMariusz Zaborski pack_sockaddr(limit->cnl_connect, sa, salen); 528*832dc76bSMariusz Zaborski return (limit); 529*832dc76bSMariusz Zaborski } 530*832dc76bSMariusz Zaborski 531*832dc76bSMariusz Zaborski cap_net_limit_t * 532*832dc76bSMariusz Zaborski cap_net_limit_bind(cap_net_limit_t *limit, const struct sockaddr *sa, 533*832dc76bSMariusz Zaborski socklen_t salen) 534*832dc76bSMariusz Zaborski { 535*832dc76bSMariusz Zaborski 536*832dc76bSMariusz Zaborski pack_sockaddr(limit->cnl_bind, sa, salen); 537*832dc76bSMariusz Zaborski return (limit); 538*832dc76bSMariusz Zaborski } 539*832dc76bSMariusz Zaborski 540*832dc76bSMariusz Zaborski /* 541*832dc76bSMariusz Zaborski * Service functions. 542*832dc76bSMariusz Zaborski */ 543*832dc76bSMariusz Zaborski 544*832dc76bSMariusz Zaborski static nvlist_t *capdnscache; 545*832dc76bSMariusz Zaborski 546*832dc76bSMariusz Zaborski static void 547*832dc76bSMariusz Zaborski net_add_sockaddr_to_cache(struct sockaddr *sa, socklen_t salen, bool deprecated) 548*832dc76bSMariusz Zaborski { 549*832dc76bSMariusz Zaborski void *cookie; 550*832dc76bSMariusz Zaborski 551*832dc76bSMariusz Zaborski if (capdnscache == NULL) { 552*832dc76bSMariusz Zaborski capdnscache = nvlist_create(NV_FLAG_NO_UNIQUE); 553*832dc76bSMariusz Zaborski } else { 554*832dc76bSMariusz Zaborski /* Lets keep it clean. Look for dups. */ 555*832dc76bSMariusz Zaborski cookie = NULL; 556*832dc76bSMariusz Zaborski while (nvlist_next(capdnscache, NULL, &cookie) != NULL) { 557*832dc76bSMariusz Zaborski const void *data; 558*832dc76bSMariusz Zaborski size_t size; 559*832dc76bSMariusz Zaborski 560*832dc76bSMariusz Zaborski assert(cnvlist_type(cookie) == NV_TYPE_BINARY); 561*832dc76bSMariusz Zaborski 562*832dc76bSMariusz Zaborski data = cnvlist_get_binary(cookie, &size); 563*832dc76bSMariusz Zaborski if (salen != size) 564*832dc76bSMariusz Zaborski continue; 565*832dc76bSMariusz Zaborski if (memcmp(data, sa, size) == 0) 566*832dc76bSMariusz Zaborski return; 567*832dc76bSMariusz Zaborski } 568*832dc76bSMariusz Zaborski } 569*832dc76bSMariusz Zaborski 570*832dc76bSMariusz Zaborski nvlist_add_binary(capdnscache, deprecated ? "d" : "", sa, salen); 571*832dc76bSMariusz Zaborski } 572*832dc76bSMariusz Zaborski 573*832dc76bSMariusz Zaborski static void 574*832dc76bSMariusz Zaborski net_add_hostent_to_cache(const char *address, size_t asize, int family) 575*832dc76bSMariusz Zaborski { 576*832dc76bSMariusz Zaborski 577*832dc76bSMariusz Zaborski if (family != AF_INET && family != AF_INET6) 578*832dc76bSMariusz Zaborski return; 579*832dc76bSMariusz Zaborski 580*832dc76bSMariusz Zaborski if (family == AF_INET6) { 581*832dc76bSMariusz Zaborski struct sockaddr_in6 connaddr; 582*832dc76bSMariusz Zaborski 583*832dc76bSMariusz Zaborski memset(&connaddr, 0, sizeof(connaddr)); 584*832dc76bSMariusz Zaborski connaddr.sin6_family = AF_INET6; 585*832dc76bSMariusz Zaborski memcpy((char *)&connaddr.sin6_addr, address, asize); 586*832dc76bSMariusz Zaborski connaddr.sin6_port = 0; 587*832dc76bSMariusz Zaborski 588*832dc76bSMariusz Zaborski net_add_sockaddr_to_cache((struct sockaddr *)&connaddr, 589*832dc76bSMariusz Zaborski sizeof(connaddr), true); 590*832dc76bSMariusz Zaborski } else { 591*832dc76bSMariusz Zaborski struct sockaddr_in connaddr; 592*832dc76bSMariusz Zaborski 593*832dc76bSMariusz Zaborski memset(&connaddr, 0, sizeof(connaddr)); 594*832dc76bSMariusz Zaborski connaddr.sin_family = AF_INET; 595*832dc76bSMariusz Zaborski memcpy((char *)&connaddr.sin_addr.s_addr, address, asize); 596*832dc76bSMariusz Zaborski connaddr.sin_port = 0; 597*832dc76bSMariusz Zaborski 598*832dc76bSMariusz Zaborski net_add_sockaddr_to_cache((struct sockaddr *)&connaddr, 599*832dc76bSMariusz Zaborski sizeof(connaddr), true); 600*832dc76bSMariusz Zaborski } 601*832dc76bSMariusz Zaborski } 602*832dc76bSMariusz Zaborski 603*832dc76bSMariusz Zaborski static bool 604*832dc76bSMariusz Zaborski net_allowed_mode(const nvlist_t *limits, uint64_t mode) 605*832dc76bSMariusz Zaborski { 606*832dc76bSMariusz Zaborski 607*832dc76bSMariusz Zaborski if (limits == NULL) 608*832dc76bSMariusz Zaborski return (true); 609*832dc76bSMariusz Zaborski 610*832dc76bSMariusz Zaborski return ((nvlist_get_number(limits, "mode") & mode) == mode); 611*832dc76bSMariusz Zaborski } 612*832dc76bSMariusz Zaborski 613*832dc76bSMariusz Zaborski static bool 614*832dc76bSMariusz Zaborski net_allowed_family(const nvlist_t *limits, int family) 615*832dc76bSMariusz Zaborski { 616*832dc76bSMariusz Zaborski const uint64_t *allowedfamily; 617*832dc76bSMariusz Zaborski size_t i, allsize; 618*832dc76bSMariusz Zaborski 619*832dc76bSMariusz Zaborski if (limits == NULL) 620*832dc76bSMariusz Zaborski return (true); 621*832dc76bSMariusz Zaborski 622*832dc76bSMariusz Zaborski /* If there are no familes at all, allow any mode. */ 623*832dc76bSMariusz Zaborski if (!nvlist_exists_number_array(limits, "family")) 624*832dc76bSMariusz Zaborski return (true); 625*832dc76bSMariusz Zaborski 626*832dc76bSMariusz Zaborski allowedfamily = nvlist_get_number_array(limits, "family", &allsize); 627*832dc76bSMariusz Zaborski for (i = 0; i < allsize; i++) { 628*832dc76bSMariusz Zaborski /* XXX: what with AF_UNSPEC? */ 629*832dc76bSMariusz Zaborski if (allowedfamily[i] == (uint64_t)family) { 630*832dc76bSMariusz Zaborski return (true); 631*832dc76bSMariusz Zaborski } 632*832dc76bSMariusz Zaborski } 633*832dc76bSMariusz Zaborski 634*832dc76bSMariusz Zaborski return (false); 635*832dc76bSMariusz Zaborski } 636*832dc76bSMariusz Zaborski 637*832dc76bSMariusz Zaborski static bool 638*832dc76bSMariusz Zaborski net_allowed_bsaddr_impl(const nvlist_t *salimits, const void *saddr, 639*832dc76bSMariusz Zaborski size_t saddrsize) 640*832dc76bSMariusz Zaborski { 641*832dc76bSMariusz Zaborski void *cookie; 642*832dc76bSMariusz Zaborski const void *limit; 643*832dc76bSMariusz Zaborski size_t limitsize; 644*832dc76bSMariusz Zaborski 645*832dc76bSMariusz Zaborski cookie = NULL; 646*832dc76bSMariusz Zaborski while (nvlist_next(salimits, NULL, &cookie) != NULL) { 647*832dc76bSMariusz Zaborski limit = cnvlist_get_binary(cookie, &limitsize); 648*832dc76bSMariusz Zaborski 649*832dc76bSMariusz Zaborski if (limitsize != saddrsize) { 650*832dc76bSMariusz Zaborski continue; 651*832dc76bSMariusz Zaborski } 652*832dc76bSMariusz Zaborski if (memcmp(limit, saddr, limitsize) == 0) { 653*832dc76bSMariusz Zaborski return (true); 654*832dc76bSMariusz Zaborski } 655*832dc76bSMariusz Zaborski 656*832dc76bSMariusz Zaborski /* 657*832dc76bSMariusz Zaborski * In case of deprecated version (gethostbyname) we have to 658*832dc76bSMariusz Zaborski * ignore port, because there is no such info in the hostent. 659*832dc76bSMariusz Zaborski * Suporting only AF_INET and AF_INET6. 660*832dc76bSMariusz Zaborski */ 661*832dc76bSMariusz Zaborski if (strcmp(cnvlist_name(cookie), "d") != 0 || 662*832dc76bSMariusz Zaborski (saddrsize != sizeof(struct sockaddr_in) && 663*832dc76bSMariusz Zaborski saddrsize != sizeof(struct sockaddr_in6))) { 664*832dc76bSMariusz Zaborski continue; 665*832dc76bSMariusz Zaborski } 666*832dc76bSMariusz Zaborski if (saddrsize == sizeof(struct sockaddr_in)) { 667*832dc76bSMariusz Zaborski const struct sockaddr_in *saddrptr; 668*832dc76bSMariusz Zaborski struct sockaddr_in sockaddr; 669*832dc76bSMariusz Zaborski 670*832dc76bSMariusz Zaborski saddrptr = (const struct sockaddr_in *)saddr; 671*832dc76bSMariusz Zaborski memcpy(&sockaddr, limit, sizeof(sockaddr)); 672*832dc76bSMariusz Zaborski sockaddr.sin_port = saddrptr->sin_port; 673*832dc76bSMariusz Zaborski 674*832dc76bSMariusz Zaborski if (memcmp(&sockaddr, saddr, saddrsize) == 0) { 675*832dc76bSMariusz Zaborski return (true); 676*832dc76bSMariusz Zaborski } 677*832dc76bSMariusz Zaborski } else if (saddrsize == sizeof(struct sockaddr_in6)) { 678*832dc76bSMariusz Zaborski const struct sockaddr_in6 *saddrptr; 679*832dc76bSMariusz Zaborski struct sockaddr_in6 sockaddr; 680*832dc76bSMariusz Zaborski 681*832dc76bSMariusz Zaborski saddrptr = (const struct sockaddr_in6 *)saddr; 682*832dc76bSMariusz Zaborski memcpy(&sockaddr, limit, sizeof(sockaddr)); 683*832dc76bSMariusz Zaborski sockaddr.sin6_port = saddrptr->sin6_port; 684*832dc76bSMariusz Zaborski 685*832dc76bSMariusz Zaborski if (memcmp(&sockaddr, saddr, saddrsize) == 0) { 686*832dc76bSMariusz Zaborski return (true); 687*832dc76bSMariusz Zaborski } 688*832dc76bSMariusz Zaborski } 689*832dc76bSMariusz Zaborski } 690*832dc76bSMariusz Zaborski 691*832dc76bSMariusz Zaborski return (false); 692*832dc76bSMariusz Zaborski } 693*832dc76bSMariusz Zaborski 694*832dc76bSMariusz Zaborski static bool 695*832dc76bSMariusz Zaborski net_allowed_bsaddr(const nvlist_t *limits, const void *saddr, size_t saddrsize) 696*832dc76bSMariusz Zaborski { 697*832dc76bSMariusz Zaborski 698*832dc76bSMariusz Zaborski if (limits == NULL) 699*832dc76bSMariusz Zaborski return (true); 700*832dc76bSMariusz Zaborski 701*832dc76bSMariusz Zaborski if (!nvlist_exists_nvlist(limits, "sockaddr")) 702*832dc76bSMariusz Zaborski return (true); 703*832dc76bSMariusz Zaborski 704*832dc76bSMariusz Zaborski return (net_allowed_bsaddr_impl(nvlist_get_nvlist(limits, "sockaddr"), 705*832dc76bSMariusz Zaborski saddr, saddrsize)); 706*832dc76bSMariusz Zaborski } 707*832dc76bSMariusz Zaborski 708*832dc76bSMariusz Zaborski static bool 709*832dc76bSMariusz Zaborski net_allowed_hosts(const nvlist_t *limits, const char *name, const char *srvname) 710*832dc76bSMariusz Zaborski { 711*832dc76bSMariusz Zaborski void *cookie; 712*832dc76bSMariusz Zaborski const nvlist_t *hlimits; 713*832dc76bSMariusz Zaborski const char *testname, *testsrvname; 714*832dc76bSMariusz Zaborski 715*832dc76bSMariusz Zaborski if (limits == NULL) { 716*832dc76bSMariusz Zaborski return (true); 717*832dc76bSMariusz Zaborski } 718*832dc76bSMariusz Zaborski 719*832dc76bSMariusz Zaborski /* If there are no hosts at all, allow any. */ 720*832dc76bSMariusz Zaborski if (!nvlist_exists_nvlist(limits, "hosts")) { 721*832dc76bSMariusz Zaborski return (true); 722*832dc76bSMariusz Zaborski } 723*832dc76bSMariusz Zaborski 724*832dc76bSMariusz Zaborski cookie = NULL; 725*832dc76bSMariusz Zaborski testname = (name == NULL ? "" : name); 726*832dc76bSMariusz Zaborski testsrvname = (srvname == NULL ? "" : srvname); 727*832dc76bSMariusz Zaborski hlimits = nvlist_get_nvlist(limits, "hosts"); 728*832dc76bSMariusz Zaborski while (nvlist_next(hlimits, NULL, &cookie) != NULL) { 729*832dc76bSMariusz Zaborski if (strcmp(cnvlist_name(cookie), "") != 0 && 730*832dc76bSMariusz Zaborski strcmp(cnvlist_name(cookie), testname) != 0) { 731*832dc76bSMariusz Zaborski continue; 732*832dc76bSMariusz Zaborski } 733*832dc76bSMariusz Zaborski 734*832dc76bSMariusz Zaborski if (strcmp(cnvlist_get_string(cookie), "") != 0 && 735*832dc76bSMariusz Zaborski strcmp(cnvlist_get_string(cookie), testsrvname) != 0) { 736*832dc76bSMariusz Zaborski continue; 737*832dc76bSMariusz Zaborski } 738*832dc76bSMariusz Zaborski 739*832dc76bSMariusz Zaborski return (true); 740*832dc76bSMariusz Zaborski } 741*832dc76bSMariusz Zaborski 742*832dc76bSMariusz Zaborski return (false); 743*832dc76bSMariusz Zaborski } 744*832dc76bSMariusz Zaborski 745*832dc76bSMariusz Zaborski static void 746*832dc76bSMariusz Zaborski hostent_pack(const struct hostent *hp, nvlist_t *nvl, bool addtocache) 747*832dc76bSMariusz Zaborski { 748*832dc76bSMariusz Zaborski unsigned int ii; 749*832dc76bSMariusz Zaborski char nvlname[64]; 750*832dc76bSMariusz Zaborski int n; 751*832dc76bSMariusz Zaborski 752*832dc76bSMariusz Zaborski nvlist_add_string(nvl, "name", hp->h_name); 753*832dc76bSMariusz Zaborski nvlist_add_number(nvl, "addrtype", (uint64_t)hp->h_addrtype); 754*832dc76bSMariusz Zaborski nvlist_add_number(nvl, "length", (uint64_t)hp->h_length); 755*832dc76bSMariusz Zaborski 756*832dc76bSMariusz Zaborski if (hp->h_aliases == NULL) { 757*832dc76bSMariusz Zaborski nvlist_add_number(nvl, "naliases", 0); 758*832dc76bSMariusz Zaborski } else { 759*832dc76bSMariusz Zaborski for (ii = 0; hp->h_aliases[ii] != NULL; ii++) { 760*832dc76bSMariusz Zaborski n = snprintf(nvlname, sizeof(nvlname), "alias%u", ii); 761*832dc76bSMariusz Zaborski assert(n > 0 && n < (int)sizeof(nvlname)); 762*832dc76bSMariusz Zaborski nvlist_add_string(nvl, nvlname, hp->h_aliases[ii]); 763*832dc76bSMariusz Zaborski } 764*832dc76bSMariusz Zaborski nvlist_add_number(nvl, "naliases", (uint64_t)ii); 765*832dc76bSMariusz Zaborski } 766*832dc76bSMariusz Zaborski 767*832dc76bSMariusz Zaborski if (hp->h_addr_list == NULL) { 768*832dc76bSMariusz Zaborski nvlist_add_number(nvl, "naddrs", 0); 769*832dc76bSMariusz Zaborski } else { 770*832dc76bSMariusz Zaborski for (ii = 0; hp->h_addr_list[ii] != NULL; ii++) { 771*832dc76bSMariusz Zaborski n = snprintf(nvlname, sizeof(nvlname), "addr%u", ii); 772*832dc76bSMariusz Zaborski assert(n > 0 && n < (int)sizeof(nvlname)); 773*832dc76bSMariusz Zaborski nvlist_add_binary(nvl, nvlname, hp->h_addr_list[ii], 774*832dc76bSMariusz Zaborski (size_t)hp->h_length); 775*832dc76bSMariusz Zaborski if (addtocache) { 776*832dc76bSMariusz Zaborski net_add_hostent_to_cache(hp->h_addr_list[ii], 777*832dc76bSMariusz Zaborski hp->h_length, hp->h_addrtype); 778*832dc76bSMariusz Zaborski } 779*832dc76bSMariusz Zaborski } 780*832dc76bSMariusz Zaborski nvlist_add_number(nvl, "naddrs", (uint64_t)ii); 781*832dc76bSMariusz Zaborski } 782*832dc76bSMariusz Zaborski } 783*832dc76bSMariusz Zaborski 784*832dc76bSMariusz Zaborski static int 785*832dc76bSMariusz Zaborski net_gethostbyname(const nvlist_t *limits, const nvlist_t *nvlin, 786*832dc76bSMariusz Zaborski nvlist_t *nvlout) 787*832dc76bSMariusz Zaborski { 788*832dc76bSMariusz Zaborski struct hostent *hp; 789*832dc76bSMariusz Zaborski int family; 790*832dc76bSMariusz Zaborski const nvlist_t *funclimit; 791*832dc76bSMariusz Zaborski const char *name; 792*832dc76bSMariusz Zaborski bool dnscache; 793*832dc76bSMariusz Zaborski 794*832dc76bSMariusz Zaborski if (!net_allowed_mode(limits, CAPNET_DEPRECATED_NAME2ADDR)) 795*832dc76bSMariusz Zaborski return (ENOTCAPABLE); 796*832dc76bSMariusz Zaborski 797*832dc76bSMariusz Zaborski dnscache = net_allowed_mode(limits, CAPNET_CONNECTDNS); 798*832dc76bSMariusz Zaborski funclimit = dnvlist_get_nvlist(limits, LIMIT_NV_NAME2ADDR, NULL); 799*832dc76bSMariusz Zaborski 800*832dc76bSMariusz Zaborski family = (int)nvlist_get_number(nvlin, "family"); 801*832dc76bSMariusz Zaborski if (!net_allowed_family(funclimit, family)) 802*832dc76bSMariusz Zaborski return (ENOTCAPABLE); 803*832dc76bSMariusz Zaborski 804*832dc76bSMariusz Zaborski name = nvlist_get_string(nvlin, "name"); 805*832dc76bSMariusz Zaborski if (!net_allowed_hosts(funclimit, name, "")) 806*832dc76bSMariusz Zaborski return (ENOTCAPABLE); 807*832dc76bSMariusz Zaborski 808*832dc76bSMariusz Zaborski hp = gethostbyname2(name, family); 809*832dc76bSMariusz Zaborski if (hp == NULL) 810*832dc76bSMariusz Zaborski return (h_errno); 811*832dc76bSMariusz Zaborski hostent_pack(hp, nvlout, dnscache); 812*832dc76bSMariusz Zaborski return (0); 813*832dc76bSMariusz Zaborski } 814*832dc76bSMariusz Zaborski 815*832dc76bSMariusz Zaborski static int 816*832dc76bSMariusz Zaborski net_gethostbyaddr(const nvlist_t *limits, const nvlist_t *nvlin, 817*832dc76bSMariusz Zaborski nvlist_t *nvlout) 818*832dc76bSMariusz Zaborski { 819*832dc76bSMariusz Zaborski struct hostent *hp; 820*832dc76bSMariusz Zaborski const void *addr; 821*832dc76bSMariusz Zaborski size_t addrsize; 822*832dc76bSMariusz Zaborski int family; 823*832dc76bSMariusz Zaborski const nvlist_t *funclimit; 824*832dc76bSMariusz Zaborski 825*832dc76bSMariusz Zaborski if (!net_allowed_mode(limits, CAPNET_DEPRECATED_ADDR2NAME)) 826*832dc76bSMariusz Zaborski return (ENOTCAPABLE); 827*832dc76bSMariusz Zaborski 828*832dc76bSMariusz Zaborski funclimit = dnvlist_get_nvlist(limits, LIMIT_NV_ADDR2NAME, NULL); 829*832dc76bSMariusz Zaborski 830*832dc76bSMariusz Zaborski family = (int)nvlist_get_number(nvlin, "family"); 831*832dc76bSMariusz Zaborski if (!net_allowed_family(funclimit, family)) 832*832dc76bSMariusz Zaborski return (ENOTCAPABLE); 833*832dc76bSMariusz Zaborski 834*832dc76bSMariusz Zaborski addr = nvlist_get_binary(nvlin, "addr", &addrsize); 835*832dc76bSMariusz Zaborski if (!net_allowed_bsaddr(funclimit, addr, addrsize)) 836*832dc76bSMariusz Zaborski return (ENOTCAPABLE); 837*832dc76bSMariusz Zaborski 838*832dc76bSMariusz Zaborski hp = gethostbyaddr(addr, (socklen_t)addrsize, family); 839*832dc76bSMariusz Zaborski if (hp == NULL) 840*832dc76bSMariusz Zaborski return (h_errno); 841*832dc76bSMariusz Zaborski hostent_pack(hp, nvlout, false); 842*832dc76bSMariusz Zaborski return (0); 843*832dc76bSMariusz Zaborski } 844*832dc76bSMariusz Zaborski 845*832dc76bSMariusz Zaborski static int 846*832dc76bSMariusz Zaborski net_getnameinfo(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) 847*832dc76bSMariusz Zaborski { 848*832dc76bSMariusz Zaborski struct sockaddr_storage sast; 849*832dc76bSMariusz Zaborski const void *sabin; 850*832dc76bSMariusz Zaborski char *host, *serv; 851*832dc76bSMariusz Zaborski size_t sabinsize, hostlen, servlen; 852*832dc76bSMariusz Zaborski socklen_t salen; 853*832dc76bSMariusz Zaborski int error, flags; 854*832dc76bSMariusz Zaborski const nvlist_t *funclimit; 855*832dc76bSMariusz Zaborski 856*832dc76bSMariusz Zaborski if (!net_allowed_mode(limits, CAPNET_ADDR2NAME)) 857*832dc76bSMariusz Zaborski return (ENOTCAPABLE); 858*832dc76bSMariusz Zaborski funclimit = dnvlist_get_nvlist(limits, LIMIT_NV_ADDR2NAME, NULL); 859*832dc76bSMariusz Zaborski 860*832dc76bSMariusz Zaborski error = 0; 861*832dc76bSMariusz Zaborski host = serv = NULL; 862*832dc76bSMariusz Zaborski memset(&sast, 0, sizeof(sast)); 863*832dc76bSMariusz Zaborski 864*832dc76bSMariusz Zaborski hostlen = (size_t)nvlist_get_number(nvlin, "hostlen"); 865*832dc76bSMariusz Zaborski servlen = (size_t)nvlist_get_number(nvlin, "servlen"); 866*832dc76bSMariusz Zaborski 867*832dc76bSMariusz Zaborski if (hostlen > 0) { 868*832dc76bSMariusz Zaborski host = calloc(1, hostlen + 1); 869*832dc76bSMariusz Zaborski if (host == NULL) { 870*832dc76bSMariusz Zaborski error = EAI_MEMORY; 871*832dc76bSMariusz Zaborski goto out; 872*832dc76bSMariusz Zaborski } 873*832dc76bSMariusz Zaborski } 874*832dc76bSMariusz Zaborski if (servlen > 0) { 875*832dc76bSMariusz Zaborski serv = calloc(1, servlen + 1); 876*832dc76bSMariusz Zaborski if (serv == NULL) { 877*832dc76bSMariusz Zaborski error = EAI_MEMORY; 878*832dc76bSMariusz Zaborski goto out; 879*832dc76bSMariusz Zaborski } 880*832dc76bSMariusz Zaborski } 881*832dc76bSMariusz Zaborski 882*832dc76bSMariusz Zaborski sabin = nvlist_get_binary(nvlin, "sa", &sabinsize); 883*832dc76bSMariusz Zaborski if (sabinsize > sizeof(sast)) { 884*832dc76bSMariusz Zaborski error = EAI_FAIL; 885*832dc76bSMariusz Zaborski goto out; 886*832dc76bSMariusz Zaborski } 887*832dc76bSMariusz Zaborski if (!net_allowed_bsaddr(funclimit, sabin, sabinsize)) 888*832dc76bSMariusz Zaborski return (ENOTCAPABLE); 889*832dc76bSMariusz Zaborski 890*832dc76bSMariusz Zaborski memcpy(&sast, sabin, sabinsize); 891*832dc76bSMariusz Zaborski salen = (socklen_t)sabinsize; 892*832dc76bSMariusz Zaborski 893*832dc76bSMariusz Zaborski if ((sast.ss_family != AF_INET || 894*832dc76bSMariusz Zaborski salen != sizeof(struct sockaddr_in)) && 895*832dc76bSMariusz Zaborski (sast.ss_family != AF_INET6 || 896*832dc76bSMariusz Zaborski salen != sizeof(struct sockaddr_in6))) { 897*832dc76bSMariusz Zaborski error = EAI_FAIL; 898*832dc76bSMariusz Zaborski goto out; 899*832dc76bSMariusz Zaborski } 900*832dc76bSMariusz Zaborski 901*832dc76bSMariusz Zaborski if (!net_allowed_family(funclimit, (int)sast.ss_family)) { 902*832dc76bSMariusz Zaborski error = ENOTCAPABLE; 903*832dc76bSMariusz Zaborski goto out; 904*832dc76bSMariusz Zaborski } 905*832dc76bSMariusz Zaborski 906*832dc76bSMariusz Zaborski flags = (int)nvlist_get_number(nvlin, "flags"); 907*832dc76bSMariusz Zaborski 908*832dc76bSMariusz Zaborski error = getnameinfo((struct sockaddr *)&sast, salen, host, hostlen, 909*832dc76bSMariusz Zaborski serv, servlen, flags); 910*832dc76bSMariusz Zaborski if (error != 0) 911*832dc76bSMariusz Zaborski goto out; 912*832dc76bSMariusz Zaborski 913*832dc76bSMariusz Zaborski if (host != NULL) 914*832dc76bSMariusz Zaborski nvlist_move_string(nvlout, "host", host); 915*832dc76bSMariusz Zaborski if (serv != NULL) 916*832dc76bSMariusz Zaborski nvlist_move_string(nvlout, "serv", serv); 917*832dc76bSMariusz Zaborski out: 918*832dc76bSMariusz Zaborski if (error != 0) { 919*832dc76bSMariusz Zaborski free(host); 920*832dc76bSMariusz Zaborski free(serv); 921*832dc76bSMariusz Zaborski } 922*832dc76bSMariusz Zaborski return (error); 923*832dc76bSMariusz Zaborski } 924*832dc76bSMariusz Zaborski 925*832dc76bSMariusz Zaborski static nvlist_t * 926*832dc76bSMariusz Zaborski addrinfo_pack(const struct addrinfo *ai) 927*832dc76bSMariusz Zaborski { 928*832dc76bSMariusz Zaborski nvlist_t *nvl; 929*832dc76bSMariusz Zaborski 930*832dc76bSMariusz Zaborski nvl = nvlist_create(0); 931*832dc76bSMariusz Zaborski nvlist_add_number(nvl, "ai_flags", (uint64_t)ai->ai_flags); 932*832dc76bSMariusz Zaborski nvlist_add_number(nvl, "ai_family", (uint64_t)ai->ai_family); 933*832dc76bSMariusz Zaborski nvlist_add_number(nvl, "ai_socktype", (uint64_t)ai->ai_socktype); 934*832dc76bSMariusz Zaborski nvlist_add_number(nvl, "ai_protocol", (uint64_t)ai->ai_protocol); 935*832dc76bSMariusz Zaborski nvlist_add_binary(nvl, "ai_addr", ai->ai_addr, (size_t)ai->ai_addrlen); 936*832dc76bSMariusz Zaborski if (ai->ai_canonname != NULL) 937*832dc76bSMariusz Zaborski nvlist_add_string(nvl, "ai_canonname", ai->ai_canonname); 938*832dc76bSMariusz Zaborski 939*832dc76bSMariusz Zaborski return (nvl); 940*832dc76bSMariusz Zaborski } 941*832dc76bSMariusz Zaborski 942*832dc76bSMariusz Zaborski static int 943*832dc76bSMariusz Zaborski net_getaddrinfo(const nvlist_t *limits, const nvlist_t *nvlin, nvlist_t *nvlout) 944*832dc76bSMariusz Zaborski { 945*832dc76bSMariusz Zaborski struct addrinfo hints, *hintsp, *res, *cur; 946*832dc76bSMariusz Zaborski const char *hostname, *servname; 947*832dc76bSMariusz Zaborski char nvlname[64]; 948*832dc76bSMariusz Zaborski nvlist_t *elem; 949*832dc76bSMariusz Zaborski unsigned int ii; 950*832dc76bSMariusz Zaborski int error, family, n; 951*832dc76bSMariusz Zaborski const nvlist_t *funclimit; 952*832dc76bSMariusz Zaborski bool dnscache; 953*832dc76bSMariusz Zaborski 954*832dc76bSMariusz Zaborski if (!net_allowed_mode(limits, CAPNET_NAME2ADDR)) 955*832dc76bSMariusz Zaborski return (ENOTCAPABLE); 956*832dc76bSMariusz Zaborski dnscache = net_allowed_mode(limits, CAPNET_CONNECTDNS); 957*832dc76bSMariusz Zaborski funclimit = dnvlist_get_nvlist(limits, LIMIT_NV_NAME2ADDR, NULL); 958*832dc76bSMariusz Zaborski 959*832dc76bSMariusz Zaborski hostname = dnvlist_get_string(nvlin, "hostname", NULL); 960*832dc76bSMariusz Zaborski servname = dnvlist_get_string(nvlin, "servname", NULL); 961*832dc76bSMariusz Zaborski if (nvlist_exists_number(nvlin, "hints.ai_flags")) { 962*832dc76bSMariusz Zaborski hints.ai_flags = (int)nvlist_get_number(nvlin, 963*832dc76bSMariusz Zaborski "hints.ai_flags"); 964*832dc76bSMariusz Zaborski hints.ai_family = (int)nvlist_get_number(nvlin, 965*832dc76bSMariusz Zaborski "hints.ai_family"); 966*832dc76bSMariusz Zaborski hints.ai_socktype = (int)nvlist_get_number(nvlin, 967*832dc76bSMariusz Zaborski "hints.ai_socktype"); 968*832dc76bSMariusz Zaborski hints.ai_protocol = (int)nvlist_get_number(nvlin, 969*832dc76bSMariusz Zaborski "hints.ai_protocol"); 970*832dc76bSMariusz Zaborski hints.ai_addrlen = 0; 971*832dc76bSMariusz Zaborski hints.ai_addr = NULL; 972*832dc76bSMariusz Zaborski hints.ai_canonname = NULL; 973*832dc76bSMariusz Zaborski hints.ai_next = NULL; 974*832dc76bSMariusz Zaborski hintsp = &hints; 975*832dc76bSMariusz Zaborski family = hints.ai_family; 976*832dc76bSMariusz Zaborski } else { 977*832dc76bSMariusz Zaborski hintsp = NULL; 978*832dc76bSMariusz Zaborski family = AF_UNSPEC; 979*832dc76bSMariusz Zaborski } 980*832dc76bSMariusz Zaborski 981*832dc76bSMariusz Zaborski if (!net_allowed_family(funclimit, family)) 982*832dc76bSMariusz Zaborski return (ENOTCAPABLE); 983*832dc76bSMariusz Zaborski if (!net_allowed_hosts(funclimit, hostname, servname)) 984*832dc76bSMariusz Zaborski return (ENOTCAPABLE); 985*832dc76bSMariusz Zaborski error = getaddrinfo(hostname, servname, hintsp, &res); 986*832dc76bSMariusz Zaborski if (error != 0) { 987*832dc76bSMariusz Zaborski goto out; 988*832dc76bSMariusz Zaborski } 989*832dc76bSMariusz Zaborski 990*832dc76bSMariusz Zaborski for (cur = res, ii = 0; cur != NULL; cur = cur->ai_next, ii++) { 991*832dc76bSMariusz Zaborski elem = addrinfo_pack(cur); 992*832dc76bSMariusz Zaborski n = snprintf(nvlname, sizeof(nvlname), "res%u", ii); 993*832dc76bSMariusz Zaborski assert(n > 0 && n < (int)sizeof(nvlname)); 994*832dc76bSMariusz Zaborski nvlist_move_nvlist(nvlout, nvlname, elem); 995*832dc76bSMariusz Zaborski if (dnscache) { 996*832dc76bSMariusz Zaborski net_add_sockaddr_to_cache(cur->ai_addr, 997*832dc76bSMariusz Zaborski cur->ai_addrlen, false); 998*832dc76bSMariusz Zaborski } 999*832dc76bSMariusz Zaborski } 1000*832dc76bSMariusz Zaborski 1001*832dc76bSMariusz Zaborski freeaddrinfo(res); 1002*832dc76bSMariusz Zaborski error = 0; 1003*832dc76bSMariusz Zaborski out: 1004*832dc76bSMariusz Zaborski return (error); 1005*832dc76bSMariusz Zaborski } 1006*832dc76bSMariusz Zaborski 1007*832dc76bSMariusz Zaborski static int 1008*832dc76bSMariusz Zaborski net_bind(const nvlist_t *limits, nvlist_t *nvlin, nvlist_t *nvlout) 1009*832dc76bSMariusz Zaborski { 1010*832dc76bSMariusz Zaborski int socket, serrno; 1011*832dc76bSMariusz Zaborski const void *saddr; 1012*832dc76bSMariusz Zaborski size_t len; 1013*832dc76bSMariusz Zaborski const nvlist_t *funclimit; 1014*832dc76bSMariusz Zaborski 1015*832dc76bSMariusz Zaborski if (!net_allowed_mode(limits, CAPNET_BIND)) 1016*832dc76bSMariusz Zaborski return (ENOTCAPABLE); 1017*832dc76bSMariusz Zaborski funclimit = dnvlist_get_nvlist(limits, LIMIT_NV_BIND, NULL); 1018*832dc76bSMariusz Zaborski 1019*832dc76bSMariusz Zaborski saddr = nvlist_get_binary(nvlin, "saddr", &len); 1020*832dc76bSMariusz Zaborski 1021*832dc76bSMariusz Zaborski if (!net_allowed_bsaddr(funclimit, saddr, len)) 1022*832dc76bSMariusz Zaborski return (ENOTCAPABLE); 1023*832dc76bSMariusz Zaborski 1024*832dc76bSMariusz Zaborski socket = nvlist_take_descriptor(nvlin, "s"); 1025*832dc76bSMariusz Zaborski if (bind(socket, saddr, len) < 0) { 1026*832dc76bSMariusz Zaborski serrno = errno; 1027*832dc76bSMariusz Zaborski close(socket); 1028*832dc76bSMariusz Zaborski return (serrno); 1029*832dc76bSMariusz Zaborski } 1030*832dc76bSMariusz Zaborski 1031*832dc76bSMariusz Zaborski nvlist_move_descriptor(nvlout, "s", socket); 1032*832dc76bSMariusz Zaborski 1033*832dc76bSMariusz Zaborski return (0); 1034*832dc76bSMariusz Zaborski } 1035*832dc76bSMariusz Zaborski 1036*832dc76bSMariusz Zaborski static int 1037*832dc76bSMariusz Zaborski net_connect(const nvlist_t *limits, nvlist_t *nvlin, nvlist_t *nvlout) 1038*832dc76bSMariusz Zaborski { 1039*832dc76bSMariusz Zaborski int socket, serrno; 1040*832dc76bSMariusz Zaborski const void *saddr; 1041*832dc76bSMariusz Zaborski const nvlist_t *funclimit; 1042*832dc76bSMariusz Zaborski size_t len; 1043*832dc76bSMariusz Zaborski bool conn, conndns; 1044*832dc76bSMariusz Zaborski 1045*832dc76bSMariusz Zaborski conn = net_allowed_mode(limits, CAPNET_CONNECT); 1046*832dc76bSMariusz Zaborski conndns = net_allowed_mode(limits, CAPNET_CONNECTDNS); 1047*832dc76bSMariusz Zaborski 1048*832dc76bSMariusz Zaborski if (!conn && !conndns) 1049*832dc76bSMariusz Zaborski return (ENOTCAPABLE); 1050*832dc76bSMariusz Zaborski 1051*832dc76bSMariusz Zaborski funclimit = dnvlist_get_nvlist(limits, LIMIT_NV_CONNECT, NULL); 1052*832dc76bSMariusz Zaborski 1053*832dc76bSMariusz Zaborski saddr = nvlist_get_binary(nvlin, "saddr", &len); 1054*832dc76bSMariusz Zaborski if (conn && !net_allowed_bsaddr(funclimit, saddr, len)) { 1055*832dc76bSMariusz Zaborski return (ENOTCAPABLE); 1056*832dc76bSMariusz Zaborski } else if (conndns && (capdnscache == NULL || 1057*832dc76bSMariusz Zaborski !net_allowed_bsaddr_impl(capdnscache, saddr, len))) { 1058*832dc76bSMariusz Zaborski return (ENOTCAPABLE); 1059*832dc76bSMariusz Zaborski } 1060*832dc76bSMariusz Zaborski socket = dup(nvlist_get_descriptor(nvlin, "s")); 1061*832dc76bSMariusz Zaborski if (connect(socket, saddr, len) < 0) { 1062*832dc76bSMariusz Zaborski serrno = errno; 1063*832dc76bSMariusz Zaborski close(socket); 1064*832dc76bSMariusz Zaborski return (serrno); 1065*832dc76bSMariusz Zaborski } 1066*832dc76bSMariusz Zaborski 1067*832dc76bSMariusz Zaborski nvlist_move_descriptor(nvlout, "s", socket); 1068*832dc76bSMariusz Zaborski 1069*832dc76bSMariusz Zaborski return (0); 1070*832dc76bSMariusz Zaborski } 1071*832dc76bSMariusz Zaborski 1072*832dc76bSMariusz Zaborski static bool 1073*832dc76bSMariusz Zaborski verify_only_sa_newlimts(const nvlist_t *oldfunclimits, 1074*832dc76bSMariusz Zaborski const nvlist_t *newfunclimit) 1075*832dc76bSMariusz Zaborski { 1076*832dc76bSMariusz Zaborski void *cookie; 1077*832dc76bSMariusz Zaborski 1078*832dc76bSMariusz Zaborski cookie = NULL; 1079*832dc76bSMariusz Zaborski while (nvlist_next(newfunclimit, NULL, &cookie) != NULL) { 1080*832dc76bSMariusz Zaborski void *sacookie; 1081*832dc76bSMariusz Zaborski 1082*832dc76bSMariusz Zaborski if (strcmp(cnvlist_name(cookie), "sockaddr") != 0) 1083*832dc76bSMariusz Zaborski return (false); 1084*832dc76bSMariusz Zaborski 1085*832dc76bSMariusz Zaborski if (cnvlist_type(cookie) != NV_TYPE_NVLIST) 1086*832dc76bSMariusz Zaborski return (false); 1087*832dc76bSMariusz Zaborski 1088*832dc76bSMariusz Zaborski sacookie = NULL; 1089*832dc76bSMariusz Zaborski while (nvlist_next(cnvlist_get_nvlist(cookie), NULL, 1090*832dc76bSMariusz Zaborski &sacookie) != NULL) { 1091*832dc76bSMariusz Zaborski const void *sa; 1092*832dc76bSMariusz Zaborski size_t sasize; 1093*832dc76bSMariusz Zaborski 1094*832dc76bSMariusz Zaborski if (cnvlist_type(sacookie) != NV_TYPE_BINARY) 1095*832dc76bSMariusz Zaborski return (false); 1096*832dc76bSMariusz Zaborski 1097*832dc76bSMariusz Zaborski sa = cnvlist_get_binary(sacookie, &sasize); 1098*832dc76bSMariusz Zaborski if (!net_allowed_bsaddr(oldfunclimits, sa, sasize)) 1099*832dc76bSMariusz Zaborski return (false); 1100*832dc76bSMariusz Zaborski } 1101*832dc76bSMariusz Zaborski } 1102*832dc76bSMariusz Zaborski 1103*832dc76bSMariusz Zaborski return (true); 1104*832dc76bSMariusz Zaborski } 1105*832dc76bSMariusz Zaborski 1106*832dc76bSMariusz Zaborski static bool 1107*832dc76bSMariusz Zaborski verify_bind_newlimts(const nvlist_t *oldlimits, 1108*832dc76bSMariusz Zaborski const nvlist_t *newfunclimit) 1109*832dc76bSMariusz Zaborski { 1110*832dc76bSMariusz Zaborski const nvlist_t *oldfunclimits; 1111*832dc76bSMariusz Zaborski 1112*832dc76bSMariusz Zaborski oldfunclimits = NULL; 1113*832dc76bSMariusz Zaborski if (oldlimits != NULL) { 1114*832dc76bSMariusz Zaborski oldfunclimits = dnvlist_get_nvlist(oldlimits, LIMIT_NV_BIND, 1115*832dc76bSMariusz Zaborski NULL); 1116*832dc76bSMariusz Zaborski } 1117*832dc76bSMariusz Zaborski 1118*832dc76bSMariusz Zaborski return (verify_only_sa_newlimts(oldfunclimits, newfunclimit)); 1119*832dc76bSMariusz Zaborski } 1120*832dc76bSMariusz Zaborski 1121*832dc76bSMariusz Zaborski 1122*832dc76bSMariusz Zaborski static bool 1123*832dc76bSMariusz Zaborski verify_connect_newlimits(const nvlist_t *oldlimits, 1124*832dc76bSMariusz Zaborski const nvlist_t *newfunclimit) 1125*832dc76bSMariusz Zaborski { 1126*832dc76bSMariusz Zaborski const nvlist_t *oldfunclimits; 1127*832dc76bSMariusz Zaborski 1128*832dc76bSMariusz Zaborski oldfunclimits = NULL; 1129*832dc76bSMariusz Zaborski if (oldlimits != NULL) { 1130*832dc76bSMariusz Zaborski oldfunclimits = dnvlist_get_nvlist(oldlimits, LIMIT_NV_CONNECT, 1131*832dc76bSMariusz Zaborski NULL); 1132*832dc76bSMariusz Zaborski } 1133*832dc76bSMariusz Zaborski 1134*832dc76bSMariusz Zaborski return (verify_only_sa_newlimts(oldfunclimits, newfunclimit)); 1135*832dc76bSMariusz Zaborski } 1136*832dc76bSMariusz Zaborski 1137*832dc76bSMariusz Zaborski static bool 1138*832dc76bSMariusz Zaborski verify_addr2name_newlimits(const nvlist_t *oldlimits, 1139*832dc76bSMariusz Zaborski const nvlist_t *newfunclimit) 1140*832dc76bSMariusz Zaborski { 1141*832dc76bSMariusz Zaborski void *cookie; 1142*832dc76bSMariusz Zaborski const nvlist_t *oldfunclimits; 1143*832dc76bSMariusz Zaborski 1144*832dc76bSMariusz Zaborski oldfunclimits = NULL; 1145*832dc76bSMariusz Zaborski if (oldlimits != NULL) { 1146*832dc76bSMariusz Zaborski oldfunclimits = dnvlist_get_nvlist(oldlimits, 1147*832dc76bSMariusz Zaborski LIMIT_NV_ADDR2NAME, NULL); 1148*832dc76bSMariusz Zaborski } 1149*832dc76bSMariusz Zaborski 1150*832dc76bSMariusz Zaborski cookie = NULL; 1151*832dc76bSMariusz Zaborski while (nvlist_next(newfunclimit, NULL, &cookie) != NULL) { 1152*832dc76bSMariusz Zaborski if (strcmp(cnvlist_name(cookie), "sockaddr") == 0) { 1153*832dc76bSMariusz Zaborski void *sacookie; 1154*832dc76bSMariusz Zaborski 1155*832dc76bSMariusz Zaborski if (cnvlist_type(cookie) != NV_TYPE_NVLIST) 1156*832dc76bSMariusz Zaborski return (false); 1157*832dc76bSMariusz Zaborski 1158*832dc76bSMariusz Zaborski sacookie = NULL; 1159*832dc76bSMariusz Zaborski while (nvlist_next(cnvlist_get_nvlist(cookie), NULL, 1160*832dc76bSMariusz Zaborski &sacookie) != NULL) { 1161*832dc76bSMariusz Zaborski const void *sa; 1162*832dc76bSMariusz Zaborski size_t sasize; 1163*832dc76bSMariusz Zaborski 1164*832dc76bSMariusz Zaborski if (cnvlist_type(sacookie) != NV_TYPE_BINARY) 1165*832dc76bSMariusz Zaborski return (false); 1166*832dc76bSMariusz Zaborski 1167*832dc76bSMariusz Zaborski sa = cnvlist_get_binary(sacookie, &sasize); 1168*832dc76bSMariusz Zaborski if (!net_allowed_bsaddr(oldfunclimits, sa, 1169*832dc76bSMariusz Zaborski sasize)) { 1170*832dc76bSMariusz Zaborski return (false); 1171*832dc76bSMariusz Zaborski } 1172*832dc76bSMariusz Zaborski } 1173*832dc76bSMariusz Zaborski } else if (strcmp(cnvlist_name(cookie), "family") == 0) { 1174*832dc76bSMariusz Zaborski size_t i, sfamilies; 1175*832dc76bSMariusz Zaborski const uint64_t *families; 1176*832dc76bSMariusz Zaborski 1177*832dc76bSMariusz Zaborski if (cnvlist_type(cookie) != NV_TYPE_NUMBER_ARRAY) 1178*832dc76bSMariusz Zaborski return (false); 1179*832dc76bSMariusz Zaborski 1180*832dc76bSMariusz Zaborski families = cnvlist_get_number_array(cookie, &sfamilies); 1181*832dc76bSMariusz Zaborski for (i = 0; i < sfamilies; i++) { 1182*832dc76bSMariusz Zaborski if (!net_allowed_family(oldfunclimits, 1183*832dc76bSMariusz Zaborski families[i])) { 1184*832dc76bSMariusz Zaborski return (false); 1185*832dc76bSMariusz Zaborski } 1186*832dc76bSMariusz Zaborski } 1187*832dc76bSMariusz Zaborski } else { 1188*832dc76bSMariusz Zaborski return (false); 1189*832dc76bSMariusz Zaborski } 1190*832dc76bSMariusz Zaborski } 1191*832dc76bSMariusz Zaborski 1192*832dc76bSMariusz Zaborski return (true); 1193*832dc76bSMariusz Zaborski } 1194*832dc76bSMariusz Zaborski 1195*832dc76bSMariusz Zaborski static bool 1196*832dc76bSMariusz Zaborski verify_name2addr_newlimits(const nvlist_t *oldlimits, 1197*832dc76bSMariusz Zaborski const nvlist_t *newfunclimit) 1198*832dc76bSMariusz Zaborski { 1199*832dc76bSMariusz Zaborski void *cookie; 1200*832dc76bSMariusz Zaborski const nvlist_t *oldfunclimits; 1201*832dc76bSMariusz Zaborski 1202*832dc76bSMariusz Zaborski oldfunclimits = NULL; 1203*832dc76bSMariusz Zaborski if (oldlimits != NULL) { 1204*832dc76bSMariusz Zaborski oldfunclimits = dnvlist_get_nvlist(oldlimits, 1205*832dc76bSMariusz Zaborski LIMIT_NV_ADDR2NAME, NULL); 1206*832dc76bSMariusz Zaborski } 1207*832dc76bSMariusz Zaborski 1208*832dc76bSMariusz Zaborski cookie = NULL; 1209*832dc76bSMariusz Zaborski while (nvlist_next(newfunclimit, NULL, &cookie) != NULL) { 1210*832dc76bSMariusz Zaborski if (strcmp(cnvlist_name(cookie), "hosts") == 0) { 1211*832dc76bSMariusz Zaborski void *hostcookie; 1212*832dc76bSMariusz Zaborski 1213*832dc76bSMariusz Zaborski if (cnvlist_type(cookie) != NV_TYPE_NVLIST) 1214*832dc76bSMariusz Zaborski return (false); 1215*832dc76bSMariusz Zaborski 1216*832dc76bSMariusz Zaborski hostcookie = NULL; 1217*832dc76bSMariusz Zaborski while (nvlist_next(cnvlist_get_nvlist(cookie), NULL, 1218*832dc76bSMariusz Zaborski &hostcookie) != NULL) { 1219*832dc76bSMariusz Zaborski if (cnvlist_type(hostcookie) != NV_TYPE_STRING) 1220*832dc76bSMariusz Zaborski return (false); 1221*832dc76bSMariusz Zaborski 1222*832dc76bSMariusz Zaborski if (!net_allowed_hosts(oldfunclimits, 1223*832dc76bSMariusz Zaborski cnvlist_name(hostcookie), 1224*832dc76bSMariusz Zaborski cnvlist_get_string(hostcookie))) { 1225*832dc76bSMariusz Zaborski return (false); 1226*832dc76bSMariusz Zaborski } 1227*832dc76bSMariusz Zaborski } 1228*832dc76bSMariusz Zaborski } else if (strcmp(cnvlist_name(cookie), "family") == 0) { 1229*832dc76bSMariusz Zaborski size_t i, sfamilies; 1230*832dc76bSMariusz Zaborski const uint64_t *families; 1231*832dc76bSMariusz Zaborski 1232*832dc76bSMariusz Zaborski if (cnvlist_type(cookie) != NV_TYPE_NUMBER_ARRAY) 1233*832dc76bSMariusz Zaborski return (false); 1234*832dc76bSMariusz Zaborski 1235*832dc76bSMariusz Zaborski families = cnvlist_get_number_array(cookie, &sfamilies); 1236*832dc76bSMariusz Zaborski for (i = 0; i < sfamilies; i++) { 1237*832dc76bSMariusz Zaborski if (!net_allowed_family(oldfunclimits, 1238*832dc76bSMariusz Zaborski families[i])) { 1239*832dc76bSMariusz Zaborski return (false); 1240*832dc76bSMariusz Zaborski } 1241*832dc76bSMariusz Zaborski } 1242*832dc76bSMariusz Zaborski } else { 1243*832dc76bSMariusz Zaborski return (false); 1244*832dc76bSMariusz Zaborski } 1245*832dc76bSMariusz Zaborski } 1246*832dc76bSMariusz Zaborski 1247*832dc76bSMariusz Zaborski return (true); 1248*832dc76bSMariusz Zaborski } 1249*832dc76bSMariusz Zaborski 1250*832dc76bSMariusz Zaborski static int 1251*832dc76bSMariusz Zaborski net_limit(const nvlist_t *oldlimits, const nvlist_t *newlimits) 1252*832dc76bSMariusz Zaborski { 1253*832dc76bSMariusz Zaborski const char *name; 1254*832dc76bSMariusz Zaborski void *cookie; 1255*832dc76bSMariusz Zaborski bool hasmode, hasconnect, hasbind, hasaddr2name, hasname2addr; 1256*832dc76bSMariusz Zaborski 1257*832dc76bSMariusz Zaborski /* 1258*832dc76bSMariusz Zaborski * Modes: 1259*832dc76bSMariusz Zaborski * ADDR2NAME: 1260*832dc76bSMariusz Zaborski * getnameinfo 1261*832dc76bSMariusz Zaborski * DEPRECATED_ADDR2NAME: 1262*832dc76bSMariusz Zaborski * gethostbyaddr 1263*832dc76bSMariusz Zaborski * 1264*832dc76bSMariusz Zaborski * NAME2ADDR: 1265*832dc76bSMariusz Zaborski * getaddrinfo 1266*832dc76bSMariusz Zaborski * DEPRECATED_NAME2ADDR: 1267*832dc76bSMariusz Zaborski * gethostbyname 1268*832dc76bSMariusz Zaborski * 1269*832dc76bSMariusz Zaborski * Limit scheme: 1270*832dc76bSMariusz Zaborski * mode : NV_TYPE_NUMBER 1271*832dc76bSMariusz Zaborski * connect : NV_TYPE_NVLIST 1272*832dc76bSMariusz Zaborski * sockaddr : NV_TYPE_NVLIST 1273*832dc76bSMariusz Zaborski * "" : NV_TYPE_BINARY 1274*832dc76bSMariusz Zaborski * ... : NV_TYPE_BINARY 1275*832dc76bSMariusz Zaborski * bind : NV_TYPE_NVLIST 1276*832dc76bSMariusz Zaborski * sockaddr : NV_TYPE_NVLIST 1277*832dc76bSMariusz Zaborski * "" : NV_TYPE_BINARY 1278*832dc76bSMariusz Zaborski * ... : NV_TYPE_BINARY 1279*832dc76bSMariusz Zaborski * addr2name : NV_TYPE_NVLIST 1280*832dc76bSMariusz Zaborski * family : NV_TYPE_NUMBER_ARRAY 1281*832dc76bSMariusz Zaborski * sockaddr : NV_TYPE_NVLIST 1282*832dc76bSMariusz Zaborski * "" : NV_TYPE_BINARY 1283*832dc76bSMariusz Zaborski * ... : NV_TYPE_BINARY 1284*832dc76bSMariusz Zaborski * name2addr : NV_TYPE_NVLIST 1285*832dc76bSMariusz Zaborski * family : NV_TYPE_NUMBER 1286*832dc76bSMariusz Zaborski * hosts : NV_TYPE_NVLIST 1287*832dc76bSMariusz Zaborski * host : servname : NV_TYPE_STRING 1288*832dc76bSMariusz Zaborski */ 1289*832dc76bSMariusz Zaborski 1290*832dc76bSMariusz Zaborski hasmode = false; 1291*832dc76bSMariusz Zaborski hasconnect = false; 1292*832dc76bSMariusz Zaborski hasbind = false; 1293*832dc76bSMariusz Zaborski hasaddr2name = false; 1294*832dc76bSMariusz Zaborski hasname2addr = false; 1295*832dc76bSMariusz Zaborski 1296*832dc76bSMariusz Zaborski cookie = NULL; 1297*832dc76bSMariusz Zaborski while ((name = nvlist_next(newlimits, NULL, &cookie)) != NULL) { 1298*832dc76bSMariusz Zaborski if (strcmp(name, "mode") == 0) { 1299*832dc76bSMariusz Zaborski if (cnvlist_type(cookie) != NV_TYPE_NUMBER) { 1300*832dc76bSMariusz Zaborski return (NO_RECOVERY); 1301*832dc76bSMariusz Zaborski } 1302*832dc76bSMariusz Zaborski if (!net_allowed_mode(oldlimits, 1303*832dc76bSMariusz Zaborski cnvlist_get_number(cookie))) { 1304*832dc76bSMariusz Zaborski return (ENOTCAPABLE); 1305*832dc76bSMariusz Zaborski } 1306*832dc76bSMariusz Zaborski hasmode = true; 1307*832dc76bSMariusz Zaborski continue; 1308*832dc76bSMariusz Zaborski } 1309*832dc76bSMariusz Zaborski 1310*832dc76bSMariusz Zaborski if (cnvlist_type(cookie) != NV_TYPE_NVLIST) { 1311*832dc76bSMariusz Zaborski return (NO_RECOVERY); 1312*832dc76bSMariusz Zaborski } 1313*832dc76bSMariusz Zaborski 1314*832dc76bSMariusz Zaborski if (strcmp(name, LIMIT_NV_BIND) == 0) { 1315*832dc76bSMariusz Zaborski hasbind = true; 1316*832dc76bSMariusz Zaborski if (!verify_bind_newlimts(oldlimits, 1317*832dc76bSMariusz Zaborski cnvlist_get_nvlist(cookie))) { 1318*832dc76bSMariusz Zaborski return (ENOTCAPABLE); 1319*832dc76bSMariusz Zaborski } 1320*832dc76bSMariusz Zaborski } else if (strcmp(name, LIMIT_NV_CONNECT) == 0) { 1321*832dc76bSMariusz Zaborski hasconnect = true; 1322*832dc76bSMariusz Zaborski if (!verify_connect_newlimits(oldlimits, 1323*832dc76bSMariusz Zaborski cnvlist_get_nvlist(cookie))) { 1324*832dc76bSMariusz Zaborski return (ENOTCAPABLE); 1325*832dc76bSMariusz Zaborski } 1326*832dc76bSMariusz Zaborski } else if (strcmp(name, LIMIT_NV_ADDR2NAME) == 0) { 1327*832dc76bSMariusz Zaborski hasaddr2name = true; 1328*832dc76bSMariusz Zaborski if (!verify_addr2name_newlimits(oldlimits, 1329*832dc76bSMariusz Zaborski cnvlist_get_nvlist(cookie))) { 1330*832dc76bSMariusz Zaborski return (ENOTCAPABLE); 1331*832dc76bSMariusz Zaborski } 1332*832dc76bSMariusz Zaborski } else if (strcmp(name, LIMIT_NV_NAME2ADDR) == 0) { 1333*832dc76bSMariusz Zaborski hasname2addr = true; 1334*832dc76bSMariusz Zaborski if (!verify_name2addr_newlimits(oldlimits, 1335*832dc76bSMariusz Zaborski cnvlist_get_nvlist(cookie))) { 1336*832dc76bSMariusz Zaborski return (ENOTCAPABLE); 1337*832dc76bSMariusz Zaborski } 1338*832dc76bSMariusz Zaborski } 1339*832dc76bSMariusz Zaborski } 1340*832dc76bSMariusz Zaborski 1341*832dc76bSMariusz Zaborski /* Mode is required. */ 1342*832dc76bSMariusz Zaborski if (!hasmode) 1343*832dc76bSMariusz Zaborski return (ENOTCAPABLE); 1344*832dc76bSMariusz Zaborski 1345*832dc76bSMariusz Zaborski /* 1346*832dc76bSMariusz Zaborski * If the new limit doesn't mention mode or family we have to 1347*832dc76bSMariusz Zaborski * check if the current limit does have those. Missing mode or 1348*832dc76bSMariusz Zaborski * family in the limit means that all modes or families are 1349*832dc76bSMariusz Zaborski * allowed. 1350*832dc76bSMariusz Zaborski */ 1351*832dc76bSMariusz Zaborski if (oldlimits == NULL) 1352*832dc76bSMariusz Zaborski return (0); 1353*832dc76bSMariusz Zaborski if (!hasconnect && nvlist_exists(oldlimits, LIMIT_NV_BIND)) 1354*832dc76bSMariusz Zaborski return (ENOTCAPABLE); 1355*832dc76bSMariusz Zaborski if (!hasconnect && nvlist_exists(oldlimits, LIMIT_NV_CONNECT)) 1356*832dc76bSMariusz Zaborski return (ENOTCAPABLE); 1357*832dc76bSMariusz Zaborski if (!hasaddr2name && nvlist_exists(oldlimits, LIMIT_NV_ADDR2NAME)) 1358*832dc76bSMariusz Zaborski return (ENOTCAPABLE); 1359*832dc76bSMariusz Zaborski if (!hasname2addr && nvlist_exists(oldlimits, LIMIT_NV_NAME2ADDR)) 1360*832dc76bSMariusz Zaborski return (ENOTCAPABLE); 1361*832dc76bSMariusz Zaborski return (0); 1362*832dc76bSMariusz Zaborski } 1363*832dc76bSMariusz Zaborski 1364*832dc76bSMariusz Zaborski static int 1365*832dc76bSMariusz Zaborski net_command(const char *cmd, const nvlist_t *limits, nvlist_t *nvlin, 1366*832dc76bSMariusz Zaborski nvlist_t *nvlout) 1367*832dc76bSMariusz Zaborski { 1368*832dc76bSMariusz Zaborski 1369*832dc76bSMariusz Zaborski if (strcmp(cmd, "bind") == 0) 1370*832dc76bSMariusz Zaborski return (net_bind(limits, nvlin, nvlout)); 1371*832dc76bSMariusz Zaborski else if (strcmp(cmd, "connect") == 0) 1372*832dc76bSMariusz Zaborski return (net_connect(limits, nvlin, nvlout)); 1373*832dc76bSMariusz Zaborski else if (strcmp(cmd, "gethostbyname") == 0) 1374*832dc76bSMariusz Zaborski return (net_gethostbyname(limits, nvlin, nvlout)); 1375*832dc76bSMariusz Zaborski else if (strcmp(cmd, "gethostbyaddr") == 0) 1376*832dc76bSMariusz Zaborski return (net_gethostbyaddr(limits, nvlin, nvlout)); 1377*832dc76bSMariusz Zaborski else if (strcmp(cmd, "getnameinfo") == 0) 1378*832dc76bSMariusz Zaborski return (net_getnameinfo(limits, nvlin, nvlout)); 1379*832dc76bSMariusz Zaborski else if (strcmp(cmd, "getaddrinfo") == 0) 1380*832dc76bSMariusz Zaborski return (net_getaddrinfo(limits, nvlin, nvlout)); 1381*832dc76bSMariusz Zaborski 1382*832dc76bSMariusz Zaborski return (EINVAL); 1383*832dc76bSMariusz Zaborski } 1384*832dc76bSMariusz Zaborski 1385*832dc76bSMariusz Zaborski CREATE_SERVICE("system.net", net_limit, net_command, 0); 1386