Bring in a transport-independent RPC (TI-RPC).
[dragonfly.git] / usr.sbin / bootparamd / bootparamd / bootparamd.c
blob9c8b59d8f998d9f502f9d25e44be8311f9fd62b8
1 /*
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>
8 */
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 $
15 #ifdef YP
16 #include <rpc/rpc.h>
17 #include <rpcsvc/yp_prot.h>
18 #include <rpcsvc/ypclnt.h>
19 #endif
20 #include "bootparam_prot.h"
21 #include <ctype.h>
22 #include <err.h>
23 #include <netdb.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <syslog.h>
27 #include <unistd.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;
34 #define MAXLEN 800
36 struct hostent *he;
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);
46 bp_whoami_res *
47 bootparamproc_whoami_1_svc(bp_whoami_arg *whoami, struct svc_req *req)
49 in_addr_t haddr;
50 static bp_whoami_res res;
51 if (debug)
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);
57 if (dolog)
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,
65 sizeof(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",
86 res.client_name,
87 res.domain_name,
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",
94 res.client_name,
95 res.domain_name,
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);
101 return(&res);
103 failed:
104 if (debug) warnx("whoami failed");
105 if (dolog) syslog(LOG_NOTICE,"whoami failed\n");
106 return(NULL);
110 bp_getfile_res *
111 bootparamproc_getfile_1_svc(bp_getfile_arg *getfile, struct svc_req *req)
113 char *where, *index();
114 static bp_getfile_res res;
116 if (debug)
117 warnx("getfile got question for \"%s\" and file \"%s\"",
118 getfile->client_name, getfile->file_id);
120 if (dolog)
121 syslog(LOG_NOTICE,"getfile got question for \"%s\" and file \"%s\"\n",
122 getfile->client_name, getfile->file_id);
124 he = NULL;
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';
136 where++;
137 strcpy(path, where);
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);
151 } else goto failed;
153 if (debug)
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);
160 if (dolog)
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);
167 return(&res);
169 failed:
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);
173 return(NULL);
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)
185 FILE *bpf;
186 char *where;
187 static char *result;
188 int resultlen;
189 #ifdef YP
190 static char *yp_domain;
191 #endif
193 int ch, pch, fid_len, res = 0;
194 int match = 0;
195 char info[MAX_FILEID + MAX_PATH_LEN+MAX_MACHINE_NAME + 3];
197 bpf = fopen(bootpfile, "r");
198 if ( ! bpf )
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) ) {
205 match = 1;
206 } else {
207 he = gethostbyname(hostname);
208 if (he && !strcmp(he->h_name, askname)) match = 1;
211 if (*hostname == '+' ) { /* NIS */
212 #ifdef YP
213 if (yp_get_default_domain(&yp_domain)) {
214 if (debug) warn("NIS");
215 return(0);
217 if (yp_match(yp_domain, "bootparams", askname, strlen(askname),
218 &result, &resultlen))
219 return (0);
220 if (strstr(result, fileid) == NULL) {
221 buffer[0] = '\0';
222 } else {
223 snprintf(buffer, blen,
224 "%s",strchr(strstr(result,fileid), '=') + 1);
225 if (strchr(buffer, ' ') != NULL)
226 *(char *)(strchr(buffer, ' ')) = '\0';
228 if (fclose(bpf))
229 warnx("could not close %s", bootpfile);
230 return(1);
231 #else
232 return(0); /* ENOTSUP */
233 #endif
235 /* skip to next entry */
236 if ( match ) break;
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
244 info of the file */
246 if (match) {
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 */
255 res = 1; break;
257 } else {
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 */
268 } /* needed for. */
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 */
274 return(match);
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)
284 int ch, pch;
285 FILE *bpf;
286 int res = 0;
287 static char *result;
288 int resultlen;
289 #ifdef YP
290 static char *yp_domain;
291 #endif
293 /* struct hostent *cmp_he;*/
295 bpf = fopen(bootpfile, "r");
296 if ( ! bpf )
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 */
305 res = 1;
306 break;
307 } else {
308 /* check the alias list */
309 he = NULL;
310 he = gethostbyname(hostname);
311 if (he && !strcmp(askname, he->h_name)) {
312 res = 1;
313 break;
317 if (*hostname == '+' ) { /* NIS */
318 #ifdef YP
319 if (yp_get_default_domain(&yp_domain)) {
320 if (debug) warn("NIS");
321 return(0);
323 if (!yp_match(yp_domain, "bootparams", askname, strlen(askname),
324 &result, &resultlen)) {
325 /* return true for match of hostname */
326 he = NULL;
327 he = gethostbyname(askname);
328 if (he && !strcmp(askname, he->h_name)) {
329 res = 1;
330 snprintf(hostname, len, "%s", he->h_name);
333 if (fclose(bpf))
334 warnx("could not close %s", bootpfile);
335 return(res);
336 #else
337 return(0); /* ENOTSUP */
338 #endif
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); }
347 return(res);