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