GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: usr.sbin/rbootd/parseconf.c Lines: 0 81 0.0 %
Date: 2017-11-07 Branches: 0 112 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: parseconf.c,v 1.13 2016/05/29 02:19:02 guenther Exp $	*/
2
/*	$NetBSD: parseconf.c,v 1.4 1995/10/06 05:12:16 thorpej Exp $	*/
3
4
/*
5
 * Copyright (c) 1988, 1992 The University of Utah and the Center
6
 *	for Software Science (CSS).
7
 * Copyright (c) 1992, 1993
8
 *	The Regents of the University of California.  All rights reserved.
9
 *
10
 * This code is derived from software contributed to Berkeley by
11
 * the Center for Software Science of the University of Utah Computer
12
 * Science Department.  CSS requests users of this software to return
13
 * to css-dist@cs.utah.edu any improvements that they make and grant
14
 * CSS redistribution rights.
15
 *
16
 * Redistribution and use in source and binary forms, with or without
17
 * modification, are permitted provided that the following conditions
18
 * are met:
19
 * 1. Redistributions of source code must retain the above copyright
20
 *    notice, this list of conditions and the following disclaimer.
21
 * 2. Redistributions in binary form must reproduce the above copyright
22
 *    notice, this list of conditions and the following disclaimer in the
23
 *    documentation and/or other materials provided with the distribution.
24
 * 3. Neither the name of the University nor the names of its contributors
25
 *    may be used to endorse or promote products derived from this software
26
 *    without specific prior written permission.
27
 *
28
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38
 * SUCH DAMAGE.
39
 *
40
 *	from: @(#)parseconf.c	8.1 (Berkeley) 6/4/93
41
 *
42
 * From: Utah Hdr: parseconf.c 3.1 92/07/06
43
 * Author: Jeff Forys, University of Utah CSS
44
 */
