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