]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/ip/tinc.c
94a5e0ec687e950d4592be97050b7a12de6a4be5
[plan9front.git] / sys / src / cmd / ip / tinc.c
1 #include <u.h>
2 #include <libc.h>
3 #include <mp.h>
4 #include <libsec.h>
5 #include <auth.h>
6 #include <ip.h>
7
8 enum {
9         OptIndirect     = 1,
10         OptTcpOnly      = 3,
11         OptPmtuDiscov   = 4,
12         OptClampMss     = 8,
13
14         MaxWeight       = 0x7fffffff,
15         AESkeylen       = 256/8,
16         MAClen          = 4,
17
18         Eaddrlen        = 6,
19         EtherType       = 2*Eaddrlen,
20         EtherHdr        = EtherType+2,
21
22         Ip4Hdr          = 20,
23         Ip6Hdr          = 40,
24         UdpHdr          = 8,
25         TcpHdr          = 20,
26
27         /* worst case: UDPv6 over 6in4 over PPPoE */
28         DefPMTU         = 1500-8-Ip4Hdr-Ip6Hdr-UdpHdr-4-AESbsize-MAClen,
29
30         MaxPacket       = 4096,
31
32         /* messages */
33         ID              = 0,
34         META_KEY        = 1,
35         CHALLENGE       = 2,
36         CHAL_REPLY      = 3,
37         ACK             = 4,
38         PING            = 8,
39         PONG            = 9,
40         ADD_SUBNET      = 10,
41         DEL_SUBNET      = 11,
42         ADD_EDGE        = 12,
43         DEL_EDGE        = 13,
44         KEY_CHANGED     = 14,
45         REQ_KEY         = 15,
46         ANS_KEY         = 16,
47         TCP_PACKET      = 17,
48
49         /* openssl crap */
50         EVP_AES256CBC   = 427,
51         EVP_AES256CFB   = 429,
52         EVP_SHA256      = 672,
53 };
54
55 typedef struct Snet Snet;
56 typedef struct Edge Edge;
57 typedef struct Ciph Ciph;
58 typedef struct Host Host;
59 typedef struct Conn Conn;
60
61 struct Snet
62 {
63         Host    *owner;
64
65         Snet    *next;  /* next subnet on owner */
66         uchar   ip[IPaddrlen];
67         uchar   mask[IPaddrlen];
68         int     prefixlen;
69         int     weight;
70         char    reported;
71         char    deleted;
72 };
73
74 struct Edge
75 {
76         Host    *src;
77         Host    *dst;
78         Edge    *next;  /* next edge on src */
79         Edge    *rev;   /* reverse drection edge */
80
81         uchar   ip[IPaddrlen];
82         int     port;
83
84         int     options;
85         int     weight;
86         char    reported;
87         char    deleted;
88 };
89
90 struct Ciph
91 {
92         void    (*crypt)(uchar*, int, AESstate*);
93         uint    seq;
94         uchar   key[AESkeylen+AESbsize];
95         AESstate cs[1];
96         Lock;
97 };
98
99 struct Host
100 {
101         Host    *next;
102         char    *name;
103         char    *addr;
104
105         Conn    *conn;
106         Host    *from;
107         Edge    *link;
108
109         Snet    *snet;
110
111         uchar   ip[IPaddrlen];
112         int     port;
113
114         int     connected;
115         int     options;
116         int     pmtu;
117         int     udpfd;
118
119         uvlong  ooo;    /* out of order replay window */
120         Ciph    cin[1];
121         Ciph    cout[1];
122
123         RSApub  *rsapub;
124 };
125
126 struct Conn
127 {
128         Host    *host;
129         Edge    *edge;
130
131         int     fd;
132         int     port;
133         uchar   ip[IPaddrlen];
134
135         vlong   pingtime;
136
137         QLock   sendlk;
138
139         Ciph    cin[1];
140         Ciph    cout[1];
141
142         char    *rp;
143         char    *wp;
144         char    buf[MaxPacket+16];
145 };
146
147 QLock   hostslk;
148 Host    *hosts;
149
150 Edge    **edges;
151 int     nedges;
152 Snet    **snet;
153 int     nsnet;
154
155 int     debug;
156 int     maxprocs = 100;
157
158 char    *myname = nil;
159 Host    *myhost = nil;
160
161 Conn    *bcast = (void*)-1;
162 Conn    *lconn = nil;
163 RWLock  netlk;
164
165 char    *outside = "/net";
166 char    *inside = "/net";
167 char    device[128];
168 int     ipcfd = -1;
169 int     ipdfd = -1;
170 uchar   localip[IPaddrlen];
171 uchar   localmask[IPaddrlen];
172 int     rcfd = -1;
173
174 void    deledge(Edge*);
175 void    delsubnet(Snet*);
176 void    netrecalc(void);
177
178 int     consend(Conn *c, char *fmt, ...);
179 #pragma varargck argpos consend 2
180 int     sendudp(Host *h, int fd, uchar *p, int n);
181 void    routepkt(Host *s, uchar *p, int n);
182 void    needkey(Host *from);
183 void    clearkey(Host *from);
184
185 void*
186 emalloc(ulong len)
187 {
188         void *v = malloc(len);
189         if(v == nil)
190                 sysfatal("malloc: %r");
191         setmalloctag(v, getcallerpc(&len));
192         memset(v, 0, len);
193         return v;
194 }
195 void*
196 erealloc(void *v, ulong len)
197 {
198         if((v = realloc(v, len)) == nil && len != 0)
199                 sysfatal("realloc: %r");
200         setrealloctag(v, getcallerpc(&v));
201         return v;
202 }
203 char*
204 estrdup(char *s)
205 {
206         if((s = strdup(s)) == nil)
207                 sysfatal("strdup: %r");
208         setmalloctag(s, getcallerpc(&s));
209         return s;
210 }
211
212 char*
213 fd2dir(int fd, char *dir, int len)
214 {
215         char *p;
216
217         *dir = 0;
218         if(fd2path(fd, dir, len) < 0)
219                 return nil;
220         p = strrchr(dir, '/');
221         if(p == nil || p == dir)
222                 return nil;
223         *p = 0;
224         return dir;
225 }
226
227 int
228 dir2ipport(char *dir, uchar ip[IPaddrlen])
229 {
230         NetConnInfo *nci;
231         int port = -1;
232
233         if((nci = getnetconninfo(dir, -1)) == nil)
234                 return -1;
235         if(parseip(ip, nci->rsys) != -1)
236                 port = atoi(nci->rserv);
237         freenetconninfo(nci);
238         return port;
239 }
240
241 void
242 hangupfd(int fd)
243 {
244         char buf[128];
245
246         if(fd < 0 || fd2dir(fd, buf, sizeof(buf)-5) == nil)
247                 return;
248         strcat(buf, "/ctl");
249         if((fd = open(buf, OWRITE)) >= 0){
250                 hangup(fd);
251                 close(fd);
252         }
253 }
254
255 void
256 netlock(Conn *c)
257 {
258         if(c != nil) {
259                 wlock(&netlk);
260                 assert(lconn == nil);
261                 lconn = c;
262         } else {
263                 rlock(&netlk);
264                 assert(lconn == nil);
265         }
266 }
267 void
268 netunlock(Conn *c)
269 {
270         if(c != nil){
271                 assert(c == lconn);
272                 netrecalc();
273                 lconn = nil;
274                 wunlock(&netlk);
275         }else {
276                 assert(lconn == nil);
277                 runlock(&netlk);
278         }
279 }
280
281 int
282 edgecmp(Edge *a, Edge *b)
283 {
284         int c;
285
286         if((c = a->deleted - b->deleted) != 0)
287                 return c;
288         return a->weight - b->weight;
289 }
290 int
291 edgepcmp(void *a, void *b)
292 {
293         return edgecmp(*(Edge**)a, *(Edge**)b);
294 }
295
296 int
297 subnetcmp(Snet *a, Snet *b)
298 {
299         int c;
300
301         if((c = a->deleted - b->deleted) != 0)
302                 return c;
303         if((c = ipcmp(b->mask, a->mask)) != 0)
304                 return c;
305         if((c = ipcmp(a->ip, b->ip)) != 0)
306                 return c;
307         return a->weight - b->weight;
308 }
309 int
310 subnetpcmp(void *a, void *b)
311 {
312         return subnetcmp(*(Snet**)a, *(Snet**)b);
313 }
314
315 Snet*
316 lookupnet(uchar ip[IPaddrlen])
317 {
318         int i;
319         Snet *t;
320         uchar x[IPaddrlen];
321
322         for(i=0; i<nsnet; i++){
323                 t = snet[i];
324                 maskip(ip, t->mask, x);
325                 if(ipcmp(x, t->ip) == 0)
326                         return t;
327         }
328         return nil;
329 }
330
331 void
332 reportsubnet(Conn *c, Snet *t)
333 {
334         if(c == nil || !(t->deleted || t->owner->connected))
335                 return;
336         if(c == bcast){
337                 Edge *x;
338
339                 if(t->deleted != t->reported)
340                         return;
341                 t->reported = !t->deleted;
342                 for(x = myhost->link; x != nil; x = x->next)
343                         if(x->dst->conn != lconn && x->dst->from == myhost)
344                                 reportsubnet(x->dst->conn, t);
345                 return;
346         }
347         if(t->owner == c->host)
348                 return;
349         if(t->deleted)
350                 consend(c, "%d %x %s %I/%d#%d", DEL_SUBNET, rand(),
351                         t->owner->name, t->ip, t->prefixlen, t->weight);
352         else
353                 consend(c, "%d %x %s %I/%d#%d", ADD_SUBNET, rand(), t->owner->name,
354                         t->ip, t->prefixlen, t->weight);
355 }
356 void
357 reportedge(Conn *c, Edge *e)
358 {
359         if(c == nil || !(e->deleted || e->src->connected && e->dst->connected))
360                 return;
361         if(c == bcast){
362                 Edge *x;
363
364                 if(e->deleted != e->reported)
365                         return;
366                 e->reported = !e->deleted;
367                 for(x = myhost->link; x != nil; x = x->next)
368                         if(x->dst->conn != lconn && x->dst->from == myhost)
369                                 reportedge(x->dst->conn, e);
370                 return;
371         }
372         if(e->src == c->host)
373                 return;
374         if(e->deleted){
375                 if(e->dst == c->host)
376                         return;
377                 consend(c, "%d %x %s %s", DEL_EDGE, rand(),
378                         e->src->name, e->dst->name);
379         } else
380                 consend(c, "%d %x %s %s %I %d %x %d", ADD_EDGE, rand(),
381                         e->src->name, e->dst->name,
382                         e->ip, e->port, e->options, e->weight);
383 }
384
385 void
386 netrecalc(void)
387 {
388         static int hostup = 0;
389         Host *h;
390         Edge *e;
391         Snet *t;
392         int i;
393
394         if(myhost == nil)
395                 return;
396
397         qsort(edges, nedges, sizeof(edges[0]), edgepcmp);
398         while(nedges > 0 && edges[nedges-1]->deleted){
399                 reportedge(bcast, edges[--nedges]);
400                 free(edges[nedges]);
401                 edges[nedges] = nil;
402         }
403         for(h = hosts; h != nil; h = h->next) h->from = nil;
404
405         myhost->from = myhost;
406         myhost->connected = 1;
407
408 Loop:
409         for(i=0; i<nedges; i++){
410                 e = edges[i];
411                 if(e->src->from == nil || (h = e->dst)->from != nil)
412                         continue;
413                 memmove(h->ip, e->ip, IPaddrlen);
414                 h->port = e->port;
415                 h->options = e->options;
416                 h->from = e->src;
417                 if(h->connected == 0){
418                         h->connected = 1;
419                         for(t = h->snet; t != nil; t = t->next)
420                                 t->reported = 0;
421                         e->reported = 0;
422
423                         fprint(rcfd, "NAME=%s NODE=%s DEVICE=%s INTERFACE=%I"
424                                 " REMOTENET=%s REMOTEADDRESS=%I REMOTEPORT=%d"
425                                 " ./hosts/%s-up\n",
426                                 myname, h->name, device, localip,
427                                 outside, h->ip, h->port,
428                                 h->name);
429                 }
430                 goto Loop;
431         }
432
433         for(h = hosts; h != nil; h = h->next){
434                 if(h->from == nil && h->connected){
435                         h->connected = 0;
436                         clearkey(h);
437
438                         fprint(rcfd, "NAME=%s NODE=%s DEVICE=%s INTERFACE=%I"
439                                 " REMOTENET=%s REMOTEADDRESS=%I REMOTEPORT=%d"
440                                 " ./hosts/%s-down\n",
441                                 myname, h->name, device, localip,
442                                 outside, h->ip, h->port,
443                                 h->name);
444
445                         while(h->link != nil) {
446                                 deledge(h->link->rev);
447                                 deledge(h->link);
448                         }
449                         while(h->snet != nil) delsubnet(h->snet);
450                 }
451         }
452
453         i = myhost->link != nil;
454         if(i != hostup){
455                 hostup = i;
456
457                 fprint(rcfd, "NAME=%s NODE=%s DEVICE=%s INTERFACE=%I"
458                         " REMOTENET=%s REMOTEADDRESS=%I REMOTEPORT=%d"
459                         " ./host-%s\n",
460                         myname, myhost->name, device, localip,
461                         outside, myhost->ip, myhost->port,
462                         hostup ? "up" : "down");
463         }
464
465
466         qsort(snet, nsnet, sizeof(snet[0]), subnetpcmp);
467         for(i = nsnet-1; i >= 0; i--){
468                 t = snet[i];
469
470                 if(t->owner != myhost && (t->deleted || t->reported == 0))
471                         fprint(rcfd, "NAME=%s NODE=%s DEVICE=%s INTERFACE=%I"
472                                 " REMOTENET=%s REMOTEADDRESS=%I REMOTEPORT=%d"
473                                 " SUBNET=(%I %M) WEIGHT=%d"
474                                 " ./subnet-%s\n",
475                                 myname, t->owner->name, device, localip,
476                                 outside, t->owner->ip, t->owner->port,
477                                 t->ip, t->mask, t->weight,
478                                 t->deleted ? "down" : "up");
479
480                 reportsubnet(bcast, t);
481                 if(t->deleted){
482                         assert(i == nsnet-1);
483                         snet[i] = nil;
484                         nsnet = i;
485                         free(t);
486                 }
487         }
488
489         qsort(edges, nedges, sizeof(edges[0]), edgepcmp);
490         for(i = nedges-1; i >= 0; i--){
491                 reportedge(bcast, edges[i]);
492                 if(edges[i]->deleted){
493                         assert(i == nedges-1);
494                         nedges = i;
495                         free(edges[i]);
496                         edges[i] = nil;
497                 }
498         }
499 }
500
501 Snet*
502 getsubnet(Host *h, char *s, int new)
503 {
504         uchar ip[IPaddrlen], mask[IPaddrlen];
505         int weight, prefixlen;
506         Snet *t;
507
508         if(parseipandmask(ip, mask, s, strchr(s, '/')) == -1)
509                 return nil;
510
511         for(prefixlen = 0; prefixlen < 128; prefixlen++)
512                 if((mask[prefixlen/8] & (0x80 >> (prefixlen%8))) == 0)
513                         break;
514         if(isv4(ip))
515                 prefixlen -= 96;
516
517         maskip(ip, mask, ip);
518
519         weight = 10;
520         if((s = strchr(s, '#')) != nil)
521                 weight = atoi(s+1);
522
523         for(t = h->snet; t != nil; t = t->next)
524                 if(ipcmp(t->ip, ip) == 0 && ipcmp(t->mask, mask) == 0){
525                         if(new)
526                                 t->weight = weight;
527                         return t;
528                 }
529
530         if(!new)
531                 return nil;
532
533         t = emalloc(sizeof(Snet));
534         ipmove(t->ip, ip);
535         ipmove(t->mask, mask);
536         t->prefixlen = prefixlen;
537         t->weight = weight;
538         t->owner = h;
539         t->next = h->snet;
540         h->snet = t;
541         if((nsnet % 16) == 0)
542                 snet = erealloc(snet, sizeof(snet[0])*(nsnet+16));
543         snet[nsnet++] = t;
544         return t;
545 }
546
547 void
548 delsubnet(Snet *t)
549 {
550         Snet **tp;
551
552         if(t == nil || t->deleted)
553                 return;
554         for(tp = &t->owner->snet; *tp != nil; tp = &(*tp)->next){
555                 if(*tp == t){
556                         *tp = t->next;
557                         break;
558                 }
559         }
560         t->next = nil;
561         t->deleted = 1;
562 }
563
564 Edge*
565 getedge(Host *src, Host *dst, int new)
566 {
567         Edge *e;
568
569         for(e = src->link; e != nil; e = e->next)
570                 if(e->dst == dst)
571                         return e;
572         if(!new)
573                 return nil;
574         e = emalloc(sizeof(Edge));
575         e->weight = MaxWeight;
576         e->src = src;
577         e->dst = dst;
578         e->next = src->link;
579         src->link = e;
580         if((e->rev = getedge(dst, src, 0)) != nil)
581                 e->rev->rev = e;
582         if((nedges % 16) == 0)
583                 edges = erealloc(edges, sizeof(edges[0])*(nedges+16));
584         edges[nedges++] = e;
585         return e;
586 }
587
588 void
589 deledge(Edge *e)
590 {
591         Edge **ep;
592
593         if(e == nil || e->deleted)
594                 return;
595         if(e->rev != nil){
596                 if(e->rev->rev != nil){
597                         assert(e->rev->rev == e);
598                         e->rev->rev = nil;
599                 }
600                 e->rev = nil;
601         }
602         for(ep = &e->src->link; *ep != nil; ep = &((*ep)->next))
603                 if(*ep == e){
604                         *ep = e->next;
605                         break;
606                 }
607         e->next = nil;
608         e->options = 0;
609         e->weight = MaxWeight;
610         e->port = 0;
611         memset(e->ip, 0, IPaddrlen);
612         e->deleted = 1;
613 }
614
615 Host*
616 gethost(char *name, int new)
617 {
618         char buf[8*1024], *s, *e, *x;
619         Host *h;
620         int fd, n;
621
622         if(*name == 0 || *name == '.' || strchr(name, '/') != nil)
623                 return nil;
624         qlock(&hostslk);
625         for(h = hosts; h != nil; h = h->next)
626                 if(strcmp(h->name, name) == 0)
627                         goto out;
628
629         n = -1;
630         snprint(buf, sizeof(buf), "hosts/%s", name);
631         if((fd = open(buf, OREAD)) >= 0){
632                 n = read(fd, buf, sizeof(buf)-1);
633                 close(fd);
634         }
635         if(n < 0){
636                 if(!new)
637                         goto out;
638                 n = 0;
639         }
640         buf[n] = 0;
641
642         h = emalloc(sizeof(Host));
643         h->name = estrdup(name);
644         h->addr = estrdup(name);
645         h->port = 655;
646         h->pmtu = DefPMTU;
647         h->options = OptClampMss|OptPmtuDiscov;
648         h->udpfd = -1;
649         h->connected = 0;
650         h->rsapub = nil;
651         h->next = hosts;
652         hosts = h;
653         if((s = (char*)decodePEM(buf, "RSA PUBLIC KEY", &n, nil)) != nil){
654                 h->rsapub = asn1toRSApub((uchar*)s, n);
655                 free(s);
656         }
657         for(s = buf; s != nil; s = e){
658                 char *f[2];
659
660                 if((e = strchr(s, '\n')) != nil)
661                         *e++ = 0;
662                 if(*s == '#' || (x = strchr(s, '=')) == nil)
663                         continue;
664                 *x = ' ';
665                 if((n = tokenize(s, f, 2)) != 2)
666                         continue;
667                 if(cistrcmp(f[0], "Address") == 0){
668                         if(tokenize(f[1], f, 2) > 1)
669                                 h->port = atoi(f[1]);
670                         free(h->addr);
671                         h->addr = estrdup(f[0]);
672                         continue;
673                 }
674                 if(cistrcmp(f[0], "IndirectData") == 0){
675                         h->options |= OptIndirect*(cistrcmp(f[1], "yes") == 0);
676                         continue;
677                 }
678                 if(cistrcmp(f[0], "TCPonly") == 0){
679                         h->options |= OptTcpOnly*(cistrcmp(f[1], "yes") == 0);
680                         continue;
681                 }
682                 if(cistrcmp(f[0], "ClampMSS") == 0){
683                         h->options &= ~(OptClampMss*(cistrcmp(f[1], "no") == 0));
684                         continue;
685                 }
686                 if(cistrcmp(f[0], "PMTUDiscovery") == 0){
687                         h->options &= ~(OptPmtuDiscov*(cistrcmp(f[1], "no") == 0));
688                         continue;
689                 }
690                 if(cistrcmp(f[0], "PMTU") == 0){
691                         h->pmtu = atoi(f[1]);
692                         if(h->pmtu > MaxPacket)
693                                 h->pmtu = MaxPacket;
694                         else if(h->pmtu < 512)
695                                 h->pmtu = 512;
696                         continue;
697                 }
698                 if(cistrcmp(f[0], "Port") == 0){
699                         h->port = atoi(f[1]);
700                         continue;
701                 }
702                 if(cistrcmp(f[0], "Subnet") == 0){
703                         if(myhost == nil)
704                                 getsubnet(h, f[1], 1);
705                         continue;
706                 }
707         }
708         parseip(h->ip, h->addr);
709 out:
710         qunlock(&hostslk);
711         return h;
712 }
713
714 Host*
715 findhost(uchar ip[IPaddrlen], int port)
716 {
717         Host *h;
718
719         qlock(&hostslk);
720         for(h = hosts; h != nil; h = h->next){
721                 if(ipcmp(ip, h->ip) == 0 && (port == -1 || port == h->port))
722                         break;
723         }
724         qunlock(&hostslk);
725         return h;
726 }
727
728 AuthRpc*
729 getrsarpc(void)
730 {
731         AuthRpc *rpc;
732         int afd, r;
733         char *s;
734         mpint *m;
735
736         if(myhost->rsapub == nil){
737                 werrstr("no RSA public key");
738                 return nil;
739         }
740         if((afd = open("/mnt/factotum/rpc", ORDWR)) < 0)
741                 return nil;
742         if((rpc = auth_allocrpc(afd)) == nil){
743                 close(afd);
744                 return nil;
745         }
746         m = mpnew(0);
747         s = smprint("proto=rsa service=tinc role=client host=%q", myhost->name);
748         r = auth_rpc(rpc, "start", s, strlen(s));
749         free(s);
750         if(r != ARok){
751                 goto Err;
752         }
753         werrstr("no key found");
754         while(auth_rpc(rpc, "read", nil, 0) == ARok){
755                 s = rpc->arg;
756                 if(strtomp(s, &s, 16, m) == nil)
757                         continue;
758                 if(mpcmp(m, myhost->rsapub->n) != 0)
759                         continue;
760                 mpfree(m);
761                 return rpc;
762         }
763 Err:
764         mpfree(m);
765         auth_freerpc(rpc);
766         close(afd);
767         return nil;
768 }
769 void
770 putrsarpc(AuthRpc *rpc)
771 {
772         if(rpc == nil)
773                 return;
774         close(rpc->afd);
775         auth_freerpc(rpc);
776 }
777
778
779 int
780 conread(Conn *c)
781 {
782         int n;
783
784         if(c->rp > c->buf){
785                 memmove(c->buf, c->rp, c->wp - c->rp);
786                 c->wp -= (c->rp - c->buf);
787                 c->rp = c->buf;
788         }
789         if((n = read(c->fd, c->wp, &c->buf[sizeof(c->buf)] - c->wp)) <= 0)
790                 return n;
791         if(c->cin->crypt != nil)
792                 (*c->cin->crypt)((uchar*)c->wp, n, c->cin->cs);
793         c->wp += n;
794         return n;
795 }
796 int
797 conwrite(Conn *c, char *s, int n)
798 {
799         if(c->cout->crypt != nil)
800                 (*c->cout->crypt)((uchar*)s, n, c->cout->cs);
801         if(write(c->fd, s, n) != n)
802                 return -1;
803         return 0;
804 }
805
806 int
807 conrecv(Conn *c, char **f, int nf)
808 {
809         char *s, *e;
810
811         do {
812                 if(c->wp > c->rp && (e = memchr(s = c->rp, '\n', c->wp - c->rp)) != nil){
813                         *e++ = 0;
814                         c->rp = e;
815 if(debug) fprint(2, "<-%s %s\n", c->host != nil ? c->host->name : "???", s);
816                         return tokenize(s, f, nf);
817                 }
818         } while(conread(c) > 0);
819         return 0;
820 }
821 int
822 consend(Conn *c, char *fmt, ...)
823 {
824         char buf[1024];
825         va_list a;
826         int n;
827
828         if(c == nil)
829                 return -1;
830
831         va_start(a, fmt);
832         n = vsnprint(buf, sizeof(buf)-2, fmt, a);
833         va_end(a);
834
835         buf[n++] = '\n';
836         buf[n] = 0;
837
838         qlock(&c->sendlk);
839 if(debug) fprint(2, "->%s %s", c->host != nil ? c->host->name : "???", buf);
840         n = conwrite(c, buf, n);
841         qunlock(&c->sendlk);
842
843         return n;
844 }
845
846 int
847 recvudp(Host *h, int fd)
848 {
849         uchar buf[4+MaxPacket+AESbsize+MAClen], mac[SHA2_256dlen];
850         AESstate cs[1];
851         uint seq;
852         int n, o;
853
854         if((n = read(fd, buf, sizeof(buf))) <= 0)
855                 return -1;
856         lock(h->cin);
857         if(h->cin->crypt == nil || (n -= MAClen) < AESbsize){
858                 unlock(h->cin);
859                 return -1;
860         }
861         hmac_sha2_256(buf, n, h->cin->key, sizeof(h->cin->key), mac, nil);
862         if(tsmemcmp(mac, buf+n, MAClen) != 0){
863                 unlock(h->cin);
864                 return -1;
865         }
866         memmove(cs, h->cin->cs, sizeof(cs));
867         (*h->cin->crypt)(buf, n, cs);
868         if((n -= buf[n-1]) < 4){
869                 unlock(h->cin);
870                 return -1;
871         }
872
873         seq  = buf[0]<<24;
874         seq |= buf[1]<<16;
875         seq |= buf[2]<<8;
876         seq |= buf[3]<<0;
877
878         if((o = (int)(seq - h->cin->seq)) > 0){
879                 h->cin->seq = seq;
880                 h->ooo = o < 64 ? h->ooo<<o | 1ULL : 0ULL;
881         } else {
882                 o = -o;
883                 if(o >= 64 || (h->ooo & 1ULL<<o) != 0){
884                         unlock(h->cin);
885                         return 0;
886                 }
887                 h->ooo |= 1ULL<<o;
888         }
889         h->udpfd = fd;
890         unlock(h->cin);
891
892         /* pmtu probe */
893         if(n >= 4+14 && buf[4+12] == 0 && buf[4+13] == 0){
894                 if(buf[4+0] == 0){
895                         buf[4+0] = 1;
896                         sendudp(h, fd, buf+4, n-4);
897                 }
898                 return 0;
899         }
900
901         routepkt(h, buf+4, n-4);
902         return 0;
903 }
904 int
905 sendudp(Host *h, int fd, uchar *p, int n)
906 {
907         uchar buf[4+MaxPacket+AESbsize+SHA2_256dlen];
908         AESstate cs[1];
909         uint seq;
910         int pad;
911
912         if(fd < 0 || n > MaxPacket)
913                 return -1;
914         lock(h->cout);
915         if(h->cout->crypt == nil){
916                 unlock(h->cout);
917                 needkey(h);
918                 return -1;
919         }
920
921         seq = ++h->cout->seq;
922         buf[0] = seq>>24;
923         buf[1] = seq>>16;
924         buf[2] = seq>>8;
925         buf[3] = seq>>0;
926
927         memmove(buf+4, p, n), n += 4;
928         pad = AESbsize - ((uint)n % AESbsize);
929         memset(buf+n, pad, pad), n += pad;
930         memmove(cs, h->cout->cs, sizeof(cs));
931         (*h->cout->crypt)(buf, n, cs);
932         hmac_sha2_256(buf, n, h->cout->key, sizeof(h->cout->key), buf+n, nil);
933         unlock(h->cout);
934         n += MAClen;
935         if(write(fd, buf, n) != n)
936                 return -1;
937         if((seq & 0xFFFFF) == 0) needkey(h);
938         return 0;
939 }
940
941 int
942 sendtcp(Host *h, uchar *p, int n)
943 {
944         char buf[24];
945         Conn *c;
946         int m;
947
948         if((c = h->conn) == nil)
949                 return -1;
950         m = snprint(buf, sizeof(buf), "17 %d\n", n);
951         qlock(&c->sendlk);
952         if(conwrite(c, buf, m) < 0
953         || conwrite(c, (char*)p, n) < 0)
954                 n = -1;
955         else
956                 n = 0;
957         qunlock(&c->sendlk);
958         return n;
959 }
960
961 void
962 forward(Host *s, Host *d, uchar *p, int n)
963 {
964         if(d->from == nil)
965                 return;
966         while(d != s && d != myhost){
967                 if(n <= d->pmtu && sendudp(d, d->udpfd, p, n) == 0)
968                         return;
969                 if(sendtcp(d, p, n) == 0)
970                         return;
971                 d = d->from;
972         }
973 }
974
975 int
976 updatebyte(int csum, uchar *b, uchar *p, int v)
977 {
978         int o;
979
980         o = *p;
981         v &= 255;
982         *p = v;
983         if(((p - b) & 1) == 0){
984                 o <<= 8;
985                 v <<= 8;
986         }
987         csum += o^0xFFFF;
988         csum += v;
989         while(v = csum >> 16)
990                 csum = (csum & 0xFFFF) + v;
991         return csum;
992 }
993
994 void
995 clampmss(Host *d, uchar *p, int n, int o)
996 {
997         int oldmss, newmss, csum;
998         uchar *h, *e;
999
1000         if(n <= TcpHdr || (p[13]&2) == 0 || (d->options & OptClampMss) == 0)
1001                 return;
1002         if((e = p+(p[12]>>4)*4) > p+n)
1003                 return;
1004         for(h = p+TcpHdr; h < e;){
1005                 switch(h[0]){
1006                 case 0:
1007                         return;
1008                 case 1:
1009                         h++;
1010                         continue;
1011                 }
1012                 if(h[1] < 2 || h[1] > e - h)
1013                         return;
1014                 if(h[0] == 2 && h[1] == 4)
1015                         goto Found;
1016                 h += h[1];
1017         }
1018         return;
1019 Found:
1020         oldmss = h[2]<<8 | h[3];
1021         newmss = myhost->pmtu;
1022         if(d->pmtu < newmss)
1023                 newmss = d->pmtu;
1024         newmss -= o + TcpHdr;
1025         if(oldmss <= newmss)
1026                 return;
1027 if(debug) fprint(2, "clamping tcp mss %d -> %d for %s\n", oldmss, newmss, d->name);
1028         csum = (p[16]<<8 | p[17]) ^ 0xFFFF;
1029         csum = updatebyte(csum, p, h+2, newmss>>8);
1030         csum = updatebyte(csum, p, h+3, newmss);
1031         csum ^= 0xFFFF;
1032         p[16] = csum>>8;
1033         p[17] = csum;
1034 }
1035
1036 void
1037 routepkt(Host *s, uchar *p, int n)
1038 {
1039         uchar src[IPaddrlen], dst[IPaddrlen];
1040         int o, type;
1041         Snet *t;
1042
1043 Ether:
1044         if(n <= EtherHdr)
1045                 return;
1046         switch(p[EtherType+0]<<8 | p[EtherType+1]){
1047         default:
1048                 return;
1049         case 0x8100:    /* VLAN */
1050                 memmove(p+4, p, 2*Eaddrlen);
1051                 p += 4, n -= 4;
1052                 goto Ether;
1053         case 0x0800:    /* IPv4 */
1054         case 0x86DD:    /* IPv6 */
1055                 break;
1056         }
1057         switch(p[EtherHdr] & 0xF0){
1058         default:
1059                 return;
1060         case 0x40:
1061                 o = EtherHdr+(p[EtherHdr] & 15)*4;
1062                 if(n < EtherHdr+Ip4Hdr || n < o)
1063                         return;
1064                 type = p[EtherHdr+9];
1065                 v4tov6(src, p+EtherHdr+12);
1066                 v4tov6(dst, p+EtherHdr+16);
1067                 break;
1068         case 0x60:
1069                 o = EtherHdr+Ip6Hdr;
1070                 if(n < o)
1071                         return;
1072                 type = p[EtherHdr+6];
1073                 memmove(src, p+EtherHdr+8, 16);
1074                 memmove(dst, p+EtherHdr+24, 16);
1075                 break;
1076         }
1077         netlock(nil);
1078         if((t = lookupnet(dst)) != nil){
1079                 if(type == 6)   /* TCP */
1080                         clampmss(t->owner, p+o, n-o, o);
1081                 if(t->owner == myhost)
1082                         write(ipdfd, p+EtherHdr, n-EtherHdr);
1083                 else
1084                         forward(s, t->owner, p, n);
1085         }
1086         netunlock(nil);
1087 }
1088
1089 void
1090 updateweight(Edge *e, int ms)
1091 {
1092         e->weight = (e->weight + ms) / 2;
1093         if(e->weight < 0)
1094                 e->weight = 0;
1095 }
1096
1097 int
1098 metaauth(Conn *c)
1099 {
1100         mpint *m, *h;
1101         uchar b[512];
1102         AuthRpc *rpc;
1103         char *f[8];
1104         int n, n1, n2, ms;
1105         Edge *e;
1106
1107         c->pingtime = nsec();
1108         if(consend(c, "%d %s 17", ID, myhost->name) < 0)
1109                 return -1;
1110         n = conrecv(c, f, nelem(f));
1111         if(n != 3 || atoi(f[0]) != ID || atoi(f[2]) != 17)
1112                 return -1;
1113         if((c->host = gethost(f[1], 0)) == nil
1114         || c->host == myhost || c->host->rsapub == nil)
1115                 return -1;
1116
1117         n1 = (mpsignif(c->host->rsapub->n)+7)/8;
1118         if(n1 < AESkeylen+AESbsize || n1 > sizeof(b))
1119                 return -1;
1120         n2 = (mpsignif(myhost->rsapub->n)+7)/8;
1121         if(n2 < AESkeylen+AESbsize || n2 > sizeof(b))
1122                 return -1;
1123
1124         m = mpnrand(c->host->rsapub->n, genrandom, nil);
1125         mptober(m, b, n1);
1126         setupAESstate(c->cout->cs, b+n1-AESkeylen, AESkeylen, b+n1-AESkeylen-AESbsize);
1127         rsaencrypt(c->host->rsapub, m, m);
1128         mptober(m, b, n1);
1129         mpfree(m);
1130         if(consend(c, "%d %d %d 0 0 %.*H", META_KEY, EVP_AES256CFB, EVP_SHA256, n1, b) < 0)
1131                 return -1;
1132         c->cout->crypt = aesCFBencrypt;
1133
1134         n = conrecv(c, f, nelem(f));
1135         if(n != 6 || atoi(f[0]) != META_KEY || strlen(f[5]) != 2*n2)
1136                 return -1;
1137         if(atoi(f[1]) != EVP_AES256CFB || atoi(f[2]) != EVP_SHA256){
1138                 fprint(2, "%s uses unknown cipher/digest agorithms: %s %s\n",
1139                         c->host->name, f[1], f[2]);
1140                 return -1;
1141         }
1142
1143         if((rpc = getrsarpc()) == nil
1144         || auth_rpc(rpc, "write", f[5], strlen(f[5])) != ARok
1145         || auth_rpc(rpc, "read", nil, 0) != ARok){
1146                 putrsarpc(rpc);
1147                 return -1;
1148         }
1149
1150         m = strtomp(rpc->arg, nil, 16, nil);
1151         putrsarpc(rpc);
1152         mptober(m, b, n2);
1153         mpfree(m);
1154         setupAESstate(c->cin->cs, b+n2-AESkeylen, AESkeylen, b+n2-AESkeylen-AESbsize);
1155         c->cin->crypt = aesCFBdecrypt;
1156
1157         h = mpnrand(c->host->rsapub->n, genrandom, nil);
1158         mptober(h, b, n1);
1159         if(consend(c, "%d %.*H", CHALLENGE, n1, b) < 0){
1160                 mpfree(h);
1161                 return -1;
1162         }
1163         sha2_256(b, n1, b, nil);
1164         betomp(b, SHA2_256dlen, h);
1165
1166         n = conrecv(c, f, nelem(f));
1167         if(n != 2 || atoi(f[0]) != CHALLENGE){
1168                 mpfree(h);
1169                 return -1;
1170         }
1171         m = strtomp(f[1], nil, 16, nil);
1172         mptober(m, b, n2);
1173         mpfree(m);
1174         sha2_256(b, n2, b, nil);
1175         if(consend(c, "%d %.*H", CHAL_REPLY, SHA2_256dlen, b) < 0){
1176                 mpfree(h);
1177                 return -1;
1178         }
1179         n = conrecv(c, f, nelem(f));
1180         if(n != 2 || atoi(f[0]) != CHAL_REPLY){
1181                 mpfree(h);
1182                 return -1;
1183         }
1184         m = strtomp(f[1], nil, 16, nil);
1185         n = mpcmp(m, h);
1186         mpfree(m);
1187         mpfree(h);
1188         if(n != 0)
1189                 return -1;
1190         ms = (nsec() - c->pingtime)/1000000LL;
1191         if(consend(c, "%d %d %d %x", ACK, myhost->port, ms, myhost->options) < 0)
1192                 return -1;
1193         n = conrecv(c, f, nelem(f));
1194         if(n != 4 || atoi(f[0]) != ACK)
1195                 return -1;
1196
1197         netlock(c);
1198         e = getedge(myhost, c->host, 1);
1199         memmove(e->ip, c->ip, IPaddrlen);
1200         e->port = atoi(f[1]);
1201         e->weight = atoi(f[2]);
1202         e->options = strtol(f[3], nil, 16);
1203         updateweight(e, ms);
1204         c->pingtime = 0;
1205         c->edge = e;
1206         c->host->conn = c;
1207         netunlock(c);
1208
1209         return 0;
1210 }
1211
1212 Conn*
1213 nearcon(Host *to)
1214 {
1215         while(to != nil && to != myhost){
1216                 if(to->conn != nil)
1217                         return to->conn;
1218                 to = to->from;
1219         }
1220         return nil;
1221 }
1222
1223 void
1224 sendkey(Host *to)
1225 {
1226         lock(to->cin);
1227         to->ooo = 0;
1228         to->cin->seq = 0;
1229         genrandom(to->cin->key, sizeof(to->cin->key));
1230         setupAESstate(to->cin->cs, to->cin->key, AESkeylen, to->cin->key+AESkeylen);
1231         to->cin->crypt = aesCBCdecrypt;
1232         unlock(to->cin);
1233
1234         consend(nearcon(to), "%d %s %s %.*H %d %d %d %d", ANS_KEY,
1235                 myhost->name, to->name,
1236                 sizeof(to->cin->key), to->cin->key,
1237                 EVP_AES256CBC, EVP_SHA256, MAClen, 0);
1238 }
1239 void
1240 needkey(Host *from)
1241 {
1242         consend(nearcon(from), "%d %s %s", REQ_KEY, myhost->name, from->name);
1243 }
1244 void
1245 recvkey(Host *from, char **f)
1246 {
1247         uchar key[sizeof(from->cout->key)];
1248         mpint *m;
1249
1250         if(atoi(f[1]) != EVP_AES256CBC || atoi(f[2]) != EVP_SHA256
1251         || atoi(f[3]) != MAClen || atoi(f[4]) != 0){
1252                 fprint(2, "%s key uses unknown parameters: %s %s %s %s\n",
1253                         from->name, f[1], f[2], f[3], f[4]);
1254                 return;
1255         }
1256         if(strlen(f[0]) != sizeof(key)*2)
1257                 return;
1258         if((m = strtomp(f[0], nil, 16, nil)) == nil)
1259                 return;
1260         mptober(m, key, sizeof(key));
1261         mpfree(m);
1262         lock(from->cout);
1263         if(tsmemcmp(key, from->cout->key, sizeof(key)) == 0)
1264                 goto Out;
1265         from->cout->seq = 0;
1266         memmove(from->cout->key, key, sizeof(key));
1267         setupAESstate(from->cout->cs, from->cout->key, AESkeylen, from->cout->key+AESkeylen);
1268         from->cout->crypt = aesCBCencrypt;
1269 Out:
1270         unlock(from->cout);
1271         memset(key, 0, sizeof(key));
1272 }
1273 void
1274 clearkey(Host *from)
1275 {
1276         lock(from->cout);
1277         from->cout->crypt = nil;
1278         from->cout->seq = 0;
1279         memset(from->cout->cs, 0, sizeof(from->cout->cs));
1280         genrandom(from->cout->key, sizeof(from->cout->key));
1281         unlock(from->cout);
1282 }
1283
1284 void
1285 metapeer(Conn *c)
1286 {
1287         char *f[8];
1288         Host *h, *r;
1289         Edge *e;
1290         Snet *t;
1291         int i, n;
1292
1293         netlock(nil);
1294         for(i=0; i<nsnet; i++)
1295                 reportsubnet(c, snet[i]);
1296         for(i=0; i<nedges; i++)
1297                 reportedge(c, edges[i]);
1298         netunlock(nil);
1299
1300         sendkey(c->host);
1301         while((n = conrecv(c, f, nelem(f))) > 0){
1302                 switch(atoi(f[0])){
1303                 case PING:
1304                         if(consend(c, "%d %x", PONG, rand()) < 0)
1305                                 return;
1306                         continue;
1307                 case PONG:
1308                         netlock(c);
1309                         if(c->pingtime != 0){
1310                                 if((e = getedge(myhost, c->host, 0)) != nil)
1311                                         updateweight(e, (nsec() - c->pingtime) / 1000000LL);
1312                                 c->pingtime = 0;
1313                         }
1314                         netunlock(c);
1315                         continue;
1316                 case ADD_SUBNET:
1317                         if(n != 4 || (h = gethost(f[2], 1)) == nil || h == myhost)
1318                                 break;
1319                         netlock(c);
1320                         getsubnet(h, f[3], 1);
1321                         netunlock(c);
1322                         continue;
1323                 case DEL_SUBNET:
1324                         if(n != 4 || (h = gethost(f[2], 0)) == nil || h == myhost)
1325                                 break;
1326                         netlock(c);
1327                         if((t = getsubnet(h, f[3], 0)) != nil)
1328                                 delsubnet(t);
1329                         netunlock(c);
1330                         continue;
1331                 case ADD_EDGE:
1332                         if(n != 8 || (h = gethost(f[2], 1)) == nil || h == myhost
1333                         || (r = gethost(f[3], 1)) == nil)
1334                                 break;
1335                         netlock(c);
1336                         if((e = getedge(h, r, 1)) != nil){
1337                                 if(parseip(e->ip, f[4]) == -1)
1338                                         memmove(e->ip, r->ip, IPaddrlen);
1339                                 e->port = atoi(f[5]);
1340                                 e->weight = atoi(f[7]);
1341                                 e->options = strtol(f[6], nil, 16);
1342                         }
1343                         netunlock(c);
1344                         continue;
1345                 case DEL_EDGE:
1346                         if(n != 4 || (h = gethost(f[2], 0)) == nil || h == myhost
1347                         || (r = gethost(f[3], 1)) == nil)
1348                                 break;
1349                         netlock(c);
1350                         if((e = getedge(h, r, 0)) != nil)
1351                                 deledge(e);
1352                         netunlock(c);
1353                         continue;
1354                 case KEY_CHANGED:
1355                         if(n != 3 || (h = gethost(f[2], 0)) == nil || h == myhost)
1356                                 break;
1357                         netlock(c);
1358                         clearkey(h);
1359                         for(e = myhost->link; e != nil; e = e->next)
1360                                 if(e->dst->conn != c && e->dst->from == myhost)
1361                                         consend(e->dst->conn, "%s %s %s", f[0], f[1], f[2]);
1362                         netunlock(c);
1363                         continue;
1364                 case REQ_KEY:
1365                         if(n != 3 || (h = gethost(f[1], 0)) == nil || h == myhost
1366                         || (r = gethost(f[2], 0)) == nil)
1367                                 break;
1368                         netlock(nil);
1369                         if(r != myhost)
1370                                 consend(nearcon(r), "%s %s %s", f[0], f[1], f[2]);
1371                         else
1372                                 sendkey(h);
1373                         netunlock(nil);
1374                         continue;
1375                 case ANS_KEY:
1376                         if(n != 8 || (h = gethost(f[1], 0)) == nil || h == myhost
1377                         || (r = gethost(f[2], 0)) == nil)
1378                                 break;
1379                         netlock(nil);
1380                         if(r != myhost)
1381                                 consend(nearcon(r), "%s %s %s %s %s %s %s %s",
1382                                         f[0], f[1], f[2], f[3],
1383                                         f[4], f[5], f[6], f[7]);
1384                         else
1385                                 recvkey(h, &f[3]);
1386                         netunlock(nil);
1387                         continue;
1388                 case TCP_PACKET:
1389                         if(n != 2)
1390                                 return;
1391                         n = atoi(f[1]);
1392                         if(n < 0 || n > MaxPacket)
1393                                 return;
1394                         while((c->wp - c->rp) < n && conread(c) > 0)
1395                                 ;
1396                         if(c->wp - c->rp < n)
1397                                 return;
1398                         routepkt(c->host, (uchar*)c->rp, n);
1399                         c->rp += n;
1400                         continue;
1401                 }
1402         }
1403 }
1404
1405 void
1406 tcpclient(int fd, int incoming)
1407 {
1408         Conn *c;
1409         char dir[128];
1410
1411         c = emalloc(sizeof(Conn));
1412         c->host = nil;
1413         c->fd = fd;
1414         c->rp = c->wp = c->buf;
1415         c->port = dir2ipport(fd2dir(fd, dir, sizeof(dir)), c->ip);
1416         procsetname("tcpclient %s %s %s %I!%d", myhost->name,
1417                 incoming ? "in" : "out", dir, c->ip, c->port);
1418         if(metaauth(c) == 0){
1419                 procsetname("tcpclient %s %s %s %I!%d %s", myhost->name,
1420                         incoming ? "in" : "out", dir, c->ip, c->port, c->host->name);
1421                 metapeer(c);
1422         }
1423         netlock(c);
1424         if(c->host != nil && c->host->conn == c){
1425                 c->host->conn = nil;
1426                 if(c->edge != nil && c->edge->dst == c->host){
1427                         deledge(c->edge->rev);
1428                         deledge(c->edge);
1429                 }
1430                 hangupfd(c->host->udpfd);
1431         }
1432         netunlock(c);
1433         memset(c, 0, sizeof(*c));
1434         free(c);
1435         close(fd);
1436 }
1437
1438 void
1439 udpclient(int fd, int incoming)
1440 {
1441         uchar ip[IPaddrlen];
1442         char dir[128];
1443         int port;
1444         Host *h;
1445
1446         port = dir2ipport(fd2dir(fd, dir, sizeof(dir)), ip);
1447         h = findhost(ip, port);
1448         if(h == nil && incoming)
1449                 h = findhost(ip, -1);   /* might be behind NAT */
1450         if(h != nil && h != myhost){
1451                 procsetname("udpclient %s %s %s %I!%d %s", myhost->name,
1452                         incoming ? "in": "out", dir, ip, port, h->name);
1453
1454                 if(!incoming){
1455                         lock(h->cin);
1456                         if(h->udpfd == -1)
1457                                 h->udpfd = fd;
1458                         unlock(h->cin);
1459                 }
1460
1461                 do {
1462                         alarm(15*1000);
1463                 } while(recvudp(h, fd) == 0);
1464
1465                 lock(h->cin);
1466                 if(h->udpfd == fd)
1467                         h->udpfd = -1;
1468                 unlock(h->cin);
1469
1470                 wlock(&netlk);
1471                 wunlock(&netlk);
1472         }
1473         close(fd);
1474 }
1475
1476 int
1477 dialer(char *proto, char *host, int rport, int lport)
1478 {
1479         char addr[40], local[16];
1480         int dfd;
1481
1482         snprint(local, sizeof(local), "%d", lport);
1483         snprint(addr, sizeof(addr), "%s/%s!%s!%d", outside, proto, host, rport);
1484         procsetname("dialer %s %s", myhost->name, addr);
1485
1486         for(;;){
1487                 if((dfd = dial(addr, lport ? local : nil, nil, nil)) >= 0){
1488                         switch(rfork(RFPROC|RFMEM)){
1489                         case 0:
1490                                 return dfd;
1491                         case -1:
1492                                 close(dfd);
1493                                 continue;
1494                         }
1495                         if(waitpid() < 0)
1496                                 return -1;
1497                 }
1498                 sleep(10000);
1499         }
1500 }
1501
1502 int
1503 listener(char *proto, int port, int nprocs)
1504 {
1505         char addr[40], adir[40], ldir[40];
1506         int acfd, lcfd, dfd;
1507
1508         snprint(addr, sizeof(addr), "%s/%s!*!%d", outside, proto, port);
1509         procsetname("listener %s %s", myhost->name, addr);
1510
1511         if((acfd = announce(addr, adir)) < 0)
1512                 return -1;
1513         while((lcfd = listen(adir, ldir)) >= 0){
1514                 if((dfd = accept(lcfd, ldir)) >= 0)
1515                         switch(rfork(RFPROC|RFMEM)){
1516                         default:
1517                                 if(nprocs > 1 || waitpid() < 0) nprocs--;
1518                                 break;
1519                         case 0:
1520                                 return dfd;
1521                         case -1:
1522                                 close(dfd);
1523                         }
1524                 close(lcfd);
1525         }
1526         close(acfd);
1527         return -1;
1528 }
1529
1530 void
1531 pingpong(void)
1532 {
1533         Edge *e;
1534         Conn *c;
1535
1536         procsetname("pingpong %s", myhost->name);
1537         for(;;){
1538                 sleep(15*1000 + (rand() % 3000));
1539                 netlock(nil);
1540                 for(e = myhost->link; e != nil; e = e->next){
1541                         if((c = e->dst->conn) != nil){
1542                                 if(c->pingtime != 0){
1543                                         hangupfd(c->fd);
1544                                         continue;
1545                                 }
1546                                 c->pingtime = nsec();
1547                                 consend(c, "%d %x", PING, rand());
1548                         }
1549                 }
1550                 netunlock(nil);
1551         }
1552 }
1553
1554 void
1555 ipifcsetup(void)
1556 {
1557         int n;
1558
1559         snprint(device, sizeof device, "%s/ipifc/clone", inside);
1560         if((ipcfd = open(device, ORDWR)) < 0)
1561                 sysfatal("can't open ip interface: %r");
1562         if((n = read(ipcfd, device, sizeof device - 1)) <= 0)
1563                 sysfatal("can't read interface number: %r");
1564         device[n] = 0;
1565         snprint(device, sizeof device, "%s/ipifc/%d/data", inside, atoi(device));
1566         if((ipdfd = open(device, ORDWR)) < 0)
1567                 sysfatal("can't open ip data: %r");
1568         fprint(ipcfd, "bind pkt");
1569         fprint(ipcfd, "mtu %d", myhost->pmtu-EtherHdr);
1570         fprint(ipcfd, "add %I %M", localip, localmask);
1571         *strrchr(device, '/') = 0;
1572 }
1573
1574 void
1575 ip2tunnel(void)
1576 {
1577         uchar buf[MaxPacket];
1578         int n;
1579
1580         procsetname("ip2tunnel %s %s %I %M", myhost->name,
1581                 fd2dir(ipdfd, (char*)buf, sizeof(buf)),
1582                 localip, localmask);
1583         while((n = read(ipdfd, buf+EtherHdr, sizeof buf-EtherHdr)) > 0){
1584                 memset(buf, 0, 2*Eaddrlen);
1585                 if((buf[EtherHdr]&0xF0) == 0x60){
1586                         buf[EtherType+0] = 0x86;
1587                         buf[EtherType+1] = 0xDD;
1588                 } else{
1589                         buf[EtherType+0] = 0x08;
1590                         buf[EtherType+1] = 0x00;
1591                 }
1592                 routepkt(myhost, buf, n+EtherHdr);
1593         }
1594 }
1595
1596 void
1597 catch(void*, char *msg)
1598 {
1599         if(strcmp(msg, "alarm") == 0 || strcmp(msg, "interrupt") == 0)
1600                 noted(NCONT);
1601         noted(NDFLT);
1602 }
1603 void
1604 shutdown(void)
1605 {
1606         postnote(PNGROUP, getpid(), "shutdown");
1607 }
1608
1609 void
1610 usage(void)
1611 {
1612         fprint(2, "%s [-d] [-p maxprocs] [-x inside] [-o outside] [-c confdir] [-n myname] "
1613                 "localip localmask [host...]\n", argv0);
1614         exits("usage");
1615 }
1616
1617 void
1618 main(int argc, char *argv[])
1619 {
1620         Host *h;
1621         Snet *t;
1622         AuthRpc *rpc;
1623         int i, pfd[2];
1624
1625         quotefmtinstall();
1626         fmtinstall('I', eipfmt);
1627         fmtinstall('M', eipfmt);
1628         fmtinstall('H', encodefmt);
1629
1630         ARGBEGIN {
1631         case 'd':
1632                 debug++;
1633                 break;
1634         case 'p':
1635                 if((maxprocs = atoi(EARGF(usage()))) < 1)
1636                         sysfatal("bad number of procs");
1637                 break;
1638         case 'c':
1639                 if(chdir(EARGF(usage())) < 0)
1640                         sysfatal("can't change directory: %r");
1641                 break;
1642         case 'n':
1643                 myname = EARGF(usage());
1644                 break;
1645         case 'x':
1646                 outside = inside = EARGF(usage());
1647                 break;
1648         case 'o':
1649                 outside = EARGF(usage());
1650                 break;
1651         default:
1652                 usage();
1653         } ARGEND;
1654
1655         if(argc < 2)
1656                 usage();
1657         if(parseipandmask(localip, localmask, argv[0], argv[1]) == -1)
1658                 sysfatal("bad local ip/mask: %s/%s", argv[0], argv[1]);
1659         argv += 2, argc -= 2;
1660
1661         srand(fastrand());
1662         if(myname == nil)
1663                 myname = sysname();
1664         if((myhost = gethost(myname, 0)) == nil)
1665                 sysfatal("can't get my host: %r");
1666         if((rpc = getrsarpc()) == nil)
1667                 sysfatal("can't find my key in factotum: %r");
1668         putrsarpc(rpc);
1669
1670         for(i = 0; i < argc; i++){
1671                 if((h = gethost(argv[i], 0)) == nil)
1672                         sysfatal("unknown host: %s", *argv);
1673                 if(h == myhost)
1674                         sysfatal("will not connect to myself");
1675                 if(h->rsapub == nil)
1676                         sysfatal("no RSA public key for: %s", h->name);
1677         }
1678
1679         if(myhost->snet == nil){
1680                 char snet[64];
1681                 snprint(snet, sizeof(snet), "%I/128", localip);
1682                 getsubnet(myhost, snet, 1);
1683         }
1684         if((t = lookupnet(localip)) == nil)
1685                 sysfatal("no subnet found for local ip %I", localip);
1686         if(t->owner != myhost)
1687                 sysfatal("local ip %I belongs to host %s subnet %I %M",
1688                         localip, t->owner->name, t->ip, t->mask);
1689
1690         if(pipe(pfd) < 0)
1691                 sysfatal("can't create pipe: %r");
1692         switch(rfork(RFPROC|RFFDG|RFREND|RFNOTEG|RFENVG)){
1693         case -1:
1694                 sysfatal("can't fork: %r");
1695         case 0:
1696                 dup(pfd[1], 0);
1697                 close(pfd[0]);
1698                 close(pfd[1]);
1699                 if(!debug){
1700                         close(2);
1701                         while(open("/dev/null", OWRITE) == 1)
1702                                 ;
1703                 }
1704                 execl("/bin/rc", "rc", debug? "-v": nil, nil);
1705                 sysfatal("can't exec: %r");
1706         }
1707         rcfd = pfd[0];
1708         close(pfd[1]);
1709
1710         ipifcsetup();
1711         notify(catch);
1712         switch(rfork(RFPROC|RFFDG|RFREND|RFNOTEG)){
1713         case -1:
1714                 sysfatal("can't fork: %r");
1715         case 0:
1716                 break;
1717         default:
1718                 if(debug){
1719                         waitpid();
1720                         fprint(ipcfd, "unbind");
1721                 }
1722                 exits(nil);
1723         }
1724         atexit(shutdown);
1725
1726         fprint(rcfd, "NAME=%s NODE=%s DEVICE=%s INTERFACE=%I ./tinc-up\n",
1727                 myname, myhost->name, device, localip);
1728
1729         if(rfork(RFPROC|RFMEM) == 0){
1730                 tcpclient(listener("tcp", myhost->port, maxprocs), 1);
1731                 exits(nil);
1732         }
1733         if((myhost->options & OptTcpOnly) == 0)
1734         if(rfork(RFPROC|RFMEM) == 0){
1735                 udpclient(listener("udp", myhost->port, maxprocs), 1);
1736                 exits(nil);
1737         }
1738         for(i = 0; i < argc; i++){
1739                 if((h = gethost(argv[i], 0)) == nil)
1740                         continue;
1741                 if(rfork(RFPROC|RFMEM) == 0){
1742                         tcpclient(dialer("tcp", h->addr, h->port, myhost->port), 0);
1743                         exits(nil);
1744                 }
1745                 if((h->options & OptTcpOnly) == 0)
1746                 if(rfork(RFPROC|RFMEM) == 0){
1747                         udpclient(dialer("udp", h->addr, h->port, myhost->port), 0);
1748                         exits(nil);
1749                 }
1750         }
1751         if(rfork(RFPROC|RFMEM) == 0){
1752                 pingpong();
1753                 exits(nil);
1754         }
1755         ip2tunnel();
1756
1757         fprint(rcfd, "NAME=%s NODE=%s DEVICE=%s INTERFACE=%I ./tinc-down\n",
1758                 myname, myhost->name, device, localip);
1759 }