45
46
#include <sys/stat.h>
47
48
#include <ctype.h>
49
#include <dirent.h>
50
#include <stdio.h>
51
#include <stdlib.h>
52
#include <string.h>
53
#include <syslog.h>
54
#include "defs.h"
55
56
/*
57
**  ParseConfig -- parse the config file into linked list of clients.
58
**
59
**	Parameters:
60
**		None.
61
**
62
**	Returns:
63
**		1 on success, 0 otherwise.
64
**
65
**	Side Effects:
66
**		- Linked list of clients will be (re)allocated.
67
**
68
**	Warnings:
69
**		- GetBootFiles() must be called before this routine
70
**		  to create a linked list of default boot files.
71
*/
72
int
73
ParseConfig(void)
74
{
75
	char line[C_LINELEN], *cp, *bcp;
76
	int i, j, linecnt = 0;
77
	u_int8_t *addr;
78
	CLIENT *client;
79
	FILE *fp;
80
81
	if (BootAny)				/* ignore config file */
82
		return(1);
83
84
	FreeClients();				/* delete old list of clients */
85
86
	if ((fp = fopen(ConfigFile, "r")) == NULL) {
87
		syslog(LOG_ERR, "ParseConfig: can't open config file (%s)",
88
		    ConfigFile);
89
		return(0);
90
	}
91
92
	/*
93
	 *  GETSTR positions `bcp' at the start of the current token,
94
	 *  and null terminates it.  `cp' is positioned at the start
95
	 *  of the next token.  spaces & commas are separators.
96
	 */
97
#define GETSTR	while (isspace((unsigned char)*cp) || *cp == ',')	\
98
			cp++;						\
99
		bcp = cp;						\
100
		while (*cp && *cp!=',' && !isspace((unsigned char)*cp))	\
101
			cp++;						\
102
		if (*cp)						\
103
			*cp++ = '\0'
104
105
	/*
106
	 *  For each line, parse it into a new CLIENT struct.
107
	 */
108
	while (fgets(line, C_LINELEN, fp) != NULL) {
109
		linecnt++;				/* line counter */
110
111
		if (*line == '\0' || *line == '#')	/* ignore comment */
112
			continue;
113
114
		if ((cp = strchr(line,'#')) != NULL)	/* trash comments */
115
			*cp = '\0';
116
117
		cp = line;				/* init `cp' */
118
		GETSTR;					/* get RMP addr */
119
		if (bcp == cp)				/* all delimiters */
120
			continue;
121
122
		/*
123
		 *  Get an RMP address from a string.  Abort on failure.
124
		 */
125
		if ((addr = ParseAddr(bcp)) == NULL) {
126
			syslog(LOG_ERR,
127
			    "ParseConfig: line %d: cant parse <%s>",
128
			    linecnt, bcp);
129
			continue;
130
		}
131
132
		if ((client = NewClient(addr)) == NULL)	/* alloc new client */
133
			continue;
134
135
		GETSTR;					/* get first file */
136
137
		/*
138
		 *  If no boot files are spec'd, use the default list.
139
		 *  Otherwise, validate each file (`bcp') against the
140
		 *  list of bootable files.
141
		 */
142
		i = 0;
143
		if (bcp == cp) {			/* no files spec'd */
144
			for (; i < C_MAXFILE && BootFiles[i] != NULL; i++)
145
				client->files[i] = BootFiles[i];
146
		} else {
147
			do {
148
				/*
149
				 *  For each boot file spec'd, make sure it's
150
				 *  in our list.  If so, include a pointer to
151
				 *  it in the CLIENT's list of boot files.
152
				 */
153
				for (j = 0; ; j++) {
154
					if (j==C_MAXFILE||BootFiles[j]==NULL) {
155
						syslog(LOG_ERR,
156
						    "ParseConfig: line %d: no boot file (%s)",
157
						    linecnt, bcp);
158
						break;
159
					}
160
					if (STREQN(BootFiles[j], bcp)) {
161
						if (i < C_MAXFILE)
162
							client->files[i++] =
163
							    BootFiles[j];
164
						else
165
							syslog(LOG_ERR, "ParseConfig: line %d: too many boot files (%s)",
166
							       linecnt, bcp);
167
						break;
168
					}
169
				}
170
				GETSTR;			/* get next file */
171
			} while (bcp != cp);
172
173
			/*
174
			 *  Restricted list of boot files were spec'd,
175
			 *  however, none of them were found.  Since we
176
			 *  apparently cant let them boot "just anything",
177
			 *  the entire record is invalidated.
178
			 */
179
			if (i == 0) {
180
				FreeClient(client);
181
				continue;
182
			}
183
		}
184
185
		/*
186
		 *  Link this client into the linked list of clients.
187
		 *  SIGHUP has already been blocked.
188
		 */
189
		if (Clients)
190
			client->next = Clients;
191
		Clients = client;
192
	}
193
194
	(void) fclose(fp);				/* close config file */
195
	return(1);					/* return success */
196
}
197
198
/*
199
**  ParseAddr -- Parse a string containing an RMP address.
200
**
201
**	This routine is fairly liberal at parsing an RMP address.  The
202
**	address must contain 6 octets consisting of between 0 and 2 hex
203
**	chars (upper/lower case) separated by colons.  If two colons are
204
**	together (e.g. "::", the octet between them is recorded as being
205
**	zero.  Hence, the following addrs are all valid and parse to the
206
**	same thing:
207
**
208
**		08:00:09:00:66:ad	8::9:0:66:AD	8::9::66:aD
209
**
210
**	For clarity, an RMP address is really an Ethernet address, but
211
**	since the HP boot code uses IEEE 802.3, it's really an IEEE
212
**	802.3 address.  Of course, all of these are identical.
213
**
214
**	Parameters:
215
**		str - string representation of an RMP address.
216
**
217
**	Returns:
218
**		pointer to a static array of RMP_ADDRLEN bytes.
219
**
220
**	Side Effects:
221
**		None.
222
**
223
**	Warnings:
224
**		- The return value points to a static buffer; it must
225
**		  be copied if it's to be saved.
226
*/
227
u_int8_t *
228
ParseAddr(char *str)
229
{
230
	static u_int8_t addr[RMP_ADDRLEN];
231
	int part, subpart;
232
	unsigned int i;
233
	char *cp;
234
235
	bzero((char *)&addr[0], RMP_ADDRLEN);	/* zero static buffer */
236
237
	part = subpart = 0;
238
	for (cp = str; *cp; cp++) {
239
		/*
240
		 *  A colon (`:') must be used to delimit each octet.
241
		 */
242
		if (*cp == ':') {
243
			if (++part == RMP_ADDRLEN)	/* too many parts */
244
				return(NULL);
245
			subpart = 0;
246
			continue;
247
		}
248
249
		/*
250
		 *  Convert hex character to an integer.
251
		 */
252
		if (isdigit((unsigned char)*cp))
253
			i = *cp - '0';
254
		else {
255
			i = (isupper((unsigned char)*cp) ?
256
			    tolower((unsigned char)*cp) : *cp) - 'a' + 10;
257
			if (i < 10 || i > 15)		/* not a hex char */
258
				return(NULL);
259
		}
260
261
		if (subpart++) {
262
			if (subpart > 2)		/* too many hex chars */
263
				return(NULL);
264
			addr[part] <<= 4;
265
		}
266
		addr[part] |= i;
267
	}
268
269
	if (part != (RMP_ADDRLEN-1))			/* too few parts */
270
		return(NULL);
271
272
	return(&addr[0]);
273
}
274
275
/*
276
**  GetBootFiles -- record list of files in current (boot) directory.
277
**
278
**	Parameters:
279
**		None.
280
**
281
**	Returns:
282
**		Number of boot files on success, 0 on failure.
283
**
284
**	Side Effects:
285
**		Strings in `BootFiles' are freed/allocated.
286
**
287
**	Warnings:
288
**		- After this routine is called, ParseConfig() must be
289
**		  called to re-order it's list of boot file pointers.
290
*/
291
int
292
GetBootFiles(void)
293
{
294
	struct stat statb;
295
	struct dirent *dp;
296
	DIR *dfd;
297
	int i;
298
299
	/*
300
	 *  Free the current list of boot files.
301
	 */
302
	for (i = 0; i < C_MAXFILE && BootFiles[i] != NULL; i++) {
303
		FreeStr(BootFiles[i]);
304
		BootFiles[i] = NULL;
305
	}
306
307
	/*
308
	 *  Open current directory to read boot file names.
309
	 */
310
	if ((dfd = opendir(".")) == NULL) {	/* open BootDir */
311
		syslog(LOG_ERR, "GetBootFiles: can't open directory (%s)",
312
		       BootDir);
313
		return(0);
314
	}
315
316
	/*
317
	 *  Read each boot file name and allocate space for it in the
318
	 *  list of boot files (BootFiles).  All boot files read after
319
	 *  C_MAXFILE will be ignored.
320
	 */
321
	i = 0;
322
	for (dp = readdir(dfd); dp != NULL; dp = readdir(dfd)) {
323
		if (stat(dp->d_name, &statb) < 0 ||
324
		    (statb.st_mode & S_IFMT) != S_IFREG)
325
			continue;
326
		if (i == C_MAXFILE)
327
			syslog(LOG_ERR,
328
			       "GetBootFiles: too many boot files (%s ignored)",
329
			       dp->d_name);
330
		else if ((BootFiles[i] = NewStr(dp->d_name)) != NULL)
331
			i++;
332
	}
333
334
	(void) closedir(dfd);			/* close BootDir */
335
336
	if (i == 0)				/* cant find any boot files */
337
		syslog(LOG_ERR, "GetBootFiles: no boot files (%s)", BootDir);
338
339
	return(i);
340
}