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$"; 13 #endif /* not lint */ 14 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; 33 34 #define MAXLEN 800 35 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]; 42 43 int getthefile(char *, char *, char *, int); 44 int checkhost(char *, char *, int); 45 46 bp_whoami_res * 47 bootparamproc_whoami_1_svc(whoami, req) 48 bp_whoami_arg *whoami; 49 struct svc_req *req; 50 { 51 in_addr_t haddr; 52 static bp_whoami_res res; 53 if (debug) 54 fprintf(stderr,"whoami got question for %d.%d.%d.%d\n", 55 255 & whoami->client_address.bp_address_u.ip_addr.net, 56 255 & whoami->client_address.bp_address_u.ip_addr.host, 57 255 & whoami->client_address.bp_address_u.ip_addr.lh, 58 255 & whoami->client_address.bp_address_u.ip_addr.impno); 59 if (dolog) 60 syslog(LOG_NOTICE, "whoami got question for %d.%d.%d.%d\n", 61 255 & whoami->client_address.bp_address_u.ip_addr.net, 62 255 & whoami->client_address.bp_address_u.ip_addr.host, 63 255 & whoami->client_address.bp_address_u.ip_addr.lh, 64 255 & whoami->client_address.bp_address_u.ip_addr.impno); 65 66 bcopy((char *)&whoami->client_address.bp_address_u.ip_addr, (char *)&haddr, 67 sizeof(haddr)); 68 he = gethostbyaddr((char *)&haddr,sizeof(haddr),AF_INET); 69 if ( ! he ) goto failed; 70 71 if (debug) warnx("this is host %s", he->h_name); 72 if (dolog) syslog(LOG_NOTICE,"This is host %s\n", he->h_name); 73 74 strncpy(askname, he->h_name, sizeof(askname)); 75 askname[sizeof(askname)-1] = 0; 76 77 if (checkhost(askname, hostname, sizeof hostname) ) { 78 res.client_name = hostname; 79 getdomainname(domain_name, MAX_MACHINE_NAME); 80 res.domain_name = domain_name; 81 82 if ( res.router_address.address_type != IP_ADDR_TYPE ) { 83 res.router_address.address_type = IP_ADDR_TYPE; 84 bcopy( &route_addr, &res.router_address.bp_address_u.ip_addr, sizeof(in_addr_t)); 85 } 86 if (debug) fprintf(stderr, 87 "Returning %s %s %d.%d.%d.%d\n", 88 res.client_name, 89 res.domain_name, 90 255 & res.router_address.bp_address_u.ip_addr.net, 91 255 & res.router_address.bp_address_u.ip_addr.host, 92 255 & res.router_address.bp_address_u.ip_addr.lh, 93 255 & res.router_address.bp_address_u.ip_addr.impno); 94 if (dolog) syslog(LOG_NOTICE, 95 "Returning %s %s %d.%d.%d.%d\n", 96 res.client_name, 97 res.domain_name, 98 255 & res.router_address.bp_address_u.ip_addr.net, 99 255 & res.router_address.bp_address_u.ip_addr.host, 100 255 & res.router_address.bp_address_u.ip_addr.lh, 101 255 & res.router_address.bp_address_u.ip_addr.impno); 102 103 return(&res); 104 } 105 failed: 106 if (debug) warnx("whoami failed"); 107 if (dolog) syslog(LOG_NOTICE,"whoami failed\n"); 108 return(NULL); 109 } 110 111 112 bp_getfile_res * 113 bootparamproc_getfile_1_svc(getfile, req) 114 bp_getfile_arg *getfile; 115 struct svc_req *req; 116 { 117 char *where; 118 static bp_getfile_res res; 119 120 if (debug) 121 warnx("getfile got question for \"%s\" and file \"%s\"", 122 getfile->client_name, getfile->file_id); 123 124 if (dolog) 125 syslog(LOG_NOTICE,"getfile got question for \"%s\" and file \"%s\"\n", 126 getfile->client_name, getfile->file_id); 127 128 he = NULL; 129 he = gethostbyname(getfile->client_name); 130 if (! he ) goto failed; 131 132 strncpy(askname, he->h_name, sizeof(askname)); 133 askname[sizeof(askname)-1] = 0; 134 135 if (getthefile(askname, getfile->file_id,buffer,sizeof(buffer))) { 136 if ( (where = strchr(buffer,':')) ) { 137 /* buffer is re-written to contain the name of the info of file */ 138 strncpy(hostname, buffer, where - buffer); 139 hostname[where - buffer] = '\0'; 140 where++; 141 strcpy(path, where); 142 he = gethostbyname(hostname); 143 if ( !he ) goto failed; 144 bcopy( he->h_addr, &res.server_address.bp_address_u.ip_addr, 4); 145 res.server_name = hostname; 146 res.server_path = path; 147 res.server_address.address_type = IP_ADDR_TYPE; 148 } 149 else { /* special for dump, answer with null strings */ 150 if (!strcmp(getfile->file_id, "dump")) { 151 res.server_name = ""; 152 res.server_path = ""; 153 res.server_address.address_type = IP_ADDR_TYPE; 154 bzero(&res.server_address.bp_address_u.ip_addr,4); 155 } else goto failed; 156 } 157 if (debug) 158 fprintf(stderr, "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); 164 if (dolog) 165 syslog(LOG_NOTICE, "returning server:%s path:%s address: %d.%d.%d.%d\n", 166 res.server_name, res.server_path, 167 255 & res.server_address.bp_address_u.ip_addr.net, 168 255 & res.server_address.bp_address_u.ip_addr.host, 169 255 & res.server_address.bp_address_u.ip_addr.lh, 170 255 & res.server_address.bp_address_u.ip_addr.impno); 171 return(&res); 172 } 173 failed: 174 if (debug) warnx("getfile failed for %s", getfile->client_name); 175 if (dolog) syslog(LOG_NOTICE, 176 "getfile failed for %s\n", getfile->client_name); 177 return(NULL); 178 } 179 180 /* getthefile return 1 and fills the buffer with the information 181 of the file, e g "host:/export/root/client" if it can be found. 182 If the host is in the database, but the file is not, the buffer 183 will be empty. (This makes it possible to give the special 184 empty answer for the file "dump") */ 185 186 int 187 getthefile(askname,fileid,buffer,blen) 188 char *askname; 189 char *fileid, *buffer; 190 int blen; 191 { 192 FILE *bpf; 193 char *where; 194 #ifdef YP 195 static char *result; 196 int resultlen; 197 static char *yp_domain; 198 #endif 199 200 int ch, pch, fid_len, res = 0; 201 int match = 0; 202 char info[MAX_FILEID + MAX_PATH_LEN+MAX_MACHINE_NAME + 3]; 203 204 bpf = fopen(bootpfile, "r"); 205 if ( ! bpf ) 206 errx(1, "no %s", bootpfile); 207 208 /* XXX see comment below */ 209 while ( fscanf(bpf, "%255s", hostname) > 0 && !match ) { 210 if ( *hostname != '#' ) { /* comment */ 211 if ( ! strcmp(hostname, askname) ) { 212 match = 1; 213 } else { 214 he = gethostbyname(hostname); 215 if (he && !strcmp(he->h_name, askname)) match = 1; 216 } 217 } 218 if (*hostname == '+' ) { /* NIS */ 219 #ifdef YP 220 if (yp_get_default_domain(&yp_domain)) { 221 if (debug) warn("NIS"); 222 return(0); 223 } 224 if (yp_match(yp_domain, "bootparams", askname, strlen(askname), 225 &result, &resultlen)) 226 return (0); 227 if (strstr(result, fileid) == NULL) { 228 buffer[0] = '\0'; 229 } else { 230 snprintf(buffer, blen, 231 "%s",strchr(strstr(result,fileid), '=') + 1); 232 if (strchr(buffer, ' ') != NULL) 233 *(char *)(strchr(buffer, ' ')) = '\0'; 234 } 235 if (fclose(bpf)) 236 warnx("could not close %s", bootpfile); 237 return(1); 238 #else 239 return(0); /* ENOTSUP */ 240 #endif 241 } 242 /* skip to next entry */ 243 if ( match ) break; 244 pch = ch = getc(bpf); 245 while ( ! ( ch == '\n' && pch != '\\') && ch != EOF) { 246 pch = ch; ch = getc(bpf); 247 } 248 } 249 250 /* if match is true we read the rest of the line to get the 251 info of the file */ 252 253 if (match) { 254 fid_len = strlen(fileid); 255 while ( ! res && (fscanf(bpf,"%s", info)) > 0) { /* read a string */ 256 ch = getc(bpf); /* and a character */ 257 if ( *info != '#' ) { /* Comment ? */ 258 if (! strncmp(info, fileid, fid_len) && *(info + fid_len) == '=') { 259 where = info + fid_len + 1; 260 if ( isprint( *where )) { 261 strcpy(buffer, where); /* found file */ 262 res = 1; break; 263 } 264 } else { 265 while (isspace(ch) && ch != '\n') ch = getc(bpf); 266 /* read to end of line */ 267 if ( ch == '\n' ) { /* didn't find it */ 268 res = -1; break; /* but host is there */ 269 } 270 if ( ch == '\\' ) { /* more info */ 271 ch = getc(bpf); /* maybe on next line */ 272 if (ch == '\n') continue; /* read it in next loop */ 273 ungetc(ch, bpf); ungetc('\\',bpf); /* push the character(s) back */ 274 } else ungetc(ch, bpf); /* but who know what a `\` is */ 275 } /* needed for. */ 276 } else break; /* a commented rest-of-line */ 277 } 278 } 279 if (fclose(bpf)) { warnx("could not close %s", bootpfile); } 280 if ( res == -1) buffer[0] = '\0'; /* host found, file not */ 281 return(match); 282 } 283 284 /* checkhost puts the hostname found in the database file in 285 the hostname-variable and returns 1, if askname is a valid 286 name for a host in the database */ 287 288 int 289 checkhost(askname, hostname, len) 290 char *askname; 291 char *hostname; 292 int len; 293 { 294 int ch, pch; 295 FILE *bpf; 296 int res = 0; 297 #ifdef YP 298 static char *result; 299 int resultlen; 300 static char *yp_domain; 301 #endif 302 303 /* struct hostent *cmp_he;*/ 304 305 bpf = fopen(bootpfile, "r"); 306 if ( ! bpf ) 307 errx(1, "no %s", bootpfile); 308 309 /* XXX there is no way in ISO C to specify the maximal length for a 310 conversion in a variable way */ 311 while ( fscanf(bpf, "%254s", hostname) > 0 ) { 312 if ( *hostname != '#' ) { /* comment */ 313 if ( ! strcmp(hostname, askname) ) { 314 /* return true for match of hostname */ 315 res = 1; 316 break; 317 } else { 318 /* check the alias list */ 319 he = NULL; 320 he = gethostbyname(hostname); 321 if (he && !strcmp(askname, he->h_name)) { 322 res = 1; 323 break; 324 } 325 } 326 } 327 if (*hostname == '+' ) { /* NIS */ 328 #ifdef YP 329 if (yp_get_default_domain(&yp_domain)) { 330 if (debug) warn("NIS"); 331 return(0); 332 } 333 if (!yp_match(yp_domain, "bootparams", askname, strlen(askname), 334 &result, &resultlen)) { 335 /* return true for match of hostname */ 336 he = NULL; 337 he = gethostbyname(askname); 338 if (he && !strcmp(askname, he->h_name)) { 339 res = 1; 340 snprintf(hostname, len, "%s", he->h_name); 341 } 342 } 343 if (fclose(bpf)) 344 warnx("could not close %s", bootpfile); 345 return(res); 346 #else 347 return(0); /* ENOTSUP */ 348 #endif 349 } 350 /* skip to next entry */ 351 pch = ch = getc(bpf); 352 while ( ! ( ch == '\n' && pch != '\\') && ch != EOF) { 353 pch = ch; ch = getc(bpf); 354 } 355 } 356 if (fclose(bpf)) { warnx("could not close %s", bootpfile); } 357 return(res); 358 } 359