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