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