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