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