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