145405Smsmith/* 245405Smsmith 345405SmsmithThis code is not copyright, and is placed in the public domain. Feel free to 445405Smsmithuse and modify. Please send modifications and/or suggestions + bug fixes to 545405Smsmith 645405Smsmith Klas Heggemann <klas@nada.kth.se> 745405Smsmith 845405Smsmith*/ 945405Smsmith 1045405Smsmith#ifndef lint 1145405Smsmithstatic const char rcsid[] = 1245405Smsmith "$FreeBSD$"; 1345405Smsmith#endif /* not lint */ 1445405Smsmith 1545405Smsmith#ifdef YP 1645405Smsmith#include <rpc/rpc.h> 1745405Smsmith#include <rpcsvc/yp_prot.h> 1845405Smsmith#include <rpcsvc/ypclnt.h> 1945405Smsmith#endif 2045405Smsmith#include "bootparam_prot.h" 2145405Smsmith#include <ctype.h> 2245405Smsmith#include <err.h> 2345405Smsmith#include <netdb.h> 2445405Smsmith#include <stdio.h> 2545405Smsmith#include <string.h> 2650477Speter#include <syslog.h> 2745405Smsmith#include <unistd.h> 2845405Smsmith#include <sys/types.h> 2945405Smsmith#include <sys/socket.h> 3045405Smsmithextern int debug, dolog; 3145405Smsmithextern in_addr_t route_addr; 3245405Smsmithextern char *bootpfile; 3345405Smsmith 3476078Sjhb#define MAXLEN 800 3545405Smsmith 3645405Smsmithstruct hostent *he; 3745405Smsmithstatic char buffer[MAXLEN]; 3845405Smsmithstatic char hostname[MAX_MACHINE_NAME]; 3945405Smsmithstatic char askname[MAX_MACHINE_NAME]; 4045405Smsmithstatic char path[MAX_PATH_LEN]; 4145405Smsmithstatic char domain_name[MAX_MACHINE_NAME]; 4245405Smsmith 4345405Smsmithint getthefile(char *, char *, char *, int); 4445405Smsmithint checkhost(char *, char *, int); 4545405Smsmith 4645405Smsmithbp_whoami_res * 4745405Smsmithbootparamproc_whoami_1_svc(whoami, req) 4845405Smsmithbp_whoami_arg *whoami; 4945405Smsmithstruct svc_req *req; 5045405Smsmith{ 5145405Smsmith in_addr_t haddr; 5245405Smsmith static bp_whoami_res res; 5345405Smsmith if (debug) 5445405Smsmith fprintf(stderr,"whoami got question for %d.%d.%d.%d\n", 5545405Smsmith 255 & whoami->client_address.bp_address_u.ip_addr.net, 5645405Smsmith 255 & whoami->client_address.bp_address_u.ip_addr.host, 5745405Smsmith 255 & whoami->client_address.bp_address_u.ip_addr.lh, 5845405Smsmith 255 & whoami->client_address.bp_address_u.ip_addr.impno); 5945405Smsmith if (dolog) 6045405Smsmith syslog(LOG_NOTICE, "whoami got question for %d.%d.%d.%d\n", 6145405Smsmith 255 & whoami->client_address.bp_address_u.ip_addr.net, 6245405Smsmith 255 & whoami->client_address.bp_address_u.ip_addr.host, 6346215Smsmith 255 & whoami->client_address.bp_address_u.ip_addr.lh, 6446215Smsmith 255 & whoami->client_address.bp_address_u.ip_addr.impno); 6546215Smsmith 6646215Smsmith bcopy((char *)&whoami->client_address.bp_address_u.ip_addr, (char *)&haddr, 6746215Smsmith sizeof(haddr)); 6845405Smsmith he = gethostbyaddr((char *)&haddr,sizeof(haddr),AF_INET); 6945405Smsmith if ( ! he ) goto failed; 7045405Smsmith 7146215Smsmith if (debug) warnx("this is host %s", he->h_name); 7246215Smsmith if (dolog) syslog(LOG_NOTICE,"This is host %s\n", he->h_name); 7345405Smsmith 7445405Smsmith strncpy(askname, he->h_name, sizeof(askname)); 7546215Smsmith askname[sizeof(askname)-1] = 0; 7646215Smsmith 7746215Smsmith if (checkhost(askname, hostname, sizeof hostname) ) { 7845405Smsmith res.client_name = hostname; 7945405Smsmith getdomainname(domain_name, MAX_MACHINE_NAME); 8045405Smsmith res.domain_name = domain_name; 8145405Smsmith 8294683Sdwmalone if ( res.router_address.address_type != IP_ADDR_TYPE ) { 8394683Sdwmalone res.router_address.address_type = IP_ADDR_TYPE; 8448925Smsmith bcopy( &route_addr, &res.router_address.bp_address_u.ip_addr, sizeof(in_addr_t)); 8548925Smsmith } 8645405Smsmith if (debug) fprintf(stderr, 8745405Smsmith "Returning %s %s %d.%d.%d.%d\n", 8845405Smsmith res.client_name, 8945405Smsmith res.domain_name, 9045405Smsmith 255 & res.router_address.bp_address_u.ip_addr.net, 9145405Smsmith 255 & res.router_address.bp_address_u.ip_addr.host, 9245405Smsmith 255 & res.router_address.bp_address_u.ip_addr.lh, 9345405Smsmith 255 & res.router_address.bp_address_u.ip_addr.impno); 9445405Smsmith if (dolog) syslog(LOG_NOTICE, 9545405Smsmith "Returning %s %s %d.%d.%d.%d\n", 9645405Smsmith res.client_name, 9745405Smsmith res.domain_name, 9845405Smsmith 255 & res.router_address.bp_address_u.ip_addr.net, 9994683Sdwmalone 255 & res.router_address.bp_address_u.ip_addr.host, 10094683Sdwmalone 255 & res.router_address.bp_address_u.ip_addr.lh, 10145405Smsmith 255 & res.router_address.bp_address_u.ip_addr.impno); 10245405Smsmith 10345405Smsmith return(&res); 10445405Smsmith } 10545405Smsmith failed: 10694683Sdwmalone if (debug) warnx("whoami failed"); 10794683Sdwmalone if (dolog) syslog(LOG_NOTICE,"whoami failed\n"); 10894683Sdwmalone return(NULL); 10994683Sdwmalone} 11094683Sdwmalone 11194683Sdwmalone 11294683Sdwmalonebp_getfile_res * 11394683Sdwmalone bootparamproc_getfile_1_svc(getfile, req) 11494683Sdwmalonebp_getfile_arg *getfile; 11548925Smsmithstruct svc_req *req; 11694683Sdwmalone{ 11748925Smsmith char *where, *index(); 11894683Sdwmalone static bp_getfile_res res; 11994683Sdwmalone 12094683Sdwmalone if (debug) 12194683Sdwmalone warnx("getfile got question for \"%s\" and file \"%s\"", 12294683Sdwmalone getfile->client_name, getfile->file_id); 12394683Sdwmalone 12494683Sdwmalone if (dolog) 12594683Sdwmalone syslog(LOG_NOTICE,"getfile got question for \"%s\" and file \"%s\"\n", 12694683Sdwmalone getfile->client_name, getfile->file_id); 12794683Sdwmalone 12845405Smsmith he = NULL; 12945405Smsmith he = gethostbyname(getfile->client_name); 13045405Smsmith if (! he ) goto failed; 13145405Smsmith 13245405Smsmith strncpy(askname, he->h_name, sizeof(askname)); 13345405Smsmith askname[sizeof(askname)-1] = 0; 13445405Smsmith 13545405Smsmith if (getthefile(askname, getfile->file_id,buffer,sizeof(buffer))) { 13645405Smsmith if ( (where = index(buffer,':')) ) { 13745405Smsmith /* buffer is re-written to contain the name of the info of file */ 13845405Smsmith strncpy(hostname, buffer, where - buffer); 13945405Smsmith hostname[where - buffer] = '\0'; 14045405Smsmith where++; 14145405Smsmith strcpy(path, where); 14245405Smsmith he = gethostbyname(hostname); 14345405Smsmith if ( !he ) goto failed; 14445405Smsmith bcopy( he->h_addr, &res.server_address.bp_address_u.ip_addr, 4); 14545405Smsmith res.server_name = hostname; 14645405Smsmith res.server_path = path; 14745405Smsmith res.server_address.address_type = IP_ADDR_TYPE; 14845405Smsmith } 14945405Smsmith else { /* special for dump, answer with null strings */ 15045405Smsmith if (!strcmp(getfile->file_id, "dump")) { 15145405Smsmith res.server_name = ""; 15245405Smsmith res.server_path = ""; 15345405Smsmith res.server_address.address_type = IP_ADDR_TYPE; 15445405Smsmith bzero(&res.server_address.bp_address_u.ip_addr,4); 15545405Smsmith } else goto failed; 15645405Smsmith } 15745405Smsmith if (debug) 15845405Smsmith fprintf(stderr, "returning server:%s path:%s address: %d.%d.%d.%d\n", 15945405Smsmith res.server_name, res.server_path, 16045405Smsmith 255 & res.server_address.bp_address_u.ip_addr.net, 16145405Smsmith 255 & res.server_address.bp_address_u.ip_addr.host, 16245405Smsmith 255 & res.server_address.bp_address_u.ip_addr.lh, 16345405Smsmith 255 & res.server_address.bp_address_u.ip_addr.impno); 16445405Smsmith if (dolog) 16545405Smsmith syslog(LOG_NOTICE, "returning server:%s path:%s address: %d.%d.%d.%d\n", 16694683Sdwmalone res.server_name, res.server_path, 16745405Smsmith 255 & res.server_address.bp_address_u.ip_addr.net, 16845405Smsmith 255 & res.server_address.bp_address_u.ip_addr.host, 16945405Smsmith 255 & res.server_address.bp_address_u.ip_addr.lh, 17045405Smsmith 255 & res.server_address.bp_address_u.ip_addr.impno); 17145405Smsmith return(&res); 17245405Smsmith } 17345405Smsmith failed: 17445405Smsmith if (debug) warnx("getfile failed for %s", getfile->client_name); 17545405Smsmith if (dolog) syslog(LOG_NOTICE, 17645405Smsmith "getfile failed for %s\n", getfile->client_name); 17745405Smsmith return(NULL); 17894683Sdwmalone} 17945405Smsmith 18045405Smsmith/* getthefile return 1 and fills the buffer with the information 18145405Smsmith of the file, e g "host:/export/root/client" if it can be found. 18245405Smsmith If the host is in the database, but the file is not, the buffer 18345405Smsmith will be empty. (This makes it possible to give the special 18445405Smsmith empty answer for the file "dump") */ 18545405Smsmith 18645405Smsmithint 18745405Smsmithgetthefile(askname,fileid,buffer,blen) 18845405Smsmithchar *askname; 18945405Smsmithchar *fileid, *buffer; 19094683Sdwmaloneint blen; 19145405Smsmith{ 19245405Smsmith FILE *bpf; 19345405Smsmith char *where; 19445405Smsmith#ifdef YP 19545405Smsmith static char *result; 19645405Smsmith int resultlen; 19745405Smsmith static char *yp_domain; 19845405Smsmith#endif 19945405Smsmith 20045405Smsmith int ch, pch, fid_len, res = 0; 20145405Smsmith int match = 0; 20245405Smsmith char info[MAX_FILEID + MAX_PATH_LEN+MAX_MACHINE_NAME + 3]; 20345405Smsmith 20494683Sdwmalone bpf = fopen(bootpfile, "r"); 20545405Smsmith if ( ! bpf ) 20645405Smsmith errx(1, "no %s", bootpfile); 20745405Smsmith 20845405Smsmith /* XXX see comment below */ 20945405Smsmith while ( fscanf(bpf, "%255s", hostname) > 0 && !match ) { 21045405Smsmith if ( *hostname != '#' ) { /* comment */ 21145405Smsmith if ( ! strcmp(hostname, askname) ) { 21245405Smsmith match = 1; 21345405Smsmith } else { 21445405Smsmith he = gethostbyname(hostname); 21545405Smsmith if (he && !strcmp(he->h_name, askname)) match = 1; 21645405Smsmith } 21745405Smsmith } 21845405Smsmith if (*hostname == '+' ) { /* NIS */ 21945405Smsmith#ifdef YP 22045405Smsmith if (yp_get_default_domain(&yp_domain)) { 22145405Smsmith if (debug) warn("NIS"); 22245405Smsmith return(0); 22345405Smsmith } 22445405Smsmith if (yp_match(yp_domain, "bootparams", askname, strlen(askname), 22545405Smsmith &result, &resultlen)) 22645405Smsmith return (0); 22745405Smsmith if (strstr(result, fileid) == NULL) { 22845405Smsmith buffer[0] = '\0'; 22945405Smsmith } else { 23094683Sdwmalone snprintf(buffer, blen, 23194683Sdwmalone "%s",strchr(strstr(result,fileid), '=') + 1); 23245405Smsmith if (strchr(buffer, ' ') != NULL) 23345405Smsmith *(char *)(strchr(buffer, ' ')) = '\0'; 23445405Smsmith } 23545405Smsmith if (fclose(bpf)) 23645405Smsmith warnx("could not close %s", bootpfile); 23745405Smsmith return(1); 23845405Smsmith#else 23994683Sdwmalone return(0); /* ENOTSUP */ 24094683Sdwmalone#endif 24194683Sdwmalone } 24294683Sdwmalone /* skip to next entry */ 24394683Sdwmalone if ( match ) break; 24494683Sdwmalone pch = ch = getc(bpf); 24594683Sdwmalone while ( ! ( ch == '\n' && pch != '\\') && ch != EOF) { 24694683Sdwmalone pch = ch; ch = getc(bpf); 24794683Sdwmalone } 24894683Sdwmalone } 24945405Smsmith 25046215Smsmith /* if match is true we read the rest of the line to get the 25146215Smsmith info of the file */ 25246215Smsmith 25346215Smsmith if (match) { 25445405Smsmith fid_len = strlen(fileid); 25548925Smsmith while ( ! res && (fscanf(bpf,"%s", info)) > 0) { /* read a string */ 25645405Smsmith ch = getc(bpf); /* and a character */ 25745405Smsmith if ( *info != '#' ) { /* Comment ? */ 25845405Smsmith if (! strncmp(info, fileid, fid_len) && *(info + fid_len) == '=') { 25945405Smsmith where = info + fid_len + 1; 26075421Sjhb if ( isprint( *where )) { 26145405Smsmith strcpy(buffer, where); /* found file */ 26245405Smsmith res = 1; break; 26345405Smsmith } 26445405Smsmith } else { 26548925Smsmith while (isspace(ch) && ch != '\n') ch = getc(bpf); 26648925Smsmith /* read to end of line */ 26745405Smsmith if ( ch == '\n' ) { /* didn't find it */ 26849421Smsmith res = -1; break; /* but host is there */ 26946215Smsmith } 27048925Smsmith if ( ch == '\\' ) { /* more info */ 27146215Smsmith ch = getc(bpf); /* maybe on next line */ 27246215Smsmith if (ch == '\n') continue; /* read it in next loop */ 27346215Smsmith ungetc(ch, bpf); ungetc('\\',bpf); /* push the character(s) back */ 27446215Smsmith } else ungetc(ch, bpf); /* but who know what a `\` is */ 27548925Smsmith } /* needed for. */ 27648925Smsmith } else break; /* a commented rest-of-line */ 27746215Smsmith } 27848925Smsmith } 27948925Smsmith if (fclose(bpf)) { warnx("could not close %s", bootpfile); } 28046215Smsmith if ( res == -1) buffer[0] = '\0'; /* host found, file not */ 28148925Smsmith return(match); 28246215Smsmith} 28394683Sdwmalone 28446215Smsmith/* checkhost puts the hostname found in the database file in 28546215Smsmith the hostname-variable and returns 1, if askname is a valid 28646215Smsmith name for a host in the database */ 28748925Smsmith 28846215Smsmithint 28945405Smsmithcheckhost(askname, hostname, len) 29045405Smsmithchar *askname; 29145405Smsmithchar *hostname; 29245405Smsmithint len; 29348925Smsmith{ 29445405Smsmith int ch, pch; 29545405Smsmith FILE *bpf; 29645405Smsmith int res = 0; 29745405Smsmith#ifdef YP 29845405Smsmith static char *result; 29945405Smsmith int resultlen; 30045405Smsmith static char *yp_domain; 30194683Sdwmalone#endif 30245405Smsmith 30345405Smsmith/* struct hostent *cmp_he;*/ 30494683Sdwmalone 30545405Smsmith bpf = fopen(bootpfile, "r"); 30645405Smsmith if ( ! bpf ) 30745405Smsmith errx(1, "no %s", bootpfile); 30845405Smsmith 30945405Smsmith /* XXX there is no way in ISO C to specify the maximal length for a 31045405Smsmith conversion in a variable way */ 31145405Smsmith while ( fscanf(bpf, "%254s", hostname) > 0 ) { 31294683Sdwmalone if ( *hostname != '#' ) { /* comment */ 31345405Smsmith if ( ! strcmp(hostname, askname) ) { 31445405Smsmith /* return true for match of hostname */ 31594683Sdwmalone res = 1; 31645405Smsmith break; 31745405Smsmith } else { 31845405Smsmith /* check the alias list */ 31945405Smsmith he = NULL; 32045405Smsmith he = gethostbyname(hostname); 32145405Smsmith if (he && !strcmp(askname, he->h_name)) { 32245405Smsmith res = 1; 32394683Sdwmalone break; 32445405Smsmith } 32545405Smsmith } 32694683Sdwmalone } 32745405Smsmith if (*hostname == '+' ) { /* NIS */ 32845405Smsmith#ifdef YP 32945405Smsmith if (yp_get_default_domain(&yp_domain)) { 33045405Smsmith if (debug) warn("NIS"); 33145405Smsmith return(0); 33245405Smsmith } 33345405Smsmith if (!yp_match(yp_domain, "bootparams", askname, strlen(askname), 33445405Smsmith &result, &resultlen)) { 33545405Smsmith /* return true for match of hostname */ 33645405Smsmith he = NULL; 33794683Sdwmalone he = gethostbyname(askname); 33845405Smsmith if (he && !strcmp(askname, he->h_name)) { 33945405Smsmith res = 1; 34094683Sdwmalone snprintf(hostname, len, "%s", he->h_name); 34145405Smsmith } 34245405Smsmith } 34345405Smsmith if (fclose(bpf)) 34445405Smsmith warnx("could not close %s", bootpfile); 34545405Smsmith return(res); 34645405Smsmith#else 34745405Smsmith return(0); /* ENOTSUP */ 34845405Smsmith#endif 34945405Smsmith } 35045405Smsmith /* skip to next entry */ 35145405Smsmith pch = ch = getc(bpf); 35245405Smsmith while ( ! ( ch == '\n' && pch != '\\') && ch != EOF) { 35345405Smsmith pch = ch; ch = getc(bpf); 35448925Smsmith } 35545405Smsmith } 35645405Smsmith if (fclose(bpf)) { warnx("could not close %s", bootpfile); } 35745405Smsmith return(res); 35845405Smsmith} 35945405Smsmith