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