qio: Track the amount of bytes read
[akaros.git] / kern / src / net / netif.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 static int netown(struct netfile *, char *unused_char_p_t, int);
44 static int openfile(struct ether *, int);
45 static char *matchtoken(char *unused_char_p_t, char *);
46 static char *netmulti(struct ether *, struct netfile *,
47                                           uint8_t * unused_uint8_p_t, int);
48 static int parseaddr(uint8_t * unused_uint8_p_t, char *unused_char_p_t, int);
49
50 /*
51  *  set up a new network interface
52  */
53 void netifinit(struct ether *nif, char *name, int nfile, uint32_t limit)
54 {
55         qlock_init(&nif->qlock);
56         strlcpy(nif->name, name, KNAMELEN);
57         nif->nfile = nfile;
58         nif->f = kzmalloc(nfile * sizeof(struct netfile *), 0);
59         if (nif->f)
60                 memset(nif->f, 0, nfile * sizeof(struct netfile *));
61         else
62                 nif->nfile = 0;
63         nif->limit = limit;
64 }
65
66 /*
67  *  generate a 3 level directory
68  */
69 static int
70 netifgen(struct chan *c, char *unused_char_p_t, struct dirtab *vp,
71                  int unused_int, int i, struct dir *dp)
72 {
73         struct qid q;
74         struct ether *nif = (struct ether *)vp;
75         struct netfile *f;
76         int perm;
77         char *o;
78
79         q.type = QTFILE;
80         q.vers = 0;
81
82         /* top level directory contains the name of the network */
83         if (c->qid.path == 0) {
84                 switch (i) {
85                         case DEVDOTDOT:
86                                 q.path = 0;
87                                 q.type = QTDIR;
88                                 devdir(c, q, ".", 0, eve.name, 0555, dp);
89                                 break;
90                         case 0:
91                                 q.path = N2ndqid;
92                                 q.type = QTDIR;
93                                 strlcpy(get_cur_genbuf(), nif->name, GENBUF_SZ);
94                                 devdir(c, q, get_cur_genbuf(), 0, eve.name, 0555, dp);
95                                 break;
96                         default:
97                                 return -1;
98                 }
99                 return 1;
100         }
101
102         /* second level contains clone plus all the conversations.
103          *
104          * This ancient comment is from plan9.  Inferno and nxm both had issues
105          * here.  You couldn't ls /net/ether0/ when it didn't have any convs.  There
106          * were also issues with nxm where you couldn't stat ether0/x/stats
107          * properly.
108          *
109          * The issue is that if we handle things like Nstatqid, then we will never
110          * pass it down to the third level. And since we just set the path ==
111          * Nstatqid, we won't have the NETID muxed in. If someone isn't trying to
112          * generate a chan, but instead is looking it up (devwalk generates, devstat
113          * already has the chan), then they are also looking for a devdir with path
114          * containing ID << 5. So if you stat ether0/1/ifstats, devstat is looking
115          * for path 41, but we return path 9 (41 = 32 + 9). (these numbers are
116          * before we tracked NETID + 1).
117          *
118          * We (akaros and plan9) had a big if here, that would catch things that do
119          * not exist in the subdirs of a netif. Things like clone make sense here.
120          * I guess addr too, though that seems to be added since the original
121          * comment. You can see what the 3rd level was expecting to parse by looking
122          * farther down in the code.
123          *
124          * The root of the problem was that the old code couldn't tell the
125          * difference between no netid and netid 0. Now, we determine if we're at
126          * the second level by the lack of a netid, instead of trying to enumerate
127          * the qid types that the second level could have. The latter approach
128          * allowed for something like ether0/1/stats, but we couldn't actually
129          * devstat ether0/stats directly. It's worth noting that there is no
130          * difference to the content of ether0/stats and ether0/x/stats (when you
131          * read), but they have different chan qids.
132          *
133          * Here's the old if block:
134          t = NETTYPE(c->qid.path);
135          if (t == N2ndqid || t == Ncloneqid || t == Naddrqid) {
136          */
137         if (NETID(c->qid.path) == -1) {
138                 switch (i) {
139                         case DEVDOTDOT:
140                                 q.type = QTDIR;
141                                 q.path = 0;
142                                 devdir(c, q, ".", 0, eve.name, DMDIR | 0555, dp);
143                                 break;
144                         case 0:
145                                 q.path = Ncloneqid;
146                                 devdir(c, q, "clone", 0, eve.name, 0666, dp);
147                                 break;
148                         case 1:
149                                 q.path = Naddrqid;
150                                 devdir(c, q, "addr", 0, eve.name, 0666, dp);
151                                 break;
152                         case 2:
153                                 q.path = Nstatqid;
154                                 devdir(c, q, "stats", 0, eve.name, 0444, dp);
155                                 break;
156                         case 3:
157                                 q.path = Nifstatqid;
158                                 devdir(c, q, "ifstats", 0, eve.name, 0444, dp);
159                                 break;
160                         default:
161                                 i -= 4;
162                                 if (i >= nif->nfile)
163                                         return -1;
164                                 if (nif->f[i] == 0)
165                                         return 0;
166                                 q.type = QTDIR;
167                                 q.path = NETQID(i, N3rdqid);
168                                 snprintf(get_cur_genbuf(), GENBUF_SZ, "%d", i);
169                                 devdir(c, q, get_cur_genbuf(), 0, eve.name, DMDIR | 0555, dp);
170                                 break;
171                 }
172                 return 1;
173         }
174
175         /* third level */
176         f = nif->f[NETID(c->qid.path)];
177         if (f == 0)
178                 return 0;
179         if (*f->owner) {
180                 o = f->owner;
181                 perm = f->mode;
182         } else {
183                 o = eve.name;
184                 perm = 0666;
185         }
186         switch (i) {
187                 case DEVDOTDOT:
188                         q.type = QTDIR;
189                         q.path = N2ndqid;
190                         strlcpy(get_cur_genbuf(), nif->name, GENBUF_SZ);
191                         devdir(c, q, get_cur_genbuf(), 0, eve.name, DMDIR | 0555, dp);
192                         break;
193                 case 0:
194                         q.path = NETQID(NETID(c->qid.path), Ndataqid);
195                         devdir(c, q, "data", 0, o, perm, dp);
196                         break;
197                 case 1:
198                         q.path = NETQID(NETID(c->qid.path), Nctlqid);
199                         devdir(c, q, "ctl", 0, o, perm, dp);
200                         break;
201                 case 2:
202                         q.path = NETQID(NETID(c->qid.path), Nstatqid);
203                         devdir(c, q, "stats", 0, eve.name, 0444, dp);
204                         break;
205                 case 3:
206                         q.path = NETQID(NETID(c->qid.path), Ntypeqid);
207                         devdir(c, q, "type", 0, eve.name, 0444, dp);
208                         break;
209                 case 4:
210                         q.path = NETQID(NETID(c->qid.path), Nifstatqid);
211                         devdir(c, q, "ifstats", 0, eve.name, 0444, dp);
212                         break;
213                 default:
214                         return -1;
215         }
216         return 1;
217 }
218
219 struct walkqid *netifwalk(struct ether *nif, struct chan *c, struct chan *nc,
220                                                   char **name, int nname)
221 {
222         return devwalk(c, nc, name, nname, (struct dirtab *)nif, 0, netifgen);
223 }
224
225 struct chan *netifopen(struct ether *nif, struct chan *c, int omode)
226 {
227         int id;
228         struct netfile *f;
229
230         id = 0;
231         if (c->qid.type & QTDIR) {
232                 if (omode & O_WRITE)
233                         error(EPERM, ERROR_FIXME);
234         } else {
235                 switch (NETTYPE(c->qid.path)) {
236                         case Ndataqid:
237                         case Nctlqid:
238                                 id = NETID(c->qid.path);
239                                 openfile(nif, id);
240                                 break;
241                         case Ncloneqid:
242                                 id = openfile(nif, -1);
243                                 c->qid.path = NETQID(id, Nctlqid);
244                                 break;
245                         default:
246                                 if (omode & O_WRITE)
247                                         error(EINVAL, ERROR_FIXME);
248                 }
249                 switch (NETTYPE(c->qid.path)) {
250                         case Ndataqid:
251                         case Nctlqid:
252                                 f = nif->f[id];
253                                 if (netown(f, current->user.name, omode & 7) < 0)
254                                         error(EPERM, ERROR_FIXME);
255                                 break;
256                 }
257         }
258         c->mode = openmode(omode);
259         c->flag |= COPEN;
260         c->offset = 0;
261         c->iounit = qiomaxatomic;
262         return c;
263 }
264
265 long
266 netifread(struct ether *nif, struct chan *c, void *a, long n,
267           uint32_t offset)
268 {
269         int i, j;
270         struct netfile *f;
271         char *p;
272
273         if (c->qid.type & QTDIR)
274                 return devdirread(c, a, n, (struct dirtab *)nif, 0, netifgen);
275
276         switch (NETTYPE(c->qid.path)) {
277                 case Ndataqid:
278                         f = nif->f[NETID(c->qid.path)];
279                         return qread(f->in, a, n);
280                 case Nctlqid:
281                         return readnum(offset, a, n, NETID(c->qid.path), NUMSIZE);
282                 case Nstatqid:
283                         p = kzmalloc(READSTR, 0);
284                         if (p == NULL)
285                                 return 0;
286                         j = snprintf(p, READSTR, "in: %d\n", nif->inpackets);
287                         j += snprintf(p + j, READSTR - j, "link: %d\n", nif->link);
288                         j += snprintf(p + j, READSTR - j, "out: %d\n", nif->outpackets);
289                         j += snprintf(p + j, READSTR - j, "crc errs: %d\n", nif->crcs);
290                         j += snprintf(p + j, READSTR - j, "overflows: %d\n",
291                                                   nif->overflows);
292                         j += snprintf(p + j, READSTR - j, "soft overflows: %d\n",
293                                                   nif->soverflows);
294                         j += snprintf(p + j, READSTR - j, "framing errs: %d\n",
295                                                   nif->frames);
296                         j += snprintf(p + j, READSTR - j, "buffer errs: %d\n", nif->buffs);
297                         j += snprintf(p + j, READSTR - j, "output errs: %d\n", nif->oerrs);
298                         j += snprintf(p + j, READSTR - j, "prom: %d\n", nif->prom);
299                         j += snprintf(p + j, READSTR - j, "mbps: %d\n", nif->mbps);
300                         j += snprintf(p + j, READSTR - j, "addr: ");
301                         for (i = 0; i < nif->alen; i++)
302                                 j += snprintf(p + j, READSTR - j, "%02.2x", nif->addr[i]);
303                         j += snprintf(p + j, READSTR - j, "\n");
304                         j += snprintf(p + j, READSTR - j, "feat: ");
305                         if (nif->feat & NETF_IPCK)
306                                 j += snprintf(p + j, READSTR - j, "ipck ");
307                         if (nif->feat & NETF_UDPCK)
308                                 j += snprintf(p + j, READSTR - j, "udpck ");
309                         if (nif->feat & NETF_TCPCK)
310                                 j += snprintf(p + j, READSTR - j, "tcpck ");
311                         if (nif->feat & NETF_PADMIN)
312                                 j += snprintf(p + j, READSTR - j, "padmin ");
313                         if (nif->feat & NETF_SG)
314                                 j += snprintf(p + j, READSTR - j, "sg ");
315                         if (nif->feat & NETF_TSO)
316                                 j += snprintf(p + j, READSTR - j, "tso ");
317                         if (nif->feat & NETF_LRO)
318                                 j += snprintf(p + j, READSTR - j, "lro ");
319                         snprintf(p + j, READSTR - j, "\n");
320                         n = readstr(offset, a, n, p);
321                         kfree(p);
322                         return n;
323                 case Naddrqid:
324                         p = kzmalloc(READSTR, 0);
325                         if (p == NULL)
326                                 return 0;
327                         j = 0;
328                         for (i = 0; i < nif->alen; i++)
329                                 j += snprintf(p + j, READSTR - j, "%02.2x", nif->addr[i]);
330                         n = readstr(offset, a, n, p);
331                         kfree(p);
332                         return n;
333                 case Ntypeqid:
334                         f = nif->f[NETID(c->qid.path)];
335                         return readnum(offset, a, n, f->type, NUMSIZE);
336                 case Nifstatqid:
337                         return 0;
338         }
339         error(EINVAL, ERROR_FIXME);
340         return -1;      /* not reached */
341 }
342
343 struct block *netifbread(struct ether *nif, struct chan *c, long n,
344                                                  uint32_t offset)
345 {
346         if ((c->qid.type & QTDIR) || NETTYPE(c->qid.path) != Ndataqid)
347                 return devbread(c, n, offset);
348
349         return qbread(nif->f[NETID(c->qid.path)]->in, n);
350 }
351
352 /*
353  *  make sure this type isn't already in use on this device
354  */
355 static int typeinuse(struct ether *nif, int type)
356 {
357         struct netfile *f, **fp, **efp;
358
359         if (type <= 0)
360                 return 0;
361
362         efp = &nif->f[nif->nfile];
363         for (fp = nif->f; fp < efp; fp++) {
364                 f = *fp;
365                 if (f == 0)
366                         continue;
367                 if (f->type == type)
368                         return 1;
369         }
370         return 0;
371 }
372
373 /*
374  *  the devxxx.c that calls us handles writing data, it knows best
375  */
376 long netifwrite(struct ether *nif, struct chan *c, void *a, long n)
377 {
378         ERRSTACK(1);
379         struct netfile *f;
380         int type;
381         char *p, buf[64];
382         uint8_t binaddr[Nmaxaddr];
383
384         if (NETTYPE(c->qid.path) != Nctlqid)
385                 error(EPERM, ERROR_FIXME);
386
387         if (n >= sizeof(buf))
388                 n = sizeof(buf) - 1;
389         memmove(buf, a, n);
390         buf[n] = 0;
391
392         qlock(&nif->qlock);
393         if (waserror()) {
394                 qunlock(&nif->qlock);
395                 nexterror();
396         }
397
398         f = nif->f[NETID(c->qid.path)];
399         if ((p = matchtoken(buf, "connect")) != 0) {
400                 type = strtol(p, 0, 0); /* allows any base, though usually hex */
401                 if (typeinuse(nif, type))
402                         error(EBUSY, ERROR_FIXME);
403                 f->type = type;
404                 if (f->type < 0)
405                         nif->all++;
406         } else if (matchtoken(buf, "promiscuous")) {
407                 if (f->prom == 0) {
408                         /* Note that promisc has two meanings: put the NIC into promisc
409                          * mode, and record our outbound traffic.  See etheroq(). */
410                         if (nif->prom == 0 && nif->promiscuous != NULL)
411                                 nif->promiscuous(nif->arg, 1);
412                         f->prom = 1;
413                         nif->prom++;
414                 }
415         } else if ((p = matchtoken(buf, "scanbs")) != 0) {
416                 /* scan for base stations */
417                 if (f->scan == 0) {
418                         type = strtol(p, 0, 0); /* allows any base, though usually hex */
419                         if (type < 5)
420                                 type = 5;
421                         if (nif->scanbs != NULL)
422                                 nif->scanbs(nif->arg, type);
423                         f->scan = type;
424                         nif->scan++;
425                 }
426         } else if (matchtoken(buf, "bridge")) {
427                 f->bridge = 1;
428         } else if (matchtoken(buf, "headersonly")) {
429                 f->headersonly = 1;
430         } else if ((p = matchtoken(buf, "addmulti")) != 0) {
431                 if (parseaddr(binaddr, p, nif->alen) < 0)
432                         error(EFAIL, "bad address");
433                 p = netmulti(nif, f, binaddr, 1);
434                 if (p)
435                         error(EFAIL, p);
436         } else if ((p = matchtoken(buf, "remmulti")) != 0) {
437                 if (parseaddr(binaddr, p, nif->alen) < 0)
438                         error(EFAIL, "bad address");
439                 p = netmulti(nif, f, binaddr, 0);
440                 if (p)
441                         error(EFAIL, p);
442         } else if (matchtoken(buf, "oneblock")) {
443                 /* Qmsg + Qcoal = one block at a time. */
444                 q_toggle_qmsg(f->in, TRUE);
445                 q_toggle_qcoalesce(f->in, TRUE);
446         } else
447                 n = -1;
448         qunlock(&nif->qlock);
449         poperror();
450         return n;
451 }
452
453 int netifwstat(struct ether *nif, struct chan *c, uint8_t * db, int n)
454 {
455         struct dir *dir;
456         struct netfile *f;
457         int m;
458
459         f = nif->f[NETID(c->qid.path)];
460         if (f == 0)
461                 error(ENOENT, ERROR_FIXME);
462
463         if (netown(f, current->user.name, O_WRITE) < 0)
464                 error(EPERM, ERROR_FIXME);
465
466         dir = kzmalloc(sizeof(struct dir) + n, 0);
467         m = convM2D(db, n, &dir[0], (char *)&dir[1]);
468         if (m == 0) {
469                 kfree(dir);
470                 error(ENODATA, ERROR_FIXME);
471         }
472         if (!emptystr(dir[0].uid))
473                 strlcpy(f->owner, dir[0].uid, KNAMELEN);
474         if (dir[0].mode != -1)
475                 f->mode = dir[0].mode;
476         kfree(dir);
477         return m;
478 }
479
480 int netifstat(struct ether *nif, struct chan *c, uint8_t * db, int n)
481 {
482         return devstat(c, db, n, (struct dirtab *)nif, 0, netifgen);
483 }
484
485 void netifclose(struct ether *nif, struct chan *c)
486 {
487         struct netfile *f;
488         int t;
489         struct netaddr *ap;
490
491         if ((c->flag & COPEN) == 0)
492                 return;
493
494         t = NETTYPE(c->qid.path);
495         if (t != Ndataqid && t != Nctlqid)
496                 return;
497
498         f = nif->f[NETID(c->qid.path)];
499         qlock(&f->qlock);
500         if (--(f->inuse) == 0) {
501                 if (f->prom) {
502                         qlock(&nif->qlock);
503                         if (--(nif->prom) == 0 && nif->promiscuous != NULL)
504                                 nif->promiscuous(nif->arg, 0);
505                         qunlock(&nif->qlock);
506                         f->prom = 0;
507                 }
508                 if (f->scan) {
509                         qlock(&nif->qlock);
510                         if (--(nif->scan) == 0 && nif->scanbs != NULL)
511                                 nif->scanbs(nif->arg, 0);
512                         qunlock(&nif->qlock);
513                         f->prom = 0;
514                         f->scan = 0;
515                 }
516                 if (f->nmaddr) {
517                         qlock(&nif->qlock);
518                         t = 0;
519                         for (ap = nif->maddr; ap; ap = ap->next) {
520                                 if (f->maddr[t / 8] & (1 << (t % 8)))
521                                         netmulti(nif, f, ap->addr, 0);
522                         }
523                         qunlock(&nif->qlock);
524                         f->nmaddr = 0;
525                 }
526                 if (f->type < 0) {
527                         qlock(&nif->qlock);
528                         --(nif->all);
529                         qunlock(&nif->qlock);
530                 }
531                 f->owner[0] = 0;
532                 f->type = 0;
533                 f->bridge = 0;
534                 f->headersonly = 0;
535                 qclose(f->in);
536         }
537         qunlock(&f->qlock);
538 }
539
540 spinlock_t netlock = SPINLOCK_INITIALIZER;
541
542 static int netown(struct netfile *p, char *o, int omode)
543 {
544         int mode;
545         int rwx;
546
547         spin_lock(&netlock);
548         if (*p->owner) {
549                 if (strncmp(o, p->owner, KNAMELEN) == 0)        /* User */
550                         mode = p->mode;
551                 else if (strncmp(o, eve.name, KNAMELEN) == 0)   /* Bootes is group */
552                         mode = p->mode << 3;
553                 else
554                         mode = p->mode << 6;    /* Other */
555
556                 rwx = omode_to_rwx(omode);
557                 if ((rwx & mode) == rwx) {
558                         spin_unlock(&netlock);
559                         return 0;
560                 } else {
561                         spin_unlock(&netlock);
562                         return -1;
563                 }
564         }
565         strlcpy(p->owner, o, KNAMELEN);
566         p->mode = 0660;
567         spin_unlock(&netlock);
568         return 0;
569 }
570
571 /*
572  *  Increment the reference count of a network device.
573  *  If id < 0, return an unused ether device.
574  */
575 static int openfile(struct ether *nif, int id)
576 {
577         ERRSTACK(1);
578         struct netfile *f, **fp, **efp;
579
580         if (id >= 0) {
581                 f = nif->f[id];
582                 if (f == 0)
583                         error(ENODEV, ERROR_FIXME);
584                 qlock(&f->qlock);
585                 qreopen(f->in);
586                 f->inuse++;
587                 qunlock(&f->qlock);
588                 return id;
589         }
590
591         qlock(&nif->qlock);
592         if (waserror()) {
593                 qunlock(&nif->qlock);
594                 nexterror();
595         }
596         efp = &nif->f[nif->nfile];
597         for (fp = nif->f; fp < efp; fp++) {
598                 f = *fp;
599                 if (f == 0) {
600                         f = kzmalloc(sizeof(struct netfile), 0);
601                         if (f == 0)
602                                 exhausted("memory");
603                         /* since we lock before netifinit (if we ever call that...) */
604                         qlock_init(&f->qlock);
605                         f->in = qopen(nif->limit, Qmsg, 0, 0);
606                         if (f->in == NULL) {
607                                 kfree(f);
608                                 exhausted("memory");
609                         }
610                         *fp = f;
611                         qlock(&f->qlock);
612                 } else {
613                         qlock(&f->qlock);
614                         if (f->inuse) {
615                                 qunlock(&f->qlock);
616                                 continue;
617                         }
618                 }
619                 f->inuse = 1;
620                 qreopen(f->in);
621                 netown(f, current->user.name, 0);
622                 qunlock(&f->qlock);
623                 qunlock(&nif->qlock);
624                 poperror();
625                 return fp - nif->f;
626         }
627         error(ENODEV, ERROR_FIXME);
628         return -1;      /* not reached */
629 }
630
631 /*
632  *  look for a token starting a string,
633  *  return a pointer to first non-space char after it
634  */
635 static char *matchtoken(char *p, char *token)
636 {
637         int n;
638
639         n = strlen(token);
640         if (strncmp(p, token, n))
641                 return 0;
642         p += n;
643         if (*p == 0)
644                 return p;
645         if (*p != ' ' && *p != '\t' && *p != '\n')
646                 return 0;
647         while (*p == ' ' || *p == '\t' || *p == '\n')
648                 p++;
649         return p;
650 }
651
652 static uint32_t hash(uint8_t * a, int len)
653 {
654         uint32_t sum = 0;
655
656         while (len-- > 0)
657                 sum = (sum << 1) + *a++;
658         return sum % Nmhash;
659 }
660
661 int activemulti(struct ether *nif, uint8_t * addr, int alen)
662 {
663         struct netaddr *hp;
664
665         for (hp = nif->mhash[hash(addr, alen)]; hp; hp = hp->hnext)
666                 if (memcmp(addr, hp->addr, alen) == 0) {
667                         if (hp->ref)
668                                 return 1;
669                         else
670                                 break;
671                 }
672         return 0;
673 }
674
675 static int parseaddr(uint8_t * to, char *from, int alen)
676 {
677         char nip[4];
678         char *p;
679         int i;
680
681         p = from;
682         for (i = 0; i < alen; i++) {
683                 if (*p == 0)
684                         return -1;
685                 nip[0] = *p++;
686                 if (*p == 0)
687                         return -1;
688                 nip[1] = *p++;
689                 nip[2] = 0;
690                 to[i] = strtoul(nip, 0, 16);
691                 if (*p == ':')
692                         p++;
693         }
694         return 0;
695 }
696
697 /*
698  *  keep track of multicast addresses
699  */
700 static char *netmulti(struct ether *nif, struct netfile *f, uint8_t * addr,
701                                           int add)
702 {
703         struct netaddr **l, *ap;
704         int i;
705         uint32_t h;
706
707         if (nif->multicast == NULL)
708                 return "interface does not support multicast";
709
710         l = &nif->maddr;
711         i = 0;
712         for (ap = *l; ap; ap = *l) {
713                 if (memcmp(addr, ap->addr, nif->alen) == 0)
714                         break;
715                 i++;
716                 l = &ap->next;
717         }
718
719         if (add) {
720                 if (ap == 0) {
721                         /* TODO: AFAIK, this never gets freed.  if we fix that, we can use a
722                          * kref too (instead of int ap->ref). */
723                         *l = ap = kzmalloc(sizeof(*ap), 0);
724                         memmove(ap->addr, addr, nif->alen);
725                         ap->next = 0;
726                         ap->ref = 1;
727                         h = hash(addr, nif->alen);
728                         ap->hnext = nif->mhash[h];
729                         nif->mhash[h] = ap;
730                 } else {
731                         ap->ref++;
732                 }
733                 if (ap->ref == 1) {
734                         nif->nmaddr++;
735                         nif->multicast(nif->arg, addr, 1);
736                 }
737                 if (i < 8 * sizeof(f->maddr)) {
738                         if ((f->maddr[i / 8] & (1 << (i % 8))) == 0)
739                                 f->nmaddr++;
740                         f->maddr[i / 8] |= 1 << (i % 8);
741                 }
742         } else {
743                 if (ap == 0 || ap->ref == 0)
744                         return 0;
745                 ap->ref--;
746                 if (ap->ref == 0) {
747                         nif->nmaddr--;
748                         nif->multicast(nif->arg, addr, 0);
749                 }
750                 if (i < 8 * sizeof(f->maddr)) {
751                         if ((f->maddr[i / 8] & (1 << (i % 8))) != 0)
752                                 f->nmaddr--;
753                         f->maddr[i / 8] &= ~(1 << (i % 8));
754                 }
755         }
756         return 0;
757 }