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 |
|
|
} |