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