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