#ifndef LINT
static char *rcsid="checkperm.c,v 1.1.1.1 1999/08/12 19:36:46 woods Exp";
#endif

/*
	checkperm.c,v
	Revision 1.1.1.1  1999/08/12 19:36:46  woods
	whoson version 1.08
	
	Revision 1.5  1998/07/26 14:06:40  crosser
	make it sutable for client too (extern names)

	Revision 1.4  1998/07/05 00:26:18  crosser
	Change copyright

	Revision 1.3  1998/07/04 23:39:35  crosser
	fix bug with zero mask

	Revision 1.3  1998/07/04 00:13:43  crosser
	*** empty log message ***

	Revision 1.2  1998/07/02 18:01:15  crosser
	change error reporting to syslog

	Revision 1.1  1998/07/02 15:37:07  crosser
	Initial revision

*/

/*
	WHAT IS IT:
		Implementation of experimental "whoson" protocol
	AUTHOR:
		Eugene G. Crosser <crosser@average.org>
	COPYRIGHT:
		Public domain
*/

#include "config.h"

#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <ctype.h>

#include "checkperm.h"
#include "report.h"

struct _perm *wso_perm_parse(int allow,char *what)
{
	struct _perm *rec;
	int a1,a2,a3,a4;
	unsigned long pattern,mask;
	int nbits;

	if (sscanf(what,"%d.%d.%d.%d/%d",&a1,&a2,&a3,&a4,&nbits) != 5) {
		ERRLOG((LOG_ERR,"unparsable pattern \"%s\"\n",what))
		return NULL;
	}

	if (nbits == 0) mask=0L;
	else mask=(~0L)<<((sizeof(unsigned long)*8)-nbits);
	pattern=(a1<<24)|(a2<<16)|(a3<<8)|(a4);
	pattern&=mask;
DPRINT(("perm_parse allow=%d nbits=%d pattern=%08lx mask=%08lx\n",
			allow,nbits,pattern,mask))

	rec=(struct _perm *)malloc(sizeof(struct _perm));
	if (rec == NULL) {
		ERRLOG((LOG_ERR,"alloc perm structure: %m"))
		return NULL;
	}

	rec->next=NULL;
	rec->allow=allow;
	rec->pattern=pattern;
	rec->mask=mask;
	rec->weight=nbits;
	return rec;
}

int wso_perm_check(struct _perm *chain,unsigned long addr)
{
	struct _perm *rec;
	int allow,weight;

	allow=0;
	weight=0;
	for (rec=chain;rec;rec=rec->next) {
		if (rec->weight < weight) continue;
		if ((addr & rec->mask) != rec->pattern) continue;
		allow=rec->allow;
		weight=rec->weight;
DPRINT(("perm_check found match %08lx allow=%d with weight=%d\n",
						addr,allow,weight))
	}

DPRINT(("perm_check returns allow=%d with weight=%d\n",allow,weight))

	return allow;
}
