Remove bootp
[akaros.git] / kern / src / net / ipifc.c
1 /* Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
2  * Portions Copyright © 1997-1999 Vita Nuova Limited
3  * Portions Copyright © 2000-2007 Vita Nuova Holdings Limited
4  *                                (www.vitanuova.com)
5  * Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
6  *
7  * Modified for the Akaros operating system:
8  * Copyright (c) 2013-2014 The Regents of the University of California
9  * Copyright (c) 2013-2015 Google Inc.
10  *
11  * Permission is hereby granted, free of charge, to any person obtaining a copy
12  * of this software and associated documentation files (the "Software"), to deal
13  * in the Software without restriction, including without limitation the rights
14  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15  * copies of the Software, and to permit persons to whom the Software is
16  * furnished to do so, subject to the following conditions:
17  *
18  * The above copyright notice and this permission notice shall be included in
19  * all copies or substantial portions of the Software.
20  *
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
24  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27  * SOFTWARE. */
28
29 #include <vfs.h>
30 #include <kfs.h>
31 #include <slab.h>
32 #include <kmalloc.h>
33 #include <kref.h>
34 #include <string.h>
35 #include <stdio.h>
36 #include <assert.h>
37 #include <error.h>
38 #include <cpio.h>
39 #include <pmap.h>
40 #include <smp.h>
41 #include <ip.h>
42
43 #define DPRINT if(0)print
44
45 enum {
46         Maxmedia = 32,
47         Nself = Maxmedia * 5,
48         NHASH = (1 << 6),
49         NCACHE = 256,
50         QMAX = 64 * 1024 - 1,
51 };
52
53 struct medium *media[Maxmedia] = {
54         0
55 };
56
57 /*
58  *  cache of local addresses (addresses we answer to)
59  */
60 struct Ipself {
61         uint8_t a[IPaddrlen];
62         struct Ipself *hnext;           /* next address in the hash table */
63         struct Iplink *link;            /* binding twixt Ipself and Ipifc */
64         uint32_t expire;
65         uint8_t type;                           /* type of address */
66         int ref;
67         struct Ipself *next;            /* free list */
68 };
69
70 struct Ipselftab {
71         qlock_t qlock;
72         int inited;
73         int acceptall;                          /* true if an interface has the null address */
74         struct Ipself *hash[NHASH];     /* hash chains */
75 };
76
77 /*
78  *  Multicast addresses are chained onto a Chan so that
79  *  we can remove them when the Chan is closed.
80  */
81 typedef struct Ipmcast Ipmcast;
82 struct Ipmcast {
83         Ipmcast *next;
84         uint8_t ma[IPaddrlen];          /* multicast address */
85         uint8_t ia[IPaddrlen];          /* interface address */
86 };
87
88 /* quick hash for ip addresses */
89 #define hashipa(a) ( ( ((a)[IPaddrlen-2]<<8) | (a)[IPaddrlen-1] )%NHASH )
90
91 static char tifc[] = "ifc ";
92
93 static void addselfcache(struct Fs *f, struct Ipifc *ifc, struct Iplifc *lifc,
94                                                  uint8_t * a, int type);
95 static void remselfcache(struct Fs *f,
96                                                  struct Ipifc *ifc, struct Iplifc *lifc, uint8_t * a);
97 static char *ipifcjoinmulti(struct Ipifc *ifc, char **argv, int argc);
98 static char *ipifcleavemulti(struct Ipifc *ifc, char **argv, int argc);
99 static void ipifcregisterproxy(struct Fs *, struct Ipifc *,
100                                                            uint8_t * unused_uint8_p_t);
101 static char *ipifcremlifc(struct Ipifc *, struct Iplifc *);
102
103 /*
104  *  link in a new medium
105  */
106 void addipmedium(struct medium *med)
107 {
108         int i;
109
110         for (i = 0; i < ARRAY_SIZE(media) - 1; i++)
111                 if (media[i] == NULL) {
112                         media[i] = med;
113                         break;
114                 }
115 }
116
117 /*
118  *  find the medium with this name
119  */
120 struct medium *ipfindmedium(char *name)
121 {
122         struct medium **mp;
123
124         for (mp = media; *mp != NULL; mp++)
125                 if (strcmp((*mp)->name, name) == 0)
126                         break;
127         return *mp;
128 }
129
130 /*
131  *  attach a device (or pkt driver) to the interface.
132  *  called with c locked
133  */
134 static char *ipifcbind(struct conv *c, char **argv, int argc)
135 {
136         ERRSTACK(1);
137         struct Ipifc *ifc;
138         struct medium *m;
139
140         if (argc < 2)
141                 return errno_to_string(EINVAL);
142
143         ifc = (struct Ipifc *)c->ptcl;
144
145         /* bind the device to the interface */
146         m = ipfindmedium(argv[1]);
147         if (m == NULL)
148                 return "unknown interface type";
149
150         wlock(&ifc->rwlock);
151         if (ifc->m != NULL) {
152                 wunlock(&ifc->rwlock);
153                 return "interface already bound";
154         }
155         if (waserror()) {
156                 wunlock(&ifc->rwlock);
157                 nexterror();
158         }
159
160         /* do medium specific binding */
161         (*m->bind) (ifc, argc, argv);
162
163         /* set the bound device name */
164         if (argc > 2)
165                 strlcpy(ifc->dev, argv[2], sizeof(ifc->dev));
166         else
167                 snprintf(ifc->dev, sizeof(ifc->dev), "%s%d", m->name, c->x);
168
169         /* set up parameters */
170         ifc->m = m;
171         ifc->mintu = ifc->m->mintu;
172         ifc->maxtu = ifc->m->maxtu;
173         if (ifc->m->unbindonclose == 0)
174                 ifc->conv->inuse++;
175         ifc->rp.mflag = 0;      // default not managed
176         ifc->rp.oflag = 0;
177         ifc->rp.maxraint = 600000;      // millisecs
178         ifc->rp.minraint = 200000;
179         ifc->rp.linkmtu = 0;    // no mtu sent
180         ifc->rp.reachtime = 0;
181         ifc->rp.rxmitra = 0;
182         ifc->rp.ttl = MAXTTL;
183         ifc->rp.routerlt = 3 * (ifc->rp.maxraint);
184
185         /* any ancillary structures (like routes) no longer pertain */
186         ifc->ifcid++;
187
188         /* reopen all the queues closed by a previous unbind */
189         qreopen(c->rq);
190         qreopen(c->eq);
191         qreopen(c->sq);
192
193         wunlock(&ifc->rwlock);
194         poperror();
195
196         return NULL;
197 }
198
199 /*
200  *  detach a device from an interface, close the interface
201  *  called with ifc->conv closed
202  */
203 static char *ipifcunbind(struct Ipifc *ifc)
204 {
205         ERRSTACK(1);
206         char *err;
207
208         wlock(&ifc->rwlock);
209         if (waserror()) {
210                 wunlock(&ifc->rwlock);
211                 nexterror();
212         }
213
214         /* dissociate routes */
215         if (ifc->m != NULL && ifc->m->unbindonclose == 0)
216                 ifc->conv->inuse--;
217         ifc->ifcid++;
218
219         /* disassociate device */
220         if (ifc->m != NULL && ifc->m->unbind)
221                 (*ifc->m->unbind) (ifc);
222         memset(ifc->dev, 0, sizeof(ifc->dev));
223         ifc->arg = NULL;
224         ifc->reassemble = 0;
225
226         /* close queues to stop queuing of packets */
227         qclose(ifc->conv->rq);
228         qclose(ifc->conv->wq);
229         qclose(ifc->conv->sq);
230
231         /* disassociate logical interfaces */
232         while (ifc->lifc) {
233                 err = ipifcremlifc(ifc, ifc->lifc);
234                 if (err)
235                         error(EFAIL, err);
236         }
237
238         ifc->m = NULL;
239         wunlock(&ifc->rwlock);
240         poperror();
241         return NULL;
242 }
243
244 char sfixedformat[] =
245         "device %s maxtu %d sendra %d recvra %d mflag %d oflag %d maxraint %d minraint %d linkmtu %d reachtime %d rxmitra %d ttl %d routerlt %d pktin %lu pktout %lu errin %lu errout %lu\n";
246
247 char slineformat[] = "  %-40I %-10M %-40I %-12lu %-12lu\n";
248
249 static int ipifcstate(struct conv *c, char *state, int n)
250 {
251         struct Ipifc *ifc;
252         struct Iplifc *lifc;
253         int m;
254
255         ifc = (struct Ipifc *)c->ptcl;
256
257         m = snprintf(state, n, sfixedformat,
258                                  ifc->dev, ifc->maxtu, ifc->sendra6, ifc->recvra6,
259                                  ifc->rp.mflag, ifc->rp.oflag, ifc->rp.maxraint,
260                                  ifc->rp.minraint, ifc->rp.linkmtu, ifc->rp.reachtime,
261                                  ifc->rp.rxmitra, ifc->rp.ttl, ifc->rp.routerlt,
262                                  ifc->in, ifc->out, ifc->inerr, ifc->outerr);
263
264         rlock(&ifc->rwlock);
265         for (lifc = ifc->lifc; lifc && n > m; lifc = lifc->next)
266                 m += snprintf(state + m, n - m, slineformat,
267                                           lifc->local, lifc->mask, lifc->remote,
268                                           lifc->validlt, lifc->preflt);
269         if (ifc->lifc == NULL)
270                 m += snprintf(state + m, n - m, "\n");
271         runlock(&ifc->rwlock);
272         return m;
273 }
274
275 static int ipifclocal(struct conv *c, char *state, int n)
276 {
277         struct Ipifc *ifc;
278         struct Iplifc *lifc;
279         struct Iplink *link;
280         int m;
281
282         ifc = (struct Ipifc *)c->ptcl;
283
284         m = 0;
285
286         rlock(&ifc->rwlock);
287         for (lifc = ifc->lifc; lifc; lifc = lifc->next) {
288                 m += snprintf(state + m, n - m, "%-40.40I ->", lifc->local);
289                 for (link = lifc->link; link; link = link->lifclink)
290                         m += snprintf(state + m, n - m, " %-40.40I", link->self->a);
291                 m += snprintf(state + m, n - m, "\n");
292         }
293         runlock(&ifc->rwlock);
294         return m;
295 }
296
297 static int ipifcinuse(struct conv *c)
298 {
299         struct Ipifc *ifc;
300
301         ifc = (struct Ipifc *)c->ptcl;
302         return ifc->m != NULL;
303 }
304
305 /*
306  *  called when a process writes to an interface's 'data'
307  */
308 static void ipifckick(void *x)
309 {
310         ERRSTACK(1);
311         struct conv *c = x;
312         struct block *bp;
313         struct Ipifc *ifc;
314
315         bp = qget(c->wq);
316         if (bp == NULL)
317                 return;
318
319         ifc = (struct Ipifc *)c->ptcl;
320         if (!canrlock(&ifc->rwlock)) {
321                 freeb(bp);
322                 return;
323         }
324         if (waserror()) {
325                 runlock(&ifc->rwlock);
326                 nexterror();
327         }
328         if (ifc->m == NULL || ifc->m->pktin == NULL)
329                 freeb(bp);
330         else
331                 (*ifc->m->pktin) (c->p->f, ifc, bp);
332         runlock(&ifc->rwlock);
333         poperror();
334 }
335
336 /*
337  *  called when a new ipifc structure is created
338  */
339 static void ipifccreate(struct conv *c)
340 {
341         struct Ipifc *ifc;
342
343         c->rq = qopen(QMAX, 0, 0, 0);
344         c->sq = qopen(2 * QMAX, 0, 0, 0);
345         c->wq = qopen(QMAX, Qkick, ipifckick, c);
346         ifc = (struct Ipifc *)c->ptcl;
347         ifc->conv = c;
348         ifc->unbinding = 0;
349         ifc->m = NULL;
350         ifc->reassemble = 0;
351 }
352
353 /*
354  *  called after last close of ipifc data or ctl
355  *  called with c locked, we must unlock
356  */
357 static void ipifcclose(struct conv *c)
358 {
359         struct Ipifc *ifc;
360         struct medium *m;
361
362         ifc = (struct Ipifc *)c->ptcl;
363         m = ifc->m;
364         if (m != NULL && m->unbindonclose)
365                 ipifcunbind(ifc);
366 }
367
368 /*
369  *  change an interface's mtu
370  */
371 char *ipifcsetmtu(struct Ipifc *ifc, char **argv, int argc)
372 {
373         int mtu;
374
375         if (argc < 2)
376                 return errno_to_string(EINVAL);
377         if (ifc->m == NULL)
378                 return errno_to_string(EINVAL);
379         mtu = strtoul(argv[1], 0, 0);
380         if (mtu < ifc->m->mintu || mtu > ifc->m->maxtu)
381                 return errno_to_string(EINVAL);
382         ifc->maxtu = mtu;
383         return NULL;
384 }
385
386 /*
387  *  add an address to an interface.
388  */
389 char *ipifcadd(struct Ipifc *ifc, char **argv, int argc, int tentative,
390                            struct Iplifc *lifcp)
391 {
392         uint8_t ip[IPaddrlen], mask[IPaddrlen], rem[IPaddrlen];
393         uint8_t bcast[IPaddrlen], net[IPaddrlen];
394         struct Iplifc *lifc, **l;
395         int i, type, mtu;
396         struct Fs *f;
397         int sendnbrdisc = 0;
398
399         if (ifc->m == NULL)
400                 return "ipifc not yet bound to device";
401
402         f = ifc->conv->p->f;
403
404         type = Rifc;
405         memset(ip, 0, IPaddrlen);
406         memset(mask, 0, IPaddrlen);
407         memset(rem, 0, IPaddrlen);
408         switch (argc) {
409                 case 6:
410                         if (strcmp(argv[5], "proxy") == 0)
411                                 type |= Rproxy;
412                         /* fall through */
413                 case 5:
414                         mtu = strtoul(argv[4], 0, 0);
415                         if (mtu >= ifc->m->mintu && mtu <= ifc->m->maxtu)
416                                 ifc->maxtu = mtu;
417                         /* fall through */
418                 case 4:
419                         parseip(ip, argv[1]);
420                         parseipmask(mask, argv[2]);
421                         parseip(rem, argv[3]);
422                         maskip(rem, mask, net);
423                         break;
424                 case 3:
425                         parseip(ip, argv[1]);
426                         parseipmask(mask, argv[2]);
427                         maskip(ip, mask, rem);
428                         maskip(rem, mask, net);
429                         break;
430                 case 2:
431                         parseip(ip, argv[1]);
432                         memmove(mask, defmask(ip), IPaddrlen);
433                         maskip(ip, mask, rem);
434                         maskip(rem, mask, net);
435                         break;
436                 default:
437                         return errno_to_string(EINVAL);
438         }
439         if (isv4(ip))
440                 tentative = 0;
441         wlock(&ifc->rwlock);
442
443         /* ignore if this is already a local address for this ifc */
444         for (lifc = ifc->lifc; lifc; lifc = lifc->next) {
445                 if (ipcmp(lifc->local, ip) == 0) {
446                         if (lifc->tentative != tentative)
447                                 lifc->tentative = tentative;
448                         if (lifcp != NULL) {
449                                 lifc->onlink = lifcp->onlink;
450                                 lifc->autoflag = lifcp->autoflag;
451                                 lifc->validlt = lifcp->validlt;
452                                 lifc->preflt = lifcp->preflt;
453                                 lifc->origint = lifcp->origint;
454                         }
455                         goto out;
456                 }
457         }
458
459         /* add the address to the list of logical ifc's for this ifc */
460         lifc = kzmalloc(sizeof(struct Iplifc), 0);
461         ipmove(lifc->local, ip);
462         ipmove(lifc->mask, mask);
463         ipmove(lifc->remote, rem);
464         ipmove(lifc->net, net);
465         lifc->tentative = tentative;
466         if (lifcp != NULL) {
467                 lifc->onlink = lifcp->onlink;
468                 lifc->autoflag = lifcp->autoflag;
469                 lifc->validlt = lifcp->validlt;
470                 lifc->preflt = lifcp->preflt;
471                 lifc->origint = lifcp->origint;
472         } else {        // default values
473                 lifc->onlink = 1;
474                 lifc->autoflag = 1;
475                 lifc->validlt = UINT64_MAX;
476                 lifc->preflt = UINT64_MAX;
477                 lifc->origint = NOW / 10 ^ 3;
478         }
479         lifc->next = NULL;
480
481         for (l = &ifc->lifc; *l; l = &(*l)->next) ;
482         *l = lifc;
483
484         /* check for point-to-point interface */
485         if (ipcmp(ip, v6loopback))      /* skip v6 loopback, it's a special address */
486                 if (ipcmp(mask, IPallbits) == 0)
487                         type |= Rptpt;
488
489         /* add local routes */
490         if (isv4(ip))
491                 v4addroute(f, tifc, rem + IPv4off, mask + IPv4off, rem + IPv4off, type);
492         else
493                 v6addroute(f, tifc, rem, mask, rem, type);
494
495         addselfcache(f, ifc, lifc, ip, Runi);
496
497         if ((type & (Rproxy | Rptpt)) == (Rproxy | Rptpt)) {
498                 ipifcregisterproxy(f, ifc, rem);
499                 goto out;
500         }
501
502         if (isv4(ip) || ipcmp(ip, IPnoaddr) == 0) {
503                 /* add subnet directed broadcast address to the self cache */
504                 for (i = 0; i < IPaddrlen; i++)
505                         bcast[i] = (ip[i] & mask[i]) | ~mask[i];
506                 addselfcache(f, ifc, lifc, bcast, Rbcast);
507
508                 /* add subnet directed network address to the self cache */
509                 for (i = 0; i < IPaddrlen; i++)
510                         bcast[i] = (ip[i] & mask[i]) & mask[i];
511                 addselfcache(f, ifc, lifc, bcast, Rbcast);
512
513                 /* add network directed broadcast address to the self cache */
514                 memmove(mask, defmask(ip), IPaddrlen);
515                 for (i = 0; i < IPaddrlen; i++)
516                         bcast[i] = (ip[i] & mask[i]) | ~mask[i];
517                 addselfcache(f, ifc, lifc, bcast, Rbcast);
518
519                 /* add network directed network address to the self cache */
520                 memmove(mask, defmask(ip), IPaddrlen);
521                 for (i = 0; i < IPaddrlen; i++)
522                         bcast[i] = (ip[i] & mask[i]) & mask[i];
523                 addselfcache(f, ifc, lifc, bcast, Rbcast);
524
525                 addselfcache(f, ifc, lifc, IPv4bcast, Rbcast);
526         } else {
527                 if (ipcmp(ip, v6loopback) == 0) {
528                         /* add node-local mcast address */
529                         addselfcache(f, ifc, lifc, v6allnodesN, Rmulti);
530
531                         /* add route for all node multicast */
532                         v6addroute(f, tifc, v6allnodesN, v6allnodesNmask, v6allnodesN,
533                                            Rmulti);
534                 }
535
536                 /* add all nodes multicast address */
537                 addselfcache(f, ifc, lifc, v6allnodesL, Rmulti);
538
539                 /* add route for all nodes multicast */
540                 v6addroute(f, tifc, v6allnodesL, v6allnodesLmask, v6allnodesL, Rmulti);
541
542                 /* add solicited-node multicast address */
543                 ipv62smcast(bcast, ip);
544                 addselfcache(f, ifc, lifc, bcast, Rmulti);
545
546                 sendnbrdisc = 1;
547         }
548
549         /* register the address on this network for address resolution */
550         if (isv4(ip) && ifc->m->areg != NULL)
551                 (*ifc->m->areg) (ifc, ip);
552
553 out:
554         wunlock(&ifc->rwlock);
555         if (tentative && sendnbrdisc)
556                 icmpns(f, 0, SRC_UNSPEC, ip, TARG_MULTI, ifc->mac);
557         return NULL;
558 }
559
560 /*
561  *  remove a logical interface from an ifc
562  *  always called with ifc wlock'd
563  */
564 static char *ipifcremlifc(struct Ipifc *ifc, struct Iplifc *lifc)
565 {
566         struct Iplifc **l;
567         struct Fs *f;
568
569         f = ifc->conv->p->f;
570
571         /*
572          *  find address on this interface and remove from chain.
573          *  for pt to pt we actually specify the remote address as the
574          *  addresss to remove.
575          */
576         for (l = &ifc->lifc; *l != NULL && *l != lifc; l = &(*l)->next) ;
577         if (*l == NULL)
578                 return "address not on this interface";
579         *l = lifc->next;
580
581         /* disassociate any addresses */
582         while (lifc->link)
583                 remselfcache(f, ifc, lifc, lifc->link->self->a);
584
585         /* remove the route for this logical interface */
586         if (isv4(lifc->local))
587                 v4delroute(f, lifc->remote + IPv4off, lifc->mask + IPv4off, 1);
588         else {
589                 v6delroute(f, lifc->remote, lifc->mask, 1);
590                 if (ipcmp(lifc->local, v6loopback) == 0)
591                         /* remove route for all node multicast */
592                         v6delroute(f, v6allnodesN, v6allnodesNmask, 1);
593                 else if (memcmp(lifc->local, v6linklocal, v6llpreflen) == 0)
594                         /* remove route for all link multicast */
595                         v6delroute(f, v6allnodesL, v6allnodesLmask, 1);
596         }
597
598         kfree(lifc);
599         return NULL;
600
601 }
602
603 /*
604  *  remove an address from an interface.
605  *  called with c locked
606  */
607 char *ipifcrem(struct Ipifc *ifc, char **argv, int argc)
608 {
609         uint8_t ip[IPaddrlen];
610         uint8_t mask[IPaddrlen];
611         uint8_t rem[IPaddrlen];
612         struct Iplifc *lifc;
613         char *rv;
614
615         if (argc < 3)
616                 return errno_to_string(EINVAL);
617
618         parseip(ip, argv[1]);
619         parseipmask(mask, argv[2]);
620         if (argc < 4)
621                 maskip(ip, mask, rem);
622         else
623                 parseip(rem, argv[3]);
624
625         wlock(&ifc->rwlock);
626
627         /*
628          *  find address on this interface and remove from chain.
629          *  for pt to pt we actually specify the remote address as the
630          *  addresss to remove.
631          */
632         for (lifc = ifc->lifc; lifc != NULL; lifc = lifc->next) {
633                 if (memcmp(ip, lifc->local, IPaddrlen) == 0
634                         && memcmp(mask, lifc->mask, IPaddrlen) == 0
635                         && memcmp(rem, lifc->remote, IPaddrlen) == 0)
636                         break;
637         }
638
639         rv = ipifcremlifc(ifc, lifc);
640         wunlock(&ifc->rwlock);
641         return rv;
642 }
643
644 /*
645  * distribute routes to active interfaces like the
646  * TRIP linecards
647  */
648 void
649 ipifcaddroute(struct Fs *f, int vers, uint8_t * addr, uint8_t * mask,
650                           uint8_t * gate, int type)
651 {
652         struct medium *m;
653         struct conv **cp, **e;
654         struct Ipifc *ifc;
655
656         e = &f->ipifc->conv[f->ipifc->nc];
657         for (cp = f->ipifc->conv; cp < e; cp++) {
658                 if (*cp != NULL) {
659                         ifc = (struct Ipifc *)(*cp)->ptcl;
660                         m = ifc->m;
661                         if (m == NULL)
662                                 continue;
663                         if (m->addroute != NULL)
664                                 m->addroute(ifc, vers, addr, mask, gate, type);
665                 }
666         }
667 }
668
669 void ipifcremroute(struct Fs *f, int vers, uint8_t * addr, uint8_t * mask)
670 {
671         struct medium *m;
672         struct conv **cp, **e;
673         struct Ipifc *ifc;
674
675         e = &f->ipifc->conv[f->ipifc->nc];
676         for (cp = f->ipifc->conv; cp < e; cp++) {
677                 if (*cp != NULL) {
678                         ifc = (struct Ipifc *)(*cp)->ptcl;
679                         m = ifc->m;
680                         if (m == NULL)
681                                 continue;
682                         if (m->remroute != NULL)
683                                 m->remroute(ifc, vers, addr, mask);
684                 }
685         }
686 }
687
688 /*
689  *  associate an address with the interface.  This wipes out any previous
690  *  addresses.  This is a macro that means, remove all the old interfaces
691  *  and add a new one.
692  */
693 static char *ipifcconnect(struct conv *c, char **argv, int argc)
694 {
695         ERRSTACK(1);
696         char *err;
697         struct Ipifc *ifc;
698
699         ifc = (struct Ipifc *)c->ptcl;
700
701         if (ifc->m == NULL)
702                 return "ipifc not yet bound to device";
703
704         wlock(&ifc->rwlock);
705         if (waserror()) {
706                 wunlock(&ifc->rwlock);
707                 nexterror();
708         }
709         while (ifc->lifc) {
710                 err = ipifcremlifc(ifc, ifc->lifc);
711                 if (err)
712                         error(EFAIL, err);
713         }
714         wunlock(&ifc->rwlock);
715         poperror();
716
717         err = ipifcadd(ifc, argv, argc, 0, NULL);
718         if (err)
719                 return err;
720
721         Fsconnected(c, NULL);
722
723         return NULL;
724 }
725
726 char *ipifcsetpar6(struct Ipifc *ifc, char **argv, int argc)
727 {
728         int i, argsleft, vmax = ifc->rp.maxraint, vmin = ifc->rp.minraint;
729
730         argsleft = argc - 1;
731         i = 1;
732
733         if (argsleft % 2 != 0)
734                 return errno_to_string(EINVAL);
735
736         while (argsleft > 1) {
737                 if (strcmp(argv[i], "recvra") == 0)
738                         ifc->recvra6 = (atoi(argv[i + 1]) != 0);
739                 else if (strcmp(argv[i], "sendra") == 0)
740                         ifc->sendra6 = (atoi(argv[i + 1]) != 0);
741                 else if (strcmp(argv[i], "mflag") == 0)
742                         ifc->rp.mflag = (atoi(argv[i + 1]) != 0);
743                 else if (strcmp(argv[i], "oflag") == 0)
744                         ifc->rp.oflag = (atoi(argv[i + 1]) != 0);
745                 else if (strcmp(argv[i], "maxraint") == 0)
746                         ifc->rp.maxraint = atoi(argv[i + 1]);
747                 else if (strcmp(argv[i], "minraint") == 0)
748                         ifc->rp.minraint = atoi(argv[i + 1]);
749                 else if (strcmp(argv[i], "linkmtu") == 0)
750                         ifc->rp.linkmtu = atoi(argv[i + 1]);
751                 else if (strcmp(argv[i], "reachtime") == 0)
752                         ifc->rp.reachtime = atoi(argv[i + 1]);
753                 else if (strcmp(argv[i], "rxmitra") == 0)
754                         ifc->rp.rxmitra = atoi(argv[i + 1]);
755                 else if (strcmp(argv[i], "ttl") == 0)
756                         ifc->rp.ttl = atoi(argv[i + 1]);
757                 else if (strcmp(argv[i], "routerlt") == 0)
758                         ifc->rp.routerlt = atoi(argv[i + 1]);
759                 else
760                         return errno_to_string(EINVAL);
761
762                 argsleft -= 2;
763                 i += 2;
764         }
765
766         // consistency check
767         if (ifc->rp.maxraint < ifc->rp.minraint) {
768                 ifc->rp.maxraint = vmax;
769                 ifc->rp.minraint = vmin;
770                 return errno_to_string(EINVAL);
771         }
772
773         return NULL;
774 }
775
776 char *ipifcsendra6(struct Ipifc *ifc, char **argv, int argc)
777 {
778         int i;
779
780         i = 0;
781         if (argc > 1)
782                 i = atoi(argv[1]);
783         ifc->sendra6 = (i != 0);
784         return NULL;
785 }
786
787 char *ipifcrecvra6(struct Ipifc *ifc, char **argv, int argc)
788 {
789         int i;
790
791         i = 0;
792         if (argc > 1)
793                 i = atoi(argv[1]);
794         ifc->recvra6 = (i != 0);
795         return NULL;
796 }
797
798 /*
799  *  non-standard control messages.
800  *  called with c locked.
801  */
802 static char *ipifcctl(struct conv *c, char **argv, int argc)
803 {
804         struct Ipifc *ifc;
805         int i;
806
807         ifc = (struct Ipifc *)c->ptcl;
808         if (strcmp(argv[0], "add") == 0)
809                 return ipifcadd(ifc, argv, argc, 0, NULL);
810         else if (strcmp(argv[0], "try") == 0)
811                 return ipifcadd(ifc, argv, argc, 1, NULL);
812         else if (strcmp(argv[0], "remove") == 0)
813                 return ipifcrem(ifc, argv, argc);
814         else if (strcmp(argv[0], "unbind") == 0)
815                 return ipifcunbind(ifc);
816         else if (strcmp(argv[0], "joinmulti") == 0)
817                 return ipifcjoinmulti(ifc, argv, argc);
818         else if (strcmp(argv[0], "leavemulti") == 0)
819                 return ipifcleavemulti(ifc, argv, argc);
820         else if (strcmp(argv[0], "mtu") == 0)
821                 return ipifcsetmtu(ifc, argv, argc);
822         else if (strcmp(argv[0], "reassemble") == 0) {
823                 ifc->reassemble = 1;
824                 return NULL;
825         } else if (strcmp(argv[0], "iprouting") == 0) {
826                 i = 1;
827                 if (argc > 1)
828                         i = atoi(argv[1]);
829                 iprouting(c->p->f, i);
830                 return NULL;
831         } else if (strcmp(argv[0], "addpref6") == 0)
832                 return ipifcaddpref6(ifc, argv, argc);
833         else if (strcmp(argv[0], "setpar6") == 0)
834                 return ipifcsetpar6(ifc, argv, argc);
835         else if (strcmp(argv[0], "sendra6") == 0)
836                 return ipifcsendra6(ifc, argv, argc);
837         else if (strcmp(argv[0], "recvra6") == 0)
838                 return ipifcrecvra6(ifc, argv, argc);
839         return "unsupported ctl";
840 }
841
842 int ipifcstats(struct Proto *ipifc, char *buf, int len)
843 {
844         return ipstats(ipifc->f, buf, len);
845 }
846
847 void ipifcinit(struct Fs *f)
848 {
849         struct Proto *ipifc;
850
851         ipifc = kzmalloc(sizeof(struct Proto), 0);
852         ipifc->name = "ipifc";
853         ipifc->connect = ipifcconnect;
854         ipifc->announce = NULL;
855         ipifc->bind = ipifcbind;
856         ipifc->state = ipifcstate;
857         ipifc->create = ipifccreate;
858         ipifc->close = ipifcclose;
859         ipifc->rcv = NULL;
860         ipifc->ctl = ipifcctl;
861         ipifc->advise = NULL;
862         ipifc->stats = ipifcstats;
863         ipifc->inuse = ipifcinuse;
864         ipifc->local = ipifclocal;
865         ipifc->ipproto = -1;
866         ipifc->nc = Maxmedia;
867         ipifc->ptclsize = sizeof(struct Ipifc);
868
869         f->ipifc = ipifc;       /* hack for ipifcremroute, findipifc, ... */
870         f->self = kzmalloc(sizeof(struct Ipselftab), 0);        /* hack for ipforme */
871         qlock_init(&f->self->qlock);
872
873         Fsproto(f, ipifc);
874 }
875
876 /*
877  *  add to self routing cache
878  *      called with c locked
879  */
880 static void
881 addselfcache(struct Fs *f, struct Ipifc *ifc,
882                          struct Iplifc *lifc, uint8_t * a, int type)
883 {
884         struct Ipself *p;
885         struct Iplink *lp;
886         int h;
887
888         qlock(&f->self->qlock);
889
890         /* see if the address already exists */
891         h = hashipa(a);
892         for (p = f->self->hash[h]; p; p = p->next)
893                 if (memcmp(a, p->a, IPaddrlen) == 0)
894                         break;
895
896         /* allocate a local address and add to hash chain */
897         if (p == NULL) {
898                 p = kzmalloc(sizeof(*p), 0);
899                 ipmove(p->a, a);
900                 p->type = type;
901                 p->next = f->self->hash[h];
902                 f->self->hash[h] = p;
903
904                 /* if the null address, accept all packets */
905                 if (ipcmp(a, v4prefix) == 0 || ipcmp(a, IPnoaddr) == 0)
906                         f->self->acceptall = 1;
907         }
908
909         /* look for a link for this lifc */
910         for (lp = p->link; lp; lp = lp->selflink)
911                 if (lp->lifc == lifc)
912                         break;
913
914         /* allocate a lifc-to-local link and link to both */
915         if (lp == NULL) {
916                 lp = kzmalloc(sizeof(*lp), 0);
917                 kref_init(&lp->ref, fake_release, 1);
918                 lp->lifc = lifc;
919                 lp->self = p;
920                 lp->selflink = p->link;
921                 p->link = lp;
922                 lp->lifclink = lifc->link;
923                 lifc->link = lp;
924
925                 /* add to routing table */
926                 if (isv4(a))
927                         v4addroute(f, tifc, a + IPv4off, IPallbits + IPv4off, a + IPv4off,
928                                            type);
929                 else
930                         v6addroute(f, tifc, a, IPallbits, a, type);
931
932                 if ((type & Rmulti) && ifc->m->addmulti != NULL)
933                         (*ifc->m->addmulti) (ifc, a, lifc->local);
934         } else {
935                 kref_get(&lp->ref, 1);
936         }
937
938         qunlock(&f->self->qlock);
939 }
940
941 /*
942  *  These structures are unlinked from their chains while
943  *  other threads may be using them.  To avoid excessive locking,
944  *  just put them aside for a while before freeing them.
945  *      called with f->self locked
946  */
947 static struct Iplink *freeiplink;
948 static struct Ipself *freeipself;
949
950 static void iplinkfree(struct Iplink *p)
951 {
952         struct Iplink **l, *np;
953         uint64_t now = NOW;
954
955         l = &freeiplink;
956         for (np = *l; np; np = *l) {
957                 if (np->expire > now) {
958                         *l = np->next;
959                         kfree(np);
960                         continue;
961                 }
962                 l = &np->next;
963         }
964         p->expire = now + 5000; /* give other threads 5 secs to get out */
965         p->next = NULL;
966         *l = p;
967 }
968
969 static void ipselffree(struct Ipself *p)
970 {
971         struct Ipself **l, *np;
972         uint64_t now = NOW;
973
974         l = &freeipself;
975         for (np = *l; np; np = *l) {
976                 if (np->expire > now) {
977                         *l = np->next;
978                         kfree(np);
979                         continue;
980                 }
981                 l = &np->next;
982         }
983         p->expire = now + 5000; /* give other threads 5 secs to get out */
984         p->next = NULL;
985         *l = p;
986 }
987
988 /*
989  *  Decrement reference for this address on this link.
990  *  Unlink from selftab if this is the last ref.
991  *      called with c locked
992  */
993 static void
994 remselfcache(struct Fs *f, struct Ipifc *ifc, struct Iplifc *lifc, uint8_t * a)
995 {
996         struct Ipself *p, **l;
997         struct Iplink *link, **l_self, **l_lifc;
998
999         qlock(&f->self->qlock);
1000
1001         /* find the unique selftab entry */
1002         l = &f->self->hash[hashipa(a)];
1003         for (p = *l; p; p = *l) {
1004                 if (ipcmp(p->a, a) == 0)
1005                         break;
1006                 l = &p->next;
1007         }
1008
1009         if (p == NULL)
1010                 goto out;
1011
1012         /*
1013          *  walk down links from an ifc looking for one
1014          *  that matches the selftab entry
1015          */
1016         l_lifc = &lifc->link;
1017         for (link = *l_lifc; link; link = *l_lifc) {
1018                 if (link->self == p)
1019                         break;
1020                 l_lifc = &link->lifclink;
1021         }
1022
1023         if (link == NULL)
1024                 goto out;
1025
1026         /*
1027          *  walk down the links from the selftab looking for
1028          *  the one we just found
1029          */
1030         l_self = &p->link;
1031         for (link = *l_self; link; link = *l_self) {
1032                 if (link == *(l_lifc))
1033                         break;
1034                 l_self = &link->selflink;
1035         }
1036
1037         if (link == NULL)
1038                 panic("remselfcache");
1039
1040         if (kref_refcnt(&link->ref) > 1)
1041                 goto out;
1042
1043         if ((p->type & Rmulti) && ifc->m->remmulti != NULL)
1044                 (*ifc->m->remmulti) (ifc, a, lifc->local);
1045
1046         /* ref == 0, remove from both chains and free the link */
1047         *l_lifc = link->lifclink;
1048         *l_self = link->selflink;
1049         iplinkfree(link);
1050
1051         if (p->link != NULL)
1052                 goto out;
1053
1054         /* remove from routing table */
1055         if (isv4(a))
1056                 v4delroute(f, a + IPv4off, IPallbits + IPv4off, 1);
1057         else
1058                 v6delroute(f, a, IPallbits, 1);
1059
1060         /* no more links, remove from hash and free */
1061         *l = p->next;
1062         ipselffree(p);
1063
1064         /* if IPnoaddr, forget */
1065         if (ipcmp(a, v4prefix) == 0 || ipcmp(a, IPnoaddr) == 0)
1066                 f->self->acceptall = 0;
1067
1068 out:
1069         qunlock(&f->self->qlock);
1070 }
1071
1072 static char *stformat = "%-44.44I %2.2d %4.4s\n";
1073 enum {
1074         Nstformat = 41,
1075 };
1076
1077 long ipselftabread(struct Fs *f, char *cp, uint32_t offset, int n)
1078 {
1079         int i, m, nifc, off;
1080         struct Ipself *p;
1081         struct Iplink *link;
1082         char state[8];
1083
1084         m = 0;
1085         off = offset;
1086         qlock(&f->self->qlock);
1087         for (i = 0; i < NHASH && m < n; i++) {
1088                 for (p = f->self->hash[i]; p != NULL && m < n; p = p->next) {
1089                         nifc = 0;
1090                         for (link = p->link; link; link = link->selflink)
1091                                 nifc++;
1092                         routetype(p->type, state);
1093                         m += snprintf(cp + m, n - m, stformat, p->a, nifc, state);
1094                         if (off > 0) {
1095                                 off -= m;
1096                                 m = 0;
1097                         }
1098                 }
1099         }
1100         qunlock(&f->self->qlock);
1101         return m;
1102 }
1103
1104 int iptentative(struct Fs *f, uint8_t * addr)
1105 {
1106         struct Ipself *p;
1107
1108         p = f->self->hash[hashipa(addr)];
1109         for (; p; p = p->next) {
1110                 if (ipcmp(addr, p->a) == 0) {
1111                         return p->link->lifc->tentative;
1112                 }
1113         }
1114         return 0;
1115 }
1116
1117 /*
1118  *  returns
1119  *      0               - no match
1120  *      Runi
1121  *      Rbcast
1122  *      Rmcast
1123  */
1124 int ipforme(struct Fs *f, uint8_t * addr)
1125 {
1126         struct Ipself *p;
1127
1128         p = f->self->hash[hashipa(addr)];
1129         for (; p; p = p->next) {
1130                 if (ipcmp(addr, p->a) == 0)
1131                         return p->type;
1132         }
1133
1134         /* hack to say accept anything */
1135         if (f->self->acceptall)
1136                 return Runi;
1137
1138         return 0;
1139 }
1140
1141 /*
1142  *  find the ifc on same net as the remote system.  If none,
1143  *  return NULL.
1144  */
1145 struct Ipifc *findipifc(struct Fs *f, uint8_t * remote, int type)
1146 {
1147         struct Ipifc *ifc, *x;
1148         struct Iplifc *lifc;
1149         struct conv **cp, **e;
1150         uint8_t gnet[IPaddrlen];
1151         uint8_t xmask[IPaddrlen];
1152
1153         x = NULL;
1154         memset(xmask, 0, IPaddrlen);
1155
1156         /* find most specific match */
1157         e = &f->ipifc->conv[f->ipifc->nc];
1158         for (cp = f->ipifc->conv; cp < e; cp++) {
1159                 if (*cp == 0)
1160                         continue;
1161
1162                 ifc = (struct Ipifc *)(*cp)->ptcl;
1163
1164                 for (lifc = ifc->lifc; lifc; lifc = lifc->next) {
1165                         maskip(remote, lifc->mask, gnet);
1166                         if (ipcmp(gnet, lifc->net) == 0) {
1167                                 if (x == NULL || ipcmp(lifc->mask, xmask) > 0) {
1168                                         x = ifc;
1169                                         ipmove(xmask, lifc->mask);
1170                                 }
1171                         }
1172                 }
1173         }
1174         if (x != NULL)
1175                 return x;
1176
1177         /* for now for broadcast and multicast, just use first interface */
1178         if (type & (Rbcast | Rmulti)) {
1179                 for (cp = f->ipifc->conv; cp < e; cp++) {
1180                         if (*cp == 0)
1181                                 continue;
1182                         ifc = (struct Ipifc *)(*cp)->ptcl;
1183                         if (ifc->lifc != NULL)
1184                                 return ifc;
1185                 }
1186         }
1187
1188         return NULL;
1189 }
1190
1191 enum {
1192         unknownv6,
1193         multicastv6,
1194         unspecifiedv6,
1195         linklocalv6,
1196         sitelocalv6,
1197         globalv6,
1198 };
1199
1200 int v6addrtype(uint8_t * addr)
1201 {
1202         if (isv6global(addr))
1203                 return globalv6;
1204         if (islinklocal(addr))
1205                 return linklocalv6;
1206         if (isv6mcast(addr))
1207                 return multicastv6;
1208         if (issitelocal(addr))
1209                 return sitelocalv6;
1210         return unknownv6;
1211 }
1212
1213 #define v6addrcurr(lifc) (( (lifc)->origint + (lifc)->preflt >= (NOW/10^3) ) || ( (lifc)->preflt == UINT64_MAX ))
1214
1215 static void findprimaryipv6(struct Fs *f, uint8_t * local)
1216 {
1217         struct conv **cp, **e;
1218         struct Ipifc *ifc;
1219         struct Iplifc *lifc;
1220         int atype, atypel;
1221
1222         ipmove(local, v6Unspecified);
1223         atype = unspecifiedv6;
1224
1225         /* find "best" (global > sitelocal > link local > unspecified)
1226          * local address; address must be current */
1227
1228         e = &f->ipifc->conv[f->ipifc->nc];
1229         for (cp = f->ipifc->conv; cp < e; cp++) {
1230                 if (*cp == 0)
1231                         continue;
1232                 ifc = (struct Ipifc *)(*cp)->ptcl;
1233                 for (lifc = ifc->lifc; lifc; lifc = lifc->next) {
1234                         atypel = v6addrtype(lifc->local);
1235                         if (atypel > atype)
1236                                 if (v6addrcurr(lifc)) {
1237                                         ipmove(local, lifc->local);
1238                                         atype = atypel;
1239                                         if (atype == globalv6)
1240                                                 return;
1241                                 }
1242                 }
1243         }
1244 }
1245
1246 /*
1247  *  returns first ip address configured
1248  */
1249 static void findprimaryipv4(struct Fs *f, uint8_t * local)
1250 {
1251         struct conv **cp, **e;
1252         struct Ipifc *ifc;
1253         struct Iplifc *lifc;
1254
1255         /* find first ifc local address */
1256         e = &f->ipifc->conv[f->ipifc->nc];
1257         for (cp = f->ipifc->conv; cp < e; cp++) {
1258                 if (*cp == 0)
1259                         continue;
1260                 ifc = (struct Ipifc *)(*cp)->ptcl;
1261                 if ((lifc = ifc->lifc) != NULL) {
1262                         ipmove(local, lifc->local);
1263                         return;
1264                 }
1265         }
1266 }
1267
1268 /*
1269  *  find the local address 'closest' to the remote system, copy it to
1270  *  local and return the ifc for that address
1271  */
1272 void findlocalip(struct Fs *f, uint8_t * local, uint8_t * remote)
1273 {
1274         struct Ipifc *ifc;
1275         struct Iplifc *lifc;
1276         struct route *r;
1277         uint8_t gate[IPaddrlen];
1278         uint8_t gnet[IPaddrlen];
1279         int version;
1280         int atype = unspecifiedv6, atypel = unknownv6;
1281
1282         qlock(&f->ipifc->qlock);
1283         r = v6lookup(f, remote, NULL);
1284         version = isv4(remote) ? V4 : V6;
1285
1286         if (r != NULL) {
1287                 ifc = r->rt.ifc;
1288                 if (r->rt.type & Rv4)
1289                         v4tov6(gate, r->v4.gate);
1290                 else {
1291                         ipmove(gate, r->v6.gate);
1292                         ipmove(local, v6Unspecified);
1293                 }
1294
1295                 /* find ifc address closest to the gateway to use */
1296                 switch (version) {
1297                         case V4:
1298                                 for (lifc = ifc->lifc; lifc; lifc = lifc->next) {
1299                                         maskip(gate, lifc->mask, gnet);
1300                                         if (ipcmp(gnet, lifc->net) == 0) {
1301                                                 ipmove(local, lifc->local);
1302                                                 goto out;
1303                                         }
1304                                 }
1305                                 break;
1306                         case V6:
1307                                 for (lifc = ifc->lifc; lifc; lifc = lifc->next) {
1308                                         atypel = v6addrtype(lifc->local);
1309                                         maskip(gate, lifc->mask, gnet);
1310                                         if (ipcmp(gnet, lifc->net) == 0)
1311                                                 if (atypel > atype)
1312                                                         if (v6addrcurr(lifc)) {
1313                                                                 ipmove(local, lifc->local);
1314                                                                 atype = atypel;
1315                                                                 if (atype == globalv6)
1316                                                                         break;
1317                                                         }
1318                                 }
1319                                 if (atype > unspecifiedv6)
1320                                         goto out;
1321                                 break;
1322                         default:
1323                                 panic("findlocalip: version %d", version);
1324                 }
1325         }
1326
1327         switch (version) {
1328                 case V4:
1329                         findprimaryipv4(f, local);
1330                         break;
1331                 case V6:
1332                         findprimaryipv6(f, local);
1333                         break;
1334                 default:
1335                         panic("findlocalip2: version %d", version);
1336         }
1337
1338 out:
1339         qunlock(&f->ipifc->qlock);
1340 }
1341
1342 /*
1343  *  return first v4 address associated with an interface
1344  */
1345 int ipv4local(struct Ipifc *ifc, uint8_t * addr)
1346 {
1347         struct Iplifc *lifc;
1348
1349         for (lifc = ifc->lifc; lifc; lifc = lifc->next) {
1350                 if (isv4(lifc->local)) {
1351                         memmove(addr, lifc->local + IPv4off, IPv4addrlen);
1352                         return 1;
1353                 }
1354         }
1355         return 0;
1356 }
1357
1358 /*
1359  *  return first v6 address associated with an interface
1360  */
1361 int ipv6local(struct Ipifc *ifc, uint8_t * addr)
1362 {
1363         struct Iplifc *lifc;
1364
1365         for (lifc = ifc->lifc; lifc; lifc = lifc->next) {
1366                 if (!isv4(lifc->local) && !(lifc->tentative)) {
1367                         ipmove(addr, lifc->local);
1368                         return 1;
1369                 }
1370         }
1371         return 0;
1372 }
1373
1374 int ipv6anylocal(struct Ipifc *ifc, uint8_t * addr)
1375 {
1376         struct Iplifc *lifc;
1377
1378         for (lifc = ifc->lifc; lifc; lifc = lifc->next) {
1379                 if (!isv4(lifc->local)) {
1380                         ipmove(addr, lifc->local);
1381                         return SRC_UNI;
1382                 }
1383         }
1384         return SRC_UNSPEC;
1385 }
1386
1387 /*
1388  *  see if this address is bound to the interface
1389  */
1390 struct Iplifc *iplocalonifc(struct Ipifc *ifc, uint8_t * ip)
1391 {
1392         struct Iplifc *lifc;
1393
1394         for (lifc = ifc->lifc; lifc; lifc = lifc->next)
1395                 if (ipcmp(ip, lifc->local) == 0)
1396                         return lifc;
1397         return NULL;
1398 }
1399
1400 /*
1401  *  See if we're proxying for this address on this interface
1402  */
1403 int ipproxyifc(struct Fs *f, struct Ipifc *ifc, uint8_t * ip)
1404 {
1405         struct route *r;
1406         uint8_t net[IPaddrlen];
1407         struct Iplifc *lifc;
1408
1409         /* see if this is a direct connected pt to pt address */
1410         r = v6lookup(f, ip, NULL);
1411         if (r == NULL)
1412                 return 0;
1413         if ((r->rt.type & (Rifc | Rproxy)) != (Rifc | Rproxy))
1414                 return 0;
1415
1416         /* see if this is on the right interface */
1417         for (lifc = ifc->lifc; lifc; lifc = lifc->next) {
1418                 maskip(ip, lifc->mask, net);
1419                 if (ipcmp(net, lifc->remote) == 0)
1420                         return 1;
1421         }
1422
1423         return 0;
1424 }
1425
1426 /*
1427  *  return multicast version if any
1428  */
1429 int ipismulticast(uint8_t * ip)
1430 {
1431         if (isv4(ip)) {
1432                 if (ip[IPv4off] >= 0xe0 && ip[IPv4off] < 0xf0)
1433                         return V4;
1434         } else {
1435                 if (ip[0] == 0xff)
1436                         return V6;
1437         }
1438         return 0;
1439 }
1440
1441 int ipisbm(uint8_t * ip)
1442 {
1443         if (isv4(ip)) {
1444                 if (ip[IPv4off] >= 0xe0 && ip[IPv4off] < 0xf0)
1445                         return V4;
1446                 if (ipcmp(ip, IPv4bcast) == 0)
1447                         return V4;
1448         } else {
1449                 if (ip[0] == 0xff)
1450                         return V6;
1451         }
1452         return 0;
1453 }
1454
1455 /*
1456  *  add a multicast address to an interface, called with c locked
1457  */
1458 void ipifcaddmulti(struct conv *c, uint8_t * ma, uint8_t * ia)
1459 {
1460         ERRSTACK(1);
1461         struct Ipifc *ifc;
1462         struct Iplifc *lifc;
1463         struct conv **p;
1464         struct Ipmulti *multi, **l;
1465         struct Fs *f;
1466
1467         f = c->p->f;
1468
1469         for (l = &c->multi; *l; l = &(*l)->next)
1470                 if (ipcmp(ma, (*l)->ma) == 0)
1471                         if (ipcmp(ia, (*l)->ia) == 0)
1472                                 return; /* it's already there */
1473
1474         multi = *l = kzmalloc(sizeof(*multi), 0);
1475         ipmove(multi->ma, ma);
1476         ipmove(multi->ia, ia);
1477         multi->next = NULL;
1478
1479         for (p = f->ipifc->conv; *p; p++) {
1480                 if ((*p)->inuse == 0)
1481                         continue;
1482                 ifc = (struct Ipifc *)(*p)->ptcl;
1483                 wlock(&ifc->rwlock);
1484                 if (waserror()) {
1485                         wunlock(&ifc->rwlock);
1486                         nexterror();
1487                 }
1488                 for (lifc = ifc->lifc; lifc; lifc = lifc->next)
1489                         if (ipcmp(ia, lifc->local) == 0)
1490                                 addselfcache(f, ifc, lifc, ma, Rmulti);
1491                 wunlock(&ifc->rwlock);
1492                 poperror();
1493         }
1494 }
1495
1496 /*
1497  *  remove a multicast address from an interface, called with c locked
1498  */
1499 void ipifcremmulti(struct conv *c, uint8_t * ma, uint8_t * ia)
1500 {
1501         ERRSTACK(1);
1502         struct Ipmulti *multi, **l;
1503         struct Iplifc *lifc;
1504         struct conv **p;
1505         struct Ipifc *ifc;
1506         struct Fs *f;
1507
1508         f = c->p->f;
1509
1510         for (l = &c->multi; *l; l = &(*l)->next)
1511                 if (ipcmp(ma, (*l)->ma) == 0)
1512                         if (ipcmp(ia, (*l)->ia) == 0)
1513                                 break;
1514
1515         multi = *l;
1516         if (multi == NULL)
1517                 return; /* we don't have it open */
1518
1519         *l = multi->next;
1520
1521         for (p = f->ipifc->conv; *p; p++) {
1522                 if ((*p)->inuse == 0)
1523                         continue;
1524
1525                 ifc = (struct Ipifc *)(*p)->ptcl;
1526                 wlock(&ifc->rwlock);
1527                 if (waserror()) {
1528                         wunlock(&ifc->rwlock);
1529                         nexterror();
1530                 }
1531                 for (lifc = ifc->lifc; lifc; lifc = lifc->next)
1532                         if (ipcmp(ia, lifc->local) == 0)
1533                                 remselfcache(f, ifc, lifc, ma);
1534                 wunlock(&ifc->rwlock);
1535                 poperror();
1536         }
1537
1538         kfree(multi);
1539 }
1540
1541 /*
1542  *  make lifc's join and leave multicast groups
1543  */
1544 static char *ipifcjoinmulti(struct Ipifc *ifc, char **argv, int argc)
1545 {
1546         return NULL;
1547 }
1548
1549 static char *ipifcleavemulti(struct Ipifc *ifc, char **argv, int argc)
1550 {
1551         return NULL;
1552 }
1553
1554 static void ipifcregisterproxy(struct Fs *f, struct Ipifc *ifc, uint8_t * ip)
1555 {
1556         struct conv **cp, **e;
1557         struct Ipifc *nifc;
1558         struct Iplifc *lifc;
1559         struct medium *m;
1560         uint8_t net[IPaddrlen];
1561
1562         /* register the address on any network that will proxy for us */
1563         e = &f->ipifc->conv[f->ipifc->nc];
1564
1565         if (!isv4(ip)) {        // V6
1566                 for (cp = f->ipifc->conv; cp < e; cp++) {
1567                         if (*cp == NULL)
1568                                 continue;
1569                         nifc = (struct Ipifc *)(*cp)->ptcl;
1570                         if (nifc == ifc)
1571                                 continue;
1572
1573                         rlock(&nifc->rwlock);
1574                         m = nifc->m;
1575                         if (m == NULL || m->addmulti == NULL) {
1576                                 runlock(&nifc->rwlock);
1577                                 continue;
1578                         }
1579                         for (lifc = nifc->lifc; lifc; lifc = lifc->next) {
1580                                 maskip(ip, lifc->mask, net);
1581                                 if (ipcmp(net, lifc->remote) == 0) {    /* add solicited-node multicast address */
1582                                         ipv62smcast(net, ip);
1583                                         addselfcache(f, nifc, lifc, net, Rmulti);
1584                                         arpenter(f, V6, ip, nifc->mac, 6, 0);
1585                                         //(*m->addmulti)(nifc, net, ip);
1586                                         break;
1587                                 }
1588                         }
1589                         runlock(&nifc->rwlock);
1590                 }
1591                 return;
1592         } else {        // V4
1593                 for (cp = f->ipifc->conv; cp < e; cp++) {
1594                         if (*cp == NULL)
1595                                 continue;
1596                         nifc = (struct Ipifc *)(*cp)->ptcl;
1597                         if (nifc == ifc)
1598                                 continue;
1599
1600                         rlock(&nifc->rwlock);
1601                         m = nifc->m;
1602                         if (m == NULL || m->areg == NULL) {
1603                                 runlock(&nifc->rwlock);
1604                                 continue;
1605                         }
1606                         for (lifc = nifc->lifc; lifc; lifc = lifc->next) {
1607                                 maskip(ip, lifc->mask, net);
1608                                 if (ipcmp(net, lifc->remote) == 0) {
1609                                         (*m->areg) (nifc, ip);
1610                                         break;
1611                                 }
1612                         }
1613                         runlock(&nifc->rwlock);
1614                 }
1615         }
1616 }
1617
1618 // added for new v6 mesg types
1619 static void adddefroute6(struct Fs *f, uint8_t * gate, int force)
1620 {
1621         struct route *r;
1622
1623         r = v6lookup(f, v6Unspecified, NULL);
1624         if (r != NULL)
1625                 if (!(force) && (strcmp(r->rt.tag, "ra") != 0)) // route entries generated
1626                         return; // by all other means take
1627         // precedence over router annc
1628
1629         v6delroute(f, v6Unspecified, v6Unspecified, 1);
1630         v6addroute(f, "ra", v6Unspecified, v6Unspecified, gate, 0);
1631 }
1632
1633 enum {
1634         Ngates = 3,
1635 };
1636
1637 char *ipifcaddpref6(struct Ipifc *ifc, char **argv, int argc)
1638 {
1639         uint8_t onlink = 1;
1640         uint8_t autoflag = 1;
1641         uint64_t validlt = UINT64_MAX;
1642         uint64_t preflt = UINT64_MAX;
1643         uint64_t origint = NOW / 10 ^ 3;
1644         uint8_t prefix[IPaddrlen];
1645         int plen = 64;
1646         struct Iplifc *lifc;
1647         char addr[40], preflen[6];
1648         char *params[3];
1649
1650         switch (argc) {
1651                 case 7:
1652                         preflt = atoi(argv[6]);
1653                         /* fall through */
1654                 case 6:
1655                         validlt = atoi(argv[5]);
1656                         /* fall through */
1657                 case 5:
1658                         autoflag = atoi(argv[4]);
1659                         /* fall through */
1660                 case 4:
1661                         onlink = atoi(argv[3]);
1662                         /* fall through */
1663                 case 3:
1664                         plen = atoi(argv[2]);
1665                 case 2:
1666                         break;
1667                 default:
1668                         return errno_to_string(EINVAL);
1669         }
1670
1671         if ((parseip(prefix, argv[1]) != 6) ||
1672                 (validlt < preflt) || (plen < 0) || (plen > 64) || (islinklocal(prefix))
1673                 )
1674                 return errno_to_string(EINVAL);
1675
1676         lifc = kzmalloc(sizeof(struct Iplifc), 0);
1677         lifc->onlink = (onlink != 0);
1678         lifc->autoflag = (autoflag != 0);
1679         lifc->validlt = validlt;
1680         lifc->preflt = preflt;
1681         lifc->origint = origint;
1682
1683         if (ifc->m->pref2addr != NULL)
1684                 ifc->m->pref2addr(prefix, ifc->mac);
1685         else
1686                 return errno_to_string(EINVAL);
1687
1688         snprintf(addr, sizeof(addr), "%I", prefix);
1689         snprintf(preflen, sizeof(preflen), "/%d", plen);
1690         params[0] = "add";
1691         params[1] = addr;
1692         params[2] = preflen;
1693
1694         return ipifcadd(ifc, params, 3, 0, lifc);
1695 }