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