Print this page
7388 Support DHCP Client FQDN. Allow IAID/DUID for all v4.
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_door.c
+++ new/usr/src/cmd/cmd-inet/lib/ipmgmtd/ipmgmt_door.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 /*
23 23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 + * Copyright (c) 2016, Chris Fraire <cfraire@me.com>.
24 25 */
25 26
26 27 /*
27 28 * Main door handler functions used by ipmgmtd to process the different door
28 29 * call requests, issued by the library libipadm.so.
29 30 */
30 31
31 32 #include <alloca.h>
32 33 #include <pwd.h>
33 34 #include <auth_attr.h>
34 35 #include <secdb.h>
35 36 #include <stdlib.h>
36 37 #include <stdio.h>
37 38 #include <string.h>
38 39 #include <strings.h>
39 40 #include <errno.h>
40 41 #include <assert.h>
41 42 #include <libnvpair.h>
42 43 #include "ipmgmt_impl.h"
43 44
44 45 /* Handler declaration for each door command */
45 46 typedef void ipmgmt_door_handler_t(void *argp);
46 47
47 48 static ipmgmt_door_handler_t ipmgmt_getaddr_handler,
48 49 ipmgmt_getprop_handler,
49 50 ipmgmt_getif_handler,
50 51 ipmgmt_initif_handler,
51 52 ipmgmt_aobjop_handler,
52 53 ipmgmt_resetaddr_handler,
53 54 ipmgmt_setif_handler,
54 55 ipmgmt_resetif_handler,
55 56 ipmgmt_resetprop_handler,
56 57 ipmgmt_setaddr_handler,
57 58 ipmgmt_setprop_handler;
58 59
59 60 typedef struct ipmgmt_door_info_s {
60 61 uint_t idi_cmd;
61 62 boolean_t idi_set;
62 63 ipmgmt_door_handler_t *idi_handler;
63 64 } ipmgmt_door_info_t;
64 65
65 66 /* maps door commands to door handler functions */
66 67 static ipmgmt_door_info_t i_ipmgmt_door_info_tbl[] = {
67 68 { IPMGMT_CMD_SETPROP, B_TRUE, ipmgmt_setprop_handler },
68 69 { IPMGMT_CMD_SETIF, B_TRUE, ipmgmt_setif_handler },
69 70 { IPMGMT_CMD_SETADDR, B_TRUE, ipmgmt_setaddr_handler },
70 71 { IPMGMT_CMD_GETPROP, B_FALSE, ipmgmt_getprop_handler },
71 72 { IPMGMT_CMD_GETIF, B_FALSE, ipmgmt_getif_handler },
72 73 { IPMGMT_CMD_GETADDR, B_FALSE, ipmgmt_getaddr_handler },
73 74 { IPMGMT_CMD_RESETIF, B_TRUE, ipmgmt_resetif_handler },
74 75 { IPMGMT_CMD_RESETADDR, B_TRUE, ipmgmt_resetaddr_handler },
75 76 { IPMGMT_CMD_RESETPROP, B_TRUE, ipmgmt_resetprop_handler },
76 77 { IPMGMT_CMD_INITIF, B_TRUE, ipmgmt_initif_handler },
77 78 { IPMGMT_CMD_ADDROBJ_LOOKUPADD, B_TRUE, ipmgmt_aobjop_handler },
78 79 { IPMGMT_CMD_ADDROBJ_SETLIFNUM, B_TRUE, ipmgmt_aobjop_handler },
79 80 { IPMGMT_CMD_ADDROBJ_ADD, B_TRUE, ipmgmt_aobjop_handler },
80 81 { IPMGMT_CMD_AOBJNAME2ADDROBJ, B_FALSE, ipmgmt_aobjop_handler },
81 82 { IPMGMT_CMD_LIF2ADDROBJ, B_FALSE, ipmgmt_aobjop_handler },
82 83 { 0, 0, NULL },
83 84 };
84 85
85 86 /*
86 87 * The main server procedure function that gets invoked for any of the incoming
87 88 * door commands. Inside this function we identify the incoming command and
88 89 * invoke the right door handler function.
89 90 */
90 91 /* ARGSUSED */
91 92 void
92 93 ipmgmt_handler(void *cookie, char *argp, size_t argsz, door_desc_t *dp,
93 94 uint_t n_desc)
94 95 {
95 96 ipmgmt_door_info_t *infop = NULL;
96 97 ipmgmt_retval_t retval;
97 98 int i;
98 99 uint_t err;
99 100 ucred_t *cred = NULL;
100 101
101 102 for (i = 0; i_ipmgmt_door_info_tbl[i].idi_cmd != 0; i++) {
102 103 if (i_ipmgmt_door_info_tbl[i].idi_cmd ==
103 104 ((ipmgmt_arg_t *)(void *)argp)->ia_cmd) {
104 105 infop = &i_ipmgmt_door_info_tbl[i];
105 106 break;
106 107 }
107 108 }
108 109
109 110 if (infop == NULL) {
110 111 ipmgmt_log(LOG_ERR, "Invalid door command specified");
111 112 err = EINVAL;
112 113 goto fail;
113 114 }
114 115
115 116 /* check for solaris.network.interface.config authorization */
116 117 if (infop->idi_set) {
117 118 uid_t uid;
118 119 struct passwd pwd;
119 120 char buf[1024];
120 121
121 122 if (door_ucred(&cred) != 0) {
122 123 err = errno;
123 124 ipmgmt_log(LOG_ERR, "Could not get user credentials.");
124 125 goto fail;
125 126 }
126 127 uid = ucred_getruid(cred);
127 128 if ((int)uid < 0) {
128 129 err = errno;
129 130 ipmgmt_log(LOG_ERR, "Could not get user id.");
130 131 goto fail;
131 132 }
132 133 if (getpwuid_r(uid, &pwd, buf, sizeof (buf)) ==
133 134 NULL) {
134 135 err = errno;
135 136 ipmgmt_log(LOG_ERR, "Could not get password entry.");
136 137 goto fail;
137 138 }
138 139 if (chkauthattr(NETWORK_INTERFACE_CONFIG_AUTH,
139 140 pwd.pw_name) != 1) {
140 141 err = EPERM;
141 142 ipmgmt_log(LOG_ERR, "Not authorized for operation.");
142 143 goto fail;
143 144 }
144 145 ucred_free(cred);
145 146 }
146 147
147 148 /* individual handlers take care of calling door_return */
148 149 infop->idi_handler((void *)argp);
149 150 return;
150 151 fail:
151 152 ucred_free(cred);
152 153 retval.ir_err = err;
153 154 (void) door_return((char *)&retval, sizeof (retval), NULL, 0);
154 155 }
155 156
156 157 /*
157 158 * Handles the door command IPMGMT_CMD_GETPROP. It retrieves the persisted
158 159 * property value for the given property.
159 160 */
160 161 static void
161 162 ipmgmt_getprop_handler(void *argp)
162 163 {
163 164 ipmgmt_prop_arg_t *pargp = argp;
164 165 ipmgmt_getprop_rval_t rval, *rvalp = &rval;
165 166
166 167 assert(pargp->ia_cmd == IPMGMT_CMD_GETPROP);
167 168
168 169 rvalp->ir_err = ipmgmt_db_walk(ipmgmt_db_getprop, pargp, IPADM_DB_READ);
169 170 if (rvalp->ir_err == 0)
170 171 (void) strlcpy(rvalp->ir_pval, pargp->ia_pval,
171 172 sizeof (rvalp->ir_pval));
172 173 (void) door_return((char *)rvalp, sizeof (*rvalp), NULL, 0);
173 174 }
174 175
175 176 /*
176 177 * Handles the door command IPMGMT_CMD_SETPROP. It persists the property value
177 178 * for the given property in the DB.
178 179 */
179 180 static void
180 181 ipmgmt_setprop_handler(void *argp)
181 182 {
182 183 ipmgmt_prop_arg_t *pargp = argp;
183 184 ipmgmt_retval_t rval;
184 185 ipadm_dbwrite_cbarg_t cb;
185 186 nvlist_t *nvl = NULL;
186 187 int err;
187 188
188 189 assert(pargp->ia_cmd == IPMGMT_CMD_SETPROP);
189 190
190 191 if ((err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) != 0)
191 192 goto fail;
192 193 if (pargp->ia_module[0] != '\0' &&
193 194 (err = nvlist_add_string(nvl, IPADM_NVP_PROTONAME,
194 195 pargp->ia_module)) != 0) {
195 196 goto fail;
196 197 }
197 198 if (pargp->ia_ifname[0] != '\0' &&
198 199 (err = nvlist_add_string(nvl, IPADM_NVP_IFNAME,
199 200 pargp->ia_ifname)) != 0)
200 201 goto fail;
201 202 if (pargp->ia_aobjname[0] != '\0' &&
202 203 (err = nvlist_add_string(nvl, IPADM_NVP_AOBJNAME,
203 204 pargp->ia_aobjname)) != 0)
204 205 goto fail;
205 206 if ((err = nvlist_add_string(nvl, pargp->ia_pname,
206 207 pargp->ia_pval)) != 0)
207 208 goto fail;
208 209
209 210 cb.dbw_nvl = nvl;
210 211 cb.dbw_flags = pargp->ia_flags;
211 212 err = ipmgmt_db_walk(ipmgmt_db_update, &cb, IPADM_DB_WRITE);
212 213 fail:
213 214 nvlist_free(nvl);
214 215 rval.ir_err = err;
215 216 (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
216 217 }
217 218
|
↓ open down ↓ |
184 lines elided |
↑ open up ↑ |
218 219 /*
219 220 * Helper function for ipmgmt_setaddr_handler().
220 221 * It converts the nvlist_t, `nvl', to aobjmap node `nodep'.
221 222 */
222 223 static int
223 224 i_ipmgmt_nvl2aobjnode(nvlist_t *nvl, ipmgmt_aobjmap_t *nodep)
224 225 {
225 226 char *aobjname = NULL, *ifname = NULL;
226 227 int32_t lnum;
227 228 nvlist_t *nvladdr;
228 - struct sockaddr_storage addr;
229 - uint_t n;
230 229 sa_family_t af = AF_UNSPEC;
231 230 ipadm_addr_type_t addrtype = IPADM_ADDR_NONE;
232 231 int err = 0;
233 232
234 233 /*
235 234 * Retrieve all the information needed to build '*nodep' from
236 235 * nvlist_t nvl.
237 236 */
238 237 if ((err = nvlist_lookup_string(nvl, IPADM_NVP_AOBJNAME,
239 238 &aobjname)) != 0 ||
240 239 (err = nvlist_lookup_string(nvl, IPADM_NVP_IFNAME, &ifname)) != 0 ||
241 240 (err = nvlist_lookup_int32(nvl, IPADM_NVP_LIFNUM, &lnum)) != 0) {
242 241 return (err);
243 242 }
244 243 if (nvlist_exists(nvl, IPADM_NVP_IPV4ADDR)) {
245 244 af = AF_INET;
246 245 addrtype = IPADM_ADDR_STATIC;
247 - } else if (nvlist_exists(nvl, IPADM_NVP_DHCP)) {
246 + } else if (nvlist_lookup_nvlist(nvl, IPADM_NVP_DHCP, &nvladdr) == 0) {
247 + char *reqhost;
248 + boolean_t primary;
249 +
248 250 af = AF_INET;
249 251 addrtype = IPADM_ADDR_DHCP;
252 +
253 + if (nvlist_lookup_boolean_value(nvladdr, IPADM_NVP_PRIMARY,
254 + &primary) != 0)
255 + return (EINVAL);
256 + nodep->ipmgmt_am_primary = primary;
257 +
258 + /*
259 + * ipmgmt_am_reqhost comes through in `nvl' for purposes of updating
260 + * the cached representation, but it is persisted as a stand-alone
261 + * DB line; so remove it after copying it.
262 + */
263 + if (!nvlist_exists(nvl, IPADM_NVP_REQHOST)) {
264 + *nodep->ipmgmt_am_reqhost = '\0';
265 + } else {
266 + if ((err = nvlist_lookup_string(nvl, IPADM_NVP_REQHOST,
267 + &reqhost)) != 0)
268 + return (err);
269 +
270 + (void) strlcpy(nodep->ipmgmt_am_reqhost, reqhost,
271 + sizeof (nodep->ipmgmt_am_reqhost));
272 + (void) nvlist_remove(nvl, IPADM_NVP_REQHOST, DATA_TYPE_STRING);
273 + }
250 274 } else if (nvlist_exists(nvl, IPADM_NVP_IPV6ADDR)) {
251 275 af = AF_INET6;
252 276 addrtype = IPADM_ADDR_STATIC;
253 277 } else if (nvlist_lookup_nvlist(nvl, IPADM_NVP_INTFID, &nvladdr) == 0) {
254 - struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&addr;
278 + struct sockaddr_in6 sin6 = {0};
255 279 uint8_t *addr6;
256 280 uint32_t plen;
281 + uint_t n;
257 282
258 283 af = AF_INET6;
259 284 addrtype = IPADM_ADDR_IPV6_ADDRCONF;
260 285 if (nvlist_lookup_uint32(nvladdr, IPADM_NVP_PREFIXLEN,
261 286 &plen) != 0)
262 287 return (EINVAL);
263 288 if (plen != 0) {
264 289 if (nvlist_lookup_uint8_array(nvladdr,
265 290 IPADM_NVP_IPNUMADDR, &addr6, &n) != 0)
266 291 return (EINVAL);
267 - bcopy(addr6, &sin6->sin6_addr, n);
268 - } else {
269 - bzero(&sin6->sin6_addr, sizeof (sin6->sin6_addr));
292 + bcopy(addr6, &sin6.sin6_addr, n);
270 293 }
294 +
295 + nodep->ipmgmt_am_linklocal = B_TRUE;
296 + nodep->ipmgmt_am_ifid = sin6;
271 297 }
272 298
273 299 /*
274 - * populate the `*nodep' with retrieved values.
300 + * populate the non-addrtype-specific `*nodep' with retrieved values.
275 301 */
276 302 (void) strlcpy(nodep->am_ifname, ifname, sizeof (nodep->am_ifname));
277 303 (void) strlcpy(nodep->am_aobjname, aobjname,
278 304 sizeof (nodep->am_aobjname));
279 305 nodep->am_lnum = lnum;
280 306 nodep->am_family = af;
281 307 nodep->am_atype = addrtype;
282 - if (addrtype == IPADM_ADDR_IPV6_ADDRCONF) {
283 - nodep->am_linklocal = B_TRUE;
284 - nodep->am_ifid = addr;
285 - }
286 308 nodep->am_next = NULL;
287 309
288 310 /*
289 311 * Do not store logical interface number in persistent store as it
290 312 * takes different value on reboot. So remove it from `nvl'.
291 313 */
292 314 if (nvlist_exists(nvl, IPADM_NVP_LIFNUM))
293 315 (void) nvlist_remove(nvl, IPADM_NVP_LIFNUM, DATA_TYPE_INT32);
294 316
295 317 return (0);
296 318 }
297 319
298 320 /*
299 321 * Handles the door command IPMGMT_CMD_SETADDR. It adds a new address object
300 - * node to the list `aobjmap' and then persists the address information in the
301 - * DB.
322 + * node to the list `aobjmap' and optionally persists the address
323 + * information in the DB.
302 324 */
303 325 static void
304 326 ipmgmt_setaddr_handler(void *argp)
305 327 {
306 328 ipmgmt_setaddr_arg_t *sargp = argp;
307 329 ipmgmt_retval_t rval;
308 - ipmgmt_aobjmap_t node;
330 + ipmgmt_aobjmap_t node = {0};
309 331 nvlist_t *nvl = NULL;
310 332 char *nvlbuf;
311 333 size_t nvlsize = sargp->ia_nvlsize;
312 334 uint32_t flags = sargp->ia_flags;
313 335 int err = 0;
314 336
315 337 nvlbuf = (char *)argp + sizeof (ipmgmt_setaddr_arg_t);
316 338 if ((err = nvlist_unpack(nvlbuf, nvlsize, &nvl, NV_ENCODE_NATIVE)) != 0)
317 339 goto ret;
318 340 if (flags & (IPMGMT_ACTIVE|IPMGMT_INIT)) {
319 341 if ((err = i_ipmgmt_nvl2aobjnode(nvl, &node)) != 0)
320 342 goto ret;
321 343 if (flags & IPMGMT_INIT)
322 344 node.am_flags = (IPMGMT_ACTIVE|IPMGMT_PERSIST);
323 345 else
324 - node.am_flags = flags;
346 + node.am_flags = flags & ~IPMGMT_PROPS_ONLY;
325 347 if ((err = ipmgmt_aobjmap_op(&node, ADDROBJ_ADD)) != 0)
326 348 goto ret;
327 349 }
328 - if (flags & IPMGMT_PERSIST) {
350 + if ((flags & IPMGMT_PERSIST) && !(flags & IPMGMT_PROPS_ONLY)) {
329 351 ipadm_dbwrite_cbarg_t cb;
330 352
331 353 cb.dbw_nvl = nvl;
332 354 cb.dbw_flags = 0;
333 355 err = ipmgmt_db_walk(ipmgmt_db_add, &cb, IPADM_DB_WRITE);
334 356 }
335 357 ret:
336 358 nvlist_free(nvl);
337 359 rval.ir_err = err;
338 360 (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
339 361 }
340 362
341 363 /*
342 - * Handles the door commands that modify the `aobjmap' structure.
364 + * Handles the door commands that read or modify the `aobjmap' structure.
343 365 *
344 366 * IPMGMT_CMD_ADDROBJ_LOOKUPADD - places a stub address object in `aobjmap'
345 367 * after ensuring that the namespace is not taken. If required, also
346 368 * generates an `aobjname' for address object for the library to use.
347 369 * IPMGMT_CMD_ADDROBJ_ADD - add/update address object in `aobjmap'
348 370 * IPMGMT_CMD_LIF2ADDROBJ - given a logical interface, return address object
349 371 * associated with that logical interface.
350 372 * IPMGMT_CMD_AOBJNAME2ADDROBJ - given an address object name return logical
351 373 * interface associated with that address object.
352 374 */
353 375 static void
354 376 ipmgmt_aobjop_handler(void *argp)
355 377 {
356 378 ipmgmt_aobjop_arg_t *largp = argp;
357 379 ipmgmt_retval_t rval;
358 380 ipmgmt_aobjop_rval_t aobjrval;
359 381 void *rvalp;
360 382 size_t rsize;
361 383 ipmgmt_aobjmap_t node;
362 384 int err = 0;
363 385 char *ifname = largp->ia_ifname;
364 386 char *aobjname = largp->ia_aobjname;
365 387 int32_t lnum = largp->ia_lnum;
366 388 sa_family_t af = largp->ia_family;
367 389 ipadm_addr_type_t atype = largp->ia_atype;
368 390 ipmgmt_aobjmap_t *head;
369 391
370 392 switch (largp->ia_cmd) {
371 393 case IPMGMT_CMD_ADDROBJ_LOOKUPADD:
372 394 rsize = sizeof (ipmgmt_aobjop_rval_t);
373 395 rvalp = &aobjrval;
374 396 bzero(&node, sizeof (node));
375 397 (void) strlcpy(node.am_aobjname, aobjname,
376 398 sizeof (node.am_aobjname));
377 399 (void) strlcpy(node.am_ifname, ifname,
378 400 sizeof (node.am_ifname));
379 401 node.am_family = af;
380 402 node.am_atype = atype;
381 403 /* no logical number is associated with this addrobj yet */
382 404 node.am_lnum = -1;
383 405 /* The address object is not persisted yet. */
384 406 node.am_flags = IPMGMT_ACTIVE;
385 407 err = ipmgmt_aobjmap_op(&node, ADDROBJ_LOOKUPADD);
386 408 if (err == 0) {
387 409 (void) strlcpy(aobjrval.ir_aobjname, node.am_aobjname,
388 410 sizeof (aobjrval.ir_aobjname));
389 411 }
390 412 break;
391 413 case IPMGMT_CMD_ADDROBJ_SETLIFNUM:
392 414 rsize = sizeof (ipmgmt_retval_t);
393 415 rvalp = &rval;
394 416 bzero(&node, sizeof (node));
395 417 (void) strlcpy(node.am_aobjname, aobjname,
396 418 sizeof (node.am_aobjname));
397 419 (void) strlcpy(node.am_ifname, ifname,
398 420 sizeof (node.am_ifname));
399 421 node.am_family = af;
400 422 node.am_lnum = lnum;
401 423 err = ipmgmt_aobjmap_op(&node, ADDROBJ_SETLIFNUM);
402 424 break;
403 425 case IPMGMT_CMD_ADDROBJ_ADD:
404 426 rsize = sizeof (ipmgmt_retval_t);
405 427 rvalp = &rval;
406 428 if (aobjname[0] == '\0' || ifname[0] == '\0' || lnum == -1 ||
407 429 af == AF_UNSPEC) {
408 430 err = EINVAL;
409 431 break;
410 432 }
411 433 bzero(&node, sizeof (node));
412 434 (void) strlcpy(node.am_aobjname, aobjname,
413 435 sizeof (node.am_aobjname));
414 436 (void) strlcpy(node.am_ifname, ifname,
415 437 sizeof (node.am_ifname));
416 438 node.am_atype = atype;
417 439 node.am_lnum = lnum;
418 440 node.am_family = af;
419 441 /* The address object is not persisted. */
420 442 node.am_flags = IPMGMT_ACTIVE;
421 443 err = ipmgmt_aobjmap_op(&node, ADDROBJ_ADD);
422 444 break;
423 445 case IPMGMT_CMD_AOBJNAME2ADDROBJ:
424 446 rsize = sizeof (ipmgmt_aobjop_rval_t);
425 447 rvalp = &aobjrval;
426 448 bzero(&aobjrval, sizeof (aobjrval));
427 449 if (aobjname[0] == '\0') {
428 450 err = EINVAL;
429 451 break;
430 452 }
431 453 (void) pthread_rwlock_rdlock(&aobjmap.aobjmap_rwlock);
432 454 head = aobjmap.aobjmap_head;
433 455 for (; head; head = head->am_next) {
|
↓ open down ↓ |
81 lines elided |
↑ open up ↑ |
434 456 if (strcmp(head->am_aobjname, aobjname) != 0)
435 457 continue;
436 458 /*
437 459 * For an auto-configured interface, return
438 460 * the lifnum that has the link-local on it.
439 461 * Other logical interfaces were created for
440 462 * prefixes and dhcpv6 addresses and do not
441 463 * have am_ifid set.
442 464 */
443 465 if (head->am_atype != IPADM_ADDR_IPV6_ADDRCONF ||
444 - head->am_linklocal) {
466 + head->ipmgmt_am_linklocal) {
445 467 break;
446 468 }
447 469 }
448 470 if (head == NULL) {
449 471 err = ENOENT;
450 472 (void) pthread_rwlock_unlock(&aobjmap.aobjmap_rwlock);
451 473 break;
452 474 }
453 475 (void) strlcpy(aobjrval.ir_ifname, head->am_ifname,
454 476 sizeof (aobjrval.ir_ifname));
455 477 aobjrval.ir_lnum = head->am_lnum;
456 478 aobjrval.ir_family = head->am_family;
457 479 aobjrval.ir_flags = head->am_flags;
458 480 aobjrval.ir_atype = head->am_atype;
459 - if (head->am_atype == IPADM_ADDR_IPV6_ADDRCONF &&
460 - head->am_linklocal)
461 - aobjrval.ir_ifid = head->am_ifid;
481 + (void) memcpy(&aobjrval.ir_atype_cache, &head->am_atype_cache,
482 + sizeof (aobjrval.ir_atype_cache));
462 483 (void) pthread_rwlock_unlock(&aobjmap.aobjmap_rwlock);
463 484 break;
464 485 case IPMGMT_CMD_LIF2ADDROBJ:
465 486 rsize = sizeof (ipmgmt_aobjop_rval_t);
466 487 rvalp = &aobjrval;
467 488 bzero(&aobjrval, sizeof (aobjrval));
468 489 if (ifname[0] == '\0') {
469 490 err = EINVAL;
470 491 break;
471 492 }
472 493 (void) pthread_rwlock_rdlock(&aobjmap.aobjmap_rwlock);
473 494 head = aobjmap.aobjmap_head;
474 495 for (; head; head = head->am_next) {
475 496 if (strcmp(head->am_ifname, ifname) == 0 &&
476 497 head->am_lnum == lnum &&
477 498 head->am_family == af) {
478 499 break;
479 500 }
|
↓ open down ↓ |
8 lines elided |
↑ open up ↑ |
480 501 }
481 502 if (head == NULL) {
482 503 err = ENOENT;
483 504 (void) pthread_rwlock_unlock(&aobjmap.aobjmap_rwlock);
484 505 break;
485 506 }
486 507 (void) strlcpy(aobjrval.ir_aobjname, head->am_aobjname,
487 508 sizeof (aobjrval.ir_aobjname));
488 509 aobjrval.ir_atype = head->am_atype;
489 510 aobjrval.ir_flags = head->am_flags;
511 + (void) memcpy(&aobjrval.ir_atype_cache, &head->am_atype_cache,
512 + sizeof (aobjrval.ir_atype_cache));
490 513 (void) pthread_rwlock_unlock(&aobjmap.aobjmap_rwlock);
491 514 break;
492 515 default:
493 516 rsize = sizeof (ipmgmt_retval_t);
494 517 rvalp = &rval;
495 518 err = EINVAL;
496 519 }
497 520 ((ipmgmt_retval_t *)rvalp)->ir_err = err;
498 521 (void) door_return((char *)rvalp, rsize, NULL, 0);
499 522 }
500 523
501 524 /*
502 525 * Given an interface name and family, deletes all the address objects
503 526 * associated with it.
504 527 */
505 528 void
506 529 i_ipmgmt_delif_aobjs(char *ifname, sa_family_t af, uint32_t flags)
507 530 {
508 531 ipmgmt_aobjmap_t *head, *next, *prev;
509 532 ipadm_db_op_t db_op;
510 533
511 534 prev = NULL;
512 535
513 536 (void) pthread_rwlock_wrlock(&aobjmap.aobjmap_rwlock);
514 537 head = aobjmap.aobjmap_head;
515 538 for (; head; head = next) {
516 539 next = head->am_next;
517 540 if (strcmp(head->am_ifname, ifname) != 0 ||
518 541 head->am_family != af) {
519 542 prev = head;
520 543 continue;
521 544 }
522 545
523 546 if (head->am_flags == (IPMGMT_ACTIVE|IPMGMT_PERSIST) &&
524 547 flags == IPMGMT_ACTIVE) {
525 548 /*
526 549 * If the addres is present in both active and
527 550 * persistent store, and if we are performing
528 551 * a temporary delete, we update the node to
529 552 * indicate that the address is only present in
530 553 * persistent store and we proceed. Otherwise
531 554 * we always delete the node from aobjmap.
532 555 */
533 556 head->am_flags &= ~IPMGMT_ACTIVE;
534 557 head->am_lnum = -1;
535 558 db_op = IPADM_DB_WRITE;
536 559 } else {
537 560 db_op = IPADM_DB_DELETE;
538 561 if (prev == NULL)
539 562 aobjmap.aobjmap_head = next;
540 563 else
541 564 prev->am_next = next;
542 565 }
543 566 (void) ipmgmt_persist_aobjmap(head, db_op);
544 567 if (db_op == IPADM_DB_DELETE)
545 568 free(head);
546 569 }
547 570 (void) pthread_rwlock_unlock(&aobjmap.aobjmap_rwlock);
548 571 }
549 572
550 573 /*
551 574 * Handles the door command IPMGMT_CMD_SETIF. It persists the interface
552 575 * information in the DB.
553 576 */
554 577 static void
555 578 ipmgmt_setif_handler(void *argp)
556 579 {
557 580 ipmgmt_retval_t rval;
558 581
559 582 rval.ir_err = ipmgmt_persist_if(argp);
560 583 (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
561 584 }
562 585
563 586 /*
564 587 * Handles the door command IPMGMT_CMD_RESETIF. For the given interface,
565 588 * deletes all the persisted interface configuration. It also deletes, from
566 589 * `aobjmap', all the address objects configured on the given interface.
567 590 */
568 591 static void
569 592 ipmgmt_resetif_handler(void *argp)
570 593 {
571 594 ipmgmt_if_arg_t *rargp = argp;
572 595 ipmgmt_retval_t rval;
573 596 ipmgmt_if_cbarg_t cbarg;
574 597 uint32_t flags = rargp->ia_flags;
575 598 int err = 0;
576 599
577 600 cbarg.cb_family = rargp->ia_family;
578 601 cbarg.cb_ifname = rargp->ia_ifname;
579 602 if (flags & IPMGMT_PERSIST)
580 603 err = ipmgmt_db_walk(ipmgmt_db_resetif, &cbarg,
581 604 IPADM_DB_DELETE);
582 605
583 606 if (flags & IPMGMT_ACTIVE)
584 607 i_ipmgmt_delif_aobjs(rargp->ia_ifname, rargp->ia_family,
585 608 flags);
586 609
587 610 rval.ir_err = err;
588 611 (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
589 612 }
590 613
591 614 /*
592 615 * Handles the door command IPMGMT_CMD_RESETADDR. For the given addrobj
593 616 * deletes all the persisted addrobj configuration. It also deletes the
594 617 * corresponding node, from `aobjmap'.
595 618 */
596 619 static void
597 620 ipmgmt_resetaddr_handler(void *argp)
598 621 {
599 622 ipmgmt_addr_arg_t *rargp = argp;
600 623 ipmgmt_retval_t rval;
601 624 ipmgmt_aobjmap_t node;
602 625 uint32_t flags = rargp->ia_flags;
603 626 int err = 0;
604 627 ipmgmt_resetaddr_cbarg_t cbarg;
605 628
606 629 cbarg.cb_aobjname = rargp->ia_aobjname;
607 630
608 631 if (flags & IPMGMT_PERSIST)
609 632 err = ipmgmt_db_walk(ipmgmt_db_resetaddr, &cbarg,
610 633 IPADM_DB_DELETE);
611 634
612 635 if (flags & IPMGMT_ACTIVE) {
613 636 bzero(&node, sizeof (node));
614 637 (void) strlcpy(node.am_aobjname, rargp->ia_aobjname,
615 638 sizeof (node.am_aobjname));
616 639
617 640 /*
618 641 * am_lnum is used only for IPv6 autoconf case, since there
619 642 * can be multiple nodes with the same aobjname.
620 643 */
621 644 node.am_lnum = rargp->ia_lnum;
622 645 node.am_flags = flags;
623 646 (void) ipmgmt_aobjmap_op(&node, ADDROBJ_DELETE);
624 647 }
625 648
626 649 rval.ir_err = err;
627 650 (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
628 651 }
629 652
630 653 /*
631 654 * Handles the door command IPMGMT_CMD_GETADDR. It retrieves the persisted
632 655 * address for a given `gargp->ia_aobjname'. If it is not defined then it
633 656 * retrieves all the addresses configured on `gargp->ia_ifname'. The
634 657 * "ipadm show-addr addrobj" or "ipadm show-addr <ifname>/\*" will call this
635 658 * handler through library.
636 659 */
637 660 static void
638 661 ipmgmt_getaddr_handler(void *argp)
639 662 {
640 663 size_t buflen, onvlsize;
641 664 char *buf, *onvlbuf;
642 665 ipmgmt_getaddr_arg_t *gargp = argp;
643 666 ipmgmt_getaddr_cbarg_t cbarg;
644 667 ipmgmt_get_rval_t rval, *rvalp = &rval;
645 668 int err = 0;
646 669
647 670 cbarg.cb_ifname = gargp->ia_ifname;
648 671 cbarg.cb_aobjname = gargp->ia_aobjname;
649 672 cbarg.cb_ocnt = 0;
650 673 if (nvlist_alloc(&cbarg.cb_onvl, NV_UNIQUE_NAME, 0) != 0)
651 674 goto fail;
652 675 err = ipmgmt_db_walk(ipmgmt_db_getaddr, &cbarg, IPADM_DB_READ);
653 676 if (err == ENOENT && cbarg.cb_ocnt > 0) {
654 677 /*
655 678 * If there is atleast one entry in the nvlist,
656 679 * do not return error.
657 680 */
658 681 err = 0;
659 682 }
660 683 if (err != 0)
661 684 goto fail;
662 685
663 686 if ((err = nvlist_size(cbarg.cb_onvl, &onvlsize,
664 687 NV_ENCODE_NATIVE)) != 0) {
665 688 goto fail;
666 689 }
667 690 buflen = onvlsize + sizeof (ipmgmt_get_rval_t);
668 691 /*
669 692 * We cannot use malloc() here because door_return never returns, and
670 693 * memory allocated by malloc() would get leaked. Use alloca() instead.
671 694 */
672 695 buf = alloca(buflen);
673 696 onvlbuf = buf + sizeof (ipmgmt_get_rval_t);
674 697 if ((err = nvlist_pack(cbarg.cb_onvl, &onvlbuf, &onvlsize,
675 698 NV_ENCODE_NATIVE, 0)) != 0) {
676 699 goto fail;
677 700 }
678 701 nvlist_free(cbarg.cb_onvl);
679 702 rvalp = (ipmgmt_get_rval_t *)(void *)buf;
680 703 rvalp->ir_err = 0;
681 704 rvalp->ir_nvlsize = onvlsize;
682 705
683 706 (void) door_return(buf, buflen, NULL, 0);
684 707 return;
685 708 fail:
686 709 nvlist_free(cbarg.cb_onvl);
687 710 rvalp->ir_err = err;
688 711 (void) door_return((char *)rvalp, sizeof (*rvalp), NULL, 0);
689 712 }
690 713
691 714 /*
692 715 * Handles the door command IPMGMT_CMD_RESETPROP. It deletes the property line
693 716 * from the DB.
694 717 */
695 718 static void
696 719 ipmgmt_resetprop_handler(void *argp)
697 720 {
698 721 ipmgmt_prop_arg_t *pargp = argp;
699 722 ipmgmt_retval_t rval;
700 723
701 724 assert(pargp->ia_cmd == IPMGMT_CMD_RESETPROP);
702 725
703 726 rval.ir_err = ipmgmt_db_walk(ipmgmt_db_resetprop, pargp,
704 727 IPADM_DB_DELETE);
705 728 (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
706 729 }
707 730
708 731 /*
709 732 * Handles the door command IPMGMT_CMD_GETIF. It retrieves the name of all the
710 733 * persisted interfaces and the IP protocols (IPv4 or IPv6) they support.
711 734 */
712 735 static void
713 736 ipmgmt_getif_handler(void *argp)
714 737 {
715 738 ipmgmt_getif_arg_t *getif = argp;
716 739 ipmgmt_getif_rval_t *rvalp;
717 740 ipmgmt_retval_t rval;
718 741 ipmgmt_getif_cbarg_t cbarg;
719 742 ipadm_if_info_t *ifp, *rifp, *curifp;
720 743 int i, err = 0, count = 0;
721 744 size_t rbufsize;
722 745
723 746 assert(getif->ia_cmd == IPMGMT_CMD_GETIF);
724 747
725 748 bzero(&cbarg, sizeof (cbarg));
726 749 cbarg.cb_ifname = getif->ia_ifname;
727 750 err = ipmgmt_db_walk(ipmgmt_db_getif, &cbarg, IPADM_DB_READ);
728 751 if (err == ENOENT && cbarg.cb_ifinfo) {
729 752 /*
730 753 * If there is atleast one entry in the nvlist,
731 754 * do not return error.
732 755 */
733 756 err = 0;
734 757 }
735 758 if (err != 0) {
736 759 rval.ir_err = err;
737 760 (void) door_return((char *)&rval, sizeof (rval), NULL, 0);
738 761 return;
739 762 }
740 763
741 764 /* allocate sufficient buffer to return the interface info */
742 765 for (ifp = cbarg.cb_ifinfo; ifp != NULL; ifp = ifp->ifi_next)
743 766 ++count;
744 767 rbufsize = sizeof (*rvalp) + count * sizeof (*ifp);
745 768 rvalp = alloca(rbufsize);
746 769 bzero(rvalp, rbufsize);
747 770
748 771 rvalp->ir_ifcnt = count;
749 772 rifp = rvalp->ir_ifinfo;
750 773 ifp = cbarg.cb_ifinfo;
751 774
752 775 /*
753 776 * copy the interface info to buffer allocated on stack. The reason
754 777 * we do this is to avoid memory leak, as door_return() would never
755 778 * return
756 779 */
757 780 for (i = 0; i < count; i++) {
758 781 rifp = rvalp->ir_ifinfo + i;
759 782 (void) bcopy(ifp, rifp, sizeof (*rifp));
760 783 rifp->ifi_next = NULL;
761 784 curifp = ifp->ifi_next;
762 785 free(ifp);
763 786 ifp = curifp;
764 787 }
765 788 rvalp->ir_err = err;
766 789 (void) door_return((char *)rvalp, rbufsize, NULL, 0);
767 790 }
768 791
769 792 /*
770 793 * Handles the door command IPMGMT_CMD_INITIF. It retrieves all the persisted
771 794 * interface configuration (interface properties and addresses), for all those
772 795 * interfaces that need to be initialized.
773 796 */
774 797 static void
775 798 ipmgmt_initif_handler(void *argp)
776 799 {
777 800 ipmgmt_initif_arg_t *initif = argp;
778 801 size_t buflen, nvlsize;
779 802 char *buf = NULL, *onvlbuf, *invlbuf;
780 803 ipmgmt_get_rval_t rval, *rvalp = &rval;
781 804 ipmgmt_initif_cbarg_t cbarg;
782 805 int err;
783 806
784 807 assert(initif->ia_cmd == IPMGMT_CMD_INITIF);
785 808
786 809 bzero(&cbarg, sizeof (cbarg));
787 810 invlbuf = (char *)argp + sizeof (ipmgmt_initif_arg_t);
788 811 nvlsize = initif->ia_nvlsize;
789 812 err = nvlist_unpack(invlbuf, nvlsize, &cbarg.cb_invl, NV_ENCODE_NATIVE);
790 813 if (err != 0)
791 814 goto fail;
792 815
793 816 cbarg.cb_family = initif->ia_family;
794 817 if (nvlist_alloc(&cbarg.cb_onvl, NV_UNIQUE_NAME, 0) != 0)
795 818 goto fail;
796 819
797 820 err = ipmgmt_db_walk(ipmgmt_db_initif, &cbarg, IPADM_DB_READ);
798 821 if (err == ENOENT && cbarg.cb_ocnt > 0) {
799 822 /*
800 823 * If there is atleast one entry in the nvlist,
801 824 * do not return error.
802 825 */
803 826 err = 0;
804 827 }
805 828 if (err != 0)
806 829 goto fail;
807 830
808 831 if ((err = nvlist_size(cbarg.cb_onvl, &nvlsize, NV_ENCODE_NATIVE)) != 0)
809 832 goto fail;
810 833 buflen = nvlsize + sizeof (ipmgmt_get_rval_t);
811 834 /*
812 835 * We cannot use malloc() here because door_return never returns, and
813 836 * memory allocated by malloc() would get leaked. Use alloca() instead.
814 837 */
815 838 buf = alloca(buflen);
816 839 onvlbuf = buf + sizeof (ipmgmt_get_rval_t);
817 840 if ((err = nvlist_pack(cbarg.cb_onvl, &onvlbuf, &nvlsize,
818 841 NV_ENCODE_NATIVE, 0)) != 0) {
819 842 goto fail;
820 843 }
821 844 nvlist_free(cbarg.cb_invl);
822 845 nvlist_free(cbarg.cb_onvl);
823 846 rvalp = (ipmgmt_get_rval_t *)(void *)buf;
824 847 rvalp->ir_err = 0;
825 848 rvalp->ir_nvlsize = nvlsize;
826 849
827 850 (void) door_return(buf, buflen, NULL, 0);
828 851 return;
829 852 fail:
830 853 nvlist_free(cbarg.cb_invl);
831 854 nvlist_free(cbarg.cb_onvl);
832 855 rvalp->ir_err = err;
833 856 (void) door_return((char *)rvalp, sizeof (*rvalp), NULL, 0);
834 857 }
835 858
836 859 int
837 860 ipmgmt_persist_if(ipmgmt_if_arg_t *sargp)
838 861 {
839 862 ipadm_dbwrite_cbarg_t cb;
840 863 uint32_t flags = sargp->ia_flags;
841 864 nvlist_t *nvl = NULL;
842 865 int err = 0;
843 866 char strval[IPMGMT_STRSIZE];
844 867
845 868 if (!(flags & IPMGMT_PERSIST) || sargp->ia_family == AF_UNSPEC ||
846 869 sargp->ia_ifname[0] == '\0') {
847 870 err = EINVAL;
848 871 goto ret;
849 872 }
850 873 if ((err = nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0)) != 0)
851 874 goto ret;
852 875 if ((err = nvlist_add_string(nvl, IPADM_NVP_IFNAME,
853 876 sargp->ia_ifname)) != 0)
854 877 goto ret;
855 878 (void) snprintf(strval, IPMGMT_STRSIZE, "%d", sargp->ia_family);
856 879 if ((err = nvlist_add_string(nvl, IPADM_NVP_FAMILY, strval)) != 0)
857 880 goto ret;
858 881 cb.dbw_nvl = nvl;
859 882 cb.dbw_flags = 0;
860 883 err = ipmgmt_db_walk(ipmgmt_db_add, &cb, IPADM_DB_WRITE);
861 884 ret:
862 885 nvlist_free(nvl);
863 886 return (err);
864 887 }
|
↓ open down ↓ |
365 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX