1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 /* 26 * This file contains functions for address management such as creating 27 * an address, deleting an address, enabling an address, disabling an 28 * address, bringing an address down or up, setting/getting properties 29 * on an address object and listing address information 30 * for all addresses in active as well as persistent configuration. 31 */ 32 #include <sys/types.h> 33 #include <sys/socket.h> 34 #include <netdb.h> 35 #include <inet/ip.h> 36 #include <string.h> 37 #include <strings.h> 38 #include <assert.h> 39 #include <sys/sockio.h> 40 #include <errno.h> 41 #include <unistd.h> 42 #include <stropts.h> 43 #include <zone.h> 44 #include <netinet/in.h> 45 #include <arpa/inet.h> 46 #include <fcntl.h> 47 #include <ctype.h> 48 #include <dhcpagent_util.h> 49 #include <dhcpagent_ipc.h> 50 #include <ipadm_ndpd.h> 51 #include <libdladm.h> 52 #include <libdllink.h> 53 #include <libdliptun.h> 54 #include <ifaddrs.h> 55 #include "libipadm_impl.h" 56 57 #define SIN6(a) ((struct sockaddr_in6 *)a) 58 #define SIN(a) ((struct sockaddr_in *)a) 59 60 static ipadm_status_t i_ipadm_create_addr(ipadm_handle_t, ipadm_addrobj_t, 61 uint32_t); 62 static ipadm_status_t i_ipadm_create_dhcp(ipadm_handle_t, ipadm_addrobj_t, 63 uint32_t); 64 static ipadm_status_t i_ipadm_delete_dhcp(ipadm_handle_t, ipadm_addrobj_t, 65 boolean_t); 66 static ipadm_status_t i_ipadm_get_db_addr(ipadm_handle_t, const char *, 67 const char *, nvlist_t **); 68 static ipadm_status_t i_ipadm_op_dhcp(ipadm_addrobj_t, dhcp_ipc_type_t, 69 int *); 70 static ipadm_status_t i_ipadm_validate_create_addr(ipadm_handle_t, 71 ipadm_addrobj_t, uint32_t); 72 static ipadm_status_t i_ipadm_addr_persist_nvl(ipadm_handle_t, nvlist_t *, 73 uint32_t); 74 static ipadm_status_t i_ipadm_get_default_prefixlen(struct sockaddr_storage *, 75 uint32_t *); 76 static ipadm_status_t i_ipadm_get_static_addr_db(ipadm_handle_t, 77 ipadm_addrobj_t); 78 static boolean_t i_ipadm_is_user_aobjname_valid(const char *); 79 80 /* 81 * Callback functions to retrieve property values from the kernel. These 82 * functions, when required, translate the values from the kernel to a format 83 * suitable for printing. They also retrieve DEFAULT, PERM and POSSIBLE values 84 * for a given property. 85 */ 86 static ipadm_pd_getf_t i_ipadm_get_prefixlen, i_ipadm_get_addr_flag, 87 i_ipadm_get_zone, i_ipadm_get_broadcast; 88 89 /* 90 * Callback functions to set property values. These functions translate the 91 * values to a format suitable for kernel consumption, allocate the necessary 92 * ioctl buffers and then invoke ioctl(). 93 */ 94 static ipadm_pd_setf_t i_ipadm_set_prefixlen, i_ipadm_set_addr_flag, 95 i_ipadm_set_zone; 96 97 /* address properties description table */ 98 ipadm_prop_desc_t ipadm_addrprop_table[] = { 99 { "broadcast", IPADMPROP_CLASS_ADDR, MOD_PROTO_NONE, 0, 100 NULL, NULL, i_ipadm_get_broadcast }, 101 102 { "deprecated", IPADMPROP_CLASS_ADDR, MOD_PROTO_NONE, 0, 103 i_ipadm_set_addr_flag, i_ipadm_get_onoff, 104 i_ipadm_get_addr_flag }, 105 106 { "prefixlen", IPADMPROP_CLASS_ADDR, MOD_PROTO_NONE, 0, 107 i_ipadm_set_prefixlen, i_ipadm_get_prefixlen, 108 i_ipadm_get_prefixlen }, 109 110 { "private", IPADMPROP_CLASS_ADDR, MOD_PROTO_NONE, 0, 111 i_ipadm_set_addr_flag, i_ipadm_get_onoff, i_ipadm_get_addr_flag }, 112 113 { "transmit", IPADMPROP_CLASS_ADDR, MOD_PROTO_NONE, 0, 114 i_ipadm_set_addr_flag, i_ipadm_get_onoff, i_ipadm_get_addr_flag }, 115 116 { "zone", IPADMPROP_CLASS_ADDR, MOD_PROTO_NONE, 0, 117 i_ipadm_set_zone, NULL, i_ipadm_get_zone }, 118 119 { NULL, 0, 0, 0, NULL, NULL, NULL } 120 }; 121 122 static ipadm_prop_desc_t up_addrprop = { "up", IPADMPROP_CLASS_ADDR, 123 MOD_PROTO_NONE, 0, NULL, NULL, NULL }; 124 125 /* 126 * Helper function that initializes the `ipadm_ifname', `ipadm_aobjname', and 127 * `ipadm_atype' fields of the given `ipaddr'. 128 */ 129 void 130 i_ipadm_init_addr(ipadm_addrobj_t ipaddr, const char *ifname, 131 const char *aobjname, ipadm_addr_type_t atype) 132 { 133 bzero(ipaddr, sizeof (struct ipadm_addrobj_s)); 134 (void) strlcpy(ipaddr->ipadm_ifname, ifname, 135 sizeof (ipaddr->ipadm_ifname)); 136 (void) strlcpy(ipaddr->ipadm_aobjname, aobjname, 137 sizeof (ipaddr->ipadm_aobjname)); 138 ipaddr->ipadm_atype = atype; 139 } 140 141 /* 142 * Determine the permission of the property depending on whether it has a 143 * set() and/or get() callback functions. 144 */ 145 static ipadm_status_t 146 i_ipadm_pd2permstr(ipadm_prop_desc_t *pdp, char *buf, uint_t *bufsize) 147 { 148 uint_t perm; 149 size_t nbytes; 150 151 perm = 0; 152 if (pdp->ipd_set != NULL) 153 perm |= MOD_PROP_PERM_WRITE; 154 if (pdp->ipd_get != NULL) 155 perm |= MOD_PROP_PERM_READ; 156 157 nbytes = snprintf(buf, *bufsize, "%c%c", 158 ((perm & MOD_PROP_PERM_READ) != 0) ? 'r' : '-', 159 ((perm & MOD_PROP_PERM_WRITE) != 0) ? 'w' : '-'); 160 161 if (nbytes >= *bufsize) { 162 /* insufficient buffer space */ 163 *bufsize = nbytes + 1; 164 return (IPADM_NO_BUFS); 165 } 166 return (IPADM_SUCCESS); 167 } 168 169 /* 170 * Given an addrobj with `ipadm_aobjname' filled in, i_ipadm_get_addrobj() 171 * retrieves the information necessary for any operation on the object, 172 * such as delete-addr, enable-addr, disable-addr, up-addr, down-addr, 173 * refresh-addr, get-addrprop or set-addrprop. The information include 174 * the logical interface number, address type, address family, 175 * the interface id (if the address type is IPADM_ADDR_IPV6_ADDRCONF) and 176 * the ipadm_flags that indicate if the address is present in 177 * active configuration or persistent configuration or both. If the address 178 * is not found, IPADM_NOTSUP is returned. 179 */ 180 ipadm_status_t 181 i_ipadm_get_addrobj(ipadm_handle_t iph, ipadm_addrobj_t ipaddr) 182 { 183 ipmgmt_aobjop_arg_t larg; 184 ipmgmt_aobjop_rval_t rval, *rvalp; 185 int err = 0; 186 187 /* populate the door_call argument structure */ 188 larg.ia_cmd = IPMGMT_CMD_AOBJNAME2ADDROBJ; 189 (void) strlcpy(larg.ia_aobjname, ipaddr->ipadm_aobjname, 190 sizeof (larg.ia_aobjname)); 191 192 rvalp = &rval; 193 err = ipadm_door_call(iph, &larg, sizeof (larg), (void **)&rvalp, 194 sizeof (rval), B_FALSE); 195 if (err != 0) 196 return (ipadm_errno2status(err)); 197 (void) strlcpy(ipaddr->ipadm_ifname, rval.ir_ifname, 198 sizeof (ipaddr->ipadm_ifname)); 199 ipaddr->ipadm_lifnum = rval.ir_lnum; 200 ipaddr->ipadm_atype = rval.ir_atype; 201 ipaddr->ipadm_af = rval.ir_family; 202 ipaddr->ipadm_flags = rval.ir_flags; 203 if (rval.ir_atype == IPADM_ADDR_IPV6_ADDRCONF) { 204 (void) memcpy(&ipaddr->ipadm_intfid, &rval.ir_ifid, 205 sizeof (ipaddr->ipadm_intfid)); 206 } 207 208 return (IPADM_SUCCESS); 209 } 210 211 /* 212 * Retrieves the static address (IPv4 or IPv6) for the given address object 213 * in `ipaddr' from persistent DB. 214 */ 215 static ipadm_status_t 216 i_ipadm_get_static_addr_db(ipadm_handle_t iph, ipadm_addrobj_t ipaddr) 217 { 218 ipadm_status_t status; 219 nvlist_t *onvl; 220 nvlist_t *anvl = NULL; 221 nvlist_t *nvladdr; 222 nvpair_t *nvp; 223 char *name; 224 char *aobjname = ipaddr->ipadm_aobjname; 225 char *sname; 226 sa_family_t af = AF_UNSPEC; 227 228 /* 229 * Get the address line in the nvlist `onvl' from ipmgmtd daemon. 230 */ 231 status = i_ipadm_get_db_addr(iph, NULL, aobjname, &onvl); 232 if (status != IPADM_SUCCESS) 233 return (status); 234 /* 235 * Walk through the nvlist `onvl' to extract the IPADM_NVP_IPV4ADDR 236 * or the IPADM_NVP_IPV6ADDR name-value pair. 237 */ 238 for (nvp = nvlist_next_nvpair(onvl, NULL); nvp != NULL; 239 nvp = nvlist_next_nvpair(onvl, NULL)) { 240 if (nvpair_value_nvlist(nvp, &anvl) != 0) 241 continue; 242 if (nvlist_exists(anvl, IPADM_NVP_IPV4ADDR) || 243 nvlist_exists(anvl, IPADM_NVP_IPV6ADDR)) 244 break; 245 } 246 if (nvp == NULL) 247 goto fail; 248 for (nvp = nvlist_next_nvpair(anvl, NULL); 249 nvp != NULL; nvp = nvlist_next_nvpair(anvl, nvp)) { 250 name = nvpair_name(nvp); 251 if (strcmp(name, IPADM_NVP_IPV4ADDR) == 0) { 252 af = AF_INET; 253 break; 254 } else if (strcmp(name, IPADM_NVP_IPV6ADDR) == 0) { 255 af = AF_INET6; 256 break; 257 } 258 } 259 assert(af != AF_UNSPEC); 260 if (nvpair_value_nvlist(nvp, &nvladdr) != 0 || 261 nvlist_lookup_string(nvladdr, IPADM_NVP_IPADDRHNAME, &sname) != 0 || 262 ipadm_set_addr(ipaddr, sname, af) != IPADM_SUCCESS) { 263 goto fail; 264 } 265 nvlist_free(onvl); 266 return (IPADM_SUCCESS); 267 fail: 268 nvlist_free(onvl); 269 return (IPADM_NOTFOUND); 270 } 271 272 /* 273 * For the given `addrobj->ipadm_lifnum' and `addrobj->ipadm_af', this function 274 * fills in the address objname, the address type and the ipadm_flags. 275 */ 276 ipadm_status_t 277 i_ipadm_get_lif2addrobj(ipadm_handle_t iph, ipadm_addrobj_t addrobj) 278 { 279 ipmgmt_aobjop_arg_t larg; 280 ipmgmt_aobjop_rval_t rval, *rvalp; 281 int err; 282 283 larg.ia_cmd = IPMGMT_CMD_LIF2ADDROBJ; 284 (void) strlcpy(larg.ia_ifname, addrobj->ipadm_ifname, 285 sizeof (larg.ia_ifname)); 286 larg.ia_lnum = addrobj->ipadm_lifnum; 287 larg.ia_family = addrobj->ipadm_af; 288 289 rvalp = &rval; 290 err = ipadm_door_call(iph, &larg, sizeof (larg), (void **)&rvalp, 291 sizeof (rval), B_FALSE); 292 if (err != 0) 293 return (ipadm_errno2status(err)); 294 (void) strlcpy(addrobj->ipadm_aobjname, rval.ir_aobjname, 295 sizeof (addrobj->ipadm_aobjname)); 296 addrobj->ipadm_atype = rval.ir_atype; 297 addrobj->ipadm_flags = rval.ir_flags; 298 299 return (IPADM_SUCCESS); 300 } 301 302 /* 303 * Adds an addrobj to ipmgmtd daemon's aobjmap (active configuration). 304 * with the given name and logical interface number. 305 * This API is called by in.ndpd to add addrobjs when new prefixes or 306 * dhcpv6 addresses are configured. 307 */ 308 ipadm_status_t 309 ipadm_add_aobjname(ipadm_handle_t iph, const char *ifname, sa_family_t af, 310 const char *aobjname, ipadm_addr_type_t atype, int lnum) 311 { 312 ipmgmt_aobjop_arg_t larg; 313 int err; 314 315 larg.ia_cmd = IPMGMT_CMD_ADDROBJ_ADD; 316 (void) strlcpy(larg.ia_ifname, ifname, sizeof (larg.ia_ifname)); 317 (void) strlcpy(larg.ia_aobjname, aobjname, sizeof (larg.ia_aobjname)); 318 larg.ia_atype = atype; 319 larg.ia_lnum = lnum; 320 larg.ia_family = af; 321 err = ipadm_door_call(iph, &larg, sizeof (larg), NULL, 0, B_FALSE); 322 return (ipadm_errno2status(err)); 323 } 324 325 /* 326 * Deletes an address object with given name and logical number from ipmgmtd 327 * daemon's aobjmap (active configuration). This API is called by in.ndpd to 328 * remove addrobjs when auto-configured prefixes or dhcpv6 addresses are 329 * removed. 330 */ 331 ipadm_status_t 332 ipadm_delete_aobjname(ipadm_handle_t iph, const char *ifname, sa_family_t af, 333 const char *aobjname, ipadm_addr_type_t atype, int lnum) 334 { 335 struct ipadm_addrobj_s aobj; 336 337 i_ipadm_init_addr(&aobj, ifname, aobjname, atype); 338 aobj.ipadm_af = af; 339 aobj.ipadm_lifnum = lnum; 340 return (i_ipadm_delete_addrobj(iph, &aobj, IPADM_OPT_ACTIVE)); 341 } 342 343 /* 344 * Gets all the addresses from active configuration and populates the 345 * address information in `addrinfo'. 346 */ 347 static ipadm_status_t 348 i_ipadm_active_addr_info(ipadm_handle_t iph, const char *ifname, 349 ipadm_addr_info_t **addrinfo, uint32_t ipadm_flags, int64_t lifc_flags) 350 { 351 ipadm_status_t status; 352 struct ifaddrs *ifap, *ifa; 353 ipadm_addr_info_t *curr, *prev = NULL; 354 struct ifaddrs *cifaddr; 355 struct lifreq lifr; 356 int sock; 357 uint64_t flags; 358 char cifname[LIFNAMSIZ]; 359 struct sockaddr_in6 *sin6; 360 struct ipadm_addrobj_s ipaddr; 361 char *sep; 362 int lnum; 363 364 retry: 365 *addrinfo = NULL; 366 367 /* Get all the configured addresses */ 368 if (getallifaddrs(AF_UNSPEC, &ifa, lifc_flags) < 0) 369 return (ipadm_errno2status(errno)); 370 /* Return if there is nothing to process. */ 371 if (ifa == NULL) 372 return (IPADM_SUCCESS); 373 bzero(&lifr, sizeof (lifr)); 374 for (ifap = ifa; ifap != NULL; ifap = ifap->ifa_next) { 375 (void) strlcpy(cifname, ifap->ifa_name, sizeof (cifname)); 376 lnum = 0; 377 if ((sep = strrchr(cifname, ':')) != NULL) { 378 *sep++ = '\0'; 379 lnum = atoi(sep); 380 } 381 if (ifname != NULL && strcmp(cifname, ifname) != 0) 382 continue; 383 if (!(ipadm_flags & IPADM_OPT_ZEROADDR) && 384 sockaddrunspec(ifap->ifa_addr) && 385 !(ifap->ifa_flags & IFF_DHCPRUNNING)) 386 continue; 387 388 /* Allocate and populate the current node in the list. */ 389 if ((curr = calloc(1, sizeof (ipadm_addr_info_t))) == NULL) 390 goto fail; 391 392 /* Link to the list in `addrinfo'. */ 393 if (prev != NULL) 394 prev->ia_ifa.ifa_next = &curr->ia_ifa; 395 else 396 *addrinfo = curr; 397 prev = curr; 398 399 cifaddr = &curr->ia_ifa; 400 if ((cifaddr->ifa_name = strdup(ifap->ifa_name)) == NULL) 401 goto fail; 402 cifaddr->ifa_flags = ifap->ifa_flags; 403 cifaddr->ifa_addr = malloc(sizeof (struct sockaddr_storage)); 404 if (cifaddr->ifa_addr == NULL) 405 goto fail; 406 *cifaddr->ifa_addr = *ifap->ifa_addr; 407 cifaddr->ifa_netmask = malloc(sizeof (struct sockaddr_storage)); 408 if (cifaddr->ifa_netmask == NULL) 409 goto fail; 410 *cifaddr->ifa_netmask = *ifap->ifa_netmask; 411 if (ifap->ifa_flags & IFF_POINTOPOINT) { 412 cifaddr->ifa_dstaddr = malloc( 413 sizeof (struct sockaddr_storage)); 414 if (cifaddr->ifa_dstaddr == NULL) 415 goto fail; 416 *cifaddr->ifa_dstaddr = *ifap->ifa_dstaddr; 417 } else if (ifap->ifa_flags & IFF_BROADCAST) { 418 cifaddr->ifa_broadaddr = malloc( 419 sizeof (struct sockaddr_storage)); 420 if (cifaddr->ifa_broadaddr == NULL) 421 goto fail; 422 *cifaddr->ifa_broadaddr = *ifap->ifa_broadaddr; 423 } 424 /* Get the addrobj name stored for this logical interface. */ 425 ipaddr.ipadm_aobjname[0] = '\0'; 426 (void) strlcpy(ipaddr.ipadm_ifname, cifname, 427 sizeof (ipaddr.ipadm_ifname)); 428 ipaddr.ipadm_lifnum = lnum; 429 ipaddr.ipadm_af = ifap->ifa_addr->ss_family; 430 status = i_ipadm_get_lif2addrobj(iph, &ipaddr); 431 432 /* 433 * Find address type from ifa_flags, if we could not get it 434 * from daemon. 435 */ 436 sin6 = SIN6(ifap->ifa_addr); 437 flags = ifap->ifa_flags; 438 if (status == IPADM_SUCCESS) { 439 (void) strlcpy(curr->ia_aobjname, ipaddr.ipadm_aobjname, 440 sizeof (curr->ia_aobjname)); 441 curr->ia_atype = ipaddr.ipadm_atype; 442 } else if ((flags & IFF_DHCPRUNNING) && (!(flags & IFF_IPV6) || 443 !IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr))) { 444 curr->ia_atype = IPADM_ADDR_DHCP; 445 } else if (flags & IFF_ADDRCONF) { 446 curr->ia_atype = IPADM_ADDR_IPV6_ADDRCONF; 447 } else { 448 curr->ia_atype = IPADM_ADDR_STATIC; 449 } 450 /* 451 * Populate the flags for the active configuration from the 452 * `ifa_flags'. 453 */ 454 if (!(flags & IFF_UP)) { 455 if (flags & IFF_DUPLICATE) 456 curr->ia_state = IFA_DUPLICATE; 457 else 458 curr->ia_state = IFA_DOWN; 459 } else { 460 curr->ia_cflags |= IA_UP; 461 if (flags & IFF_RUNNING) { 462 (void) strlcpy(lifr.lifr_name, ifap->ifa_name, 463 sizeof (lifr.lifr_name)); 464 sock = (ifap->ifa_addr->ss_family == AF_INET) ? 465 iph->iph_sock : iph->iph_sock6; 466 if (ioctl(sock, SIOCGLIFDADSTATE, 467 (caddr_t)&lifr) < 0) { 468 if (errno == ENXIO) { 469 freeifaddrs(ifa); 470 ipadm_free_addr_info(*addrinfo); 471 goto retry; 472 } 473 goto fail; 474 } 475 if (lifr.lifr_dadstate == DAD_IN_PROGRESS) 476 curr->ia_state = IFA_TENTATIVE; 477 else 478 curr->ia_state = IFA_OK; 479 } else { 480 curr->ia_state = IFA_INACCESSIBLE; 481 } 482 } 483 if (flags & IFF_UNNUMBERED) 484 curr->ia_cflags |= IA_UNNUMBERED; 485 if (flags & IFF_PRIVATE) 486 curr->ia_cflags |= IA_PRIVATE; 487 if (flags & IFF_TEMPORARY) 488 curr->ia_cflags |= IA_TEMPORARY; 489 if (flags & IFF_DEPRECATED) 490 curr->ia_cflags |= IA_DEPRECATED; 491 492 } 493 494 freeifaddrs(ifa); 495 return (IPADM_SUCCESS); 496 497 fail: 498 /* On error, cleanup everything and return. */ 499 ipadm_free_addr_info(*addrinfo); 500 *addrinfo = NULL; 501 freeifaddrs(ifa); 502 return (ipadm_errno2status(errno)); 503 } 504 505 /* 506 * From the given `name', i_ipadm_name2atype() deduces the address type 507 * and address family. If the `name' implies an address, it returns B_TRUE. 508 * Else, returns B_FALSE and leaves the output parameters unchanged. 509 */ 510 boolean_t 511 i_ipadm_name2atype(const char *name, sa_family_t *af, ipadm_addr_type_t *type) 512 { 513 boolean_t is_addr = B_TRUE; 514 515 if (strcmp(name, IPADM_NVP_IPV4ADDR) == 0) { 516 *af = AF_INET; 517 *type = IPADM_ADDR_STATIC; 518 } else if (strcmp(name, IPADM_NVP_IPV6ADDR) == 0) { 519 *af = AF_INET6; 520 *type = IPADM_ADDR_STATIC; 521 } else if (strcmp(name, IPADM_NVP_DHCP) == 0) { 522 *af = AF_INET; 523 *type = IPADM_ADDR_DHCP; 524 } else if (strcmp(name, IPADM_NVP_INTFID) == 0) { 525 *af = AF_INET6; 526 *type = IPADM_ADDR_IPV6_ADDRCONF; 527 } else { 528 is_addr = B_FALSE; 529 } 530 531 return (is_addr); 532 } 533 534 /* 535 * Parses the given nvlist `nvl' for an address or an address property. 536 * The input nvlist must contain either an address or an address property. 537 * `ainfo' is an input as well as output parameter. When an address or an 538 * address property is found, `ainfo' is updated with the information found. 539 * Some of the fields may be already filled in by the calling function. 540 * 541 * The fields that will be filled/updated by this function are `ia_pflags', 542 * `ia_sname' and `ia_dname'. Values for `ia_pflags' are obtained if the `nvl' 543 * contains an address property. `ia_sname', `ia_dname', and `ia_pflags' are 544 * obtained if `nvl' contains an address. 545 */ 546 static ipadm_status_t 547 i_ipadm_nvl2ainfo_common(nvlist_t *nvl, ipadm_addr_info_t *ainfo) 548 { 549 nvlist_t *nvladdr; 550 char *name; 551 char *propstr = NULL; 552 char *sname, *dname; 553 nvpair_t *nvp; 554 sa_family_t af; 555 ipadm_addr_type_t atype; 556 boolean_t is_addr = B_FALSE; 557 int err; 558 559 for (nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL; 560 nvp = nvlist_next_nvpair(nvl, nvp)) { 561 name = nvpair_name(nvp); 562 if (i_ipadm_name2atype(name, &af, &atype)) { 563 err = nvpair_value_nvlist(nvp, &nvladdr); 564 is_addr = B_TRUE; 565 } else if (IPADM_PRIV_NVP(name)) { 566 continue; 567 } else { 568 err = nvpair_value_string(nvp, &propstr); 569 } 570 if (err != 0) 571 return (ipadm_errno2status(err)); 572 } 573 574 if (is_addr) { 575 /* 576 * We got an address from the nvlist `nvl'. 577 * Parse `nvladdr' and populate relevant information 578 * in `ainfo'. 579 */ 580 switch (atype) { 581 case IPADM_ADDR_STATIC: 582 if (strcmp(name, "up") == 0 && 583 strcmp(propstr, "yes") == 0) { 584 ainfo->ia_pflags |= IA_UP; 585 } 586 /* 587 * For static addresses, we need to get the hostnames. 588 */ 589 err = nvlist_lookup_string(nvladdr, 590 IPADM_NVP_IPADDRHNAME, &sname); 591 if (err != 0) 592 return (ipadm_errno2status(err)); 593 (void) strlcpy(ainfo->ia_sname, sname, 594 sizeof (ainfo->ia_sname)); 595 err = nvlist_lookup_string(nvladdr, 596 IPADM_NVP_IPDADDRHNAME, &dname); 597 if (err == 0) { 598 (void) strlcpy(ainfo->ia_dname, dname, 599 sizeof (ainfo->ia_dname)); 600 } 601 break; 602 case IPADM_ADDR_DHCP: 603 case IPADM_ADDR_IPV6_ADDRCONF: 604 /* 605 * dhcp and addrconf address objects are always 606 * marked up when re-enabled. 607 */ 608 ainfo->ia_pflags |= IA_UP; 609 break; 610 default: 611 return (IPADM_FAILURE); 612 } 613 } else { 614 /* 615 * We got an address property from `nvl'. Parse the 616 * name and the property value. Update the `ainfo->ia_pflags' 617 * for the flags. 618 */ 619 if (strcmp(name, "deprecated") == 0) { 620 if (strcmp(propstr, IPADM_ONSTR) == 0) 621 ainfo->ia_pflags |= IA_DEPRECATED; 622 } else if (strcmp(name, "private") == 0) { 623 if (strcmp(propstr, IPADM_ONSTR) == 0) 624 ainfo->ia_pflags |= IA_PRIVATE; 625 } 626 } 627 628 return (IPADM_SUCCESS); 629 } 630 631 /* 632 * Parses the given nvlist `nvl' for an address or an address property. 633 * The input nvlist must contain either an address or an address property. 634 * `ainfo' is an input as well as output parameter. When an address or an 635 * address property is found, `ainfo' is updated with the information found. 636 * Some of the fields may be already filled in by the calling function, 637 * because of previous calls to i_ipadm_nvl2ainfo_active(). 638 * 639 * Since the address object in `nvl' is also in the active configuration, the 640 * fields that will be filled/updated by this function are `ia_pflags', 641 * `ia_sname' and `ia_dname'. 642 * 643 * If this function returns an error, the calling function will take 644 * care of freeing the fields in `ainfo'. 645 */ 646 static ipadm_status_t 647 i_ipadm_nvl2ainfo_active(nvlist_t *nvl, ipadm_addr_info_t *ainfo) 648 { 649 return (i_ipadm_nvl2ainfo_common(nvl, ainfo)); 650 } 651 652 /* 653 * Parses the given nvlist `nvl' for an address or an address property. 654 * The input nvlist must contain either an address or an address property. 655 * `ainfo' is an input as well as output parameter. When an address or an 656 * address property is found, `ainfo' is updated with the information found. 657 * Some of the fields may be already filled in by the calling function, 658 * because of previous calls to i_ipadm_nvl2ainfo_persist(). 659 * 660 * All the relevant fields in `ainfo' will be filled by this function based 661 * on what we find in `nvl'. 662 * 663 * If this function returns an error, the calling function will take 664 * care of freeing the fields in `ainfo'. 665 */ 666 static ipadm_status_t 667 i_ipadm_nvl2ainfo_persist(nvlist_t *nvl, ipadm_addr_info_t *ainfo) 668 { 669 nvlist_t *nvladdr; 670 struct ifaddrs *ifa; 671 char *name; 672 char *ifname = NULL; 673 char *aobjname = NULL; 674 char *propstr = NULL; 675 nvpair_t *nvp; 676 sa_family_t af; 677 ipadm_addr_type_t atype; 678 boolean_t is_addr = B_FALSE; 679 size_t size = sizeof (struct sockaddr_storage); 680 struct sockaddr_in6 *sin6; 681 uint32_t plen = 0; 682 int err; 683 ipadm_status_t status; 684 685 status = i_ipadm_nvl2ainfo_common(nvl, ainfo); 686 if (status != IPADM_SUCCESS) 687 return (status); 688 689 for (nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL; 690 nvp = nvlist_next_nvpair(nvl, nvp)) { 691 name = nvpair_name(nvp); 692 if (strcmp(name, IPADM_NVP_IFNAME) == 0) { 693 err = nvpair_value_string(nvp, &ifname); 694 } else if (strcmp(name, IPADM_NVP_AOBJNAME) == 0) { 695 err = nvpair_value_string(nvp, &aobjname); 696 } else if (i_ipadm_name2atype(name, &af, &atype)) { 697 err = nvpair_value_nvlist(nvp, &nvladdr); 698 is_addr = B_TRUE; 699 } else { 700 err = nvpair_value_string(nvp, &propstr); 701 } 702 if (err != 0) 703 return (ipadm_errno2status(err)); 704 } 705 706 ifa = &ainfo->ia_ifa; 707 (void) strlcpy(ainfo->ia_aobjname, aobjname, 708 sizeof (ainfo->ia_aobjname)); 709 if (ifa->ifa_name == NULL && (ifa->ifa_name = strdup(ifname)) == NULL) 710 return (IPADM_NO_MEMORY); 711 if (is_addr) { 712 /* 713 * We got an address from the nvlist `nvl'. 714 * Parse `nvladdr' and populate `ifa->ifa_addr'. 715 */ 716 ainfo->ia_atype = atype; 717 if ((ifa->ifa_addr = calloc(1, size)) == NULL) 718 return (IPADM_NO_MEMORY); 719 switch (atype) { 720 case IPADM_ADDR_STATIC: 721 ifa->ifa_addr->ss_family = af; 722 break; 723 case IPADM_ADDR_DHCP: 724 ifa->ifa_addr->ss_family = AF_INET; 725 break; 726 case IPADM_ADDR_IPV6_ADDRCONF: 727 sin6 = SIN6(ifa->ifa_addr); 728 sin6->sin6_family = AF_INET6; 729 if (i_ipadm_nvl2in6_addr(nvladdr, IPADM_NVP_IPNUMADDR, 730 &sin6->sin6_addr) != IPADM_SUCCESS) 731 return (IPADM_NO_MEMORY); 732 err = nvlist_lookup_uint32(nvladdr, IPADM_NVP_PREFIXLEN, 733 &plen); 734 if (err != 0) 735 return (ipadm_errno2status(err)); 736 if ((ifa->ifa_netmask = malloc(size)) == NULL) 737 return (IPADM_NO_MEMORY); 738 if ((err = plen2mask(plen, af, ifa->ifa_netmask)) != 0) 739 return (ipadm_errno2status(err)); 740 break; 741 default: 742 return (IPADM_FAILURE); 743 } 744 } else { 745 if (strcmp(name, "prefixlen") == 0) { 746 /* 747 * If a prefixlen was found, update the 748 * `ainfo->ia_ifa.ifa_netmask'. 749 */ 750 751 if ((ifa->ifa_netmask = malloc(size)) == NULL) 752 return (IPADM_NO_MEMORY); 753 /* 754 * Address property lines always follow the address 755 * line itself in the persistent db. We must have 756 * found a valid `ainfo->ia_ifa.ifa_addr' by now. 757 */ 758 assert(ifa->ifa_addr != NULL); 759 err = plen2mask(atoi(propstr), ifa->ifa_addr->ss_family, 760 ifa->ifa_netmask); 761 if (err != 0) 762 return (ipadm_errno2status(err)); 763 } 764 } 765 766 return (IPADM_SUCCESS); 767 } 768 769 /* 770 * Retrieves all addresses from active config and appends to it the 771 * addresses that are found only in persistent config. In addition, 772 * it updates the persistent fields for each address from information 773 * found in persistent config. The output parameter `addrinfo' contains 774 * complete information regarding all addresses in active as well as 775 * persistent config. 776 */ 777 static ipadm_status_t 778 i_ipadm_get_all_addr_info(ipadm_handle_t iph, const char *ifname, 779 ipadm_addr_info_t **addrinfo, uint32_t ipadm_flags, int64_t lifc_flags) 780 { 781 nvlist_t *nvladdr = NULL; 782 nvlist_t *onvl = NULL; 783 nvpair_t *nvp; 784 ipadm_status_t status; 785 ipadm_addr_info_t *ainfo = NULL; 786 ipadm_addr_info_t *curr; 787 ipadm_addr_info_t *last = NULL; 788 char *aobjname; 789 790 /* Get all addresses from active config. */ 791 status = i_ipadm_active_addr_info(iph, ifname, &ainfo, ipadm_flags, 792 lifc_flags); 793 if (status != IPADM_SUCCESS) 794 goto fail; 795 796 /* Get all addresses from persistent config. */ 797 status = i_ipadm_get_db_addr(iph, ifname, NULL, &onvl); 798 /* 799 * If no address was found in persistent config, just 800 * return what we found in active config. 801 */ 802 if (status == IPADM_NOTFOUND) { 803 /* 804 * If nothing was found neither active nor persistent 805 * config, this means that the interface does not exist, 806 * if one was provided in `ifname'. 807 */ 808 if (ainfo == NULL && ifname != NULL) 809 return (IPADM_ENXIO); 810 *addrinfo = ainfo; 811 return (IPADM_SUCCESS); 812 } 813 /* In case of any other error, cleanup and return. */ 814 if (status != IPADM_SUCCESS) 815 goto fail; 816 /* we append to make sure, loopback addresses are first */ 817 if (ainfo != NULL) { 818 for (curr = ainfo; IA_NEXT(curr) != NULL; curr = IA_NEXT(curr)) 819 ; 820 last = curr; 821 } 822 823 /* 824 * `onvl' will contain all the address lines from the db. Each line 825 * could contain the address itself or an address property. Addresses 826 * and address properties are found in separate lines. 827 * 828 * If an address A was found in active, we will already have `ainfo', 829 * and it is present in persistent configuration as well, we need to 830 * update `ainfo' with persistent information (`ia_pflags). 831 * For each address B found only in persistent configuration, 832 * append the address to the list with the address info for B from 833 * `onvl'. 834 */ 835 for (nvp = nvlist_next_nvpair(onvl, NULL); nvp != NULL; 836 nvp = nvlist_next_nvpair(onvl, nvp)) { 837 if (nvpair_value_nvlist(nvp, &nvladdr) != 0) 838 continue; 839 if (nvlist_lookup_string(nvladdr, IPADM_NVP_AOBJNAME, 840 &aobjname) != 0) 841 continue; 842 for (curr = ainfo; curr != NULL; curr = IA_NEXT(curr)) { 843 if (strcmp(curr->ia_aobjname, aobjname) == 0) 844 break; 845 } 846 if (curr == NULL) { 847 /* 848 * We did not find this address object in `ainfo'. 849 * This means that the address object exists only 850 * in the persistent configuration. Get its 851 * details and append to `ainfo'. 852 */ 853 curr = calloc(1, sizeof (ipadm_addr_info_t)); 854 if (curr == NULL) 855 goto fail; 856 curr->ia_state = IFA_DISABLED; 857 if (last != NULL) 858 last->ia_ifa.ifa_next = &curr->ia_ifa; 859 else 860 ainfo = curr; 861 last = curr; 862 } 863 /* 864 * Fill relevant fields of `curr' from the persistent info 865 * in `nvladdr'. Call the appropriate function based on the 866 * `ia_state' value. 867 */ 868 if (curr->ia_state == IFA_DISABLED) 869 status = i_ipadm_nvl2ainfo_persist(nvladdr, curr); 870 else 871 status = i_ipadm_nvl2ainfo_active(nvladdr, curr); 872 if (status != IPADM_SUCCESS) 873 goto fail; 874 } 875 *addrinfo = ainfo; 876 nvlist_free(onvl); 877 return (status); 878 fail: 879 /* On error, cleanup and return. */ 880 nvlist_free(onvl); 881 ipadm_free_addr_info(ainfo); 882 *addrinfo = NULL; 883 return (status); 884 } 885 886 /* 887 * Callback function that sets the property `prefixlen' on the address 888 * object in `arg' to the value in `pval'. 889 */ 890 /* ARGSUSED */ 891 static ipadm_status_t 892 i_ipadm_set_prefixlen(ipadm_handle_t iph, const void *arg, 893 ipadm_prop_desc_t *pdp, const void *pval, uint_t af, uint_t flags) 894 { 895 struct sockaddr_storage netmask; 896 struct lifreq lifr; 897 int err, s; 898 unsigned long prefixlen, abits; 899 char *end; 900 ipadm_addrobj_t ipaddr = (ipadm_addrobj_t)arg; 901 902 if (ipaddr->ipadm_atype == IPADM_ADDR_DHCP) 903 return (IPADM_NOTSUP); 904 905 errno = 0; 906 prefixlen = strtoul(pval, &end, 10); 907 if (errno != 0 || *end != '\0') 908 return (IPADM_INVALID_ARG); 909 910 abits = (af == AF_INET ? IP_ABITS : IPV6_ABITS); 911 if (prefixlen == 0 || prefixlen == (abits - 1)) 912 return (IPADM_INVALID_ARG); 913 914 if ((err = plen2mask(prefixlen, af, &netmask)) != 0) 915 return (ipadm_errno2status(err)); 916 917 s = (af == AF_INET ? iph->iph_sock : iph->iph_sock6); 918 919 bzero(&lifr, sizeof (lifr)); 920 i_ipadm_addrobj2lifname(ipaddr, lifr.lifr_name, 921 sizeof (lifr.lifr_name)); 922 (void) memcpy(&lifr.lifr_addr, &netmask, sizeof (netmask)); 923 if (ioctl(s, SIOCSLIFNETMASK, (caddr_t)&lifr) < 0) 924 return (ipadm_errno2status(errno)); 925 926 /* now, change the broadcast address to reflect the prefixlen */ 927 if (af == AF_INET) { 928 /* 929 * get the interface address and set it, this should reset 930 * the broadcast address. 931 */ 932 (void) ioctl(s, SIOCGLIFADDR, (caddr_t)&lifr); 933 (void) ioctl(s, SIOCSLIFADDR, (caddr_t)&lifr); 934 } 935 936 return (IPADM_SUCCESS); 937 } 938 939 940 /* 941 * Callback function that sets the given value `pval' to one of the 942 * properties among `deprecated', `private', and `transmit' as defined in 943 * `pdp', on the address object in `arg'. 944 */ 945 /* ARGSUSED */ 946 static ipadm_status_t 947 i_ipadm_set_addr_flag(ipadm_handle_t iph, const void *arg, 948 ipadm_prop_desc_t *pdp, const void *pval, uint_t af, uint_t flags) 949 { 950 char lifname[LIFNAMSIZ]; 951 uint64_t on_flags = 0, off_flags = 0; 952 boolean_t on; 953 ipadm_addrobj_t ipaddr = (ipadm_addrobj_t)arg; 954 955 if (ipaddr->ipadm_atype == IPADM_ADDR_DHCP && 956 strcmp(pdp->ipd_name, "deprecated") == 0) 957 return (IPADM_NOTSUP); 958 959 if (strcmp(pval, IPADM_ONSTR) == 0) 960 on = B_TRUE; 961 else if (strcmp(pval, IPADM_OFFSTR) == 0) 962 on = B_FALSE; 963 else 964 return (IPADM_INVALID_ARG); 965 966 if (strcmp(pdp->ipd_name, "private") == 0) { 967 if (on) 968 on_flags = IFF_PRIVATE; 969 else 970 off_flags = IFF_PRIVATE; 971 } else if (strcmp(pdp->ipd_name, "transmit") == 0) { 972 if (on) 973 off_flags = IFF_NOXMIT; 974 else 975 on_flags = IFF_NOXMIT; 976 } else if (strcmp(pdp->ipd_name, "deprecated") == 0) { 977 if (on) 978 on_flags = IFF_DEPRECATED; 979 else 980 off_flags = IFF_DEPRECATED; 981 } else { 982 return (IPADM_PROP_UNKNOWN); 983 } 984 985 i_ipadm_addrobj2lifname(ipaddr, lifname, sizeof (lifname)); 986 return (i_ipadm_set_flags(iph, lifname, af, on_flags, off_flags)); 987 } 988 989 /* 990 * Callback function that sets the property `zone' on the address 991 * object in `arg' to the value in `pval'. 992 */ 993 /* ARGSUSED */ 994 static ipadm_status_t 995 i_ipadm_set_zone(ipadm_handle_t iph, const void *arg, 996 ipadm_prop_desc_t *pdp, const void *pval, uint_t af, uint_t flags) 997 { 998 struct lifreq lifr; 999 zoneid_t zoneid; 1000 int s; 1001 1002 /* 1003 * To modify the zone assignment such that it persists across 1004 * reboots, zonecfg(1M) must be used. 1005 */ 1006 if (flags & IPADM_OPT_PERSIST) { 1007 return (IPADM_NOTSUP); 1008 } else if (flags & IPADM_OPT_ACTIVE) { 1009 /* put logical interface into all zones */ 1010 if (strcmp(pval, "all-zones") == 0) { 1011 zoneid = ALL_ZONES; 1012 } else { 1013 /* zone must be ready or running */ 1014 if ((zoneid = getzoneidbyname(pval)) == -1) 1015 return (ipadm_errno2status(errno)); 1016 } 1017 } else { 1018 return (IPADM_INVALID_ARG); 1019 } 1020 1021 s = (af == AF_INET ? iph->iph_sock : iph->iph_sock6); 1022 bzero(&lifr, sizeof (lifr)); 1023 i_ipadm_addrobj2lifname((ipadm_addrobj_t)arg, lifr.lifr_name, 1024 sizeof (lifr.lifr_name)); 1025 lifr.lifr_zoneid = zoneid; 1026 if (ioctl(s, SIOCSLIFZONE, (caddr_t)&lifr) < 0) 1027 return (ipadm_errno2status(errno)); 1028 1029 return (IPADM_SUCCESS); 1030 } 1031 1032 /* 1033 * Callback function that gets the property `broadcast' for the address 1034 * object in `arg'. 1035 */ 1036 /* ARGSUSED */ 1037 static ipadm_status_t 1038 i_ipadm_get_broadcast(ipadm_handle_t iph, const void *arg, 1039 ipadm_prop_desc_t *pdp, char *buf, uint_t *bufsize, uint_t af, 1040 uint_t valtype) 1041 { 1042 struct sockaddr_in *sin; 1043 struct lifreq lifr; 1044 char lifname[LIFNAMSIZ]; 1045 ipadm_addrobj_t ipaddr = (ipadm_addrobj_t)arg; 1046 ipadm_status_t status; 1047 size_t nbytes = 0; 1048 uint64_t ifflags = 0; 1049 1050 i_ipadm_addrobj2lifname(ipaddr, lifname, sizeof (lifname)); 1051 if (ipaddr->ipadm_flags & IPMGMT_ACTIVE) { 1052 status = i_ipadm_get_flags(iph, lifname, af, &ifflags); 1053 if (status != IPADM_SUCCESS) 1054 return (status); 1055 if (!(ifflags & IFF_BROADCAST)) { 1056 buf[0] = '\0'; 1057 return (IPADM_SUCCESS); 1058 } 1059 } 1060 1061 switch (valtype) { 1062 case MOD_PROP_DEFAULT: { 1063 struct sockaddr_storage mask; 1064 struct in_addr broadaddr; 1065 uint_t plen; 1066 in_addr_t addr, maddr; 1067 char val[MAXPROPVALLEN]; 1068 uint_t valsz = MAXPROPVALLEN; 1069 ipadm_status_t status; 1070 int err; 1071 struct sockaddr_in *sin; 1072 1073 if (!(ipaddr->ipadm_flags & IPMGMT_ACTIVE)) { 1074 /* 1075 * Since the address is unknown we cannot 1076 * obtain default prefixlen 1077 */ 1078 if (ipaddr->ipadm_atype == IPADM_ADDR_DHCP || 1079 ipaddr->ipadm_af == AF_INET6) { 1080 buf[0] = '\0'; 1081 return (IPADM_SUCCESS); 1082 } 1083 /* 1084 * For the static address, we get the address from the 1085 * persistent db. 1086 */ 1087 status = i_ipadm_get_static_addr_db(iph, ipaddr); 1088 if (status != IPADM_SUCCESS) 1089 return (status); 1090 sin = SIN(&ipaddr->ipadm_static_addr); 1091 addr = sin->sin_addr.s_addr; 1092 } else { 1093 /* 1094 * If the address object is active, we retrieve the 1095 * address from kernel. 1096 */ 1097 bzero(&lifr, sizeof (lifr)); 1098 (void) strlcpy(lifr.lifr_name, lifname, 1099 sizeof (lifr.lifr_name)); 1100 if (ioctl(iph->iph_sock, SIOCGLIFADDR, 1101 (caddr_t)&lifr) < 0) 1102 return (ipadm_errno2status(errno)); 1103 1104 addr = (SIN(&lifr.lifr_addr))->sin_addr.s_addr; 1105 } 1106 /* 1107 * For default broadcast address, get the address and the 1108 * default prefixlen for that address and then compute the 1109 * broadcast address. 1110 */ 1111 status = i_ipadm_get_prefixlen(iph, arg, NULL, val, &valsz, af, 1112 MOD_PROP_DEFAULT); 1113 if (status != IPADM_SUCCESS) 1114 return (status); 1115 1116 plen = atoi(val); 1117 if ((err = plen2mask(plen, AF_INET, &mask)) != 0) 1118 return (ipadm_errno2status(err)); 1119 maddr = (SIN(&mask))->sin_addr.s_addr; 1120 broadaddr.s_addr = (addr & maddr) | ~maddr; 1121 nbytes = snprintf(buf, *bufsize, "%s", inet_ntoa(broadaddr)); 1122 break; 1123 } 1124 case MOD_PROP_ACTIVE: 1125 bzero(&lifr, sizeof (lifr)); 1126 (void) strlcpy(lifr.lifr_name, lifname, 1127 sizeof (lifr.lifr_name)); 1128 if (ioctl(iph->iph_sock, SIOCGLIFBRDADDR, 1129 (caddr_t)&lifr) < 0) { 1130 return (ipadm_errno2status(errno)); 1131 } else { 1132 sin = SIN(&lifr.lifr_addr); 1133 nbytes = snprintf(buf, *bufsize, "%s", 1134 inet_ntoa(sin->sin_addr)); 1135 } 1136 break; 1137 default: 1138 return (IPADM_INVALID_ARG); 1139 } 1140 if (nbytes >= *bufsize) { 1141 /* insufficient buffer space */ 1142 *bufsize = nbytes + 1; 1143 return (IPADM_NO_BUFS); 1144 } 1145 return (IPADM_SUCCESS); 1146 } 1147 1148 /* 1149 * Callback function that retrieves the value of the property `prefixlen' 1150 * for the address object in `arg'. 1151 */ 1152 /* ARGSUSED */ 1153 static ipadm_status_t 1154 i_ipadm_get_prefixlen(ipadm_handle_t iph, const void *arg, 1155 ipadm_prop_desc_t *pdp, char *buf, uint_t *bufsize, uint_t af, 1156 uint_t valtype) 1157 { 1158 struct lifreq lifr; 1159 ipadm_addrobj_t ipaddr = (ipadm_addrobj_t)arg; 1160 char lifname[LIFNAMSIZ]; 1161 int s; 1162 uint32_t prefixlen; 1163 size_t nbytes; 1164 ipadm_status_t status; 1165 uint64_t lifflags; 1166 1167 i_ipadm_addrobj2lifname(ipaddr, lifname, sizeof (lifname)); 1168 if (ipaddr->ipadm_flags & IPMGMT_ACTIVE) { 1169 status = i_ipadm_get_flags(iph, lifname, af, &lifflags); 1170 if (status != IPADM_SUCCESS) { 1171 return (status); 1172 } else if (lifflags & IFF_POINTOPOINT) { 1173 buf[0] = '\0'; 1174 return (status); 1175 } 1176 } 1177 1178 s = (af == AF_INET ? iph->iph_sock : iph->iph_sock6); 1179 bzero(&lifr, sizeof (lifr)); 1180 (void) strlcpy(lifr.lifr_name, lifname, sizeof (lifr.lifr_name)); 1181 switch (valtype) { 1182 case MOD_PROP_POSSIBLE: 1183 if (af == AF_INET) 1184 nbytes = snprintf(buf, *bufsize, "1-30,32"); 1185 else 1186 nbytes = snprintf(buf, *bufsize, "1-126,128"); 1187 break; 1188 case MOD_PROP_DEFAULT: 1189 if (ipaddr->ipadm_flags & IPMGMT_ACTIVE) { 1190 /* 1191 * For static addresses, we retrieve the address 1192 * from kernel if it is active. 1193 */ 1194 if (ioctl(s, SIOCGLIFADDR, (caddr_t)&lifr) < 0) 1195 return (ipadm_errno2status(errno)); 1196 status = i_ipadm_get_default_prefixlen( 1197 &lifr.lifr_addr, &prefixlen); 1198 if (status != IPADM_SUCCESS) 1199 return (status); 1200 } else if ((ipaddr->ipadm_flags & IPMGMT_PERSIST) && 1201 ipaddr->ipadm_atype == IPADM_ADDR_DHCP) { 1202 /* 1203 * Since the address is unknown we cannot 1204 * obtain default prefixlen 1205 */ 1206 buf[0] = '\0'; 1207 return (IPADM_SUCCESS); 1208 } else { 1209 /* 1210 * If not in active config, we use the address 1211 * from persistent store. 1212 */ 1213 status = i_ipadm_get_static_addr_db(iph, ipaddr); 1214 if (status != IPADM_SUCCESS) 1215 return (status); 1216 status = i_ipadm_get_default_prefixlen( 1217 &ipaddr->ipadm_static_addr, &prefixlen); 1218 if (status != IPADM_SUCCESS) 1219 return (status); 1220 } 1221 nbytes = snprintf(buf, *bufsize, "%u", prefixlen); 1222 break; 1223 case MOD_PROP_ACTIVE: 1224 if (ioctl(s, SIOCGLIFNETMASK, (caddr_t)&lifr) < 0) 1225 return (ipadm_errno2status(errno)); 1226 prefixlen = lifr.lifr_addrlen; 1227 nbytes = snprintf(buf, *bufsize, "%u", prefixlen); 1228 break; 1229 default: 1230 return (IPADM_INVALID_ARG); 1231 } 1232 if (nbytes >= *bufsize) { 1233 /* insufficient buffer space */ 1234 *bufsize = nbytes + 1; 1235 return (IPADM_NO_BUFS); 1236 } 1237 return (IPADM_SUCCESS); 1238 } 1239 1240 /* 1241 * Callback function that retrieves the value of one of the properties 1242 * among `deprecated', `private', and `transmit' for the address object 1243 * in `arg'. 1244 */ 1245 /* ARGSUSED */ 1246 static ipadm_status_t 1247 i_ipadm_get_addr_flag(ipadm_handle_t iph, const void *arg, 1248 ipadm_prop_desc_t *pdp, char *buf, uint_t *bufsize, uint_t af, 1249 uint_t valtype) 1250 { 1251 boolean_t on = B_FALSE; 1252 char lifname[LIFNAMSIZ]; 1253 ipadm_status_t status = IPADM_SUCCESS; 1254 uint64_t ifflags; 1255 size_t nbytes; 1256 ipadm_addrobj_t ipaddr = (ipadm_addrobj_t)arg; 1257 1258 switch (valtype) { 1259 case MOD_PROP_DEFAULT: 1260 if (strcmp(pdp->ipd_name, "private") == 0 || 1261 strcmp(pdp->ipd_name, "deprecated") == 0) { 1262 on = B_FALSE; 1263 } else if (strcmp(pdp->ipd_name, "transmit") == 0) { 1264 on = B_TRUE; 1265 } else { 1266 return (IPADM_PROP_UNKNOWN); 1267 } 1268 break; 1269 case MOD_PROP_ACTIVE: 1270 /* 1271 * If the address is present in active configuration, we 1272 * retrieve it from kernel to get the property value. 1273 * Else, there is no value to return. 1274 */ 1275 i_ipadm_addrobj2lifname(ipaddr, lifname, sizeof (lifname)); 1276 status = i_ipadm_get_flags(iph, lifname, af, &ifflags); 1277 if (status != IPADM_SUCCESS) 1278 return (status); 1279 if (strcmp(pdp->ipd_name, "private") == 0) 1280 on = (ifflags & IFF_PRIVATE); 1281 else if (strcmp(pdp->ipd_name, "transmit") == 0) 1282 on = !(ifflags & IFF_NOXMIT); 1283 else if (strcmp(pdp->ipd_name, "deprecated") == 0) 1284 on = (ifflags & IFF_DEPRECATED); 1285 break; 1286 default: 1287 return (IPADM_INVALID_ARG); 1288 } 1289 nbytes = snprintf(buf, *bufsize, "%s", 1290 (on ? IPADM_ONSTR : IPADM_OFFSTR)); 1291 if (nbytes >= *bufsize) { 1292 /* insufficient buffer space */ 1293 *bufsize = nbytes + 1; 1294 status = IPADM_NO_BUFS; 1295 } 1296 1297 return (status); 1298 } 1299 1300 /* 1301 * Callback function that retrieves the value of the property `zone' 1302 * for the address object in `arg'. 1303 */ 1304 /* ARGSUSED */ 1305 static ipadm_status_t 1306 i_ipadm_get_zone(ipadm_handle_t iph, const void *arg, 1307 ipadm_prop_desc_t *pdp, char *buf, uint_t *bufsize, uint_t af, 1308 uint_t valtype) 1309 { 1310 struct lifreq lifr; 1311 char zone_name[ZONENAME_MAX]; 1312 int s; 1313 size_t nbytes = 0; 1314 1315 if (iph->iph_zoneid != GLOBAL_ZONEID) { 1316 buf[0] = '\0'; 1317 return (IPADM_SUCCESS); 1318 } 1319 1320 /* 1321 * we are in global zone. See if the lifname is assigned to shared-ip 1322 * zone or global zone. 1323 */ 1324 switch (valtype) { 1325 case MOD_PROP_DEFAULT: 1326 if (getzonenamebyid(GLOBAL_ZONEID, zone_name, 1327 sizeof (zone_name)) > 0) 1328 nbytes = snprintf(buf, *bufsize, "%s", zone_name); 1329 else 1330 return (ipadm_errno2status(errno)); 1331 break; 1332 case MOD_PROP_ACTIVE: 1333 bzero(&lifr, sizeof (lifr)); 1334 i_ipadm_addrobj2lifname((ipadm_addrobj_t)arg, lifr.lifr_name, 1335 sizeof (lifr.lifr_name)); 1336 s = (af == AF_INET ? iph->iph_sock : iph->iph_sock6); 1337 1338 if (ioctl(s, SIOCGLIFZONE, (caddr_t)&lifr) == -1) 1339 return (ipadm_errno2status(errno)); 1340 1341 if (lifr.lifr_zoneid == ALL_ZONES) { 1342 nbytes = snprintf(buf, *bufsize, "%s", "all-zones"); 1343 } else if (getzonenamebyid(lifr.lifr_zoneid, zone_name, 1344 sizeof (zone_name)) < 0) { 1345 return (ipadm_errno2status(errno)); 1346 } else { 1347 nbytes = snprintf(buf, *bufsize, "%s", zone_name); 1348 } 1349 break; 1350 default: 1351 return (IPADM_INVALID_ARG); 1352 } 1353 if (nbytes >= *bufsize) { 1354 /* insufficient buffer space */ 1355 *bufsize = nbytes + 1; 1356 return (IPADM_NO_BUFS); 1357 } 1358 1359 return (IPADM_SUCCESS); 1360 } 1361 1362 static ipadm_prop_desc_t * 1363 i_ipadm_getpropdesc(const char *pname) 1364 { 1365 int i; 1366 1367 for (i = 0; ipadm_addrprop_table[i].ipd_name != NULL; i++) { 1368 if (strcmp(pname, ipadm_addrprop_table[i].ipd_name) == 0) 1369 return (&ipadm_addrprop_table[i]); 1370 } 1371 return (NULL); 1372 } 1373 1374 /* 1375 * Gets the value of the given address property `pname' for the address 1376 * object with name `aobjname'. 1377 */ 1378 ipadm_status_t 1379 ipadm_get_addrprop(ipadm_handle_t iph, const char *pname, char *buf, 1380 uint_t *bufsize, const char *aobjname, uint_t valtype) 1381 { 1382 struct ipadm_addrobj_s ipaddr; 1383 ipadm_status_t status = IPADM_SUCCESS; 1384 sa_family_t af; 1385 ipadm_prop_desc_t *pdp = NULL; 1386 1387 if (iph == NULL || pname == NULL || buf == NULL || 1388 bufsize == NULL || *bufsize == 0 || aobjname == NULL) { 1389 return (IPADM_INVALID_ARG); 1390 } 1391 1392 /* find the property in the property description table */ 1393 if ((pdp = i_ipadm_getpropdesc(pname)) == NULL) 1394 return (IPADM_PROP_UNKNOWN); 1395 1396 /* 1397 * For the given aobjname, get the addrobj it represents and 1398 * retrieve the property value for that object. 1399 */ 1400 i_ipadm_init_addr(&ipaddr, "", aobjname, IPADM_ADDR_NONE); 1401 if ((status = i_ipadm_get_addrobj(iph, &ipaddr)) != IPADM_SUCCESS) 1402 return (status); 1403 1404 if (ipaddr.ipadm_atype == IPADM_ADDR_IPV6_ADDRCONF) 1405 return (IPADM_NOTSUP); 1406 af = ipaddr.ipadm_af; 1407 1408 /* 1409 * Call the appropriate callback function to based on the field 1410 * that was asked for. 1411 */ 1412 switch (valtype) { 1413 case IPADM_OPT_PERM: 1414 status = i_ipadm_pd2permstr(pdp, buf, bufsize); 1415 break; 1416 case IPADM_OPT_ACTIVE: 1417 if (!(ipaddr.ipadm_flags & IPMGMT_ACTIVE)) { 1418 buf[0] = '\0'; 1419 } else { 1420 status = pdp->ipd_get(iph, &ipaddr, pdp, buf, bufsize, 1421 af, MOD_PROP_ACTIVE); 1422 } 1423 break; 1424 case IPADM_OPT_DEFAULT: 1425 status = pdp->ipd_get(iph, &ipaddr, pdp, buf, bufsize, 1426 af, MOD_PROP_DEFAULT); 1427 break; 1428 case IPADM_OPT_POSSIBLE: 1429 if (pdp->ipd_get_range != NULL) { 1430 status = pdp->ipd_get_range(iph, &ipaddr, pdp, buf, 1431 bufsize, af, MOD_PROP_POSSIBLE); 1432 break; 1433 } 1434 buf[0] = '\0'; 1435 break; 1436 case IPADM_OPT_PERSIST: 1437 status = i_ipadm_get_persist_propval(iph, pdp, buf, bufsize, 1438 &ipaddr); 1439 break; 1440 default: 1441 status = IPADM_INVALID_ARG; 1442 break; 1443 } 1444 1445 return (status); 1446 } 1447 1448 /* 1449 * Sets the value of the given address property `pname' to `pval' for the 1450 * address object with name `aobjname'. 1451 */ 1452 ipadm_status_t 1453 ipadm_set_addrprop(ipadm_handle_t iph, const char *pname, 1454 const char *pval, const char *aobjname, uint_t pflags) 1455 { 1456 struct ipadm_addrobj_s ipaddr; 1457 sa_family_t af; 1458 ipadm_prop_desc_t *pdp = NULL; 1459 char defbuf[MAXPROPVALLEN]; 1460 uint_t defbufsize = MAXPROPVALLEN; 1461 boolean_t reset = (pflags & IPADM_OPT_DEFAULT); 1462 ipadm_status_t status = IPADM_SUCCESS; 1463 1464 /* Check for solaris.network.interface.config authorization */ 1465 if (!ipadm_check_auth()) 1466 return (IPADM_EAUTH); 1467 1468 if (iph == NULL || pname == NULL || aobjname == NULL || pflags == 0 || 1469 pflags == IPADM_OPT_PERSIST || 1470 (pflags & ~(IPADM_COMMON_OPT_MASK|IPADM_OPT_DEFAULT)) || 1471 (!reset && pval == NULL)) { 1472 return (IPADM_INVALID_ARG); 1473 } 1474 1475 /* find the property in the property description table */ 1476 if ((pdp = i_ipadm_getpropdesc(pname)) == NULL) 1477 return (IPADM_PROP_UNKNOWN); 1478 1479 if (pdp->ipd_set == NULL || (reset && pdp->ipd_get == NULL)) 1480 return (IPADM_NOTSUP); 1481 1482 if (!(pdp->ipd_flags & IPADMPROP_MULVAL) && 1483 (pflags & (IPADM_OPT_APPEND|IPADM_OPT_REMOVE))) { 1484 return (IPADM_INVALID_ARG); 1485 } 1486 1487 /* 1488 * For the given aobjname, get the addrobj it represents and 1489 * set the property value for that object. 1490 */ 1491 i_ipadm_init_addr(&ipaddr, "", aobjname, IPADM_ADDR_NONE); 1492 if ((status = i_ipadm_get_addrobj(iph, &ipaddr)) != IPADM_SUCCESS) 1493 return (status); 1494 1495 if (!(ipaddr.ipadm_flags & IPMGMT_ACTIVE)) 1496 return (IPADM_OP_DISABLE_OBJ); 1497 1498 /* Persistent operation not allowed on a temporary object. */ 1499 if ((pflags & IPADM_OPT_PERSIST) && 1500 !(ipaddr.ipadm_flags & IPMGMT_PERSIST)) 1501 return (IPADM_TEMPORARY_OBJ); 1502 1503 /* 1504 * Currently, setting an address property on an address object of type 1505 * IPADM_ADDR_IPV6_ADDRCONF is not supported. Supporting it involves 1506 * in.ndpd retrieving the address properties from ipmgmtd for given 1507 * address object and then setting them on auto-configured addresses, 1508 * whenever in.ndpd gets a new prefix. This will be supported in 1509 * future releases. 1510 */ 1511 if (ipaddr.ipadm_atype == IPADM_ADDR_IPV6_ADDRCONF) 1512 return (IPADM_NOTSUP); 1513 1514 /* 1515 * Setting an address property on an address object that is 1516 * not present in active configuration is not supported. 1517 */ 1518 if (!(ipaddr.ipadm_flags & IPMGMT_ACTIVE)) 1519 return (IPADM_NOTSUP); 1520 1521 af = ipaddr.ipadm_af; 1522 if (reset) { 1523 /* 1524 * If we were asked to reset the value, we need to fetch 1525 * the default value and set the default value. 1526 */ 1527 status = pdp->ipd_get(iph, &ipaddr, pdp, defbuf, &defbufsize, 1528 af, MOD_PROP_DEFAULT); 1529 if (status != IPADM_SUCCESS) 1530 return (status); 1531 pval = defbuf; 1532 } 1533 /* set the user provided or default property value */ 1534 status = pdp->ipd_set(iph, &ipaddr, pdp, pval, af, pflags); 1535 if (status != IPADM_SUCCESS) 1536 return (status); 1537 1538 /* 1539 * If IPADM_OPT_PERSIST was set in `flags', we need to store 1540 * property and its value in persistent DB. 1541 */ 1542 if (pflags & IPADM_OPT_PERSIST) { 1543 status = i_ipadm_persist_propval(iph, pdp, pval, &ipaddr, 1544 pflags); 1545 } 1546 1547 return (status); 1548 } 1549 1550 /* 1551 * Remove the address specified by the address object in `addr' 1552 * from kernel. If the address is on a non-zero logical interface, we do a 1553 * SIOCLIFREMOVEIF, otherwise we set the address to INADDR_ANY for IPv4 or 1554 * :: for IPv6. 1555 */ 1556 ipadm_status_t 1557 i_ipadm_delete_addr(ipadm_handle_t iph, ipadm_addrobj_t addr) 1558 { 1559 struct lifreq lifr; 1560 int sock; 1561 ipadm_status_t status; 1562 1563 bzero(&lifr, sizeof (lifr)); 1564 i_ipadm_addrobj2lifname(addr, lifr.lifr_name, sizeof (lifr.lifr_name)); 1565 sock = (addr->ipadm_af == AF_INET ? iph->iph_sock : iph->iph_sock6); 1566 if (addr->ipadm_lifnum == 0) { 1567 /* 1568 * Fake the deletion of the 0'th address by 1569 * clearing IFF_UP and setting it to as 0.0.0.0 or ::. 1570 */ 1571 status = i_ipadm_set_flags(iph, addr->ipadm_ifname, 1572 addr->ipadm_af, 0, IFF_UP); 1573 if (status != IPADM_SUCCESS) 1574 return (status); 1575 bzero(&lifr.lifr_addr, sizeof (lifr.lifr_addr)); 1576 lifr.lifr_addr.ss_family = addr->ipadm_af; 1577 if (ioctl(sock, SIOCSLIFADDR, (caddr_t)&lifr) < 0) 1578 return (ipadm_errno2status(errno)); 1579 if (ioctl(sock, SIOCSLIFDSTADDR, (caddr_t)&lifr) < 0) 1580 return (ipadm_errno2status(errno)); 1581 } else if (ioctl(sock, SIOCLIFREMOVEIF, (caddr_t)&lifr) < 0) { 1582 return (ipadm_errno2status(errno)); 1583 } 1584 1585 return (IPADM_SUCCESS); 1586 } 1587 1588 /* 1589 * Extracts the IPv6 address from the nvlist in `nvl'. 1590 */ 1591 ipadm_status_t 1592 i_ipadm_nvl2in6_addr(nvlist_t *nvl, char *addr_type, in6_addr_t *in6_addr) 1593 { 1594 uint8_t *addr6; 1595 uint_t n; 1596 1597 if (nvlist_lookup_uint8_array(nvl, addr_type, &addr6, &n) != 0) 1598 return (IPADM_NOTFOUND); 1599 assert(n == 16); 1600 bcopy(addr6, in6_addr->s6_addr, n); 1601 return (IPADM_SUCCESS); 1602 } 1603 1604 /* 1605 * Used to validate the given addrobj name string. Length of `aobjname' 1606 * cannot exceed IPADM_AOBJ_USTRSIZ. `aobjname' should start with an 1607 * alphabetic character and it can only contain alphanumeric characters. 1608 */ 1609 static boolean_t 1610 i_ipadm_is_user_aobjname_valid(const char *aobjname) 1611 { 1612 const char *cp; 1613 1614 if (aobjname == NULL || strlen(aobjname) >= IPADM_AOBJ_USTRSIZ || 1615 !isalpha(*aobjname)) { 1616 return (B_FALSE); 1617 } 1618 for (cp = aobjname + 1; *cp && isalnum(*cp); cp++) 1619 ; 1620 return (*cp == '\0'); 1621 } 1622 1623 /* 1624 * Computes the prefixlen for the given `addr' based on the netmask found using 1625 * the order specified in /etc/nsswitch.conf. If not found, then the 1626 * prefixlen is computed using the Classful subnetting semantics defined 1627 * in RFC 791 for IPv4 and RFC 4291 for IPv6. 1628 */ 1629 static ipadm_status_t 1630 i_ipadm_get_default_prefixlen(struct sockaddr_storage *addr, uint32_t *plen) 1631 { 1632 sa_family_t af = addr->ss_family; 1633 struct sockaddr_storage mask; 1634 struct sockaddr_in *m = (struct sockaddr_in *)&mask; 1635 struct sockaddr_in6 *sin6; 1636 struct sockaddr_in *sin; 1637 struct in_addr ia; 1638 uint32_t prefixlen = 0; 1639 1640 switch (af) { 1641 case AF_INET: 1642 sin = SIN(addr); 1643 ia.s_addr = ntohl(sin->sin_addr.s_addr); 1644 get_netmask4(&ia, &m->sin_addr); 1645 m->sin_addr.s_addr = htonl(m->sin_addr.s_addr); 1646 m->sin_family = AF_INET; 1647 prefixlen = mask2plen(&mask); 1648 break; 1649 case AF_INET6: 1650 sin6 = SIN6(addr); 1651 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) 1652 prefixlen = 10; 1653 else 1654 prefixlen = 64; 1655 break; 1656 default: 1657 return (IPADM_INVALID_ARG); 1658 } 1659 *plen = prefixlen; 1660 return (IPADM_SUCCESS); 1661 } 1662 1663 ipadm_status_t 1664 i_ipadm_resolve_addr(const char *name, sa_family_t af, 1665 struct sockaddr_storage *ss) 1666 { 1667 struct addrinfo hints, *ai; 1668 int rc; 1669 struct sockaddr_in6 *sin6; 1670 struct sockaddr_in *sin; 1671 boolean_t is_mapped; 1672 1673 (void) memset(&hints, 0, sizeof (hints)); 1674 hints.ai_family = af; 1675 hints.ai_flags = (AI_ALL | AI_V4MAPPED); 1676 rc = getaddrinfo(name, NULL, &hints, &ai); 1677 if (rc != 0) { 1678 if (rc == EAI_NONAME) 1679 return (IPADM_BAD_ADDR); 1680 else 1681 return (IPADM_FAILURE); 1682 } 1683 if (ai->ai_next != NULL) { 1684 /* maps to more than one hostname */ 1685 freeaddrinfo(ai); 1686 return (IPADM_BAD_HOSTNAME); 1687 } 1688 /* LINTED E_BAD_PTR_CAST_ALIGN */ 1689 is_mapped = IN6_IS_ADDR_V4MAPPED(&(SIN6(ai->ai_addr))->sin6_addr); 1690 if (is_mapped) { 1691 sin = SIN(ss); 1692 sin->sin_family = AF_INET; 1693 /* LINTED E_BAD_PTR_CAST_ALIGN */ 1694 IN6_V4MAPPED_TO_INADDR(&(SIN6(ai->ai_addr))->sin6_addr, 1695 &sin->sin_addr); 1696 } else { 1697 sin6 = SIN6(ss); 1698 sin6->sin6_family = AF_INET6; 1699 bcopy(ai->ai_addr, sin6, sizeof (*sin6)); 1700 } 1701 freeaddrinfo(ai); 1702 return (IPADM_SUCCESS); 1703 } 1704 1705 /* 1706 * This takes a static address string <addr>[/<mask>] or a hostname 1707 * and maps it to a single numeric IP address, consulting DNS if 1708 * hostname was provided. If a specific address family was requested, 1709 * an error is returned if the given hostname does not map to an address 1710 * of the given family. Note that this function returns failure 1711 * if the name maps to more than one IP address. 1712 */ 1713 ipadm_status_t 1714 ipadm_set_addr(ipadm_addrobj_t ipaddr, const char *astr, sa_family_t af) 1715 { 1716 char *prefixlenstr; 1717 uint32_t prefixlen = 0; 1718 char *endp; 1719 /* 1720 * We use (NI_MAXHOST + 5) because the longest possible 1721 * astr will have (NI_MAXHOST + '/' + {a maximum of 32 for IPv4 1722 * or a maximum of 128 for IPv6 + '\0') chars 1723 */ 1724 char addrstr[NI_MAXHOST + 5]; 1725 ipadm_status_t status; 1726 1727 (void) snprintf(addrstr, sizeof (addrstr), "%s", astr); 1728 if ((prefixlenstr = strchr(addrstr, '/')) != NULL) { 1729 *prefixlenstr++ = '\0'; 1730 errno = 0; 1731 prefixlen = strtoul(prefixlenstr, &endp, 10); 1732 if (errno != 0 || *endp != '\0') 1733 return (IPADM_INVALID_ARG); 1734 if ((af == AF_INET && prefixlen > IP_ABITS) || 1735 (af == AF_INET6 && prefixlen > IPV6_ABITS)) 1736 return (IPADM_INVALID_ARG); 1737 } 1738 1739 status = i_ipadm_resolve_addr(addrstr, af, &ipaddr->ipadm_static_addr); 1740 if (status == IPADM_SUCCESS) { 1741 (void) strlcpy(ipaddr->ipadm_static_aname, addrstr, 1742 sizeof (ipaddr->ipadm_static_aname)); 1743 ipaddr->ipadm_af = ipaddr->ipadm_static_addr.ss_family; 1744 ipaddr->ipadm_static_prefixlen = prefixlen; 1745 } 1746 return (status); 1747 } 1748 1749 /* 1750 * Gets the static source address from the address object in `ipaddr'. 1751 * Memory for `addr' should be already allocated by the caller. 1752 */ 1753 ipadm_status_t 1754 ipadm_get_addr(const ipadm_addrobj_t ipaddr, struct sockaddr_storage *addr) 1755 { 1756 if (ipaddr == NULL || ipaddr->ipadm_atype != IPADM_ADDR_STATIC || 1757 addr == NULL) { 1758 return (IPADM_INVALID_ARG); 1759 } 1760 *addr = ipaddr->ipadm_static_addr; 1761 1762 return (IPADM_SUCCESS); 1763 } 1764 /* 1765 * Set up tunnel destination address in ipaddr by contacting DNS. 1766 * The function works similar to ipadm_set_addr(). 1767 * The dst_addr must resolve to exactly one address. IPADM_BAD_ADDR is returned 1768 * if dst_addr resolves to more than one address. The caller has to verify 1769 * that ipadm_static_addr and ipadm_static_dst_addr have the same ss_family 1770 */ 1771 ipadm_status_t 1772 ipadm_set_dst_addr(ipadm_addrobj_t ipaddr, const char *daddrstr, sa_family_t af) 1773 { 1774 ipadm_status_t status; 1775 1776 /* mask lengths are not meaningful for point-to-point interfaces. */ 1777 if (strchr(daddrstr, '/') != NULL) 1778 return (IPADM_BAD_ADDR); 1779 1780 status = i_ipadm_resolve_addr(daddrstr, af, 1781 &ipaddr->ipadm_static_dst_addr); 1782 if (status == IPADM_SUCCESS) { 1783 (void) strlcpy(ipaddr->ipadm_static_dname, daddrstr, 1784 sizeof (ipaddr->ipadm_static_dname)); 1785 } 1786 return (status); 1787 } 1788 1789 /* 1790 * Sets the interface ID in the address object `ipaddr' with the address 1791 * in the string `interface_id'. This interface ID will be used when 1792 * ipadm_create_addr() is called with `ipaddr' with address type 1793 * set to IPADM_ADDR_IPV6_ADDRCONF. 1794 */ 1795 ipadm_status_t 1796 ipadm_set_interface_id(ipadm_addrobj_t ipaddr, const char *interface_id) 1797 { 1798 struct sockaddr_in6 *sin6; 1799 char *end; 1800 char *cp; 1801 uint32_t prefixlen; 1802 char addrstr[INET6_ADDRSTRLEN + 1]; 1803 1804 if (ipaddr == NULL || interface_id == NULL || 1805 ipaddr->ipadm_atype != IPADM_ADDR_IPV6_ADDRCONF) 1806 return (IPADM_INVALID_ARG); 1807 1808 (void) strlcpy(addrstr, interface_id, sizeof (addrstr)); 1809 if ((cp = strchr(addrstr, '/')) == NULL) 1810 return (IPADM_INVALID_ARG); 1811 *cp++ = '\0'; 1812 sin6 = &ipaddr->ipadm_intfid; 1813 if (inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) == 1) { 1814 errno = 0; 1815 prefixlen = strtoul(cp, &end, 10); 1816 if (errno != 0 || *end != '\0' || prefixlen > IPV6_ABITS) 1817 return (IPADM_INVALID_ARG); 1818 sin6->sin6_family = AF_INET6; 1819 ipaddr->ipadm_intfidlen = prefixlen; 1820 return (IPADM_SUCCESS); 1821 } 1822 return (IPADM_INVALID_ARG); 1823 } 1824 1825 /* 1826 * Sets the value for the field `ipadm_stateless' in address object `ipaddr'. 1827 */ 1828 ipadm_status_t 1829 ipadm_set_stateless(ipadm_addrobj_t ipaddr, boolean_t stateless) 1830 { 1831 if (ipaddr == NULL || 1832 ipaddr->ipadm_atype != IPADM_ADDR_IPV6_ADDRCONF) 1833 return (IPADM_INVALID_ARG); 1834 ipaddr->ipadm_stateless = stateless; 1835 1836 return (IPADM_SUCCESS); 1837 } 1838 1839 /* 1840 * Sets the value for the field `ipadm_stateful' in address object `ipaddr'. 1841 */ 1842 ipadm_status_t 1843 ipadm_set_stateful(ipadm_addrobj_t ipaddr, boolean_t stateful) 1844 { 1845 if (ipaddr == NULL || 1846 ipaddr->ipadm_atype != IPADM_ADDR_IPV6_ADDRCONF) 1847 return (IPADM_INVALID_ARG); 1848 ipaddr->ipadm_stateful = stateful; 1849 1850 return (IPADM_SUCCESS); 1851 } 1852 1853 /* 1854 * Sets the dhcp parameter `ipadm_primary' in the address object `ipaddr'. 1855 * The field is used during the address creation with address 1856 * type IPADM_ADDR_DHCP. It specifies if the interface should be set 1857 * as a primary interface for getting dhcp global options from the DHCP server. 1858 */ 1859 ipadm_status_t 1860 ipadm_set_primary(ipadm_addrobj_t ipaddr, boolean_t primary) 1861 { 1862 if (ipaddr == NULL || ipaddr->ipadm_atype != IPADM_ADDR_DHCP) 1863 return (IPADM_INVALID_ARG); 1864 ipaddr->ipadm_primary = primary; 1865 1866 return (IPADM_SUCCESS); 1867 } 1868 1869 /* 1870 * Sets the dhcp parameter `ipadm_wait' in the address object `ipaddr'. 1871 * This field is used during the address creation with address type 1872 * IPADM_ADDR_DHCP. It specifies how long the API ipadm_create_addr() 1873 * should wait before returning while the dhcp address is being acquired 1874 * by the dhcpagent. 1875 * Possible values: 1876 * - IPADM_DHCP_WAIT_FOREVER : Do not return until dhcpagent returns. 1877 * - IPADM_DHCP_WAIT_DEFAULT : Wait a default amount of time before returning. 1878 * - <integer> : Wait the specified number of seconds before returning. 1879 */ 1880 ipadm_status_t 1881 ipadm_set_wait_time(ipadm_addrobj_t ipaddr, int32_t wait) 1882 { 1883 if (ipaddr == NULL || ipaddr->ipadm_atype != IPADM_ADDR_DHCP) 1884 return (IPADM_INVALID_ARG); 1885 ipaddr->ipadm_wait = wait; 1886 return (IPADM_SUCCESS); 1887 } 1888 1889 /* 1890 * Creates a placeholder for the `ipadm_aobjname' in the ipmgmtd `aobjmap'. 1891 * If the `aobjname' already exists in the daemon's `aobjmap' then 1892 * IPADM_ADDROBJ_EXISTS will be returned. 1893 * 1894 * If the libipadm consumer set `ipaddr.ipadm_aobjname[0]' to `\0', then the 1895 * daemon will generate an `aobjname' for the given `ipaddr'. 1896 */ 1897 ipadm_status_t 1898 i_ipadm_lookupadd_addrobj(ipadm_handle_t iph, ipadm_addrobj_t ipaddr) 1899 { 1900 ipmgmt_aobjop_arg_t larg; 1901 ipmgmt_aobjop_rval_t rval, *rvalp; 1902 int err; 1903 1904 bzero(&larg, sizeof (larg)); 1905 larg.ia_cmd = IPMGMT_CMD_ADDROBJ_LOOKUPADD; 1906 (void) strlcpy(larg.ia_aobjname, ipaddr->ipadm_aobjname, 1907 sizeof (larg.ia_aobjname)); 1908 (void) strlcpy(larg.ia_ifname, ipaddr->ipadm_ifname, 1909 sizeof (larg.ia_ifname)); 1910 larg.ia_family = ipaddr->ipadm_af; 1911 larg.ia_atype = ipaddr->ipadm_atype; 1912 1913 rvalp = &rval; 1914 err = ipadm_door_call(iph, &larg, sizeof (larg), (void **)&rvalp, 1915 sizeof (rval), B_FALSE); 1916 if (err == 0 && ipaddr->ipadm_aobjname[0] == '\0') { 1917 /* copy the daemon generated `aobjname' into `ipadddr' */ 1918 (void) strlcpy(ipaddr->ipadm_aobjname, rval.ir_aobjname, 1919 sizeof (ipaddr->ipadm_aobjname)); 1920 } 1921 if (err == EEXIST) 1922 return (IPADM_ADDROBJ_EXISTS); 1923 return (ipadm_errno2status(err)); 1924 } 1925 1926 /* 1927 * Sets the logical interface number in the ipmgmtd's memory map for the 1928 * address object `ipaddr'. If another address object has the same 1929 * logical interface number, IPADM_ADDROBJ_EXISTS is returned. 1930 */ 1931 ipadm_status_t 1932 i_ipadm_setlifnum_addrobj(ipadm_handle_t iph, ipadm_addrobj_t ipaddr) 1933 { 1934 ipmgmt_aobjop_arg_t larg; 1935 ipmgmt_retval_t rval, *rvalp; 1936 int err; 1937 1938 if (iph->iph_flags & IPH_IPMGMTD) 1939 return (IPADM_SUCCESS); 1940 1941 bzero(&larg, sizeof (larg)); 1942 larg.ia_cmd = IPMGMT_CMD_ADDROBJ_SETLIFNUM; 1943 (void) strlcpy(larg.ia_aobjname, ipaddr->ipadm_aobjname, 1944 sizeof (larg.ia_aobjname)); 1945 larg.ia_lnum = ipaddr->ipadm_lifnum; 1946 (void) strlcpy(larg.ia_ifname, ipaddr->ipadm_ifname, 1947 sizeof (larg.ia_ifname)); 1948 larg.ia_family = ipaddr->ipadm_af; 1949 1950 rvalp = &rval; 1951 err = ipadm_door_call(iph, &larg, sizeof (larg), (void **)&rvalp, 1952 sizeof (rval), B_FALSE); 1953 if (err == EEXIST) 1954 return (IPADM_ADDROBJ_EXISTS); 1955 return (ipadm_errno2status(err)); 1956 } 1957 1958 /* 1959 * Creates the IPv4 or IPv6 address in the nvlist `nvl' on the interface 1960 * `ifname'. If a hostname is present, it is resolved before the address 1961 * is created. 1962 */ 1963 ipadm_status_t 1964 i_ipadm_enable_static(ipadm_handle_t iph, const char *ifname, nvlist_t *nvl, 1965 sa_family_t af) 1966 { 1967 char *prefixlenstr = NULL; 1968 char *upstr = NULL; 1969 char *sname = NULL, *dname = NULL; 1970 struct ipadm_addrobj_s ipaddr; 1971 char *aobjname = NULL; 1972 nvlist_t *nvaddr = NULL; 1973 nvpair_t *nvp; 1974 char *cidraddr; 1975 char *name; 1976 ipadm_status_t status; 1977 int err = 0; 1978 uint32_t flags = IPADM_OPT_ACTIVE; 1979 1980 /* retrieve the address information */ 1981 for (nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL; 1982 nvp = nvlist_next_nvpair(nvl, nvp)) { 1983 name = nvpair_name(nvp); 1984 if (strcmp(name, IPADM_NVP_IPV4ADDR) == 0 || 1985 strcmp(name, IPADM_NVP_IPV6ADDR) == 0) { 1986 err = nvpair_value_nvlist(nvp, &nvaddr); 1987 } else if (strcmp(name, IPADM_NVP_AOBJNAME) == 0) { 1988 err = nvpair_value_string(nvp, &aobjname); 1989 } else if (strcmp(name, IPADM_NVP_PREFIXLEN) == 0) { 1990 err = nvpair_value_string(nvp, &prefixlenstr); 1991 } else if (strcmp(name, "up") == 0) { 1992 err = nvpair_value_string(nvp, &upstr); 1993 } 1994 if (err != 0) 1995 return (ipadm_errno2status(err)); 1996 } 1997 for (nvp = nvlist_next_nvpair(nvaddr, NULL); nvp != NULL; 1998 nvp = nvlist_next_nvpair(nvaddr, nvp)) { 1999 name = nvpair_name(nvp); 2000 if (strcmp(name, IPADM_NVP_IPADDRHNAME) == 0) 2001 err = nvpair_value_string(nvp, &sname); 2002 else if (strcmp(name, IPADM_NVP_IPDADDRHNAME) == 0) 2003 err = nvpair_value_string(nvp, &dname); 2004 if (err != 0) 2005 return (ipadm_errno2status(err)); 2006 } 2007 2008 if (strcmp(upstr, "yes") == 0) 2009 flags |= IPADM_OPT_UP; 2010 2011 /* build the address object from the above information */ 2012 i_ipadm_init_addr(&ipaddr, ifname, aobjname, IPADM_ADDR_STATIC); 2013 if (prefixlenstr != NULL && atoi(prefixlenstr) > 0) { 2014 if (asprintf(&cidraddr, "%s/%s", sname, prefixlenstr) == -1) 2015 return (IPADM_NO_MEMORY); 2016 status = ipadm_set_addr(&ipaddr, cidraddr, af); 2017 free(cidraddr); 2018 } else { 2019 status = ipadm_set_addr(&ipaddr, sname, af); 2020 } 2021 if (status != IPADM_SUCCESS) 2022 return (status); 2023 2024 if (dname != NULL) { 2025 status = ipadm_set_dst_addr(&ipaddr, dname, af); 2026 if (status != IPADM_SUCCESS) 2027 return (status); 2028 } 2029 return (i_ipadm_create_addr(iph, &ipaddr, flags)); 2030 } 2031 2032 /* 2033 * Creates a dhcp address on the interface `ifname' based on the 2034 * IPADM_ADDR_DHCP address object parameters from the nvlist `nvl'. 2035 */ 2036 ipadm_status_t 2037 i_ipadm_enable_dhcp(ipadm_handle_t iph, const char *ifname, nvlist_t *nvl) 2038 { 2039 int32_t wait; 2040 boolean_t primary; 2041 nvlist_t *nvdhcp; 2042 nvpair_t *nvp; 2043 char *name; 2044 struct ipadm_addrobj_s ipaddr; 2045 char *aobjname; 2046 int err = 0; 2047 2048 /* Extract the dhcp parameters */ 2049 for (nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL; 2050 nvp = nvlist_next_nvpair(nvl, nvp)) { 2051 name = nvpair_name(nvp); 2052 if (strcmp(name, IPADM_NVP_DHCP) == 0) 2053 err = nvpair_value_nvlist(nvp, &nvdhcp); 2054 else if (strcmp(name, IPADM_NVP_AOBJNAME) == 0) 2055 err = nvpair_value_string(nvp, &aobjname); 2056 if (err != 0) 2057 return (ipadm_errno2status(err)); 2058 } 2059 for (nvp = nvlist_next_nvpair(nvdhcp, NULL); nvp != NULL; 2060 nvp = nvlist_next_nvpair(nvdhcp, nvp)) { 2061 name = nvpair_name(nvp); 2062 if (strcmp(name, IPADM_NVP_WAIT) == 0) 2063 err = nvpair_value_int32(nvp, &wait); 2064 else if (strcmp(name, IPADM_NVP_PRIMARY) == 0) 2065 err = nvpair_value_boolean_value(nvp, &primary); 2066 if (err != 0) 2067 return (ipadm_errno2status(err)); 2068 } 2069 2070 /* Build the address object */ 2071 i_ipadm_init_addr(&ipaddr, ifname, aobjname, IPADM_ADDR_DHCP); 2072 ipaddr.ipadm_primary = primary; 2073 if (iph->iph_flags & IPH_INIT) 2074 ipaddr.ipadm_wait = 0; 2075 else 2076 ipaddr.ipadm_wait = wait; 2077 ipaddr.ipadm_af = AF_INET; 2078 return (i_ipadm_create_dhcp(iph, &ipaddr, IPADM_OPT_ACTIVE)); 2079 } 2080 2081 /* 2082 * Creates auto-configured addresses on the interface `ifname' based on 2083 * the IPADM_ADDR_IPV6_ADDRCONF address object parameters from the nvlist `nvl'. 2084 */ 2085 ipadm_status_t 2086 i_ipadm_enable_addrconf(ipadm_handle_t iph, const char *ifname, nvlist_t *nvl) 2087 { 2088 struct ipadm_addrobj_s ipaddr; 2089 char *stateful = NULL, *stateless = NULL; 2090 uint_t n; 2091 uint8_t *addr6 = NULL; 2092 uint32_t intfidlen = 0; 2093 char *aobjname; 2094 nvlist_t *nvaddr; 2095 nvpair_t *nvp; 2096 char *name; 2097 int err = 0; 2098 2099 /* Extract the parameters */ 2100 for (nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL; 2101 nvp = nvlist_next_nvpair(nvl, nvp)) { 2102 name = nvpair_name(nvp); 2103 if (strcmp(name, IPADM_NVP_INTFID) == 0) 2104 err = nvpair_value_nvlist(nvp, &nvaddr); 2105 else if (strcmp(name, IPADM_NVP_AOBJNAME) == 0) 2106 err = nvpair_value_string(nvp, &aobjname); 2107 if (err != 0) 2108 return (ipadm_errno2status(err)); 2109 } 2110 for (nvp = nvlist_next_nvpair(nvaddr, NULL); nvp != NULL; 2111 nvp = nvlist_next_nvpair(nvaddr, nvp)) { 2112 name = nvpair_name(nvp); 2113 if (strcmp(name, IPADM_NVP_IPNUMADDR) == 0) 2114 err = nvpair_value_uint8_array(nvp, &addr6, &n); 2115 if (strcmp(name, IPADM_NVP_PREFIXLEN) == 0) 2116 err = nvpair_value_uint32(nvp, &intfidlen); 2117 else if (strcmp(name, IPADM_NVP_STATELESS) == 0) 2118 err = nvpair_value_string(nvp, &stateless); 2119 else if (strcmp(name, IPADM_NVP_STATEFUL) == 0) 2120 err = nvpair_value_string(nvp, &stateful); 2121 if (err != 0) 2122 return (ipadm_errno2status(err)); 2123 } 2124 /* Build the address object. */ 2125 i_ipadm_init_addr(&ipaddr, ifname, aobjname, IPADM_ADDR_IPV6_ADDRCONF); 2126 if (intfidlen > 0) { 2127 ipaddr.ipadm_intfidlen = intfidlen; 2128 bcopy(addr6, &ipaddr.ipadm_intfid.sin6_addr.s6_addr, n); 2129 } 2130 ipaddr.ipadm_stateless = (strcmp(stateless, "yes") == 0); 2131 ipaddr.ipadm_stateful = (strcmp(stateful, "yes") == 0); 2132 return (i_ipadm_create_ipv6addrs(iph, &ipaddr, IPADM_OPT_ACTIVE)); 2133 } 2134 2135 /* 2136 * Allocates `ipadm_addrobj_t' and populates the relevant member fields based on 2137 * the provided `type'. `aobjname' represents the address object name, which 2138 * is of the form `<ifname>/<addressname>'. 2139 * 2140 * The caller has to minimally provide <ifname>. If <addressname> is not 2141 * provided, then a default one will be generated by the API. 2142 */ 2143 ipadm_status_t 2144 ipadm_create_addrobj(ipadm_addr_type_t type, const char *aobjname, 2145 ipadm_addrobj_t *ipaddr) 2146 { 2147 ipadm_addrobj_t newaddr; 2148 ipadm_status_t status; 2149 char *aname, *cp; 2150 char ifname[IPADM_AOBJSIZ]; 2151 ifspec_t ifsp; 2152 2153 if (ipaddr == NULL) 2154 return (IPADM_INVALID_ARG); 2155 *ipaddr = NULL; 2156 2157 if (aobjname == NULL || aobjname[0] == '\0') 2158 return (IPADM_INVALID_ARG); 2159 2160 if (strlcpy(ifname, aobjname, IPADM_AOBJSIZ) >= IPADM_AOBJSIZ) 2161 return (IPADM_INVALID_ARG); 2162 2163 if ((aname = strchr(ifname, '/')) != NULL) 2164 *aname++ = '\0'; 2165 2166 /* Check if the interface name is valid. */ 2167 if (!ifparse_ifspec(ifname, &ifsp)) 2168 return (IPADM_INVALID_ARG); 2169 2170 /* Check if the given addrobj name is valid. */ 2171 if (aname != NULL && !i_ipadm_is_user_aobjname_valid(aname)) 2172 return (IPADM_INVALID_ARG); 2173 2174 if ((newaddr = calloc(1, sizeof (struct ipadm_addrobj_s))) == NULL) 2175 return (IPADM_NO_MEMORY); 2176 2177 /* 2178 * If the ifname has logical interface number, extract it and assign 2179 * it to `ipadm_lifnum'. Only applications with IPH_LEGACY set will do 2180 * this today. We will check for the validity later in 2181 * i_ipadm_validate_create_addr(). 2182 */ 2183 if (ifsp.ifsp_lunvalid) { 2184 newaddr->ipadm_lifnum = ifsp.ifsp_lun; 2185 cp = strchr(ifname, IPADM_LOGICAL_SEP); 2186 *cp = '\0'; 2187 } 2188 (void) strlcpy(newaddr->ipadm_ifname, ifname, 2189 sizeof (newaddr->ipadm_ifname)); 2190 2191 if (aname != NULL) { 2192 (void) snprintf(newaddr->ipadm_aobjname, 2193 sizeof (newaddr->ipadm_aobjname), "%s/%s", ifname, aname); 2194 } 2195 2196 switch (type) { 2197 case IPADM_ADDR_IPV6_ADDRCONF: 2198 newaddr->ipadm_intfidlen = 0; 2199 newaddr->ipadm_stateful = B_TRUE; 2200 newaddr->ipadm_stateless = B_TRUE; 2201 newaddr->ipadm_af = AF_INET6; 2202 break; 2203 2204 case IPADM_ADDR_DHCP: 2205 newaddr->ipadm_primary = B_FALSE; 2206 newaddr->ipadm_wait = IPADM_DHCP_WAIT_DEFAULT; 2207 newaddr->ipadm_af = AF_INET; 2208 break; 2209 2210 case IPADM_ADDR_STATIC: 2211 newaddr->ipadm_af = AF_UNSPEC; 2212 newaddr->ipadm_static_prefixlen = 0; 2213 break; 2214 2215 default: 2216 status = IPADM_INVALID_ARG; 2217 goto fail; 2218 } 2219 newaddr->ipadm_atype = type; 2220 *ipaddr = newaddr; 2221 return (IPADM_SUCCESS); 2222 fail: 2223 free(newaddr); 2224 return (status); 2225 } 2226 2227 /* 2228 * Returns `aobjname' from the address object in `ipaddr'. 2229 */ 2230 ipadm_status_t 2231 ipadm_get_aobjname(const ipadm_addrobj_t ipaddr, char *aobjname, size_t len) 2232 { 2233 if (ipaddr == NULL || aobjname == NULL) 2234 return (IPADM_INVALID_ARG); 2235 if (strlcpy(aobjname, ipaddr->ipadm_aobjname, len) >= len) 2236 return (IPADM_INVALID_ARG); 2237 2238 return (IPADM_SUCCESS); 2239 } 2240 2241 /* 2242 * Frees the address object in `ipaddr'. 2243 */ 2244 void 2245 ipadm_destroy_addrobj(ipadm_addrobj_t ipaddr) 2246 { 2247 free(ipaddr); 2248 } 2249 2250 /* 2251 * Retrieves the logical interface name from `ipaddr' and stores the 2252 * string in `lifname'. 2253 */ 2254 void 2255 i_ipadm_addrobj2lifname(ipadm_addrobj_t ipaddr, char *lifname, int lifnamesize) 2256 { 2257 if (ipaddr->ipadm_lifnum != 0) { 2258 (void) snprintf(lifname, lifnamesize, "%s:%d", 2259 ipaddr->ipadm_ifname, ipaddr->ipadm_lifnum); 2260 } else { 2261 (void) snprintf(lifname, lifnamesize, "%s", 2262 ipaddr->ipadm_ifname); 2263 } 2264 } 2265 2266 /* 2267 * Checks if a non-zero static address is present on the 0th logical interface 2268 * of the given IPv4 or IPv6 physical interface. For an IPv4 interface, it 2269 * also checks if the interface is under DHCP control. If the condition is true, 2270 * the output argument `exists' will be set to B_TRUE. Otherwise, `exists' 2271 * is set to B_FALSE. 2272 * 2273 * Note that *exists will not be initialized if an error is encountered. 2274 */ 2275 static ipadm_status_t 2276 i_ipadm_addr_exists_on_if(ipadm_handle_t iph, const char *ifname, 2277 sa_family_t af, boolean_t *exists) 2278 { 2279 struct lifreq lifr; 2280 int sock; 2281 2282 /* For IPH_LEGACY, a new logical interface will never be added. */ 2283 if (iph->iph_flags & IPH_LEGACY) { 2284 *exists = B_FALSE; 2285 return (IPADM_SUCCESS); 2286 } 2287 bzero(&lifr, sizeof (lifr)); 2288 (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name)); 2289 if (af == AF_INET) { 2290 sock = iph->iph_sock; 2291 if (ioctl(sock, SIOCGLIFFLAGS, (caddr_t)&lifr) < 0) 2292 return (ipadm_errno2status(errno)); 2293 if (lifr.lifr_flags & IFF_DHCPRUNNING) { 2294 *exists = B_TRUE; 2295 return (IPADM_SUCCESS); 2296 } 2297 } else { 2298 sock = iph->iph_sock6; 2299 } 2300 if (ioctl(sock, SIOCGLIFADDR, (caddr_t)&lifr) < 0) 2301 return (ipadm_errno2status(errno)); 2302 *exists = !sockaddrunspec(&lifr.lifr_addr); 2303 2304 return (IPADM_SUCCESS); 2305 } 2306 2307 /* 2308 * Adds a new logical interface in the kernel for interface 2309 * `addr->ipadm_ifname', if there is a non-zero address on the 0th 2310 * logical interface or if the 0th logical interface is under DHCP 2311 * control. On success, it sets the lifnum in the address object `addr'. 2312 */ 2313 ipadm_status_t 2314 i_ipadm_do_addif(ipadm_handle_t iph, ipadm_addrobj_t addr) 2315 { 2316 ipadm_status_t status; 2317 boolean_t addif; 2318 struct lifreq lifr; 2319 int sock; 2320 2321 addr->ipadm_lifnum = 0; 2322 status = i_ipadm_addr_exists_on_if(iph, addr->ipadm_ifname, 2323 addr->ipadm_af, &addif); 2324 if (status != IPADM_SUCCESS) 2325 return (status); 2326 if (addif) { 2327 /* 2328 * If there is an address on 0th logical interface, 2329 * add a new logical interface. 2330 */ 2331 bzero(&lifr, sizeof (lifr)); 2332 (void) strlcpy(lifr.lifr_name, addr->ipadm_ifname, 2333 sizeof (lifr.lifr_name)); 2334 sock = (addr->ipadm_af == AF_INET ? iph->iph_sock : 2335 iph->iph_sock6); 2336 if (ioctl(sock, SIOCLIFADDIF, (caddr_t)&lifr) < 0) 2337 return (ipadm_errno2status(errno)); 2338 addr->ipadm_lifnum = i_ipadm_get_lnum(lifr.lifr_name); 2339 } 2340 return (IPADM_SUCCESS); 2341 } 2342 2343 /* 2344 * Reads all the address lines from the persistent DB into the nvlist `onvl', 2345 * when both `ifname' and `aobjname' are NULL. If an `ifname' is provided, 2346 * it returns all the addresses for the given interface `ifname'. 2347 * If an `aobjname' is specified, then the address line corresponding to 2348 * that name will be returned. 2349 */ 2350 static ipadm_status_t 2351 i_ipadm_get_db_addr(ipadm_handle_t iph, const char *ifname, 2352 const char *aobjname, nvlist_t **onvl) 2353 { 2354 ipmgmt_getaddr_arg_t garg; 2355 ipmgmt_get_rval_t *rvalp; 2356 int err; 2357 size_t nvlsize; 2358 char *nvlbuf; 2359 2360 /* Populate the door_call argument structure */ 2361 bzero(&garg, sizeof (garg)); 2362 garg.ia_cmd = IPMGMT_CMD_GETADDR; 2363 if (aobjname != NULL) 2364 (void) strlcpy(garg.ia_aobjname, aobjname, 2365 sizeof (garg.ia_aobjname)); 2366 if (ifname != NULL) 2367 (void) strlcpy(garg.ia_ifname, ifname, sizeof (garg.ia_ifname)); 2368 2369 rvalp = malloc(sizeof (ipmgmt_get_rval_t)); 2370 err = ipadm_door_call(iph, &garg, sizeof (garg), (void **)&rvalp, 2371 sizeof (*rvalp), B_TRUE); 2372 if (err == 0) { 2373 nvlsize = rvalp->ir_nvlsize; 2374 nvlbuf = (char *)rvalp + sizeof (ipmgmt_get_rval_t); 2375 err = nvlist_unpack(nvlbuf, nvlsize, onvl, NV_ENCODE_NATIVE); 2376 } 2377 free(rvalp); 2378 return (ipadm_errno2status(err)); 2379 } 2380 2381 /* 2382 * Adds the IP address contained in the 'ipaddr' argument to the physical 2383 * interface represented by 'ifname' after doing the required validation. 2384 * If the interface does not exist, it is created before the address is 2385 * added. 2386 * 2387 * If IPH_LEGACY is set in iph_flags, flags has to be IPADM_OPT_ACTIVE 2388 * and a default addrobj name will be generated. Input `addr->ipadm_aobjname', 2389 * if provided, will be ignored and replaced with the newly generated name. 2390 * The interface name provided has to be a logical interface name that 2391 * already exists. No new logical interface will be added in this function. 2392 * 2393 * If IPADM_OPT_V46 is passed in the flags, then both IPv4 and IPv6 interfaces 2394 * are plumbed (if they haven't been already). Otherwise, just the interface 2395 * specified in `addr' is plumbed. 2396 */ 2397 ipadm_status_t 2398 ipadm_create_addr(ipadm_handle_t iph, ipadm_addrobj_t addr, uint32_t flags) 2399 { 2400 ipadm_status_t status; 2401 sa_family_t af; 2402 sa_family_t daf; 2403 sa_family_t other_af; 2404 boolean_t created_af = B_FALSE; 2405 boolean_t created_other_af = B_FALSE; 2406 ipadm_addr_type_t type; 2407 char *ifname = addr->ipadm_ifname; 2408 boolean_t legacy = (iph->iph_flags & IPH_LEGACY); 2409 boolean_t aobjfound; 2410 boolean_t is_6to4; 2411 struct lifreq lifr; 2412 uint64_t ifflags; 2413 boolean_t is_boot = (iph->iph_flags & IPH_IPMGMTD); 2414 2415 /* check for solaris.network.interface.config authorization */ 2416 if (!ipadm_check_auth()) 2417 return (IPADM_EAUTH); 2418 2419 /* Validate the addrobj. This also fills in addr->ipadm_ifname. */ 2420 status = i_ipadm_validate_create_addr(iph, addr, flags); 2421 if (status != IPADM_SUCCESS) 2422 return (status); 2423 2424 /* 2425 * For Legacy case, check if an addrobj already exists for the 2426 * given logical interface name. If one does not exist, 2427 * a default name will be generated and added to the daemon's 2428 * aobjmap. 2429 */ 2430 if (legacy) { 2431 struct ipadm_addrobj_s ipaddr; 2432 2433 ipaddr = *addr; 2434 status = i_ipadm_get_lif2addrobj(iph, &ipaddr); 2435 if (status == IPADM_SUCCESS) { 2436 aobjfound = B_TRUE; 2437 /* 2438 * With IPH_LEGACY, modifying an address that is not 2439 * a static address will return with an error. 2440 */ 2441 if (ipaddr.ipadm_atype != IPADM_ADDR_STATIC) 2442 return (IPADM_NOTSUP); 2443 /* 2444 * we found the addrobj in daemon, copy over the 2445 * aobjname to `addr'. 2446 */ 2447 (void) strlcpy(addr->ipadm_aobjname, 2448 ipaddr.ipadm_aobjname, IPADM_AOBJSIZ); 2449 } else if (status == IPADM_NOTFOUND) { 2450 aobjfound = B_FALSE; 2451 } else { 2452 return (status); 2453 } 2454 } 2455 2456 af = addr->ipadm_af; 2457 /* 2458 * Create a placeholder for this address object in the daemon. 2459 * Skip this step if we are booting a zone (and therefore being called 2460 * from ipmgmtd itself), and, for IPH_LEGACY case if the 2461 * addrobj already exists. 2462 * 2463 * Note that the placeholder is not needed in the NGZ boot case, 2464 * when zoneadmd has itself applied the "allowed-ips" property to clamp 2465 * down any interface configuration, so the namespace for the interface 2466 * is fully controlled by the GZ. 2467 */ 2468 if (!is_boot && (!legacy || !aobjfound)) { 2469 status = i_ipadm_lookupadd_addrobj(iph, addr); 2470 if (status != IPADM_SUCCESS) 2471 return (status); 2472 } 2473 2474 is_6to4 = i_ipadm_is_6to4(iph, ifname); 2475 /* Plumb the IP interfaces if necessary */ 2476 status = i_ipadm_create_if(iph, ifname, af, flags); 2477 if (status != IPADM_SUCCESS && status != IPADM_IF_EXISTS) { 2478 (void) i_ipadm_delete_addrobj(iph, addr, IPADM_OPT_ACTIVE); 2479 return (status); 2480 } 2481 if (status == IPADM_SUCCESS) 2482 created_af = B_TRUE; 2483 if (!is_6to4 && !legacy && (flags & IPADM_OPT_V46)) { 2484 other_af = (af == AF_INET ? AF_INET6 : AF_INET); 2485 status = i_ipadm_create_if(iph, ifname, other_af, flags); 2486 if (status != IPADM_SUCCESS && status != IPADM_IF_EXISTS) { 2487 (void) i_ipadm_delete_if(iph, ifname, af, flags); 2488 return (status); 2489 } 2490 if (status == IPADM_SUCCESS) 2491 created_other_af = B_TRUE; 2492 } 2493 2494 /* 2495 * Some input validation based on the interface flags: 2496 * 1. in non-global zones, make sure that we are not persistently 2497 * creating addresses on interfaces that are acquiring 2498 * address from the global zone. 2499 * 2. Validate static addresses for IFF_POINTOPOINT interfaces. 2500 */ 2501 if (addr->ipadm_atype == IPADM_ADDR_STATIC) { 2502 status = i_ipadm_get_flags(iph, ifname, af, &ifflags); 2503 if (status != IPADM_SUCCESS) 2504 goto fail; 2505 2506 if (iph->iph_zoneid != GLOBAL_ZONEID && 2507 (ifflags & IFF_L3PROTECT) && (flags & IPADM_OPT_PERSIST)) { 2508 status = IPADM_GZ_PERM; 2509 goto fail; 2510 } 2511 daf = addr->ipadm_static_dst_addr.ss_family; 2512 if (ifflags & IFF_POINTOPOINT) { 2513 if (is_6to4) { 2514 if (af != AF_INET6 || daf != AF_UNSPEC) { 2515 status = IPADM_INVALID_ARG; 2516 goto fail; 2517 } 2518 } else { 2519 if (daf != af) { 2520 status = IPADM_INVALID_ARG; 2521 goto fail; 2522 } 2523 /* Check for a valid dst address. */ 2524 if (!legacy && sockaddrunspec( 2525 &addr->ipadm_static_dst_addr)) { 2526 status = IPADM_BAD_ADDR; 2527 goto fail; 2528 } 2529 } 2530 } else { 2531 /* 2532 * Disallow setting of dstaddr when the link is not 2533 * a point-to-point link. 2534 */ 2535 if (daf != AF_UNSPEC) 2536 return (IPADM_INVALID_ARG); 2537 } 2538 } 2539 2540 /* 2541 * For 6to4 interfaces, kernel configures a default link-local 2542 * address. We need to replace it, if the caller has provided 2543 * an address that is different from the default link-local. 2544 */ 2545 if (status == IPADM_SUCCESS && is_6to4) { 2546 bzero(&lifr, sizeof (lifr)); 2547 (void) strlcpy(lifr.lifr_name, addr->ipadm_ifname, 2548 sizeof (lifr.lifr_name)); 2549 if (ioctl(iph->iph_sock6, SIOCGLIFADDR, &lifr) < 0) { 2550 status = ipadm_errno2status(errno); 2551 goto fail; 2552 } 2553 if (sockaddrcmp(&lifr.lifr_addr, &addr->ipadm_static_addr)) 2554 return (IPADM_SUCCESS); 2555 } 2556 2557 /* Create the address. */ 2558 type = addr->ipadm_atype; 2559 switch (type) { 2560 case IPADM_ADDR_STATIC: 2561 status = i_ipadm_create_addr(iph, addr, flags); 2562 break; 2563 case IPADM_ADDR_DHCP: 2564 status = i_ipadm_create_dhcp(iph, addr, flags); 2565 break; 2566 case IPADM_ADDR_IPV6_ADDRCONF: 2567 status = i_ipadm_create_ipv6addrs(iph, addr, flags); 2568 break; 2569 default: 2570 status = IPADM_INVALID_ARG; 2571 break; 2572 } 2573 2574 /* 2575 * If address was not created successfully, unplumb the interface 2576 * if it was plumbed implicitly in this function and remove the 2577 * addrobj created by the ipmgmtd daemon as a placeholder. 2578 * If IPH_LEGACY is set, then remove the addrobj only if it was 2579 * created in this function. 2580 */ 2581 fail: 2582 if (status != IPADM_DHCP_IPC_TIMEOUT && 2583 status != IPADM_SUCCESS) { 2584 if (!legacy) { 2585 if (created_af || created_other_af) { 2586 if (created_af) { 2587 (void) i_ipadm_delete_if(iph, ifname, 2588 af, flags); 2589 } 2590 if (created_other_af) { 2591 (void) i_ipadm_delete_if(iph, ifname, 2592 other_af, flags); 2593 } 2594 } else { 2595 (void) i_ipadm_delete_addrobj(iph, addr, flags); 2596 } 2597 } else if (!aobjfound) { 2598 (void) i_ipadm_delete_addrobj(iph, addr, flags); 2599 } 2600 } 2601 2602 return (status); 2603 } 2604 2605 /* 2606 * Creates the static address in `ipaddr' in kernel. After successfully 2607 * creating it, it updates the ipmgmtd daemon's aobjmap with the logical 2608 * interface information. 2609 */ 2610 static ipadm_status_t 2611 i_ipadm_create_addr(ipadm_handle_t iph, ipadm_addrobj_t ipaddr, uint32_t flags) 2612 { 2613 struct lifreq lifr; 2614 ipadm_status_t status = IPADM_SUCCESS; 2615 int sock; 2616 struct sockaddr_storage m, *mask = &m; 2617 const struct sockaddr_storage *addr = &ipaddr->ipadm_static_addr; 2618 const struct sockaddr_storage *daddr = &ipaddr->ipadm_static_dst_addr; 2619 sa_family_t af; 2620 boolean_t legacy = (iph->iph_flags & IPH_LEGACY); 2621 struct ipadm_addrobj_s legacy_addr; 2622 boolean_t default_prefixlen = B_FALSE; 2623 boolean_t is_boot; 2624 2625 is_boot = ((iph->iph_flags & IPH_IPMGMTD) != 0); 2626 af = ipaddr->ipadm_af; 2627 sock = (af == AF_INET ? iph->iph_sock : iph->iph_sock6); 2628 2629 /* If prefixlen was not provided, get default prefixlen */ 2630 if (ipaddr->ipadm_static_prefixlen == 0) { 2631 /* prefixlen was not provided, get default prefixlen */ 2632 status = i_ipadm_get_default_prefixlen( 2633 &ipaddr->ipadm_static_addr, 2634 &ipaddr->ipadm_static_prefixlen); 2635 if (status != IPADM_SUCCESS) 2636 return (status); 2637 default_prefixlen = B_TRUE; 2638 } 2639 (void) plen2mask(ipaddr->ipadm_static_prefixlen, af, mask); 2640 2641 /* 2642 * Create a new logical interface if needed; otherwise, just 2643 * use the 0th logical interface. 2644 */ 2645 retry: 2646 if (!(iph->iph_flags & IPH_LEGACY)) { 2647 status = i_ipadm_do_addif(iph, ipaddr); 2648 if (status != IPADM_SUCCESS) 2649 return (status); 2650 /* 2651 * We don't have to set the lifnum for IPH_INIT case, because 2652 * there is no placeholder created for the address object in 2653 * this case. For IPH_LEGACY, we don't do this because the 2654 * lifnum is given by the caller and it will be set in the 2655 * end while we call the i_ipadm_addr_persist(). 2656 */ 2657 if (!(iph->iph_flags & IPH_INIT)) { 2658 status = i_ipadm_setlifnum_addrobj(iph, ipaddr); 2659 if (status == IPADM_ADDROBJ_EXISTS) 2660 goto retry; 2661 if (status != IPADM_SUCCESS) 2662 return (status); 2663 } 2664 } 2665 i_ipadm_addrobj2lifname(ipaddr, lifr.lifr_name, 2666 sizeof (lifr.lifr_name)); 2667 lifr.lifr_addr = *mask; 2668 if (ioctl(sock, SIOCSLIFNETMASK, (caddr_t)&lifr) < 0) { 2669 status = ipadm_errno2status(errno); 2670 goto ret; 2671 } 2672 lifr.lifr_addr = *addr; 2673 if (ioctl(sock, SIOCSLIFADDR, (caddr_t)&lifr) < 0) { 2674 status = ipadm_errno2status(errno); 2675 goto ret; 2676 } 2677 /* Set the destination address, if one is given. */ 2678 if (daddr->ss_family != AF_UNSPEC) { 2679 lifr.lifr_addr = *daddr; 2680 if (ioctl(sock, SIOCSLIFDSTADDR, (caddr_t)&lifr) < 0) { 2681 status = ipadm_errno2status(errno); 2682 goto ret; 2683 } 2684 } 2685 2686 if (flags & IPADM_OPT_UP) { 2687 status = i_ipadm_set_flags(iph, lifr.lifr_name, af, IFF_UP, 0); 2688 2689 /* 2690 * IPADM_DAD_FOUND is a soft-error for create-addr. 2691 * No need to tear down the address. 2692 */ 2693 if (status == IPADM_DAD_FOUND) 2694 status = IPADM_SUCCESS; 2695 } 2696 2697 if (status == IPADM_SUCCESS && !is_boot) { 2698 /* 2699 * For IPH_LEGACY, we might be modifying the address on 2700 * an address object that already exists e.g. by doing 2701 * "ifconfig bge0:1 <addr>; ifconfig bge0:1 <newaddr>" 2702 * So, we need to store the object only if it does not 2703 * already exist in ipmgmtd. 2704 */ 2705 if (legacy) { 2706 bzero(&legacy_addr, sizeof (legacy_addr)); 2707 (void) strlcpy(legacy_addr.ipadm_aobjname, 2708 ipaddr->ipadm_aobjname, 2709 sizeof (legacy_addr.ipadm_aobjname)); 2710 status = i_ipadm_get_addrobj(iph, &legacy_addr); 2711 if (status == IPADM_SUCCESS && 2712 legacy_addr.ipadm_lifnum >= 0) { 2713 return (status); 2714 } 2715 } 2716 status = i_ipadm_addr_persist(iph, ipaddr, default_prefixlen, 2717 flags); 2718 } 2719 ret: 2720 if (status != IPADM_SUCCESS && !legacy) 2721 (void) i_ipadm_delete_addr(iph, ipaddr); 2722 return (status); 2723 } 2724 2725 /* 2726 * Removes the address object identified by `aobjname' from both active and 2727 * persistent configuration. The address object will be removed from only 2728 * active configuration if IPH_LEGACY is set in `iph->iph_flags'. 2729 * 2730 * If the address type is IPADM_ADDR_STATIC or IPADM_ADDR_DHCP, the address 2731 * in the address object will be removed from the physical interface. 2732 * If the address type is IPADM_ADDR_DHCP, the flag IPADM_OPT_RELEASE specifies 2733 * whether the lease should be released. If IPADM_OPT_RELEASE is not 2734 * specified, the lease will be dropped. This option is not supported 2735 * for other address types. 2736 * 2737 * If the address type is IPADM_ADDR_IPV6_ADDRCONF, the link-local address and 2738 * all the autoconfigured addresses will be removed. 2739 * Finally, the address object is also removed from ipmgmtd's aobjmap and from 2740 * the persistent DB. 2741 */ 2742 ipadm_status_t 2743 ipadm_delete_addr(ipadm_handle_t iph, const char *aobjname, uint32_t flags) 2744 { 2745 ipadm_status_t status; 2746 struct ipadm_addrobj_s ipaddr; 2747 boolean_t release = ((flags & IPADM_OPT_RELEASE) != 0); 2748 2749 /* check for solaris.network.interface.config authorization */ 2750 if (!ipadm_check_auth()) 2751 return (IPADM_EAUTH); 2752 2753 /* validate input */ 2754 if (flags == 0 || ((flags & IPADM_OPT_PERSIST) && 2755 !(flags & IPADM_OPT_ACTIVE)) || 2756 (flags & ~(IPADM_COMMON_OPT_MASK|IPADM_OPT_RELEASE))) { 2757 return (IPADM_INVALID_ARG); 2758 } 2759 bzero(&ipaddr, sizeof (ipaddr)); 2760 if (aobjname == NULL || strlcpy(ipaddr.ipadm_aobjname, aobjname, 2761 IPADM_AOBJSIZ) >= IPADM_AOBJSIZ) { 2762 return (IPADM_INVALID_ARG); 2763 } 2764 2765 /* Retrieve the address object information from ipmgmtd. */ 2766 status = i_ipadm_get_addrobj(iph, &ipaddr); 2767 if (status != IPADM_SUCCESS) 2768 return (status); 2769 2770 if (release && ipaddr.ipadm_atype != IPADM_ADDR_DHCP) 2771 return (IPADM_NOTSUP); 2772 /* 2773 * If requested to delete just from active config but the address 2774 * is not in active config, return error. 2775 */ 2776 if (!(ipaddr.ipadm_flags & IPMGMT_ACTIVE) && 2777 (flags & IPADM_OPT_ACTIVE) && !(flags & IPADM_OPT_PERSIST)) { 2778 return (IPADM_NOTFOUND); 2779 } 2780 2781 /* 2782 * If address is present in active config, remove it from 2783 * kernel. 2784 */ 2785 if (ipaddr.ipadm_flags & IPMGMT_ACTIVE) { 2786 switch (ipaddr.ipadm_atype) { 2787 case IPADM_ADDR_STATIC: 2788 status = i_ipadm_delete_addr(iph, &ipaddr); 2789 break; 2790 case IPADM_ADDR_DHCP: 2791 status = i_ipadm_delete_dhcp(iph, &ipaddr, release); 2792 break; 2793 case IPADM_ADDR_IPV6_ADDRCONF: 2794 status = i_ipadm_delete_ipv6addrs(iph, &ipaddr); 2795 break; 2796 default: 2797 /* 2798 * This is the case of address object name residing in 2799 * daemon's aobjmap (added by ADDROBJ_LOOKUPADD). Fall 2800 * through and delete that address object. 2801 */ 2802 break; 2803 } 2804 2805 /* 2806 * If the address was previously deleted from the active 2807 * config, we will get a IPADM_ENXIO from kernel. 2808 * We will still proceed and purge the address information 2809 * in the DB. 2810 */ 2811 if (status == IPADM_ENXIO) 2812 status = IPADM_SUCCESS; 2813 else if (status != IPADM_SUCCESS) 2814 return (status); 2815 } 2816 2817 if (!(ipaddr.ipadm_flags & IPMGMT_PERSIST) && 2818 (flags & IPADM_OPT_PERSIST)) { 2819 flags &= ~IPADM_OPT_PERSIST; 2820 } 2821 status = i_ipadm_delete_addrobj(iph, &ipaddr, flags); 2822 if (status == IPADM_NOTFOUND) 2823 return (status); 2824 return (IPADM_SUCCESS); 2825 } 2826 2827 /* 2828 * Starts the dhcpagent and sends it the message DHCP_START to start 2829 * configuring a dhcp address on the given interface in `addr'. 2830 * After making the dhcpagent request, it also updates the 2831 * address object information in ipmgmtd's aobjmap and creates an 2832 * entry in persistent DB if IPADM_OPT_PERSIST is set in `flags'. 2833 */ 2834 static ipadm_status_t 2835 i_ipadm_create_dhcp(ipadm_handle_t iph, ipadm_addrobj_t addr, uint32_t flags) 2836 { 2837 ipadm_status_t status; 2838 ipadm_status_t dh_status; 2839 2840 if (dhcp_start_agent(DHCP_IPC_MAX_WAIT) == -1) 2841 return (IPADM_DHCP_START_ERROR); 2842 /* 2843 * Create a new logical interface if needed; otherwise, just 2844 * use the 0th logical interface. 2845 */ 2846 retry: 2847 status = i_ipadm_do_addif(iph, addr); 2848 if (status != IPADM_SUCCESS) 2849 return (status); 2850 /* 2851 * We don't have to set the lifnum for IPH_INIT case, because 2852 * there is no placeholder created for the address object in this 2853 * case. 2854 */ 2855 if (!(iph->iph_flags & IPH_INIT)) { 2856 status = i_ipadm_setlifnum_addrobj(iph, addr); 2857 if (status == IPADM_ADDROBJ_EXISTS) 2858 goto retry; 2859 if (status != IPADM_SUCCESS) 2860 return (status); 2861 } 2862 /* Send DHCP_START to the dhcpagent. */ 2863 status = i_ipadm_op_dhcp(addr, DHCP_START, NULL); 2864 /* 2865 * We do not undo the create-addr operation for IPADM_DHCP_IPC_TIMEOUT 2866 * since it is only a soft error to indicate the caller that the lease 2867 * might be required after the function returns. 2868 */ 2869 if (status != IPADM_SUCCESS && status != IPADM_DHCP_IPC_TIMEOUT) 2870 goto fail; 2871 dh_status = status; 2872 2873 /* Persist the address object information in ipmgmtd. */ 2874 status = i_ipadm_addr_persist(iph, addr, B_FALSE, flags); 2875 if (status != IPADM_SUCCESS) 2876 goto fail; 2877 2878 return (dh_status); 2879 fail: 2880 /* In case of error, delete the dhcp address */ 2881 (void) i_ipadm_delete_dhcp(iph, addr, B_TRUE); 2882 return (status); 2883 } 2884 2885 /* 2886 * Releases/drops the dhcp lease on the logical interface in the address 2887 * object `addr'. If `release' is set to B_FALSE, the lease will be dropped. 2888 */ 2889 static ipadm_status_t 2890 i_ipadm_delete_dhcp(ipadm_handle_t iph, ipadm_addrobj_t addr, boolean_t release) 2891 { 2892 ipadm_status_t status; 2893 int dherr; 2894 2895 /* Send DHCP_RELEASE or DHCP_DROP to the dhcpagent */ 2896 if (release) { 2897 status = i_ipadm_op_dhcp(addr, DHCP_RELEASE, &dherr); 2898 /* 2899 * If no lease was obtained on the object, we should 2900 * drop the dhcp control on the interface. 2901 */ 2902 if (status != IPADM_SUCCESS && dherr == DHCP_IPC_E_OUTSTATE) 2903 status = i_ipadm_op_dhcp(addr, DHCP_DROP, NULL); 2904 } else { 2905 status = i_ipadm_op_dhcp(addr, DHCP_DROP, NULL); 2906 } 2907 if (status != IPADM_SUCCESS) 2908 return (status); 2909 2910 /* Delete the logical interface */ 2911 if (addr->ipadm_lifnum != 0) { 2912 struct lifreq lifr; 2913 2914 bzero(&lifr, sizeof (lifr)); 2915 i_ipadm_addrobj2lifname(addr, lifr.lifr_name, 2916 sizeof (lifr.lifr_name)); 2917 if (ioctl(iph->iph_sock, SIOCLIFREMOVEIF, (caddr_t)&lifr) < 0) 2918 return (ipadm_errno2status(errno)); 2919 } 2920 2921 return (IPADM_SUCCESS); 2922 } 2923 2924 /* 2925 * Communicates with the dhcpagent to send a dhcp message of type `type'. 2926 * It returns the dhcp error in `dhcperror' if a non-null pointer is provided 2927 * in `dhcperror'. 2928 */ 2929 static ipadm_status_t 2930 i_ipadm_op_dhcp(ipadm_addrobj_t addr, dhcp_ipc_type_t type, int *dhcperror) 2931 { 2932 dhcp_ipc_request_t *request; 2933 dhcp_ipc_reply_t *reply = NULL; 2934 char ifname[LIFNAMSIZ]; 2935 int error; 2936 int dhcp_timeout; 2937 2938 /* Construct a message to the dhcpagent. */ 2939 bzero(&ifname, sizeof (ifname)); 2940 i_ipadm_addrobj2lifname(addr, ifname, sizeof (ifname)); 2941 if (addr->ipadm_primary) 2942 type |= DHCP_PRIMARY; 2943 request = dhcp_ipc_alloc_request(type, ifname, NULL, 0, DHCP_TYPE_NONE); 2944 if (request == NULL) 2945 return (IPADM_NO_MEMORY); 2946 2947 if (addr->ipadm_wait == IPADM_DHCP_WAIT_FOREVER) 2948 dhcp_timeout = DHCP_IPC_WAIT_FOREVER; 2949 else if (addr->ipadm_wait == IPADM_DHCP_WAIT_DEFAULT) 2950 dhcp_timeout = DHCP_IPC_WAIT_DEFAULT; 2951 else 2952 dhcp_timeout = addr->ipadm_wait; 2953 /* Send the message to dhcpagent. */ 2954 error = dhcp_ipc_make_request(request, &reply, dhcp_timeout); 2955 free(request); 2956 if (error == 0) { 2957 error = reply->return_code; 2958 free(reply); 2959 } 2960 if (error != 0) { 2961 if (dhcperror != NULL) 2962 *dhcperror = error; 2963 if (error != DHCP_IPC_E_TIMEOUT) 2964 return (IPADM_DHCP_IPC_ERROR); 2965 else if (dhcp_timeout != 0) 2966 return (IPADM_DHCP_IPC_TIMEOUT); 2967 } 2968 2969 return (IPADM_SUCCESS); 2970 } 2971 2972 /* 2973 * Returns the IP addresses of the specified interface in both the 2974 * active and the persistent configuration. If no 2975 * interface is specified, it returns all non-zero IP addresses 2976 * configured on all interfaces in active and persistent 2977 * configurations. 2978 * `addrinfo' will contain addresses that are 2979 * (1) in both active and persistent configuration (created persistently) 2980 * (2) only in active configuration (created temporarily) 2981 * (3) only in persistent configuration (disabled addresses) 2982 * 2983 * Address list that is returned by this function must be freed 2984 * using the ipadm_freeaddr_info() function. 2985 */ 2986 ipadm_status_t 2987 ipadm_addr_info(ipadm_handle_t iph, const char *ifname, 2988 ipadm_addr_info_t **addrinfo, uint32_t flags, int64_t lifc_flags) 2989 { 2990 ifspec_t ifsp; 2991 2992 if (addrinfo == NULL || iph == NULL) 2993 return (IPADM_INVALID_ARG); 2994 if (ifname != NULL && 2995 (!ifparse_ifspec(ifname, &ifsp) || ifsp.ifsp_lunvalid)) { 2996 return (IPADM_INVALID_ARG); 2997 } 2998 return (i_ipadm_get_all_addr_info(iph, ifname, addrinfo, 2999 flags, lifc_flags)); 3000 } 3001 3002 /* 3003 * Frees the structure allocated by ipadm_addr_info(). 3004 */ 3005 void 3006 ipadm_free_addr_info(ipadm_addr_info_t *ainfo) 3007 { 3008 freeifaddrs((struct ifaddrs *)ainfo); 3009 } 3010 3011 /* 3012 * Makes a door call to ipmgmtd to update its `aobjmap' with the address 3013 * object in `ipaddr'. This door call also updates the persistent DB to 3014 * remember address object to be recreated on next reboot or on an 3015 * ipadm_enable_addr()/ipadm_enable_if() call. 3016 */ 3017 ipadm_status_t 3018 i_ipadm_addr_persist(ipadm_handle_t iph, const ipadm_addrobj_t ipaddr, 3019 boolean_t default_prefixlen, uint32_t flags) 3020 { 3021 char *aname = ipaddr->ipadm_aobjname; 3022 nvlist_t *nvl; 3023 int err = 0; 3024 ipadm_status_t status; 3025 char pval[MAXPROPVALLEN]; 3026 uint_t pflags = 0; 3027 ipadm_prop_desc_t *pdp = NULL; 3028 3029 /* 3030 * Construct the nvl to send to the door. 3031 */ 3032 if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) 3033 return (IPADM_NO_MEMORY); 3034 if ((err = nvlist_add_string(nvl, IPADM_NVP_IFNAME, 3035 ipaddr->ipadm_ifname)) != 0 || 3036 (err = nvlist_add_string(nvl, IPADM_NVP_AOBJNAME, aname)) != 0 || 3037 (err = nvlist_add_int32(nvl, IPADM_NVP_LIFNUM, 3038 ipaddr->ipadm_lifnum)) != 0) { 3039 status = ipadm_errno2status(err); 3040 goto ret; 3041 } 3042 switch (ipaddr->ipadm_atype) { 3043 case IPADM_ADDR_STATIC: 3044 status = i_ipadm_add_ipaddr2nvl(nvl, ipaddr); 3045 if (status != IPADM_SUCCESS) 3046 goto ret; 3047 (void) snprintf(pval, sizeof (pval), "%d", 3048 ipaddr->ipadm_static_prefixlen); 3049 if (flags & IPADM_OPT_UP) 3050 err = nvlist_add_string(nvl, "up", "yes"); 3051 else 3052 err = nvlist_add_string(nvl, "up", "no"); 3053 status = ipadm_errno2status(err); 3054 break; 3055 case IPADM_ADDR_DHCP: 3056 status = i_ipadm_add_dhcp2nvl(nvl, ipaddr->ipadm_primary, 3057 ipaddr->ipadm_wait); 3058 break; 3059 case IPADM_ADDR_IPV6_ADDRCONF: 3060 status = i_ipadm_add_intfid2nvl(nvl, ipaddr); 3061 break; 3062 } 3063 if (status != IPADM_SUCCESS) 3064 goto ret; 3065 3066 if (iph->iph_flags & IPH_INIT) { 3067 /* 3068 * IPMGMT_INIT tells the ipmgmtd to set both IPMGMT_ACTIVE and 3069 * IPMGMT_PERSIST on the address object in its `aobjmap'. 3070 * For the callers ipadm_enable_if() and ipadm_enable_addr(), 3071 * IPADM_OPT_PERSIST is not set in their flags. They send 3072 * IPH_INIT in iph_flags, so that the address object will be 3073 * set as both IPMGMT_ACTIVE and IPMGMT_PERSIST. 3074 */ 3075 pflags |= IPMGMT_INIT; 3076 } else { 3077 if (flags & IPADM_OPT_ACTIVE) 3078 pflags |= IPMGMT_ACTIVE; 3079 if (flags & IPADM_OPT_PERSIST) 3080 pflags |= IPMGMT_PERSIST; 3081 } 3082 status = i_ipadm_addr_persist_nvl(iph, nvl, pflags); 3083 /* 3084 * prefixlen is stored in a separate line in the DB and not along 3085 * with the address itself, since it is also an address property and 3086 * all address properties are stored in separate lines. We need to 3087 * persist the prefixlen by calling the function that persists 3088 * address properties. 3089 */ 3090 if (status == IPADM_SUCCESS && !default_prefixlen && 3091 ipaddr->ipadm_atype == IPADM_ADDR_STATIC && 3092 (flags & IPADM_OPT_PERSIST)) { 3093 for (pdp = ipadm_addrprop_table; pdp->ipd_name != NULL; pdp++) { 3094 if (strcmp("prefixlen", pdp->ipd_name) == 0) 3095 break; 3096 } 3097 assert(pdp != NULL); 3098 status = i_ipadm_persist_propval(iph, pdp, pval, ipaddr, flags); 3099 } 3100 ret: 3101 nvlist_free(nvl); 3102 return (status); 3103 } 3104 3105 /* 3106 * Makes the door call to ipmgmtd to store the address object in the 3107 * nvlist `nvl'. 3108 */ 3109 static ipadm_status_t 3110 i_ipadm_addr_persist_nvl(ipadm_handle_t iph, nvlist_t *nvl, uint32_t flags) 3111 { 3112 char *buf = NULL, *nvlbuf = NULL; 3113 size_t nvlsize, bufsize; 3114 ipmgmt_setaddr_arg_t *sargp; 3115 int err; 3116 3117 err = nvlist_pack(nvl, &nvlbuf, &nvlsize, NV_ENCODE_NATIVE, 0); 3118 if (err != 0) 3119 return (ipadm_errno2status(err)); 3120 bufsize = sizeof (*sargp) + nvlsize; 3121 buf = calloc(1, bufsize); 3122 sargp = (void *)buf; 3123 sargp->ia_cmd = IPMGMT_CMD_SETADDR; 3124 sargp->ia_flags = flags; 3125 sargp->ia_nvlsize = nvlsize; 3126 (void) bcopy(nvlbuf, buf + sizeof (*sargp), nvlsize); 3127 err = ipadm_door_call(iph, buf, bufsize, NULL, 0, B_FALSE); 3128 free(buf); 3129 free(nvlbuf); 3130 return (ipadm_errno2status(err)); 3131 } 3132 3133 /* 3134 * Makes a door call to ipmgmtd to remove the address object in `ipaddr' 3135 * from its `aobjmap'. This door call also removes the address object and all 3136 * its properties from the persistent DB if IPADM_OPT_PERSIST is set in 3137 * `flags', so that the object will not be recreated on next reboot or on an 3138 * ipadm_enable_addr()/ipadm_enable_if() call. 3139 */ 3140 ipadm_status_t 3141 i_ipadm_delete_addrobj(ipadm_handle_t iph, const ipadm_addrobj_t ipaddr, 3142 uint32_t flags) 3143 { 3144 ipmgmt_addr_arg_t arg; 3145 int err; 3146 3147 arg.ia_cmd = IPMGMT_CMD_RESETADDR; 3148 arg.ia_flags = 0; 3149 if (flags & IPADM_OPT_ACTIVE) 3150 arg.ia_flags |= IPMGMT_ACTIVE; 3151 if (flags & IPADM_OPT_PERSIST) 3152 arg.ia_flags |= IPMGMT_PERSIST; 3153 (void) strlcpy(arg.ia_aobjname, ipaddr->ipadm_aobjname, 3154 sizeof (arg.ia_aobjname)); 3155 arg.ia_lnum = ipaddr->ipadm_lifnum; 3156 err = ipadm_door_call(iph, &arg, sizeof (arg), NULL, 0, B_FALSE); 3157 return (ipadm_errno2status(err)); 3158 } 3159 3160 /* 3161 * Checks if the caller is authorized for the up/down operation. 3162 * Retrieves the address object corresponding to `aobjname' from ipmgmtd 3163 * and retrieves the address flags for that object from kernel. 3164 * The arguments `ipaddr' and `ifflags' must be allocated by the caller. 3165 */ 3166 static ipadm_status_t 3167 i_ipadm_updown_common(ipadm_handle_t iph, const char *aobjname, 3168 ipadm_addrobj_t ipaddr, uint32_t ipadm_flags, uint64_t *ifflags) 3169 { 3170 ipadm_status_t status; 3171 char lifname[LIFNAMSIZ]; 3172 3173 /* check for solaris.network.interface.config authorization */ 3174 if (!ipadm_check_auth()) 3175 return (IPADM_EAUTH); 3176 3177 /* validate input */ 3178 if (aobjname == NULL || strlcpy(ipaddr->ipadm_aobjname, aobjname, 3179 IPADM_AOBJSIZ) >= IPADM_AOBJSIZ) { 3180 return (IPADM_INVALID_ARG); 3181 } 3182 3183 /* Retrieve the address object information. */ 3184 status = i_ipadm_get_addrobj(iph, ipaddr); 3185 if (status != IPADM_SUCCESS) 3186 return (status); 3187 3188 if (!(ipaddr->ipadm_flags & IPMGMT_ACTIVE)) 3189 return (IPADM_OP_DISABLE_OBJ); 3190 if ((ipadm_flags & IPADM_OPT_PERSIST) && 3191 !(ipaddr->ipadm_flags & IPMGMT_PERSIST)) 3192 return (IPADM_TEMPORARY_OBJ); 3193 if (ipaddr->ipadm_atype == IPADM_ADDR_IPV6_ADDRCONF || 3194 (ipaddr->ipadm_atype == IPADM_ADDR_DHCP && 3195 (ipadm_flags & IPADM_OPT_PERSIST))) 3196 return (IPADM_NOTSUP); 3197 3198 i_ipadm_addrobj2lifname(ipaddr, lifname, sizeof (lifname)); 3199 return (i_ipadm_get_flags(iph, lifname, ipaddr->ipadm_af, ifflags)); 3200 } 3201 3202 /* 3203 * Marks the address in the address object `aobjname' up. This operation is 3204 * not supported for an address object of type IPADM_ADDR_IPV6_ADDRCONF. 3205 * For an address object of type IPADM_ADDR_DHCP, this operation can 3206 * only be temporary and no updates will be made to the persistent DB. 3207 */ 3208 ipadm_status_t 3209 ipadm_up_addr(ipadm_handle_t iph, const char *aobjname, uint32_t ipadm_flags) 3210 { 3211 struct ipadm_addrobj_s ipaddr; 3212 ipadm_status_t status; 3213 uint64_t flags; 3214 char lifname[LIFNAMSIZ]; 3215 3216 status = i_ipadm_updown_common(iph, aobjname, &ipaddr, ipadm_flags, 3217 &flags); 3218 if (status != IPADM_SUCCESS) 3219 return (status); 3220 if (flags & IFF_UP) 3221 goto persist; 3222 /* 3223 * If the address is already a duplicate, then refresh-addr 3224 * should be used to mark it up. 3225 */ 3226 if (flags & IFF_DUPLICATE) 3227 return (IPADM_DAD_FOUND); 3228 3229 i_ipadm_addrobj2lifname(&ipaddr, lifname, sizeof (lifname)); 3230 status = i_ipadm_set_flags(iph, lifname, ipaddr.ipadm_af, IFF_UP, 0); 3231 if (status != IPADM_SUCCESS) 3232 return (status); 3233 3234 persist: 3235 /* Update persistent DB. */ 3236 if (ipadm_flags & IPADM_OPT_PERSIST) { 3237 status = i_ipadm_persist_propval(iph, &up_addrprop, 3238 "yes", &ipaddr, 0); 3239 } 3240 3241 return (status); 3242 } 3243 3244 /* 3245 * Marks the address in the address object `aobjname' down. This operation is 3246 * not supported for an address object of type IPADM_ADDR_IPV6_ADDRCONF. 3247 * For an address object of type IPADM_ADDR_DHCP, this operation can 3248 * only be temporary and no updates will be made to the persistent DB. 3249 */ 3250 ipadm_status_t 3251 ipadm_down_addr(ipadm_handle_t iph, const char *aobjname, uint32_t ipadm_flags) 3252 { 3253 struct ipadm_addrobj_s ipaddr; 3254 ipadm_status_t status; 3255 struct lifreq lifr; 3256 uint64_t flags; 3257 3258 status = i_ipadm_updown_common(iph, aobjname, &ipaddr, ipadm_flags, 3259 &flags); 3260 if (status != IPADM_SUCCESS) 3261 return (status); 3262 i_ipadm_addrobj2lifname(&ipaddr, lifr.lifr_name, 3263 sizeof (lifr.lifr_name)); 3264 if (flags & IFF_UP) { 3265 status = i_ipadm_set_flags(iph, lifr.lifr_name, 3266 ipaddr.ipadm_af, 0, IFF_UP); 3267 if (status != IPADM_SUCCESS) 3268 return (status); 3269 } else if (flags & IFF_DUPLICATE) { 3270 /* 3271 * Clear the IFF_DUPLICATE flag. 3272 */ 3273 if (ioctl(iph->iph_sock, SIOCGLIFADDR, &lifr) < 0) 3274 return (ipadm_errno2status(errno)); 3275 if (ioctl(iph->iph_sock, SIOCSLIFADDR, &lifr) < 0) 3276 return (ipadm_errno2status(errno)); 3277 } 3278 3279 /* Update persistent DB */ 3280 if (ipadm_flags & IPADM_OPT_PERSIST) { 3281 status = i_ipadm_persist_propval(iph, &up_addrprop, 3282 "no", &ipaddr, 0); 3283 } 3284 3285 return (status); 3286 } 3287 3288 /* 3289 * Refreshes the address in the address object `aobjname'. If the address object 3290 * is of type IPADM_ADDR_STATIC, DAD is re-initiated on the address. If 3291 * `ipadm_flags' has IPADM_OPT_INFORM set, a DHCP_INFORM message is sent to the 3292 * dhcpagent for this static address. If the address object is of type 3293 * IPADM_ADDR_DHCP, a DHCP_EXTEND message is sent to the dhcpagent. 3294 * If a dhcp address has not yet been acquired, a DHCP_START is sent to the 3295 * dhcpagent. This operation is not supported for an address object of 3296 * type IPADM_ADDR_IPV6_ADDRCONF. 3297 */ 3298 ipadm_status_t 3299 ipadm_refresh_addr(ipadm_handle_t iph, const char *aobjname, 3300 uint32_t ipadm_flags) 3301 { 3302 ipadm_status_t status = IPADM_SUCCESS; 3303 uint64_t flags; 3304 struct ipadm_addrobj_s ipaddr; 3305 sa_family_t af; 3306 char lifname[LIFNAMSIZ]; 3307 boolean_t inform = 3308 ((ipadm_flags & IPADM_OPT_INFORM) != 0); 3309 int dherr; 3310 3311 /* check for solaris.network.interface.config authorization */ 3312 if (!ipadm_check_auth()) 3313 return (IPADM_EAUTH); 3314 3315 /* validate input */ 3316 if (aobjname == NULL || strlcpy(ipaddr.ipadm_aobjname, aobjname, 3317 IPADM_AOBJSIZ) >= IPADM_AOBJSIZ) { 3318 return (IPADM_INVALID_ARG); 3319 } 3320 3321 /* Retrieve the address object information. */ 3322 status = i_ipadm_get_addrobj(iph, &ipaddr); 3323 if (status != IPADM_SUCCESS) 3324 return (status); 3325 3326 if (!(ipaddr.ipadm_flags & IPMGMT_ACTIVE)) 3327 return (IPADM_OP_DISABLE_OBJ); 3328 3329 if (i_ipadm_is_vni(ipaddr.ipadm_ifname)) 3330 return (IPADM_NOTSUP); 3331 if (inform && ipaddr.ipadm_atype != IPADM_ADDR_STATIC) 3332 return (IPADM_INVALID_ARG); 3333 af = ipaddr.ipadm_af; 3334 if (ipaddr.ipadm_atype == IPADM_ADDR_STATIC) { 3335 i_ipadm_addrobj2lifname(&ipaddr, lifname, sizeof (lifname)); 3336 status = i_ipadm_get_flags(iph, lifname, af, &flags); 3337 if (status != IPADM_SUCCESS) 3338 return (status); 3339 if (inform) { 3340 ipaddr.ipadm_wait = IPADM_DHCP_WAIT_DEFAULT; 3341 return (i_ipadm_op_dhcp(&ipaddr, DHCP_INFORM, NULL)); 3342 } 3343 if (!(flags & IFF_DUPLICATE)) 3344 return (IPADM_SUCCESS); 3345 status = i_ipadm_set_flags(iph, lifname, af, IFF_UP, 0); 3346 } else if (ipaddr.ipadm_atype == IPADM_ADDR_DHCP) { 3347 status = i_ipadm_op_dhcp(&ipaddr, DHCP_EXTEND, &dherr); 3348 /* 3349 * Restart the dhcp address negotiation with server if no 3350 * address has been acquired yet. 3351 */ 3352 if (status != IPADM_SUCCESS && dherr == DHCP_IPC_E_OUTSTATE) { 3353 ipaddr.ipadm_wait = IPADM_DHCP_WAIT_DEFAULT; 3354 status = i_ipadm_op_dhcp(&ipaddr, DHCP_START, NULL); 3355 } 3356 } else { 3357 status = IPADM_NOTSUP; 3358 } 3359 return (status); 3360 } 3361 3362 /* 3363 * This is called from ipadm_create_addr() to validate the address parameters. 3364 * It does the following steps: 3365 * 1. Validates the interface name. 3366 * 2. Verifies that the interface is not an IPMP meta-interface or an 3367 * underlying interface. 3368 * 3. In case of a persistent operation, verifies that the interface 3369 * is persistent. Returns error if interface is not enabled but 3370 * is in persistent config. 3371 * 4. Verifies that the destination address is not set or the address type is 3372 * not DHCP or ADDRCONF when the interface is a loopback interface. 3373 * 5. Verifies that the address type is not DHCP or ADDRCONF when the interface 3374 * has IFF_VRRP interface flag set. 3375 */ 3376 static ipadm_status_t 3377 i_ipadm_validate_create_addr(ipadm_handle_t iph, ipadm_addrobj_t ipaddr, 3378 uint32_t flags) 3379 { 3380 sa_family_t af; 3381 sa_family_t other_af; 3382 char *ifname; 3383 ipadm_status_t status; 3384 boolean_t legacy = (iph->iph_flags & IPH_LEGACY); 3385 boolean_t islo, isvni; 3386 uint64_t ifflags = 0; 3387 boolean_t p_exists; 3388 boolean_t af_exists, other_af_exists, a_exists; 3389 3390 if (ipaddr == NULL || flags == 0 || flags == IPADM_OPT_PERSIST || 3391 (flags & ~(IPADM_COMMON_OPT_MASK|IPADM_OPT_UP|IPADM_OPT_V46))) { 3392 return (IPADM_INVALID_ARG); 3393 } 3394 3395 if (ipaddr->ipadm_af == AF_UNSPEC) 3396 return (IPADM_BAD_ADDR); 3397 3398 if (!legacy && ipaddr->ipadm_lifnum != 0) 3399 return (IPADM_INVALID_ARG); 3400 3401 if (legacy && ipaddr->ipadm_atype != IPADM_ADDR_STATIC) 3402 return (IPADM_NOTSUP); 3403 3404 ifname = ipaddr->ipadm_ifname; 3405 3406 if (i_ipadm_is_ipmp(iph, ifname) || i_ipadm_is_under_ipmp(iph, ifname)) 3407 return (IPADM_NOTSUP); 3408 3409 af = ipaddr->ipadm_af; 3410 af_exists = ipadm_if_enabled(iph, ifname, af); 3411 /* 3412 * For legacy case, interfaces are not implicitly plumbed. We need to 3413 * check if the interface exists in the active configuration. 3414 */ 3415 if (legacy && !af_exists) 3416 return (IPADM_ENXIO); 3417 3418 other_af = (af == AF_INET ? AF_INET6 : AF_INET); 3419 other_af_exists = ipadm_if_enabled(iph, ifname, other_af); 3420 /* 3421 * Check if one of the v4 or the v6 interfaces exists in the 3422 * active configuration. An interface is considered disabled only 3423 * if both v4 and v6 are not active. 3424 */ 3425 a_exists = (af_exists || other_af_exists); 3426 3427 /* Check if interface exists in the persistent configuration. */ 3428 status = i_ipadm_if_pexists(iph, ifname, af, &p_exists); 3429 if (status != IPADM_SUCCESS) 3430 return (status); 3431 if (!a_exists && p_exists) 3432 return (IPADM_OP_DISABLE_OBJ); 3433 if ((flags & IPADM_OPT_PERSIST) && a_exists && !p_exists) { 3434 /* 3435 * If address has to be created persistently, 3436 * and the interface does not exist in the persistent 3437 * store but in active config, fail. 3438 */ 3439 return (IPADM_TEMPORARY_OBJ); 3440 } 3441 if (af_exists) { 3442 status = i_ipadm_get_flags(iph, ifname, af, &ifflags); 3443 if (status != IPADM_SUCCESS) 3444 return (status); 3445 } 3446 3447 /* Perform validation steps (4) and (5) */ 3448 islo = i_ipadm_is_loopback(ifname); 3449 isvni = i_ipadm_is_vni(ifname); 3450 switch (ipaddr->ipadm_atype) { 3451 case IPADM_ADDR_STATIC: 3452 if ((islo || isvni) && ipaddr->ipadm_static_dname[0] != '\0') 3453 return (IPADM_INVALID_ARG); 3454 /* Check for a valid src address */ 3455 if (!legacy && sockaddrunspec(&ipaddr->ipadm_static_addr)) 3456 return (IPADM_BAD_ADDR); 3457 break; 3458 case IPADM_ADDR_DHCP: 3459 if (islo || (ifflags & IFF_VRRP)) 3460 return (IPADM_NOTSUP); 3461 break; 3462 case IPADM_ADDR_IPV6_ADDRCONF: 3463 if (islo || (ifflags & IFF_VRRP) || 3464 i_ipadm_is_6to4(iph, ifname)) { 3465 return (IPADM_NOTSUP); 3466 } 3467 break; 3468 default: 3469 return (IPADM_INVALID_ARG); 3470 } 3471 3472 return (IPADM_SUCCESS); 3473 } 3474 3475 ipadm_status_t 3476 i_ipadm_merge_prefixlen_from_nvl(nvlist_t *invl, nvlist_t *onvl, 3477 const char *aobjname) 3478 { 3479 nvpair_t *nvp, *prefixnvp; 3480 nvlist_t *tnvl; 3481 char *aname; 3482 int err; 3483 3484 for (nvp = nvlist_next_nvpair(invl, NULL); nvp != NULL; 3485 nvp = nvlist_next_nvpair(invl, nvp)) { 3486 if (nvpair_value_nvlist(nvp, &tnvl) == 0 && 3487 nvlist_exists(tnvl, IPADM_NVP_PREFIXLEN) && 3488 nvlist_lookup_string(tnvl, IPADM_NVP_AOBJNAME, 3489 &aname) == 0 && strcmp(aname, aobjname) == 0) { 3490 /* prefixlen exists for given address object */ 3491 (void) nvlist_lookup_nvpair(tnvl, IPADM_NVP_PREFIXLEN, 3492 &prefixnvp); 3493 err = nvlist_add_nvpair(onvl, prefixnvp); 3494 if (err == 0) { 3495 err = nvlist_remove(invl, nvpair_name(nvp), 3496 nvpair_type(nvp)); 3497 } 3498 return (ipadm_errno2status(err)); 3499 } 3500 } 3501 return (IPADM_SUCCESS); 3502 } 3503 3504 /* 3505 * Re-enables the address object `aobjname' based on the saved 3506 * configuration for `aobjname'. 3507 */ 3508 ipadm_status_t 3509 ipadm_enable_addr(ipadm_handle_t iph, const char *aobjname, uint32_t flags) 3510 { 3511 nvlist_t *addrnvl, *nvl; 3512 nvpair_t *nvp; 3513 ipadm_status_t status; 3514 struct ipadm_addrobj_s ipaddr; 3515 3516 /* check for solaris.network.interface.config authorization */ 3517 if (!ipadm_check_auth()) 3518 return (IPADM_EAUTH); 3519 3520 /* validate input */ 3521 if (flags & IPADM_OPT_PERSIST) 3522 return (IPADM_NOTSUP); 3523 if (aobjname == NULL || strlcpy(ipaddr.ipadm_aobjname, aobjname, 3524 IPADM_AOBJSIZ) >= IPADM_AOBJSIZ) { 3525 return (IPADM_INVALID_ARG); 3526 } 3527 3528 /* Retrieve the address object information. */ 3529 status = i_ipadm_get_addrobj(iph, &ipaddr); 3530 if (status != IPADM_SUCCESS) 3531 return (status); 3532 if (ipaddr.ipadm_flags & IPMGMT_ACTIVE) 3533 return (IPADM_ADDROBJ_EXISTS); 3534 3535 status = i_ipadm_get_db_addr(iph, NULL, aobjname, &addrnvl); 3536 if (status != IPADM_SUCCESS) 3537 return (status); 3538 3539 assert(addrnvl != NULL); 3540 3541 for (nvp = nvlist_next_nvpair(addrnvl, NULL); nvp != NULL; 3542 nvp = nvlist_next_nvpair(addrnvl, nvp)) { 3543 if (nvpair_value_nvlist(nvp, &nvl) != 0) 3544 continue; 3545 3546 if (nvlist_exists(nvl, IPADM_NVP_IPV4ADDR) || 3547 nvlist_exists(nvl, IPADM_NVP_IPV6ADDR)) { 3548 status = i_ipadm_merge_prefixlen_from_nvl(addrnvl, nvl, 3549 aobjname); 3550 if (status != IPADM_SUCCESS) 3551 continue; 3552 } 3553 iph->iph_flags |= IPH_INIT; 3554 status = i_ipadm_init_addrobj(iph, nvl); 3555 iph->iph_flags &= ~IPH_INIT; 3556 if (status != IPADM_SUCCESS) 3557 break; 3558 } 3559 3560 return (status); 3561 } 3562 3563 /* 3564 * Disables the address object in `aobjname' from the active configuration. 3565 * Error code return values follow the model in ipadm_delete_addr(). 3566 */ 3567 ipadm_status_t 3568 ipadm_disable_addr(ipadm_handle_t iph, const char *aobjname, uint32_t flags) 3569 { 3570 /* validate input */ 3571 if (flags & IPADM_OPT_PERSIST) 3572 return (IPADM_NOTSUP); 3573 3574 return (ipadm_delete_addr(iph, aobjname, IPADM_OPT_ACTIVE)); 3575 } 3576