xref: /inferno-os/os/ip/devip.c (revision 6e425a9de8c003b5a733621a6b6730ec3cc902b8)
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 	return nil;
986 }
987 
988 /*
989  *  initiate announcement and sleep till its set up
990  */
991 static int
992 announced(void* a)
993 {
994 	return ((Conv*)a)->state == Announced;
995 }
996 static void
997 announcectlmsg(Proto *x, Conv *c, Cmdbuf *cb)
998 {
999 	char *p;
1000 
1001 	if(c->state != 0)
1002 		error(Econinuse);
1003 	c->state = Announcing;
1004 	c->cerr[0] = '\0';
1005 	if(x->announce == nil)
1006 		error("announce not supported");
1007 	p = x->announce(c, cb->f, cb->nf);
1008 	if(p != nil)
1009 		error(p);
1010 
1011 	qunlock(c);
1012 	if(waserror()){
1013 		qlock(c);
1014 		nexterror();
1015 	}
1016 	sleep(&c->cr, announced, c);
1017 	qlock(c);
1018 	poperror();
1019 
1020 	if(c->cerr[0] != '\0')
1021 		error(c->cerr);
1022 }
1023 
1024 /*
1025  *  called by protocol bind routine to set addresses
1026  */
1027 char*
1028 Fsstdbind(Conv* c, char* argv[], int argc)
1029 {
1030 	switch(argc){
1031 	default:
1032 		return "bad args to bind";
1033 	case 2:
1034 		return setladdrport(c, argv[1], 0);
1035 	}
1036 	return nil;
1037 }
1038 
1039 static void
1040 bindctlmsg(Proto *x, Conv *c, Cmdbuf *cb)
1041 {
1042 	char *p;
1043 
1044 	if(x->bind == nil)
1045 		p = Fsstdbind(c, cb->f, cb->nf);
1046 	else
1047 		p = x->bind(c, cb->f, cb->nf);
1048 	if(p != nil)
1049 		error(p);
1050 }
1051 
1052 static void
1053 tosctlmsg(Conv *c, Cmdbuf *cb)
1054 {
1055 	if(cb->nf < 2)
1056 		c->tos = 0;
1057 	else
1058 		c->tos = atoi(cb->f[1]);
1059 }
1060 
1061 static void
1062 ttlctlmsg(Conv *c, Cmdbuf *cb)
1063 {
1064 	if(cb->nf < 2)
1065 		c->ttl = MAXTTL;
1066 	else
1067 		c->ttl = atoi(cb->f[1]);
1068 }
1069 
1070 static long
1071 ipwrite(Chan* ch, void *v, long n, vlong off)
1072 {
1073 	Conv *c;
1074 	Proto *x;
1075 	char *p;
1076 	Cmdbuf *cb;
1077 	uchar ia[IPaddrlen], ma[IPaddrlen];
1078 	Fs *f;
1079 	char *a;
1080 
1081 	a = v;
1082 	f = ipfs[ch->dev];
1083 
1084 	switch(TYPE(ch->qid)){
1085 	default:
1086 		error(Eperm);
1087 	case Qdata:
1088 		x = f->p[PROTO(ch->qid)];
1089 		c = x->conv[CONV(ch->qid)];
1090 
1091 		if(c->wq == nil)
1092 			error(Eperm);
1093 
1094 		qwrite(c->wq, a, n);
1095 		break;
1096 	case Qarp:
1097 		return arpwrite(f, a, n);
1098 	case Qiproute:
1099 		return routewrite(f, ch, a, n);
1100 	case Qlog:
1101 		netlogctl(f, a, n);
1102 		return n;
1103 	case Qndb:
1104 		return ndbwrite(f, a, off, n);
1105 	case Qctl:
1106 		x = f->p[PROTO(ch->qid)];
1107 		c = x->conv[CONV(ch->qid)];
1108 		cb = parsecmd(a, n);
1109 
1110 		qlock(c);
1111 		if(waserror()) {
1112 			qunlock(c);
1113 			free(cb);
1114 			nexterror();
1115 		}
1116 		if(cb->nf < 1)
1117 			error("short control request");
1118 		if(strcmp(cb->f[0], "connect") == 0)
1119 			connectctlmsg(x, c, cb);
1120 		else if(strcmp(cb->f[0], "announce") == 0)
1121 			announcectlmsg(x, c, cb);
1122 		else if(strcmp(cb->f[0], "bind") == 0)
1123 			bindctlmsg(x, c, cb);
1124 		else if(strcmp(cb->f[0], "ttl") == 0)
1125 			ttlctlmsg(c, cb);
1126 		else if(strcmp(cb->f[0], "tos") == 0)
1127 			tosctlmsg(c, cb);
1128 		else if(strcmp(cb->f[0], "ignoreadvice") == 0)
1129 			c->ignoreadvice = 1;
1130 		else if(strcmp(cb->f[0], "addmulti") == 0){
1131 			if(cb->nf < 2)
1132 				error("addmulti needs interface address");
1133 			if(cb->nf == 2){
1134 				if(!ipismulticast(c->raddr))
1135 					error("addmulti for a non multicast address");
1136 				parseip(ia, cb->f[1]);
1137 				ipifcaddmulti(c, c->raddr, ia);
1138 			} else {
1139 				parseip(ma, cb->f[2]);
1140 				if(!ipismulticast(ma))
1141 					error("addmulti for a non multicast address");
1142 				parseip(ia, cb->f[1]);
1143 				ipifcaddmulti(c, ma, ia);
1144 			}
1145 		} else if(strcmp(cb->f[0], "remmulti") == 0){
1146 			if(cb->nf < 2)
1147 				error("remmulti needs interface address");
1148 			if(!ipismulticast(c->raddr))
1149 				error("remmulti for a non multicast address");
1150 			parseip(ia, cb->f[1]);
1151 			ipifcremmulti(c, c->raddr, ia);
1152 		} else if(x->ctl != nil) {
1153 			p = x->ctl(c, cb->f, cb->nf);
1154 			if(p != nil)
1155 				error(p);
1156 		} else
1157 			error("unknown control request");
1158 		qunlock(c);
1159 		free(cb);
1160 		poperror();
1161 	}
1162 	return n;
1163 }
1164 
1165 static long
1166 ipbwrite(Chan* ch, Block* bp, ulong offset)
1167 {
1168 	Conv *c;
1169 	Proto *x;
1170 	Fs *f;
1171 	int n;
1172 
1173 	switch(TYPE(ch->qid)){
1174 	case Qdata:
1175 		f = ipfs[ch->dev];
1176 		x = f->p[PROTO(ch->qid)];
1177 		c = x->conv[CONV(ch->qid)];
1178 
1179 		if(c->wq == nil)
1180 			error(Eperm);
1181 
1182 		if(bp->next)
1183 			bp = concatblock(bp);
1184 		n = BLEN(bp);
1185 		qbwrite(c->wq, bp);
1186 		return n;
1187 	default:
1188 		return devbwrite(ch, bp, offset);
1189 	}
1190 }
1191 
1192 Dev ipdevtab = {
1193 	'I',
1194 	"ip",
1195 
1196 	ipreset,
1197 	devinit,
1198 	devshutdown,
1199 	ipattach,
1200 	ipwalk,
1201 	ipstat,
1202 	ipopen,
1203 	devcreate,
1204 	ipclose,
1205 	ipread,
1206 	ipbread,
1207 	ipwrite,
1208 	ipbwrite,
1209 	devremove,
1210 	ipwstat,
1211 };
1212 
1213 int
1214 Fsproto(Fs *f, Proto *p)
1215 {
1216 	if(f->np >= Maxproto)
1217 		return -1;
1218 
1219 	p->f = f;
1220 
1221 	if(p->ipproto > 0){
1222 		if(f->t2p[p->ipproto] != nil)
1223 			return -1;
1224 		f->t2p[p->ipproto] = p;
1225 	}
1226 
1227 	p->qid.type = QTDIR;
1228 	p->qid.path = QID(f->np, 0, Qprotodir);
1229 	p->conv = malloc(sizeof(Conv*)*(p->nc+1));
1230 	if(p->conv == nil)
1231 		panic("Fsproto");
1232 
1233 	p->x = f->np;
1234 	p->nextport = 0;
1235 	p->nextrport = 600;
1236 	f->p[f->np++] = p;
1237 
1238 	return 0;
1239 }
1240 
1241 /*
1242  *  return true if this protocol is
1243  *  built in
1244  */
1245 int
1246 Fsbuiltinproto(Fs* f, uchar proto)
1247 {
1248 	return f->t2p[proto] != nil;
1249 }
1250 
1251 /*
1252  *  called with protocol locked
1253  */
1254 Conv*
1255 Fsprotoclone(Proto *p, char *user)
1256 {
1257 	Conv *c, **pp, **ep;
1258 
1259 retry:
1260 	c = nil;
1261 	ep = &p->conv[p->nc];
1262 	for(pp = p->conv; pp < ep; pp++) {
1263 		c = *pp;
1264 		if(c == nil){
1265 			c = malloc(sizeof(Conv));
1266 			if(c == nil)
1267 				error(Enomem);
1268 			qlock(c);
1269 			c->p = p;
1270 			c->x = pp - p->conv;
1271 			if(p->ptclsize != 0){
1272 				c->ptcl = malloc(p->ptclsize);
1273 				if(c->ptcl == nil) {
1274 					free(c);
1275 					error(Enomem);
1276 				}
1277 			}
1278 			*pp = c;
1279 			p->ac++;
1280 			c->eq = qopen(1024, Qmsg, 0, 0);
1281 			(*p->create)(c);
1282 			break;
1283 		}
1284 		if(canqlock(c)){
1285 			/*
1286 			 *  make sure both processes and protocol
1287 			 *  are done with this Conv
1288 			 */
1289 			if(c->inuse == 0 && (p->inuse == nil || (*p->inuse)(c) == 0))
1290 				break;
1291 
1292 			qunlock(c);
1293 		}
1294 	}
1295 	if(pp >= ep) {
1296 		if(p->gc != nil && (*p->gc)(p))
1297 			goto retry;
1298 		return nil;
1299 	}
1300 
1301 	c->inuse = 1;
1302 	kstrdup(&c->owner, user);
1303 	c->perm = 0660;
1304 	c->state = Idle;
1305 	ipmove(c->laddr, IPnoaddr);
1306 	ipmove(c->raddr, IPnoaddr);
1307 	c->r = nil;
1308 	c->rgen = 0;
1309 	c->lport = 0;
1310 	c->rport = 0;
1311 	c->restricted = 0;
1312 	c->ttl = MAXTTL;
1313 	c->tos = DFLTTOS;
1314 	qreopen(c->rq);
1315 	qreopen(c->wq);
1316 	qreopen(c->eq);
1317 
1318 	qunlock(c);
1319 	return c;
1320 }
1321 
1322 int
1323 Fsconnected(Conv* c, char* msg)
1324 {
1325 	if(msg != nil && *msg != '\0')
1326 		kstrcpy(c->cerr, msg, sizeof(c->cerr));
1327 
1328 	switch(c->state){
1329 
1330 	case Announcing:
1331 		c->state = Announced;
1332 		break;
1333 
1334 	case Connecting:
1335 		c->state = Connected;
1336 		break;
1337 	}
1338 
1339 	wakeup(&c->cr);
1340 	return 0;
1341 }
1342 
1343 Proto*
1344 Fsrcvpcol(Fs* f, uchar proto)
1345 {
1346 	if(f->ipmux)
1347 		return f->ipmux;
1348 	else
1349 		return f->t2p[proto];
1350 }
1351 
1352 Proto*
1353 Fsrcvpcolx(Fs *f, uchar proto)
1354 {
1355 	return f->t2p[proto];
1356 }
1357 
1358 /*
1359  *  called with protocol locked
1360  */
1361 Conv*
1362 Fsnewcall(Conv *c, uchar *raddr, ushort rport, uchar *laddr, ushort lport, uchar version)
1363 {
1364 	Conv *nc;
1365 	Conv **l;
1366 	int i;
1367 
1368 	qlock(c);
1369 	i = 0;
1370 	for(l = &c->incall; *l; l = &(*l)->next)
1371 		i++;
1372 	if(i >= Maxincall) {
1373 		qunlock(c);
1374 		return nil;
1375 	}
1376 
1377 	/* find a free conversation */
1378 	nc = Fsprotoclone(c->p, network);
1379 	if(nc == nil) {
1380 		qunlock(c);
1381 		return nil;
1382 	}
1383 	ipmove(nc->raddr, raddr);
1384 	nc->rport = rport;
1385 	ipmove(nc->laddr, laddr);
1386 	nc->lport = lport;
1387 	nc->next = nil;
1388 	*l = nc;
1389 	nc->state = Connected;
1390 	nc->ipversion = version;
1391 
1392 	qunlock(c);
1393 
1394 	wakeup(&c->listenr);
1395 
1396 	return nc;
1397 }
1398 
1399 static long
1400 ndbwrite(Fs *f, char *a, ulong off, int n)
1401 {
1402 	if(off > strlen(f->ndb))
1403 		error(Eio);
1404 	if(off+n >= sizeof(f->ndb)-1)
1405 		error(Eio);
1406 	memmove(f->ndb+off, a, n);
1407 	f->ndb[off+n] = 0;
1408 	f->ndbvers++;
1409 	f->ndbmtime = seconds();
1410 	return n;
1411 }
1412 
1413 ulong
1414 scalednconv(void)
1415 {
1416 	if(conf.npage*BY2PG >= 128*MB)
1417 		return Nchans*4;
1418 	return Nchans;
1419 }
1420