3 This code is not copyright, and is placed in the public domain. Feel free to
4 use and modify. Please send modifications and/or suggestions + bug fixes to
6 Klas Heggemann <klas@nada.kth.se>
11 * $FreeBSD: src/usr.sbin/bootparamd/bootparamd/bootparamd.c,v 1.10 1999/08/28 01:15:39 peter Exp $
12 * $DragonFly: src/usr.sbin/bootparamd/bootparamd/bootparamd.c,v 1.4 2003/11/15 23:33:35 eirikn Exp $
15 #include <rpcsvc/yp_prot.h>
16 #include <rpcsvc/ypclnt.h>
17 #include "bootparam_prot.h"
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 extern int debug, dolog;
28 extern unsigned long route_addr;
29 extern char *bootpfile;
34 static char buffer[MAXLEN];
35 static char hostname[MAX_MACHINE_NAME];
36 static char askname[MAX_MACHINE_NAME];
37 static char path[MAX_PATH_LEN];
38 static char domain_name[MAX_MACHINE_NAME];
40 int getthefile(char *, char *, char *, int);
41 int checkhost(char *, char *, int);
44 bootparamproc_whoami_1(bp_whoami_arg *whoami)
47 static bp_whoami_res res;
49 fprintf(stderr,"whoami got question for %d.%d.%d.%d\n",
50 255 & whoami->client_address.bp_address_u.ip_addr.net,
51 255 & whoami->client_address.bp_address_u.ip_addr.host,
52 255 & whoami->client_address.bp_address_u.ip_addr.lh,
53 255 & whoami->client_address.bp_address_u.ip_addr.impno);
55 syslog(LOG_NOTICE, "whoami got question for %d.%d.%d.%d\n",
56 255 & whoami->client_address.bp_address_u.ip_addr.net,
57 255 & whoami->client_address.bp_address_u.ip_addr.host,
58 255 & whoami->client_address.bp_address_u.ip_addr.lh,
59 255 & whoami->client_address.bp_address_u.ip_addr.impno);
61 bcopy((char *)&whoami->client_address.bp_address_u.ip_addr, (char *)&haddr,
63 he = gethostbyaddr((char *)&haddr,sizeof(haddr),AF_INET);
64 if ( ! he ) goto failed;
66 if (debug) warnx("this is host %s", he->h_name);
67 if (dolog) syslog(LOG_NOTICE,"This is host %s\n", he->h_name);
69 strncpy(askname, he->h_name, sizeof(askname));
70 askname[sizeof(askname)-1] = 0;
72 if (checkhost(askname, hostname, sizeof hostname) ) {
73 res.client_name = hostname;
74 getdomainname(domain_name, MAX_MACHINE_NAME);
75 res.domain_name = domain_name;
77 if ( res.router_address.address_type != IP_ADDR_TYPE ) {
78 res.router_address.address_type = IP_ADDR_TYPE;
79 bcopy( &route_addr, &res.router_address.bp_address_u.ip_addr, 4);
81 if (debug) fprintf(stderr,
82 "Returning %s %s %d.%d.%d.%d\n",
85 255 & res.router_address.bp_address_u.ip_addr.net,
86 255 & res.router_address.bp_address_u.ip_addr.host,
87 255 & res.router_address.bp_address_u.ip_addr.lh,
88 255 & res.router_address.bp_address_u.ip_addr.impno);
89 if (dolog) syslog(LOG_NOTICE,
90 "Returning %s %s %d.%d.%d.%d\n",
93 255 & res.router_address.bp_address_u.ip_addr.net,
94 255 & res.router_address.bp_address_u.ip_addr.host,
95 255 & res.router_address.bp_address_u.ip_addr.lh,
96 255 & res.router_address.bp_address_u.ip_addr.impno);
101 if (debug) warnx("whoami failed");
102 if (dolog) syslog(LOG_NOTICE,"whoami failed\n");
108 bootparamproc_getfile_1(bp_getfile_arg *getfile)
110 char *where, *index();
111 static bp_getfile_res res;
114 warnx("getfile got question for \"%s\" and file \"%s\"",
115 getfile->client_name, getfile->file_id);
118 syslog(LOG_NOTICE,"getfile got question for \"%s\" and file \"%s\"\n",
119 getfile->client_name, getfile->file_id);
122 he = gethostbyname(getfile->client_name);
123 if (! he ) goto failed;
125 strncpy(askname, he->h_name, sizeof(askname));
126 askname[sizeof(askname)-1] = 0;
128 if (getthefile(askname, getfile->file_id,buffer,sizeof(buffer))) {
129 if ( (where = index(buffer,':')) ) {
130 /* buffer is re-written to contain the name of the info of file */
131 strncpy(hostname, buffer, where - buffer);
132 hostname[where - buffer] = '\0';
135 he = gethostbyname(hostname);
136 if ( !he ) goto failed;
137 bcopy( he->h_addr, &res.server_address.bp_address_u.ip_addr, 4);
138 res.server_name = hostname;
139 res.server_path = path;
140 res.server_address.address_type = IP_ADDR_TYPE;
142 else { /* special for dump, answer with null strings */
143 if (!strcmp(getfile->file_id, "dump")) {
144 res.server_name = "";
145 res.server_path = "";
146 res.server_address.address_type = IP_ADDR_TYPE;
147 bzero(&res.server_address.bp_address_u.ip_addr,4);
151 fprintf(stderr, "returning server:%s path:%s address: %d.%d.%d.%d\n",
152 res.server_name, res.server_path,
153 255 & res.server_address.bp_address_u.ip_addr.net,
154 255 & res.server_address.bp_address_u.ip_addr.host,
155 255 & res.server_address.bp_address_u.ip_addr.lh,
156 255 & res.server_address.bp_address_u.ip_addr.impno);
158 syslog(LOG_NOTICE, "returning server:%s path:%s address: %d.%d.%d.%d\n",
159 res.server_name, res.server_path,
160 255 & res.server_address.bp_address_u.ip_addr.net,
161 255 & res.server_address.bp_address_u.ip_addr.host,
162 255 & res.server_address.bp_address_u.ip_addr.lh,
163 255 & res.server_address.bp_address_u.ip_addr.impno);
167 if (debug) warnx("getfile failed for %s", getfile->client_name);
168 if (dolog) syslog(LOG_NOTICE,
169 "getfile failed for %s\n", getfile->client_name);
173 /* getthefile return 1 and fills the buffer with the information
174 of the file, e g "host:/export/root/client" if it can be found.
175 If the host is in the database, but the file is not, the buffer
176 will be empty. (This makes it possible to give the special
177 empty answer for the file "dump") */
180 getthefile(char *askname, char *fileid, char *buffer, int blen)
186 static char *yp_domain;
188 int ch, pch, fid_len, res = 0;
190 char info[MAX_FILEID + MAX_PATH_LEN+MAX_MACHINE_NAME + 3];
192 bpf = fopen(bootpfile, "r");
194 errx(1, "no %s", bootpfile);
196 /* XXX see comment below */
197 while ( fscanf(bpf, "%255s", hostname) > 0 && !match ) {
198 if ( *hostname != '#' ) { /* comment */
199 if ( ! strcmp(hostname, askname) ) {
202 he = gethostbyname(hostname);
203 if (he && !strcmp(he->h_name, askname)) match = 1;
206 if (*hostname == '+' ) { /* NIS */
207 if (yp_get_default_domain(&yp_domain)) {
208 if (debug) warn("NIS");
211 if (yp_match(yp_domain, "bootparams", askname, strlen(askname),
212 &result, &resultlen))
214 if (strstr(result, fileid) == NULL) {
217 snprintf(buffer, blen,
218 "%s",strchr(strstr(result,fileid), '=') + 1);
219 if (strchr(buffer, ' ') != NULL)
220 *(char *)(strchr(buffer, ' ')) = '\0';
223 warnx("could not close %s", bootpfile);
226 /* skip to next entry */
228 pch = ch = getc(bpf);
229 while ( ! ( ch == '\n' && pch != '\\') && ch != EOF) {
230 pch = ch; ch = getc(bpf);
234 /* if match is true we read the rest of the line to get the
238 fid_len = strlen(fileid);
239 while ( ! res && (fscanf(bpf,"%s", info)) > 0) { /* read a string */
240 ch = getc(bpf); /* and a character */
241 if ( *info != '#' ) { /* Comment ? */
242 if (! strncmp(info, fileid, fid_len) && *(info + fid_len) == '=') {
243 where = info + fid_len + 1;
244 if ( isprint( *where )) {
245 strcpy(buffer, where); /* found file */
249 while (isspace(ch) && ch != '\n') ch = getc(bpf);
250 /* read to end of line */
251 if ( ch == '\n' ) { /* didn't find it */
252 res = -1; break; /* but host is there */
254 if ( ch == '\\' ) { /* more info */
255 ch = getc(bpf); /* maybe on next line */
256 if (ch == '\n') continue; /* read it in next loop */
257 ungetc(ch, bpf); ungetc('\\',bpf); /* push the character(s) back */
258 } else ungetc(ch, bpf); /* but who know what a `\` is */
260 } else break; /* a commented rest-of-line */
263 if (fclose(bpf)) { warnx("could not close %s", bootpfile); }
264 if ( res == -1) buffer[0] = '\0'; /* host found, file not */
268 /* checkhost puts the hostname found in the database file in
269 the hostname-variable and returns 1, if askname is a valid
270 name for a host in the database */
273 checkhost(char *askname, char *hostname, int len)
280 static char *yp_domain;
282 /* struct hostent *cmp_he;*/
284 bpf = fopen(bootpfile, "r");
286 errx(1, "no %s", bootpfile);
288 /* XXX there is no way in ISO C to specify the maximal length for a
289 conversion in a variable way */
290 while ( fscanf(bpf, "%254s", hostname) > 0 ) {
291 if ( *hostname != '#' ) { /* comment */
292 if ( ! strcmp(hostname, askname) ) {
293 /* return true for match of hostname */
297 /* check the alias list */
299 he = gethostbyname(hostname);
300 if (he && !strcmp(askname, he->h_name)) {
306 if (*hostname == '+' ) { /* NIS */
307 if (yp_get_default_domain(&yp_domain)) {
308 if (debug) warn("NIS");
311 if (!yp_match(yp_domain, "bootparams", askname, strlen(askname),
312 &result, &resultlen)) {
313 /* return true for match of hostname */
315 he = gethostbyname(askname);
316 if (he && !strcmp(askname, he->h_name)) {
318 snprintf(hostname, len, "%s", he->h_name);
322 warnx("could not close %s", bootpfile);
325 /* skip to next entry */
326 pch = ch = getc(bpf);
327 while ( ! ( ch == '\n' && pch != '\\') && ch != EOF) {
328 pch = ch; ch = getc(bpf);
331 if (fclose(bpf)) { warnx("could not close %s", bootpfile); }