Devtab created with linker tables
[akaros.git] / kern / src / net / devip.c
1 // INFERNO
2 #include <vfs.h>
3 #include <kfs.h>
4 #include <slab.h>
5 #include <kmalloc.h>
6 #include <kref.h>
7 #include <string.h>
8 #include <stdio.h>
9 #include <assert.h>
10 #include <error.h>
11 #include <cpio.h>
12 #include <pmap.h>
13 #include <smp.h>
14 #include <ip.h>
15
16 enum
17 {
18         Qtopdir=        1,              /* top level directory */
19         Qtopbase,
20         Qarp=           Qtopbase,
21         Qbootp,
22         Qndb,
23         Qiproute,
24         Qiprouter,
25         Qipselftab,
26         Qlog,
27
28         Qprotodir,                      /* directory for a protocol */
29         Qprotobase,
30         Qclone=         Qprotobase,
31         Qstats,
32
33         Qconvdir,                       /* directory for a conversation */
34         Qconvbase,
35         Qctl=           Qconvbase,
36         Qdata,
37         Qerr,
38         Qlisten,
39         Qlocal,
40         Qremote,
41         Qstatus,
42         Qsnoop,
43
44         Logtype=        5,
45         Masktype=       (1<<Logtype)-1,
46         Logconv=        12,
47         Maskconv=       (1<<Logconv)-1,
48         Shiftconv=      Logtype,
49         Logproto=       8,
50         Maskproto=      (1<<Logproto)-1,
51         Shiftproto=     Logtype + Logconv,
52
53         Nfs=            32,
54 };
55 #define TYPE(x)         ( ((uint32_t)(x).path) & Masktype )
56 #define CONV(x)         ( (((uint32_t)(x).path) >> Shiftconv) & Maskconv )
57 #define PROTO(x)        ( (((uint32_t)(x).path) >> Shiftproto) & Maskproto )
58 #define QID(p, c, y)    ( ((p)<<(Shiftproto)) | ((c)<<Shiftconv) | (y))
59 static char network[] = "network";
60
61 qlock_t fslock;
62 struct Fs       *ipfs[Nfs];     /* attached fs's */
63 struct queue    *qlog;
64
65 extern  void nullmediumlink(void);
66 extern  void pktmediumlink(void);
67 extern char *eve;
68 static  long ndbwrite(struct Fs*, char *unused_char_p_t, uint32_t, int);
69 static  void    closeconv(struct conv*);
70
71 static int
72 ip3gen(struct chan *c, int i, struct dir *dp)
73 {
74         struct qid q;
75         struct conv *cv;
76         char *p;
77
78         cv = ipfs[c->dev]->p[PROTO(c->qid)]->conv[CONV(c->qid)];
79         if(cv->owner == NULL)
80                 kstrdup(&cv->owner, eve);
81         mkqid(&q, QID(PROTO(c->qid), CONV(c->qid), i), 0, QTFILE);
82
83         switch(i) {
84         default:
85                 return -1;
86         case Qctl:
87                 devdir(c, q, "ctl", 0, cv->owner, cv->perm, dp);
88                 return 1;
89         case Qdata:
90                 devdir(c, q, "data", qlen(cv->rq), cv->owner, cv->perm, dp);
91                 return 1;
92         case Qerr:
93                 devdir(c, q, "err", qlen(cv->eq), cv->owner, cv->perm, dp);
94                 return 1;
95         case Qlisten:
96                 devdir(c, q, "listen", 0, cv->owner, cv->perm, dp);
97                 return 1;
98         case Qlocal:
99                 p = "local";
100                 break;
101         case Qremote:
102                 p = "remote";
103                 break;
104         case Qsnoop:
105                 if(strcmp(cv->p->name, "ipifc") != 0)
106                         return -1;
107                 devdir(c, q, "snoop", qlen(cv->sq), cv->owner, 0400, dp);
108                 return 1;
109         case Qstatus:
110                 p = "status";
111                 break;
112         }
113         devdir(c, q, p, 0, cv->owner, 0444, dp);
114         return 1;
115 }
116
117 static int
118 ip2gen(struct chan *c, int i, struct dir *dp)
119 {
120         struct qid q;
121
122         switch(i) {
123         case Qclone:
124                 mkqid(&q, QID(PROTO(c->qid), 0, Qclone), 0, QTFILE);
125                 devdir(c, q, "clone", 0, network, 0666, dp);
126                 return 1;
127         case Qstats:
128                 mkqid(&q, QID(PROTO(c->qid), 0, Qstats), 0, QTFILE);
129                 devdir(c, q, "stats", 0, network, 0444, dp);
130                 return 1;
131         }       
132         return -1;
133 }
134
135 static int
136 ip1gen(struct chan *c, int i, struct dir *dp)
137 {
138         struct qid q;
139         char *p;
140         int prot;
141         int len = 0;
142         struct Fs *f;
143         extern uint32_t kerndate;
144
145         f = ipfs[c->dev];
146
147         prot = 0666;
148         mkqid(&q, QID(0, 0, i), 0, QTFILE);
149         switch(i) {
150         default:
151                 return -1;
152         case Qarp:
153                 p = "arp";
154                 break;
155         case Qbootp:
156                 p = "bootp";
157                 if(bootp == NULL)
158                         return 0;
159                 break;
160         case Qndb:
161                 p = "ndb";
162                 len = strlen(f->ndb);
163                 q.vers = f->ndbvers;
164                 break;
165         case Qiproute:
166                 p = "iproute";
167                 break;
168         case Qipselftab:
169                 p = "ipselftab";
170                 prot = 0444;
171                 break;
172         case Qiprouter:
173                 p = "iprouter";
174                 break;
175         case Qlog:
176                 p = "log";
177                 break;
178         }
179         devdir(c, q, p, len, network, prot, dp);
180         if(i == Qndb && f->ndbmtime > kerndate)
181                 dp->mtime = f->ndbmtime;
182         return 1;
183 }
184
185 static int
186 ipgen(struct chan *c, char *unused_char_p_t, struct dirtab*d, int unused_int, int s, struct dir *dp)
187 {
188         struct qid q;
189         struct conv *cv;
190         struct Fs *f;
191
192         f = ipfs[c->dev];
193
194         switch(TYPE(c->qid)) {
195         case Qtopdir:
196                 if(s == DEVDOTDOT){
197                         mkqid(&q, QID(0, 0, Qtopdir), 0, QTDIR);
198                         snprintf(get_cur_genbuf(), GENBUF_SZ, "#I%lud", c->dev);
199                         devdir(c, q, get_cur_genbuf(), 0, network, 0555, dp);
200                         return 1;
201                 }
202                 if(s < f->np) {
203                         if(f->p[s]->connect == NULL)
204                                 return 0;       /* protocol with no user interface */
205                         mkqid(&q, QID(s, 0, Qprotodir), 0, QTDIR);
206                         devdir(c, q, f->p[s]->name, 0, network, 0555, dp);
207                         return 1;
208                 }
209                 s -= f->np;
210                 return ip1gen(c, s+Qtopbase, dp);
211         case Qarp:
212         case Qbootp:
213         case Qndb:
214         case Qlog:
215         case Qiproute:
216         case Qiprouter:
217         case Qipselftab:
218                 return ip1gen(c, TYPE(c->qid), dp);
219         case Qprotodir:
220                 if(s == DEVDOTDOT){
221                         mkqid(&q, QID(0, 0, Qtopdir), 0, QTDIR);
222                         snprintf(get_cur_genbuf(), GENBUF_SZ, "#I%lud", c->dev);
223                         devdir(c, q, get_cur_genbuf(), 0, network, 0555, dp);
224                         return 1;
225                 }
226                 if(s < f->p[PROTO(c->qid)]->ac) {
227                         cv = f->p[PROTO(c->qid)]->conv[s];
228                         snprintf(get_cur_genbuf(), GENBUF_SZ, "%d", s);
229                         mkqid(&q, QID(PROTO(c->qid), s, Qconvdir), 0, QTDIR);
230                         devdir(c, q, get_cur_genbuf(), 0, cv->owner, 0555, dp);
231                         return 1;
232                 }
233                 s -= f->p[PROTO(c->qid)]->ac;
234                 return ip2gen(c, s+Qprotobase, dp);
235         case Qclone:
236         case Qstats:
237                 return ip2gen(c, TYPE(c->qid), dp);
238         case Qconvdir:
239                 if(s == DEVDOTDOT){
240                         s = PROTO(c->qid);
241                         mkqid(&q, QID(s, 0, Qprotodir), 0, QTDIR);
242                         devdir(c, q, f->p[s]->name, 0, network, 0555, dp);
243                         return 1;
244                 }
245                 return ip3gen(c, s+Qconvbase, dp);
246         case Qctl:
247         case Qdata:
248         case Qerr:
249         case Qlisten:
250         case Qlocal:
251         case Qremote:
252         case Qstatus:
253         case Qsnoop:
254                 return ip3gen(c, TYPE(c->qid), dp);
255         }
256         return -1;
257 }
258
259 static void
260 ipinit(void)
261 {
262         qlock_init(&fslock);
263         nullmediumlink();
264         pktmediumlink();
265 /* if only
266         fmtinstall('i', eipfmt);
267         fmtinstall('I', eipfmt);
268         fmtinstall('E', eipfmt);
269         fmtinstall('V', eipfmt);
270         fmtinstall('M', eipfmt);
271 */
272 }
273
274 static void
275 ipreset(void)
276 {
277 }
278
279 static struct Fs*
280 ipgetfs(int dev)
281 {
282         extern void (*ipprotoinit[])(struct Fs*);
283         struct Fs *f;
284         int i;
285
286         if(dev >= Nfs)
287                 return NULL;
288
289         qlock(&fslock);
290         if(ipfs[dev] == NULL){
291                 f = kzmalloc(sizeof(struct Fs), KMALLOC_WAIT);
292                 rwinit(&f->rwlock);
293                 qlock_init(&f->iprouter.qlock);
294                 ip_init(f);
295                 arpinit(f);
296                 netloginit(f);
297                 for(i = 0; ipprotoinit[i]; i++)
298                         ipprotoinit[i](f);
299                 f->dev = dev;
300                 ipfs[dev] = f;
301         }
302         qunlock(&fslock);
303
304         return ipfs[dev];
305 }
306
307 struct IPaux*
308 newipaux(char *owner, char *tag)
309 {
310         struct IPaux *a;
311         int n;
312
313         a = kzmalloc(sizeof(*a), 0);
314         kstrdup(&a->owner, owner);
315         memset(a->tag, ' ', sizeof(a->tag));
316         n = strlen(tag);
317         if(n > sizeof(a->tag))
318                 n = sizeof(a->tag);
319         memmove(a->tag, tag, n);
320         return a;
321 }
322
323 #define ATTACHER(c) (((struct IPaux*)((c)->aux))->owner)
324
325 static struct chan*
326 ipattach(char* spec)
327 {
328         struct chan *c;
329         int dev;
330
331         dev = atoi(spec);
332         if(dev >= Nfs)
333                 error("bad specification");
334
335         ipgetfs(dev);
336         c = devattach('I', spec);
337         mkqid(&c->qid, QID(0, 0, Qtopdir), 0, QTDIR);
338         c->dev = dev;
339
340         c->aux = newipaux(commonuser(), "none");
341
342         return c;
343 }
344
345 static struct walkqid*
346 ipwalk(struct chan* c, struct chan *nc, char **name, int nname)
347 {
348         struct IPaux *a = c->aux;
349         struct walkqid* w;
350
351         w = devwalk(c, nc, name, nname, NULL, 0, ipgen);
352         if(w != NULL && w->clone != NULL)
353                 w->clone->aux = newipaux(a->owner, a->tag);
354         return w;
355 }
356
357 static int
358 ipstat(struct chan* c, uint8_t* db, int n)
359 {
360         return devstat(c, db, n, NULL, 0, ipgen);
361 }
362
363 static int
364 incoming(void* arg)
365 {
366         struct conv *conv;
367
368         conv = arg;
369         return conv->incall != NULL;
370 }
371
372 static int m2p[] = {
373         [OREAD]         4,
374         [OWRITE]        2,
375         [ORDWR]         6
376 };
377
378 static struct chan*
379 ipopen(struct chan* c, int omode)
380 {
381         ERRSTACK(2);
382         struct conv *cv, *nc;
383         struct Proto *p;
384         int perm;
385         struct Fs *f;
386
387         perm = m2p[omode&3];
388
389         f = ipfs[c->dev];
390
391         switch(TYPE(c->qid)) {
392         default:
393                 break;
394         case Qndb:
395                 if(omode & (OWRITE|OTRUNC) && !iseve())
396                         error(Eperm);
397                 if((omode & (OWRITE|OTRUNC)) == (OWRITE|OTRUNC))
398                         f->ndb[0] = 0;
399                 break;
400         case Qlog:
401                 netlogopen(f);
402                 break;
403         case Qiprouter:
404                 iprouteropen(f);
405                 break;
406         case Qiproute:
407                 break;
408         case Qtopdir:
409         case Qprotodir:
410         case Qconvdir:
411         case Qstatus:
412         case Qremote:
413         case Qlocal:
414         case Qstats:
415         case Qbootp:
416         case Qipselftab:
417                 if((omode & OREAD) != OREAD)
418                         error(Eperm);
419                 break;
420         case Qsnoop:
421                 if((omode & OREAD) != OREAD)
422                         error(Eperm);
423                 p = f->p[PROTO(c->qid)];
424                 cv = p->conv[CONV(c->qid)];
425                 if(strcmp(ATTACHER(c), cv->owner) != 0 && !iseve())
426                         error(Eperm);
427                 atomic_inc(&cv->snoopers);
428                 break;
429         case Qclone:
430                 p = f->p[PROTO(c->qid)];
431                 qlock(&p->qlock);
432                 if(waserror()){
433                         qunlock(&p->qlock);
434                         nexterror();
435                 }
436                 cv = Fsprotoclone(p, ATTACHER(c));
437                 qunlock(&p->qlock);
438                 poperror();
439                 if(cv == NULL) {
440                         error(Enodev);
441                         break;
442                 }
443                 mkqid(&c->qid, QID(p->x, cv->x, Qctl), 0, QTFILE);
444                 break;
445         case Qdata:
446         case Qctl:
447         case Qerr:
448                 p = f->p[PROTO(c->qid)];
449                 qlock(&p->qlock);
450                 cv = p->conv[CONV(c->qid)];
451                 qlock(&cv->qlock);
452                 if(waserror()) {
453                         qunlock(&cv->qlock);
454                         qunlock(&p->qlock);
455                         nexterror();
456                 }
457                 if((perm & (cv->perm>>6)) != perm) {
458                         if(strcmp(ATTACHER(c), cv->owner) != 0)
459                                 error(Eperm);
460                         if((perm & cv->perm) != perm)
461                                 error(Eperm); 
462
463                 }
464                 cv->inuse++;
465                 if(cv->inuse == 1){
466                         kstrdup(&cv->owner, ATTACHER(c));
467                         cv->perm = 0660;
468                 }
469                 qunlock(&cv->qlock);
470                 qunlock(&p->qlock);
471                 poperror();
472                 break;
473         case Qlisten:
474                 cv = f->p[PROTO(c->qid)]->conv[CONV(c->qid)];
475                 if((perm & (cv->perm>>6)) != perm) {
476                         if(strcmp(ATTACHER(c), cv->owner) != 0)
477                                 error(Eperm);
478                         if((perm & cv->perm) != perm)
479                                 error(Eperm); 
480
481                 }
482
483                 if(cv->state != Announced)
484                         error("not announced");
485
486                 if(waserror()){
487                         closeconv(cv);
488                         nexterror();
489                 }
490                 qlock(&cv->qlock);
491                 cv->inuse++;
492                 qunlock(&cv->qlock);
493
494                 nc = NULL;
495                 while(nc == NULL) {
496                         /* give up if we got a hangup */
497                         if(qisclosed(cv->rq))
498                                 error("listen hungup");
499
500                         qlock(&cv->listenq);
501                         if(waserror()) {
502                                 qunlock(&cv->listenq);
503                                 nexterror();
504                         }
505
506                         /* wait for a connect */
507                         rendez_sleep(&cv->listenr, incoming, cv);
508
509                         qlock(&cv->qlock);
510                         nc = cv->incall;
511                         if(nc != NULL){
512                                 cv->incall = nc->next;
513                                 mkqid(&c->qid, QID(PROTO(c->qid), nc->x, Qctl), 0, QTFILE);
514                                 kstrdup(&cv->owner, ATTACHER(c));
515                         }
516                         qunlock(&cv->qlock);
517
518                         qunlock(&cv->listenq);
519                         poperror();
520                 }
521                 closeconv(cv);
522                 poperror();
523                 break;
524         }
525         c->mode = openmode(omode);
526         c->flag |= COPEN;
527         c->offset = 0;
528         return c;
529 }
530
531 static int
532 ipwstat(struct chan *c, uint8_t *dp, int n)
533 {
534         ERRSTACK(2);
535         struct dir *d;
536         struct conv *cv;
537         struct Fs *f;
538         struct Proto *p;
539
540         f = ipfs[c->dev];
541         switch(TYPE(c->qid)) {
542         default:
543                 error(Eperm);
544                 break;
545         case Qctl:
546         case Qdata:
547                 break;
548         }
549
550         d = kzmalloc(sizeof(*d) + n, 0);
551         if(waserror()){
552                 kfree(d);
553                 nexterror();
554         }
555         n = convM2D(dp, n, d, ( char *)&d[1]);
556         if(n == 0)
557                 error(Eshortstat);
558         p = f->p[PROTO(c->qid)];
559         cv = p->conv[CONV(c->qid)];
560         if(!iseve() && strcmp(ATTACHER(c), cv->owner) != 0)
561                 error(Eperm);
562         if(!emptystr(d->uid))
563                 kstrdup(&cv->owner, d->uid);
564         if(d->mode != ~0UL)
565                 cv->perm = d->mode & 0777;
566         poperror();
567         kfree(d);
568         return n;
569 }
570
571 static void
572 closeconv(struct conv *cv)
573 {
574         struct conv *nc;
575         struct Ipmulti *mp;
576
577         qlock(&cv->qlock);
578
579         if(--cv->inuse > 0) {
580                 qunlock(&cv->qlock);
581                 return;
582         }
583
584         /* close all incoming calls since no listen will ever happen */
585         for(nc = cv->incall; nc; nc = cv->incall){
586                 cv->incall = nc->next;
587                 closeconv(nc);
588         }
589         cv->incall = NULL;
590
591         kstrdup(&cv->owner, network);
592         cv->perm = 0660;
593
594         while((mp = cv->multi) != NULL)
595                 ipifcremmulti(cv, mp->ma, mp->ia);
596
597         cv->r = NULL;
598         cv->rgen = 0;
599         cv->p->close(cv);
600         cv->state = Idle;
601         qunlock(&cv->qlock);
602 }
603
604 static void
605 ipclose(struct chan* c)
606 {
607         struct Fs *f;
608
609         f = ipfs[c->dev];
610         switch(TYPE(c->qid)) {
611         default:
612                 break;
613         case Qlog:
614                 if(c->flag & COPEN)
615                         netlogclose(f);
616                 break;
617         case Qiprouter:
618                 if(c->flag & COPEN)
619                         iprouterclose(f);
620                 break;
621         case Qdata:
622         case Qctl:
623         case Qerr:
624                 if(c->flag & COPEN)
625                         closeconv(f->p[PROTO(c->qid)]->conv[CONV(c->qid)]);
626                 break;
627         case Qsnoop:
628                 if(c->flag & COPEN)
629                         atomic_dec(&f->p[PROTO(c->qid)]->conv[CONV(c->qid)]->snoopers);
630                 break;
631         }
632         kfree(((struct IPaux*)c->aux)->owner);
633         kfree(c->aux);
634 }
635
636 enum
637 {
638         Statelen=       32*1024,
639 };
640
641 static long
642 ipread(struct chan *ch, void *a, long n, int64_t off)
643 {
644         struct conv *c;
645         struct Proto *x;
646         char *buf, *p;
647         long rv;
648         struct Fs *f;
649         uint32_t offset = off;
650
651         f = ipfs[ch->dev];
652
653         p = a;
654         switch(TYPE(ch->qid)) {
655         default:
656                 error(Eperm);
657         case Qtopdir:
658         case Qprotodir:
659         case Qconvdir:
660                 return devdirread(ch, a, n, 0, 0, ipgen);
661         case Qarp:
662                 return arpread(f->arp, a, offset, n);
663         case Qbootp:
664                 return bootpread(a, offset, n);
665         case Qndb:
666                 return readstr(offset, a, n, f->ndb);
667         case Qiproute:
668                 return routeread(f, a, offset, n);
669         case Qiprouter:
670                 return iprouterread(f, a, n);
671         case Qipselftab:
672                 return ipselftabread(f, a, offset, n);
673         case Qlog:
674                 return netlogread(f, a, offset, n);
675         case Qctl:
676                 snprintf(get_cur_genbuf(), GENBUF_SZ, "%lud", CONV(ch->qid));
677                 return readstr(offset, p, n, get_cur_genbuf());
678         case Qremote:
679                 buf = kzmalloc(Statelen, 0);
680                 x = f->p[PROTO(ch->qid)];
681                 c = x->conv[CONV(ch->qid)];
682                 if(x->remote == NULL) {
683                         snprintf(buf, Statelen, "%I!%d\n", c->raddr, c->rport);
684                 } else {
685                         (*x->remote)(c, buf, Statelen-2);
686                 }
687                 rv = readstr(offset, p, n, buf);
688                 kfree(buf);
689                 return rv;
690         case Qlocal:
691                 buf = kzmalloc(Statelen, 0);
692                 x = f->p[PROTO(ch->qid)];
693                 c = x->conv[CONV(ch->qid)];
694                 if(x->local == NULL) {
695                         snprintf(buf, Statelen, "%I!%d\n", c->laddr, c->lport);
696                 } else {
697                         (*x->local)(c, buf, Statelen-2);
698                 }
699                 rv = readstr(offset, p, n, buf);
700                 kfree(buf);
701                 return rv;
702         case Qstatus:
703                 buf = kzmalloc(Statelen, 0);
704                 x = f->p[PROTO(ch->qid)];
705                 c = x->conv[CONV(ch->qid)];
706                 (*x->state)(c, buf, Statelen-2);
707                 rv = readstr(offset, p, n, buf);
708                 kfree(buf);
709                 return rv;
710         case Qdata:
711                 c = f->p[PROTO(ch->qid)]->conv[CONV(ch->qid)];
712                 return qread(c->rq, a, n);
713         case Qerr:
714                 c = f->p[PROTO(ch->qid)]->conv[CONV(ch->qid)];
715                 return qread(c->eq, a, n);
716         case Qsnoop:
717                 c = f->p[PROTO(ch->qid)]->conv[CONV(ch->qid)];
718                 return qread(c->sq, a, n);
719         case Qstats:
720                 x = f->p[PROTO(ch->qid)];
721                 if(x->stats == NULL)
722                         error("stats not implemented");
723                 buf = kzmalloc(Statelen, 0);
724                 (*x->stats)(x, buf, Statelen);
725                 rv = readstr(offset, p, n, buf);
726                 kfree(buf);
727                 return rv;
728         }
729 }
730
731 static struct block*
732 ipbread(struct chan* ch, long n, uint32_t offset)
733 {
734         struct conv *c;
735         struct Proto *x;
736         struct Fs *f;
737
738         switch(TYPE(ch->qid)){
739         case Qdata:
740                 f = ipfs[ch->dev];
741                 x = f->p[PROTO(ch->qid)];
742                 c = x->conv[CONV(ch->qid)];
743                 return qbread(c->rq, n);
744         default:
745                 return devbread(ch, n, offset);
746         }
747 }
748
749 /*
750  *  set local address to be that of the ifc closest to remote address
751  */
752 static void
753 setladdr(struct conv* c)
754 {
755         findlocalip(c->p->f, c->laddr, c->raddr);
756 }
757
758 /*
759  *  set a local port making sure the quad of raddr,rport,laddr,lport is unique
760  */
761 static char*
762 setluniqueport(struct conv* c, int lport)
763 {
764         struct Proto *p;
765         struct conv *xp;
766         int x;
767
768         p = c->p;
769
770         qlock(&p->qlock);
771         for(x = 0; x < p->nc; x++){
772                 xp = p->conv[x];
773                 if(xp == NULL)
774                         break;
775                 if(xp == c)
776                         continue;
777                 if((xp->state == Connected || xp->state == Announced)
778                 && xp->lport == lport
779                 && xp->rport == c->rport
780                 && ipcmp(xp->raddr, c->raddr) == 0
781                 && ipcmp(xp->laddr, c->laddr) == 0){
782                         qunlock(&p->qlock);
783                         return "address in use";
784                 }
785         }
786         c->lport = lport;
787         qunlock(&p->qlock);
788         return NULL;
789 }
790
791 /*
792  *  pick a local port and set it
793  */
794 static void
795 setlport(struct conv* c)
796 {
797         struct Proto *p;
798         uint16_t *pp;
799         int x, found;
800
801         p = c->p;
802         if(c->restricted)
803                 pp = &p->nextrport;
804         else
805                 pp = &p->nextport;
806         qlock(&p->qlock);
807         for(;;(*pp)++){
808                 /*
809                  * Fsproto initialises p->nextport to 0 and the restricted
810                  * ports (p->nextrport) to 600.
811                  * Restricted ports must lie between 600 and 1024.
812                  * For the initial condition or if the unrestricted port number
813                  * has wrapped round, select a random port between 5000 and 1<<15
814                  * to start at.
815                  */
816                 if(c->restricted){
817                         if(*pp >= 1024)
818                                 *pp = 600;
819                 }
820                 else while(*pp < 5000)
821                         *pp = nrand(1<<15);
822
823                 found = 0;
824                 for(x = 0; x < p->nc; x++){
825                         if(p->conv[x] == NULL)
826                                 break;
827                         if(p->conv[x]->lport == *pp){
828                                 found = 1;
829                                 break;
830                         }
831                 }
832                 if(!found)
833                         break;
834         }
835         c->lport = (*pp)++;
836         qunlock(&p->qlock);
837 }
838
839 /*
840  *  set a local address and port from a string of the form
841  *      [address!]port[!r]
842  */
843 static char*
844 setladdrport(struct conv* c, char* str, int announcing)
845 {
846         char *p;
847         char *rv;
848         uint16_t lport;
849         uint8_t addr[IPaddrlen];
850
851         rv = NULL;
852
853         /*
854          *  ignore restricted part if it exists.  it's
855          *  meaningless on local ports.
856          */
857         p = strchr(str, '!');
858         if(p != NULL){
859                 *p++ = 0;
860                 if(strcmp(p, "r") == 0)
861                         p = NULL;
862         }
863
864         c->lport = 0;
865         if(p == NULL){
866                 if(announcing)
867                         ipmove(c->laddr, IPnoaddr);
868                 else
869                         setladdr(c);
870                 p = str;
871         } else {
872                 if(strcmp(str, "*") == 0)
873                         ipmove(c->laddr, IPnoaddr);
874                 else {
875                         parseip(addr, str);
876                         if(ipforme(c->p->f, addr))
877                                 ipmove(c->laddr, addr);
878                         else
879                                 return "not a local IP address";
880                 }
881         }
882
883         /* one process can get all connections */
884         if(announcing && strcmp(p, "*") == 0){
885                 if(!iseve())
886                         error(Eperm);
887                 return setluniqueport(c, 0);
888         }
889
890         lport = atoi(p);
891         if(lport <= 0)
892                 setlport(c);
893         else
894                 rv = setluniqueport(c, lport);
895         return rv;
896 }
897
898 static char*
899 setraddrport(struct conv* c, char* str)
900 {
901         char *p;
902
903         p = strchr(str, '!');
904         if(p == NULL)
905                 return "malformed address";
906         *p++ = 0;
907         parseip(c->raddr, str);
908         c->rport = atoi(p);
909         p = strchr(p, '!');
910         if(p){
911                 if(strstr(p, "!r") != NULL)
912                         c->restricted = 1;
913         }
914         return NULL;
915 }
916
917 /*
918  *  called by protocol connect routine to set addresses
919  */
920 char*
921 Fsstdconnect(struct conv *c, char *argv[], int argc)
922 {
923         char *p;
924
925         switch(argc) {
926         default:
927                 return "bad args to connect";
928         case 2:
929                 p = setraddrport(c, argv[1]);
930                 if(p != NULL)
931                         return p;
932                 setladdr(c);
933                 setlport(c);
934                 break;
935         case 3:
936                 p = setraddrport(c, argv[1]);
937                 if(p != NULL)
938                         return p;
939                 p = setladdrport(c, argv[2], 0);
940                 if(p != NULL)
941                         return p;
942         }
943
944         if((memcmp(c->raddr, v4prefix, IPv4off) == 0 &&
945                 memcmp(c->laddr, v4prefix, IPv4off) == 0)
946                 || ipcmp(c->raddr, IPnoaddr) == 0)
947                 c->ipversion = V4;
948         else
949                 c->ipversion = V6;
950
951         return NULL;
952 }
953 /*
954  *  initiate connection and sleep till its set up
955  */
956 static int
957 connected(void* a)
958 {
959         return ((struct conv*)a)->state == Connected;
960 }
961 static void
962 connectctlmsg(struct Proto *x, struct conv *c, struct cmdbuf *cb)
963 {
964         ERRSTACK(1);
965         char *p;
966
967         if(c->state != 0)
968                 error(Econinuse);
969         c->state = Connecting;
970         c->cerr[0] = '\0';
971         if(x->connect == NULL)
972                 error("connect not supported");
973         p = x->connect(c, cb->f, cb->nf);
974         if(p != NULL)
975                 error(p);
976
977         qunlock(&c->qlock);
978         if(waserror()){
979                 qlock(&c->qlock);
980                 nexterror();
981         }
982         rendez_sleep(&c->cr, connected, c);
983         qlock(&c->qlock);
984         poperror();
985
986         if(c->cerr[0] != '\0')
987                 error(c->cerr);
988 }
989
990 /*
991  *  called by protocol announce routine to set addresses
992  */
993 char*
994 Fsstdannounce(struct conv* c, char* argv[], int argc)
995 {
996         memset(c->raddr, 0, sizeof(c->raddr));
997         c->rport = 0;
998         switch(argc){
999         default:
1000                 return "bad args to announce";
1001         case 2:
1002                 return setladdrport(c, argv[1], 1);
1003         }
1004 }
1005
1006 /*
1007  *  initiate announcement and sleep till its set up
1008  */
1009 static int
1010 announced(void* a)
1011 {
1012         return ((struct conv*)a)->state == Announced;
1013 }
1014 static void
1015 announcectlmsg(struct Proto *x, struct conv *c, struct cmdbuf *cb)
1016 {
1017         ERRSTACK(1);
1018         char *p;
1019
1020         if(c->state != 0)
1021                 error(Econinuse);
1022         c->state = Announcing;
1023         c->cerr[0] = '\0';
1024         if(x->announce == NULL)
1025                 error("announce not supported");
1026         p = x->announce(c, cb->f, cb->nf);
1027         if(p != NULL)
1028                 error(p);
1029
1030         qunlock(&c->qlock);
1031         if(waserror()){
1032                 qlock(&c->qlock);
1033                 nexterror();
1034         }
1035         rendez_sleep(&c->cr, announced, c);
1036         qlock(&c->qlock);
1037         poperror();
1038
1039         if(c->cerr[0] != '\0')
1040                 error(c->cerr);
1041 }
1042
1043 /*
1044  *  called by protocol bind routine to set addresses
1045  */
1046 char*
1047 Fsstdbind(struct conv* c, char* argv[], int argc)
1048 {
1049         switch(argc){
1050         default:
1051                 return "bad args to bind";
1052         case 2:
1053                 return setladdrport(c, argv[1], 0);
1054         }
1055 }
1056
1057 static void
1058 bindctlmsg(struct Proto *x, struct conv *c, struct cmdbuf *cb)
1059 {
1060         char *p;
1061
1062         if(x->bind == NULL)
1063                 p = Fsstdbind(c, cb->f, cb->nf);
1064         else
1065                 p = x->bind(c, cb->f, cb->nf);
1066         if(p != NULL)
1067                 error(p);
1068 }
1069
1070 static void
1071 tosctlmsg(struct conv *c, struct cmdbuf *cb)
1072 {
1073         if(cb->nf < 2)
1074                 c->tos = 0;
1075         else
1076                 c->tos = atoi(cb->f[1]);
1077 }
1078
1079 static void
1080 ttlctlmsg(struct conv *c, struct cmdbuf *cb)
1081 {
1082         if(cb->nf < 2)
1083                 c->ttl = MAXTTL;
1084         else
1085                 c->ttl = atoi(cb->f[1]);
1086 }
1087
1088 static long
1089 ipwrite(struct chan* ch, void *v, long n, int64_t off)
1090 {
1091         ERRSTACK(1);
1092         struct conv *c;
1093         struct Proto *x;
1094         char *p;
1095         struct cmdbuf *cb;
1096         uint8_t ia[IPaddrlen], ma[IPaddrlen];
1097         struct Fs *f;
1098         char *a;
1099
1100         a = v;
1101         f = ipfs[ch->dev];
1102
1103         switch(TYPE(ch->qid)){
1104         default:
1105                 error(Eperm);
1106         case Qdata:
1107                 x = f->p[PROTO(ch->qid)];
1108                 c = x->conv[CONV(ch->qid)];
1109
1110                 if(c->wq == NULL)
1111                         error(Eperm);
1112
1113                 qwrite(c->wq, a, n);
1114                 break;
1115         case Qarp:
1116                 return arpwrite(f, a, n);
1117         case Qiproute:
1118                 return routewrite(f, ch, a, n);
1119         case Qlog:
1120                 netlogctl(f, a, n);
1121                 return n;
1122         case Qndb:
1123                 return ndbwrite(f, a, off, n);
1124         case Qctl:
1125                 x = f->p[PROTO(ch->qid)];
1126                 c = x->conv[CONV(ch->qid)];
1127                 cb = parsecmd(a, n);
1128
1129                 qlock(&c->qlock);
1130                 if(waserror()) {
1131                         qunlock(&c->qlock);
1132                         kfree(cb);
1133                         nexterror();
1134                 }
1135                 if(cb->nf < 1)
1136                         error("short control request");
1137                 if(strcmp(cb->f[0], "connect") == 0)
1138                         connectctlmsg(x, c, cb);
1139                 else if(strcmp(cb->f[0], "announce") == 0)
1140                         announcectlmsg(x, c, cb);
1141                 else if(strcmp(cb->f[0], "bind") == 0)
1142                         bindctlmsg(x, c, cb);
1143                 else if(strcmp(cb->f[0], "ttl") == 0)
1144                         ttlctlmsg(c, cb);
1145                 else if(strcmp(cb->f[0], "tos") == 0)
1146                         tosctlmsg(c, cb);
1147                 else if(strcmp(cb->f[0], "ignoreadvice") == 0)
1148                         c->ignoreadvice = 1;
1149                 else if(strcmp(cb->f[0], "addmulti") == 0){
1150                         if(cb->nf < 2)
1151                                 error("addmulti needs interface address");
1152                         if(cb->nf == 2){
1153                                 if(!ipismulticast(c->raddr))
1154                                         error("addmulti for a non multicast address");
1155                                 parseip(ia, cb->f[1]);
1156                                 ipifcaddmulti(c, c->raddr, ia);
1157                         } else {
1158                                 parseip(ma, cb->f[2]);
1159                                 if(!ipismulticast(ma))
1160                                         error("addmulti for a non multicast address");
1161                                 parseip(ia, cb->f[1]);
1162                                 ipifcaddmulti(c, ma, ia);
1163                         }
1164                 } else if(strcmp(cb->f[0], "remmulti") == 0){
1165                         if(cb->nf < 2)
1166                                 error("remmulti needs interface address");
1167                         if(!ipismulticast(c->raddr))
1168                                 error("remmulti for a non multicast address");
1169                         parseip(ia, cb->f[1]);
1170                         ipifcremmulti(c, c->raddr, ia);
1171                 } else if(x->ctl != NULL) {
1172                         p = x->ctl(c, cb->f, cb->nf);
1173                         if(p != NULL)
1174                                 error(p);
1175                 } else
1176                         error("unknown control request");
1177                 qunlock(&c->qlock);
1178                 kfree(cb);
1179                 poperror();
1180         }
1181         return n;
1182 }
1183
1184 static long
1185 ipbwrite(struct chan* ch, struct block* bp, uint32_t offset)
1186 {
1187         struct conv *c;
1188         struct Proto *x;
1189         struct Fs *f;
1190         int n;
1191
1192         switch(TYPE(ch->qid)){
1193         case Qdata:
1194                 f = ipfs[ch->dev];
1195                 x = f->p[PROTO(ch->qid)];
1196                 c = x->conv[CONV(ch->qid)];
1197
1198                 if(c->wq == NULL)
1199                         error(Eperm);
1200
1201                 if(bp->next)
1202                         bp = concatblock(bp);
1203                 n = BLEN(bp);
1204                 qbwrite(c->wq, bp);
1205                 return n;
1206         default:
1207                 return devbwrite(ch, bp, offset);
1208         }
1209 }
1210
1211 struct dev ipdevtab __devtab = {
1212         'I',
1213         "ip",
1214
1215         ipreset,
1216         ipinit,
1217         devshutdown,
1218         ipattach,
1219         ipwalk,
1220         ipstat,
1221         ipopen,
1222         devcreate,
1223         ipclose,
1224         ipread,
1225         ipbread,
1226         ipwrite,
1227         ipbwrite,
1228         devremove,
1229         ipwstat,
1230 };
1231
1232 int
1233 Fsproto(struct Fs *f, struct Proto *p)
1234 {
1235         if(f->np >= Maxproto)
1236                 return -1;
1237
1238         qlock_init(&p->qlock);
1239         p->f = f;
1240
1241         if(p->ipproto > 0){
1242                 if(f->t2p[p->ipproto] != NULL)
1243                         return -1;
1244                 f->t2p[p->ipproto] = p;
1245         }
1246
1247         p->qid.type = QTDIR;
1248         p->qid.path = QID(f->np, 0, Qprotodir);
1249         p->conv = kzmalloc(sizeof(struct conv *) * (p->nc + 1), 0);
1250         if(p->conv == NULL)
1251                 panic("Fsproto");
1252
1253         p->x = f->np;
1254         p->nextport = 0;
1255         p->nextrport = 600;
1256         f->p[f->np++] = p;
1257
1258         return 0;
1259 }
1260
1261 /*
1262  *  return true if this protocol is
1263  *  built in
1264  */
1265 int
1266 Fsbuiltinproto(struct Fs* f, uint8_t proto)
1267 {
1268         return f->t2p[proto] != NULL;
1269 }
1270
1271 /*
1272  *  called with protocol locked
1273  */
1274 struct conv*
1275 Fsprotoclone(struct Proto *p, char *user)
1276 {
1277         struct conv *c, **pp, **ep;
1278
1279 retry:
1280         c = NULL;
1281         ep = &p->conv[p->nc];
1282         for(pp = p->conv; pp < ep; pp++) {
1283                 c = *pp;
1284                 if(c == NULL){
1285                         c = kzmalloc(sizeof(struct conv), 0);
1286                         if(c == NULL)
1287                                 error(Enomem);
1288                         qlock_init(&c->qlock);
1289                         qlock_init(&c->listenq);
1290                         rendez_init(&c->cr);
1291                         rendez_init(&c->listenr);
1292                         qlock(&c->qlock);
1293                         c->p = p;
1294                         c->x = pp - p->conv;
1295                         if(p->ptclsize != 0){
1296                                 c->ptcl = kzmalloc(p->ptclsize, 0);
1297                                 if(c->ptcl == NULL) {
1298                                         kfree(c);
1299                                         error(Enomem);
1300                                 }
1301                         }
1302                         *pp = c;
1303                         p->ac++;
1304                         c->eq = qopen(1024, Qmsg, 0, 0);
1305                         (*p->create)(c);
1306                         break;
1307                 }
1308                 if(canqlock(&c->qlock)){
1309                         /*
1310                          *  make sure both processes and protocol
1311                          *  are done with this Conv
1312                          */
1313                         if(c->inuse == 0 && (p->inuse == NULL || (*p->inuse)(c) == 0))
1314                                 break;
1315
1316                         qunlock(&c->qlock);
1317                 }
1318         }
1319         if(pp >= ep) {
1320                 if(p->gc != NULL && (*p->gc)(p))
1321                         goto retry;
1322                 return NULL;
1323         }
1324
1325         c->inuse = 1;
1326         kstrdup(&c->owner, user);
1327         c->perm = 0660;
1328         c->state = Idle;
1329         ipmove(c->laddr, IPnoaddr);
1330         ipmove(c->raddr, IPnoaddr);
1331         c->r = NULL;
1332         c->rgen = 0;
1333         c->lport = 0;
1334         c->rport = 0;
1335         c->restricted = 0;
1336         c->ttl = MAXTTL;
1337         c->tos = DFLTTOS;
1338         qreopen(c->rq);
1339         qreopen(c->wq);
1340         qreopen(c->eq);
1341
1342         qunlock(&c->qlock);
1343         return c;
1344 }
1345
1346 int
1347 Fsconnected(struct conv* c, char* msg)
1348 {
1349         if(msg != NULL && *msg != '\0')
1350                 strncpy(c->cerr, msg, sizeof(c->cerr));
1351
1352         switch(c->state){
1353
1354         case Announcing:
1355                 c->state = Announced;
1356                 break;
1357
1358         case Connecting:
1359                 c->state = Connected;
1360                 break;
1361         }
1362
1363         rendez_wakeup(&c->cr);
1364         return 0;
1365 }
1366
1367 struct Proto*
1368 Fsrcvpcol(struct Fs* f, uint8_t proto)
1369 {
1370         if(f->ipmux)
1371                 return f->ipmux;
1372         else
1373                 return f->t2p[proto];
1374 }
1375
1376 struct Proto*
1377 Fsrcvpcolx(struct Fs *f, uint8_t proto)
1378 {
1379         return f->t2p[proto];
1380 }
1381
1382 /*
1383  *  called with protocol locked
1384  */
1385 struct conv*
1386 Fsnewcall(struct conv *c, uint8_t *raddr, uint16_t rport, uint8_t *laddr,
1387           uint16_t lport, uint8_t version)
1388 {
1389         struct conv *nc;
1390         struct conv **l;
1391         int i;
1392
1393         qlock(&c->qlock);
1394         i = 0;
1395         for(l = &c->incall; *l; l = &(*l)->next)
1396                 i++;
1397         if(i >= Maxincall) {
1398                 qunlock(&c->qlock);
1399                 return NULL;
1400         }
1401
1402         /* find a free conversation */
1403         nc = Fsprotoclone(c->p, network);
1404         if(nc == NULL) {
1405                 qunlock(&c->qlock);
1406                 return NULL;
1407         }
1408         ipmove(nc->raddr, raddr);
1409         nc->rport = rport;
1410         ipmove(nc->laddr, laddr);
1411         nc->lport = lport;
1412         nc->next = NULL;
1413         *l = nc;
1414         nc->state = Connected;
1415         nc->ipversion = version;
1416
1417         qunlock(&c->qlock);
1418
1419         rendez_wakeup(&c->listenr);
1420
1421         return nc;
1422 }
1423
1424 static long
1425 ndbwrite(struct Fs *f, char *a, uint32_t off, int n)
1426 {
1427         if(off > strlen(f->ndb))
1428                 error(Eio);
1429         if(off+n >= sizeof(f->ndb)-1)
1430                 error(Eio);
1431         memmove(f->ndb+off, a, n);
1432         f->ndb[off+n] = 0;
1433         f->ndbvers++;
1434         f->ndbmtime = seconds();
1435         return n;
1436 }
1437
1438 uint32_t
1439 scalednconv(void)
1440 {
1441         //if(conf.npage*BY2PG >= 128*MB)
1442                 return Nchans*4;
1443                 //      return Nchans;
1444 }