1 /* 2 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 5 6 Klas Heggemann <klas@nada.kth.se> 7 8 */ 9 10 #ifndef lint 11 static const char rcsid[] = 12 "$FreeBSD: src/usr.sbin/bootparamd/bootparamd/bootparamd.c,v 1.10 1999/08/28 01:15:39 peter Exp $"; 13 #endif /* not lint */ 14 15 #include <rpc/rpc.h> 16 #include <rpcsvc/yp_prot.h> 17 #include <rpcsvc/ypclnt.h> 18 #include "bootparam_prot.h" 19 #include <ctype.h> 20 #include <err.h> 21 #include <netdb.h> 22 #include <stdio.h> 23 #include <string.h> 24 #include <syslog.h> 25 #include <unistd.h> 26 #include <sys/types.h> 27 #include <sys/socket.h> 28 extern int debug, dolog; 29 extern unsigned long route_addr; 30 extern char *bootpfile; 31 32 #define MAXLEN 800 33 34 struct hostent *he; 35 static char buffer[MAXLEN]; 36 static char hostname[MAX_MACHINE_NAME]; 37 static char askname[MAX_MACHINE_NAME]; 38 static char path[MAX_PATH_LEN]; 39 static char domain_name[MAX_MACHINE_NAME]; 40 41 int getthefile __P((char *, char *, char *, int)); 42 int checkhost __P((char *, char *, int)); 43 44 bp_whoami_res * 45 bootparamproc_whoami_1(whoami) 46 bp_whoami_arg *whoami; 47 { 48 long haddr; 49 static bp_whoami_res res; 50 if (debug) 51 fprintf(stderr,"whoami got question for %d.%d.%d.%d\n", 52 255 & whoami->client_address.bp_address_u.ip_addr.net, 53 255 & whoami->client_address.bp_address_u.ip_addr.host, 54 255 & whoami->client_address.bp_address_u.ip_addr.lh, 55 255 & whoami->client_address.bp_address_u.ip_addr.impno); 56 if (dolog) 57 syslog(LOG_NOTICE, "whoami got question for %d.%d.%d.%d\n", 58 255 & whoami->client_address.bp_address_u.ip_addr.net, 59 255 & whoami->client_address.bp_address_u.ip_addr.host, 60 255 & whoami->client_address.bp_address_u.ip_addr.lh, 61 255 & whoami->client_address.bp_address_u.ip_addr.impno); 62 63 bcopy((char *)&whoami->client_address.bp_address_u.ip_addr, (char *)&haddr, 64 sizeof(haddr)); 65 he = gethostbyaddr((char *)&haddr,sizeof(haddr),AF_INET); 66 if ( ! he ) goto failed; 67 68 if (debug) warnx("this is host %s", he->h_name); 69 if (dolog) syslog(LOG_NOTICE,"This is host %s\n", he->h_name); 70 71 strncpy(askname, he->h_name, sizeof(askname)); 72 askname[sizeof(askname)-1] = 0; 73 74 if (checkhost(askname, hostname, sizeof hostname) ) { 75 res.client_name = hostname; 76 getdomainname(domain_name, MAX_MACHINE_NAME); 77 res.domain_name = domain_name; 78 79 if ( res.router_address.address_type != IP_ADDR_TYPE ) { 80 res.router_address.address_type = IP_ADDR_TYPE; 81 bcopy( &route_addr, &res.router_address.bp_address_u.ip_addr, 4); 82 } 83 if (debug) fprintf(stderr, 84 "Returning %s %s %d.%d.%d.%d\n", 85 res.client_name, 86 res.domain_name, 87 255 & res.router_address.bp_address_u.ip_addr.net, 88 255 & res.router_address.bp_address_u.ip_addr.host, 89 255 & res.router_address.bp_address_u.ip_addr.lh, 90 255 & res.router_address.bp_address_u.ip_addr.impno); 91 if (dolog) syslog(LOG_NOTICE, 92 "Returning %s %s %d.%d.%d.%d\n", 93 res.client_name, 94 res.domain_name, 95 255 & res.router_address.bp_address_u.ip_addr.net, 96 255 & res.router_address.bp_address_u.ip_addr.host, 97 255 & res.router_address.bp_address_u.ip_addr.lh, 98 255 & res.router_address.bp_address_u.ip_addr.impno); 99 100 return(&res); 101 } 102 failed: 103 if (debug) warnx("whoami failed"); 104 if (dolog) syslog(LOG_NOTICE,"whoami failed\n"); 105 return(NULL); 106 } 107 108 109 bp_getfile_res * 110 bootparamproc_getfile_1(getfile) 111 bp_getfile_arg *getfile; 112 { 113 char *where, *index(); 114 static bp_getfile_res res; 115 116 if (debug) 117 warnx("getfile got question for \"%s\" and file \"%s\"", 118 getfile->client_name, getfile->file_id); 119 120 if (dolog) 121 syslog(LOG_NOTICE,"getfile got question for \"%s\" and file \"%s\"\n", 122 getfile->client_name, getfile->file_id); 123 124 he = NULL; 125 he = gethostbyname(getfile->client_name); 126 if (! he ) goto failed; 127 128 strncpy(askname, he->h_name, sizeof(askname)); 129 askname[sizeof(askname)-1] = 0; 130 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; 144 } 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; 152 } 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); 168 } 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); 174 } 175 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") */ 181 182 int 183 getthefile(askname,fileid,buffer,blen) 184 char *askname; 185 char *fileid, *buffer; 186 int blen; 187 { 188 FILE *bpf; 189 char *where; 190 static char *result; 191 int resultlen; 192 static char *yp_domain; 193 194 int ch, pch, fid_len, res = 0; 195 int match = 0; 196 char info[MAX_FILEID + MAX_PATH_LEN+MAX_MACHINE_NAME + 3]; 197 198 bpf = fopen(bootpfile, "r"); 199 if ( ! bpf ) 200 errx(1, "no %s", bootpfile); 201 202 /* XXX see comment below */ 203 while ( fscanf(bpf, "%255s", hostname) > 0 && !match ) { 204 if ( *hostname != '#' ) { /* comment */ 205 if ( ! strcmp(hostname, askname) ) { 206 match = 1; 207 } else { 208 he = gethostbyname(hostname); 209 if (he && !strcmp(he->h_name, askname)) match = 1; 210 } 211 } 212 if (*hostname == '+' ) { /* NIS */ 213 if (yp_get_default_domain(&yp_domain)) { 214 if (debug) warn("NIS"); 215 return(0); 216 } 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'; 227 } 228 if (fclose(bpf)) 229 warnx("could not close %s", bootpfile); 230 return(1); 231 } 232 /* skip to next entry */ 233 if ( match ) break; 234 pch = ch = getc(bpf); 235 while ( ! ( ch == '\n' && pch != '\\') && ch != EOF) { 236 pch = ch; ch = getc(bpf); 237 } 238 } 239 240 /* if match is true we read the rest of the line to get the 241 info of the file */ 242 243 if (match) { 244 fid_len = strlen(fileid); 245 while ( ! res && (fscanf(bpf,"%s", info)) > 0) { /* read a string */ 246 ch = getc(bpf); /* and a character */ 247 if ( *info != '#' ) { /* Comment ? */ 248 if (! strncmp(info, fileid, fid_len) && *(info + fid_len) == '=') { 249 where = info + fid_len + 1; 250 if ( isprint( *where )) { 251 strcpy(buffer, where); /* found file */ 252 res = 1; break; 253 } 254 } else { 255 while (isspace(ch) && ch != '\n') ch = getc(bpf); 256 /* read to end of line */ 257 if ( ch == '\n' ) { /* didn't find it */ 258 res = -1; break; /* but host is there */ 259 } 260 if ( ch == '\\' ) { /* more info */ 261 ch = getc(bpf); /* maybe on next line */ 262 if (ch == '\n') continue; /* read it in next loop */ 263 ungetc(ch, bpf); ungetc('\\',bpf); /* push the character(s) back */ 264 } else ungetc(ch, bpf); /* but who know what a `\` is */ 265 } /* needed for. */ 266 } else break; /* a commented rest-of-line */ 267 } 268 } 269 if (fclose(bpf)) { warnx("could not close %s", bootpfile); } 270 if ( res == -1) buffer[0] = '\0'; /* host found, file not */ 271 return(match); 272 } 273 274 /* checkhost puts the hostname found in the database file in 275 the hostname-variable and returns 1, if askname is a valid 276 name for a host in the database */ 277 278 int 279 checkhost(askname, hostname, len) 280 char *askname; 281 char *hostname; 282 int len; 283 { 284 int ch, pch; 285 FILE *bpf; 286 int res = 0; 287 static char *result; 288 int resultlen; 289 static char *yp_domain; 290 291 /* struct hostent *cmp_he;*/ 292 293 bpf = fopen(bootpfile, "r"); 294 if ( ! bpf ) 295 errx(1, "no %s", bootpfile); 296 297 /* XXX there is no way in ISO C to specify the maximal length for a 298 conversion in a variable way */ 299 while ( fscanf(bpf, "%254s", hostname) > 0 ) { 300 if ( *hostname != '#' ) { /* comment */ 301 if ( ! strcmp(hostname, askname) ) { 302 /* return true for match of hostname */ 303 res = 1; 304 break; 305 } else { 306 /* check the alias list */ 307 he = NULL; 308 he = gethostbyname(hostname); 309 if (he && !strcmp(askname, he->h_name)) { 310 res = 1; 311 break; 312 } 313 } 314 } 315 if (*hostname == '+' ) { /* NIS */ 316 if (yp_get_default_domain(&yp_domain)) { 317 if (debug) warn("NIS"); 318 return(0); 319 } 320 if (!yp_match(yp_domain, "bootparams", askname, strlen(askname), 321 &result, &resultlen)) { 322 /* return true for match of hostname */ 323 he = NULL; 324 he = gethostbyname(askname); 325 if (he && !strcmp(askname, he->h_name)) { 326 res = 1; 327 snprintf(hostname, len, "%s", he->h_name); 328 } 329 } 330 if (fclose(bpf)) 331 warnx("could not close %s", bootpfile); 332 return(res); 333 } 334 /* skip to next entry */ 335 pch = ch = getc(bpf); 336 while ( ! ( ch == '\n' && pch != '\\') && ch != EOF) { 337 pch = ch; ch = getc(bpf); 338 } 339 } 340 if (fclose(bpf)) { warnx("could not close %s", bootpfile); } 341 return(res); 342 } 343