1/*
2 * Copyright (c) 1999 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23/*
24 * netinfo.c - Routines for dealing with the NetInfo database.
25 *
26 **********************************************************************
27 * HISTORY
28 * 10-Jun-89  Peter King
29 *	Created.
30 * 23-Feb-98  Dieter Siegmund (dieter@apple.com)
31 *      Removed all of the promiscous-related stuff,
32 *	left with routines to do host creation/lookup.
33 * 11-Sep-06  Dieter Siegmund (dieter@apple.com)
34 *	Imported netinfo code from Libinfo
35 **********************************************************************
36 */
37
38/*
39 * Include Files
40 */
41#include <ctype.h>
42#include <pwd.h>
43#include <netdb.h>
44#include <string.h>
45#include <syslog.h>
46#include <sys/types.h>
47#include <sys/socket.h>
48#include <net/if.h>
49#include <netinet/in.h>
50#include <netinet/if_ether.h>
51#include <arpa/inet.h>
52#include <string.h>
53#include <unistd.h>
54#include <stdlib.h>
55#include <stdio.h>
56#include "host_identifier.h"
57#include "netinfo.h"
58
59/*
60 * Imported from Libinfo START ---v
61 */
62#define  mm_used() mstats()
63
64#define MM_ALLOC(obj) obj = ((void *)malloc(sizeof(*(obj))))
65
66#define MM_FREE(obj)  free((void *)(obj))
67
68#define MM_ZERO(obj)  bzero((void *)(obj), sizeof(*(obj)))
69
70#define MM_BCOPY(b1, b2, size) bcopy((void *)(b1), (void *)(b2), \
71				     (unsigned)(size))
72
73#define MM_BEQ(b1, b2, size) (bcmp((void *)(b1), (void *)(b2), \
74				   (unsigned)(size)) == 0)
75
76#define MM_ALLOC_ARRAY(obj, len)  \
77	obj = ((void *)malloc(sizeof(*(obj)) * (len)))
78
79#define MM_ZERO_ARRAY(obj, len) bzero((void *)(obj), sizeof(*obj) * len)
80
81#define MM_FREE_ARRAY(obj, len) free((void *)(obj))
82
83#define MM_GROW_ARRAY(obj, len) \
84	((obj == NULL) ? (MM_ALLOC_ARRAY((obj), (len) + 1)) : \
85	 (obj = (void *)realloc((void *)(obj), \
86				sizeof(*(obj)) * ((len) + 1))))
87
88#define MM_SHRINK_ARRAY(obj, len) \
89	obj = (void *)realloc((void *)(obj), \
90			      sizeof(*(obj)) * ((len) - 1))
91
92void
93ni_proplist_insert(
94		ni_proplist *pl,
95		const ni_property prop,
96		ni_index where
97		)
98{
99	ni_index i;
100
101	MM_GROW_ARRAY(pl->nipl_val, pl->nipl_len);
102	for (i = pl->nipl_len; i > where; i--) {
103		pl->nipl_val[i] = pl->nipl_val[i - 1];
104	}
105	pl->nipl_val[i] = ni_prop_dup(prop);
106	pl->nipl_len++;
107}
108
109void
110ni_proplist_delete(
111		ni_proplist *pl,
112		ni_index which
113		)
114{
115	int i;
116
117	ni_prop_free(&pl->nipl_val[which]);
118	for (i = which + 1; i < pl->nipl_len; i++) {
119		pl->nipl_val[i - 1] = pl->nipl_val[i];
120	}
121	MM_SHRINK_ARRAY(pl->nipl_val, pl->nipl_len--);
122}
123
124void
125ni_proplist_free(
126		 ni_proplist *pl
127		 )
128{
129	ni_index i;
130
131	if (pl->nipl_val == NULL) {
132		return;
133	}
134	for (i = 0; i < pl->nipl_len; i++) {
135		ni_prop_free(&pl->nipl_val[i]);
136	}
137	MM_FREE_ARRAY(pl->nipl_val, pl->nipl_len);
138	NI_INIT(pl);
139}
140
141ni_proplist
142ni_proplist_dup(
143	     const ni_proplist pl
144	     )
145{
146	ni_proplist newlist;
147	ni_index i;
148
149	newlist.nipl_len = pl.nipl_len;
150	MM_ALLOC_ARRAY(newlist.nipl_val, pl.nipl_len);
151	for (i = 0; i < pl.nipl_len; i++) {
152		newlist.nipl_val[i].nip_name = ni_name_dup(pl.nipl_val[i].nip_name);
153		newlist.nipl_val[i].nip_val = ni_namelist_dup(pl.nipl_val[i].nip_val);
154	}
155	return (newlist);
156}
157
158ni_index
159ni_proplist_match(
160	       const ni_proplist pl,
161	       ni_name_const pname,
162	       ni_name_const pval
163	   )
164{
165	ni_index i;
166	ni_index j;
167	ni_namelist nl;
168
169	for (i = 0; i < pl.nipl_len; i++) {
170		if (ni_name_match(pname, pl.nipl_val[i].nip_name)) {
171			if (pval == NULL) {
172				return (i);
173			}
174			nl = pl.nipl_val[i].nip_val;
175			for (j = 0; j < nl.ninl_len; j++) {
176				if (ni_name_match(pval, nl.ninl_val[j])) {
177					return (i);
178				}
179			}
180			break;
181		}
182	}
183	return (NI_INDEX_NULL);
184}
185
186
187ni_property
188ni_prop_dup(
189	 const ni_property prop
190	 )
191{
192	ni_property newprop;
193
194	newprop.nip_name = ni_name_dup(prop.nip_name);
195	newprop.nip_val = ni_namelist_dup(prop.nip_val);
196	return (newprop);
197}
198
199void
200ni_prop_free(
201	     ni_property *prop
202	     )
203{
204	ni_name_free(&prop->nip_name);
205	ni_namelist_free(&prop->nip_val);
206}
207
208int
209ni_name_match(
210	   ni_name_const nm1,
211	   ni_name_const nm2
212	   )
213{
214	return (strcmp(nm1, nm2) == 0);
215}
216
217ni_name
218ni_name_dup(
219	 ni_name_const nm
220	 )
221{
222	return (strcpy(malloc(strlen(nm) + 1), nm));
223}
224
225
226void
227ni_name_free(
228	     ni_name *nm
229	     )
230{
231	if (*nm != NULL) {
232		free(*nm);
233		*nm = NULL;
234	}
235}
236
237ni_namelist
238ni_namelist_dup(
239	     const ni_namelist nl
240	     )
241{
242	ni_namelist newlist;
243	ni_index i;
244
245	newlist.ninl_len = nl.ninl_len;
246	MM_ALLOC_ARRAY(newlist.ninl_val, newlist.ninl_len);
247	for (i = 0; i < nl.ninl_len; i++) {
248		newlist.ninl_val[i] = ni_name_dup(nl.ninl_val[i]);
249	}
250	return (newlist);
251}
252
253void
254ni_namelist_free(
255	      ni_namelist *nl
256	      )
257{
258	ni_index i;
259
260	if (nl->ninl_val == NULL) {
261		return;
262	}
263	for (i = 0; i < nl->ninl_len; i++) {
264		ni_name_free(&nl->ninl_val[i]);
265	}
266	MM_FREE_ARRAY(nl->ninl_val, nl->ninl_len);
267	NI_INIT(nl);
268}
269
270void
271ni_namelist_insert(
272		ni_namelist *nl,
273		ni_name_const nm,
274		ni_index where
275		)
276{
277	ni_index i;
278
279	MM_GROW_ARRAY(nl->ninl_val, nl->ninl_len);
280	for (i = nl->ninl_len; i > where; i--) {
281		nl->ninl_val[i] = nl->ninl_val[i - 1];
282	}
283	nl->ninl_val[i] = ni_name_dup(nm);
284	nl->ninl_len++;
285}
286
287void
288ni_namelist_delete(
289		ni_namelist *nl,
290		ni_index which
291		)
292{
293	int i;
294
295	ni_name_free(&nl->ninl_val[which]);
296	for (i = which + 1; i < nl-> ninl_len; i++) {
297		nl->ninl_val[i - 1] = nl->ninl_val[i];
298	}
299	MM_SHRINK_ARRAY(nl->ninl_val, nl->ninl_len--);
300}
301
302ni_index
303ni_namelist_match(
304	       const ni_namelist nl,
305	       ni_name_const nm
306	       )
307{
308	ni_index i;
309
310	for (i = 0; i < nl.ninl_len; i++) {
311		if (ni_name_match(nl.ninl_val[i], nm)) {
312			return (i);
313		}
314	}
315	return (NI_INDEX_NULL);
316}
317
318/*
319 * Imported from Libinfo END ---^
320 */
321
322/*
323 * Exported routines
324 */
325
326void
327ni_proplist_dump(ni_proplist * pl)
328{
329    int i, j;
330
331    for (i = 0; i < pl->nipl_len; i++) {
332	ni_property * prop = &(pl->nipl_val[i]);
333	ni_namelist * nl_p = &prop->nip_val;
334	if (nl_p->ninl_len == 0) {
335	    printf("\"%s\"\n", prop->nip_name);
336	}
337	else {
338	    printf("\"%s\" = ", prop->nip_name);
339	    for (j = 0; j < nl_p->ninl_len; j++)
340		printf("%s\"%s\"", (j == 0) ? "" : ", ", nl_p->ninl_val[j]);
341	    printf("\n");
342	}
343    }
344}
345
346void
347ni_set_prop(ni_proplist * pl_p, ni_name prop, ni_name value,
348	    boolean_t * modified)
349{
350    ni_index		where;
351
352    where = ni_proplist_match(*pl_p, prop, NULL);
353    if (where != NI_INDEX_NULL) {
354	if (value != NULL && where == ni_proplist_match(*pl_p, prop, value)) {
355	    return; /* already set */
356	}
357	ni_proplist_delete(pl_p, where);
358    }
359    ni_proplist_insertprop(pl_p, prop, value, where);
360    if (modified)
361	*modified = TRUE;
362    return;
363}
364
365void
366ni_delete_prop(ni_proplist * pl_p, ni_name prop, boolean_t * modified)
367{
368    int where;
369
370    where = ni_proplist_match(*pl_p, prop, NULL);
371    if (where != NI_INDEX_NULL) {
372	ni_proplist_delete(pl_p, where);
373	if (modified)
374	    *modified = TRUE;
375    }
376    return;
377}
378
379