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