Print this page
NEX-7968 libipadm returns reversed value for standby interface property
Reviewed by: Dan Fields <dan.fields@nexenta.com>
OS-161: Integrate IPMP changes
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/libipadm/common/ipadm_prop.c
+++ new/usr/src/lib/libipadm/common/ipadm_prop.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
|
↓ open down ↓ |
10 lines elided |
↑ open up ↑ |
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
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 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
23 24 * Copyright (c) 2013 by Delphix. All rights reserved.
25 + * Copyright 2016 Nexenta Systems, Inc.
24 26 */
25 27
26 28 /*
27 29 * This file contains routines that are used to modify/retrieve protocol or
28 30 * interface property values. It also holds all the supported properties for
29 31 * both IP interface and protocols in `ipadm_prop_desc_t'. Following protocols
30 32 * are supported: IP, IPv4, IPv6, TCP, SCTP, UDP and ICMP.
31 33 *
32 34 * This file also contains walkers, which walks through the property table and
33 35 * calls the callback function, of the form `ipadm_prop_wfunc_t' , for every
34 36 * property in the table.
35 37 */
36 38
37 39 #include <unistd.h>
38 40 #include <errno.h>
39 41 #include <ctype.h>
40 42 #include <fcntl.h>
41 43 #include <strings.h>
42 44 #include <stdlib.h>
43 45 #include <netinet/in.h>
44 46 #include <arpa/inet.h>
45 47 #include <sys/sockio.h>
46 48 #include <assert.h>
47 49 #include <libdllink.h>
48 50 #include <zone.h>
49 51 #include "libipadm_impl.h"
50 52 #include <inet/tunables.h>
51 53
52 54 #define IPADM_NONESTR "none"
53 55 #define DEF_METRIC_VAL 0 /* default metric value */
54 56
55 57 #define A_CNT(arr) (sizeof (arr) / sizeof (arr[0]))
56 58
57 59 static ipadm_status_t i_ipadm_validate_if(ipadm_handle_t, const char *,
58 60 uint_t, uint_t);
59 61
60 62 /*
61 63 * Callback functions to retrieve property values from the kernel. These
62 64 * functions, when required, translate the values from the kernel to a format
63 65 * suitable for printing. For example: boolean values will be translated
64 66 * to on/off. They also retrieve DEFAULT, PERM and POSSIBLE values for
65 67 * a given property.
66 68 */
67 69 static ipadm_pd_getf_t i_ipadm_get_prop, i_ipadm_get_ifprop_flags,
68 70 i_ipadm_get_mtu, i_ipadm_get_metric,
69 71 i_ipadm_get_usesrc, i_ipadm_get_forwarding,
70 72 i_ipadm_get_ecnsack, i_ipadm_get_hostmodel;
71 73
72 74 /*
73 75 * Callback function to set property values. These functions translate the
74 76 * values to a format suitable for kernel consumption, allocates the necessary
75 77 * ioctl buffers and then invokes ioctl().
76 78 */
77 79 static ipadm_pd_setf_t i_ipadm_set_prop, i_ipadm_set_mtu,
78 80 i_ipadm_set_ifprop_flags,
79 81 i_ipadm_set_metric, i_ipadm_set_usesrc,
80 82 i_ipadm_set_forwarding, i_ipadm_set_eprivport,
81 83 i_ipadm_set_ecnsack, i_ipadm_set_hostmodel;
82 84
83 85 /* array of protocols we support */
84 86 static int protocols[] = { MOD_PROTO_IP, MOD_PROTO_RAWIP,
85 87 MOD_PROTO_TCP, MOD_PROTO_UDP,
86 88 MOD_PROTO_SCTP };
87 89
88 90 /*
89 91 * Supported IP protocol properties.
90 92 */
91 93 static ipadm_prop_desc_t ipadm_ip_prop_table[] = {
92 94 { "arp", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV4, 0,
93 95 i_ipadm_set_ifprop_flags, i_ipadm_get_onoff,
94 96 i_ipadm_get_ifprop_flags },
95 97
96 98 { "forwarding", NULL, IPADMPROP_CLASS_MODIF, MOD_PROTO_IPV4, 0,
97 99 i_ipadm_set_forwarding, i_ipadm_get_onoff,
98 100 i_ipadm_get_forwarding },
99 101
100 102 { "metric", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV4, 0,
101 103 i_ipadm_set_metric, NULL, i_ipadm_get_metric },
102 104
103 105 { "mtu", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV4, 0,
104 106 i_ipadm_set_mtu, i_ipadm_get_mtu, i_ipadm_get_mtu },
105 107
106 108 { "exchange_routes", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV4, 0,
107 109 i_ipadm_set_ifprop_flags, i_ipadm_get_onoff,
108 110 i_ipadm_get_ifprop_flags },
109 111
110 112 { "usesrc", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV4, 0,
111 113 i_ipadm_set_usesrc, NULL, i_ipadm_get_usesrc },
112 114
113 115 { "ttl", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_IPV4, 0,
114 116 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
115 117
116 118 { "forwarding", NULL, IPADMPROP_CLASS_MODIF, MOD_PROTO_IPV6, 0,
117 119 i_ipadm_set_forwarding, i_ipadm_get_onoff,
118 120 i_ipadm_get_forwarding },
119 121
120 122 { "hoplimit", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_IPV6, 0,
121 123 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
122 124
123 125 { "metric", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV6, 0,
124 126 i_ipadm_set_metric, NULL, i_ipadm_get_metric },
125 127
126 128 { "mtu", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV6, 0,
127 129 i_ipadm_set_mtu, i_ipadm_get_mtu, i_ipadm_get_mtu },
128 130
129 131 { "nud", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV6, 0,
130 132 i_ipadm_set_ifprop_flags, i_ipadm_get_onoff,
131 133 i_ipadm_get_ifprop_flags },
132 134
133 135 { "exchange_routes", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV6, 0,
134 136 i_ipadm_set_ifprop_flags, i_ipadm_get_onoff,
135 137 i_ipadm_get_ifprop_flags },
136 138
137 139 { "usesrc", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IPV6, 0,
|
↓ open down ↓ |
104 lines elided |
↑ open up ↑ |
138 140 i_ipadm_set_usesrc, NULL, i_ipadm_get_usesrc },
139 141
140 142 { "hostmodel", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_IPV6, 0,
141 143 i_ipadm_set_hostmodel, i_ipadm_get_hostmodel,
142 144 i_ipadm_get_hostmodel },
143 145
144 146 { "hostmodel", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_IPV4, 0,
145 147 i_ipadm_set_hostmodel, i_ipadm_get_hostmodel,
146 148 i_ipadm_get_hostmodel },
147 149
150 + { "standby", NULL, IPADMPROP_CLASS_IF, MOD_PROTO_IP, 0,
151 + i_ipadm_set_ifprop_flags, i_ipadm_get_onoff,
152 + i_ipadm_get_ifprop_flags },
153 +
154 +
148 155 { NULL, NULL, 0, 0, 0, NULL, NULL, NULL }
149 156 };
150 157
151 158 /* possible values for TCP properties `ecn' and `sack' */
152 159 static const char *ecn_sack_vals[] = {"never", "passive", "active", NULL};
153 160
154 161 /* Supported TCP protocol properties */
155 162 static ipadm_prop_desc_t ipadm_tcp_prop_table[] = {
156 163 { "ecn", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP, 0,
157 164 i_ipadm_set_ecnsack, i_ipadm_get_ecnsack, i_ipadm_get_ecnsack },
158 165
159 166 { "extra_priv_ports", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP,
160 167 IPADMPROP_MULVAL, i_ipadm_set_eprivport, i_ipadm_get_prop,
161 168 i_ipadm_get_prop },
162 169
163 170 { "largest_anon_port", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP, 0,
164 171 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
165 172
166 173 { "max_buf", "_max_buf", IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP, 0,
167 174 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
168 175
169 176 { "recv_buf", "recv_maxbuf", IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP, 0,
170 177 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
171 178
172 179 { "sack", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP, 0,
173 180 i_ipadm_set_ecnsack, i_ipadm_get_ecnsack, i_ipadm_get_ecnsack },
174 181
175 182 { "send_buf", "send_maxbuf", IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP, 0,
176 183 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
177 184
178 185 { "smallest_anon_port", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP, 0,
179 186 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
180 187
181 188 { "smallest_nonpriv_port", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_TCP,
182 189 0, i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
183 190
184 191 { NULL, NULL, 0, 0, 0, NULL, NULL, NULL }
185 192 };
186 193
187 194 /* Supported UDP protocol properties */
188 195 static ipadm_prop_desc_t ipadm_udp_prop_table[] = {
189 196 { "extra_priv_ports", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_UDP,
190 197 IPADMPROP_MULVAL, i_ipadm_set_eprivport, i_ipadm_get_prop,
191 198 i_ipadm_get_prop },
192 199
193 200 { "largest_anon_port", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_UDP, 0,
194 201 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
195 202
196 203 { "max_buf", "_max_buf", IPADMPROP_CLASS_MODULE, MOD_PROTO_UDP, 0,
197 204 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
198 205
199 206 { "recv_buf", "recv_maxbuf", IPADMPROP_CLASS_MODULE, MOD_PROTO_UDP, 0,
200 207 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
201 208
202 209 { "send_buf", "send_maxbuf", IPADMPROP_CLASS_MODULE, MOD_PROTO_UDP, 0,
203 210 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
204 211
205 212 { "smallest_anon_port", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_UDP, 0,
206 213 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
207 214
208 215 { "smallest_nonpriv_port", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_UDP,
209 216 0, i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
210 217
211 218 { NULL, NULL, 0, 0, 0, NULL, NULL, NULL }
212 219 };
213 220
214 221 /* Supported SCTP protocol properties */
215 222 static ipadm_prop_desc_t ipadm_sctp_prop_table[] = {
216 223 { "extra_priv_ports", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_SCTP,
217 224 IPADMPROP_MULVAL, i_ipadm_set_eprivport, i_ipadm_get_prop,
218 225 i_ipadm_get_prop },
219 226
220 227 { "largest_anon_port", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_SCTP, 0,
221 228 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
222 229
223 230 { "max_buf", "_max_buf", IPADMPROP_CLASS_MODULE, MOD_PROTO_SCTP, 0,
224 231 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
225 232
226 233 { "recv_buf", "recv_maxbuf", IPADMPROP_CLASS_MODULE, MOD_PROTO_SCTP, 0,
227 234 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
228 235
229 236 { "send_buf", "send_maxbuf", IPADMPROP_CLASS_MODULE, MOD_PROTO_SCTP, 0,
230 237 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
231 238
232 239 { "smallest_anon_port", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_SCTP, 0,
233 240 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
234 241
235 242 { "smallest_nonpriv_port", NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_SCTP,
236 243 0, i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
237 244
238 245 { NULL, NULL, 0, 0, 0, NULL, NULL, NULL }
239 246 };
240 247
241 248 /* Supported ICMP protocol properties */
242 249 static ipadm_prop_desc_t ipadm_icmp_prop_table[] = {
243 250 { "max_buf", "_max_buf", IPADMPROP_CLASS_MODULE, MOD_PROTO_RAWIP, 0,
244 251 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
245 252
246 253 { "recv_buf", "recv_maxbuf", IPADMPROP_CLASS_MODULE, MOD_PROTO_RAWIP, 0,
247 254 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
248 255
249 256 { "send_buf", "send_maxbuf", IPADMPROP_CLASS_MODULE, MOD_PROTO_RAWIP, 0,
250 257 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop },
251 258
252 259 { NULL, NULL, 0, 0, 0, NULL, NULL, NULL }
253 260 };
254 261
255 262 /*
256 263 * A dummy private property structure, used while handling private
257 264 * protocol properties (properties not yet supported by libipadm).
258 265 */
259 266 static ipadm_prop_desc_t ipadm_privprop =
260 267 { NULL, NULL, IPADMPROP_CLASS_MODULE, MOD_PROTO_NONE, 0,
261 268 i_ipadm_set_prop, i_ipadm_get_prop, i_ipadm_get_prop };
262 269
263 270 /*
264 271 * Returns the property description table, for the given protocol
265 272 */
266 273 static ipadm_prop_desc_t *
267 274 i_ipadm_get_propdesc_table(uint_t proto)
268 275 {
269 276 switch (proto) {
270 277 case MOD_PROTO_IP:
271 278 case MOD_PROTO_IPV4:
272 279 case MOD_PROTO_IPV6:
273 280 return (ipadm_ip_prop_table);
274 281 case MOD_PROTO_RAWIP:
275 282 return (ipadm_icmp_prop_table);
276 283 case MOD_PROTO_TCP:
277 284 return (ipadm_tcp_prop_table);
278 285 case MOD_PROTO_UDP:
279 286 return (ipadm_udp_prop_table);
280 287 case MOD_PROTO_SCTP:
281 288 return (ipadm_sctp_prop_table);
282 289 }
283 290
284 291 return (NULL);
285 292 }
286 293
287 294 static ipadm_prop_desc_t *
288 295 i_ipadm_get_prop_desc(const char *pname, uint_t proto, int *errp)
289 296 {
290 297 int err = 0;
291 298 boolean_t matched_name = B_FALSE;
292 299 ipadm_prop_desc_t *ipdp = NULL, *ipdtbl;
293 300
294 301 if ((ipdtbl = i_ipadm_get_propdesc_table(proto)) == NULL) {
295 302 err = EINVAL;
296 303 goto ret;
297 304 }
298 305
299 306 for (ipdp = ipdtbl; ipdp->ipd_name != NULL; ipdp++) {
300 307 if (strcmp(pname, ipdp->ipd_name) == 0 ||
301 308 (ipdp->ipd_old_name != NULL &&
302 309 strcmp(pname, ipdp->ipd_old_name) == 0)) {
303 310 matched_name = B_TRUE;
304 311 if (ipdp->ipd_proto == proto)
305 312 break;
306 313 }
307 314 }
308 315
309 316 if (ipdp->ipd_name == NULL) {
310 317 err = ENOENT;
311 318 /* if we matched name, but failed protocol check */
312 319 if (matched_name)
313 320 err = EPROTO;
314 321 ipdp = NULL;
315 322 }
316 323 ret:
317 324 if (errp != NULL)
318 325 *errp = err;
319 326 return (ipdp);
320 327 }
321 328
322 329 char *
323 330 ipadm_proto2str(uint_t proto)
324 331 {
325 332 switch (proto) {
326 333 case MOD_PROTO_IP:
327 334 return ("ip");
328 335 case MOD_PROTO_IPV4:
329 336 return ("ipv4");
330 337 case MOD_PROTO_IPV6:
331 338 return ("ipv6");
332 339 case MOD_PROTO_RAWIP:
333 340 return ("icmp");
334 341 case MOD_PROTO_TCP:
335 342 return ("tcp");
336 343 case MOD_PROTO_UDP:
337 344 return ("udp");
338 345 case MOD_PROTO_SCTP:
339 346 return ("sctp");
340 347 }
341 348
342 349 return (NULL);
343 350 }
344 351
345 352 uint_t
346 353 ipadm_str2proto(const char *protostr)
347 354 {
348 355 if (protostr == NULL)
349 356 return (MOD_PROTO_NONE);
350 357 if (strcmp(protostr, "tcp") == 0)
351 358 return (MOD_PROTO_TCP);
352 359 else if (strcmp(protostr, "udp") == 0)
353 360 return (MOD_PROTO_UDP);
354 361 else if (strcmp(protostr, "ip") == 0)
355 362 return (MOD_PROTO_IP);
356 363 else if (strcmp(protostr, "ipv4") == 0)
357 364 return (MOD_PROTO_IPV4);
358 365 else if (strcmp(protostr, "ipv6") == 0)
359 366 return (MOD_PROTO_IPV6);
360 367 else if (strcmp(protostr, "icmp") == 0)
361 368 return (MOD_PROTO_RAWIP);
362 369 else if (strcmp(protostr, "sctp") == 0)
363 370 return (MOD_PROTO_SCTP);
364 371 else if (strcmp(protostr, "arp") == 0)
365 372 return (MOD_PROTO_IP);
366 373
367 374 return (MOD_PROTO_NONE);
368 375 }
369 376
370 377 /* ARGSUSED */
371 378 static ipadm_status_t
372 379 i_ipadm_set_mtu(ipadm_handle_t iph, const void *arg,
373 380 ipadm_prop_desc_t *pdp, const void *pval, uint_t proto, uint_t flags)
374 381 {
375 382 struct lifreq lifr;
376 383 char *endp;
377 384 uint_t mtu;
378 385 int s;
379 386 const char *ifname = arg;
380 387 char val[MAXPROPVALLEN];
381 388
382 389 /* to reset MTU first retrieve the default MTU and then set it */
383 390 if (flags & IPADM_OPT_DEFAULT) {
384 391 ipadm_status_t status;
385 392 uint_t size = MAXPROPVALLEN;
386 393
387 394 status = i_ipadm_get_prop(iph, arg, pdp, val, &size,
388 395 proto, MOD_PROP_DEFAULT);
389 396 if (status != IPADM_SUCCESS)
390 397 return (status);
391 398 pval = val;
392 399 }
393 400
394 401 errno = 0;
395 402 mtu = (uint_t)strtol(pval, &endp, 10);
396 403 if (errno != 0 || *endp != '\0')
397 404 return (IPADM_INVALID_ARG);
398 405
399 406 bzero(&lifr, sizeof (lifr));
400 407 (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
401 408 lifr.lifr_mtu = mtu;
402 409
403 410 s = (proto == MOD_PROTO_IPV6 ? iph->iph_sock6 : iph->iph_sock);
404 411 if (ioctl(s, SIOCSLIFMTU, (caddr_t)&lifr) < 0)
405 412 return (ipadm_errno2status(errno));
406 413
407 414 return (IPADM_SUCCESS);
408 415 }
409 416
410 417 /* ARGSUSED */
411 418 static ipadm_status_t
412 419 i_ipadm_set_metric(ipadm_handle_t iph, const void *arg,
413 420 ipadm_prop_desc_t *pdp, const void *pval, uint_t proto, uint_t flags)
414 421 {
415 422 struct lifreq lifr;
416 423 char *endp;
417 424 int metric;
418 425 const char *ifname = arg;
419 426 int s;
420 427
421 428 /* if we are resetting, set the value to its default value */
422 429 if (flags & IPADM_OPT_DEFAULT) {
423 430 metric = DEF_METRIC_VAL;
424 431 } else {
425 432 errno = 0;
426 433 metric = (uint_t)strtol(pval, &endp, 10);
427 434 if (errno != 0 || *endp != '\0')
428 435 return (IPADM_INVALID_ARG);
429 436 }
430 437
431 438 bzero(&lifr, sizeof (lifr));
432 439 (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
433 440 lifr.lifr_metric = metric;
434 441
435 442 s = (proto == MOD_PROTO_IPV6 ? iph->iph_sock6 : iph->iph_sock);
436 443
437 444 if (ioctl(s, SIOCSLIFMETRIC, (caddr_t)&lifr) < 0)
438 445 return (ipadm_errno2status(errno));
439 446
440 447 return (IPADM_SUCCESS);
441 448 }
442 449
443 450 /* ARGSUSED */
444 451 static ipadm_status_t
445 452 i_ipadm_set_usesrc(ipadm_handle_t iph, const void *arg,
446 453 ipadm_prop_desc_t *pdp, const void *pval, uint_t proto, uint_t flags)
447 454 {
448 455 struct lifreq lifr;
449 456 const char *ifname = arg;
450 457 int s;
451 458 uint_t ifindex = 0;
452 459
453 460 /* if we are resetting, set the value to its default value */
454 461 if (flags & IPADM_OPT_DEFAULT)
455 462 pval = IPADM_NONESTR;
456 463
457 464 /*
458 465 * cannot specify logical interface name. We can also filter out other
459 466 * bogus interface names here itself through i_ipadm_validate_ifname().
460 467 */
461 468 if (strcmp(pval, IPADM_NONESTR) != 0 &&
462 469 !i_ipadm_validate_ifname(iph, pval))
463 470 return (IPADM_INVALID_ARG);
464 471
465 472 bzero(&lifr, sizeof (lifr));
466 473 (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
467 474
468 475 s = (proto == MOD_PROTO_IPV6 ? iph->iph_sock6 : iph->iph_sock);
469 476
470 477 if (strcmp(pval, IPADM_NONESTR) != 0) {
471 478 if ((ifindex = if_nametoindex(pval)) == 0)
472 479 return (ipadm_errno2status(errno));
473 480 lifr.lifr_index = ifindex;
474 481 } else {
475 482 if (ioctl(s, SIOCGLIFUSESRC, (caddr_t)&lifr) < 0)
476 483 return (ipadm_errno2status(errno));
477 484 lifr.lifr_index = 0;
478 485 }
479 486 if (ioctl(s, SIOCSLIFUSESRC, (caddr_t)&lifr) < 0)
480 487 return (ipadm_errno2status(errno));
481 488
482 489 return (IPADM_SUCCESS);
483 490 }
484 491
485 492 static struct hostmodel_strval {
486 493 char *esm_str;
487 494 ip_hostmodel_t esm_val;
488 495 } esm_arr[] = {
489 496 {"weak", IP_WEAK_ES},
490 497 {"src-priority", IP_SRC_PRI_ES},
491 498 {"strong", IP_STRONG_ES},
492 499 {"custom", IP_MAXVAL_ES}
493 500 };
494 501
495 502 static ip_hostmodel_t
496 503 i_ipadm_hostmodel_str2val(const char *pval)
497 504 {
498 505 int i;
499 506
500 507 for (i = 0; i < A_CNT(esm_arr); i++) {
501 508 if (esm_arr[i].esm_str != NULL &&
502 509 strcmp(pval, esm_arr[i].esm_str) == 0) {
503 510 return (esm_arr[i].esm_val);
504 511 }
505 512 }
506 513 return (IP_MAXVAL_ES);
507 514 }
508 515
509 516 static char *
510 517 i_ipadm_hostmodel_val2str(ip_hostmodel_t pval)
511 518 {
512 519 int i;
513 520
514 521 for (i = 0; i < A_CNT(esm_arr); i++) {
515 522 if (esm_arr[i].esm_val == pval)
516 523 return (esm_arr[i].esm_str);
517 524 }
518 525 return (NULL);
519 526 }
520 527
521 528 /* ARGSUSED */
522 529 static ipadm_status_t
523 530 i_ipadm_set_hostmodel(ipadm_handle_t iph, const void *arg,
524 531 ipadm_prop_desc_t *pdp, const void *pval, uint_t proto, uint_t flags)
525 532 {
526 533 ip_hostmodel_t hostmodel;
527 534 char val[11]; /* covers uint32_max as a string */
528 535
529 536 if ((flags & IPADM_OPT_DEFAULT) == 0) {
530 537 hostmodel = i_ipadm_hostmodel_str2val(pval);
531 538 if (hostmodel == IP_MAXVAL_ES)
532 539 return (IPADM_INVALID_ARG);
533 540 (void) snprintf(val, sizeof (val), "%d", hostmodel);
534 541 pval = val;
535 542 }
536 543 return (i_ipadm_set_prop(iph, NULL, pdp, pval, proto, flags));
537 544 }
538 545
539 546 /* ARGSUSED */
540 547 static ipadm_status_t
541 548 i_ipadm_get_hostmodel(ipadm_handle_t iph, const void *arg,
542 549 ipadm_prop_desc_t *pdp, char *buf, uint_t *bufsize, uint_t proto,
543 550 uint_t valtype)
544 551 {
545 552 ip_hostmodel_t hostmodel;
546 553 char *cp;
547 554 size_t nbytes;
548 555 ipadm_status_t status;
549 556
550 557 switch (valtype) {
551 558 case MOD_PROP_PERM:
552 559 nbytes = snprintf(buf, *bufsize, "%d", MOD_PROP_PERM_RW);
553 560 break;
554 561 case MOD_PROP_DEFAULT:
555 562 nbytes = snprintf(buf, *bufsize, "weak");
556 563 break;
557 564 case MOD_PROP_ACTIVE:
558 565 status = i_ipadm_get_prop(iph, arg, pdp, buf, bufsize, proto,
559 566 valtype);
560 567 if (status != IPADM_SUCCESS)
561 568 return (status);
562 569 bcopy(buf, &hostmodel, sizeof (hostmodel));
563 570 cp = i_ipadm_hostmodel_val2str(hostmodel);
564 571 nbytes = snprintf(buf, *bufsize, "%s",
565 572 (cp != NULL ? cp : "?"));
566 573 break;
567 574 case MOD_PROP_POSSIBLE:
568 575 nbytes = snprintf(buf, *bufsize, "strong,src-priority,weak");
569 576 break;
570 577 default:
571 578 return (IPADM_INVALID_ARG);
572 579 }
573 580 if (nbytes >= *bufsize) {
574 581 /* insufficient buffer space */
575 582 *bufsize = nbytes + 1;
576 583 return (IPADM_NO_BUFS);
577 584 }
578 585 return (IPADM_SUCCESS);
579 586 }
580 587
581 588 /* ARGSUSED */
582 589 static ipadm_status_t
583 590 i_ipadm_set_ifprop_flags(ipadm_handle_t iph, const void *arg,
584 591 ipadm_prop_desc_t *pdp, const void *pval, uint_t proto, uint_t flags)
585 592 {
586 593 ipadm_status_t status = IPADM_SUCCESS;
587 594 const char *ifname = arg;
|
↓ open down ↓ |
430 lines elided |
↑ open up ↑ |
588 595 uint64_t on_flags = 0, off_flags = 0;
589 596 boolean_t on = B_FALSE;
590 597 sa_family_t af = (proto == MOD_PROTO_IPV6 ? AF_INET6 : AF_INET);
591 598
592 599 /* if we are resetting, set the value to its default value */
593 600 if (flags & IPADM_OPT_DEFAULT) {
594 601 if (strcmp(pdp->ipd_name, "exchange_routes") == 0 ||
595 602 strcmp(pdp->ipd_name, "arp") == 0 ||
596 603 strcmp(pdp->ipd_name, "nud") == 0) {
597 604 pval = IPADM_ONSTR;
598 - } else if (strcmp(pdp->ipd_name, "forwarding") == 0) {
605 + } else if (strcmp(pdp->ipd_name, "forwarding") == 0 ||
606 + strcmp(pdp->ipd_name, "standby") == 0) {
599 607 pval = IPADM_OFFSTR;
600 608 } else {
601 609 return (IPADM_PROP_UNKNOWN);
602 610 }
603 611 }
604 612
605 613 if (strcmp(pval, IPADM_ONSTR) == 0)
606 614 on = B_TRUE;
607 615 else if (strcmp(pval, IPADM_OFFSTR) == 0)
608 616 on = B_FALSE;
609 617 else
610 618 return (IPADM_INVALID_ARG);
611 619
612 620 if (strcmp(pdp->ipd_name, "exchange_routes") == 0) {
613 621 if (on)
614 622 off_flags = IFF_NORTEXCH;
615 623 else
616 624 on_flags = IFF_NORTEXCH;
617 625 } else if (strcmp(pdp->ipd_name, "arp") == 0) {
618 626 if (on)
619 627 off_flags = IFF_NOARP;
620 628 else
621 629 on_flags = IFF_NOARP;
|
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
622 630 } else if (strcmp(pdp->ipd_name, "nud") == 0) {
623 631 if (on)
624 632 off_flags = IFF_NONUD;
625 633 else
626 634 on_flags = IFF_NONUD;
627 635 } else if (strcmp(pdp->ipd_name, "forwarding") == 0) {
628 636 if (on)
629 637 on_flags = IFF_ROUTER;
630 638 else
631 639 off_flags = IFF_ROUTER;
640 + } else if (strcmp(pdp->ipd_name, "standby") == 0) {
641 + if (on)
642 + on_flags = IFF_STANDBY;
643 + else
644 + off_flags = IFF_STANDBY;
632 645 }
633 646
634 647 if (on_flags || off_flags) {
635 648 status = i_ipadm_set_flags(iph, ifname, af, on_flags,
636 649 off_flags);
637 650 }
638 651 return (status);
639 652 }
640 653
641 654 /* ARGSUSED */
642 655 static ipadm_status_t
643 656 i_ipadm_set_eprivport(ipadm_handle_t iph, const void *arg,
644 657 ipadm_prop_desc_t *pdp, const void *pval, uint_t proto, uint_t flags)
645 658 {
646 659 nvlist_t *portsnvl = NULL;
647 660 nvpair_t *nvp;
648 661 ipadm_status_t status = IPADM_SUCCESS;
649 662 int err;
650 663 uint_t count = 0;
651 664
652 665 if (flags & IPADM_OPT_DEFAULT) {
653 666 assert(pval == NULL);
654 667 return (i_ipadm_set_prop(iph, arg, pdp, pval, proto, flags));
655 668 }
656 669
657 670 if ((err = ipadm_str2nvlist(pval, &portsnvl, IPADM_NORVAL)) != 0)
658 671 return (ipadm_errno2status(err));
659 672
660 673 /* count the number of ports */
661 674 for (nvp = nvlist_next_nvpair(portsnvl, NULL); nvp != NULL;
662 675 nvp = nvlist_next_nvpair(portsnvl, nvp)) {
663 676 ++count;
664 677 }
665 678
666 679 if (iph->iph_flags & IPH_INIT) {
667 680 flags |= IPADM_OPT_APPEND;
668 681 } else if (count > 1) {
669 682 /*
670 683 * We allow only one port to be added, removed or
671 684 * assigned at a time.
672 685 *
673 686 * However on reboot, while initializing protocol
674 687 * properties, extra_priv_ports might have multiple
675 688 * values. Only in that case we allow setting multiple
676 689 * values.
677 690 */
678 691 nvlist_free(portsnvl);
679 692 return (IPADM_INVALID_ARG);
680 693 }
681 694
682 695 for (nvp = nvlist_next_nvpair(portsnvl, NULL); nvp != NULL;
683 696 nvp = nvlist_next_nvpair(portsnvl, nvp)) {
684 697 status = i_ipadm_set_prop(iph, arg, pdp, nvpair_name(nvp),
685 698 proto, flags);
686 699 if (status != IPADM_SUCCESS)
687 700 break;
688 701 }
689 702 nvlist_free(portsnvl);
690 703 return (status);
691 704 }
692 705
693 706 /* ARGSUSED */
694 707 static ipadm_status_t
695 708 i_ipadm_set_forwarding(ipadm_handle_t iph, const void *arg,
696 709 ipadm_prop_desc_t *pdp, const void *pval, uint_t proto, uint_t flags)
697 710 {
698 711 const char *ifname = arg;
699 712 ipadm_status_t status;
700 713
701 714 /*
702 715 * if interface name is provided, then set forwarding using the
703 716 * IFF_ROUTER flag
704 717 */
705 718 if (ifname != NULL) {
706 719 status = i_ipadm_set_ifprop_flags(iph, ifname, pdp, pval,
707 720 proto, flags);
708 721 } else {
709 722 char *val = NULL;
710 723
711 724 /*
712 725 * if the caller is IPH_LEGACY, `pval' already contains
713 726 * numeric values.
714 727 */
715 728 if (!(flags & IPADM_OPT_DEFAULT) &&
716 729 !(iph->iph_flags & IPH_LEGACY)) {
717 730
718 731 if (strcmp(pval, IPADM_ONSTR) == 0)
719 732 val = "1";
720 733 else if (strcmp(pval, IPADM_OFFSTR) == 0)
721 734 val = "0";
722 735 else
723 736 return (IPADM_INVALID_ARG);
724 737 pval = val;
725 738 }
726 739
727 740 status = i_ipadm_set_prop(iph, ifname, pdp, pval, proto, flags);
728 741 }
729 742
730 743 return (status);
731 744 }
732 745
733 746 /* ARGSUSED */
734 747 static ipadm_status_t
735 748 i_ipadm_set_ecnsack(ipadm_handle_t iph, const void *arg,
736 749 ipadm_prop_desc_t *pdp, const void *pval, uint_t proto, uint_t flags)
737 750 {
738 751 uint_t i;
739 752 char val[MAXPROPVALLEN];
740 753
741 754 /* if IPH_LEGACY is set, `pval' already contains numeric values */
742 755 if (!(flags & IPADM_OPT_DEFAULT) && !(iph->iph_flags & IPH_LEGACY)) {
743 756 for (i = 0; ecn_sack_vals[i] != NULL; i++) {
744 757 if (strcmp(pval, ecn_sack_vals[i]) == 0)
745 758 break;
746 759 }
747 760 if (ecn_sack_vals[i] == NULL)
748 761 return (IPADM_INVALID_ARG);
749 762 (void) snprintf(val, MAXPROPVALLEN, "%d", i);
750 763 pval = val;
751 764 }
752 765
753 766 return (i_ipadm_set_prop(iph, arg, pdp, pval, proto, flags));
754 767 }
755 768
756 769 /* ARGSUSED */
757 770 ipadm_status_t
758 771 i_ipadm_get_ecnsack(ipadm_handle_t iph, const void *arg,
759 772 ipadm_prop_desc_t *pdp, char *buf, uint_t *bufsize, uint_t proto,
760 773 uint_t valtype)
761 774 {
762 775 ipadm_status_t status = IPADM_SUCCESS;
763 776 uint_t i, nbytes = 0;
764 777
765 778 switch (valtype) {
766 779 case MOD_PROP_POSSIBLE:
767 780 for (i = 0; ecn_sack_vals[i] != NULL; i++) {
768 781 if (i == 0)
769 782 nbytes += snprintf(buf + nbytes,
770 783 *bufsize - nbytes, "%s", ecn_sack_vals[i]);
771 784 else
772 785 nbytes += snprintf(buf + nbytes,
773 786 *bufsize - nbytes, ",%s", ecn_sack_vals[i]);
774 787 if (nbytes >= *bufsize)
775 788 break;
776 789 }
777 790 break;
778 791 case MOD_PROP_PERM:
779 792 case MOD_PROP_DEFAULT:
780 793 case MOD_PROP_ACTIVE:
781 794 status = i_ipadm_get_prop(iph, arg, pdp, buf, bufsize, proto,
782 795 valtype);
783 796
784 797 /*
785 798 * If IPH_LEGACY is set, do not convert the value returned
786 799 * from kernel,
787 800 */
788 801 if (iph->iph_flags & IPH_LEGACY)
789 802 break;
790 803
791 804 /*
792 805 * For current and default value, convert the value returned
793 806 * from kernel to more discrete representation.
794 807 */
795 808 if (status == IPADM_SUCCESS && (valtype == MOD_PROP_ACTIVE ||
796 809 valtype == MOD_PROP_DEFAULT)) {
797 810 i = atoi(buf);
798 811 assert(i < 3);
799 812 nbytes = snprintf(buf, *bufsize, "%s",
800 813 ecn_sack_vals[i]);
801 814 }
802 815 break;
803 816 default:
804 817 return (IPADM_INVALID_ARG);
805 818 }
806 819 if (nbytes >= *bufsize) {
807 820 /* insufficient buffer space */
808 821 *bufsize = nbytes + 1;
809 822 return (IPADM_NO_BUFS);
810 823 }
811 824
812 825 return (status);
813 826 }
814 827
815 828 /* ARGSUSED */
816 829 static ipadm_status_t
817 830 i_ipadm_get_forwarding(ipadm_handle_t iph, const void *arg,
818 831 ipadm_prop_desc_t *pdp, char *buf, uint_t *bufsize, uint_t proto,
819 832 uint_t valtype)
820 833 {
821 834 const char *ifname = arg;
822 835 ipadm_status_t status = IPADM_SUCCESS;
823 836
824 837 /*
825 838 * if interface name is provided, then get forwarding status using
826 839 * SIOCGLIFFLAGS
827 840 */
828 841 if (ifname != NULL) {
829 842 status = i_ipadm_get_ifprop_flags(iph, ifname, pdp,
830 843 buf, bufsize, pdp->ipd_proto, valtype);
831 844 } else {
832 845 status = i_ipadm_get_prop(iph, ifname, pdp, buf,
833 846 bufsize, proto, valtype);
834 847 /*
835 848 * If IPH_LEGACY is set, do not convert the value returned
836 849 * from kernel,
837 850 */
838 851 if (iph->iph_flags & IPH_LEGACY)
839 852 goto ret;
840 853 if (status == IPADM_SUCCESS && (valtype == MOD_PROP_ACTIVE ||
841 854 valtype == MOD_PROP_DEFAULT)) {
842 855 uint_t val = atoi(buf);
843 856
844 857 (void) snprintf(buf, *bufsize,
845 858 (val == 1 ? IPADM_ONSTR : IPADM_OFFSTR));
846 859 }
847 860 }
848 861
849 862 ret:
850 863 return (status);
851 864 }
852 865
853 866 /* ARGSUSED */
854 867 static ipadm_status_t
855 868 i_ipadm_get_mtu(ipadm_handle_t iph, const void *arg,
856 869 ipadm_prop_desc_t *pdp, char *buf, uint_t *bufsize, uint_t proto,
857 870 uint_t valtype)
858 871 {
859 872 struct lifreq lifr;
860 873 const char *ifname = arg;
861 874 size_t nbytes;
862 875 int s;
863 876
864 877 switch (valtype) {
865 878 case MOD_PROP_PERM:
866 879 nbytes = snprintf(buf, *bufsize, "%d", MOD_PROP_PERM_RW);
867 880 break;
868 881 case MOD_PROP_DEFAULT:
869 882 case MOD_PROP_POSSIBLE:
870 883 return (i_ipadm_get_prop(iph, arg, pdp, buf, bufsize,
871 884 proto, valtype));
872 885 case MOD_PROP_ACTIVE:
873 886 bzero(&lifr, sizeof (lifr));
874 887 (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
875 888 s = (proto == MOD_PROTO_IPV6 ? iph->iph_sock6 : iph->iph_sock);
876 889
877 890 if (ioctl(s, SIOCGLIFMTU, (caddr_t)&lifr) < 0)
878 891 return (ipadm_errno2status(errno));
879 892 nbytes = snprintf(buf, *bufsize, "%u", lifr.lifr_mtu);
880 893 break;
881 894 default:
882 895 return (IPADM_INVALID_ARG);
883 896 }
884 897 if (nbytes >= *bufsize) {
885 898 /* insufficient buffer space */
886 899 *bufsize = nbytes + 1;
887 900 return (IPADM_NO_BUFS);
888 901 }
889 902 return (IPADM_SUCCESS);
890 903 }
891 904
892 905 /* ARGSUSED */
893 906 static ipadm_status_t
894 907 i_ipadm_get_metric(ipadm_handle_t iph, const void *arg,
895 908 ipadm_prop_desc_t *pdp, char *buf, uint_t *bufsize, uint_t proto,
896 909 uint_t valtype)
897 910 {
898 911 struct lifreq lifr;
899 912 const char *ifname = arg;
900 913 size_t nbytes;
901 914 int s, val;
902 915
903 916 switch (valtype) {
904 917 case MOD_PROP_PERM:
905 918 val = MOD_PROP_PERM_RW;
906 919 break;
907 920 case MOD_PROP_DEFAULT:
908 921 val = DEF_METRIC_VAL;
909 922 break;
910 923 case MOD_PROP_ACTIVE:
911 924 bzero(&lifr, sizeof (lifr));
912 925 (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
913 926
914 927 s = (proto == MOD_PROTO_IPV6 ? iph->iph_sock6 : iph->iph_sock);
915 928 if (ioctl(s, SIOCGLIFMETRIC, (caddr_t)&lifr) < 0)
916 929 return (ipadm_errno2status(errno));
917 930 val = lifr.lifr_metric;
918 931 break;
919 932 default:
920 933 return (IPADM_INVALID_ARG);
921 934 }
922 935 nbytes = snprintf(buf, *bufsize, "%d", val);
923 936 if (nbytes >= *bufsize) {
924 937 /* insufficient buffer space */
925 938 *bufsize = nbytes + 1;
926 939 return (IPADM_NO_BUFS);
927 940 }
928 941
929 942 return (IPADM_SUCCESS);
930 943 }
931 944
932 945 /* ARGSUSED */
933 946 static ipadm_status_t
934 947 i_ipadm_get_usesrc(ipadm_handle_t iph, const void *arg,
935 948 ipadm_prop_desc_t *ipd, char *buf, uint_t *bufsize, uint_t proto,
936 949 uint_t valtype)
937 950 {
938 951 struct lifreq lifr;
939 952 const char *ifname = arg;
940 953 int s;
941 954 char if_name[IF_NAMESIZE];
942 955 size_t nbytes;
943 956
944 957 switch (valtype) {
945 958 case MOD_PROP_PERM:
946 959 nbytes = snprintf(buf, *bufsize, "%d", MOD_PROP_PERM_RW);
947 960 break;
948 961 case MOD_PROP_DEFAULT:
949 962 nbytes = snprintf(buf, *bufsize, "%s", IPADM_NONESTR);
950 963 break;
951 964 case MOD_PROP_ACTIVE:
952 965 bzero(&lifr, sizeof (lifr));
953 966 (void) strlcpy(lifr.lifr_name, ifname, sizeof (lifr.lifr_name));
954 967
955 968 s = (proto == MOD_PROTO_IPV6 ? iph->iph_sock6 : iph->iph_sock);
956 969 if (ioctl(s, SIOCGLIFUSESRC, (caddr_t)&lifr) < 0)
957 970 return (ipadm_errno2status(errno));
958 971 if (lifr.lifr_index == 0) {
959 972 /* no src address was set, so print 'none' */
960 973 (void) strlcpy(if_name, IPADM_NONESTR,
961 974 sizeof (if_name));
962 975 } else if (if_indextoname(lifr.lifr_index, if_name) == NULL) {
963 976 return (ipadm_errno2status(errno));
964 977 }
965 978 nbytes = snprintf(buf, *bufsize, "%s", if_name);
966 979 break;
967 980 default:
968 981 return (IPADM_INVALID_ARG);
969 982 }
970 983 if (nbytes >= *bufsize) {
971 984 /* insufficient buffer space */
972 985 *bufsize = nbytes + 1;
973 986 return (IPADM_NO_BUFS);
974 987 }
975 988 return (IPADM_SUCCESS);
976 989 }
977 990
978 991 /* ARGSUSED */
979 992 static ipadm_status_t
980 993 i_ipadm_get_ifprop_flags(ipadm_handle_t iph, const void *arg,
981 994 ipadm_prop_desc_t *pdp, char *buf, uint_t *bufsize, uint_t proto,
982 995 uint_t valtype)
983 996 {
984 997 uint64_t intf_flags;
985 998 char *val;
986 999 size_t nbytes;
987 1000 const char *ifname = arg;
988 1001 sa_family_t af;
989 1002 ipadm_status_t status = IPADM_SUCCESS;
|
↓ open down ↓ |
348 lines elided |
↑ open up ↑ |
990 1003
991 1004 switch (valtype) {
992 1005 case MOD_PROP_PERM:
993 1006 nbytes = snprintf(buf, *bufsize, "%d", MOD_PROP_PERM_RW);
994 1007 break;
995 1008 case MOD_PROP_DEFAULT:
996 1009 if (strcmp(pdp->ipd_name, "exchange_routes") == 0 ||
997 1010 strcmp(pdp->ipd_name, "arp") == 0 ||
998 1011 strcmp(pdp->ipd_name, "nud") == 0) {
999 1012 val = IPADM_ONSTR;
1000 - } else if (strcmp(pdp->ipd_name, "forwarding") == 0) {
1013 + } else if (strcmp(pdp->ipd_name, "forwarding") == 0 ||
1014 + strcmp(pdp->ipd_name, "standby") == 0) {
1001 1015 val = IPADM_OFFSTR;
1002 1016 } else {
1003 1017 return (IPADM_PROP_UNKNOWN);
1004 1018 }
1005 1019 nbytes = snprintf(buf, *bufsize, "%s", val);
1006 1020 break;
1007 1021 case MOD_PROP_ACTIVE:
1008 1022 af = (proto == MOD_PROTO_IPV6 ? AF_INET6 : AF_INET);
1009 1023 status = i_ipadm_get_flags(iph, ifname, af, &intf_flags);
1010 1024 if (status != IPADM_SUCCESS)
1011 1025 return (status);
1012 1026
1013 1027 val = IPADM_OFFSTR;
1014 1028 if (strcmp(pdp->ipd_name, "exchange_routes") == 0) {
1015 1029 if (!(intf_flags & IFF_NORTEXCH))
|
↓ open down ↓ |
5 lines elided |
↑ open up ↑ |
1016 1030 val = IPADM_ONSTR;
1017 1031 } else if (strcmp(pdp->ipd_name, "forwarding") == 0) {
1018 1032 if (intf_flags & IFF_ROUTER)
1019 1033 val = IPADM_ONSTR;
1020 1034 } else if (strcmp(pdp->ipd_name, "arp") == 0) {
1021 1035 if (!(intf_flags & IFF_NOARP))
1022 1036 val = IPADM_ONSTR;
1023 1037 } else if (strcmp(pdp->ipd_name, "nud") == 0) {
1024 1038 if (!(intf_flags & IFF_NONUD))
1025 1039 val = IPADM_ONSTR;
1040 + } else if (strcmp(pdp->ipd_name, "standby") == 0) {
1041 + if (intf_flags & IFF_STANDBY)
1042 + val = IPADM_ONSTR;
1026 1043 }
1027 1044 nbytes = snprintf(buf, *bufsize, "%s", val);
1028 1045 break;
1029 1046 default:
1030 1047 return (IPADM_INVALID_ARG);
1031 1048 }
1032 1049 if (nbytes >= *bufsize) {
1033 1050 /* insufficient buffer space */
1034 1051 *bufsize = nbytes + 1;
1035 1052 status = IPADM_NO_BUFS;
1036 1053 }
1037 1054
1038 1055 return (status);
1039 1056 }
1040 1057
1041 1058 static void
1042 1059 i_ipadm_perm2str(char *buf, uint_t *bufsize)
1043 1060 {
1044 1061 uint_t perm = atoi(buf);
1045 1062
1046 1063 (void) snprintf(buf, *bufsize, "%c%c",
1047 1064 ((perm & MOD_PROP_PERM_READ) != 0) ? 'r' : '-',
1048 1065 ((perm & MOD_PROP_PERM_WRITE) != 0) ? 'w' : '-');
1049 1066 }
1050 1067
1051 1068 /* ARGSUSED */
1052 1069 static ipadm_status_t
1053 1070 i_ipadm_get_prop(ipadm_handle_t iph, const void *arg,
1054 1071 ipadm_prop_desc_t *pdp, char *buf, uint_t *bufsize, uint_t proto,
1055 1072 uint_t valtype)
1056 1073 {
1057 1074 ipadm_status_t status = IPADM_SUCCESS;
1058 1075 const char *ifname = arg;
1059 1076 mod_ioc_prop_t *mip;
1060 1077 char *pname = pdp->ipd_name;
1061 1078 uint_t iocsize;
1062 1079
1063 1080 /* allocate sufficient ioctl buffer to retrieve value */
1064 1081 iocsize = sizeof (mod_ioc_prop_t) + *bufsize - 1;
1065 1082 if ((mip = calloc(1, iocsize)) == NULL)
1066 1083 return (IPADM_NO_BUFS);
1067 1084
1068 1085 mip->mpr_version = MOD_PROP_VERSION;
1069 1086 mip->mpr_flags = valtype;
1070 1087 mip->mpr_proto = proto;
1071 1088 if (ifname != NULL) {
1072 1089 (void) strlcpy(mip->mpr_ifname, ifname,
1073 1090 sizeof (mip->mpr_ifname));
1074 1091 }
1075 1092 (void) strlcpy(mip->mpr_name, pname, sizeof (mip->mpr_name));
1076 1093 mip->mpr_valsize = *bufsize;
1077 1094
1078 1095 if (i_ipadm_strioctl(iph->iph_sock, SIOCGETPROP, (char *)mip,
1079 1096 iocsize) < 0) {
1080 1097 if (errno == ENOENT)
1081 1098 status = IPADM_PROP_UNKNOWN;
1082 1099 else
1083 1100 status = ipadm_errno2status(errno);
1084 1101 } else {
1085 1102 bcopy(mip->mpr_val, buf, *bufsize);
1086 1103 }
1087 1104
1088 1105 free(mip);
1089 1106 return (status);
1090 1107 }
1091 1108
1092 1109 /*
1093 1110 * Populates the ipmgmt_prop_arg_t based on the class of property.
1094 1111 *
1095 1112 * For private protocol properties, while persisting information in ipadm
1096 1113 * data store, to ensure there is no collision of namespace between ipadm
1097 1114 * private nvpair names (which also starts with '_', see ipadm_ipmgmt.h)
1098 1115 * and private protocol property names, we will prepend IPADM_PRIV_PROP_PREFIX
1099 1116 * to property names.
1100 1117 */
1101 1118 static void
1102 1119 i_ipadm_populate_proparg(ipmgmt_prop_arg_t *pargp, ipadm_prop_desc_t *pdp,
1103 1120 const char *pval, const void *object)
1104 1121 {
1105 1122 const struct ipadm_addrobj_s *ipaddr;
1106 1123 uint_t class = pdp->ipd_class;
1107 1124 uint_t proto = pdp->ipd_proto;
1108 1125
1109 1126 (void) strlcpy(pargp->ia_pname, pdp->ipd_name,
1110 1127 sizeof (pargp->ia_pname));
1111 1128 if (pval != NULL)
1112 1129 (void) strlcpy(pargp->ia_pval, pval, sizeof (pargp->ia_pval));
1113 1130
1114 1131 switch (class) {
1115 1132 case IPADMPROP_CLASS_MODULE:
1116 1133 /* if it's a private property then add the prefix. */
1117 1134 if (pdp->ipd_name[0] == '_') {
1118 1135 (void) snprintf(pargp->ia_pname,
1119 1136 sizeof (pargp->ia_pname), "_%s", pdp->ipd_name);
1120 1137 }
1121 1138 (void) strlcpy(pargp->ia_module, object,
1122 1139 sizeof (pargp->ia_module));
1123 1140 break;
1124 1141 case IPADMPROP_CLASS_MODIF:
1125 1142 /* check if object is protostr or an ifname */
1126 1143 if (ipadm_str2proto(object) != MOD_PROTO_NONE) {
1127 1144 (void) strlcpy(pargp->ia_module, object,
1128 1145 sizeof (pargp->ia_module));
1129 1146 break;
1130 1147 }
1131 1148 /* it's an interface property, fall through */
1132 1149 /* FALLTHRU */
1133 1150 case IPADMPROP_CLASS_IF:
1134 1151 (void) strlcpy(pargp->ia_ifname, object,
1135 1152 sizeof (pargp->ia_ifname));
1136 1153 (void) strlcpy(pargp->ia_module, ipadm_proto2str(proto),
1137 1154 sizeof (pargp->ia_module));
1138 1155 break;
1139 1156 case IPADMPROP_CLASS_ADDR:
1140 1157 ipaddr = object;
1141 1158 (void) strlcpy(pargp->ia_ifname, ipaddr->ipadm_ifname,
1142 1159 sizeof (pargp->ia_ifname));
1143 1160 (void) strlcpy(pargp->ia_aobjname, ipaddr->ipadm_aobjname,
1144 1161 sizeof (pargp->ia_aobjname));
1145 1162 break;
1146 1163 }
1147 1164 }
1148 1165
1149 1166 /*
1150 1167 * Common function to retrieve property value for a given interface `ifname' or
1151 1168 * for a given protocol `proto'. The property name is in `pname'.
1152 1169 *
1153 1170 * `valtype' determines the type of value that will be retrieved.
1154 1171 * IPADM_OPT_ACTIVE - current value of the property (active config)
1155 1172 * IPADM_OPT_PERSIST - value of the property from persistent store
1156 1173 * IPADM_OPT_DEFAULT - default hard coded value (boot-time value)
1157 1174 * IPADM_OPT_PERM - read/write permissions for the value
1158 1175 * IPADM_OPT_POSSIBLE - range of values
1159 1176 */
1160 1177 static ipadm_status_t
1161 1178 i_ipadm_getprop_common(ipadm_handle_t iph, const char *ifname,
1162 1179 const char *pname, char *buf, uint_t *bufsize, uint_t proto,
1163 1180 uint_t valtype)
1164 1181 {
1165 1182 ipadm_status_t status = IPADM_SUCCESS;
1166 1183 ipadm_prop_desc_t *pdp;
1167 1184 char priv_propname[MAXPROPNAMELEN];
1168 1185 boolean_t is_if = (ifname != NULL);
1169 1186 int err = 0;
1170 1187
1171 1188 pdp = i_ipadm_get_prop_desc(pname, proto, &err);
1172 1189 if (err == EPROTO)
1173 1190 return (IPADM_BAD_PROTOCOL);
1174 1191 /* there are no private interface properties */
1175 1192 if (is_if && err == ENOENT)
1176 1193 return (IPADM_PROP_UNKNOWN);
1177 1194
1178 1195 if (pdp != NULL) {
1179 1196 /*
1180 1197 * check whether the property can be
1181 1198 * applied on an interface
1182 1199 */
1183 1200 if (is_if && !(pdp->ipd_class & IPADMPROP_CLASS_IF))
1184 1201 return (IPADM_INVALID_ARG);
1185 1202 /*
1186 1203 * check whether the property can be
1187 1204 * applied on a module
1188 1205 */
1189 1206 if (!is_if && !(pdp->ipd_class & IPADMPROP_CLASS_MODULE))
1190 1207 return (IPADM_INVALID_ARG);
1191 1208
1192 1209 } else {
1193 1210 /* private protocol properties, pass it to kernel directly */
1194 1211 pdp = &ipadm_privprop;
1195 1212 (void) strlcpy(priv_propname, pname, sizeof (priv_propname));
1196 1213 pdp->ipd_name = priv_propname;
1197 1214 }
1198 1215
1199 1216 switch (valtype) {
1200 1217 case IPADM_OPT_PERM:
1201 1218 status = pdp->ipd_get(iph, ifname, pdp, buf, bufsize, proto,
1202 1219 MOD_PROP_PERM);
1203 1220 if (status == IPADM_SUCCESS)
1204 1221 i_ipadm_perm2str(buf, bufsize);
1205 1222 break;
1206 1223 case IPADM_OPT_ACTIVE:
1207 1224 status = pdp->ipd_get(iph, ifname, pdp, buf, bufsize, proto,
1208 1225 MOD_PROP_ACTIVE);
1209 1226 break;
1210 1227 case IPADM_OPT_DEFAULT:
1211 1228 status = pdp->ipd_get(iph, ifname, pdp, buf, bufsize, proto,
1212 1229 MOD_PROP_DEFAULT);
1213 1230 break;
1214 1231 case IPADM_OPT_POSSIBLE:
1215 1232 if (pdp->ipd_get_range != NULL) {
1216 1233 status = pdp->ipd_get_range(iph, ifname, pdp, buf,
1217 1234 bufsize, proto, MOD_PROP_POSSIBLE);
1218 1235 break;
1219 1236 }
1220 1237 buf[0] = '\0';
1221 1238 break;
1222 1239 case IPADM_OPT_PERSIST:
1223 1240 /* retrieve from database */
1224 1241 if (is_if)
1225 1242 status = i_ipadm_get_persist_propval(iph, pdp, buf,
1226 1243 bufsize, ifname);
1227 1244 else
1228 1245 status = i_ipadm_get_persist_propval(iph, pdp, buf,
1229 1246 bufsize, ipadm_proto2str(proto));
1230 1247 break;
1231 1248 default:
1232 1249 status = IPADM_INVALID_ARG;
1233 1250 break;
1234 1251 }
1235 1252 return (status);
1236 1253 }
1237 1254
1238 1255 /*
1239 1256 * Get protocol property of the specified protocol.
1240 1257 */
1241 1258 ipadm_status_t
1242 1259 ipadm_get_prop(ipadm_handle_t iph, const char *pname, char *buf,
1243 1260 uint_t *bufsize, uint_t proto, uint_t valtype)
1244 1261 {
1245 1262 /*
1246 1263 * validate the arguments of the function.
1247 1264 */
1248 1265 if (iph == NULL || pname == NULL || buf == NULL ||
1249 1266 bufsize == NULL || *bufsize == 0) {
1250 1267 return (IPADM_INVALID_ARG);
1251 1268 }
1252 1269 /*
1253 1270 * Do we support this proto, if not return error.
1254 1271 */
1255 1272 if (ipadm_proto2str(proto) == NULL)
1256 1273 return (IPADM_NOTSUP);
1257 1274
1258 1275 return (i_ipadm_getprop_common(iph, NULL, pname, buf, bufsize,
1259 1276 proto, valtype));
1260 1277 }
1261 1278
1262 1279 /*
1263 1280 * Get interface property of the specified interface.
1264 1281 */
1265 1282 ipadm_status_t
1266 1283 ipadm_get_ifprop(ipadm_handle_t iph, const char *ifname, const char *pname,
1267 1284 char *buf, uint_t *bufsize, uint_t proto, uint_t valtype)
1268 1285 {
1269 1286 /* validate the arguments of the function. */
1270 1287 if (iph == NULL || pname == NULL || buf == NULL ||
1271 1288 bufsize == NULL || *bufsize == 0) {
1272 1289 return (IPADM_INVALID_ARG);
1273 1290 }
1274 1291
1275 1292 /* Do we support this proto, if not return error. */
1276 1293 if (ipadm_proto2str(proto) == NULL)
1277 1294 return (IPADM_NOTSUP);
1278 1295
1279 1296 /*
1280 1297 * check if interface name is provided for interface property and
1281 1298 * is valid.
1282 1299 */
1283 1300 if (!i_ipadm_validate_ifname(iph, ifname))
1284 1301 return (IPADM_INVALID_ARG);
1285 1302
1286 1303 return (i_ipadm_getprop_common(iph, ifname, pname, buf, bufsize,
1287 1304 proto, valtype));
1288 1305 }
1289 1306
1290 1307 /*
1291 1308 * Allocates sufficient ioctl buffers and copies property name and the
1292 1309 * value, among other things. If the flag IPADM_OPT_DEFAULT is set, then
1293 1310 * `pval' will be NULL and it instructs the kernel to reset the current
1294 1311 * value to property's default value.
1295 1312 */
1296 1313 static ipadm_status_t
1297 1314 i_ipadm_set_prop(ipadm_handle_t iph, const void *arg,
1298 1315 ipadm_prop_desc_t *pdp, const void *pval, uint_t proto, uint_t flags)
1299 1316 {
1300 1317 ipadm_status_t status = IPADM_SUCCESS;
1301 1318 const char *ifname = arg;
1302 1319 mod_ioc_prop_t *mip;
1303 1320 char *pname = pdp->ipd_name;
1304 1321 uint_t valsize, iocsize;
1305 1322 uint_t iocflags = 0;
1306 1323
1307 1324 if (flags & IPADM_OPT_DEFAULT) {
1308 1325 iocflags |= MOD_PROP_DEFAULT;
1309 1326 } else if (flags & IPADM_OPT_ACTIVE) {
1310 1327 iocflags |= MOD_PROP_ACTIVE;
1311 1328 if (flags & IPADM_OPT_APPEND)
1312 1329 iocflags |= MOD_PROP_APPEND;
1313 1330 else if (flags & IPADM_OPT_REMOVE)
1314 1331 iocflags |= MOD_PROP_REMOVE;
1315 1332 }
1316 1333
1317 1334 if (pval != NULL) {
1318 1335 valsize = strlen(pval);
1319 1336 iocsize = sizeof (mod_ioc_prop_t) + valsize - 1;
1320 1337 } else {
1321 1338 valsize = 0;
1322 1339 iocsize = sizeof (mod_ioc_prop_t);
1323 1340 }
1324 1341
1325 1342 if ((mip = calloc(1, iocsize)) == NULL)
1326 1343 return (IPADM_NO_BUFS);
1327 1344
1328 1345 mip->mpr_version = MOD_PROP_VERSION;
1329 1346 mip->mpr_flags = iocflags;
1330 1347 mip->mpr_proto = proto;
1331 1348 if (ifname != NULL) {
1332 1349 (void) strlcpy(mip->mpr_ifname, ifname,
1333 1350 sizeof (mip->mpr_ifname));
1334 1351 }
1335 1352
1336 1353 (void) strlcpy(mip->mpr_name, pname, sizeof (mip->mpr_name));
1337 1354 mip->mpr_valsize = valsize;
1338 1355 if (pval != NULL)
1339 1356 bcopy(pval, mip->mpr_val, valsize);
1340 1357
1341 1358 if (i_ipadm_strioctl(iph->iph_sock, SIOCSETPROP, (char *)mip,
1342 1359 iocsize) < 0) {
1343 1360 if (errno == ENOENT)
1344 1361 status = IPADM_PROP_UNKNOWN;
1345 1362 else
1346 1363 status = ipadm_errno2status(errno);
1347 1364 }
1348 1365 free(mip);
1349 1366 return (status);
1350 1367 }
1351 1368
1352 1369 /*
1353 1370 * Common function for modifying both protocol/interface property.
1354 1371 *
1355 1372 * If:
1356 1373 * IPADM_OPT_PERSIST is set then the value is persisted.
1357 1374 * IPADM_OPT_DEFAULT is set then the default value for the property will
1358 1375 * be applied.
1359 1376 */
1360 1377 static ipadm_status_t
1361 1378 i_ipadm_setprop_common(ipadm_handle_t iph, const char *ifname,
1362 1379 const char *pname, const char *buf, uint_t proto, uint_t pflags)
1363 1380 {
1364 1381 ipadm_status_t status = IPADM_SUCCESS;
1365 1382 boolean_t persist = (pflags & IPADM_OPT_PERSIST);
1366 1383 boolean_t reset = (pflags & IPADM_OPT_DEFAULT);
1367 1384 ipadm_prop_desc_t *pdp;
1368 1385 boolean_t is_if = (ifname != NULL);
1369 1386 char priv_propname[MAXPROPNAMELEN];
1370 1387 int err = 0;
1371 1388
1372 1389 /* Check that property value is within the allowed size */
1373 1390 if (!reset && strnlen(buf, MAXPROPVALLEN) >= MAXPROPVALLEN)
1374 1391 return (IPADM_INVALID_ARG);
1375 1392
1376 1393 pdp = i_ipadm_get_prop_desc(pname, proto, &err);
1377 1394 if (err == EPROTO)
1378 1395 return (IPADM_BAD_PROTOCOL);
1379 1396 /* there are no private interface properties */
1380 1397 if (is_if && err == ENOENT)
1381 1398 return (IPADM_PROP_UNKNOWN);
1382 1399
1383 1400 if (pdp != NULL) {
1384 1401 /* do some sanity checks */
1385 1402 if (is_if) {
1386 1403 if (!(pdp->ipd_class & IPADMPROP_CLASS_IF))
1387 1404 return (IPADM_INVALID_ARG);
1388 1405 } else {
1389 1406 if (!(pdp->ipd_class & IPADMPROP_CLASS_MODULE))
1390 1407 return (IPADM_INVALID_ARG);
1391 1408 }
1392 1409 /*
1393 1410 * if the property is not multi-valued and IPADM_OPT_APPEND or
1394 1411 * IPADM_OPT_REMOVE is specified, return IPADM_INVALID_ARG.
1395 1412 */
1396 1413 if (!(pdp->ipd_flags & IPADMPROP_MULVAL) && (pflags &
1397 1414 (IPADM_OPT_APPEND|IPADM_OPT_REMOVE))) {
1398 1415 return (IPADM_INVALID_ARG);
1399 1416 }
1400 1417 } else {
1401 1418 /* private protocol property, pass it to kernel directly */
1402 1419 pdp = &ipadm_privprop;
1403 1420 (void) strlcpy(priv_propname, pname, sizeof (priv_propname));
1404 1421 pdp->ipd_name = priv_propname;
1405 1422 }
1406 1423
1407 1424 status = pdp->ipd_set(iph, ifname, pdp, buf, proto, pflags);
1408 1425 if (status != IPADM_SUCCESS)
1409 1426 return (status);
1410 1427
1411 1428 if (persist) {
1412 1429 if (is_if)
1413 1430 status = i_ipadm_persist_propval(iph, pdp, buf, ifname,
1414 1431 pflags);
1415 1432 else
1416 1433 status = i_ipadm_persist_propval(iph, pdp, buf,
1417 1434 ipadm_proto2str(proto), pflags);
1418 1435 }
1419 1436 return (status);
1420 1437 }
1421 1438
1422 1439 /*
1423 1440 * Sets the property value of the specified interface
1424 1441 */
1425 1442 ipadm_status_t
1426 1443 ipadm_set_ifprop(ipadm_handle_t iph, const char *ifname, const char *pname,
1427 1444 const char *buf, uint_t proto, uint_t pflags)
1428 1445 {
1429 1446 boolean_t reset = (pflags & IPADM_OPT_DEFAULT);
1430 1447 ipadm_status_t status;
1431 1448
1432 1449 /* check for solaris.network.interface.config authorization */
1433 1450 if (!ipadm_check_auth())
1434 1451 return (IPADM_EAUTH);
1435 1452 /*
1436 1453 * validate the arguments of the function.
1437 1454 */
1438 1455 if (iph == NULL || pname == NULL || (!reset && buf == NULL) ||
1439 1456 pflags == 0 || pflags == IPADM_OPT_PERSIST ||
1440 1457 (pflags & ~(IPADM_COMMON_OPT_MASK|IPADM_OPT_DEFAULT))) {
1441 1458 return (IPADM_INVALID_ARG);
1442 1459 }
1443 1460
1444 1461 /*
1445 1462 * Do we support this protocol, if not return error.
1446 1463 */
1447 1464 if (ipadm_proto2str(proto) == NULL)
1448 1465 return (IPADM_NOTSUP);
1449 1466
1450 1467 /*
1451 1468 * Validate the interface and check if a persistent
1452 1469 * operation is performed on a temporary object.
1453 1470 */
1454 1471 status = i_ipadm_validate_if(iph, ifname, proto, pflags);
1455 1472 if (status != IPADM_SUCCESS)
1456 1473 return (status);
1457 1474
1458 1475 return (i_ipadm_setprop_common(iph, ifname, pname, buf, proto,
1459 1476 pflags));
1460 1477 }
1461 1478
1462 1479 /*
1463 1480 * Sets the property value of the specified protocol.
1464 1481 */
1465 1482 ipadm_status_t
1466 1483 ipadm_set_prop(ipadm_handle_t iph, const char *pname, const char *buf,
1467 1484 uint_t proto, uint_t pflags)
1468 1485 {
1469 1486 boolean_t reset = (pflags & IPADM_OPT_DEFAULT);
1470 1487
1471 1488 /* check for solaris.network.interface.config authorization */
1472 1489 if (!ipadm_check_auth())
1473 1490 return (IPADM_EAUTH);
1474 1491 /*
1475 1492 * validate the arguments of the function.
1476 1493 */
1477 1494 if (iph == NULL || pname == NULL ||(!reset && buf == NULL) ||
1478 1495 pflags == 0 || pflags == IPADM_OPT_PERSIST ||
1479 1496 (pflags & ~(IPADM_COMMON_OPT_MASK|IPADM_OPT_DEFAULT|
1480 1497 IPADM_OPT_APPEND|IPADM_OPT_REMOVE))) {
1481 1498 return (IPADM_INVALID_ARG);
1482 1499 }
1483 1500
1484 1501 /*
1485 1502 * Do we support this proto, if not return error.
1486 1503 */
1487 1504 if (ipadm_proto2str(proto) == NULL)
1488 1505 return (IPADM_NOTSUP);
1489 1506
1490 1507 return (i_ipadm_setprop_common(iph, NULL, pname, buf, proto,
1491 1508 pflags));
1492 1509 }
1493 1510
1494 1511 /* helper function for ipadm_walk_proptbl */
1495 1512 static void
1496 1513 i_ipadm_walk_proptbl(ipadm_prop_desc_t *pdtbl, uint_t proto, uint_t class,
1497 1514 ipadm_prop_wfunc_t *func, void *arg)
1498 1515 {
1499 1516 ipadm_prop_desc_t *pdp;
1500 1517
1501 1518 for (pdp = pdtbl; pdp->ipd_name != NULL; pdp++) {
1502 1519 if (!(pdp->ipd_class & class))
1503 1520 continue;
1504 1521
1505 1522 if (proto != MOD_PROTO_NONE && !(pdp->ipd_proto & proto))
1506 1523 continue;
1507 1524
1508 1525 /*
1509 1526 * we found a class specific match, call the
1510 1527 * user callback function.
1511 1528 */
1512 1529 if (func(arg, pdp->ipd_name, pdp->ipd_proto) == B_FALSE)
1513 1530 break;
1514 1531 }
1515 1532 }
1516 1533
1517 1534 /*
1518 1535 * Walks through all the properties, for a given protocol and property class
1519 1536 * (protocol or interface).
1520 1537 *
1521 1538 * Further if proto == MOD_PROTO_NONE, then it walks through all the supported
1522 1539 * protocol property tables.
1523 1540 */
1524 1541 ipadm_status_t
1525 1542 ipadm_walk_proptbl(uint_t proto, uint_t class, ipadm_prop_wfunc_t *func,
1526 1543 void *arg)
1527 1544 {
1528 1545 ipadm_prop_desc_t *pdtbl;
1529 1546 ipadm_status_t status = IPADM_SUCCESS;
1530 1547 int i;
1531 1548 int count = A_CNT(protocols);
1532 1549
1533 1550 if (func == NULL)
1534 1551 return (IPADM_INVALID_ARG);
1535 1552
1536 1553 switch (class) {
1537 1554 case IPADMPROP_CLASS_ADDR:
1538 1555 pdtbl = ipadm_addrprop_table;
1539 1556 break;
1540 1557 case IPADMPROP_CLASS_IF:
1541 1558 case IPADMPROP_CLASS_MODULE:
1542 1559 pdtbl = i_ipadm_get_propdesc_table(proto);
1543 1560 if (pdtbl == NULL && proto != MOD_PROTO_NONE)
1544 1561 return (IPADM_INVALID_ARG);
1545 1562 break;
1546 1563 default:
1547 1564 return (IPADM_INVALID_ARG);
1548 1565 }
1549 1566
1550 1567 if (pdtbl != NULL) {
1551 1568 /*
1552 1569 * proto will be MOD_PROTO_NONE in the case of
1553 1570 * IPADMPROP_CLASS_ADDR.
1554 1571 */
1555 1572 i_ipadm_walk_proptbl(pdtbl, proto, class, func, arg);
1556 1573 } else {
1557 1574 /* Walk thru all the protocol tables, we support */
1558 1575 for (i = 0; i < count; i++) {
1559 1576 pdtbl = i_ipadm_get_propdesc_table(protocols[i]);
1560 1577 i_ipadm_walk_proptbl(pdtbl, protocols[i], class, func,
1561 1578 arg);
1562 1579 }
1563 1580 }
1564 1581 return (status);
1565 1582 }
1566 1583
1567 1584 /*
1568 1585 * Given a property name, walks through all the instances of a property name.
1569 1586 * Some properties have two instances one for v4 interfaces and another for v6
1570 1587 * interfaces. For example: MTU. MTU can have different values for v4 and v6.
1571 1588 * Therefore there are two properties for 'MTU'.
1572 1589 *
1573 1590 * This function invokes `func' for every instance of property `pname'
1574 1591 */
1575 1592 ipadm_status_t
1576 1593 ipadm_walk_prop(const char *pname, uint_t proto, uint_t class,
1577 1594 ipadm_prop_wfunc_t *func, void *arg)
1578 1595 {
1579 1596 ipadm_prop_desc_t *pdtbl, *pdp;
1580 1597 ipadm_status_t status = IPADM_SUCCESS;
1581 1598 boolean_t matched = B_FALSE;
1582 1599
1583 1600 if (pname == NULL || func == NULL)
1584 1601 return (IPADM_INVALID_ARG);
1585 1602
1586 1603 switch (class) {
1587 1604 case IPADMPROP_CLASS_ADDR:
1588 1605 pdtbl = ipadm_addrprop_table;
1589 1606 break;
1590 1607 case IPADMPROP_CLASS_IF:
1591 1608 case IPADMPROP_CLASS_MODULE:
1592 1609 pdtbl = i_ipadm_get_propdesc_table(proto);
1593 1610 break;
1594 1611 default:
1595 1612 return (IPADM_INVALID_ARG);
1596 1613 }
1597 1614
1598 1615 if (pdtbl == NULL)
1599 1616 return (IPADM_INVALID_ARG);
1600 1617
1601 1618 for (pdp = pdtbl; pdp->ipd_name != NULL; pdp++) {
1602 1619 if (strcmp(pname, pdp->ipd_name) != 0)
1603 1620 continue;
1604 1621 if (!(pdp->ipd_proto & proto))
1605 1622 continue;
1606 1623 matched = B_TRUE;
1607 1624 /* we found a match, call the callback function */
1608 1625 if (func(arg, pdp->ipd_name, pdp->ipd_proto) == B_FALSE)
1609 1626 break;
1610 1627 }
1611 1628 if (!matched)
1612 1629 status = IPADM_PROP_UNKNOWN;
1613 1630 return (status);
1614 1631 }
1615 1632
1616 1633 /* ARGSUSED */
1617 1634 ipadm_status_t
1618 1635 i_ipadm_get_onoff(ipadm_handle_t iph, const void *arg, ipadm_prop_desc_t *dp,
1619 1636 char *buf, uint_t *bufsize, uint_t proto, uint_t valtype)
1620 1637 {
1621 1638 (void) snprintf(buf, *bufsize, "%s,%s", IPADM_ONSTR, IPADM_OFFSTR);
1622 1639 return (IPADM_SUCCESS);
1623 1640 }
1624 1641
1625 1642 /*
1626 1643 * Makes a door call to ipmgmtd to retrieve the persisted property value
1627 1644 */
1628 1645 ipadm_status_t
1629 1646 i_ipadm_get_persist_propval(ipadm_handle_t iph, ipadm_prop_desc_t *pdp,
1630 1647 char *gbuf, uint_t *gbufsize, const void *object)
1631 1648 {
1632 1649 ipmgmt_prop_arg_t parg;
1633 1650 ipmgmt_getprop_rval_t rval, *rvalp;
1634 1651 size_t nbytes;
1635 1652 int err = 0;
1636 1653
1637 1654 bzero(&parg, sizeof (parg));
1638 1655 parg.ia_cmd = IPMGMT_CMD_GETPROP;
1639 1656 i_ipadm_populate_proparg(&parg, pdp, NULL, object);
1640 1657
1641 1658 rvalp = &rval;
1642 1659 err = ipadm_door_call(iph, &parg, sizeof (parg), (void **)&rvalp,
1643 1660 sizeof (rval), B_FALSE);
1644 1661 if (err == 0) {
1645 1662 /* assert that rvalp was not reallocated */
1646 1663 assert(rvalp == &rval);
1647 1664
1648 1665 /* `ir_pval' contains the property value */
1649 1666 nbytes = snprintf(gbuf, *gbufsize, "%s", rvalp->ir_pval);
1650 1667 if (nbytes >= *gbufsize) {
1651 1668 /* insufficient buffer space */
1652 1669 *gbufsize = nbytes + 1;
1653 1670 err = ENOBUFS;
1654 1671 }
1655 1672 }
1656 1673 return (ipadm_errno2status(err));
1657 1674 }
1658 1675
1659 1676 /*
1660 1677 * Persists the property value for a given property in the data store
1661 1678 */
1662 1679 ipadm_status_t
1663 1680 i_ipadm_persist_propval(ipadm_handle_t iph, ipadm_prop_desc_t *pdp,
1664 1681 const char *pval, const void *object, uint_t flags)
1665 1682 {
1666 1683 ipmgmt_prop_arg_t parg;
1667 1684 int err = 0;
1668 1685
1669 1686 bzero(&parg, sizeof (parg));
1670 1687 i_ipadm_populate_proparg(&parg, pdp, pval, object);
1671 1688 /*
1672 1689 * Check if value to be persisted need to be appended or removed. This
1673 1690 * is required for multi-valued property.
1674 1691 */
1675 1692 if (flags & IPADM_OPT_APPEND)
1676 1693 parg.ia_flags |= IPMGMT_APPEND;
1677 1694 if (flags & IPADM_OPT_REMOVE)
1678 1695 parg.ia_flags |= IPMGMT_REMOVE;
1679 1696
1680 1697 if (flags & (IPADM_OPT_DEFAULT|IPADM_OPT_REMOVE))
1681 1698 parg.ia_cmd = IPMGMT_CMD_RESETPROP;
1682 1699 else
1683 1700 parg.ia_cmd = IPMGMT_CMD_SETPROP;
1684 1701
1685 1702 err = ipadm_door_call(iph, &parg, sizeof (parg), NULL, 0, B_FALSE);
1686 1703
1687 1704 /*
1688 1705 * its fine if there were no entry in the DB to delete. The user
1689 1706 * might be changing property value, which was not changed
1690 1707 * persistently.
|
↓ open down ↓ |
655 lines elided |
↑ open up ↑ |
1691 1708 */
1692 1709 if (err == ENOENT)
1693 1710 err = 0;
1694 1711 return (ipadm_errno2status(err));
1695 1712 }
1696 1713
1697 1714 /*
1698 1715 * This is called from ipadm_set_ifprop() to validate the set operation.
1699 1716 * It does the following steps:
1700 1717 * 1. Validates the interface name.
1701 - * 2. Fails if it is an IPMP meta-interface or an underlying interface.
1702 - * 3. In case of a persistent operation, verifies that the
1718 + * 2. In case of a persistent operation, verifies that the
1703 1719 * interface is persistent.
1704 1720 */
1705 1721 static ipadm_status_t
1706 1722 i_ipadm_validate_if(ipadm_handle_t iph, const char *ifname,
1707 1723 uint_t proto, uint_t flags)
1708 1724 {
1709 1725 sa_family_t af, other_af;
1710 1726 ipadm_status_t status;
1711 1727 boolean_t p_exists;
1712 1728 boolean_t af_exists, other_af_exists, a_exists;
1713 1729
1714 1730 /* Check if the interface name is valid. */
1715 1731 if (!i_ipadm_validate_ifname(iph, ifname))
1716 1732 return (IPADM_INVALID_ARG);
1717 1733
1718 1734 af = (proto == MOD_PROTO_IPV6 ? AF_INET6 : AF_INET);
1719 - /*
1720 - * Setting properties on an IPMP meta-interface or underlying
1721 - * interface is not supported.
1722 - */
1723 - if (i_ipadm_is_ipmp(iph, ifname) || i_ipadm_is_under_ipmp(iph, ifname))
1724 - return (IPADM_NOTSUP);
1725 1735
1726 1736 /* Check if interface exists in the persistent configuration. */
1727 1737 status = i_ipadm_if_pexists(iph, ifname, af, &p_exists);
1728 1738 if (status != IPADM_SUCCESS)
1729 1739 return (status);
1730 1740
1731 1741 /* Check if interface exists in the active configuration. */
1732 1742 af_exists = ipadm_if_enabled(iph, ifname, af);
1733 1743 other_af = (af == AF_INET ? AF_INET6 : AF_INET);
1734 1744 other_af_exists = ipadm_if_enabled(iph, ifname, other_af);
1735 1745 a_exists = (af_exists || other_af_exists);
1736 1746 if (!a_exists && p_exists)
1737 1747 return (IPADM_OP_DISABLE_OBJ);
1738 1748 if (!af_exists)
1739 1749 return (IPADM_ENXIO);
1740 1750
1741 1751 /*
1742 1752 * If a persistent operation is requested, check if the underlying
1743 1753 * IP interface is persistent.
1744 1754 */
1745 1755 if ((flags & IPADM_OPT_PERSIST) && !p_exists)
1746 1756 return (IPADM_TEMPORARY_OBJ);
1747 1757 return (IPADM_SUCCESS);
1748 1758 }
1749 1759
1750 1760 /*
1751 1761 * Private protocol properties namespace scheme:
1752 1762 *
1753 1763 * PSARC 2010/080 identified the private protocol property names to be the
1754 1764 * leading protocol names. For e.g. tcp_strong_iss, ip_strict_src_multihoming,
1755 1765 * et al,. However to be consistent with private data-link property names,
1756 1766 * which starts with '_', private protocol property names will start with '_'.
1757 1767 * For e.g. _strong_iss, _strict_src_multihoming, et al,.
1758 1768 */
1759 1769
1760 1770 /* maps new private protocol property name to the old private property name */
1761 1771 typedef struct ipadm_oname2nname_map {
1762 1772 char *iom_oname;
1763 1773 char *iom_nname;
1764 1774 uint_t iom_proto;
1765 1775 } ipadm_oname2nname_map_t;
1766 1776
1767 1777 /*
1768 1778 * IP is a special case. It isn't straight forward to derive the legacy name
1769 1779 * from the new name and vice versa. No set standard was followed in naming
1770 1780 * the properties and hence we need a table to capture the mapping.
1771 1781 */
1772 1782 static ipadm_oname2nname_map_t name_map[] = {
1773 1783 { "arp_probe_delay", "_arp_probe_delay",
1774 1784 MOD_PROTO_IP },
1775 1785 { "arp_fastprobe_delay", "_arp_fastprobe_delay",
1776 1786 MOD_PROTO_IP },
1777 1787 { "arp_probe_interval", "_arp_probe_interval",
1778 1788 MOD_PROTO_IP },
1779 1789 { "arp_fastprobe_interval", "_arp_fastprobe_interval",
1780 1790 MOD_PROTO_IP },
1781 1791 { "arp_probe_count", "_arp_probe_count",
1782 1792 MOD_PROTO_IP },
1783 1793 { "arp_fastprobe_count", "_arp_fastprobe_count",
1784 1794 MOD_PROTO_IP },
1785 1795 { "arp_defend_interval", "_arp_defend_interval",
1786 1796 MOD_PROTO_IP },
1787 1797 { "arp_defend_rate", "_arp_defend_rate",
1788 1798 MOD_PROTO_IP },
1789 1799 { "arp_defend_period", "_arp_defend_period",
1790 1800 MOD_PROTO_IP },
1791 1801 { "ndp_defend_interval", "_ndp_defend_interval",
1792 1802 MOD_PROTO_IP },
1793 1803 { "ndp_defend_rate", "_ndp_defend_rate",
1794 1804 MOD_PROTO_IP },
1795 1805 { "ndp_defend_period", "_ndp_defend_period",
1796 1806 MOD_PROTO_IP },
1797 1807 { "igmp_max_version", "_igmp_max_version",
1798 1808 MOD_PROTO_IP },
1799 1809 { "mld_max_version", "_mld_max_version",
1800 1810 MOD_PROTO_IP },
1801 1811 { "ipsec_override_persocket_policy", "_ipsec_override_persocket_policy",
1802 1812 MOD_PROTO_IP },
1803 1813 { "ipsec_policy_log_interval", "_ipsec_policy_log_interval",
1804 1814 MOD_PROTO_IP },
1805 1815 { "icmp_accept_clear_messages", "_icmp_accept_clear_messages",
1806 1816 MOD_PROTO_IP },
1807 1817 { "igmp_accept_clear_messages", "_igmp_accept_clear_messages",
1808 1818 MOD_PROTO_IP },
1809 1819 { "pim_accept_clear_messages", "_pim_accept_clear_messages",
1810 1820 MOD_PROTO_IP },
1811 1821 { "ip_respond_to_echo_multicast", "_respond_to_echo_multicast",
1812 1822 MOD_PROTO_IPV4 },
1813 1823 { "ip_send_redirects", "_send_redirects",
1814 1824 MOD_PROTO_IPV4 },
1815 1825 { "ip_forward_src_routed", "_forward_src_routed",
1816 1826 MOD_PROTO_IPV4 },
1817 1827 { "ip_icmp_return_data_bytes", "_icmp_return_data_bytes",
1818 1828 MOD_PROTO_IPV4 },
1819 1829 { "ip_ignore_redirect", "_ignore_redirect",
1820 1830 MOD_PROTO_IPV4 },
1821 1831 { "ip_strict_dst_multihoming", "_strict_dst_multihoming",
1822 1832 MOD_PROTO_IPV4 },
1823 1833 { "ip_reasm_timeout", "_reasm_timeout",
1824 1834 MOD_PROTO_IPV4 },
1825 1835 { "ip_strict_src_multihoming", "_strict_src_multihoming",
1826 1836 MOD_PROTO_IPV4 },
1827 1837 { "ipv4_dad_announce_interval", "_dad_announce_interval",
1828 1838 MOD_PROTO_IPV4 },
1829 1839 { "ipv4_icmp_return_pmtu", "_icmp_return_pmtu",
1830 1840 MOD_PROTO_IPV4 },
1831 1841 { "ipv6_dad_announce_interval", "_dad_announce_interval",
1832 1842 MOD_PROTO_IPV6 },
1833 1843 { "ipv6_icmp_return_pmtu", "_icmp_return_pmtu",
1834 1844 MOD_PROTO_IPV6 },
1835 1845 { NULL, NULL, MOD_PROTO_NONE }
1836 1846 };
1837 1847
1838 1848 /*
1839 1849 * Following API returns a new property name in `nname' for the given legacy
1840 1850 * property name in `oname'.
1841 1851 */
1842 1852 int
1843 1853 ipadm_legacy2new_propname(const char *oname, char *nname, uint_t nnamelen,
1844 1854 uint_t *proto)
1845 1855 {
1846 1856 const char *str;
1847 1857 ipadm_oname2nname_map_t *ionmp;
1848 1858
1849 1859 /* if it's a public property, there is nothing to return */
1850 1860 if (i_ipadm_get_prop_desc(oname, *proto, NULL) != NULL)
1851 1861 return (-1);
1852 1862
1853 1863 /*
1854 1864 * we didn't find the `oname' in the table, check if the property
1855 1865 * name begins with a leading protocol.
1856 1866 */
1857 1867 str = oname;
1858 1868 switch (*proto) {
1859 1869 case MOD_PROTO_TCP:
1860 1870 if (strstr(oname, "tcp_") == oname)
1861 1871 str += strlen("tcp");
1862 1872 break;
1863 1873 case MOD_PROTO_SCTP:
1864 1874 if (strstr(oname, "sctp_") == oname)
1865 1875 str += strlen("sctp");
1866 1876 break;
1867 1877 case MOD_PROTO_UDP:
1868 1878 if (strstr(oname, "udp_") == oname)
1869 1879 str += strlen("udp");
1870 1880 break;
1871 1881 case MOD_PROTO_RAWIP:
1872 1882 if (strstr(oname, "icmp_") == oname)
1873 1883 str += strlen("icmp");
1874 1884 break;
1875 1885 case MOD_PROTO_IP:
1876 1886 case MOD_PROTO_IPV4:
1877 1887 case MOD_PROTO_IPV6:
1878 1888 if (strstr(oname, "ip6_") == oname) {
1879 1889 *proto = MOD_PROTO_IPV6;
1880 1890 str += strlen("ip6");
1881 1891 } else {
1882 1892 for (ionmp = name_map; ionmp->iom_oname != NULL;
1883 1893 ionmp++) {
1884 1894 if (strcmp(oname, ionmp->iom_oname) == 0) {
1885 1895 str = ionmp->iom_nname;
1886 1896 *proto = ionmp->iom_proto;
1887 1897 break;
1888 1898 }
1889 1899 }
1890 1900 if (ionmp->iom_oname != NULL)
1891 1901 break;
1892 1902
1893 1903 if (strstr(oname, "ip_") == oname) {
1894 1904 *proto = MOD_PROTO_IP;
1895 1905 str += strlen("ip");
1896 1906 }
1897 1907 }
1898 1908 break;
1899 1909 default:
1900 1910 return (-1);
1901 1911 }
1902 1912 (void) snprintf(nname, nnamelen, "%s", str);
1903 1913 return (0);
1904 1914 }
1905 1915
1906 1916 /*
1907 1917 * Following API is required for ndd.c alone. To maintain backward
1908 1918 * compatibility with ndd output, we need to print the legacy name
1909 1919 * for the new name.
1910 1920 */
1911 1921 int
1912 1922 ipadm_new2legacy_propname(const char *oname, char *nname,
1913 1923 uint_t nnamelen, uint_t proto)
1914 1924 {
1915 1925 char *prefix;
1916 1926 ipadm_oname2nname_map_t *ionmp;
1917 1927
1918 1928 /* if it's a public property, there is nothing to prepend */
1919 1929 if (i_ipadm_get_prop_desc(oname, proto, NULL) != NULL)
1920 1930 return (-1);
1921 1931
1922 1932 switch (proto) {
1923 1933 case MOD_PROTO_TCP:
1924 1934 prefix = "tcp";
1925 1935 break;
1926 1936 case MOD_PROTO_SCTP:
1927 1937 prefix = "sctp";
1928 1938 break;
1929 1939 case MOD_PROTO_UDP:
1930 1940 prefix = "udp";
1931 1941 break;
1932 1942 case MOD_PROTO_RAWIP:
1933 1943 prefix = "icmp";
1934 1944 break;
1935 1945 case MOD_PROTO_IP:
1936 1946 case MOD_PROTO_IPV4:
1937 1947 case MOD_PROTO_IPV6:
1938 1948 /* handle special case for IP */
1939 1949 for (ionmp = name_map; ionmp->iom_oname != NULL; ionmp++) {
1940 1950 if (strcmp(oname, ionmp->iom_nname) == 0 &&
1941 1951 ionmp->iom_proto == proto) {
1942 1952 (void) strlcpy(nname, ionmp->iom_oname,
1943 1953 nnamelen);
1944 1954 return (0);
1945 1955 }
1946 1956 }
1947 1957 if (proto == MOD_PROTO_IPV6)
1948 1958 prefix = "ip6";
1949 1959 else
1950 1960 prefix = "ip";
1951 1961 break;
1952 1962 default:
1953 1963 return (-1);
1954 1964 }
1955 1965 (void) snprintf(nname, nnamelen, "%s%s", prefix, oname);
1956 1966 return (0);
1957 1967 }
|
↓ open down ↓ |
223 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX