Merge remote-tracking branch 'origin/master'
[unleashed/lotheac.git] / usr / src / lib / libipadm / common / ipadm_prop.c
blob820741f1a3182fd050a8fa668a4aff0e3e17734e
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright (c) 2013 by Delphix. All rights reserved.
27 * This file contains routines that are used to modify/retrieve protocol or
28 * interface property values. It also holds all the supported properties for
29 * both IP interface and protocols in `ipadm_prop_desc_t'. Following protocols
30 * are supported: IP, IPv4, IPv6, TCP, SCTP, UDP and ICMP.
32 * This file also contains walkers, which walks through the property table and
33 * calls the callback function, of the form `ipadm_prop_wfunc_t' , for every
34 * property in the table.
37 #include <unistd.h>
38 #include <errno.h>
39 #include <ctype.h>
40 #include <fcntl.h>
41 #include <strings.h>
42 #include <stdlib.h>
43 #include <netinet/in.h>
44 #include <arpa/inet.h>
45 #include <sys/sockio.h>
46 #include <assert.h>
47 #include <libdllink.h>
48 #include <zone.h>
49 #include "libipadm_impl.h"
50 #include <inet/tunables.h>
52 #define IPADM_NONESTR "none"
53 #define DEF_METRIC_VAL 0 /* default metric value */
55 #define A_CNT(arr) (sizeof (arr) / sizeof (arr[0]))
57 static ipadm_status_t i_ipadm_validate_if(ipadm_handle_t, const char *,
58 uint_t, uint_t);
61 * Callback functions to retrieve property values from the kernel. These
62 * functions, when required, translate the values from the kernel to a format
63 * suitable for printing. For example: boolean values will be translated
64 * to on/off. They also retrieve DEFAULT, PERM and POSSIBLE values for
65 * a given property.
67 static ipadm_pd_getf_t i_ipadm_get_prop, i_ipadm_get_ifprop_flags,
68 i_ipadm_get_mtu, i_ipadm_get_metric,
69 i_ipadm_get_usesrc, i_ipadm_get_forwarding,
70 i_ipadm_get_ecnsack, i_ipadm_get_hostmodel;
73 * Callback function to set property values. These functions translate the
74 * values to a format suitable for kernel consumption, allocates the necessary
75 * ioctl buffers and then invokes ioctl().
77 static ipadm_pd_setf_t i_ipadm_set_prop, i_ipadm_set_mtu,
78 i_ipadm_set_ifprop_flags,
79 i_ipadm_set_metric, i_ipadm_set_usesrc,
80 i_ipadm_set_forwarding, i_ipadm_set_eprivport,
81 i_ipadm_set_ecnsack, i_ipadm_set_hostmodel;
83 /* array of protocols we support */
84 static int protocols[] = { MOD_PROTO_IP, MOD_PROTO_RAWIP,
85 MOD_PROTO_TCP, MOD_PROTO_UDP,
86 MOD_PROTO_SCTP };
89 * Supported IP protocol properties.
91 static ipadm_prop_desc_t ipadm_ip_prop_table[] = {
92 { "arp", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV4, 0,
93 i_ipadm_set_ifprop_flags, i_ipadm_get_onoff,
94 i_ipadm_get_ifprop_flags },
96 { "forwarding", NULL, IPADMPROP_CLASS_MODIF, MOD_PROTO_IPV4, 0,
97 i_ipadm_set_forwarding, i_ipadm_get_onoff,
98 i_ipadm_get_forwarding },
100 { "metric", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV4, 0,
101 i_ipadm_set_metric, NULL, i_ipadm_get_metric },
103 { "mtu", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV4, 0,
104 i_ipadm_set_mtu, i_ipadm_get_mtu, i_ipadm_get_mtu },
106 { "exchange_routes", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV4, 0,
107 i_ipadm_set_ifprop_flags, i_ipadm_get_onoff,
108 i_ipadm_get_ifprop_flags },
110 { "usesrc", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV4, 0,
111 i_ipadm_set_usesrc, NULL, i_ipadm_get_usesrc },
113 { "ttl", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_IPV4, 0,
114 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
116 { "forwarding", NULL, IPADMPROP_CLASS_MODIF, MOD_PROTO_IPV6, 0,
117 i_ipadm_set_forwarding, i_ipadm_get_onoff,
118 i_ipadm_get_forwarding },
120 { "hoplimit", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_IPV6, 0,
121 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
123 { "metric", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV6, 0,
124 i_ipadm_set_metric, NULL, i_ipadm_get_metric },
126 { "mtu", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV6, 0,
127 i_ipadm_set_mtu, i_ipadm_get_mtu, i_ipadm_get_mtu },
129 { "nud", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV6, 0,
130 i_ipadm_set_ifprop_flags, i_ipadm_get_onoff,
131 i_ipadm_get_ifprop_flags },
133 { "exchange_routes", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV6, 0,
134 i_ipadm_set_ifprop_flags, i_ipadm_get_onoff,
135 i_ipadm_get_ifprop_flags },
137 { "usesrc", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV6, 0,
138 i_ipadm_set_usesrc, NULL, i_ipadm_get_usesrc },
140 { "hostmodel", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_IPV6, 0,
141 i_ipadm_set_hostmodel, i_ipadm_get_hostmodel,
142 i_ipadm_get_hostmodel },
144 { "hostmodel", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_IPV4, 0,
145 i_ipadm_set_hostmodel, i_ipadm_get_hostmodel,
146 i_ipadm_get_hostmodel },
148 { NULL, NULL, 0, 0, 0, NULL, NULL, NULL }
151 /* possible values for TCP properties `ecn' and `sack' */
152 static const char *ecn_sack_vals[] = {"never", "passive", "active", NULL};
154 /* Supported TCP protocol properties */
155 static ipadm_prop_desc_t ipadm_tcp_prop_table[] = {
156 { "dupack_fast_retrans", "dupack_fast_retransmit",
157 IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP, 0, i_ipadm_set_prop,
158 i_ipadm_get_prop, i_ipadm_get_prop },
160 { "ecn", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP, 0,
161 i_ipadm_set_ecnsack, i_ipadm_get_ecnsack, i_ipadm_get_ecnsack },
163 { "extra_priv_ports", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP,
164 IPADMPROP_MULVAL, i_ipadm_set_eprivport, i_ipadm_get_prop,
165 i_ipadm_get_prop },
167 { "largest_anon_port", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP, 0,
168 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
170 { "max_buf", "_max_buf", IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP, 0,
171 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
173 { "recv_buf", "recv_maxbuf", IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP, 0,
174 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
176 { "sack", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP, 0,
177 i_ipadm_set_ecnsack, i_ipadm_get_ecnsack, i_ipadm_get_ecnsack },
179 { "send_buf", "send_maxbuf", IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP, 0,
180 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
182 { "smallest_anon_port", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP, 0,
183 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
185 { "smallest_nonpriv_port", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP,
186 0, i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
188 { NULL, NULL, 0, 0, 0, NULL, NULL, NULL }
191 /* Supported UDP protocol properties */
192 static ipadm_prop_desc_t ipadm_udp_prop_table[] = {
193 { "extra_priv_ports", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_UDP,
194 IPADMPROP_MULVAL, i_ipadm_set_eprivport, i_ipadm_get_prop,
195 i_ipadm_get_prop },
197 { "largest_anon_port", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_UDP, 0,
198 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
200 { "max_buf", "_max_buf", IPADMPROP_CLASS_MODULE, MOD_PROTO_UDP, 0,
201 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
203 { "recv_buf", "recv_maxbuf", IPADMPROP_CLASS_MODULE, MOD_PROTO_UDP, 0,
204 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
206 { "send_buf", "send_maxbuf", IPADMPROP_CLASS_MODULE, MOD_PROTO_UDP, 0,
207 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
209 { "smallest_anon_port", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_UDP, 0,
210 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
212 { "smallest_nonpriv_port", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_UDP,
213 0, i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
215 { NULL, NULL, 0, 0, 0, NULL, NULL, NULL }
218 /* Supported SCTP protocol properties */
219 static ipadm_prop_desc_t ipadm_sctp_prop_table[] = {
220 { "extra_priv_ports", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_SCTP,
221 IPADMPROP_MULVAL, i_ipadm_set_eprivport, i_ipadm_get_prop,
222 i_ipadm_get_prop },
224 { "largest_anon_port", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_SCTP, 0,
225 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
227 { "max_buf", "_max_buf", IPADMPROP_CLASS_MODULE, MOD_PROTO_SCTP, 0,
228 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
230 { "recv_buf", "recv_maxbuf", IPADMPROP_CLASS_MODULE, MOD_PROTO_SCTP, 0,
231 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
233 { "send_buf", "send_maxbuf", IPADMPROP_CLASS_MODULE, MOD_PROTO_SCTP, 0,
234 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
236 { "smallest_anon_port", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_SCTP, 0,
237 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
239 { "smallest_nonpriv_port", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_SCTP,
240 0, i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
242 { NULL, NULL, 0, 0, 0, NULL, NULL, NULL }
245 /* Supported ICMP protocol properties */
246 static ipadm_prop_desc_t ipadm_icmp_prop_table[] = {
247 { "max_buf", "_max_buf", IPADMPROP_CLASS_MODULE, MOD_PROTO_RAWIP, 0,
248 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
250 { "recv_buf", "recv_maxbuf", IPADMPROP_CLASS_MODULE, MOD_PROTO_RAWIP, 0,
251 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
253 { "send_buf", "send_maxbuf", IPADMPROP_CLASS_MODULE, MOD_PROTO_RAWIP, 0,
254 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
256 { NULL, NULL, 0, 0, 0, NULL, NULL, NULL }
260 * A dummy private property structure, used while handling private
261 * protocol properties (properties not yet supported by libipadm).
263 static ipadm_prop_desc_t ipadm_privprop =
264 { NULL, NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_NONE, 0,
265 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop };
268 * Returns the property description table, for the given protocol
270 static ipadm_prop_desc_t *
271 i_ipadm_get_propdesc_table(uint_t proto)
273 switch (proto) {
274 case MOD_PROTO_IP:
275 case MOD_PROTO_IPV4:
276 case MOD_PROTO_IPV6:
277 return (ipadm_ip_prop_table);
278 case MOD_PROTO_RAWIP:
279 return (ipadm_icmp_prop_table);
280 case MOD_PROTO_TCP:
281 return (ipadm_tcp_prop_table);
282 case MOD_PROTO_UDP:
283 return (ipadm_udp_prop_table);
284 case MOD_PROTO_SCTP:
285 return (ipadm_sctp_prop_table);
288 return (NULL);
291 static ipadm_prop_desc_t *
292 i_ipadm_get_prop_desc(const char *pname, uint_t proto, int *errp)
294 int err = 0;
295 boolean_t matched_name = B_FALSE;
296 ipadm_prop_desc_t *ipdp = NULL, *ipdtbl;
298 if ((ipdtbl = i_ipadm_get_propdesc_table(proto)) == NULL) {
299 err = EINVAL;
300 goto ret;
303 for (ipdp = ipdtbl; ipdp->ipd_name != NULL; ipdp++) {
304 if (strcmp(pname, ipdp->ipd_name) == 0 ||
305 (ipdp->ipd_old_name != NULL &&
306 strcmp(pname, ipdp->ipd_old_name) == 0)) {
307 matched_name = B_TRUE;
308 if (ipdp->ipd_proto == proto)
309 break;
313 if (ipdp->ipd_name == NULL) {
314 err = ENOENT;
315 /* if we matched name, but failed protocol check */
316 if (matched_name)
317 err = EPROTO;
318 ipdp = NULL;
320 ret:
321 if (errp != NULL)
322 *errp = err;
323 return (ipdp);
326 char *
327 ipadm_proto2str(uint_t proto)
329 switch (proto) {
330 case MOD_PROTO_IP:
331 return ("ip");
332 case MOD_PROTO_IPV4:
333 return ("ipv4");
334 case MOD_PROTO_IPV6:
335 return ("ipv6");
336 case MOD_PROTO_RAWIP:
337 return ("icmp");
338 case MOD_PROTO_TCP:
339 return ("tcp");
340 case MOD_PROTO_UDP:
341 return ("udp");
342 case MOD_PROTO_SCTP:
343 return ("sctp");
346 return (NULL);
349 uint_t
350 ipadm_str2proto(const char *protostr)
352 if (protostr == NULL)
353 return (MOD_PROTO_NONE);
354 if (strcmp(protostr, "tcp") == 0)
355 return (MOD_PROTO_TCP);
356 else if (strcmp(protostr, "udp") == 0)
357 return (MOD_PROTO_UDP);
358 else if (strcmp(protostr, "ip") == 0)
359 return (MOD_PROTO_IP);
360 else if (strcmp(protostr, "ipv4") == 0)
361 return (MOD_PROTO_IPV4);
362 else if (strcmp(protostr, "ipv6") == 0)
363 return (MOD_PROTO_IPV6);
364 else if (strcmp(protostr, "icmp") == 0)
365 return (MOD_PROTO_RAWIP);
366 else if (strcmp(protostr, "sctp") == 0)
367 return (MOD_PROTO_SCTP);
368 else if (strcmp(protostr, "arp") == 0)
369 return (MOD_PROTO_IP);
371 return (MOD_PROTO_NONE);
374 /* ARGSUSED */
375 static ipadm_status_t
376 i_ipadm_set_mtu(ipadm_handle_t iph, const void *arg,
377 ipadm_prop_desc_t *pdp, const void *pval, uint_t proto, uint_t flags)
379 struct lifreq lifr;
380 char *endp;
381 uint_t mtu;
382 int s;
383 const char *ifname = arg;
384 char val[MAXPROPVALLEN];
386 /* to reset MTU first retrieve the default MTU and then set it */
387 if (flags & IPADM_OPT_DEFAULT) {
388 ipadm_status_t status;
389 uint_t size = MAXPROPVALLEN;
391 status = i_ipadm_get_prop(iph, arg, pdp, val, &size,
392 proto, MOD_PROP_DEFAULT);
393 if (status != IPADM_SUCCESS)
394 return (status);
395 pval = val;
398 errno = 0;
399 mtu = (uint_t)strtol(pval, &endp, 10);
400 if (errno != 0 || *endp != '\0')
401 return (IPADM_INVALID_ARG);
403 bzero(&lifr, sizeof (lifr));
404 (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
405 lifr.lifr_mtu = mtu;
407 s = (proto == MOD_PROTO_IPV6 ? iph->iph_sock6 : iph->iph_sock);
408 if (ioctl(s, SIOCSLIFMTU, (caddr_t)&lifr) < 0)
409 return (ipadm_errno2status(errno));
411 return (IPADM_SUCCESS);
414 /* ARGSUSED */
415 static ipadm_status_t
416 i_ipadm_set_metric(ipadm_handle_t iph, const void *arg,
417 ipadm_prop_desc_t *pdp, const void *pval, uint_t proto, uint_t flags)
419 struct lifreq lifr;
420 char *endp;
421 int metric;
422 const char *ifname = arg;
423 int s;
425 /* if we are resetting, set the value to its default value */
426 if (flags & IPADM_OPT_DEFAULT) {
427 metric = DEF_METRIC_VAL;
428 } else {
429 errno = 0;
430 metric = (uint_t)strtol(pval, &endp, 10);
431 if (errno != 0 || *endp != '\0')
432 return (IPADM_INVALID_ARG);
435 bzero(&lifr, sizeof (lifr));
436 (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
437 lifr.lifr_metric = metric;
439 s = (proto == MOD_PROTO_IPV6 ? iph->iph_sock6 : iph->iph_sock);
441 if (ioctl(s, SIOCSLIFMETRIC, (caddr_t)&lifr) < 0)
442 return (ipadm_errno2status(errno));
444 return (IPADM_SUCCESS);
447 /* ARGSUSED */
448 static ipadm_status_t
449 i_ipadm_set_usesrc(ipadm_handle_t iph, const void *arg,
450 ipadm_prop_desc_t *pdp, const void *pval, uint_t proto, uint_t flags)
452 struct lifreq lifr;
453 const char *ifname = arg;
454 int s;
455 uint_t ifindex = 0;
457 /* if we are resetting, set the value to its default value */
458 if (flags & IPADM_OPT_DEFAULT)
459 pval = IPADM_NONESTR;
462 * cannot specify logical interface name. We can also filter out other
463 * bogus interface names here itself through i_ipadm_validate_ifname().
465 if (strcmp(pval, IPADM_NONESTR) != 0 &&
466 !i_ipadm_validate_ifname(iph, pval))
467 return (IPADM_INVALID_ARG);
469 bzero(&lifr, sizeof (lifr));
470 (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
472 s = (proto == MOD_PROTO_IPV6 ? iph->iph_sock6 : iph->iph_sock);
474 if (strcmp(pval, IPADM_NONESTR) != 0) {
475 if ((ifindex = if_nametoindex(pval)) == 0)
476 return (ipadm_errno2status(errno));
477 lifr.lifr_index = ifindex;
478 } else {
479 if (ioctl(s, SIOCGLIFUSESRC, (caddr_t)&lifr) < 0)
480 return (ipadm_errno2status(errno));
481 lifr.lifr_index = 0;
483 if (ioctl(s, SIOCSLIFUSESRC, (caddr_t)&lifr) < 0)
484 return (ipadm_errno2status(errno));
486 return (IPADM_SUCCESS);
489 static struct hostmodel_strval {
490 char *esm_str;
491 ip_hostmodel_t esm_val;
492 } esm_arr[] = {
493 {"weak", IP_WEAK_ES},
494 {"src-priority", IP_SRC_PRI_ES},
495 {"strong", IP_STRONG_ES},
496 {"custom", IP_MAXVAL_ES}
499 static ip_hostmodel_t
500 i_ipadm_hostmodel_str2val(const char *pval)
502 int i;
504 for (i = 0; i < A_CNT(esm_arr); i++) {
505 if (esm_arr[i].esm_str != NULL &&
506 strcmp(pval, esm_arr[i].esm_str) == 0) {
507 return (esm_arr[i].esm_val);
510 return (IP_MAXVAL_ES);
513 static char *
514 i_ipadm_hostmodel_val2str(ip_hostmodel_t pval)
516 int i;
518 for (i = 0; i < A_CNT(esm_arr); i++) {
519 if (esm_arr[i].esm_val == pval)
520 return (esm_arr[i].esm_str);
522 return (NULL);
525 /* ARGSUSED */
526 static ipadm_status_t
527 i_ipadm_set_hostmodel(ipadm_handle_t iph, const void *arg,
528 ipadm_prop_desc_t *pdp, const void *pval, uint_t proto, uint_t flags)
530 ip_hostmodel_t hostmodel;
531 char val[11]; /* covers uint32_max as a string */
533 if ((flags & IPADM_OPT_DEFAULT) == 0) {
534 hostmodel = i_ipadm_hostmodel_str2val(pval);
535 if (hostmodel == IP_MAXVAL_ES)
536 return (IPADM_INVALID_ARG);
537 (void) snprintf(val, sizeof (val), "%d", hostmodel);
538 pval = val;
540 return (i_ipadm_set_prop(iph, NULL, pdp, pval, proto, flags));
543 /* ARGSUSED */
544 static ipadm_status_t
545 i_ipadm_get_hostmodel(ipadm_handle_t iph, const void *arg,
546 ipadm_prop_desc_t *pdp, char *buf, uint_t *bufsize, uint_t proto,
547 uint_t valtype)
549 ip_hostmodel_t hostmodel;
550 char *cp;
551 size_t nbytes;
552 ipadm_status_t status;
554 switch (valtype) {
555 case MOD_PROP_PERM:
556 nbytes = snprintf(buf, *bufsize, "%d", MOD_PROP_PERM_RW);
557 break;
558 case MOD_PROP_DEFAULT:
559 nbytes = snprintf(buf, *bufsize, "weak");
560 break;
561 case MOD_PROP_ACTIVE:
562 status = i_ipadm_get_prop(iph, arg, pdp, buf, bufsize, proto,
563 valtype);
564 if (status != IPADM_SUCCESS)
565 return (status);
566 bcopy(buf, &hostmodel, sizeof (hostmodel));
567 cp = i_ipadm_hostmodel_val2str(hostmodel);
568 nbytes = snprintf(buf, *bufsize, "%s",
569 (cp != NULL ? cp : "?"));
570 break;
571 case MOD_PROP_POSSIBLE:
572 nbytes = snprintf(buf, *bufsize, "strong,src-priority,weak");
573 break;
574 default:
575 return (IPADM_INVALID_ARG);
577 if (nbytes >= *bufsize) {
578 /* insufficient buffer space */
579 *bufsize = nbytes + 1;
580 return (IPADM_NO_BUFS);
582 return (IPADM_SUCCESS);
585 /* ARGSUSED */
586 static ipadm_status_t
587 i_ipadm_set_ifprop_flags(ipadm_handle_t iph, const void *arg,
588 ipadm_prop_desc_t *pdp, const void *pval, uint_t proto, uint_t flags)
590 ipadm_status_t status = IPADM_SUCCESS;
591 const char *ifname = arg;
592 uint64_t on_flags = 0, off_flags = 0;
593 boolean_t on = B_FALSE;
594 sa_family_t af = (proto == MOD_PROTO_IPV6 ? AF_INET6 : AF_INET);
596 /* if we are resetting, set the value to its default value */
597 if (flags & IPADM_OPT_DEFAULT) {
598 if (strcmp(pdp->ipd_name, "exchange_routes") == 0 ||
599 strcmp(pdp->ipd_name, "arp") == 0 ||
600 strcmp(pdp->ipd_name, "nud") == 0) {
601 pval = IPADM_ONSTR;
602 } else if (strcmp(pdp->ipd_name, "forwarding") == 0) {
603 pval = IPADM_OFFSTR;
604 } else {
605 return (IPADM_PROP_UNKNOWN);
609 if (strcmp(pval, IPADM_ONSTR) == 0)
610 on = B_TRUE;
611 else if (strcmp(pval, IPADM_OFFSTR) == 0)
612 on = B_FALSE;
613 else
614 return (IPADM_INVALID_ARG);
616 if (strcmp(pdp->ipd_name, "exchange_routes") == 0) {
617 if (on)
618 off_flags = IFF_NORTEXCH;
619 else
620 on_flags = IFF_NORTEXCH;
621 } else if (strcmp(pdp->ipd_name, "arp") == 0) {
622 if (on)
623 off_flags = IFF_NOARP;
624 else
625 on_flags = IFF_NOARP;
626 } else if (strcmp(pdp->ipd_name, "nud") == 0) {
627 if (on)
628 off_flags = IFF_NONUD;
629 else
630 on_flags = IFF_NONUD;
631 } else if (strcmp(pdp->ipd_name, "forwarding") == 0) {
632 if (on)
633 on_flags = IFF_ROUTER;
634 else
635 off_flags = IFF_ROUTER;
638 if (on_flags || off_flags) {
639 status = i_ipadm_set_flags(iph, ifname, af, on_flags,
640 off_flags);
642 return (status);
645 /* ARGSUSED */
646 static ipadm_status_t
647 i_ipadm_set_eprivport(ipadm_handle_t iph, const void *arg,
648 ipadm_prop_desc_t *pdp, const void *pval, uint_t proto, uint_t flags)
650 nvlist_t *portsnvl = NULL;
651 nvpair_t *nvp;
652 ipadm_status_t status = IPADM_SUCCESS;
653 int err;
654 uint_t count = 0;
656 if (flags & IPADM_OPT_DEFAULT) {
657 assert(pval == NULL);
658 return (i_ipadm_set_prop(iph, arg, pdp, pval, proto, flags));
661 if ((err = ipadm_str2nvlist(pval, &portsnvl, IPADM_NORVAL)) != 0)
662 return (ipadm_errno2status(err));
664 /* count the number of ports */
665 for (nvp = nvlist_next_nvpair(portsnvl, NULL); nvp != NULL;
666 nvp = nvlist_next_nvpair(portsnvl, nvp)) {
667 ++count;
670 if (iph->iph_flags & IPH_INIT) {
671 flags |= IPADM_OPT_APPEND;
672 } else if (count > 1) {
674 * We allow only one port to be added, removed or
675 * assigned at a time.
677 * However on reboot, while initializing protocol
678 * properties, extra_priv_ports might have multiple
679 * values. Only in that case we allow setting multiple
680 * values.
682 nvlist_free(portsnvl);
683 return (IPADM_INVALID_ARG);
686 for (nvp = nvlist_next_nvpair(portsnvl, NULL); nvp != NULL;
687 nvp = nvlist_next_nvpair(portsnvl, nvp)) {
688 status = i_ipadm_set_prop(iph, arg, pdp, nvpair_name(nvp),
689 proto, flags);
690 if (status != IPADM_SUCCESS)
691 break;
693 nvlist_free(portsnvl);
694 return (status);
697 /* ARGSUSED */
698 static ipadm_status_t
699 i_ipadm_set_forwarding(ipadm_handle_t iph, const void *arg,
700 ipadm_prop_desc_t *pdp, const void *pval, uint_t proto, uint_t flags)
702 const char *ifname = arg;
703 ipadm_status_t status;
706 * if interface name is provided, then set forwarding using the
707 * IFF_ROUTER flag
709 if (ifname != NULL) {
710 status = i_ipadm_set_ifprop_flags(iph, ifname, pdp, pval,
711 proto, flags);
712 } else {
713 char *val = NULL;
716 * if the caller is IPH_LEGACY, `pval' already contains
717 * numeric values.
719 if (!(flags & IPADM_OPT_DEFAULT) &&
720 !(iph->iph_flags & IPH_LEGACY)) {
722 if (strcmp(pval, IPADM_ONSTR) == 0)
723 val = "1";
724 else if (strcmp(pval, IPADM_OFFSTR) == 0)
725 val = "0";
726 else
727 return (IPADM_INVALID_ARG);
728 pval = val;
731 status = i_ipadm_set_prop(iph, ifname, pdp, pval, proto, flags);
734 return (status);
737 /* ARGSUSED */
738 static ipadm_status_t
739 i_ipadm_set_ecnsack(ipadm_handle_t iph, const void *arg,
740 ipadm_prop_desc_t *pdp, const void *pval, uint_t proto, uint_t flags)
742 uint_t i;
743 char val[MAXPROPVALLEN];
745 /* if IPH_LEGACY is set, `pval' already contains numeric values */
746 if (!(flags & IPADM_OPT_DEFAULT) && !(iph->iph_flags & IPH_LEGACY)) {
747 for (i = 0; ecn_sack_vals[i] != NULL; i++) {
748 if (strcmp(pval, ecn_sack_vals[i]) == 0)
749 break;
751 if (ecn_sack_vals[i] == NULL)
752 return (IPADM_INVALID_ARG);
753 (void) snprintf(val, MAXPROPVALLEN, "%d", i);
754 pval = val;
757 return (i_ipadm_set_prop(iph, arg, pdp, pval, proto, flags));
760 /* ARGSUSED */
761 ipadm_status_t
762 i_ipadm_get_ecnsack(ipadm_handle_t iph, const void *arg,
763 ipadm_prop_desc_t *pdp, char *buf, uint_t *bufsize, uint_t proto,
764 uint_t valtype)
766 ipadm_status_t status = IPADM_SUCCESS;
767 uint_t i, nbytes = 0;
769 switch (valtype) {
770 case MOD_PROP_POSSIBLE:
771 for (i = 0; ecn_sack_vals[i] != NULL; i++) {
772 if (i == 0)
773 nbytes += snprintf(buf + nbytes,
774 *bufsize - nbytes, "%s", ecn_sack_vals[i]);
775 else
776 nbytes += snprintf(buf + nbytes,
777 *bufsize - nbytes, ",%s", ecn_sack_vals[i]);
778 if (nbytes >= *bufsize)
779 break;
781 break;
782 case MOD_PROP_PERM:
783 case MOD_PROP_DEFAULT:
784 case MOD_PROP_ACTIVE:
785 status = i_ipadm_get_prop(iph, arg, pdp, buf, bufsize, proto,
786 valtype);
789 * If IPH_LEGACY is set, do not convert the value returned
790 * from kernel,
792 if (iph->iph_flags & IPH_LEGACY)
793 break;
796 * For current and default value, convert the value returned
797 * from kernel to more discrete representation.
799 if (status == IPADM_SUCCESS && (valtype == MOD_PROP_ACTIVE ||
800 valtype == MOD_PROP_DEFAULT)) {
801 i = atoi(buf);
802 assert(i < 3);
803 nbytes = snprintf(buf, *bufsize, "%s",
804 ecn_sack_vals[i]);
806 break;
807 default:
808 return (IPADM_INVALID_ARG);
810 if (nbytes >= *bufsize) {
811 /* insufficient buffer space */
812 *bufsize = nbytes + 1;
813 return (IPADM_NO_BUFS);
816 return (status);
819 /* ARGSUSED */
820 static ipadm_status_t
821 i_ipadm_get_forwarding(ipadm_handle_t iph, const void *arg,
822 ipadm_prop_desc_t *pdp, char *buf, uint_t *bufsize, uint_t proto,
823 uint_t valtype)
825 const char *ifname = arg;
826 ipadm_status_t status = IPADM_SUCCESS;
829 * if interface name is provided, then get forwarding status using
830 * SIOCGLIFFLAGS
832 if (ifname != NULL) {
833 status = i_ipadm_get_ifprop_flags(iph, ifname, pdp,
834 buf, bufsize, pdp->ipd_proto, valtype);
835 } else {
836 status = i_ipadm_get_prop(iph, ifname, pdp, buf,
837 bufsize, proto, valtype);
839 * If IPH_LEGACY is set, do not convert the value returned
840 * from kernel,
842 if (iph->iph_flags & IPH_LEGACY)
843 goto ret;
844 if (status == IPADM_SUCCESS && (valtype == MOD_PROP_ACTIVE ||
845 valtype == MOD_PROP_DEFAULT)) {
846 uint_t val = atoi(buf);
848 (void) snprintf(buf, *bufsize,
849 (val == 1 ? IPADM_ONSTR : IPADM_OFFSTR));
853 ret:
854 return (status);
857 /* ARGSUSED */
858 static ipadm_status_t
859 i_ipadm_get_mtu(ipadm_handle_t iph, const void *arg,
860 ipadm_prop_desc_t *pdp, char *buf, uint_t *bufsize, uint_t proto,
861 uint_t valtype)
863 struct lifreq lifr;
864 const char *ifname = arg;
865 size_t nbytes;
866 int s;
868 switch (valtype) {
869 case MOD_PROP_PERM:
870 nbytes = snprintf(buf, *bufsize, "%d", MOD_PROP_PERM_RW);
871 break;
872 case MOD_PROP_DEFAULT:
873 case MOD_PROP_POSSIBLE:
874 return (i_ipadm_get_prop(iph, arg, pdp, buf, bufsize,
875 proto, valtype));
876 case MOD_PROP_ACTIVE:
877 bzero(&lifr, sizeof (lifr));
878 (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
879 s = (proto == MOD_PROTO_IPV6 ? iph->iph_sock6 : iph->iph_sock);
881 if (ioctl(s, SIOCGLIFMTU, (caddr_t)&lifr) < 0)
882 return (ipadm_errno2status(errno));
883 nbytes = snprintf(buf, *bufsize, "%u", lifr.lifr_mtu);
884 break;
885 default:
886 return (IPADM_INVALID_ARG);
888 if (nbytes >= *bufsize) {
889 /* insufficient buffer space */
890 *bufsize = nbytes + 1;
891 return (IPADM_NO_BUFS);
893 return (IPADM_SUCCESS);
896 /* ARGSUSED */
897 static ipadm_status_t
898 i_ipadm_get_metric(ipadm_handle_t iph, const void *arg,
899 ipadm_prop_desc_t *pdp, char *buf, uint_t *bufsize, uint_t proto,
900 uint_t valtype)
902 struct lifreq lifr;
903 const char *ifname = arg;
904 size_t nbytes;
905 int s, val;
907 switch (valtype) {
908 case MOD_PROP_PERM:
909 val = MOD_PROP_PERM_RW;
910 break;
911 case MOD_PROP_DEFAULT:
912 val = DEF_METRIC_VAL;
913 break;
914 case MOD_PROP_ACTIVE:
915 bzero(&lifr, sizeof (lifr));
916 (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
918 s = (proto == MOD_PROTO_IPV6 ? iph->iph_sock6 : iph->iph_sock);
919 if (ioctl(s, SIOCGLIFMETRIC, (caddr_t)&lifr) < 0)
920 return (ipadm_errno2status(errno));
921 val = lifr.lifr_metric;
922 break;
923 default:
924 return (IPADM_INVALID_ARG);
926 nbytes = snprintf(buf, *bufsize, "%d", val);
927 if (nbytes >= *bufsize) {
928 /* insufficient buffer space */
929 *bufsize = nbytes + 1;
930 return (IPADM_NO_BUFS);
933 return (IPADM_SUCCESS);
936 /* ARGSUSED */
937 static ipadm_status_t
938 i_ipadm_get_usesrc(ipadm_handle_t iph, const void *arg,
939 ipadm_prop_desc_t *ipd, char *buf, uint_t *bufsize, uint_t proto,
940 uint_t valtype)
942 struct lifreq lifr;
943 const char *ifname = arg;
944 int s;
945 char if_name[IF_NAMESIZE];
946 size_t nbytes;
948 switch (valtype) {
949 case MOD_PROP_PERM:
950 nbytes = snprintf(buf, *bufsize, "%d", MOD_PROP_PERM_RW);
951 break;
952 case MOD_PROP_DEFAULT:
953 nbytes = snprintf(buf, *bufsize, "%s", IPADM_NONESTR);
954 break;
955 case MOD_PROP_ACTIVE:
956 bzero(&lifr, sizeof (lifr));
957 (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
959 s = (proto == MOD_PROTO_IPV6 ? iph->iph_sock6 : iph->iph_sock);
960 if (ioctl(s, SIOCGLIFUSESRC, (caddr_t)&lifr) < 0)
961 return (ipadm_errno2status(errno));
962 if (lifr.lifr_index == 0) {
963 /* no src address was set, so print 'none' */
964 (void) strlcpy(if_name, IPADM_NONESTR,
965 sizeof (if_name));
966 } else if (if_indextoname(lifr.lifr_index, if_name) == NULL) {
967 return (ipadm_errno2status(errno));
969 nbytes = snprintf(buf, *bufsize, "%s", if_name);
970 break;
971 default:
972 return (IPADM_INVALID_ARG);
974 if (nbytes >= *bufsize) {
975 /* insufficient buffer space */
976 *bufsize = nbytes + 1;
977 return (IPADM_NO_BUFS);
979 return (IPADM_SUCCESS);
982 /* ARGSUSED */
983 static ipadm_status_t
984 i_ipadm_get_ifprop_flags(ipadm_handle_t iph, const void *arg,
985 ipadm_prop_desc_t *pdp, char *buf, uint_t *bufsize, uint_t proto,
986 uint_t valtype)
988 uint64_t intf_flags;
989 char *val;
990 size_t nbytes;
991 const char *ifname = arg;
992 sa_family_t af;
993 ipadm_status_t status = IPADM_SUCCESS;
995 switch (valtype) {
996 case MOD_PROP_PERM:
997 nbytes = snprintf(buf, *bufsize, "%d", MOD_PROP_PERM_RW);
998 break;
999 case MOD_PROP_DEFAULT:
1000 if (strcmp(pdp->ipd_name, "exchange_routes") == 0 ||
1001 strcmp(pdp->ipd_name, "arp") == 0 ||
1002 strcmp(pdp->ipd_name, "nud") == 0) {
1003 val = IPADM_ONSTR;
1004 } else if (strcmp(pdp->ipd_name, "forwarding") == 0) {
1005 val = IPADM_OFFSTR;
1006 } else {
1007 return (IPADM_PROP_UNKNOWN);
1009 nbytes = snprintf(buf, *bufsize, "%s", val);
1010 break;
1011 case MOD_PROP_ACTIVE:
1012 af = (proto == MOD_PROTO_IPV6 ? AF_INET6 : AF_INET);
1013 status = i_ipadm_get_flags(iph, ifname, af, &intf_flags);
1014 if (status != IPADM_SUCCESS)
1015 return (status);
1017 val = IPADM_OFFSTR;
1018 if (strcmp(pdp->ipd_name, "exchange_routes") == 0) {
1019 if (!(intf_flags & IFF_NORTEXCH))
1020 val = IPADM_ONSTR;
1021 } else if (strcmp(pdp->ipd_name, "forwarding") == 0) {
1022 if (intf_flags & IFF_ROUTER)
1023 val = IPADM_ONSTR;
1024 } else if (strcmp(pdp->ipd_name, "arp") == 0) {
1025 if (!(intf_flags & IFF_NOARP))
1026 val = IPADM_ONSTR;
1027 } else if (strcmp(pdp->ipd_name, "nud") == 0) {
1028 if (!(intf_flags & IFF_NONUD))
1029 val = IPADM_ONSTR;
1031 nbytes = snprintf(buf, *bufsize, "%s", val);
1032 break;
1033 default:
1034 return (IPADM_INVALID_ARG);
1036 if (nbytes >= *bufsize) {
1037 /* insufficient buffer space */
1038 *bufsize = nbytes + 1;
1039 status = IPADM_NO_BUFS;
1042 return (status);
1045 static void
1046 i_ipadm_perm2str(char *buf, uint_t *bufsize)
1048 uint_t perm = atoi(buf);
1050 (void) snprintf(buf, *bufsize, "%c%c",
1051 ((perm & MOD_PROP_PERM_READ) != 0) ? 'r' : '-',
1052 ((perm & MOD_PROP_PERM_WRITE) != 0) ? 'w' : '-');
1055 /* ARGSUSED */
1056 static ipadm_status_t
1057 i_ipadm_get_prop(ipadm_handle_t iph, const void *arg,
1058 ipadm_prop_desc_t *pdp, char *buf, uint_t *bufsize, uint_t proto,
1059 uint_t valtype)
1061 ipadm_status_t status = IPADM_SUCCESS;
1062 const char *ifname = arg;
1063 mod_ioc_prop_t *mip;
1064 char *pname = pdp->ipd_name;
1065 uint_t iocsize;
1067 /* allocate sufficient ioctl buffer to retrieve value */
1068 iocsize = sizeof (mod_ioc_prop_t);
1069 if ((mip = calloc(1, iocsize)) == NULL)
1070 return (IPADM_NO_BUFS);
1072 mip->mpr_version = MOD_PROP_VERSION;
1073 mip->mpr_flags = valtype;
1074 mip->mpr_proto = proto;
1075 if (ifname != NULL) {
1076 (void) strlcpy(mip->mpr_ifname, ifname,
1077 sizeof (mip->mpr_ifname));
1079 (void) strlcpy(mip->mpr_name, pname, sizeof (mip->mpr_name));
1081 if (ioctl(iph->iph_sock, SIOCGETPROP, (char *)mip) < 0) {
1082 if (errno == ENOENT)
1083 status = IPADM_PROP_UNKNOWN;
1084 else
1085 status = ipadm_errno2status(errno);
1086 } else {
1087 bcopy(mip->mpr_val, buf, *bufsize);
1090 free(mip);
1091 return (status);
1095 * Populates the ipmgmt_prop_arg_t based on the class of property.
1097 * For private protocol properties, while persisting information in ipadm
1098 * data store, to ensure there is no collision of namespace between ipadm
1099 * private nvpair names (which also starts with '_', see ipadm_ipmgmt.h)
1100 * and private protocol property names, we will prepend IPADM_PRIV_PROP_PREFIX
1101 * to property names.
1103 static void
1104 i_ipadm_populate_proparg(ipmgmt_prop_arg_t *pargp, ipadm_prop_desc_t *pdp,
1105 const char *pval, const void *object)
1107 const struct ipadm_addrobj_s *ipaddr;
1108 uint_t class = pdp->ipd_class;
1109 uint_t proto = pdp->ipd_proto;
1111 (void) strlcpy(pargp->ia_pname, pdp->ipd_name,
1112 sizeof (pargp->ia_pname));
1113 if (pval != NULL)
1114 (void) strlcpy(pargp->ia_pval, pval, sizeof (pargp->ia_pval));
1116 switch (class) {
1117 case IPADMPROP_CLASS_MODULE:
1118 /* if it's a private property then add the prefix. */
1119 if (pdp->ipd_name[0] == '_') {
1120 (void) snprintf(pargp->ia_pname,
1121 sizeof (pargp->ia_pname), "_%s", pdp->ipd_name);
1123 (void) strlcpy(pargp->ia_module, object,
1124 sizeof (pargp->ia_module));
1125 break;
1126 case IPADMPROP_CLASS_MODIF:
1127 /* check if object is protostr or an ifname */
1128 if (ipadm_str2proto(object) != MOD_PROTO_NONE) {
1129 (void) strlcpy(pargp->ia_module, object,
1130 sizeof (pargp->ia_module));
1131 break;
1133 /* it's an interface property, fall through */
1134 /* FALLTHRU */
1135 case IPADMPROP_CLASS_IF:
1136 (void) strlcpy(pargp->ia_ifname, object,
1137 sizeof (pargp->ia_ifname));
1138 (void) strlcpy(pargp->ia_module, ipadm_proto2str(proto),
1139 sizeof (pargp->ia_module));
1140 break;
1141 case IPADMPROP_CLASS_ADDR:
1142 ipaddr = object;
1143 (void) strlcpy(pargp->ia_ifname, ipaddr->ipadm_ifname,
1144 sizeof (pargp->ia_ifname));
1145 (void) strlcpy(pargp->ia_aobjname, ipaddr->ipadm_aobjname,
1146 sizeof (pargp->ia_aobjname));
1147 break;
1152 * Common function to retrieve property value for a given interface `ifname' or
1153 * for a given protocol `proto'. The property name is in `pname'.
1155 * `valtype' determines the type of value that will be retrieved.
1156 * IPADM_OPT_ACTIVE - current value of the property (active config)
1157 * IPADM_OPT_PERSIST - value of the property from persistent store
1158 * IPADM_OPT_DEFAULT - default hard coded value (boot-time value)
1159 * IPADM_OPT_PERM - read/write permissions for the value
1160 * IPADM_OPT_POSSIBLE - range of values
1162 static ipadm_status_t
1163 i_ipadm_getprop_common(ipadm_handle_t iph, const char *ifname,
1164 const char *pname, char *buf, uint_t *bufsize, uint_t proto,
1165 uint_t valtype)
1167 ipadm_status_t status = IPADM_SUCCESS;
1168 ipadm_prop_desc_t *pdp;
1169 char priv_propname[MAXPROPNAMELEN];
1170 boolean_t is_if = (ifname != NULL);
1171 int err = 0;
1173 pdp = i_ipadm_get_prop_desc(pname, proto, &err);
1174 if (err == EPROTO)
1175 return (IPADM_BAD_PROTOCOL);
1176 /* there are no private interface properties */
1177 if (is_if && err == ENOENT)
1178 return (IPADM_PROP_UNKNOWN);
1180 if (pdp != NULL) {
1182 * check whether the property can be
1183 * applied on an interface
1185 if (is_if && !(pdp->ipd_class & IPADMPROP_CLASS_IF))
1186 return (IPADM_INVALID_ARG);
1188 * check whether the property can be
1189 * applied on a module
1191 if (!is_if && !(pdp->ipd_class & IPADMPROP_CLASS_MODULE))
1192 return (IPADM_INVALID_ARG);
1194 } else {
1195 /* private protocol properties, pass it to kernel directly */
1196 pdp = &ipadm_privprop;
1197 (void) strlcpy(priv_propname, pname, sizeof (priv_propname));
1198 pdp->ipd_name = priv_propname;
1201 switch (valtype) {
1202 case IPADM_OPT_PERM:
1203 status = pdp->ipd_get(iph, ifname, pdp, buf, bufsize, proto,
1204 MOD_PROP_PERM);
1205 if (status == IPADM_SUCCESS)
1206 i_ipadm_perm2str(buf, bufsize);
1207 break;
1208 case IPADM_OPT_ACTIVE:
1209 status = pdp->ipd_get(iph, ifname, pdp, buf, bufsize, proto,
1210 MOD_PROP_ACTIVE);
1211 break;
1212 case IPADM_OPT_DEFAULT:
1213 status = pdp->ipd_get(iph, ifname, pdp, buf, bufsize, proto,
1214 MOD_PROP_DEFAULT);
1215 break;
1216 case IPADM_OPT_POSSIBLE:
1217 if (pdp->ipd_get_range != NULL) {
1218 status = pdp->ipd_get_range(iph, ifname, pdp, buf,
1219 bufsize, proto, MOD_PROP_POSSIBLE);
1220 break;
1222 buf[0] = '\0';
1223 break;
1224 case IPADM_OPT_PERSIST:
1225 /* retrieve from database */
1226 if (is_if)
1227 status = i_ipadm_get_persist_propval(iph, pdp, buf,
1228 bufsize, ifname);
1229 else
1230 status = i_ipadm_get_persist_propval(iph, pdp, buf,
1231 bufsize, ipadm_proto2str(proto));
1232 break;
1233 default:
1234 status = IPADM_INVALID_ARG;
1235 break;
1237 return (status);
1241 * Get protocol property of the specified protocol.
1243 ipadm_status_t
1244 ipadm_get_prop(ipadm_handle_t iph, const char *pname, char *buf,
1245 uint_t *bufsize, uint_t proto, uint_t valtype)
1248 * validate the arguments of the function.
1250 if (iph == NULL || pname == NULL || buf == NULL ||
1251 bufsize == NULL || *bufsize == 0) {
1252 return (IPADM_INVALID_ARG);
1255 * Do we support this proto, if not return error.
1257 if (ipadm_proto2str(proto) == NULL)
1258 return (IPADM_NOTSUP);
1260 return (i_ipadm_getprop_common(iph, NULL, pname, buf, bufsize,
1261 proto, valtype));
1265 * Get interface property of the specified interface.
1267 ipadm_status_t
1268 ipadm_get_ifprop(ipadm_handle_t iph, const char *ifname, const char *pname,
1269 char *buf, uint_t *bufsize, uint_t proto, uint_t valtype)
1271 /* validate the arguments of the function. */
1272 if (iph == NULL || pname == NULL || buf == NULL ||
1273 bufsize == NULL || *bufsize == 0) {
1274 return (IPADM_INVALID_ARG);
1277 /* Do we support this proto, if not return error. */
1278 if (ipadm_proto2str(proto) == NULL)
1279 return (IPADM_NOTSUP);
1282 * check if interface name is provided for interface property and
1283 * is valid.
1285 if (!i_ipadm_validate_ifname(iph, ifname))
1286 return (IPADM_INVALID_ARG);
1288 return (i_ipadm_getprop_common(iph, ifname, pname, buf, bufsize,
1289 proto, valtype));
1293 * Allocates sufficient ioctl buffers and copies property name and the
1294 * value, among other things. If the flag IPADM_OPT_DEFAULT is set, then
1295 * `pval' will be NULL and it instructs the kernel to reset the current
1296 * value to property's default value.
1298 static ipadm_status_t
1299 i_ipadm_set_prop(ipadm_handle_t iph, const void *arg,
1300 ipadm_prop_desc_t *pdp, const void *pval, uint_t proto, uint_t flags)
1302 ipadm_status_t status = IPADM_SUCCESS;
1303 const char *ifname = arg;
1304 mod_ioc_prop_t *mip;
1305 char *pname = pdp->ipd_name;
1306 uint_t iocsize;
1307 uint_t iocflags = 0;
1309 if (flags & IPADM_OPT_DEFAULT) {
1310 iocflags |= MOD_PROP_DEFAULT;
1311 } else if (flags & IPADM_OPT_ACTIVE) {
1312 iocflags |= MOD_PROP_ACTIVE;
1313 if (flags & IPADM_OPT_APPEND)
1314 iocflags |= MOD_PROP_APPEND;
1315 else if (flags & IPADM_OPT_REMOVE)
1316 iocflags |= MOD_PROP_REMOVE;
1319 iocsize = sizeof (mod_ioc_prop_t);
1321 if ((mip = calloc(1, iocsize)) == NULL)
1322 return (IPADM_NO_BUFS);
1324 mip->mpr_version = MOD_PROP_VERSION;
1325 mip->mpr_flags = iocflags;
1326 mip->mpr_proto = proto;
1327 if (ifname != NULL) {
1328 (void) strlcpy(mip->mpr_ifname, ifname,
1329 sizeof (mip->mpr_ifname));
1332 (void) strlcpy(mip->mpr_name, pname, sizeof (mip->mpr_name));
1333 if (pval != NULL)
1334 (void) strlcpy(mip->mpr_val, pval, sizeof(mip->mpr_val));
1336 if (ioctl(iph->iph_sock, SIOCSETPROP, (char *)mip) < 0) {
1337 if (errno == ENOENT)
1338 status = IPADM_PROP_UNKNOWN;
1339 else
1340 status = ipadm_errno2status(errno);
1342 free(mip);
1343 return (status);
1347 * Common function for modifying both protocol/interface property.
1349 * If:
1350 * IPADM_OPT_PERSIST is set then the value is persisted.
1351 * IPADM_OPT_DEFAULT is set then the default value for the property will
1352 * be applied.
1354 static ipadm_status_t
1355 i_ipadm_setprop_common(ipadm_handle_t iph, const char *ifname,
1356 const char *pname, const char *buf, uint_t proto, uint_t pflags)
1358 ipadm_status_t status = IPADM_SUCCESS;
1359 boolean_t persist = (pflags & IPADM_OPT_PERSIST);
1360 boolean_t reset = (pflags & IPADM_OPT_DEFAULT);
1361 ipadm_prop_desc_t *pdp;
1362 boolean_t is_if = (ifname != NULL);
1363 char priv_propname[MAXPROPNAMELEN];
1364 int err = 0;
1366 /* Check that property value is within the allowed size */
1367 if (!reset && strnlen(buf, MAXPROPVALLEN) >= MAXPROPVALLEN)
1368 return (IPADM_INVALID_ARG);
1370 pdp = i_ipadm_get_prop_desc(pname, proto, &err);
1371 if (err == EPROTO)
1372 return (IPADM_BAD_PROTOCOL);
1373 /* there are no private interface properties */
1374 if (is_if && err == ENOENT)
1375 return (IPADM_PROP_UNKNOWN);
1377 if (pdp != NULL) {
1378 /* do some sanity checks */
1379 if (is_if) {
1380 if (!(pdp->ipd_class & IPADMPROP_CLASS_IF))
1381 return (IPADM_INVALID_ARG);
1382 } else {
1383 if (!(pdp->ipd_class & IPADMPROP_CLASS_MODULE))
1384 return (IPADM_INVALID_ARG);
1387 * if the property is not multi-valued and IPADM_OPT_APPEND or
1388 * IPADM_OPT_REMOVE is specified, return IPADM_INVALID_ARG.
1390 if (!(pdp->ipd_flags & IPADMPROP_MULVAL) && (pflags &
1391 (IPADM_OPT_APPEND|IPADM_OPT_REMOVE))) {
1392 return (IPADM_INVALID_ARG);
1394 } else {
1395 /* private protocol property, pass it to kernel directly */
1396 pdp = &ipadm_privprop;
1397 (void) strlcpy(priv_propname, pname, sizeof (priv_propname));
1398 pdp->ipd_name = priv_propname;
1401 status = pdp->ipd_set(iph, ifname, pdp, buf, proto, pflags);
1402 if (status != IPADM_SUCCESS)
1403 return (status);
1405 if (persist) {
1406 if (is_if)
1407 status = i_ipadm_persist_propval(iph, pdp, buf, ifname,
1408 pflags);
1409 else
1410 status = i_ipadm_persist_propval(iph, pdp, buf,
1411 ipadm_proto2str(proto), pflags);
1413 return (status);
1417 * Sets the property value of the specified interface
1419 ipadm_status_t
1420 ipadm_set_ifprop(ipadm_handle_t iph, const char *ifname, const char *pname,
1421 const char *buf, uint_t proto, uint_t pflags)
1423 boolean_t reset = (pflags & IPADM_OPT_DEFAULT);
1424 ipadm_status_t status;
1426 /* check for solaris.network.interface.config authorization */
1427 if (!ipadm_check_auth())
1428 return (IPADM_EAUTH);
1430 * validate the arguments of the function.
1432 if (iph == NULL || pname == NULL || (!reset && buf == NULL) ||
1433 pflags == 0 || pflags == IPADM_OPT_PERSIST ||
1434 (pflags & ~(IPADM_COMMON_OPT_MASK|IPADM_OPT_DEFAULT))) {
1435 return (IPADM_INVALID_ARG);
1439 * Do we support this protocol, if not return error.
1441 if (ipadm_proto2str(proto) == NULL)
1442 return (IPADM_NOTSUP);
1445 * Validate the interface and check if a persistent
1446 * operation is performed on a temporary object.
1448 status = i_ipadm_validate_if(iph, ifname, proto, pflags);
1449 if (status != IPADM_SUCCESS)
1450 return (status);
1452 return (i_ipadm_setprop_common(iph, ifname, pname, buf, proto,
1453 pflags));
1457 * Sets the property value of the specified protocol.
1459 ipadm_status_t
1460 ipadm_set_prop(ipadm_handle_t iph, const char *pname, const char *buf,
1461 uint_t proto, uint_t pflags)
1463 boolean_t reset = (pflags & IPADM_OPT_DEFAULT);
1465 /* check for solaris.network.interface.config authorization */
1466 if (!ipadm_check_auth())
1467 return (IPADM_EAUTH);
1469 * validate the arguments of the function.
1471 if (iph == NULL || pname == NULL ||(!reset && buf == NULL) ||
1472 pflags == 0 || pflags == IPADM_OPT_PERSIST ||
1473 (pflags & ~(IPADM_COMMON_OPT_MASK|IPADM_OPT_DEFAULT|
1474 IPADM_OPT_APPEND|IPADM_OPT_REMOVE))) {
1475 return (IPADM_INVALID_ARG);
1479 * Do we support this proto, if not return error.
1481 if (ipadm_proto2str(proto) == NULL)
1482 return (IPADM_NOTSUP);
1484 return (i_ipadm_setprop_common(iph, NULL, pname, buf, proto,
1485 pflags));
1488 /* helper function for ipadm_walk_proptbl */
1489 static void
1490 i_ipadm_walk_proptbl(ipadm_prop_desc_t *pdtbl, uint_t proto, uint_t class,
1491 ipadm_prop_wfunc_t *func, void *arg)
1493 ipadm_prop_desc_t *pdp;
1495 for (pdp = pdtbl; pdp->ipd_name != NULL; pdp++) {
1496 if (!(pdp->ipd_class & class))
1497 continue;
1499 if (proto != MOD_PROTO_NONE && !(pdp->ipd_proto & proto))
1500 continue;
1503 * we found a class specific match, call the
1504 * user callback function.
1506 if (func(arg, pdp->ipd_name, pdp->ipd_proto) == B_FALSE)
1507 break;
1512 * Walks through all the properties, for a given protocol and property class
1513 * (protocol or interface).
1515 * Further if proto == MOD_PROTO_NONE, then it walks through all the supported
1516 * protocol property tables.
1518 ipadm_status_t
1519 ipadm_walk_proptbl(uint_t proto, uint_t class, ipadm_prop_wfunc_t *func,
1520 void *arg)
1522 ipadm_prop_desc_t *pdtbl;
1523 ipadm_status_t status = IPADM_SUCCESS;
1524 int i;
1525 int count = A_CNT(protocols);
1527 if (func == NULL)
1528 return (IPADM_INVALID_ARG);
1530 switch (class) {
1531 case IPADMPROP_CLASS_ADDR:
1532 pdtbl = ipadm_addrprop_table;
1533 break;
1534 case IPADMPROP_CLASS_IF:
1535 case IPADMPROP_CLASS_MODULE:
1536 pdtbl = i_ipadm_get_propdesc_table(proto);
1537 if (pdtbl == NULL && proto != MOD_PROTO_NONE)
1538 return (IPADM_INVALID_ARG);
1539 break;
1540 default:
1541 return (IPADM_INVALID_ARG);
1544 if (pdtbl != NULL) {
1546 * proto will be MOD_PROTO_NONE in the case of
1547 * IPADMPROP_CLASS_ADDR.
1549 i_ipadm_walk_proptbl(pdtbl, proto, class, func, arg);
1550 } else {
1551 /* Walk thru all the protocol tables, we support */
1552 for (i = 0; i < count; i++) {
1553 pdtbl = i_ipadm_get_propdesc_table(protocols[i]);
1554 i_ipadm_walk_proptbl(pdtbl, protocols[i], class, func,
1555 arg);
1558 return (status);
1562 * Given a property name, walks through all the instances of a property name.
1563 * Some properties have two instances one for v4 interfaces and another for v6
1564 * interfaces. For example: MTU. MTU can have different values for v4 and v6.
1565 * Therefore there are two properties for 'MTU'.
1567 * This function invokes `func' for every instance of property `pname'
1569 ipadm_status_t
1570 ipadm_walk_prop(const char *pname, uint_t proto, uint_t class,
1571 ipadm_prop_wfunc_t *func, void *arg)
1573 ipadm_prop_desc_t *pdtbl, *pdp;
1574 ipadm_status_t status = IPADM_SUCCESS;
1575 boolean_t matched = B_FALSE;
1577 if (pname == NULL || func == NULL)
1578 return (IPADM_INVALID_ARG);
1580 switch (class) {
1581 case IPADMPROP_CLASS_ADDR:
1582 pdtbl = ipadm_addrprop_table;
1583 break;
1584 case IPADMPROP_CLASS_IF:
1585 case IPADMPROP_CLASS_MODULE:
1586 pdtbl = i_ipadm_get_propdesc_table(proto);
1587 break;
1588 default:
1589 return (IPADM_INVALID_ARG);
1592 if (pdtbl == NULL)
1593 return (IPADM_INVALID_ARG);
1595 for (pdp = pdtbl; pdp->ipd_name != NULL; pdp++) {
1596 if (strcmp(pname, pdp->ipd_name) != 0)
1597 continue;
1598 if (!(pdp->ipd_proto & proto))
1599 continue;
1600 matched = B_TRUE;
1601 /* we found a match, call the callback function */
1602 if (func(arg, pdp->ipd_name, pdp->ipd_proto) == B_FALSE)
1603 break;
1605 if (!matched)
1606 status = IPADM_PROP_UNKNOWN;
1607 return (status);
1610 /* ARGSUSED */
1611 ipadm_status_t
1612 i_ipadm_get_onoff(ipadm_handle_t iph, const void *arg, ipadm_prop_desc_t *dp,
1613 char *buf, uint_t *bufsize, uint_t proto, uint_t valtype)
1615 (void) snprintf(buf, *bufsize, "%s,%s", IPADM_ONSTR, IPADM_OFFSTR);
1616 return (IPADM_SUCCESS);
1620 * Makes a door call to ipmgmtd to retrieve the persisted property value
1622 ipadm_status_t
1623 i_ipadm_get_persist_propval(ipadm_handle_t iph, ipadm_prop_desc_t *pdp,
1624 char *gbuf, uint_t *gbufsize, const void *object)
1626 ipmgmt_prop_arg_t parg;
1627 ipmgmt_getprop_rval_t rval, *rvalp;
1628 size_t nbytes;
1629 int err = 0;
1631 bzero(&parg, sizeof (parg));
1632 parg.ia_cmd = IPMGMT_CMD_GETPROP;
1633 i_ipadm_populate_proparg(&parg, pdp, NULL, object);
1635 rvalp = &rval;
1636 err = ipadm_door_call(iph, &parg, sizeof (parg), (void **)&rvalp,
1637 sizeof (rval), B_FALSE);
1638 if (err == 0) {
1639 /* assert that rvalp was not reallocated */
1640 assert(rvalp == &rval);
1642 /* `ir_pval' contains the property value */
1643 nbytes = snprintf(gbuf, *gbufsize, "%s", rvalp->ir_pval);
1644 if (nbytes >= *gbufsize) {
1645 /* insufficient buffer space */
1646 *gbufsize = nbytes + 1;
1647 err = ENOBUFS;
1650 return (ipadm_errno2status(err));
1654 * Persists the property value for a given property in the data store
1656 ipadm_status_t
1657 i_ipadm_persist_propval(ipadm_handle_t iph, ipadm_prop_desc_t *pdp,
1658 const char *pval, const void *object, uint_t flags)
1660 ipmgmt_prop_arg_t parg;
1661 int err = 0;
1663 bzero(&parg, sizeof (parg));
1664 i_ipadm_populate_proparg(&parg, pdp, pval, object);
1666 * Check if value to be persisted need to be appended or removed. This
1667 * is required for multi-valued property.
1669 if (flags & IPADM_OPT_APPEND)
1670 parg.ia_flags |= IPMGMT_APPEND;
1671 if (flags & IPADM_OPT_REMOVE)
1672 parg.ia_flags |= IPMGMT_REMOVE;
1674 if (flags & (IPADM_OPT_DEFAULT|IPADM_OPT_REMOVE))
1675 parg.ia_cmd = IPMGMT_CMD_RESETPROP;
1676 else
1677 parg.ia_cmd = IPMGMT_CMD_SETPROP;
1679 err = ipadm_door_call(iph, &parg, sizeof (parg), NULL, 0, B_FALSE);
1682 * its fine if there were no entry in the DB to delete. The user
1683 * might be changing property value, which was not changed
1684 * persistently.
1686 if (err == ENOENT)
1687 err = 0;
1688 return (ipadm_errno2status(err));
1692 * This is called from ipadm_set_ifprop() to validate the set operation.
1693 * It does the following steps:
1694 * 1. Validates the interface name.
1695 * 2. Fails if it is an IPMP meta-interface or an underlying interface.
1696 * 3. In case of a persistent operation, verifies that the
1697 * interface is persistent.
1699 static ipadm_status_t
1700 i_ipadm_validate_if(ipadm_handle_t iph, const char *ifname,
1701 uint_t proto, uint_t flags)
1703 sa_family_t af, other_af;
1704 ipadm_status_t status;
1705 boolean_t p_exists;
1706 boolean_t af_exists, other_af_exists, a_exists;
1708 /* Check if the interface name is valid. */
1709 if (!i_ipadm_validate_ifname(iph, ifname))
1710 return (IPADM_INVALID_ARG);
1712 af = (proto == MOD_PROTO_IPV6 ? AF_INET6 : AF_INET);
1714 * Setting properties on an IPMP meta-interface or underlying
1715 * interface is not supported.
1717 if (i_ipadm_is_ipmp(iph, ifname) || i_ipadm_is_under_ipmp(iph, ifname))
1718 return (IPADM_NOTSUP);
1720 /* Check if interface exists in the persistent configuration. */
1721 status = i_ipadm_if_pexists(iph, ifname, af, &p_exists);
1722 if (status != IPADM_SUCCESS)
1723 return (status);
1725 /* Check if interface exists in the active configuration. */
1726 af_exists = ipadm_if_enabled(iph, ifname, af);
1727 other_af = (af == AF_INET ? AF_INET6 : AF_INET);
1728 other_af_exists = ipadm_if_enabled(iph, ifname, other_af);
1729 a_exists = (af_exists || other_af_exists);
1730 if (!a_exists && p_exists)
1731 return (IPADM_OP_DISABLE_OBJ);
1732 if (!af_exists)
1733 return (IPADM_ENXIO);
1736 * If a persistent operation is requested, check if the underlying
1737 * IP interface is persistent.
1739 if ((flags & IPADM_OPT_PERSIST) && !p_exists)
1740 return (IPADM_TEMPORARY_OBJ);
1741 return (IPADM_SUCCESS);
1745 * Private protocol properties namespace scheme:
1747 * PSARC 2010/080 identified the private protocol property names to be the
1748 * leading protocol names. For e.g. tcp_strong_iss, ip_strict_src_multihoming,
1749 * et al,. However to be consistent with private data-link property names,
1750 * which starts with '_', private protocol property names will start with '_'.
1751 * For e.g. _strong_iss, _strict_src_multihoming, et al,.
1754 /* maps new private protocol property name to the old private property name */
1755 typedef struct ipadm_oname2nname_map {
1756 char *iom_oname;
1757 char *iom_nname;
1758 uint_t iom_proto;
1759 } ipadm_oname2nname_map_t;
1762 * IP is a special case. It isn't straight forward to derive the legacy name
1763 * from the new name and vice versa. No set standard was followed in naming
1764 * the properties and hence we need a table to capture the mapping.
1766 static ipadm_oname2nname_map_t name_map[] = {
1767 { "arp_probe_delay", "_arp_probe_delay",
1768 MOD_PROTO_IP },
1769 { "arp_fastprobe_delay", "_arp_fastprobe_delay",
1770 MOD_PROTO_IP },
1771 { "arp_probe_interval", "_arp_probe_interval",
1772 MOD_PROTO_IP },
1773 { "arp_fastprobe_interval", "_arp_fastprobe_interval",
1774 MOD_PROTO_IP },
1775 { "arp_probe_count", "_arp_probe_count",
1776 MOD_PROTO_IP },
1777 { "arp_fastprobe_count", "_arp_fastprobe_count",
1778 MOD_PROTO_IP },
1779 { "arp_defend_interval", "_arp_defend_interval",
1780 MOD_PROTO_IP },
1781 { "arp_defend_rate", "_arp_defend_rate",
1782 MOD_PROTO_IP },
1783 { "arp_defend_period", "_arp_defend_period",
1784 MOD_PROTO_IP },
1785 { "ndp_defend_interval", "_ndp_defend_interval",
1786 MOD_PROTO_IP },
1787 { "ndp_defend_rate", "_ndp_defend_rate",
1788 MOD_PROTO_IP },
1789 { "ndp_defend_period", "_ndp_defend_period",
1790 MOD_PROTO_IP },
1791 { "igmp_max_version", "_igmp_max_version",
1792 MOD_PROTO_IP },
1793 { "mld_max_version", "_mld_max_version",
1794 MOD_PROTO_IP },
1795 { "ipsec_override_persocket_policy", "_ipsec_override_persocket_policy",
1796 MOD_PROTO_IP },
1797 { "ipsec_policy_log_interval", "_ipsec_policy_log_interval",
1798 MOD_PROTO_IP },
1799 { "icmp_accept_clear_messages", "_icmp_accept_clear_messages",
1800 MOD_PROTO_IP },
1801 { "igmp_accept_clear_messages", "_igmp_accept_clear_messages",
1802 MOD_PROTO_IP },
1803 { "pim_accept_clear_messages", "_pim_accept_clear_messages",
1804 MOD_PROTO_IP },
1805 { "ip_respond_to_echo_multicast", "_respond_to_echo_multicast",
1806 MOD_PROTO_IPV4 },
1807 { "ip_send_redirects", "_send_redirects",
1808 MOD_PROTO_IPV4 },
1809 { "ip_forward_src_routed", "_forward_src_routed",
1810 MOD_PROTO_IPV4 },
1811 { "ip_icmp_return_data_bytes", "_icmp_return_data_bytes",
1812 MOD_PROTO_IPV4 },
1813 { "ip_ignore_redirect", "_ignore_redirect",
1814 MOD_PROTO_IPV4 },
1815 { "ip_strict_dst_multihoming", "_strict_dst_multihoming",
1816 MOD_PROTO_IPV4 },
1817 { "ip_reasm_timeout", "_reasm_timeout",
1818 MOD_PROTO_IPV4 },
1819 { "ip_strict_src_multihoming", "_strict_src_multihoming",
1820 MOD_PROTO_IPV4 },
1821 { "ipv4_dad_announce_interval", "_dad_announce_interval",
1822 MOD_PROTO_IPV4 },
1823 { "ipv4_icmp_return_pmtu", "_icmp_return_pmtu",
1824 MOD_PROTO_IPV4 },
1825 { "ipv6_dad_announce_interval", "_dad_announce_interval",
1826 MOD_PROTO_IPV6 },
1827 { "ipv6_icmp_return_pmtu", "_icmp_return_pmtu",
1828 MOD_PROTO_IPV6 },
1829 { NULL, NULL, MOD_PROTO_NONE }
1833 * Following API returns a new property name in `nname' for the given legacy
1834 * property name in `oname'.
1837 ipadm_legacy2new_propname(const char *oname, char *nname, uint_t nnamelen,
1838 uint_t *proto)
1840 const char *str;
1841 ipadm_oname2nname_map_t *ionmp;
1843 /* if it's a public property, there is nothing to return */
1844 if (i_ipadm_get_prop_desc(oname, *proto, NULL) != NULL)
1845 return (-1);
1848 * we didn't find the `oname' in the table, check if the property
1849 * name begins with a leading protocol.
1851 str = oname;
1852 switch (*proto) {
1853 case MOD_PROTO_TCP:
1854 if (strstr(oname, "tcp_") == oname)
1855 str += strlen("tcp");
1856 break;
1857 case MOD_PROTO_SCTP:
1858 if (strstr(oname, "sctp_") == oname)
1859 str += strlen("sctp");
1860 break;
1861 case MOD_PROTO_UDP:
1862 if (strstr(oname, "udp_") == oname)
1863 str += strlen("udp");
1864 break;
1865 case MOD_PROTO_RAWIP:
1866 if (strstr(oname, "icmp_") == oname)
1867 str += strlen("icmp");
1868 break;
1869 case MOD_PROTO_IP:
1870 case MOD_PROTO_IPV4:
1871 case MOD_PROTO_IPV6:
1872 if (strstr(oname, "ip6_") == oname) {
1873 *proto = MOD_PROTO_IPV6;
1874 str += strlen("ip6");
1875 } else {
1876 for (ionmp = name_map; ionmp->iom_oname != NULL;
1877 ionmp++) {
1878 if (strcmp(oname, ionmp->iom_oname) == 0) {
1879 str = ionmp->iom_nname;
1880 *proto = ionmp->iom_proto;
1881 break;
1884 if (ionmp->iom_oname != NULL)
1885 break;
1887 if (strstr(oname, "ip_") == oname) {
1888 *proto = MOD_PROTO_IP;
1889 str += strlen("ip");
1892 break;
1893 default:
1894 return (-1);
1896 (void) snprintf(nname, nnamelen, "%s", str);
1897 return (0);