Print this page
OS-161: Integrate IPMP changes (lint)
OS-161: Integrate IPMP changes
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/libipadm/common/ipadm_persist.c
+++ new/usr/src/lib/libipadm/common/ipadm_persist.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 *
|
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
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 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
23 + * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
23 24 */
24 25
25 26 /*
26 27 * This file contains routines to read/write formatted entries from/to
27 28 * libipadm data store /etc/ipadm/ipadm.conf. Each entry in the DB is a
28 29 * series of IPADM_NVPAIR_SEP separated (name, value) pairs, as shown
29 30 * below:
30 31 * name=value[;...]
31 32 *
32 33 * The 'name' determines how to interpret 'value'. The supported names are:
33 34 *
34 35 * IPADM_NVP_IPV6ADDR - value holds local and remote IPv6 addresses and when
35 36 * converted to nvlist, will contain nvpairs for local and remote
36 37 * addresses. These nvpairs are of type DATA_TYPE_STRING
37 38 *
38 39 * IPADM_NVP_IPV4ADDR - value holds local and remote IPv4 addresses and when
39 40 * converted to nvlist, will contain nvpairs for local and remote
40 41 * addresses. These nvpairs are of type DATA_TYPE_STRING
41 42 *
42 43 * IPADM_NVP_INTFID - value holds token, prefixlen, stateless and stateful
43 44 * info and when converted to nvlist, will contain following nvpairs
|
↓ open down ↓ |
11 lines elided |
↑ open up ↑ |
44 45 * interface_id: DATA_TYPE_UINT8_ARRAY
45 46 * prefixlen: DATA_TYPE_UINT32
46 47 * stateless: DATA_TYPE_STRING
47 48 * stateful: DATA_TYPE_STRING
48 49 *
49 50 * IPADM_NVP_DHCP - value holds wait time and primary info and when converted
50 51 * to nvlist, will contain following nvpairs
51 52 * wait: DATA_TYPE_INT32
52 53 * primary: DATA_TYPE_BOOLEAN
53 54 *
55 + * IPADM_NVP_FAMILIES - value holds interface families and when converted
56 + * to nvlist, will be a DATA_TYPE_UINT16_ARRAY
57 + *
58 + * IPADM_NVP_MIFNAMES - value holds IPMP group members and when converted
59 + * to nvlist, will be a DATA_TYPE_STRING_ARRAY
60 + *
54 61 * default - value is a single entity and when converted to nvlist, will
55 62 * contain nvpair of type DATA_TYPE_STRING. nvpairs private to
56 63 * ipadm are of this type. Further the property name and property
57 64 * values are stored as nvpairs of this type.
58 65 *
59 66 * The syntax for each line is described above the respective functions below.
60 67 */
61 68
62 69 #include <stdlib.h>
63 70 #include <strings.h>
64 71 #include <errno.h>
65 72 #include <ctype.h>
66 73 #include <sys/types.h>
|
↓ open down ↓ |
3 lines elided |
↑ open up ↑ |
67 74 #include <sys/stat.h>
68 75 #include <sys/dld.h>
69 76 #include <fcntl.h>
70 77 #include <dirent.h>
71 78 #include <unistd.h>
72 79 #include <assert.h>
73 80 #include <sys/socket.h>
74 81 #include <netinet/in.h>
75 82 #include <arpa/inet.h>
76 83 #include <sys/sockio.h>
84 +#include <sys/note.h>
77 85 #include "libipadm_impl.h"
78 86
79 87 #define MAXLINELEN 1024
80 88 #define IPADM_NVPAIR_SEP ";"
81 89 #define IPADM_NAME_SEP ","
82 90
83 91 static char ipadm_rootdir[MAXPATHLEN] = "/";
84 92
85 93 static int ipadm_process_db_line(db_wfunc_t *, void *, FILE *fp, FILE *nfp,
86 94 ipadm_db_op_t);
87 95
88 96 /*
89 97 * convert nvpair to a "name=value" string for writing to the DB.
90 98 */
|
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
91 99 typedef size_t ipadm_wfunc_t(nvpair_t *, char *, size_t);
92 100
93 101 /*
94 102 * ipadm_rfunc_t takes (`name', `value') and adds the appropriately typed
95 103 * nvpair to the nvlist.
96 104 */
97 105 typedef void ipadm_rfunc_t(nvlist_t *, char *name, char *value);
98 106
99 107 static ipadm_rfunc_t i_ipadm_str_dbline2nvl, i_ipadm_ip4_dbline2nvl,
100 108 i_ipadm_ip6_dbline2nvl, i_ipadm_intfid_dbline2nvl,
101 - i_ipadm_dhcp_dbline2nvl;
109 + i_ipadm_dhcp_dbline2nvl, i_ipadm_families_dbline2nvl,
110 + i_ipadm_groupmembers_dbline2nvl;
102 111
103 112 static ipadm_wfunc_t i_ipadm_str_nvp2dbline, i_ipadm_ip4_nvp2dbline,
104 113 i_ipadm_ip6_nvp2dbline, i_ipadm_intfid_nvp2dbline,
105 - i_ipadm_dhcp_nvp2dbline;
114 + i_ipadm_dhcp_nvp2dbline, i_ipadm_families_nvp2dbline,
115 + i_ipadm_groupmembers_nvp2dbline;
106 116
107 117 /*
108 118 * table of function pointers to read/write formatted entries from/to
109 119 * ipadm.conf.
110 120 */
111 121 typedef struct ipadm_conf_ent_s {
112 122 const char *ipent_type_name;
113 123 ipadm_wfunc_t *ipent_wfunc;
114 124 ipadm_rfunc_t *ipent_rfunc;
115 125 } ipadm_conf_ent_t;
116 126
117 127 static ipadm_conf_ent_t ipadm_conf_ent[] = {
118 128 { IPADM_NVP_IPV6ADDR, i_ipadm_ip6_nvp2dbline, i_ipadm_ip6_dbline2nvl },
119 129 { IPADM_NVP_IPV4ADDR, i_ipadm_ip4_nvp2dbline, i_ipadm_ip4_dbline2nvl },
120 130 { IPADM_NVP_INTFID, i_ipadm_intfid_nvp2dbline,
121 131 i_ipadm_intfid_dbline2nvl },
122 132 { IPADM_NVP_DHCP, i_ipadm_dhcp_nvp2dbline, i_ipadm_dhcp_dbline2nvl },
133 + { IPADM_NVP_FAMILIES, i_ipadm_families_nvp2dbline,
134 + i_ipadm_families_dbline2nvl },
135 + { IPADM_NVP_MIFNAMES, i_ipadm_groupmembers_nvp2dbline,
136 + i_ipadm_groupmembers_dbline2nvl},
123 137 { NULL, i_ipadm_str_nvp2dbline, i_ipadm_str_dbline2nvl }
124 138 };
125 139
126 140 static ipadm_conf_ent_t *
127 141 i_ipadm_find_conf_type(const char *type)
128 142 {
129 143 int i;
130 144
131 145 for (i = 0; ipadm_conf_ent[i].ipent_type_name != NULL; i++)
132 146 if (strcmp(type, ipadm_conf_ent[i].ipent_type_name) == 0)
133 147 break;
134 148 return (&ipadm_conf_ent[i]);
135 149 }
136 150
137 151 /*
138 152 * Extracts the hostnames IPADM_NVP_IPADDRHNAME and IPADM_NVP_IPDADDRHNAME from
139 153 * the given nvlist `nvl' and adds the strings to `buf'.
140 154 */
141 155 size_t
142 156 i_ipadm_ip_addhostname2dbline(nvlist_t *nvl, char *buf, size_t buflen)
143 157 {
144 158 char *cp;
145 159 char tmpbuf[IPADM_STRSIZE];
146 160
147 161 /* Add the local hostname */
148 162 if (nvlist_lookup_string(nvl, IPADM_NVP_IPADDRHNAME, &cp) != 0)
149 163 return (0);
150 164 (void) strlcat(buf, cp, buflen); /* local hostname */
151 165
152 166 /* Add the dst hostname */
153 167 if (nvlist_lookup_string(nvl, IPADM_NVP_IPDADDRHNAME, &cp) != 0) {
154 168 /* no dst addr. just add a NULL character */
155 169 (void) snprintf(tmpbuf, sizeof (tmpbuf), ",");
156 170 } else {
157 171 (void) snprintf(tmpbuf, sizeof (tmpbuf), ",%s", cp);
158 172 }
159 173 return (strlcat(buf, tmpbuf, buflen));
160 174 }
161 175
162 176 /*
163 177 * Converts IPADM_NVP_IPV4ADDR nvpair to a string representation for writing to
164 178 * the DB. The converted string format:
165 179 * ipv4addr=<local numeric IP string or hostname,remote numeric IP
166 180 * string or hostname>
167 181 */
168 182 static size_t
169 183 i_ipadm_ip4_nvp2dbline(nvpair_t *nvp, char *buf, size_t buflen)
170 184 {
171 185 nvlist_t *v;
172 186 int nbytes;
173 187
174 188 assert(nvpair_type(nvp) == DATA_TYPE_NVLIST &&
175 189 strcmp(nvpair_name(nvp), IPADM_NVP_IPV4ADDR) == 0);
176 190
177 191 (void) snprintf(buf, buflen, "%s=", IPADM_NVP_IPV4ADDR);
178 192 if (nvpair_value_nvlist(nvp, &v) != 0)
179 193 goto fail;
180 194 nbytes = i_ipadm_ip_addhostname2dbline(v, buf, buflen);
181 195 if (nbytes != 0)
182 196 return (nbytes);
183 197 fail:
184 198 buf[0] = '\0';
185 199 return (0);
186 200 }
187 201
188 202 /*
189 203 * Converts IPADM_NVP_IPV6ADDR nvpair to a string representation for writing to
190 204 * the DB. The converted string format:
191 205 * ipv6addr=<local numeric IP string or hostname,remote numeric IP
192 206 * string or hostname>
193 207 */
194 208 static size_t
195 209 i_ipadm_ip6_nvp2dbline(nvpair_t *nvp, char *buf, size_t buflen)
196 210 {
197 211 nvlist_t *v;
198 212 int nbytes;
199 213
200 214 assert(nvpair_type(nvp) == DATA_TYPE_NVLIST &&
201 215 strcmp(nvpair_name(nvp), IPADM_NVP_IPV6ADDR) == 0);
202 216
203 217 (void) snprintf(buf, buflen, "%s=", IPADM_NVP_IPV6ADDR);
204 218 if (nvpair_value_nvlist(nvp, &v) != 0)
205 219 goto fail;
206 220 nbytes = i_ipadm_ip_addhostname2dbline(v, buf, buflen);
207 221 if (nbytes != 0)
208 222 return (nbytes);
209 223 fail:
210 224 buf[0] = '\0';
211 225 return (0);
212 226 }
213 227
214 228 /*
215 229 * Converts IPADM_NVP_INTFID nvpair to a string representation for writing to
216 230 * the DB. The converted string format:
217 231 * IPADM_NVP_INTFID=<intfid/prefixlen>,{yes|no},{yes|no}
218 232 */
219 233 static size_t
220 234 i_ipadm_intfid_nvp2dbline(nvpair_t *nvp, char *buf, size_t buflen)
221 235 {
222 236 char addrbuf[IPADM_STRSIZE];
223 237 nvlist_t *v;
224 238 uint32_t prefixlen;
225 239 struct in6_addr in6addr;
226 240 char *stateless;
227 241 char *stateful;
228 242
229 243 assert(nvpair_type(nvp) == DATA_TYPE_NVLIST &&
230 244 strcmp(nvpair_name(nvp), IPADM_NVP_INTFID) == 0);
231 245
232 246 (void) snprintf(buf, buflen, "%s=", IPADM_NVP_INTFID);
233 247 if (nvpair_value_nvlist(nvp, &v) != 0)
234 248 goto fail;
235 249 if (i_ipadm_nvl2in6_addr(v, IPADM_NVP_IPNUMADDR, &in6addr) !=
236 250 IPADM_SUCCESS)
237 251 goto fail;
238 252 (void) inet_ntop(AF_INET6, &in6addr, addrbuf,
239 253 sizeof (addrbuf));
240 254 (void) strlcat(buf, addrbuf, buflen);
241 255 if (nvlist_lookup_uint32(v, IPADM_NVP_PREFIXLEN, &prefixlen) != 0 ||
242 256 nvlist_lookup_string(v, IPADM_NVP_STATELESS, &stateless) != 0 ||
243 257 nvlist_lookup_string(v, IPADM_NVP_STATEFUL, &stateful) != 0)
244 258 goto fail;
245 259 (void) snprintf(addrbuf, sizeof (addrbuf), "/%d,%s,%s",
246 260 prefixlen, stateless, stateful);
247 261 return (strlcat(buf, addrbuf, buflen));
248 262 fail:
249 263 buf[0] = '\0';
250 264 return (0);
251 265 }
252 266
253 267 /*
254 268 * Converts IPADM_NVP_DHCP nvpair to a string representation for writing to the
255 269 * DB. The converted string format:
256 270 * IPADM_NVP_DHCP=<wait_time>,{yes|no}
257 271 */
258 272 static size_t
259 273 i_ipadm_dhcp_nvp2dbline(nvpair_t *nvp, char *buf, size_t buflen)
260 274 {
261 275 char addrbuf[IPADM_STRSIZE];
262 276 int32_t wait;
263 277 boolean_t primary;
264 278 nvlist_t *v;
265 279
266 280 assert(nvpair_type(nvp) == DATA_TYPE_NVLIST &&
267 281 strcmp(nvpair_name(nvp), IPADM_NVP_DHCP) == 0);
268 282
269 283 if (nvpair_value_nvlist(nvp, &v) != 0 ||
270 284 nvlist_lookup_int32(v, IPADM_NVP_WAIT, &wait) != 0 ||
271 285 nvlist_lookup_boolean_value(v, IPADM_NVP_PRIMARY, &primary) != 0) {
272 286 return (0);
273 287 }
274 288 (void) snprintf(buf, buflen, "%s=", IPADM_NVP_DHCP);
275 289 (void) snprintf(addrbuf, sizeof (addrbuf), "%d,%s", wait,
276 290 (primary ? "yes" : "no"));
277 291 return (strlcat(buf, addrbuf, buflen));
278 292 }
279 293
280 294 /*
281 295 * Constructs a "<name>=<value>" string from the nvpair, whose type must
282 296 * be STRING.
283 297 */
284 298 static size_t
285 299 i_ipadm_str_nvp2dbline(nvpair_t *nvp, char *buf, size_t buflen)
286 300 {
287 301 char *str = NULL;
288 302
289 303 assert(nvpair_type(nvp) == DATA_TYPE_STRING);
290 304 if (nvpair_value_string(nvp, &str) != 0)
291 305 return (0);
292 306 return (snprintf(buf, buflen, "%s=%s", nvpair_name(nvp), str));
293 307 }
294 308
295 309 /*
296 310 * Converts a nvlist to string of the form:
297 311 * <prop0>=<val0>,...,<valn>;...;<propn>=<val0>,...,<valn>;
298 312 */
299 313 size_t
300 314 ipadm_nvlist2str(nvlist_t *nvl, char *buf, size_t buflen)
301 315 {
302 316 nvpair_t *nvp = NULL;
303 317 uint_t nbytes = 0, tbytes = 0;
304 318 ipadm_conf_ent_t *ipent;
305 319 size_t bufsize = buflen;
306 320
307 321 for (nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL;
308 322 nvp = nvlist_next_nvpair(nvl, nvp)) {
309 323 ipent = i_ipadm_find_conf_type(nvpair_name(nvp));
310 324 nbytes = (*ipent->ipent_wfunc)(nvp, buf, buflen);
311 325 /* add nvpair separator */
312 326 nbytes += snprintf(buf + nbytes, buflen - nbytes, "%s",
313 327 IPADM_NVPAIR_SEP);
314 328 buflen -= nbytes;
315 329 buf += nbytes;
316 330 tbytes += nbytes;
317 331 if (tbytes >= bufsize) /* buffer overflow */
318 332 return (0);
319 333 }
320 334 nbytes = snprintf(buf, buflen, "%c%c", '\n', '\0');
321 335 tbytes += nbytes;
322 336 if (tbytes >= bufsize)
323 337 return (0);
324 338 return (tbytes);
325 339 }
326 340
327 341 /*
328 342 * Adds a nvpair, using the `name' and `value', to the nvlist in `nvl'.
329 343 * The value will be interpreted as explained at the top of this file.
330 344 */
331 345 static void
332 346 i_ipadm_add_nvpair(nvlist_t *nvl, char *name, char *value)
333 347 {
334 348 ipadm_conf_ent_t *ipent;
335 349
336 350 ipent = i_ipadm_find_conf_type(name);
337 351 (*ipent->ipent_rfunc)(nvl, name, value);
338 352 }
339 353
340 354 /*
341 355 * Adds an nvpair for IPv4 addr to the nvlist. The "name" is the string in
342 356 * IPADM_NVP_IPV4ADDR. The "value" for IPADM_NVP_IPV4ADDR is another nvlist.
343 357 * Allocate the value nvlist for IPADM_NVP_IPV4ADDR if necessary, and add
344 358 * the address and hostnames from the address object `ipaddr' to it.
345 359 * Then add the allocated nvlist to `nvl'.
346 360 */
347 361 ipadm_status_t
348 362 i_ipadm_add_ipaddr2nvl(nvlist_t *nvl, ipadm_addrobj_t ipaddr)
349 363 {
350 364 nvlist_t *nvl_addr = NULL;
351 365 int err;
352 366 char *name;
353 367 sa_family_t af = ipaddr->ipadm_af;
354 368
355 369 if (af == AF_INET) {
356 370 name = IPADM_NVP_IPV4ADDR;
357 371 } else {
358 372 assert(af == AF_INET6);
359 373 name = IPADM_NVP_IPV6ADDR;
360 374 }
361 375
362 376 if (!nvlist_exists(nvl, name)) {
363 377 if ((err = nvlist_alloc(&nvl_addr, NV_UNIQUE_NAME, 0)) != 0)
364 378 return (ipadm_errno2status(err));
365 379 if ((err = nvlist_add_nvlist(nvl, name, nvl_addr)) != 0) {
366 380 nvlist_free(nvl_addr);
367 381 return (ipadm_errno2status(err));
368 382 }
369 383 nvlist_free(nvl_addr);
370 384 }
371 385 if ((err = nvlist_lookup_nvlist(nvl, name, &nvl_addr)) != 0 ||
372 386 (err = nvlist_add_string(nvl_addr, IPADM_NVP_IPADDRHNAME,
373 387 ipaddr->ipadm_static_aname)) != 0)
374 388 return (ipadm_errno2status(err));
375 389 if (ipaddr->ipadm_static_dname[0] != '\0') {
376 390 if ((err = nvlist_add_string(nvl_addr, IPADM_NVP_IPDADDRHNAME,
377 391 ipaddr->ipadm_static_dname)) != 0)
378 392 return (ipadm_errno2status(err));
379 393 }
380 394
381 395 return (IPADM_SUCCESS);
382 396 }
383 397
384 398 /*
385 399 * Adds an nvpair for IPv6 interface id to the nvlist. The "name" is
386 400 * the string in IPADM_NVP_INTFID. The "value" for IPADM_NVP_INTFID is another
387 401 * nvlist. Allocate the value nvlist for IPADM_NVP_INTFID if necessary, and add
388 402 * the interface id and its prefixlen from the address object `ipaddr' to it.
389 403 * Then add the allocated nvlist to `nvl'.
390 404 */
391 405 ipadm_status_t
392 406 i_ipadm_add_intfid2nvl(nvlist_t *nvl, ipadm_addrobj_t addr)
393 407 {
394 408 nvlist_t *nvl_addr = NULL;
395 409 struct in6_addr addr6;
396 410 int err;
397 411
398 412 if (!nvlist_exists(nvl, IPADM_NVP_INTFID)) {
399 413 if ((err = nvlist_alloc(&nvl_addr, NV_UNIQUE_NAME, 0)) != 0)
400 414 return (ipadm_errno2status(err));
401 415 if ((err = nvlist_add_nvlist(nvl, IPADM_NVP_INTFID,
402 416 nvl_addr)) != 0) {
403 417 nvlist_free(nvl_addr);
404 418 return (ipadm_errno2status(err));
405 419 }
406 420 nvlist_free(nvl_addr);
407 421 }
408 422 if ((err = nvlist_lookup_nvlist(nvl, IPADM_NVP_INTFID,
409 423 &nvl_addr)) != 0 || (err = nvlist_add_uint32(nvl_addr,
410 424 IPADM_NVP_PREFIXLEN, addr->ipadm_intfidlen)) != 0) {
411 425 return (ipadm_errno2status(err));
412 426 }
413 427 addr6 = addr->ipadm_intfid.sin6_addr;
414 428 if ((err = nvlist_add_uint8_array(nvl_addr, IPADM_NVP_IPNUMADDR,
415 429 addr6.s6_addr, 16)) != 0) {
416 430 return (ipadm_errno2status(err));
417 431 }
418 432 if (addr->ipadm_stateless)
419 433 err = nvlist_add_string(nvl_addr, IPADM_NVP_STATELESS, "yes");
420 434 else
421 435 err = nvlist_add_string(nvl_addr, IPADM_NVP_STATELESS, "no");
422 436 if (err != 0)
423 437 return (ipadm_errno2status(err));
424 438 if (addr->ipadm_stateful)
425 439 err = nvlist_add_string(nvl_addr, IPADM_NVP_STATEFUL, "yes");
426 440 else
427 441 err = nvlist_add_string(nvl_addr, IPADM_NVP_STATEFUL, "no");
428 442 if (err != 0)
429 443 return (ipadm_errno2status(err));
430 444
431 445 return (IPADM_SUCCESS);
432 446 }
433 447
434 448 /*
435 449 * Adds an nvpair for a dhcp address object to the nvlist. The "name" is
436 450 * the string in IPADM_NVP_DHCP. The "value" for IPADM_NVP_DHCP is another
437 451 * nvlist. Allocate the value nvlist for IPADM_NVP_DHCP if necessary, and add
438 452 * the parameters from the arguments `primary' and `wait'.
439 453 * Then add the allocated nvlist to `nvl'.
440 454 */
441 455 ipadm_status_t
442 456 i_ipadm_add_dhcp2nvl(nvlist_t *nvl, boolean_t primary, int32_t wait)
443 457 {
444 458 nvlist_t *nvl_dhcp = NULL;
445 459 int err;
446 460
447 461 if (!nvlist_exists(nvl, IPADM_NVP_DHCP)) {
448 462 if ((err = nvlist_alloc(&nvl_dhcp, NV_UNIQUE_NAME, 0)) != 0)
449 463 return (ipadm_errno2status(err));
450 464 if ((err = nvlist_add_nvlist(nvl, IPADM_NVP_DHCP,
451 465 nvl_dhcp)) != 0) {
452 466 nvlist_free(nvl_dhcp);
453 467 return (ipadm_errno2status(err));
454 468 }
455 469 nvlist_free(nvl_dhcp);
456 470 }
457 471 if ((err = nvlist_lookup_nvlist(nvl, IPADM_NVP_DHCP, &nvl_dhcp)) != 0 ||
458 472 (err = nvlist_add_int32(nvl_dhcp, IPADM_NVP_WAIT, wait)) != 0 ||
459 473 (err = nvlist_add_boolean_value(nvl_dhcp, IPADM_NVP_PRIMARY,
460 474 primary)) != 0) {
461 475 return (ipadm_errno2status(err));
462 476 }
463 477
464 478 return (IPADM_SUCCESS);
465 479 }
466 480
467 481 /*
468 482 * Add (name, value) as an nvpair of type DATA_TYPE_STRING to nvlist.
469 483 */
470 484 static void
471 485 i_ipadm_str_dbline2nvl(nvlist_t *nvl, char *name, char *value)
472 486 {
473 487 /* if value is NULL create an empty node */
474 488 if (value == NULL)
475 489 (void) nvlist_add_string(nvl, name, "");
476 490 else
477 491 (void) nvlist_add_string(nvl, name, value);
478 492 }
479 493
480 494 /*
481 495 * `name' = IPADM_NVP_IPV4ADDR and
482 496 * `value' = <local numeric IP string or hostname,remote numeric IP string or
483 497 * hostname>
484 498 * This function will add an nvlist with the hostname information in
485 499 * nvpairs to the nvlist in `nvl'.
486 500 */
487 501 static void
488 502 i_ipadm_ip4_dbline2nvl(nvlist_t *nvl, char *name, char *value)
489 503 {
490 504 char *cp, *hname;
491 505 struct ipadm_addrobj_s ipaddr;
492 506
493 507 assert(strcmp(name, IPADM_NVP_IPV4ADDR) == 0 && value != NULL);
494 508
495 509 bzero(&ipaddr, sizeof (ipaddr));
496 510 ipaddr.ipadm_af = AF_INET;
497 511
498 512 hname = value; /* local hostname */
499 513 cp = strchr(hname, ',');
500 514 assert(cp != NULL);
501 515 *cp++ = '\0';
502 516 (void) strlcpy(ipaddr.ipadm_static_aname, hname,
503 517 sizeof (ipaddr.ipadm_static_aname));
504 518
505 519 if (*cp != '\0') {
506 520 /* we have a dst hostname */
507 521 (void) strlcpy(ipaddr.ipadm_static_dname, cp,
508 522 sizeof (ipaddr.ipadm_static_dname));
509 523 }
510 524 (void) i_ipadm_add_ipaddr2nvl(nvl, &ipaddr);
511 525 }
512 526
513 527 /*
514 528 * `name' = IPADM_NVP_IPV6ADDR and
515 529 * `value' = <local numeric IP string or hostname,remote numeric IP string or
516 530 * hostname>
517 531 * This function will add an nvlist with the hostname information in
518 532 * nvpairs to the nvlist in `nvl'.
519 533 */
520 534 static void
521 535 i_ipadm_ip6_dbline2nvl(nvlist_t *nvl, char *name, char *value)
522 536 {
523 537 char *cp, *hname;
524 538 struct ipadm_addrobj_s ipaddr;
525 539
526 540 assert(strcmp(name, IPADM_NVP_IPV6ADDR) == 0 && value != NULL);
527 541
528 542 bzero(&ipaddr, sizeof (ipaddr));
529 543 ipaddr.ipadm_af = AF_INET6;
530 544
531 545 hname = value; /* local hostname */
532 546 cp = strchr(hname, ',');
533 547 assert(cp != NULL);
534 548 *cp++ = '\0';
535 549 (void) strlcpy(ipaddr.ipadm_static_aname, hname,
536 550 sizeof (ipaddr.ipadm_static_aname));
537 551
538 552 if (*cp != '\0') {
539 553 /* we have a dst hostname */
540 554 (void) strlcpy(ipaddr.ipadm_static_dname, cp,
541 555 sizeof (ipaddr.ipadm_static_dname));
542 556 }
543 557 (void) i_ipadm_add_ipaddr2nvl(nvl, &ipaddr);
544 558 }
545 559
546 560 /*
547 561 * `name' = IPADM_NVP_INTFID and `value' = <intfid/prefixlen>,{yes,no},{yes|no}
548 562 * This function will add an nvlist with the address object information in
549 563 * nvpairs to the nvlist in `nvl'.
550 564 */
551 565 static void
552 566 i_ipadm_intfid_dbline2nvl(nvlist_t *nvl, char *name, char *value)
553 567 {
554 568 char *cp;
555 569 struct ipadm_addrobj_s ipaddr;
556 570 char *endp;
557 571 char *prefixlen;
558 572 char *stateless;
559 573 char *stateful;
560 574
561 575 assert(strcmp(name, IPADM_NVP_INTFID) == 0 && value != NULL);
562 576
563 577 bzero(&ipaddr, sizeof (ipaddr));
564 578
565 579 cp = strchr(value, '/');
566 580 assert(cp != NULL);
567 581
568 582 *cp++ = '\0';
569 583 ipaddr.ipadm_intfid.sin6_family = AF_INET6;
570 584 (void) inet_pton(AF_INET6, value, &ipaddr.ipadm_intfid.sin6_addr);
571 585
572 586 prefixlen = cp;
573 587 cp = strchr(cp, ',');
574 588 assert(cp != NULL);
575 589 *cp++ = '\0';
576 590
577 591 errno = 0;
578 592 ipaddr.ipadm_intfidlen = (uint32_t)strtoul(prefixlen, &endp, 10);
579 593 if (*endp != '\0' || errno != 0)
580 594 return;
581 595
582 596 stateless = cp;
583 597 stateful = strchr(stateless, ',');
584 598 assert(stateful != NULL);
585 599 *stateful++ = '\0';
586 600 ipaddr.ipadm_stateless = (strcmp(stateless, "yes") == 0);
587 601 ipaddr.ipadm_stateful = (strcmp(stateful, "yes") == 0);
588 602
589 603 /* Add all of it to the given nvlist */
590 604 (void) i_ipadm_add_intfid2nvl(nvl, &ipaddr);
591 605 }
592 606
593 607 /*
594 608 * `name' = IPADM_NVP_DHCP and `value' = <wait_time>,{yes|no}
595 609 * This function will add an nvlist with the dhcp address object information in
596 610 * nvpairs to the nvlist in `nvl'.
597 611 */
598 612 static void
599 613 i_ipadm_dhcp_dbline2nvl(nvlist_t *nvl, char *name, char *value)
600 614 {
601 615 char *cp;
602 616 char *endp;
603 617 long wait_time;
604 618 boolean_t primary;
605 619
606 620 assert(strcmp(name, IPADM_NVP_DHCP) == 0 && value != NULL);
607 621 cp = strchr(value, ',');
|
↓ open down ↓ |
475 lines elided |
↑ open up ↑ |
608 622 assert(cp != NULL);
609 623 *cp++ = '\0';
610 624 errno = 0;
611 625 wait_time = strtol(value, &endp, 10);
612 626 if (*endp != '\0' || errno != 0)
613 627 return;
614 628 primary = (strcmp(cp, "yes") == 0);
615 629 (void) i_ipadm_add_dhcp2nvl(nvl, primary, (int32_t)wait_time);
616 630 }
617 631
632 +/*
633 + * Input 'nvp': name = IPADM_NVP_FAMILIES and value = array of 'uint16_t'
634 + *
635 + *
636 + */
637 +static size_t
638 +i_ipadm_families_nvp2dbline(nvpair_t *nvp, char *buf, size_t buflen)
639 +{
640 + uint_t nelem = 0;
641 + uint16_t *elem;
642 +
643 + assert(nvpair_type(nvp) == DATA_TYPE_UINT16_ARRAY);
644 +
645 + if (nvpair_value_uint16_array(nvp,
646 + &elem, &nelem) != 0) {
647 + buf[0] = '\0';
648 + return (0);
649 + }
650 +
651 + assert(nelem != 0 || nelem > 2);
652 +
653 + if (nelem == 1) {
654 + return (snprintf(buf, buflen, "%s=%d",
655 + nvpair_name(nvp), elem[0]));
656 + } else {
657 + return (snprintf(buf, buflen, "%s=%d,%d",
658 + nvpair_name(nvp), elem[0], elem[1]));
659 + }
660 +}
661 +
662 +/*
663 + * name = IPADM_NVP_FAMILIES and value = <FAMILY>[,FAMILY]
664 + *
665 + * output nvp: name = IPADM_NVP_FAMILIES and value = array of 'uint16_t'
666 + *
667 + */
668 +static void
669 +i_ipadm_families_dbline2nvl(nvlist_t *nvl, char *name, char *value)
670 +{
671 + _NOTE(ARGUNUSED(name))
672 + uint16_t families[2];
673 + uint_t nelem = 0;
674 + char *val, *lasts;
675 +
676 + if ((val = strtok_r(value,
677 + ",", &lasts)) != NULL) {
678 + families[0] = atoi(val);
679 + nelem++;
680 + if ((val = strtok_r(NULL,
681 + ",", &lasts)) != NULL) {
682 + families[1] = atoi(val);
683 + nelem++;
684 + }
685 + (void) nvlist_add_uint16_array(nvl,
686 + IPADM_NVP_FAMILIES, families, nelem);
687 + }
688 +}
689 +
690 +/*
691 + * input nvp: name = IPADM_NVP_MIFNAMES and value = array of 'char *'
692 + *
693 + *
694 + */
695 +static size_t
696 +i_ipadm_groupmembers_nvp2dbline(nvpair_t *nvp, char *buf, size_t buflen)
697 +{
698 + uint_t nelem = 0;
699 + char **elem;
700 + size_t n;
701 +
702 + assert(nvpair_type(nvp) == DATA_TYPE_STRING_ARRAY);
703 +
704 + if (nvpair_value_string_array(nvp,
705 + &elem, &nelem) != 0) {
706 + buf[0] = '\0';
707 + return (0);
708 + }
709 +
710 + assert(nelem != 0);
711 +
712 + n = snprintf(buf, buflen, "%s=", IPADM_NVP_MIFNAMES);
713 + if (n >= buflen)
714 + return (n);
715 +
716 + while (nelem-- > 0) {
717 + n = strlcat(buf, elem[nelem], buflen);
718 + if (nelem > 0)
719 + n = strlcat(buf, ",", buflen);
720 +
721 + if (n > buflen)
722 + return (n);
723 + }
724 +
725 + return (n);
726 +}
727 +
728 +/*
729 + * name = IPADM_NVP_MIFNAMES and value = <if_name>[,if_name]
730 + *
731 + * output nvp: name = IPADM_NVP_MIFNAMES and value = array of 'char *'
732 + */
733 +static void
734 +i_ipadm_groupmembers_dbline2nvl(nvlist_t *nvl, char *name, char *value)
735 +{
736 + char *members[256];
737 + char *member;
738 + char *val, *lasts;
739 + uint_t m_cnt = 0;
740 +
741 + assert(strcmp(name, IPADM_NVP_MIFNAMES) == 0 && value != NULL);
742 +
743 + if ((val = strtok_r(value, ",", &lasts)) != NULL) {
744 + if ((member = calloc(1, LIFNAMSIZ)) == NULL)
745 + return;
746 +
747 + (void) strlcpy(member, val, LIFNAMSIZ);
748 + members[m_cnt++] = member;
749 +
750 + while ((val = strtok_r(NULL, ",", &lasts)) != NULL) {
751 + if ((member = calloc(1, LIFNAMSIZ)) == NULL)
752 + goto fail;
753 +
754 + (void) strlcpy(member, val, LIFNAMSIZ);
755 + members[m_cnt++] = member;
756 + }
757 +
758 + (void) nvlist_add_string_array(nvl, IPADM_NVP_MIFNAMES,
759 + members, m_cnt);
760 + }
761 +
762 +fail:
763 + while (m_cnt-- > 0) {
764 + free(members[m_cnt]);
765 + }
766 +}
767 +
618 768 /*
619 769 * Parses the buffer, for name-value pairs and creates nvlist. The value
620 770 * is always considered to be a string.
621 771 */
622 772 int
623 773 ipadm_str2nvlist(const char *inbuf, nvlist_t **ipnvl, uint_t flags)
624 774 {
625 775 char *nv, *name, *val, *buf, *cp, *sep;
626 776 int err;
627 777
628 778 if (inbuf == NULL || inbuf[0] == '\0' || ipnvl == NULL)
629 779 return (EINVAL);
630 780 *ipnvl = NULL;
631 781
632 782 /*
633 783 * If IPADM_NORVAL is set, then `inbuf' should be comma delimited values
634 784 */
635 785 if ((flags & IPADM_NORVAL) && strchr(inbuf, '=') != NULL)
636 786 return (EINVAL);
637 787
638 788 if ((cp = buf = strdup(inbuf)) == NULL)
639 789 return (errno);
640 790
641 791 while (isspace(*buf))
642 792 buf++;
643 793
644 794 if (*buf == '\0') {
645 795 err = EINVAL;
646 796 goto fail;
647 797 }
648 798
649 799 nv = buf;
650 800 /*
651 801 * work on one nvpair at a time and extract the name and value
652 802 */
653 803 sep = ((flags & IPADM_NORVAL) ? IPADM_NAME_SEP : IPADM_NVPAIR_SEP);
654 804 while ((nv = strsep(&buf, sep)) != NULL) {
655 805 if (*nv == '\n')
656 806 continue;
657 807 name = nv;
658 808 if ((val = strchr(nv, '=')) != NULL)
659 809 *val++ = '\0';
660 810 if (*ipnvl == NULL &&
661 811 (err = nvlist_alloc(ipnvl, NV_UNIQUE_NAME, 0)) != 0)
662 812 goto fail;
663 813 if (nvlist_exists(*ipnvl, name)) {
664 814 err = EEXIST;
665 815 goto fail;
666 816 }
667 817 /* Add the extracted nvpair to the nvlist `ipnvl'. */
668 818 (void) i_ipadm_add_nvpair(*ipnvl, name, val);
669 819 }
670 820 free(cp);
671 821 return (0);
672 822 fail:
673 823 free(cp);
674 824 nvlist_free(*ipnvl);
675 825 *ipnvl = NULL;
676 826 return (err);
677 827 }
678 828
679 829 /*
680 830 * Opens the data store for read/write operation. For write operation we open
681 831 * another file and scribble the changes to it and copy the new file back to
682 832 * old file.
683 833 */
684 834 int
685 835 ipadm_rw_db(db_wfunc_t *db_walk_func, void *arg, const char *db_file,
686 836 mode_t db_perms, ipadm_db_op_t db_op)
687 837 {
688 838 FILE *fp, *nfp = NULL;
689 839 char file[MAXPATHLEN];
690 840 char newfile[MAXPATHLEN];
691 841 int nfd;
692 842 boolean_t writeop;
693 843 int err = 0;
694 844
695 845 writeop = (db_op != IPADM_DB_READ);
696 846
697 847 (void) snprintf(file, MAXPATHLEN, "%s/%s", ipadm_rootdir, db_file);
698 848
699 849 /* open the data store */
700 850 if ((fp = fopen(file, (writeop ? "r+" : "r"))) == NULL)
701 851 return (errno);
702 852
703 853 if (writeop) {
704 854 (void) snprintf(newfile, MAXPATHLEN, "%s/%s.new",
705 855 ipadm_rootdir, db_file);
706 856 if ((nfd = open(newfile, O_WRONLY | O_CREAT | O_TRUNC,
707 857 db_perms)) < 0) {
708 858 err = errno;
709 859 (void) fclose(fp);
710 860 return (err);
711 861 }
712 862
713 863 if ((nfp = fdopen(nfd, "w")) == NULL) {
714 864 err = errno;
715 865 (void) close(nfd);
716 866 (void) fclose(fp);
717 867 (void) unlink(newfile);
718 868 return (err);
719 869 }
720 870 }
721 871 err = ipadm_process_db_line(db_walk_func, arg, fp, nfp, db_op);
722 872 if (!writeop)
723 873 goto done;
724 874 if (err != 0 && err != ENOENT)
725 875 goto done;
726 876
727 877 if (fflush(nfp) == EOF) {
728 878 err = errno;
729 879 goto done;
730 880 }
731 881 (void) fclose(fp);
732 882 (void) fclose(nfp);
733 883
734 884 if (rename(newfile, file) < 0) {
735 885 err = errno;
736 886 (void) unlink(newfile);
737 887 }
738 888 return (err);
739 889 done:
740 890 if (nfp != NULL) {
741 891 (void) fclose(nfp);
742 892 if (err != 0)
743 893 (void) unlink(newfile);
744 894 }
745 895 (void) fclose(fp);
746 896 return (err);
747 897 }
748 898
749 899 /*
750 900 * Processes each line of the configuration file, skipping lines with
751 901 * leading spaces, blank lines and comments. The line form the DB
752 902 * is converted to nvlist and the callback function is called to process
753 903 * the list. The buf could be modified by the callback function and
754 904 * if this is a write operation and buf is not truncated, buf will
755 905 * be written to disk.
756 906 *
757 907 * Further if cont is set to B_FALSE, the remainder of the file will
758 908 * continue to be read (however callback function will not be called) and,
759 909 * if necessary, written to disk as well.
760 910 */
761 911 static int
762 912 ipadm_process_db_line(db_wfunc_t *db_walk_func, void *arg, FILE *fp, FILE *nfp,
763 913 ipadm_db_op_t db_op)
764 914 {
765 915 int err = 0;
766 916 char buf[MAXLINELEN];
767 917 boolean_t cont = B_TRUE;
768 918 int i, len;
769 919 nvlist_t *db_nvl = NULL;
770 920 boolean_t line_deleted = B_FALSE;
771 921
772 922 while (fgets(buf, MAXLINELEN, fp) != NULL) {
773 923 /*
774 924 * Skip leading spaces, blank lines, and comments.
775 925 */
776 926 len = strnlen(buf, MAXLINELEN);
777 927 for (i = 0; i < len; i++) {
778 928 if (!isspace(buf[i]))
779 929 break;
780 930 }
781 931
782 932 if (i != len && buf[i] != '#' && cont) {
783 933 if (ipadm_str2nvlist(buf, &db_nvl, 0) == 0) {
784 934 cont = db_walk_func(arg, db_nvl, buf,
785 935 MAXLINELEN, &err);
786 936 } else {
787 937 /* Delete corrupted line. */
788 938 buf[0] = '\0';
789 939 }
790 940 nvlist_free(db_nvl);
791 941 db_nvl = NULL;
792 942 }
793 943 if (err != 0)
794 944 break;
795 945 if (nfp != NULL && buf[0] == '\0')
796 946 line_deleted = B_TRUE;
797 947 if (nfp != NULL && buf[0] != '\0' && fputs(buf, nfp) == EOF) {
798 948 err = errno;
799 949 break;
800 950 }
801 951 }
802 952
803 953 if (err != 0 || !cont)
804 954 return (err);
805 955
806 956 if (db_op == IPADM_DB_WRITE) {
807 957 nvlist_t *nvl;
808 958
809 959 /*
810 960 * `arg' will be NULL when we are doing in-line update of
811 961 * entries.
812 962 */
813 963 if (arg != NULL) {
814 964 nvl = ((ipadm_dbwrite_cbarg_t *)arg)->dbw_nvl;
815 965 /*
816 966 * If the specified entry is not found above, we add
817 967 * the entry to the configuration file, here.
818 968 */
819 969 (void) memset(buf, 0, MAXLINELEN);
820 970 if (ipadm_nvlist2str(nvl, buf, MAXLINELEN) == 0)
821 971 err = ENOBUFS;
822 972 else if (fputs(buf, nfp) == EOF)
823 973 err = errno;
824 974 }
825 975 return (err);
826 976 }
827 977
828 978 if (db_op == IPADM_DB_DELETE && line_deleted)
829 979 return (0);
830 980
831 981 /* if we have come this far, then we didn't find any match */
832 982 return (ENOENT);
833 983 }
|
↓ open down ↓ |
206 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX