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