#include <ctype.h>
#include <stdio.h>
#include <tiuser.h>
#include <netdir.h>
#include <netconfig.h>
#include <sys/utsname.h>
#include <sys/param.h>
#include <string.h>
#include <stdlib.h>
#define HOSTFILE "/etc/net/%s/hosts"
#define SERVICEFILE "/etc/net/%s/services"
#define FIELD1 1
#define FIELD2 2
#define LOCALHOST "localhost"
static int searchhost(struct netconfig *, char *, int, char *);
static int searchserv(struct netconfig *, char *, int, char *);
struct nd_addrlist *
_netdir_getbyname(struct netconfig *netconfigp,
struct nd_hostserv *nd_hostservp)
{
char fulladdr[BUFSIZ];
struct nd_addrlist *retp;
struct netbuf *netbufp;
if (strcmp(nd_hostservp->h_host, HOST_BROADCAST) == 0) {
_nderror = ND_NOHOST;
return (NULL);
}
if (searchhost(netconfigp, nd_hostservp->h_host, FIELD2,
fulladdr) == 0) {
_nderror = ND_NOHOST;
return (NULL);
}
if (nd_hostservp->h_serv &&
(strcmp(nd_hostservp->h_serv, "rpcbind") == 0)) {
(void) strcat(fulladdr, ".");
(void) strcat(fulladdr, "rpc");
} else {
if (nd_hostservp->h_serv && (nd_hostservp->h_serv[0] != '\0')) {
(void) strcat(fulladdr, ".");
if (searchserv(netconfigp, nd_hostservp->h_serv, FIELD1,
fulladdr + strlen(fulladdr)) == 0) {
_nderror = ND_NOSERV;
return (NULL);
}
}
}
if ((retp = malloc(sizeof (struct nd_addrlist))) == NULL) {
_nderror = ND_NOMEM;
return (NULL);
}
retp->n_cnt = 1;
if ((retp->n_addrs = malloc(sizeof (struct netbuf))) == NULL) {
free(retp);
_nderror = ND_NOMEM;
return (NULL);
}
netbufp = retp->n_addrs;
netbufp->len = netbufp->maxlen = (int)strlen(fulladdr);
if ((netbufp->buf = strdup(fulladdr)) == NULL) {
free(netbufp);
free(retp);
_nderror = ND_NOMEM;
return (NULL);
}
_nderror = ND_OK;
return (retp);
}
struct nd_hostservlist *
_netdir_getbyaddr(struct netconfig *netconfigp, struct netbuf *netbufp)
{
char fulladdr[BUFSIZ];
char servbuf[BUFSIZ];
char hostbuf[BUFSIZ];
char *hostname;
char *servname;
struct nd_hostservlist *retp;
char *serv;
int nhost;
struct nd_hostserv *nd_hostservp;
char *nexttok;
(void) strlcpy(fulladdr, netbufp->buf, sizeof (fulladdr));
hostname = strtok_r(fulladdr, ".", &nexttok);
if (hostname == NULL) {
_nderror = ND_NOHOST;
return (NULL);
}
servname = strtok_r(NULL, " \n\t", &nexttok);
nhost = searchhost(netconfigp, hostname, FIELD1, hostbuf);
if (nhost == 0) {
_nderror = ND_NOHOST;
return (NULL);
}
if (servname == NULL) {
_nderror = ND_NOSERV;
return (NULL);
}
servbuf[0] = '\0';
serv = servbuf;
if (searchserv(netconfigp, servname, FIELD2, servbuf) == 0) {
serv = _taddr2uaddr(netconfigp, netbufp);
(void) strcpy(servbuf, serv);
free(serv);
serv = servbuf;
while (*serv != '.')
serv++;
}
if ((retp = malloc(sizeof (struct nd_hostservlist))) == NULL) {
_nderror = ND_NOMEM;
return (NULL);
}
retp->h_cnt = nhost;
retp->h_hostservs = calloc(nhost, sizeof (struct nd_hostserv));
if (retp->h_hostservs == NULL) {
free(retp);
_nderror = ND_NOMEM;
return (NULL);
}
nd_hostservp = retp->h_hostservs;
hostname = strtok_r(hostbuf, ",", &nexttok);
while (hostname && nhost--) {
if (((nd_hostservp->h_host = strdup(hostname)) == NULL) ||
((nd_hostservp->h_serv = strdup(serv)) == NULL)) {
netdir_free(retp, ND_HOSTSERVLIST);
_nderror = ND_NOMEM;
return (NULL);
}
nd_hostservp++;
hostname = strtok_r(NULL, ",", &nexttok);
}
_nderror = ND_OK;
return (retp);
}
char *
_taddr2uaddr(struct netconfig *netconfigp, struct netbuf *netbufp)
{
char *retp;
char *to;
char *from;
int i;
if ((retp = malloc(BUFSIZ)) == NULL) {
_nderror = ND_NOMEM;
return (NULL);
}
to = retp;
from = netbufp->buf;
for (i = 0; i < netbufp->len; i++) {
if (*from == '\\') {
*to++ = '\\';
*to++ = '\\';
} else {
if (*from == '\n' || !isprint((unsigned char)*from)) {
(void) sprintf(to, "\\%.3o", *from & 0xff);
to += 4;
} else {
*to++ = *from;
}
}
from++;
}
*to = '\0';
return (retp);
}
struct netbuf *
_uaddr2taddr(struct netconfig *netconfigp, char *uaddr)
{
struct netbuf *retp;
char *holdp;
char *to;
char *from;
holdp = malloc(strlen(uaddr) + 1);
if (holdp == NULL) {
_nderror = ND_NOMEM;
return (NULL);
}
from = uaddr;
to = holdp;
while (*from) {
if (*from == '\\') {
if (*(from+1) == '\\') {
*to = '\\';
from += 2;
} else {
*to = ((*(from+1) - '0') << 6) +
((*(from+2) - '0') << 3) +
(*(from+3) - '0');
from += 4;
}
} else {
*to = *from++;
}
to++;
}
*to = '\0';
if ((retp = malloc(sizeof (struct netbuf))) == NULL) {
free(holdp);
_nderror = ND_NOMEM;
return (NULL);
}
retp->maxlen = retp->len = (int)(to - holdp);
retp->buf = holdp;
return (retp);
}
int
_netdir_options(struct netconfig *netconfigp, int option, int fd, void *par)
{
struct nd_mergearg *argp;
switch (option) {
case ND_MERGEADDR:
argp = (struct nd_mergearg *)par;
argp->m_uaddr = strdup(argp->s_uaddr);
if (argp->m_uaddr == NULL) {
_nderror = ND_NOMEM;
return (-1);
}
return (0);
default:
_nderror = ND_NOCTRL;
return (-1);
}
}
static int
searchhost(struct netconfig *netconfigp, char *token, int field, char *hostbuf)
{
char searchfile[MAXPATHLEN];
char buf[BUFSIZ];
char *fileaddr;
char *filehost;
char *cmpstr;
char *retstr;
char *nexttok;
FILE *fp;
int nelements = 0;
struct utsname utsname;
if ((strcmp(token, HOST_SELF_BIND) == 0) ||
(strcmp(token, HOST_SELF_CONNECT) == 0) ||
(strcmp(token, HOST_ANY) == 0) ||
(strcmp(token, LOCALHOST) == 0) ||
(uname(&utsname) >= 0 && strcmp(token, utsname.nodename) == 0)) {
(void) strcpy(hostbuf, LOCALHOST);
return (1);
}
if (strcmp(netconfigp->nc_protofmly, NC_LOOPBACK) == 0)
return (0);
(void) snprintf(searchfile, sizeof (searchfile), HOSTFILE,
netconfigp->nc_netid);
fp = fopen(searchfile, "rF");
if (fp == NULL)
return (0);
while (fgets(buf, BUFSIZ, fp) != NULL) {
fileaddr = strtok_r(buf, " \t\n", &nexttok);
if (fileaddr == NULL || *fileaddr == '#')
continue;
if ((filehost = strtok_r(NULL, " \t\n", &nexttok)) == NULL)
continue;
cmpstr = (field == FIELD1)? fileaddr : filehost;
retstr = (field == FIELD1)? filehost : fileaddr;
if (strcmp(token, cmpstr) == 0) {
nelements++;
if (field == FIELD2) {
(void) strcpy(hostbuf, retstr);
break;
}
if (nelements > 1) {
(void) strcat(hostbuf, ",");
}
(void) strcat(hostbuf, retstr);
}
}
(void) fclose(fp);
return (nelements);
}
static int
searchserv(struct netconfig *netconfigp, char *token, int field, char *servname)
{
char searchfile[MAXPATHLEN];
char buf[BUFSIZ];
char *fileservice;
char *fileport;
char *cmpstr;
char *retstr;
char *nexttok;
FILE *fp;
(void) snprintf(searchfile, sizeof (searchfile), SERVICEFILE,
netconfigp->nc_netid);
fp = fopen(searchfile, "rF");
if (fp == NULL)
return (0);
while (fgets(buf, BUFSIZ, fp) != NULL) {
fileservice = strtok_r(buf, " \t\n", &nexttok);
if (fileservice == NULL || *fileservice == '#')
continue;
if ((fileport = strtok_r(NULL, " \t\n", &nexttok)) == NULL)
continue;
cmpstr = (field == FIELD1)? fileservice : fileport;
retstr = (field == FIELD1)? fileport : fileservice;
if (strcmp(token, cmpstr) == 0) {
(void) strcpy(servname, retstr);
(void) fclose(fp);
return (1);
}
}
(void) fclose(fp);
return (0);
}