FreeBSD/Linux Kernel Cross Reference
sys/ip/devip.c
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
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
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
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
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 sprint(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 sprint(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 sprint(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
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*
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*
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*
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*
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
337 ipstat(Chan* c, uchar* db, int n)
338 {
339 return devstat(c, db, n, nil, 0, ipgen);
340 }
341
342 static int
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*
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
510 ipcreate(Chan*, char*, int, ulong)
511 {
512 error(Eperm);
513 }
514
515 static void
516 ipremove(Chan*)
517 {
518 error(Eperm);
519 }
520
521 static int
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
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
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
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 sprint(buf, "%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 sprint(buf, "%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 sprint(buf, "%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*
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
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*
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
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 *
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 return "no ports available";
822
823 chosen:
824 c->lport = port;
825 qunlock(p);
826 return nil;
827 }
828
829 /*
830 * set a local address and port from a string of the form
831 * [address!]port[!r]
832 */
833 char*
834 setladdrport(Conv* c, char* str, int announcing)
835 {
836 char *p;
837 char *rv;
838 ushort lport;
839 uchar addr[IPaddrlen];
840
841 /*
842 * ignore restricted part if it exists. it's
843 * meaningless on local ports.
844 */
845 p = strchr(str, '!');
846 if(p != nil){
847 *p++ = 0;
848 if(strcmp(p, "r") == 0)
849 p = nil;
850 }
851
852 c->lport = 0;
853 if(p == nil){
854 if(announcing)
855 ipmove(c->laddr, IPnoaddr);
856 else
857 setladdr(c);
858 p = str;
859 } else {
860 if(strcmp(str, "*") == 0)
861 ipmove(c->laddr, IPnoaddr);
862 else {
863 if(parseip(addr, str) == -1)
864 return Ebadip;
865 if(ipforme(c->p->f, addr))
866 ipmove(c->laddr, addr);
867 else
868 return "not a local IP address";
869 }
870 }
871
872 /* one process can get all connections */
873 if(announcing && strcmp(p, "*") == 0){
874 if(!iseve())
875 error(Eperm);
876 return setluniqueport(c, 0);
877 }
878
879 lport = atoi(p);
880 if(lport <= 0)
881 rv = setlport(c);
882 else
883 rv = setluniqueport(c, lport);
884 return rv;
885 }
886
887 static char*
888 setraddrport(Conv* c, char* str)
889 {
890 char *p;
891
892 p = strchr(str, '!');
893 if(p == nil)
894 return "malformed address";
895 *p++ = 0;
896 if (parseip(c->raddr, str) == -1)
897 return Ebadip;
898 c->rport = atoi(p);
899 p = strchr(p, '!');
900 if(p){
901 if(strstr(p, "!r") != nil)
902 c->restricted = 1;
903 }
904 return nil;
905 }
906
907 /*
908 * called by protocol connect routine to set addresses
909 */
910 char*
911 Fsstdconnect(Conv *c, char *argv[], int argc)
912 {
913 char *p;
914
915 switch(argc) {
916 default:
917 return "bad args to connect";
918 case 2:
919 p = setraddrport(c, argv[1]);
920 if(p != nil)
921 return p;
922 setladdr(c);
923 p = setlport(c);
924 if (p != nil)
925 return p;
926 break;
927 case 3:
928 p = setraddrport(c, argv[1]);
929 if(p != nil)
930 return p;
931 p = setladdrport(c, argv[2], 0);
932 if(p != nil)
933 return p;
934 }
935
936 if( (memcmp(c->raddr, v4prefix, IPv4off) == 0 &&
937 memcmp(c->laddr, v4prefix, IPv4off) == 0)
938 || ipcmp(c->raddr, IPnoaddr) == 0)
939 c->ipversion = V4;
940 else
941 c->ipversion = V6;
942
943 return nil;
944 }
945 /*
946 * initiate connection and sleep till its set up
947 */
948 static int
949 connected(void* a)
950 {
951 return ((Conv*)a)->state == Connected;
952 }
953 static void
954 connectctlmsg(Proto *x, Conv *c, Cmdbuf *cb)
955 {
956 char *p;
957
958 if(c->state != 0)
959 error(Econinuse);
960 c->state = Connecting;
961 c->cerr[0] = '\0';
962 if(x->connect == nil)
963 error("connect not supported");
964 p = x->connect(c, cb->f, cb->nf);
965 if(p != nil)
966 error(p);
967
968 qunlock(c);
969 if(waserror()){
970 qlock(c);
971 nexterror();
972 }
973 sleep(&c->cr, connected, c);
974 qlock(c);
975 poperror();
976
977 if(c->cerr[0] != '\0')
978 error(c->cerr);
979 }
980
981 /*
982 * called by protocol announce routine to set addresses
983 */
984 char*
985 Fsstdannounce(Conv* c, char* argv[], int argc)
986 {
987 memset(c->raddr, 0, sizeof(c->raddr));
988 c->rport = 0;
989 switch(argc){
990 default:
991 break;
992 case 2:
993 return setladdrport(c, argv[1], 1);
994 }
995 return "bad args to announce";
996 }
997
998 /*
999 * initiate announcement and sleep till its set up
1000 */
1001 static int
1002 announced(void* a)
1003 {
1004 return ((Conv*)a)->state == Announced;
1005 }
1006 static void
1007 announcectlmsg(Proto *x, Conv *c, Cmdbuf *cb)
1008 {
1009 char *p;
1010
1011 if(c->state != 0)
1012 error(Econinuse);
1013 c->state = Announcing;
1014 c->cerr[0] = '\0';
1015 if(x->announce == nil)
1016 error("announce not supported");
1017 p = x->announce(c, cb->f, cb->nf);
1018 if(p != nil)
1019 error(p);
1020
1021 qunlock(c);
1022 if(waserror()){
1023 qlock(c);
1024 nexterror();
1025 }
1026 sleep(&c->cr, announced, c);
1027 qlock(c);
1028 poperror();
1029
1030 if(c->cerr[0] != '\0')
1031 error(c->cerr);
1032 }
1033
1034 /*
1035 * called by protocol bind routine to set addresses
1036 */
1037 char*
1038 Fsstdbind(Conv* c, char* argv[], int argc)
1039 {
1040 switch(argc){
1041 default:
1042 break;
1043 case 2:
1044 return setladdrport(c, argv[1], 0);
1045 }
1046 return "bad args to bind";
1047 }
1048
1049 static void
1050 bindctlmsg(Proto *x, Conv *c, Cmdbuf *cb)
1051 {
1052 char *p;
1053
1054 if(x->bind == nil)
1055 p = Fsstdbind(c, cb->f, cb->nf);
1056 else
1057 p = x->bind(c, cb->f, cb->nf);
1058 if(p != nil)
1059 error(p);
1060 }
1061
1062 static void
1063 tosctlmsg(Conv *c, Cmdbuf *cb)
1064 {
1065 if(cb->nf < 2)
1066 c->tos = 0;
1067 else
1068 c->tos = atoi(cb->f[1]);
1069 }
1070
1071 static void
1072 ttlctlmsg(Conv *c, Cmdbuf *cb)
1073 {
1074 if(cb->nf < 2)
1075 c->ttl = MAXTTL;
1076 else
1077 c->ttl = atoi(cb->f[1]);
1078 }
1079
1080 static long
1081 ipwrite(Chan* ch, void *v, long n, vlong off)
1082 {
1083 Conv *c;
1084 Proto *x;
1085 char *p;
1086 Cmdbuf *cb;
1087 uchar ia[IPaddrlen], ma[IPaddrlen];
1088 Fs *f;
1089 char *a;
1090 ulong offset = off;
1091
1092 a = v;
1093 f = ipfs[ch->dev];
1094
1095 switch(TYPE(ch->qid)){
1096 default:
1097 error(Eperm);
1098 case Qdata:
1099 x = f->p[PROTO(ch->qid)];
1100 c = x->conv[CONV(ch->qid)];
1101
1102 if(c->wq == nil)
1103 error(Eperm);
1104
1105 qwrite(c->wq, a, n);
1106 break;
1107 case Qarp:
1108 return arpwrite(f, a, n);
1109 case Qiproute:
1110 return routewrite(f, ch, a, n);
1111 case Qlog:
1112 netlogctl(f, a, n);
1113 return n;
1114 case Qndb:
1115 return ndbwrite(f, a, offset, n);
1116 break;
1117 case Qctl:
1118 x = f->p[PROTO(ch->qid)];
1119 c = x->conv[CONV(ch->qid)];
1120 cb = parsecmd(a, n);
1121
1122 qlock(c);
1123 if(waserror()) {
1124 qunlock(c);
1125 free(cb);
1126 nexterror();
1127 }
1128 if(cb->nf < 1)
1129 error("short control request");
1130 if(strcmp(cb->f[0], "connect") == 0)
1131 connectctlmsg(x, c, cb);
1132 else if(strcmp(cb->f[0], "announce") == 0)
1133 announcectlmsg(x, c, cb);
1134 else if(strcmp(cb->f[0], "bind") == 0)
1135 bindctlmsg(x, c, cb);
1136 else if(strcmp(cb->f[0], "ttl") == 0)
1137 ttlctlmsg(c, cb);
1138 else if(strcmp(cb->f[0], "tos") == 0)
1139 tosctlmsg(c, cb);
1140 else if(strcmp(cb->f[0], "ignoreadvice") == 0)
1141 c->ignoreadvice = 1;
1142 else if(strcmp(cb->f[0], "addmulti") == 0){
1143 if(cb->nf < 2)
1144 error("addmulti needs interface address");
1145 if(cb->nf == 2){
1146 if(!ipismulticast(c->raddr))
1147 error("addmulti for a non multicast address");
1148 if (parseip(ia, cb->f[1]) == -1)
1149 error(Ebadip);
1150 ipifcaddmulti(c, c->raddr, ia);
1151 } else {
1152 if (parseip(ia, cb->f[1]) == -1 ||
1153 parseip(ma, cb->f[2]) == -1)
1154 error(Ebadip);
1155 if(!ipismulticast(ma))
1156 error("addmulti for a non multicast address");
1157 ipifcaddmulti(c, ma, ia);
1158 }
1159 } else if(strcmp(cb->f[0], "remmulti") == 0){
1160 if(cb->nf < 2)
1161 error("remmulti needs interface address");
1162 if(!ipismulticast(c->raddr))
1163 error("remmulti for a non multicast address");
1164 if (parseip(ia, cb->f[1]) == -1)
1165 error(Ebadip);
1166 ipifcremmulti(c, c->raddr, ia);
1167 } else if(strcmp(cb->f[0], "maxfragsize") == 0){
1168 if(cb->nf < 2)
1169 error("maxfragsize needs size");
1170
1171 c->maxfragsize = (int)strtol(cb->f[1], nil, 0);
1172
1173 } else if(x->ctl != nil) {
1174 p = x->ctl(c, cb->f, cb->nf);
1175 if(p != nil)
1176 error(p);
1177 } else
1178 error("unknown control request");
1179 qunlock(c);
1180 free(cb);
1181 poperror();
1182 }
1183 return n;
1184 }
1185
1186 static long
1187 ipbwrite(Chan* ch, Block* bp, ulong offset)
1188 {
1189 Conv *c;
1190 Proto *x;
1191 Fs *f;
1192 int n;
1193
1194 switch(TYPE(ch->qid)){
1195 case Qdata:
1196 f = ipfs[ch->dev];
1197 x = f->p[PROTO(ch->qid)];
1198 c = x->conv[CONV(ch->qid)];
1199
1200 if(c->wq == nil)
1201 error(Eperm);
1202
1203 if(bp->next)
1204 bp = concatblock(bp);
1205 n = BLEN(bp);
1206 qbwrite(c->wq, bp);
1207 return n;
1208 default:
1209 return devbwrite(ch, bp, offset);
1210 }
1211 }
1212
1213 Dev ipdevtab = {
1214 'I',
1215 "ip",
1216
1217 ipreset,
1218 devinit,
1219 devshutdown,
1220 ipattach,
1221 ipwalk,
1222 ipstat,
1223 ipopen,
1224 ipcreate,
1225 ipclose,
1226 ipread,
1227 ipbread,
1228 ipwrite,
1229 ipbwrite,
1230 ipremove,
1231 ipwstat,
1232 };
1233
1234 int
1235 Fsproto(Fs *f, Proto *p)
1236 {
1237 if(f->np >= Maxproto)
1238 return -1;
1239
1240 p->f = f;
1241
1242 if(p->ipproto > 0){
1243 if(f->t2p[p->ipproto] != nil)
1244 return -1;
1245 f->t2p[p->ipproto] = p;
1246 }
1247
1248 p->qid.type = QTDIR;
1249 p->qid.path = QID(f->np, 0, Qprotodir);
1250 p->conv = malloc(sizeof(Conv*)*(p->nc+1));
1251 if(p->conv == nil)
1252 panic("Fsproto");
1253
1254 p->x = f->np;
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(Fs* f, uchar proto)
1267 {
1268 return f->t2p[proto] != nil;
1269 }
1270
1271 /*
1272 * called with protocol locked
1273 */
1274 Conv*
1275 Fsprotoclone(Proto *p, char *user)
1276 {
1277 Conv *c, **pp, **ep;
1278
1279 retry:
1280 c = nil;
1281 ep = &p->conv[p->nc];
1282 for(pp = p->conv; pp < ep; pp++) {
1283 c = *pp;
1284 if(c == nil){
1285 c = malloc(sizeof(Conv));
1286 if(c == nil)
1287 error(Enomem);
1288 qlock(c);
1289 c->p = p;
1290 c->x = pp - p->conv;
1291 if(p->ptclsize != 0){
1292 c->ptcl = malloc(p->ptclsize);
1293 if(c->ptcl == nil) {
1294 free(c);
1295 error(Enomem);
1296 }
1297 }
1298 *pp = c;
1299 p->ac++;
1300 c->eq = qopen(1024, Qmsg, 0, 0);
1301 (*p->create)(c);
1302 break;
1303 }
1304 if(canqlock(c)){
1305 /*
1306 * make sure both processes and protocol
1307 * are done with this Conv
1308 */
1309 if(c->inuse == 0 && (p->inuse == nil || (*p->inuse)(c) == 0))
1310 break;
1311
1312 qunlock(c);
1313 }
1314 }
1315 if(pp >= ep) {
1316 if(p->gc != nil && (*p->gc)(p))
1317 goto retry;
1318 return nil;
1319 }
1320
1321 c->inuse = 1;
1322 kstrdup(&c->owner, user);
1323 c->perm = 0660;
1324 c->state = Idle;
1325 ipmove(c->laddr, IPnoaddr);
1326 ipmove(c->raddr, IPnoaddr);
1327 c->r = nil;
1328 c->rgen = 0;
1329 c->lport = 0;
1330 c->rport = 0;
1331 c->restricted = 0;
1332 c->maxfragsize = 0;
1333 c->ttl = MAXTTL;
1334 qreopen(c->rq);
1335 qreopen(c->wq);
1336 qreopen(c->eq);
1337
1338 qunlock(c);
1339 return c;
1340 }
1341
1342 int
1343 Fsconnected(Conv* c, char* msg)
1344 {
1345 if(msg != nil && *msg != '\0')
1346 strncpy(c->cerr, msg, ERRMAX-1);
1347
1348 switch(c->state){
1349
1350 case Announcing:
1351 c->state = Announced;
1352 break;
1353
1354 case Connecting:
1355 c->state = Connected;
1356 break;
1357 }
1358
1359 wakeup(&c->cr);
1360 return 0;
1361 }
1362
1363 Proto*
1364 Fsrcvpcol(Fs* f, uchar proto)
1365 {
1366 if(f->ipmux)
1367 return f->ipmux;
1368 else
1369 return f->t2p[proto];
1370 }
1371
1372 Proto*
1373 Fsrcvpcolx(Fs *f, uchar proto)
1374 {
1375 return f->t2p[proto];
1376 }
1377
1378 /*
1379 * called with protocol locked
1380 */
1381 Conv*
1382 Fsnewcall(Conv *c, uchar *raddr, ushort rport, uchar *laddr, ushort lport, uchar version)
1383 {
1384 Conv *nc;
1385 Conv **l;
1386 int i;
1387
1388 qlock(c);
1389 i = 0;
1390 for(l = &c->incall; *l; l = &(*l)->next)
1391 i++;
1392 if(i >= Maxincall) {
1393 qunlock(c);
1394 return nil;
1395 }
1396
1397 /* find a free conversation */
1398 nc = Fsprotoclone(c->p, network);
1399 if(nc == nil) {
1400 qunlock(c);
1401 return nil;
1402 }
1403 ipmove(nc->raddr, raddr);
1404 nc->rport = rport;
1405 ipmove(nc->laddr, laddr);
1406 nc->lport = lport;
1407 nc->next = nil;
1408 *l = nc;
1409 nc->state = Connected;
1410 nc->ipversion = version;
1411
1412 qunlock(c);
1413
1414 wakeup(&c->listenr);
1415
1416 return nc;
1417 }
1418
1419 long
1420 ndbwrite(Fs *f, char *a, ulong off, int n)
1421 {
1422 if(off > strlen(f->ndb))
1423 error(Eio);
1424 if(off+n >= sizeof(f->ndb))
1425 error(Eio);
1426 memmove(f->ndb+off, a, n);
1427 f->ndb[off+n] = 0;
1428 f->ndbvers++;
1429 f->ndbmtime = seconds();
1430 return n;
1431 }
1432
1433 ulong
1434 scalednconv(void)
1435 {
1436 if(cpuserver && conf.npage*BY2PG >= 128*MB)
1437 return Nchans*4;
1438 return Nchans;
1439 }
Cache object: e3daaabe0dca6d2ae48e1bb8fd47c64b
|