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