c2491031ec3c9816a40da1be46190df2d0672e7a
[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], "bootp") == 0)
811                 return bootp(ifc);
812         else if (strcmp(argv[0], "try") == 0)
813                 return ipifcadd(ifc, argv, argc, 1, NULL);
814         else if (strcmp(argv[0], "remove") == 0)
815                 return ipifcrem(ifc, argv, argc);
816         else if (strcmp(argv[0], "unbind") == 0)
817                 return ipifcunbind(ifc);
818         else if (strcmp(argv[0], "joinmulti") == 0)
819                 return ipifcjoinmulti(ifc, argv, argc);
820         else if (strcmp(argv[0], "leavemulti") == 0)
821                 return ipifcleavemulti(ifc, argv, argc);
822         else if (strcmp(argv[0], "mtu") == 0)
823                 return ipifcsetmtu(ifc, argv, argc);
824         else if (strcmp(argv[0], "reassemble") == 0) {
825                 ifc->reassemble = 1;
826                 return NULL;
827         } else if (strcmp(argv[0], "iprouting") == 0) {
828                 i = 1;
829                 if (argc > 1)
830                         i = atoi(argv[1]);
831                 iprouting(c->p->f, i);
832                 return NULL;
833         } else if (strcmp(argv[0], "addpref6") == 0)
834                 return ipifcaddpref6(ifc, argv, argc);
835         else if (strcmp(argv[0], "setpar6") == 0)
836                 return ipifcsetpar6(ifc, argv, argc);
837         else if (strcmp(argv[0], "sendra6") == 0)
838                 return ipifcsendra6(ifc, argv, argc);
839         else if (strcmp(argv[0], "recvra6") == 0)
840                 return ipifcrecvra6(ifc, argv, argc);
841         return "unsupported ctl";
842 }
843
844 int ipifcstats(struct Proto *ipifc, char *buf, int len)
845 {
846         return ipstats(ipifc->f, buf, len);
847 }
848
849 void ipifcinit(struct Fs *f)
850 {
851         struct Proto *ipifc;
852
853         ipifc = kzmalloc(sizeof(struct Proto), 0);
854         ipifc->name = "ipifc";
855         ipifc->connect = ipifcconnect;
856         ipifc->announce = NULL;
857         ipifc->bind = ipifcbind;
858         ipifc->state = ipifcstate;
859         ipifc->create = ipifccreate;
860         ipifc->close = ipifcclose;
861         ipifc->rcv = NULL;
862         ipifc->ctl = ipifcctl;
863         ipifc->advise = NULL;
864         ipifc->stats = ipifcstats;
865         ipifc->inuse = ipifcinuse;
866         ipifc->local = ipifclocal;
867         ipifc->ipproto = -1;
868         ipifc->nc = Maxmedia;
869         ipifc->ptclsize = sizeof(struct Ipifc);
870
871         f->ipifc = ipifc;       /* hack for ipifcremroute, findipifc, ... */
872         f->self = kzmalloc(sizeof(struct Ipselftab), 0);        /* hack for ipforme */
873         qlock_init(&f->self->qlock);
874
875         Fsproto(f, ipifc);
876 }
877
878 /*
879  *  add to self routing cache
880  *      called with c locked
881  */
882 static void
883 addselfcache(struct Fs *f, struct Ipifc *ifc,
884                          struct Iplifc *lifc, uint8_t * a, int type)
885 {
886         struct Ipself *p;
887         struct Iplink *lp;
888         int h;
889
890         qlock(&f->self->qlock);
891
892         /* see if the address already exists */
893         h = hashipa(a);
894         for (p = f->self->hash[h]; p; p = p->next)
895                 if (memcmp(a, p->a, IPaddrlen) == 0)
896                         break;
897
898         /* allocate a local address and add to hash chain */
899         if (p == NULL) {
900                 p = kzmalloc(sizeof(*p), 0);
901                 ipmove(p->a, a);
902                 p->type = type;
903                 p->next = f->self->hash[h];
904                 f->self->hash[h] = p;
905
906                 /* if the null address, accept all packets */
907                 if (ipcmp(a, v4prefix) == 0 || ipcmp(a, IPnoaddr) == 0)
908                         f->self->acceptall = 1;
909         }
910
911         /* look for a link for this lifc */
912         for (lp = p->link; lp; lp = lp->selflink)
913                 if (lp->lifc == lifc)
914                         break;
915
916         /* allocate a lifc-to-local link and link to both */
917         if (lp == NULL) {
918                 lp = kzmalloc(sizeof(*lp), 0);
919                 kref_init(&lp->ref, fake_release, 1);
920                 lp->lifc = lifc;
921                 lp->self = p;
922                 lp->selflink = p->link;
923                 p->link = lp;
924                 lp->lifclink = lifc->link;
925                 lifc->link = lp;
926
927                 /* add to routing table */
928                 if (isv4(a))
929                         v4addroute(f, tifc, a + IPv4off, IPallbits + IPv4off, a + IPv4off,
930                                            type);
931                 else
932                         v6addroute(f, tifc, a, IPallbits, a, type);
933
934                 if ((type & Rmulti) && ifc->m->addmulti != NULL)
935                         (*ifc->m->addmulti) (ifc, a, lifc->local);
936         } else {
937                 kref_get(&lp->ref, 1);
938         }
939
940         qunlock(&f->self->qlock);
941 }
942
943 /*
944  *  These structures are unlinked from their chains while
945  *  other threads may be using them.  To avoid excessive locking,
946  *  just put them aside for a while before freeing them.
947  *      called with f->self locked
948  */
949 static struct Iplink *freeiplink;
950 static struct Ipself *freeipself;
951
952 static void iplinkfree(struct Iplink *p)
953 {
954         struct Iplink **l, *np;
955         uint64_t now = NOW;
956
957         l = &freeiplink;
958         for (np = *l; np; np = *l) {
959                 if (np->expire > now) {
960                         *l = np->next;
961                         kfree(np);
962                         continue;
963                 }
964                 l = &np->next;
965         }
966         p->expire = now + 5000; /* give other threads 5 secs to get out */
967         p->next = NULL;
968         *l = p;
969 }
970
971 static void ipselffree(struct Ipself *p)
972 {
973         struct Ipself **l, *np;
974         uint64_t now = NOW;
975
976         l = &freeipself;
977         for (np = *l; np; np = *l) {
978                 if (np->expire > now) {
979                         *l = np->next;
980                         kfree(np);
981                         continue;
982                 }
983                 l = &np->next;
984         }
985         p->expire = now + 5000; /* give other threads 5 secs to get out */
986         p->next = NULL;
987         *l = p;
988 }
989
990 /*
991  *  Decrement reference for this address on this link.
992  *  Unlink from selftab if this is the last ref.
993  *      called with c locked
994  */
995 static void
996 remselfcache(struct Fs *f, struct Ipifc *ifc, struct Iplifc *lifc, uint8_t * a)
997 {
998         struct Ipself *p, **l;
999         struct Iplink *link, **l_self, **l_lifc;
1000
1001         qlock(&f->self->qlock);
1002
1003         /* find the unique selftab entry */
1004         l = &f->self->hash[hashipa(a)];
1005         for (p = *l; p; p = *l) {
1006                 if (ipcmp(p->a, a) == 0)
1007                         break;
1008                 l = &p->next;
1009         }
1010
1011         if (p == NULL)
1012                 goto out;
1013
1014         /*
1015          *  walk down links from an ifc looking for one
1016          *  that matches the selftab entry
1017          */
1018         l_lifc = &lifc->link;
1019         for (link = *l_lifc; link; link = *l_lifc) {
1020                 if (link->self == p)
1021                         break;
1022                 l_lifc = &link->lifclink;
1023         }
1024
1025         if (link == NULL)
1026                 goto out;
1027
1028         /*
1029          *  walk down the links from the selftab looking for
1030          *  the one we just found
1031          */
1032         l_self = &p->link;
1033         for (link = *l_self; link; link = *l_self) {
1034                 if (link == *(l_lifc))
1035                         break;
1036                 l_self = &link->selflink;
1037         }
1038
1039         if (link == NULL)
1040                 panic("remselfcache");
1041
1042         if (kref_refcnt(&link->ref) > 1)
1043                 goto out;
1044
1045         if ((p->type & Rmulti) && ifc->m->remmulti != NULL)
1046                 (*ifc->m->remmulti) (ifc, a, lifc->local);
1047
1048         /* ref == 0, remove from both chains and free the link */
1049         *l_lifc = link->lifclink;
1050         *l_self = link->selflink;
1051         iplinkfree(link);
1052
1053         if (p->link != NULL)
1054                 goto out;
1055
1056         /* remove from routing table */
1057         if (isv4(a))
1058                 v4delroute(f, a + IPv4off, IPallbits + IPv4off, 1);
1059         else
1060                 v6delroute(f, a, IPallbits, 1);
1061
1062         /* no more links, remove from hash and free */
1063         *l = p->next;
1064         ipselffree(p);
1065
1066         /* if IPnoaddr, forget */
1067         if (ipcmp(a, v4prefix) == 0 || ipcmp(a, IPnoaddr) == 0)
1068                 f->self->acceptall = 0;
1069
1070 out:
1071         qunlock(&f->self->qlock);
1072 }
1073
1074 static char *stformat = "%-44.44I %2.2d %4.4s\n";
1075 enum {
1076         Nstformat = 41,
1077 };
1078
1079 long ipselftabread(struct Fs *f, char *cp, uint32_t offset, int n)
1080 {
1081         int i, m, nifc, off;
1082         struct Ipself *p;
1083         struct Iplink *link;
1084         char state[8];
1085
1086         m = 0;
1087         off = offset;
1088         qlock(&f->self->qlock);
1089         for (i = 0; i < NHASH && m < n; i++) {
1090                 for (p = f->self->hash[i]; p != NULL && m < n; p = p->next) {
1091                         nifc = 0;
1092                         for (link = p->link; link; link = link->selflink)
1093                                 nifc++;
1094                         routetype(p->type, state);
1095                         m += snprintf(cp + m, n - m, stformat, p->a, nifc, state);
1096                         if (off > 0) {
1097                                 off -= m;
1098                                 m = 0;
1099                         }
1100                 }
1101         }
1102         qunlock(&f->self->qlock);
1103         return m;
1104 }
1105
1106 int iptentative(struct Fs *f, uint8_t * addr)
1107 {
1108         struct Ipself *p;
1109
1110         p = f->self->hash[hashipa(addr)];
1111         for (; p; p = p->next) {
1112                 if (ipcmp(addr, p->a) == 0) {
1113                         return p->link->lifc->tentative;
1114                 }
1115         }
1116         return 0;
1117 }
1118
1119 /*
1120  *  returns
1121  *      0               - no match
1122  *      Runi
1123  *      Rbcast
1124  *      Rmcast
1125  */
1126 int ipforme(struct Fs *f, uint8_t * addr)
1127 {
1128         struct Ipself *p;
1129
1130         p = f->self->hash[hashipa(addr)];
1131         for (; p; p = p->next) {
1132                 if (ipcmp(addr, p->a) == 0)
1133                         return p->type;
1134         }
1135
1136         /* hack to say accept anything */
1137         if (f->self->acceptall)
1138                 return Runi;
1139
1140         return 0;
1141 }
1142
1143 /*
1144  *  find the ifc on same net as the remote system.  If none,
1145  *  return NULL.
1146  */
1147 struct Ipifc *findipifc(struct Fs *f, uint8_t * remote, int type)
1148 {
1149         struct Ipifc *ifc, *x;
1150         struct Iplifc *lifc;
1151         struct conv **cp, **e;
1152         uint8_t gnet[IPaddrlen];
1153         uint8_t xmask[IPaddrlen];
1154
1155         x = NULL;
1156         memset(xmask, 0, IPaddrlen);
1157
1158         /* find most specific match */
1159         e = &f->ipifc->conv[f->ipifc->nc];
1160         for (cp = f->ipifc->conv; cp < e; cp++) {
1161                 if (*cp == 0)
1162                         continue;
1163
1164                 ifc = (struct Ipifc *)(*cp)->ptcl;
1165
1166                 for (lifc = ifc->lifc; lifc; lifc = lifc->next) {
1167                         maskip(remote, lifc->mask, gnet);
1168                         if (ipcmp(gnet, lifc->net) == 0) {
1169                                 if (x == NULL || ipcmp(lifc->mask, xmask) > 0) {
1170                                         x = ifc;
1171                                         ipmove(xmask, lifc->mask);
1172                                 }
1173                         }
1174                 }
1175         }
1176         if (x != NULL)
1177                 return x;
1178
1179         /* for now for broadcast and multicast, just use first interface */
1180         if (type & (Rbcast | Rmulti)) {
1181                 for (cp = f->ipifc->conv; cp < e; cp++) {
1182                         if (*cp == 0)
1183                                 continue;
1184                         ifc = (struct Ipifc *)(*cp)->ptcl;
1185                         if (ifc->lifc != NULL)
1186                                 return ifc;
1187                 }
1188         }
1189
1190         return NULL;
1191 }
1192
1193 enum {
1194         unknownv6,
1195         multicastv6,
1196         unspecifiedv6,
1197         linklocalv6,
1198         sitelocalv6,
1199         globalv6,
1200 };
1201
1202 int v6addrtype(uint8_t * addr)
1203 {
1204         if (isv6global(addr))
1205                 return globalv6;
1206         if (islinklocal(addr))
1207                 return linklocalv6;
1208         if (isv6mcast(addr))
1209                 return multicastv6;
1210         if (issitelocal(addr))
1211                 return sitelocalv6;
1212         return unknownv6;
1213 }
1214
1215 #define v6addrcurr(lifc) (( (lifc)->origint + (lifc)->preflt >= (NOW/10^3) ) || ( (lifc)->preflt == UINT64_MAX ))
1216
1217 static void findprimaryipv6(struct Fs *f, uint8_t * local)
1218 {
1219         struct conv **cp, **e;
1220         struct Ipifc *ifc;
1221         struct Iplifc *lifc;
1222         int atype, atypel;
1223
1224         ipmove(local, v6Unspecified);
1225         atype = unspecifiedv6;
1226
1227         /* find "best" (global > sitelocal > link local > unspecified)
1228          * local address; address must be current */
1229
1230         e = &f->ipifc->conv[f->ipifc->nc];
1231         for (cp = f->ipifc->conv; cp < e; cp++) {
1232                 if (*cp == 0)
1233                         continue;
1234                 ifc = (struct Ipifc *)(*cp)->ptcl;
1235                 for (lifc = ifc->lifc; lifc; lifc = lifc->next) {
1236                         atypel = v6addrtype(lifc->local);
1237                         if (atypel > atype)
1238                                 if (v6addrcurr(lifc)) {
1239                                         ipmove(local, lifc->local);
1240                                         atype = atypel;
1241                                         if (atype == globalv6)
1242                                                 return;
1243                                 }
1244                 }
1245         }
1246 }
1247
1248 /*
1249  *  returns first ip address configured
1250  */
1251 static void findprimaryipv4(struct Fs *f, uint8_t * local)
1252 {
1253         struct conv **cp, **e;
1254         struct Ipifc *ifc;
1255         struct Iplifc *lifc;
1256
1257         /* find first ifc local address */
1258         e = &f->ipifc->conv[f->ipifc->nc];
1259         for (cp = f->ipifc->conv; cp < e; cp++) {
1260                 if (*cp == 0)
1261                         continue;
1262                 ifc = (struct Ipifc *)(*cp)->ptcl;
1263                 if ((lifc = ifc->lifc) != NULL) {
1264                         ipmove(local, lifc->local);
1265                         return;
1266                 }
1267         }
1268 }
1269
1270 /*
1271  *  find the local address 'closest' to the remote system, copy it to
1272  *  local and return the ifc for that address
1273  */
1274 void findlocalip(struct Fs *f, uint8_t * local, uint8_t * remote)
1275 {
1276         struct Ipifc *ifc;
1277         struct Iplifc *lifc;
1278         struct route *r;
1279         uint8_t gate[IPaddrlen];
1280         uint8_t gnet[IPaddrlen];
1281         int version;
1282         int atype = unspecifiedv6, atypel = unknownv6;
1283
1284         qlock(&f->ipifc->qlock);
1285         r = v6lookup(f, remote, NULL);
1286         version = isv4(remote) ? V4 : V6;
1287
1288         if (r != NULL) {
1289                 ifc = r->rt.ifc;
1290                 if (r->rt.type & Rv4)
1291                         v4tov6(gate, r->v4.gate);
1292                 else {
1293                         ipmove(gate, r->v6.gate);
1294                         ipmove(local, v6Unspecified);
1295                 }
1296
1297                 /* find ifc address closest to the gateway to use */
1298                 switch (version) {
1299                         case V4:
1300                                 for (lifc = ifc->lifc; lifc; lifc = lifc->next) {
1301                                         maskip(gate, lifc->mask, gnet);
1302                                         if (ipcmp(gnet, lifc->net) == 0) {
1303                                                 ipmove(local, lifc->local);
1304                                                 goto out;
1305                                         }
1306                                 }
1307                                 break;
1308                         case V6:
1309                                 for (lifc = ifc->lifc; lifc; lifc = lifc->next) {
1310                                         atypel = v6addrtype(lifc->local);
1311                                         maskip(gate, lifc->mask, gnet);
1312                                         if (ipcmp(gnet, lifc->net) == 0)
1313                                                 if (atypel > atype)
1314                                                         if (v6addrcurr(lifc)) {
1315                                                                 ipmove(local, lifc->local);
1316                                                                 atype = atypel;
1317                                                                 if (atype == globalv6)
1318                                                                         break;
1319                                                         }
1320                                 }
1321                                 if (atype > unspecifiedv6)
1322                                         goto out;
1323                                 break;
1324                         default:
1325                                 panic("findlocalip: version %d", version);
1326                 }
1327         }
1328
1329         switch (version) {
1330                 case V4:
1331                         findprimaryipv4(f, local);
1332                         break;
1333                 case V6:
1334                         findprimaryipv6(f, local);
1335                         break;
1336                 default:
1337                         panic("findlocalip2: version %d", version);
1338         }
1339
1340 out:
1341         qunlock(&f->ipifc->qlock);
1342 }
1343
1344 /*
1345  *  return first v4 address associated with an interface
1346  */
1347 int ipv4local(struct Ipifc *ifc, uint8_t * addr)
1348 {
1349         struct Iplifc *lifc;
1350
1351         for (lifc = ifc->lifc; lifc; lifc = lifc->next) {
1352                 if (isv4(lifc->local)) {
1353                         memmove(addr, lifc->local + IPv4off, IPv4addrlen);
1354                         return 1;
1355                 }
1356         }
1357         return 0;
1358 }
1359
1360 /*
1361  *  return first v6 address associated with an interface
1362  */
1363 int ipv6local(struct Ipifc *ifc, uint8_t * addr)
1364 {
1365         struct Iplifc *lifc;
1366
1367         for (lifc = ifc->lifc; lifc; lifc = lifc->next) {
1368                 if (!isv4(lifc->local) && !(lifc->tentative)) {
1369                         ipmove(addr, lifc->local);
1370                         return 1;
1371                 }
1372         }
1373         return 0;
1374 }
1375
1376 int ipv6anylocal(struct Ipifc *ifc, uint8_t * addr)
1377 {
1378         struct Iplifc *lifc;
1379
1380         for (lifc = ifc->lifc; lifc; lifc = lifc->next) {
1381                 if (!isv4(lifc->local)) {
1382                         ipmove(addr, lifc->local);
1383                         return SRC_UNI;
1384                 }
1385         }
1386         return SRC_UNSPEC;
1387 }
1388
1389 /*
1390  *  see if this address is bound to the interface
1391  */
1392 struct Iplifc *iplocalonifc(struct Ipifc *ifc, uint8_t * ip)
1393 {
1394         struct Iplifc *lifc;
1395
1396         for (lifc = ifc->lifc; lifc; lifc = lifc->next)
1397                 if (ipcmp(ip, lifc->local) == 0)
1398                         return lifc;
1399         return NULL;
1400 }
1401
1402 /*
1403  *  See if we're proxying for this address on this interface
1404  */
1405 int ipproxyifc(struct Fs *f, struct Ipifc *ifc, uint8_t * ip)
1406 {
1407         struct route *r;
1408         uint8_t net[IPaddrlen];
1409         struct Iplifc *lifc;
1410
1411         /* see if this is a direct connected pt to pt address */
1412         r = v6lookup(f, ip, NULL);
1413         if (r == NULL)
1414                 return 0;
1415         if ((r->rt.type & (Rifc | Rproxy)) != (Rifc | Rproxy))
1416                 return 0;
1417
1418         /* see if this is on the right interface */
1419         for (lifc = ifc->lifc; lifc; lifc = lifc->next) {
1420                 maskip(ip, lifc->mask, net);
1421                 if (ipcmp(net, lifc->remote) == 0)
1422                         return 1;
1423         }
1424
1425         return 0;
1426 }
1427
1428 /*
1429  *  return multicast version if any
1430  */
1431 int ipismulticast(uint8_t * ip)
1432 {
1433         if (isv4(ip)) {
1434                 if (ip[IPv4off] >= 0xe0 && ip[IPv4off] < 0xf0)
1435                         return V4;
1436         } else {
1437                 if (ip[0] == 0xff)
1438                         return V6;
1439         }
1440         return 0;
1441 }
1442
1443 int ipisbm(uint8_t * ip)
1444 {
1445         if (isv4(ip)) {
1446                 if (ip[IPv4off] >= 0xe0 && ip[IPv4off] < 0xf0)
1447                         return V4;
1448                 if (ipcmp(ip, IPv4bcast) == 0)
1449                         return V4;
1450         } else {
1451                 if (ip[0] == 0xff)
1452                         return V6;
1453         }
1454         return 0;
1455 }
1456
1457 /*
1458  *  add a multicast address to an interface, called with c locked
1459  */
1460 void ipifcaddmulti(struct conv *c, uint8_t * ma, uint8_t * ia)
1461 {
1462         ERRSTACK(1);
1463         struct Ipifc *ifc;
1464         struct Iplifc *lifc;
1465         struct conv **p;
1466         struct Ipmulti *multi, **l;
1467         struct Fs *f;
1468
1469         f = c->p->f;
1470
1471         for (l = &c->multi; *l; l = &(*l)->next)
1472                 if (ipcmp(ma, (*l)->ma) == 0)
1473                         if (ipcmp(ia, (*l)->ia) == 0)
1474                                 return; /* it's already there */
1475
1476         multi = *l = kzmalloc(sizeof(*multi), 0);
1477         ipmove(multi->ma, ma);
1478         ipmove(multi->ia, ia);
1479         multi->next = NULL;
1480
1481         for (p = f->ipifc->conv; *p; p++) {
1482                 if ((*p)->inuse == 0)
1483                         continue;
1484                 ifc = (struct Ipifc *)(*p)->ptcl;
1485                 wlock(&ifc->rwlock);
1486                 if (waserror()) {
1487                         wunlock(&ifc->rwlock);
1488                         nexterror();
1489                 }
1490                 for (lifc = ifc->lifc; lifc; lifc = lifc->next)
1491                         if (ipcmp(ia, lifc->local) == 0)
1492                                 addselfcache(f, ifc, lifc, ma, Rmulti);
1493                 wunlock(&ifc->rwlock);
1494                 poperror();
1495         }
1496 }
1497
1498 /*
1499  *  remove a multicast address from an interface, called with c locked
1500  */
1501 void ipifcremmulti(struct conv *c, uint8_t * ma, uint8_t * ia)
1502 {
1503         ERRSTACK(1);
1504         struct Ipmulti *multi, **l;
1505         struct Iplifc *lifc;
1506         struct conv **p;
1507         struct Ipifc *ifc;
1508         struct Fs *f;
1509
1510         f = c->p->f;
1511
1512         for (l = &c->multi; *l; l = &(*l)->next)
1513                 if (ipcmp(ma, (*l)->ma) == 0)
1514                         if (ipcmp(ia, (*l)->ia) == 0)
1515                                 break;
1516
1517         multi = *l;
1518         if (multi == NULL)
1519                 return; /* we don't have it open */
1520
1521         *l = multi->next;
1522
1523         for (p = f->ipifc->conv; *p; p++) {
1524                 if ((*p)->inuse == 0)
1525                         continue;
1526
1527                 ifc = (struct Ipifc *)(*p)->ptcl;
1528                 wlock(&ifc->rwlock);
1529                 if (waserror()) {
1530                         wunlock(&ifc->rwlock);
1531                         nexterror();
1532                 }
1533                 for (lifc = ifc->lifc; lifc; lifc = lifc->next)
1534                         if (ipcmp(ia, lifc->local) == 0)
1535                                 remselfcache(f, ifc, lifc, ma);
1536                 wunlock(&ifc->rwlock);
1537                 poperror();
1538         }
1539
1540         kfree(multi);
1541 }
1542
1543 /*
1544  *  make lifc's join and leave multicast groups
1545  */
1546 static char *ipifcjoinmulti(struct Ipifc *ifc, char **argv, int argc)
1547 {
1548         return NULL;
1549 }
1550
1551 static char *ipifcleavemulti(struct Ipifc *ifc, char **argv, int argc)
1552 {
1553         return NULL;
1554 }
1555
1556 static void ipifcregisterproxy(struct Fs *f, struct Ipifc *ifc, uint8_t * ip)
1557 {
1558         struct conv **cp, **e;
1559         struct Ipifc *nifc;
1560         struct Iplifc *lifc;
1561         struct medium *m;
1562         uint8_t net[IPaddrlen];
1563
1564         /* register the address on any network that will proxy for us */
1565         e = &f->ipifc->conv[f->ipifc->nc];
1566
1567         if (!isv4(ip)) {        // V6
1568                 for (cp = f->ipifc->conv; cp < e; cp++) {
1569                         if (*cp == NULL)
1570                                 continue;
1571                         nifc = (struct Ipifc *)(*cp)->ptcl;
1572                         if (nifc == ifc)
1573                                 continue;
1574
1575                         rlock(&nifc->rwlock);
1576                         m = nifc->m;
1577                         if (m == NULL || m->addmulti == NULL) {
1578                                 runlock(&nifc->rwlock);
1579                                 continue;
1580                         }
1581                         for (lifc = nifc->lifc; lifc; lifc = lifc->next) {
1582                                 maskip(ip, lifc->mask, net);
1583                                 if (ipcmp(net, lifc->remote) == 0) {    /* add solicited-node multicast address */
1584                                         ipv62smcast(net, ip);
1585                                         addselfcache(f, nifc, lifc, net, Rmulti);
1586                                         arpenter(f, V6, ip, nifc->mac, 6, 0);
1587                                         //(*m->addmulti)(nifc, net, ip);
1588                                         break;
1589                                 }
1590                         }
1591                         runlock(&nifc->rwlock);
1592                 }
1593                 return;
1594         } else {        // V4
1595                 for (cp = f->ipifc->conv; cp < e; cp++) {
1596                         if (*cp == NULL)
1597                                 continue;
1598                         nifc = (struct Ipifc *)(*cp)->ptcl;
1599                         if (nifc == ifc)
1600                                 continue;
1601
1602                         rlock(&nifc->rwlock);
1603                         m = nifc->m;
1604                         if (m == NULL || m->areg == NULL) {
1605                                 runlock(&nifc->rwlock);
1606                                 continue;
1607                         }
1608                         for (lifc = nifc->lifc; lifc; lifc = lifc->next) {
1609                                 maskip(ip, lifc->mask, net);
1610                                 if (ipcmp(net, lifc->remote) == 0) {
1611                                         (*m->areg) (nifc, ip);
1612                                         break;
1613                                 }
1614                         }
1615                         runlock(&nifc->rwlock);
1616                 }
1617         }
1618 }
1619
1620 // added for new v6 mesg types
1621 static void adddefroute6(struct Fs *f, uint8_t * gate, int force)
1622 {
1623         struct route *r;
1624
1625         r = v6lookup(f, v6Unspecified, NULL);
1626         if (r != NULL)
1627                 if (!(force) && (strcmp(r->rt.tag, "ra") != 0)) // route entries generated
1628                         return; // by all other means take
1629         // precedence over router annc
1630
1631         v6delroute(f, v6Unspecified, v6Unspecified, 1);
1632         v6addroute(f, "ra", v6Unspecified, v6Unspecified, gate, 0);
1633 }
1634
1635 enum {
1636         Ngates = 3,
1637 };
1638
1639 char *ipifcaddpref6(struct Ipifc *ifc, char **argv, int argc)
1640 {
1641         uint8_t onlink = 1;
1642         uint8_t autoflag = 1;
1643         uint64_t validlt = UINT64_MAX;
1644         uint64_t preflt = UINT64_MAX;
1645         uint64_t origint = NOW / 10 ^ 3;
1646         uint8_t prefix[IPaddrlen];
1647         int plen = 64;
1648         struct Iplifc *lifc;
1649         char addr[40], preflen[6];
1650         char *params[3];
1651
1652         switch (argc) {
1653                 case 7:
1654                         preflt = atoi(argv[6]);
1655                         /* fall through */
1656                 case 6:
1657                         validlt = atoi(argv[5]);
1658                         /* fall through */
1659                 case 5:
1660                         autoflag = atoi(argv[4]);
1661                         /* fall through */
1662                 case 4:
1663                         onlink = atoi(argv[3]);
1664                         /* fall through */
1665                 case 3:
1666                         plen = atoi(argv[2]);
1667                 case 2:
1668                         break;
1669                 default:
1670                         return errno_to_string(EINVAL);
1671         }
1672
1673         if ((parseip(prefix, argv[1]) != 6) ||
1674                 (validlt < preflt) || (plen < 0) || (plen > 64) || (islinklocal(prefix))
1675                 )
1676                 return errno_to_string(EINVAL);
1677
1678         lifc = kzmalloc(sizeof(struct Iplifc), 0);
1679         lifc->onlink = (onlink != 0);
1680         lifc->autoflag = (autoflag != 0);
1681         lifc->validlt = validlt;
1682         lifc->preflt = preflt;
1683         lifc->origint = origint;
1684
1685         if (ifc->m->pref2addr != NULL)
1686                 ifc->m->pref2addr(prefix, ifc->mac);
1687         else
1688                 return errno_to_string(EINVAL);
1689
1690         snprintf(addr, sizeof(addr), "%I", prefix);
1691         snprintf(preflen, sizeof(preflen), "/%d", plen);
1692         params[0] = "add";
1693         params[1] = addr;
1694         params[2] = preflen;
1695
1696         return ipifcadd(ifc, params, 3, 0, lifc);
1697 }