xref: /plan9/sys/src/cmd/ip/dhcpd/db.c (revision ec46fab06dcae3e636b775c4eaa679036316e1d8)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <ip.h>
47dd7cddfSDavid du Colombier #include <bio.h>
57dd7cddfSDavid du Colombier #include <ndb.h>
67dd7cddfSDavid du Colombier #include <ctype.h>
77dd7cddfSDavid du Colombier #include "dat.h"
87dd7cddfSDavid du Colombier 
97dd7cddfSDavid du Colombier /*
107dd7cddfSDavid du Colombier  *  format of a binding entry:
117dd7cddfSDavid du Colombier  *	char ipaddr[32];
127dd7cddfSDavid du Colombier  *	char id[32];
137dd7cddfSDavid du Colombier  *	char hwa[32];
147dd7cddfSDavid du Colombier  *	char otime[10];
157dd7cddfSDavid du Colombier  */
167dd7cddfSDavid du Colombier Binding *bcache;
177dd7cddfSDavid du Colombier uchar bfirst[IPaddrlen];
187dd7cddfSDavid du Colombier char *binddir = "/lib/ndb/dhcp";
197dd7cddfSDavid du Colombier 
207dd7cddfSDavid du Colombier /*
217dd7cddfSDavid du Colombier  *  convert a byte array to hex
227dd7cddfSDavid du Colombier  */
237dd7cddfSDavid du Colombier static char
hex(int x)247dd7cddfSDavid du Colombier hex(int x)
257dd7cddfSDavid du Colombier {
267dd7cddfSDavid du Colombier 	if(x < 10)
277dd7cddfSDavid du Colombier 		return x + '0';
287dd7cddfSDavid du Colombier 	return x - 10 + 'a';
297dd7cddfSDavid du Colombier }
307dd7cddfSDavid du Colombier extern char*
tohex(char * hdr,uchar * p,int len)317dd7cddfSDavid du Colombier tohex(char *hdr, uchar *p, int len)
327dd7cddfSDavid du Colombier {
337dd7cddfSDavid du Colombier 	char *s, *sp;
347dd7cddfSDavid du Colombier 	int hlen;
357dd7cddfSDavid du Colombier 
367dd7cddfSDavid du Colombier 	hlen = strlen(hdr);
377dd7cddfSDavid du Colombier 	s = malloc(hlen + 2*len + 1);
387dd7cddfSDavid du Colombier 	sp = s;
397dd7cddfSDavid du Colombier 	strcpy(sp, hdr);
407dd7cddfSDavid du Colombier 	sp += hlen;
417dd7cddfSDavid du Colombier 	for(; len > 0; len--){
427dd7cddfSDavid du Colombier 		*sp++ = hex(*p>>4);
437dd7cddfSDavid du Colombier 		*sp++ = hex(*p & 0xf);
447dd7cddfSDavid du Colombier 		p++;
457dd7cddfSDavid du Colombier 	}
467dd7cddfSDavid du Colombier 	*sp = 0;
477dd7cddfSDavid du Colombier 	return s;
487dd7cddfSDavid du Colombier }
497dd7cddfSDavid du Colombier 
507dd7cddfSDavid du Colombier /*
517dd7cddfSDavid du Colombier  *  convert a client id to a string.  If it's already
527dd7cddfSDavid du Colombier  *  ascii, leave it be.  Otherwise, convert it to hex.
537dd7cddfSDavid du Colombier  */
547dd7cddfSDavid du Colombier extern char*
toid(uchar * p,int n)557dd7cddfSDavid du Colombier toid(uchar *p, int n)
567dd7cddfSDavid du Colombier {
577dd7cddfSDavid du Colombier 	int i;
587dd7cddfSDavid du Colombier 	char *s;
597dd7cddfSDavid du Colombier 
607dd7cddfSDavid du Colombier 	for(i = 0; i < n; i++)
617dd7cddfSDavid du Colombier 		if(!isprint(p[i]))
627dd7cddfSDavid du Colombier 			return tohex("id", p, n);
637dd7cddfSDavid du Colombier 	s = malloc(n + 1);
647dd7cddfSDavid du Colombier 	memmove(s, p, n);
657dd7cddfSDavid du Colombier 	s[n] = 0;
667dd7cddfSDavid du Colombier 	return s;
677dd7cddfSDavid du Colombier }
687dd7cddfSDavid du Colombier 
697dd7cddfSDavid du Colombier /*
707dd7cddfSDavid du Colombier  *  increment an ip address
717dd7cddfSDavid du Colombier  */
727dd7cddfSDavid du Colombier static void
incip(uchar * ip)737dd7cddfSDavid du Colombier incip(uchar *ip)
747dd7cddfSDavid du Colombier {
757dd7cddfSDavid du Colombier 	int i, x;
767dd7cddfSDavid du Colombier 
777dd7cddfSDavid du Colombier 	for(i = IPaddrlen-1; i >= 0; i--){
787dd7cddfSDavid du Colombier 		x = ip[i];
797dd7cddfSDavid du Colombier 		x++;
807dd7cddfSDavid du Colombier 		ip[i] = x;
817dd7cddfSDavid du Colombier 		if((x & 0x100) == 0)
827dd7cddfSDavid du Colombier 			break;
837dd7cddfSDavid du Colombier 	}
847dd7cddfSDavid du Colombier }
857dd7cddfSDavid du Colombier 
867dd7cddfSDavid du Colombier /*
877dd7cddfSDavid du Colombier  *  find a binding for an id or hardware address
887dd7cddfSDavid du Colombier  */
897dd7cddfSDavid du Colombier static int
lockopen(char * file)907dd7cddfSDavid du Colombier lockopen(char *file)
917dd7cddfSDavid du Colombier {
929a747e4fSDavid du Colombier 	char err[ERRMAX];
937dd7cddfSDavid du Colombier 	int fd, tries;
947dd7cddfSDavid du Colombier 
957dd7cddfSDavid du Colombier 	for(tries = 0; tries < 5; tries++){
967dd7cddfSDavid du Colombier 		fd = open(file, ORDWR);
977dd7cddfSDavid du Colombier 		if(fd >= 0)
987dd7cddfSDavid du Colombier 			return fd;
999a747e4fSDavid du Colombier 		errstr(err, sizeof err);
1007dd7cddfSDavid du Colombier 		if(strstr(err, "lock")){
1017dd7cddfSDavid du Colombier 			/* wait for other process to let go of lock */
1027dd7cddfSDavid du Colombier 			sleep(250);
1037dd7cddfSDavid du Colombier 
1047dd7cddfSDavid du Colombier 			/* try again */
1057dd7cddfSDavid du Colombier 			continue;
1067dd7cddfSDavid du Colombier 		}
1077dd7cddfSDavid du Colombier 		if(strstr(err, "exist")){
1087dd7cddfSDavid du Colombier 			/* no file, create an exclusive access file */
1099a747e4fSDavid du Colombier 			fd = create(file, ORDWR, DMEXCL|0664);
1107dd7cddfSDavid du Colombier 			if(fd >= 0)
1117dd7cddfSDavid du Colombier 				return fd;
1127dd7cddfSDavid du Colombier 		}
1137dd7cddfSDavid du Colombier 	}
1147dd7cddfSDavid du Colombier 	return -1;
1157dd7cddfSDavid du Colombier }
1167dd7cddfSDavid du Colombier 
1177dd7cddfSDavid du Colombier void
setbinding(Binding * b,char * id,long t)1187dd7cddfSDavid du Colombier setbinding(Binding *b, char *id, long t)
1197dd7cddfSDavid du Colombier {
1207dd7cddfSDavid du Colombier 	if(b->boundto)
1217dd7cddfSDavid du Colombier 		free(b->boundto);
1227dd7cddfSDavid du Colombier 
1237dd7cddfSDavid du Colombier 	b->boundto = strdup(id);
1247dd7cddfSDavid du Colombier 	b->lease = t;
1257dd7cddfSDavid du Colombier }
1267dd7cddfSDavid du Colombier 
1277dd7cddfSDavid du Colombier static void
parsebinding(Binding * b,char * buf)1287dd7cddfSDavid du Colombier parsebinding(Binding *b, char *buf)
1297dd7cddfSDavid du Colombier {
1307dd7cddfSDavid du Colombier 	long t;
1317dd7cddfSDavid du Colombier 	char *id, *p;
1327dd7cddfSDavid du Colombier 
1337dd7cddfSDavid du Colombier 	/* parse */
1347dd7cddfSDavid du Colombier 	t = atoi(buf);
1357dd7cddfSDavid du Colombier 	id = strchr(buf, '\n');
1367dd7cddfSDavid du Colombier 	if(id){
1377dd7cddfSDavid du Colombier 		*id++ = 0;
1387dd7cddfSDavid du Colombier 		p = strchr(id, '\n');
1397dd7cddfSDavid du Colombier 		if(p)
1407dd7cddfSDavid du Colombier 			*p = 0;
1417dd7cddfSDavid du Colombier 	} else
1427dd7cddfSDavid du Colombier 		id = "";
1437dd7cddfSDavid du Colombier 
1447dd7cddfSDavid du Colombier 	/* replace any past info */
1457dd7cddfSDavid du Colombier 	setbinding(b, id, t);
1467dd7cddfSDavid du Colombier }
1477dd7cddfSDavid du Colombier 
1487dd7cddfSDavid du Colombier static int
writebinding(int fd,Binding * b)1497dd7cddfSDavid du Colombier writebinding(int fd, Binding *b)
1507dd7cddfSDavid du Colombier {
1519a747e4fSDavid du Colombier 	Dir *d;
1527dd7cddfSDavid du Colombier 
1537dd7cddfSDavid du Colombier 	seek(fd, 0, 0);
1547dd7cddfSDavid du Colombier 	if(fprint(fd, "%ld\n%s\n", b->lease, b->boundto) < 0)
1557dd7cddfSDavid du Colombier 		return -1;
1569a747e4fSDavid du Colombier 	d = dirfstat(fd);
1579a747e4fSDavid du Colombier 	if(d == nil)
1587dd7cddfSDavid du Colombier 		return -1;
1599a747e4fSDavid du Colombier 	b->q.type = d->qid.type;
1609a747e4fSDavid du Colombier 	b->q.path = d->qid.path;
1619a747e4fSDavid du Colombier 	b->q.vers = d->qid.vers;
1629a747e4fSDavid du Colombier 	free(d);
1637dd7cddfSDavid du Colombier 	return 0;
1647dd7cddfSDavid du Colombier }
1657dd7cddfSDavid du Colombier 
1667dd7cddfSDavid du Colombier /*
1677dd7cddfSDavid du Colombier  *  synchronize cached binding with file.  the file always wins.
1687dd7cddfSDavid du Colombier  */
169*3ff48bf5SDavid du Colombier int
syncbinding(Binding * b,int returnfd)1707dd7cddfSDavid du Colombier syncbinding(Binding *b, int returnfd)
1717dd7cddfSDavid du Colombier {
1727dd7cddfSDavid du Colombier 	char buf[512];
1737dd7cddfSDavid du Colombier 	int i, fd;
1749a747e4fSDavid du Colombier 	Dir *d;
1757dd7cddfSDavid du Colombier 
1767dd7cddfSDavid du Colombier 	snprint(buf, sizeof(buf), "%s/%I", binddir, b->ip);
1777dd7cddfSDavid du Colombier 	fd = lockopen(buf);
1787dd7cddfSDavid du Colombier 	if(fd < 0){
1797dd7cddfSDavid du Colombier 		/* assume someone else is using it */
1807dd7cddfSDavid du Colombier 		b->lease = time(0) + OfferTimeout;
1817dd7cddfSDavid du Colombier 		return -1;
1827dd7cddfSDavid du Colombier 	}
1837dd7cddfSDavid du Colombier 
1847dd7cddfSDavid du Colombier 	/* reread if changed */
1859a747e4fSDavid du Colombier 	d = dirfstat(fd);
1869a747e4fSDavid du Colombier 	if(d != nil)	/* BUG? */
1879a747e4fSDavid du Colombier 	if(d->qid.type != b->q.type || d->qid.path != b->q.path || d->qid.vers != b->q.vers){
1887dd7cddfSDavid du Colombier 		i = read(fd, buf, sizeof(buf)-1);
1897dd7cddfSDavid du Colombier 		if(i < 0)
1907dd7cddfSDavid du Colombier 			i = 0;
1917dd7cddfSDavid du Colombier 		buf[i] = 0;
1927dd7cddfSDavid du Colombier 		parsebinding(b, buf);
1939a747e4fSDavid du Colombier 		b->lasttouched = d->mtime;
1949a747e4fSDavid du Colombier 		b->q.path = d->qid.path;
1959a747e4fSDavid du Colombier 		b->q.vers = d->qid.vers;
1967dd7cddfSDavid du Colombier 	}
1977dd7cddfSDavid du Colombier 
1989a747e4fSDavid du Colombier 	free(d);
1999a747e4fSDavid du Colombier 
2007dd7cddfSDavid du Colombier 	if(returnfd)
2017dd7cddfSDavid du Colombier 		return fd;
2027dd7cddfSDavid du Colombier 
2037dd7cddfSDavid du Colombier 	close(fd);
2047dd7cddfSDavid du Colombier 	return 0;
2057dd7cddfSDavid du Colombier }
2067dd7cddfSDavid du Colombier 
2077dd7cddfSDavid du Colombier extern int
samenet(uchar * ip,Info * iip)2087dd7cddfSDavid du Colombier samenet(uchar *ip, Info *iip)
2097dd7cddfSDavid du Colombier {
2107dd7cddfSDavid du Colombier 	uchar x[IPaddrlen];
2117dd7cddfSDavid du Colombier 
2127dd7cddfSDavid du Colombier 	maskip(iip->ipmask, ip, x);
2137dd7cddfSDavid du Colombier 	return ipcmp(x, iip->ipnet) == 0;
2147dd7cddfSDavid du Colombier }
2157dd7cddfSDavid du Colombier 
2167dd7cddfSDavid du Colombier /*
2177dd7cddfSDavid du Colombier  *  create a record for each binding
2187dd7cddfSDavid du Colombier  */
2197dd7cddfSDavid du Colombier extern void
initbinding(uchar * first,int n)2207dd7cddfSDavid du Colombier initbinding(uchar *first, int n)
2217dd7cddfSDavid du Colombier {
2227dd7cddfSDavid du Colombier 	while(n-- > 0){
2237dd7cddfSDavid du Colombier 		iptobinding(first, 1);
2247dd7cddfSDavid du Colombier 		incip(first);
2257dd7cddfSDavid du Colombier 	}
2267dd7cddfSDavid du Colombier }
2277dd7cddfSDavid du Colombier 
2287dd7cddfSDavid du Colombier /*
2297dd7cddfSDavid du Colombier  *  find a binding for a specific ip address
2307dd7cddfSDavid du Colombier  */
2317dd7cddfSDavid du Colombier extern Binding*
iptobinding(uchar * ip,int mk)2327dd7cddfSDavid du Colombier iptobinding(uchar *ip, int mk)
2337dd7cddfSDavid du Colombier {
2347dd7cddfSDavid du Colombier 	Binding *b;
2357dd7cddfSDavid du Colombier 
2367dd7cddfSDavid du Colombier 	for(b = bcache; b; b = b->next){
2377dd7cddfSDavid du Colombier 		if(ipcmp(b->ip, ip) == 0){
2387dd7cddfSDavid du Colombier 			syncbinding(b, 0);
2397dd7cddfSDavid du Colombier 			return b;
2407dd7cddfSDavid du Colombier 		}
2417dd7cddfSDavid du Colombier 	}
2427dd7cddfSDavid du Colombier 
2437dd7cddfSDavid du Colombier 	if(mk == 0)
2447dd7cddfSDavid du Colombier 		return 0;
2457dd7cddfSDavid du Colombier 	b = malloc(sizeof(*b));
2467dd7cddfSDavid du Colombier 	memset(b, 0, sizeof(*b));
2477dd7cddfSDavid du Colombier 	ipmove(b->ip, ip);
2487dd7cddfSDavid du Colombier 	b->next = bcache;
2497dd7cddfSDavid du Colombier 	bcache = b;
2507dd7cddfSDavid du Colombier 	syncbinding(b, 0);
2517dd7cddfSDavid du Colombier 	return b;
2527dd7cddfSDavid du Colombier }
2537dd7cddfSDavid du Colombier 
2547dd7cddfSDavid du Colombier static void
lognolease(Binding * b)2557dd7cddfSDavid du Colombier lognolease(Binding *b)
2567dd7cddfSDavid du Colombier {
25780ee5cbfSDavid du Colombier 	/* renew the old binding, and hope it eventually goes away */
25880ee5cbfSDavid du Colombier 	b->offer = 5*60;
25980ee5cbfSDavid du Colombier 	commitbinding(b);
26080ee5cbfSDavid du Colombier 
26180ee5cbfSDavid du Colombier 	/* complain if we haven't in the last 5 minutes */
26259cc4ca5SDavid du Colombier 	if(now - b->lastcomplained < 5*60)
26359cc4ca5SDavid du Colombier 		return;
26459cc4ca5SDavid du Colombier 	syslog(0, blog, "dhcp: lease for %I to %s ended at %ld but still in use\n",
2657dd7cddfSDavid du Colombier 		b->ip, b->boundto != nil ? b->boundto : "?", b->lease);
26680ee5cbfSDavid du Colombier 	b->lastcomplained = now;
2677dd7cddfSDavid du Colombier }
2687dd7cddfSDavid du Colombier 
2697dd7cddfSDavid du Colombier /*
2707dd7cddfSDavid du Colombier  *  find a free binding for a hw addr or id on the same network as iip
2717dd7cddfSDavid du Colombier  */
2727dd7cddfSDavid du Colombier extern Binding*
idtobinding(char * id,Info * iip,int ping)2737dd7cddfSDavid du Colombier idtobinding(char *id, Info *iip, int ping)
2747dd7cddfSDavid du Colombier {
2757dd7cddfSDavid du Colombier 	Binding *b, *oldest;
2767dd7cddfSDavid du Colombier 	int oldesttime;
2777dd7cddfSDavid du Colombier 
2787dd7cddfSDavid du Colombier 	/*
2797dd7cddfSDavid du Colombier 	 *  first look for an old binding that matches.  that way
2807dd7cddfSDavid du Colombier 	 *  clients will tend to keep the same ip addresses.
2817dd7cddfSDavid du Colombier 	 */
2827dd7cddfSDavid du Colombier 	for(b = bcache; b; b = b->next){
2837dd7cddfSDavid du Colombier 		if(b->boundto && strcmp(b->boundto, id) == 0){
2847dd7cddfSDavid du Colombier 			if(!samenet(b->ip, iip))
2857dd7cddfSDavid du Colombier 				continue;
2867dd7cddfSDavid du Colombier 
2877dd7cddfSDavid du Colombier 			/* check with the other servers */
2887dd7cddfSDavid du Colombier 			syncbinding(b, 0);
2897dd7cddfSDavid du Colombier 			if(strcmp(b->boundto, id) == 0)
2907dd7cddfSDavid du Colombier 				return b;
2917dd7cddfSDavid du Colombier 		}
2927dd7cddfSDavid du Colombier 	}
2937dd7cddfSDavid du Colombier 
2947dd7cddfSDavid du Colombier 	/*
2957dd7cddfSDavid du Colombier 	 *  look for oldest binding that we think is unused
2967dd7cddfSDavid du Colombier 	 */
2977dd7cddfSDavid du Colombier 	for(;;){
2987dd7cddfSDavid du Colombier 		oldest = nil;
2997dd7cddfSDavid du Colombier 		oldesttime = 0;
3007dd7cddfSDavid du Colombier 		for(b = bcache; b; b = b->next){
30159cc4ca5SDavid du Colombier 			if(b->tried != now)
3027dd7cddfSDavid du Colombier 			if(b->lease < now && b->expoffer < now && samenet(b->ip, iip))
3037dd7cddfSDavid du Colombier 			if(oldest == nil || b->lasttouched < oldesttime){
3047dd7cddfSDavid du Colombier 				/* sync and check again */
3057dd7cddfSDavid du Colombier 				syncbinding(b, 0);
3067dd7cddfSDavid du Colombier 				if(b->lease < now && b->expoffer < now && samenet(b->ip, iip))
3077dd7cddfSDavid du Colombier 				if(oldest == nil || b->lasttouched < oldesttime){
3087dd7cddfSDavid du Colombier 					oldest = b;
3097dd7cddfSDavid du Colombier 					oldesttime = b->lasttouched;
3107dd7cddfSDavid du Colombier 				}
3117dd7cddfSDavid du Colombier 			}
3127dd7cddfSDavid du Colombier 		}
3137dd7cddfSDavid du Colombier 		if(oldest == nil)
3147dd7cddfSDavid du Colombier 			break;
3157dd7cddfSDavid du Colombier 
3167dd7cddfSDavid du Colombier 		/* make sure noone is still using it */
31759cc4ca5SDavid du Colombier 		oldest->tried = now;
3187dd7cddfSDavid du Colombier 		if(ping == 0 || icmpecho(oldest->ip) == 0)
3197dd7cddfSDavid du Colombier 			return oldest;
32080ee5cbfSDavid du Colombier 
32159cc4ca5SDavid du Colombier 		lognolease(oldest);	/* sets lastcomplained */
3227dd7cddfSDavid du Colombier 	}
3237dd7cddfSDavid du Colombier 
3247dd7cddfSDavid du Colombier 	/* try all bindings */
3257dd7cddfSDavid du Colombier 	for(b = bcache; b; b = b->next){
3267dd7cddfSDavid du Colombier 		syncbinding(b, 0);
32759cc4ca5SDavid du Colombier 		if(b->tried != now)
3287dd7cddfSDavid du Colombier 		if(b->lease < now && b->expoffer < now && samenet(b->ip, iip)){
32959cc4ca5SDavid du Colombier 			b->tried = now;
3309a747e4fSDavid du Colombier 			if(ping == 0 || icmpecho(b->ip) == 0)
3317dd7cddfSDavid du Colombier 				return b;
33280ee5cbfSDavid du Colombier 
3337dd7cddfSDavid du Colombier 			lognolease(b);
3347dd7cddfSDavid du Colombier 		}
3357dd7cddfSDavid du Colombier 	}
3367dd7cddfSDavid du Colombier 
3377dd7cddfSDavid du Colombier 	/* nothing worked, give up */
3387dd7cddfSDavid du Colombier 	return 0;
3397dd7cddfSDavid du Colombier }
3407dd7cddfSDavid du Colombier 
3417dd7cddfSDavid du Colombier /*
3427dd7cddfSDavid du Colombier  *  create an offer
3437dd7cddfSDavid du Colombier  */
3447dd7cddfSDavid du Colombier extern void
mkoffer(Binding * b,char * id,long leasetime)3457dd7cddfSDavid du Colombier mkoffer(Binding *b, char *id, long leasetime)
3467dd7cddfSDavid du Colombier {
34780ee5cbfSDavid du Colombier 	if(leasetime <= 0){
3487dd7cddfSDavid du Colombier 		if(b->lease > now + minlease)
3497dd7cddfSDavid du Colombier 			leasetime = b->lease - now;
3507dd7cddfSDavid du Colombier 		else
3517dd7cddfSDavid du Colombier 			leasetime = minlease;
3527dd7cddfSDavid du Colombier 	}
3537dd7cddfSDavid du Colombier 	if(b->offeredto)
3547dd7cddfSDavid du Colombier 		free(b->offeredto);
3557dd7cddfSDavid du Colombier 	b->offeredto = strdup(id);
3567dd7cddfSDavid du Colombier 	b->offer = leasetime;
3577dd7cddfSDavid du Colombier 	b->expoffer = now + OfferTimeout;
3587dd7cddfSDavid du Colombier }
3597dd7cddfSDavid du Colombier 
3607dd7cddfSDavid du Colombier /*
3617dd7cddfSDavid du Colombier  *  find an offer for this id
3627dd7cddfSDavid du Colombier  */
3637dd7cddfSDavid du Colombier extern Binding*
idtooffer(char * id,Info * iip)3647dd7cddfSDavid du Colombier idtooffer(char *id, Info *iip)
3657dd7cddfSDavid du Colombier {
3667dd7cddfSDavid du Colombier 	Binding *b;
3677dd7cddfSDavid du Colombier 
3687dd7cddfSDavid du Colombier 	/* look for an offer to this id */
3697dd7cddfSDavid du Colombier 	for(b = bcache; b; b = b->next){
3707dd7cddfSDavid du Colombier 		if(b->offeredto && strcmp(b->offeredto, id) == 0 && samenet(b->ip, iip)){
3717dd7cddfSDavid du Colombier 			/* make sure some other system hasn't stolen it */
3727dd7cddfSDavid du Colombier 			syncbinding(b, 0);
3737dd7cddfSDavid du Colombier 			if(b->lease < now
3747dd7cddfSDavid du Colombier 			|| (b->boundto && strcmp(b->boundto, b->offeredto) == 0))
3757dd7cddfSDavid du Colombier 				return b;
3767dd7cddfSDavid du Colombier 		}
3777dd7cddfSDavid du Colombier 	}
3787dd7cddfSDavid du Colombier 	return 0;
3797dd7cddfSDavid du Colombier }
3807dd7cddfSDavid du Colombier 
3817dd7cddfSDavid du Colombier /*
3827dd7cddfSDavid du Colombier  *  commit a lease, this could fail
3837dd7cddfSDavid du Colombier  */
3847dd7cddfSDavid du Colombier extern int
commitbinding(Binding * b)3857dd7cddfSDavid du Colombier commitbinding(Binding *b)
3867dd7cddfSDavid du Colombier {
3877dd7cddfSDavid du Colombier 	int fd;
3887dd7cddfSDavid du Colombier 	long now;
3897dd7cddfSDavid du Colombier 
3907dd7cddfSDavid du Colombier 	now = time(0);
3917dd7cddfSDavid du Colombier 
3927dd7cddfSDavid du Colombier 	if(b->offeredto == 0)
3937dd7cddfSDavid du Colombier 		return -1;
3947dd7cddfSDavid du Colombier 	fd = syncbinding(b, 1);
3957dd7cddfSDavid du Colombier 	if(fd < 0)
3967dd7cddfSDavid du Colombier 		return -1;
3977dd7cddfSDavid du Colombier 	if(b->lease > now && b->boundto && strcmp(b->boundto, b->offeredto) != 0){
3987dd7cddfSDavid du Colombier 		close(fd);
3997dd7cddfSDavid du Colombier 		return -1;
4007dd7cddfSDavid du Colombier 	}
4017dd7cddfSDavid du Colombier 	setbinding(b, b->offeredto, now + b->offer);
4027dd7cddfSDavid du Colombier 	b->lasttouched = now;
4037dd7cddfSDavid du Colombier 
4047dd7cddfSDavid du Colombier 	if(writebinding(fd, b) < 0){
4057dd7cddfSDavid du Colombier 		close(fd);
4067dd7cddfSDavid du Colombier 		return -1;
4077dd7cddfSDavid du Colombier 	}
4087dd7cddfSDavid du Colombier 	close(fd);
4097dd7cddfSDavid du Colombier 	return 0;
4107dd7cddfSDavid du Colombier }
4117dd7cddfSDavid du Colombier 
4127dd7cddfSDavid du Colombier /*
4137dd7cddfSDavid du Colombier  *  commit a lease, this could fail
4147dd7cddfSDavid du Colombier  */
4157dd7cddfSDavid du Colombier extern int
releasebinding(Binding * b,char * id)4167dd7cddfSDavid du Colombier releasebinding(Binding *b, char *id)
4177dd7cddfSDavid du Colombier {
4187dd7cddfSDavid du Colombier 	int fd;
4197dd7cddfSDavid du Colombier 	long now;
4207dd7cddfSDavid du Colombier 
4217dd7cddfSDavid du Colombier 	now = time(0);
4227dd7cddfSDavid du Colombier 
4237dd7cddfSDavid du Colombier 	fd = syncbinding(b, 1);
4247dd7cddfSDavid du Colombier 	if(fd < 0)
4257dd7cddfSDavid du Colombier 		return -1;
4267dd7cddfSDavid du Colombier 	if(b->lease > now && b->boundto && strcmp(b->boundto, id) != 0){
4277dd7cddfSDavid du Colombier 		close(fd);
4287dd7cddfSDavid du Colombier 		return -1;
4297dd7cddfSDavid du Colombier 	}
4307dd7cddfSDavid du Colombier 	b->lease = 0;
4317dd7cddfSDavid du Colombier 	b->expoffer = 0;
4327dd7cddfSDavid du Colombier 
4337dd7cddfSDavid du Colombier 	if(writebinding(fd, b) < 0){
4347dd7cddfSDavid du Colombier 		close(fd);
4357dd7cddfSDavid du Colombier 		return -1;
4367dd7cddfSDavid du Colombier 	}
4377dd7cddfSDavid du Colombier 	close(fd);
4387dd7cddfSDavid du Colombier 	return 0;
4397dd7cddfSDavid du Colombier }
440