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