#include "sliplogin.h"
#include "scanfile.h"

#include <netdb.h>

#ifdef SLIP_MODES
slip_modes modes[] = {
	    "normal",	0,              
	    "compress",	SL_MODE_CSLIP,
	    "compressed",	SL_MODE_CSLIP,
#ifdef linux
	    "6bit",	SL_MODE_SLIP6,
	    "ax25",	SL_MODE_AX25,
#endif
#ifdef SL_MODE_NOICMP
	    "noicmp",	SL_MODE_NOICMP,
#endif
	    "link2",	SL_MODE_AUTO,	/* FreeBSD 2.0 ifconfig option */
	    "autocomp",	SL_MODE_AUTO,
	    "auto",	SL_MODE_AUTO
};
#endif

void scan_sliphosts(struct slipinfo *info)
{
    FILE *fp;
    static char mask[16];
    char user[16];
    char loginargs[BUFSIZ], timeout[16];
    int j;

    if ((fp = fopen(_PATH_ACCESS, "r")) == NULL)
    {
	fprintf(stderr,"sliplogin: %s: %s\n", _PATH_ACCESS, strerror(errno));
	syslog(LOG_ERR, "%s: %m\n", _PATH_ACCESS);
	exit(1);
    }

    /* MAIN SEARCH LOOP */
    while (fgets(loginargs, sizeof(loginargs) - 1, fp))
    {
	if (ferror(fp)) break;
	if (loginargs[0]=='#') continue; /* Comment */
	
	if (loginargs[0]=='+') /* Look at NIS map ? */
	{
	    char *nisdomain, *outval, *c;
	    int   outvallen, status;

#ifdef linux	    
	    if(__yp_check(NULL)!=1) {
		syslog(LOG_ERR,"YP not running\n"); continue;
	    }
#endif	    
	    yp_get_default_domain(&nisdomain);
	    if (!nisdomain) continue;
	    
	    status=yp_match(nisdomain,"slip.hosts", info->loginname,
			    strlen(info->loginname), &outval, &outvallen);
	    if(status!=0)
	    {
		fprintf(stderr,"%s not in NIS map slip.hosts\n",
			info->loginname);
		continue; /* Read next line */
	    }
	    sscanf(outval, "%15s%15s%15s%15s%15s%15s%15s%15s%15s",
		   user, info->laddr, info->raddr, info->mask, info->sm_name,
		   timeout, info->option[0], info->option[1], info->option[2]);
	    if(strlen(loginargs+1)>1) /* Local address given */
	    {
		if((c=strchr(loginargs,'\n'))!=NULL) *c='\0';
		strncpy(info->laddr,loginargs+1,15);
	    }
	} else /* No NIS search */
	{
	    sscanf(loginargs, "%15s%15s%15s%15s%15s%15s%15s%15s%15s",
		   user, info->laddr, info->raddr, info->mask, info->sm_name,
		   timeout, info->option[0], info->option[1], info->option[2]);
	}
	if ( (strcmp(user, info->loginname) != 0) && strcmp(user, "*") != 0)
	  continue; /* Read next line */
	
	/* Found user */
	info->timeout=atoi(timeout);
	if (!info->timeout) info->timeout=-1;
	fclose(fp);
	
	/* Now check for dynamic IP assigning */
	if (strcmp(info->raddr, "DYNAMIC")==0 || strcmp(info->raddr, "*")==0)
	{
	    char *ttyn,sliptty[20],dynamic[80];
	    ttyn=ttyname(0);
	    if ((fp = fopen(_PATH_SLIPTTY, "r")) == NULL)
	    {
		fprintf(stderr,"sliplogin: %s: %s\n",
			_PATH_SLIPTTY, strerror(errno));
		syslog(LOG_ERR, "%s: %m\n", _PATH_SLIPTTY);
		FATAL(1);
	    }
	    while (fgets(dynamic, 79, fp))
	    {
		if (ferror(fp)) break;
		if (dynamic[0]=='#') continue;
		sscanf(dynamic, "%15s%15s", sliptty,info->raddr);
		if (strcmp(ttyn, sliptty) != 0) continue;
		fclose(fp);
		fp=NULL;
		break;
	    }
	    if (fp!=NULL)
	    {
		fclose(fp);
		fprintf(stderr,"sliplogin: %s not found in %s\n",
			ttyn,_PATH_SLIPTTY);
		syslog(LOG_ERR,"%s not found in %s\n",ttyn,_PATH_SLIPTTY);
		syslog(LOG_ERR,"Couldn't start slip session for %s\n",
		       info->loginname);
		FATAL(-1);
	    }
	} /* end if DYNAMIC */

	/* check for dynamic local address */
#ifdef DYNAMIC_SERVER
	strcpy(info->laddr, "*");
#endif
	if (strcmp(info->laddr, "DYNAMIC")==0 || strcmp(info->laddr, "*")==0)
	{
	    char hostname[32];
	    struct hostent* entry;
	    gethostname(hostname, 32);
	    entry = gethostbyname(hostname);
	    if (!entry) {
		syslog(LOG_ERR,"hostname not found: %m"); exit(1);
	    }
	    strcpy(info->laddr, inet_ntoa(*(struct in_addr*)entry->h_addr));
	}
	
#ifdef SLIP_MODES
	/* Prepare slip_mode */
	info->sm_value = 0;
	for (j = 0; j < sizeof(modes)/sizeof(struct slip_modes); j++)
	{
	    if (strcmp(modes[j].sm_name, info->sm_name) == 0)
	    {
		info->sm_value |= modes[j].sm_value;
		break;
	    }
	} /* end for */
#endif
	
	/*
	 * see if there's a login file we can use.  First check for
	 * one specific to this host.  If none found, try for
	 * a generic one.
	 */
	sprintf(info->loginfile, "%s.%s", _PATH_LOGIN, info->loginname);
	if (access(info->loginfile, R_OK|X_OK) != 0)
	{
	    strcpy(info->loginfile, _PATH_LOGIN);
	    if (access(info->loginfile, R_OK|X_OK))
	    {
		fputs("access denied - no login file\n", stderr);
		syslog(LOG_ERR,"access denied for %s - no %s\n",
		       info->loginname, info->loginfile);
		FATAL(5);
	    }
	}
	return;
    } /* end while */
    fclose(fp);
    (void)fprintf(stderr, "SLIP access denied for %s\n", info->loginname);
    syslog(LOG_ERR, "SLIP access denied for %s\n", info->loginname);
    FATAL(4);
}
