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.14 2008/01/30 13:48:37 rink Exp $
12 * $DragonFly: src/usr.sbin/bootparamd/bootparamd/bootparamd.c,v 1.4 2003/11/15 23:33:35 eirikn Exp $
17 #include <rpcsvc/yp_prot.h>
18 #include <rpcsvc/ypclnt.h>
20 #include "bootparam_prot.h"
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 extern int debug, dolog;
31 extern in_addr_t route_addr;
32 extern char *bootpfile;
37 static char buffer[MAXLEN];
38 static char hostname[MAX_MACHINE_NAME];
39 static char askname[MAX_MACHINE_NAME];
40 static char path[MAX_PATH_LEN];
41 static char domain_name[MAX_MACHINE_NAME];
43 int getthefile(char *, char *, char *, int);
44 int checkhost(char *, char *, int);
47 bootparamproc_whoami_1_svc(bp_whoami_arg *whoami, struct svc_req *req)
50 static bp_whoami_res res;
52 fprintf(stderr,"whoami got question for %d.%d.%d.%d\n",
53 255 & whoami->client_address.bp_address_u.ip_addr.net,
54 255 & whoami->client_address.bp_address_u.ip_addr.host,
55 255 & whoami->client_address.bp_address_u.ip_addr.lh,
56 255 & whoami->client_address.bp_address_u.ip_addr.impno);
58 syslog(LOG_NOTICE, "whoami got question for %d.%d.%d.%d\n",
59 255 & whoami->client_address.bp_address_u.ip_addr.net,
60 255 & whoami->client_address.bp_address_u.ip_addr.host,
61 255 & whoami->client_address.bp_address_u.ip_addr.lh,
62 255 & whoami->client_address.bp_address_u.ip_addr.impno);
64 bcopy((char *)&whoami->client_address.bp_address_u.ip_addr, (char *)&haddr,
66 he = gethostbyaddr(&haddr,sizeof(haddr),AF_INET);
67 if ( ! he ) goto failed;
69 if (debug) warnx("this is host %s", he->h_name);
70 if (dolog) syslog(LOG_NOTICE,"This is host %s\n", he->h_name);
72 strncpy(askname, he->h_name, sizeof(askname));
73 askname[sizeof(askname)-1] = 0;
75 if (checkhost(askname, hostname, sizeof hostname) ) {
76 res.client_name = hostname;
77 getdomainname(domain_name, MAX_MACHINE_NAME);
78 res.domain_name = domain_name;
80 if ( res.router_address.address_type != IP_ADDR_TYPE ) {
81 res.router_address.address_type = IP_ADDR_TYPE;
82 bcopy( &route_addr, &res.router_address.bp_address_u.ip_addr, sizeof(in_addr_t));
84 if (debug) fprintf(stderr,
85 "Returning %s %s %d.%d.%d.%d\n",
88 255 & res.router_address.bp_address_u.ip_addr.net,
89 255 & res.router_address.bp_address_u.ip_addr.host,
90 255 & res.router_address.bp_address_u.ip_addr.lh,
91 255 & res.router_address.bp_address_u.ip_addr.impno);
92 if (dolog) syslog(LOG_NOTICE,
93 "Returning %s %s %d.%d.%d.%d\n",
96 255 & res.router_address.bp_address_u.ip_addr.net,
97 255 & res.router_address.bp_address_u.ip_addr.host,
98 255 & res.router_address.bp_address_u.ip_addr.lh,
99 255 & res.router_address.bp_address_u.ip_addr.impno);
104 if (debug) warnx("whoami failed");
105 if (dolog) syslog(LOG_NOTICE,"whoami failed\n");
111 bootparamproc_getfile_1_svc(bp_getfile_arg *getfile, struct svc_req *req)
113 char *where, *index();
114 static bp_getfile_res res;
117 warnx("getfile got question for \"%s\" and file \"%s\"",
118 getfile->client_name, getfile->file_id);
121 syslog(LOG_NOTICE,"getfile got question for \"%s\" and file \"%s\"\n",
122 getfile->client_name, getfile->file_id);
125 he = gethostbyname(getfile->client_name);
126 if (! he ) goto failed;
128 strncpy(askname, he->h_name, sizeof(askname));
129 askname[sizeof(askname)-1] = 0;
131 if (getthefile(askname, getfile->file_id,buffer,sizeof(buffer))) {
132 if ( (where = index(buffer,':')) ) {
133 /* buffer is re-written to contain the name of the info of file */
134 strncpy(hostname, buffer, where - buffer);
135 hostname[where - buffer] = '\0';
138 he = gethostbyname(hostname);
139 if ( !he ) goto failed;
140 bcopy( he->h_addr, &res.server_address.bp_address_u.ip_addr, 4);
141 res.server_name = hostname;
142 res.server_path = path;
143 res.server_address.address_type = IP_ADDR_TYPE;
145 else { /* special for dump, answer with null strings */
146 if (!strcmp(getfile->file_id, "dump")) {
147 res.server_name = "";
148 res.server_path = "";
149 res.server_address.address_type = IP_ADDR_TYPE;
150 bzero(&res.server_address.bp_address_u.ip_addr,4);
154 fprintf(stderr, "returning server:%s path:%s address: %d.%d.%d.%d\n",
155 res.server_name, res.server_path,
156 255 & res.server_address.bp_address_u.ip_addr.net,
157 255 & res.server_address.bp_address_u.ip_addr.host,
158 255 & res.server_address.bp_address_u.ip_addr.lh,
159 255 & res.server_address.bp_address_u.ip_addr.impno);
161 syslog(LOG_NOTICE, "returning server:%s path:%s address: %d.%d.%d.%d\n",
162 res.server_name, res.server_path,
163 255 & res.server_address.bp_address_u.ip_addr.net,
164 255 & res.server_address.bp_address_u.ip_addr.host,
165 255 & res.server_address.bp_address_u.ip_addr.lh,
166 255 & res.server_address.bp_address_u.ip_addr.impno);
170 if (debug) warnx("getfile failed for %s", getfile->client_name);
171 if (dolog) syslog(LOG_NOTICE,
172 "getfile failed for %s\n", getfile->client_name);
176 /* getthefile return 1 and fills the buffer with the information
177 of the file, e g "host:/export/root/client" if it can be found.
178 If the host is in the database, but the file is not, the buffer
179 will be empty. (This makes it possible to give the special
180 empty answer for the file "dump") */
183 getthefile(char *askname, char *fileid, char *buffer, int blen)
190 static char *yp_domain;
193 int ch, pch, fid_len, res = 0;
195 char info[MAX_FILEID + MAX_PATH_LEN+MAX_MACHINE_NAME + 3];
197 bpf = fopen(bootpfile, "r");
199 errx(1, "no %s", bootpfile);
201 /* XXX see comment below */
202 while ( fscanf(bpf, "%255s", hostname) > 0 && !match ) {
203 if ( *hostname != '#' ) { /* comment */
204 if ( ! strcmp(hostname, askname) ) {
207 he = gethostbyname(hostname);
208 if (he && !strcmp(he->h_name, askname)) match = 1;
211 if (*hostname == '+' ) { /* NIS */
213 if (yp_get_default_domain(&yp_domain)) {
214 if (debug) warn("NIS");
217 if (yp_match(yp_domain, "bootparams", askname, strlen(askname),
218 &result, &resultlen))
220 if (strstr(result, fileid) == NULL) {
223 snprintf(buffer, blen,
224 "%s",strchr(strstr(result,fileid), '=') + 1);
225 if (strchr(buffer, ' ') != NULL)
226 *(char *)(strchr(buffer, ' ')) = '\0';
229 warnx("could not close %s", bootpfile);
232 return(0); /* ENOTSUP */
235 /* skip to next entry */
237 pch = ch = getc(bpf);
238 while ( ! ( ch == '\n' && pch != '\\') && ch != EOF) {
239 pch = ch; ch = getc(bpf);
243 /* if match is true we read the rest of the line to get the
247 fid_len = strlen(fileid);
248 while ( ! res && (fscanf(bpf,"%s", info)) > 0) { /* read a string */
249 ch = getc(bpf); /* and a character */
250 if ( *info != '#' ) { /* Comment ? */
251 if (! strncmp(info, fileid, fid_len) && *(info + fid_len) == '=') {
252 where = info + fid_len + 1;
253 if ( isprint( *where )) {
254 strcpy(buffer, where); /* found file */
258 while (isspace(ch) && ch != '\n') ch = getc(bpf);
259 /* read to end of line */
260 if ( ch == '\n' ) { /* didn't find it */
261 res = -1; break; /* but host is there */
263 if ( ch == '\\' ) { /* more info */
264 ch = getc(bpf); /* maybe on next line */
265 if (ch == '\n') continue; /* read it in next loop */
266 ungetc(ch, bpf); ungetc('\\',bpf); /* push the character(s) back */
267 } else ungetc(ch, bpf); /* but who know what a `\` is */
269 } else break; /* a commented rest-of-line */
272 if (fclose(bpf)) { warnx("could not close %s", bootpfile); }
273 if ( res == -1) buffer[0] = '\0'; /* host found, file not */
277 /* checkhost puts the hostname found in the database file in
278 the hostname-variable and returns 1, if askname is a valid
279 name for a host in the database */
282 checkhost(char *askname, char *hostname, int len)
290 static char *yp_domain;
293 /* struct hostent *cmp_he;*/
295 bpf = fopen(bootpfile, "r");
297 errx(1, "no %s", bootpfile);
299 /* XXX there is no way in ISO C to specify the maximal length for a
300 conversion in a variable way */
301 while ( fscanf(bpf, "%254s", hostname) > 0 ) {
302 if ( *hostname != '#' ) { /* comment */
303 if ( ! strcmp(hostname, askname) ) {
304 /* return true for match of hostname */
308 /* check the alias list */
310 he = gethostbyname(hostname);
311 if (he && !strcmp(askname, he->h_name)) {
317 if (*hostname == '+' ) { /* NIS */
319 if (yp_get_default_domain(&yp_domain)) {
320 if (debug) warn("NIS");
323 if (!yp_match(yp_domain, "bootparams", askname, strlen(askname),
324 &result, &resultlen)) {
325 /* return true for match of hostname */
327 he = gethostbyname(askname);
328 if (he && !strcmp(askname, he->h_name)) {
330 snprintf(hostname, len, "%s", he->h_name);
334 warnx("could not close %s", bootpfile);
337 return(0); /* ENOTSUP */
340 /* skip to next entry */
341 pch = ch = getc(bpf);
342 while ( ! ( ch == '\n' && pch != '\\') && ch != EOF) {
343 pch = ch; ch = getc(bpf);
346 if (fclose(bpf)) { warnx("could not close %s", bootpfile); }