#include <sys/cdefs.h>
#ifdef YP
#include <rpc/rpc.h>
#include <rpcsvc/yp_prot.h>
#include <rpcsvc/ypclnt.h>
#endif
#include "bootparam_prot.h"
#include <ctype.h>
#include <err.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <syslog.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
extern int debug, dolog;
extern in_addr_t route_addr;
extern const char *bootpfile;
#define MAXLEN 800
static struct hostent *he;
static char buffer[MAXLEN];
static char hostname[MAX_MACHINE_NAME + 1];
static char askname[MAX_MACHINE_NAME];
static char path[MAX_PATH_LEN];
static char domain_name[MAX_MACHINE_NAME];
static int getthefile(char *, char *, char *, int);
static int checkhost(char *, char *, int);
bp_whoami_res *
bootparamproc_whoami_1_svc(bp_whoami_arg *whoami, struct svc_req *req __unused)
{
in_addr_t haddr;
static bp_whoami_res res;
if (debug)
fprintf(stderr,"whoami got question for %d.%d.%d.%d\n",
255 & whoami->client_address.bp_address_u.ip_addr.net,
255 & whoami->client_address.bp_address_u.ip_addr.host,
255 & whoami->client_address.bp_address_u.ip_addr.lh,
255 & whoami->client_address.bp_address_u.ip_addr.impno);
if (dolog)
syslog(LOG_NOTICE, "whoami got question for %d.%d.%d.%d\n",
255 & whoami->client_address.bp_address_u.ip_addr.net,
255 & whoami->client_address.bp_address_u.ip_addr.host,
255 & whoami->client_address.bp_address_u.ip_addr.lh,
255 & whoami->client_address.bp_address_u.ip_addr.impno);
bcopy((char *)&whoami->client_address.bp_address_u.ip_addr, (char *)&haddr,
sizeof(haddr));
he = gethostbyaddr((char *)&haddr,sizeof(haddr),AF_INET);
if ( ! he ) goto failed;
if (debug) warnx("this is host %s", he->h_name);
if (dolog) syslog(LOG_NOTICE,"This is host %s\n", he->h_name);
strncpy(askname, he->h_name, sizeof(askname));
askname[sizeof(askname)-1] = 0;
if (checkhost(askname, hostname, sizeof hostname) ) {
res.client_name = hostname;
getdomainname(domain_name, MAX_MACHINE_NAME);
res.domain_name = domain_name;
if ( res.router_address.address_type != IP_ADDR_TYPE ) {
res.router_address.address_type = IP_ADDR_TYPE;
bcopy( &route_addr, &res.router_address.bp_address_u.ip_addr, sizeof(in_addr_t));
}
if (debug) fprintf(stderr,
"Returning %s %s %d.%d.%d.%d\n",
res.client_name,
res.domain_name,
255 & res.router_address.bp_address_u.ip_addr.net,
255 & res.router_address.bp_address_u.ip_addr.host,
255 & res.router_address.bp_address_u.ip_addr.lh,
255 & res.router_address.bp_address_u.ip_addr.impno);
if (dolog) syslog(LOG_NOTICE,
"Returning %s %s %d.%d.%d.%d\n",
res.client_name,
res.domain_name,
255 & res.router_address.bp_address_u.ip_addr.net,
255 & res.router_address.bp_address_u.ip_addr.host,
255 & res.router_address.bp_address_u.ip_addr.lh,
255 & res.router_address.bp_address_u.ip_addr.impno);
return(&res);
}
failed:
if (debug) warnx("whoami failed");
if (dolog) syslog(LOG_NOTICE,"whoami failed\n");
return(NULL);
}
bp_getfile_res *
bootparamproc_getfile_1_svc(bp_getfile_arg *getfile, struct svc_req *req __unused)
{
char *where;
static bp_getfile_res res;
if (debug)
warnx("getfile got question for \"%s\" and file \"%s\"",
getfile->client_name, getfile->file_id);
if (dolog)
syslog(LOG_NOTICE,"getfile got question for \"%s\" and file \"%s\"\n",
getfile->client_name, getfile->file_id);
he = NULL;
he = gethostbyname(getfile->client_name);
if (! he ) goto failed;
strncpy(askname, he->h_name, sizeof(askname));
askname[sizeof(askname)-1] = 0;
if (getthefile(askname, getfile->file_id,buffer,sizeof(buffer))) {
if ( (where = strchr(buffer,':')) ) {
strncpy(hostname, buffer, where - buffer);
hostname[where - buffer] = '\0';
where++;
strcpy(path, where);
he = gethostbyname(hostname);
if ( !he ) goto failed;
bcopy( he->h_addr, &res.server_address.bp_address_u.ip_addr, 4);
res.server_name = hostname;
res.server_path = path;
res.server_address.address_type = IP_ADDR_TYPE;
}
else {
if (!strcmp(getfile->file_id, "dump")) {
res.server_name = "";
res.server_path = "";
res.server_address.address_type = IP_ADDR_TYPE;
bzero(&res.server_address.bp_address_u.ip_addr,4);
} else goto failed;
}
if (debug)
fprintf(stderr, "returning server:%s path:%s address: %d.%d.%d.%d\n",
res.server_name, res.server_path,
255 & res.server_address.bp_address_u.ip_addr.net,
255 & res.server_address.bp_address_u.ip_addr.host,
255 & res.server_address.bp_address_u.ip_addr.lh,
255 & res.server_address.bp_address_u.ip_addr.impno);
if (dolog)
syslog(LOG_NOTICE, "returning server:%s path:%s address: %d.%d.%d.%d\n",
res.server_name, res.server_path,
255 & res.server_address.bp_address_u.ip_addr.net,
255 & res.server_address.bp_address_u.ip_addr.host,
255 & res.server_address.bp_address_u.ip_addr.lh,
255 & res.server_address.bp_address_u.ip_addr.impno);
return(&res);
}
failed:
if (debug) warnx("getfile failed for %s", getfile->client_name);
if (dolog) syslog(LOG_NOTICE,
"getfile failed for %s\n", getfile->client_name);
return(NULL);
}
static int
getthefile(char *l_askname, char *fileid, char *buf, int blen __unused)
{
FILE *bpf;
char *where;
#ifdef YP
static char *result;
int resultlen;
static char *yp_domain;
#endif
int ch, pch, fid_len, res = 0;
int match = 0;
#define INFOLEN 1343
_Static_assert(INFOLEN >= MAX_FILEID + MAX_PATH_LEN+MAX_MACHINE_NAME + 3,
"INFOLEN isn't large enough");
char info[INFOLEN + 1];
bpf = fopen(bootpfile, "r");
if ( ! bpf )
errx(1, "no %s", bootpfile);
while ( fscanf(bpf, "%255s", hostname) > 0 && !match ) {
if ( *hostname != '#' ) {
if ( ! strcmp(hostname, l_askname) ) {
match = 1;
} else {
he = gethostbyname(hostname);
if (he && !strcmp(he->h_name, l_askname)) match = 1;
}
}
if (*hostname == '+' ) {
#ifdef YP
if (yp_get_default_domain(&yp_domain)) {
if (debug) warn("NIS");
return(0);
}
if (yp_match(yp_domain, "bootparams", l_askname, strlen(l_askname),
&result, &resultlen))
return (0);
if (strstr(result, fileid) == NULL) {
buf[0] = '\0';
} else {
snprintf(buf, blen,
"%s",strchr(strstr(result,fileid), '=') + 1);
if (strchr(buf, ' ') != NULL)
*(char *)(strchr(buf, ' ')) = '\0';
}
if (fclose(bpf))
warnx("could not close %s", bootpfile);
return(1);
#else
if (fclose(bpf))
warnx("could not close %s", bootpfile);
return(0);
#endif
}
if ( match ) break;
pch = ch = getc(bpf);
while ( ! ( ch == '\n' && pch != '\\') && ch != EOF) {
pch = ch; ch = getc(bpf);
}
}
if (match) {
fid_len = strlen(fileid);
#define AS_FORMAT(d) "%" #d "s"
#define REXPAND(d) AS_FORMAT(d)
while ( ! res && (fscanf(bpf, REXPAND(INFOLEN), info)) > 0) {
ch = getc(bpf);
if ( *info != '#' ) {
if (! strncmp(info, fileid, fid_len) && *(info + fid_len) == '=') {
where = info + fid_len + 1;
if ( isprint( *where )) {
strcpy(buf, where);
res = 1; break;
}
} else {
while (isspace(ch) && ch != '\n') ch = getc(bpf);
if ( ch == '\n' ) {
res = -1; break;
}
if ( ch == '\\' ) {
ch = getc(bpf);
if (ch == '\n') continue;
ungetc(ch, bpf); ungetc('\\',bpf);
} else ungetc(ch, bpf);
}
} else break;
}
}
if (fclose(bpf)) { warnx("could not close %s", bootpfile); }
if ( res == -1) buf[0] = '\0';
return(match);
}
static int
checkhost(char *l_askname, char *l_hostname, int len __unused)
{
int ch, pch;
FILE *bpf;
int res = 0;
#ifdef YP
static char *result;
int resultlen;
static char *yp_domain;
#endif
bpf = fopen(bootpfile, "r");
if ( ! bpf )
errx(1, "no %s", bootpfile);
while ( fscanf(bpf, "%254s", l_hostname) > 0 ) {
if ( *l_hostname != '#' ) {
if ( ! strcmp(l_hostname, l_askname) ) {
res = 1;
break;
} else {
he = NULL;
he = gethostbyname(l_hostname);
if (he && !strcmp(l_askname, he->h_name)) {
res = 1;
break;
}
}
}
if (*l_hostname == '+' ) {
#ifdef YP
if (yp_get_default_domain(&yp_domain)) {
if (debug) warn("NIS");
return(0);
}
if (!yp_match(yp_domain, "bootparams", l_askname, strlen(l_askname),
&result, &resultlen)) {
he = NULL;
he = gethostbyname(l_askname);
if (he && !strcmp(l_askname, he->h_name)) {
res = 1;
snprintf(l_hostname, len, "%s", he->h_name);
}
}
if (fclose(bpf))
warnx("could not close %s", bootpfile);
return(res);
#else
return(0);
#endif
}
pch = ch = getc(bpf);
while ( ! ( ch == '\n' && pch != '\\') && ch != EOF) {
pch = ch; ch = getc(bpf);
}
}
if (fclose(bpf)) { warnx("could not close %s", bootpfile); }
return(res);
}