Subversion Repositories planix.SVN

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include	"u.h"
2
#include	"../port/lib.h"
3
#include	"mem.h"
4
#include	"dat.h"
5
#include	"fns.h"
6
#include	"../port/error.h"
7
#include	"../ip/ip.h"
8
 
9
enum
10
{
11
	Qtopdir=	1,		/* top level directory */
12
	Qtopbase,
13
	Qarp=		Qtopbase,
14
	Qbootp,
15
	Qndb,
16
	Qiproute,
17
	Qipselftab,
18
	Qlog,
19
 
20
	Qprotodir,			/* directory for a protocol */
21
	Qprotobase,
22
	Qclone=		Qprotobase,
23
	Qstats,
24
 
25
	Qconvdir,			/* directory for a conversation */
26
	Qconvbase,
27
	Qctl=		Qconvbase,
28
	Qdata,
29
	Qerr,
30
	Qlisten,
31
	Qlocal,
32
	Qremote,
33
	Qstatus,
34
	Qsnoop,
35
 
36
	Logtype=	5,
37
	Masktype=	(1<<Logtype)-1,
38
	Logconv=	12,
39
	Maskconv=	(1<<Logconv)-1,
40
	Shiftconv=	Logtype,
41
	Logproto=	8,
42
	Maskproto=	(1<<Logproto)-1,
43
	Shiftproto=	Logtype + Logconv,
44
 
45
	Nfs=		128,
46
};
47
#define TYPE(x) 	( ((ulong)(x).path) & Masktype )
48
#define CONV(x) 	( (((ulong)(x).path) >> Shiftconv) & Maskconv )
49
#define PROTO(x) 	( (((ulong)(x).path) >> Shiftproto) & Maskproto )
50
#define QID(p, c, y) 	( ((p)<<(Shiftproto)) | ((c)<<Shiftconv) | (y) )
51
 
52
static char network[] = "network";
53
 
54
QLock	fslock;
55
Fs	*ipfs[Nfs];	/* attached fs's */
56
Queue	*qlog;
57
 
58
extern	void nullmediumlink(void);
59
extern	void pktmediumlink(void);
60
	long ndbwrite(Fs *f, char *a, ulong off, int n);
61
 
62
static int
63
ip3gen(Chan *c, int i, Dir *dp)
64
{
65
	Qid q;
66
	Conv *cv;
67
	char *p;
68
 
69
	cv = ipfs[c->dev]->p[PROTO(c->qid)]->conv[CONV(c->qid)];
70
	if(cv->owner == nil)
71
		kstrdup(&cv->owner, eve);
72
	mkqid(&q, QID(PROTO(c->qid), CONV(c->qid), i), 0, QTFILE);
73
 
74
	switch(i) {
75
	default:
76
		return -1;
77
	case Qctl:
78
		devdir(c, q, "ctl", 0, cv->owner, cv->perm, dp);
79
		return 1;
80
	case Qdata:
81
		devdir(c, q, "data", qlen(cv->rq), cv->owner, cv->perm, dp);
82
		return 1;
83
	case Qerr:
84
		devdir(c, q, "err", qlen(cv->eq), cv->owner, cv->perm, dp);
85
		return 1;
86
	case Qlisten:
87
		devdir(c, q, "listen", 0, cv->owner, cv->perm, dp);
88
		return 1;
89
	case Qlocal:
90
		p = "local";
91
		break;
92
	case Qremote:
93
		p = "remote";
94
		break;
95
	case Qsnoop:
96
		if(strcmp(cv->p->name, "ipifc") != 0)
97
			return -1;
98
		devdir(c, q, "snoop", qlen(cv->sq), cv->owner, 0400, dp);
99
		return 1;
100
	case Qstatus:
101
		p = "status";
102
		break;
103
	}
104
	devdir(c, q, p, 0, cv->owner, 0444, dp);
105
	return 1;
106
}
107
 
108
static int
109
ip2gen(Chan *c, int i, Dir *dp)
110
{
111
	Qid q;
112
 
113
	switch(i) {
114
	case Qclone:
115
		mkqid(&q, QID(PROTO(c->qid), 0, Qclone), 0, QTFILE);
116
		devdir(c, q, "clone", 0, network, 0666, dp);
117
		return 1;
118
	case Qstats:
119
		mkqid(&q, QID(PROTO(c->qid), 0, Qstats), 0, QTFILE);
120
		devdir(c, q, "stats", 0, network, 0444, dp);
121
		return 1;
122
	}
123
	return -1;
124
}
125
 
126
static int
127
ip1gen(Chan *c, int i, Dir *dp)
128
{
129
	Qid q;
130
	char *p;
131
	int prot;
132
	int len = 0;
133
	Fs *f;
134
	extern ulong	kerndate;
135
 
136
	f = ipfs[c->dev];
137
 
138
	prot = 0666;
139
	mkqid(&q, QID(0, 0, i), 0, QTFILE);
140
	switch(i) {
141
	default:
142
		return -1;
143
	case Qarp:
144
		p = "arp";
145
		prot = 0664;
146
		break;
147
	case Qbootp:
148
		p = "bootp";
149
		break;
150
	case Qndb:
151
		p = "ndb";
152
		len = strlen(f->ndb);
153
		q.vers = f->ndbvers;
154
		break;
155
	case Qiproute:
156
		p = "iproute";
157
		prot = 0664;
158
		break;
159
	case Qipselftab:
160
		p = "ipselftab";
161
		prot = 0444;
162
		break;
163
	case Qlog:
164
		p = "log";
165
		break;
166
	}
167
	devdir(c, q, p, len, network, prot, dp);
168
	if(i == Qndb && f->ndbmtime > kerndate)
169
		dp->mtime = f->ndbmtime;
170
	return 1;
171
}
172
 
173
static int
174
ipgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp)
175
{
176
	Qid q;
177
	Conv *cv;
178
	Fs *f;
179
 
180
	f = ipfs[c->dev];
181
 
182
	switch(TYPE(c->qid)) {
183
	case Qtopdir:
184
		if(s == DEVDOTDOT){
185
			mkqid(&q, QID(0, 0, Qtopdir), 0, QTDIR);
186
			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
247
ipreset(void)
248
{
249
	nullmediumlink();
250
	pktmediumlink();
251
 
252
	fmtinstall('i', eipfmt);
253
	fmtinstall('I', eipfmt);
254
	fmtinstall('E', eipfmt);
255
	fmtinstall('V', eipfmt);
256
	fmtinstall('M', eipfmt);
257
}
258
 
259
static Fs*
260
ipgetfs(int dev)
261
{
262
	extern void (*ipprotoinit[])(Fs*);
263
	Fs *f;
264
	int i;
265
 
266
	if(dev >= Nfs)
267
		return nil;
268
 
269
	qlock(&fslock);
270
	if(ipfs[dev] == nil){
271
		f = smalloc(sizeof(Fs));
272
		ip_init(f);
273
		arpinit(f);
274
		netloginit(f);
275
		for(i = 0; ipprotoinit[i]; i++)
276
			ipprotoinit[i](f);
277
		f->dev = dev;
278
		ipfs[dev] = f;
279
	}
280
	qunlock(&fslock);
281
 
282
	return ipfs[dev];
283
}
284
 
285
IPaux*
286
newipaux(char *owner, char *tag)
287
{
288
	IPaux *a;
289
	int n;
290
 
291
	a = smalloc(sizeof(*a));
292
	kstrdup(&a->owner, owner);
293
	memset(a->tag, ' ', sizeof(a->tag));
294
	n = strlen(tag);
295
	if(n > sizeof(a->tag))
296
		n = sizeof(a->tag);
297
	memmove(a->tag, tag, n);
298
	return a;
299
}
300
 
301
#define ATTACHER(c) (((IPaux*)((c)->aux))->owner)
302
 
303
static Chan*
304
ipattach(char* spec)
305
{
306
	Chan *c;
307
	int dev;
308
 
309
	dev = atoi(spec);
310
	if(dev >= Nfs)
311
		error("bad specification");
312
 
313
	ipgetfs(dev);
314
	c = devattach('I', spec);
315
	mkqid(&c->qid, QID(0, 0, Qtopdir), 0, QTDIR);
316
	c->dev = dev;
317
 
318
	c->aux = newipaux(commonuser(), "none");
319
 
320
	return c;
321
}
322
 
323
static Walkqid*
324
ipwalk(Chan* c, Chan *nc, char **name, int nname)
325
{
326
	IPaux *a = c->aux;
327
	Walkqid* w;
328
 
329
	w = devwalk(c, nc, name, nname, nil, 0, ipgen);
330
	if(w != nil && w->clone != nil)
331
		w->clone->aux = newipaux(a->owner, a->tag);
332
	return w;
333
}
334
 
335
 
336
static int
337
ipstat(Chan* c, uchar* db, int n)
338
{
339
	return devstat(c, db, n, nil, 0, ipgen);
340
}
341
 
342
static int
343
incoming(void* arg)
344
{
345
	Conv *conv;
346
 
347
	conv = arg;
348
	return conv->incall != nil;
349
}
350
 
351
static int m2p[] = {
352
	[OREAD]		4,
353
	[OWRITE]	2,
354
	[ORDWR]		6
355
};
356
 
357
static Chan*
358
ipopen(Chan* c, int omode)
359
{
360
	Conv *cv, *nc;
361
	Proto *p;
362
	int perm;
363
	Fs *f;
364
 
365
	perm = m2p[omode&3];
366
 
367
	f = ipfs[c->dev];
368
 
369
	switch(TYPE(c->qid)) {
370
	default:
371
		break;
372
	case Qndb:
373
		if(omode & (OWRITE|OTRUNC) && !iseve())
374
			error(Eperm);
375
		if((omode & (OWRITE|OTRUNC)) == (OWRITE|OTRUNC))
376
			f->ndb[0] = 0;
377
		break;
378
	case Qlog:
379
		netlogopen(f);
380
		break;
381
	case Qiproute:
382
	case Qarp:
383
		if(omode != OREAD && !iseve())
384
			error(Eperm);
385
		break;
386
	case Qtopdir:
387
	case Qprotodir:
388
	case Qconvdir:
389
	case Qstatus:
390
	case Qremote:
391
	case Qlocal:
392
	case Qstats:
393
	case Qbootp:
394
	case Qipselftab:
395
		if(omode != OREAD)
396
			error(Eperm);
397
		break;
398
	case Qsnoop:
399
		if(omode != OREAD)
400
			error(Eperm);
401
		p = f->p[PROTO(c->qid)];
402
		cv = p->conv[CONV(c->qid)];
403
		if(strcmp(ATTACHER(c), cv->owner) != 0 && !iseve())
404
			error(Eperm);
405
		incref(&cv->snoopers);
406
		break;
407
	case Qclone:
408
		p = f->p[PROTO(c->qid)];
409
		qlock(p);
410
		if(waserror()){
411
			qunlock(p);
412
			nexterror();
413
		}
414
		cv = Fsprotoclone(p, ATTACHER(c));
415
		qunlock(p);
416
		poperror();
417
		if(cv == nil) {
418
			error(Enodev);
419
			break;
420
		}
421
		mkqid(&c->qid, QID(p->x, cv->x, Qctl), 0, QTFILE);
422
		break;
423
	case Qdata:
424
	case Qctl:
425
	case Qerr:
426
		p = f->p[PROTO(c->qid)];
427
		qlock(p);
428
		cv = p->conv[CONV(c->qid)];
429
		qlock(cv);
430
		if(waserror()) {
431
			qunlock(cv);
432
			qunlock(p);
433
			nexterror();
434
		}
435
		if((perm & (cv->perm>>6)) != perm) {
436
			if(strcmp(ATTACHER(c), cv->owner) != 0)
437
				error(Eperm);
438
		 	if((perm & cv->perm) != perm)
439
				error(Eperm);
440
 
441
		}
442
		cv->inuse++;
443
		if(cv->inuse == 1){
444
			kstrdup(&cv->owner, ATTACHER(c));
445
			cv->perm = 0660;
446
		}
447
		qunlock(cv);
448
		qunlock(p);
449
		poperror();
450
		break;
451
	case Qlisten:
452
		cv = f->p[PROTO(c->qid)]->conv[CONV(c->qid)];
453
		if((perm & (cv->perm>>6)) != perm) {
454
			if(strcmp(ATTACHER(c), cv->owner) != 0)
455
				error(Eperm);
456
		 	if((perm & cv->perm) != perm)
457
				error(Eperm);
458
 
459
		}
460
 
461
		if(cv->state != Announced)
462
			error("not announced");
463
 
464
		if(waserror()){
465
			closeconv(cv);
466
			nexterror();
467
		}
468
		qlock(cv);
469
		cv->inuse++;
470
		qunlock(cv);
471
 
472
		nc = nil;
473
		while(nc == nil) {
474
			/* give up if we got a hangup */
475
			if(qisclosed(cv->rq))
476
				error("listen hungup");
477
 
478
			qlock(&cv->listenq);
479
			if(waserror()) {
480
				qunlock(&cv->listenq);
481
				nexterror();
482
			}
483
 
484
			/* wait for a connect */
485
			sleep(&cv->listenr, incoming, cv);
486
 
487
			qlock(cv);
488
			nc = cv->incall;
489
			if(nc != nil){
490
				cv->incall = nc->next;
491
				mkqid(&c->qid, QID(PROTO(c->qid), nc->x, Qctl), 0, QTFILE);
492
				kstrdup(&cv->owner, ATTACHER(c));
493
			}
494
			qunlock(cv);
495
 
496
			qunlock(&cv->listenq);
497
			poperror();
498
		}
499
		closeconv(cv);
500
		poperror();
501
		break;
502
	}
503
	c->mode = openmode(omode);
504
	c->flag |= COPEN;
505
	c->offset = 0;
506
	return c;
507
}
508
 
509
static void
510
ipcreate(Chan*, char*, int, ulong)
511
{
512
	error(Eperm);
513
}
514
 
515
static void
516
ipremove(Chan*)
517
{
518
	error(Eperm);
519
}
520
 
521
static int
522
ipwstat(Chan *c, uchar *dp, int n)
523
{
524
	Dir d;
525
	Conv *cv;
526
	Fs *f;
527
	Proto *p;
528
 
529
	f = ipfs[c->dev];
530
	switch(TYPE(c->qid)) {
531
	default:
532
		error(Eperm);
533
		break;
534
	case Qctl:
535
	case Qdata:
536
		break;
537
	}
538
 
539
	n = convM2D(dp, n, &d, nil);
540
	if(n > 0){
541
		p = f->p[PROTO(c->qid)];
542
		cv = p->conv[CONV(c->qid)];
543
		if(!iseve() && strcmp(ATTACHER(c), cv->owner) != 0)
544
			error(Eperm);
545
		if(d.uid[0])
546
			kstrdup(&cv->owner, d.uid);
547
		cv->perm = d.mode & 0777;
548
	}
549
	return n;
550
}
551
 
552
void
553
closeconv(Conv *cv)
554
{
555
	Conv *nc;
556
	Ipmulti *mp;
557
 
558
	qlock(cv);
559
 
560
	if(--cv->inuse > 0) {
561
		qunlock(cv);
562
		return;
563
	}
564
 
565
	/* close all incoming calls since no listen will ever happen */
566
	for(nc = cv->incall; nc; nc = cv->incall){
567
		cv->incall = nc->next;
568
		closeconv(nc);
569
	}
570
	cv->incall = nil;
571
 
572
	kstrdup(&cv->owner, network);
573
	cv->perm = 0660;
574
 
575
	while((mp = cv->multi) != nil)
576
		ipifcremmulti(cv, mp->ma, mp->ia);
577
 
578
	cv->r = nil;
579
	cv->rgen = 0;
580
	cv->p->close(cv);
581
	cv->state = Idle;
582
	qunlock(cv);
583
}
584
 
585
static void
586
ipclose(Chan* c)
587
{
588
	Fs *f;
589
 
590
	f = ipfs[c->dev];
591
	switch(TYPE(c->qid)) {
592
	default:
593
		break;
594
	case Qlog:
595
		if(c->flag & COPEN)
596
			netlogclose(f);
597
		break;
598
	case Qdata:
599
	case Qctl:
600
	case Qerr:
601
		if(c->flag & COPEN)
602
			closeconv(f->p[PROTO(c->qid)]->conv[CONV(c->qid)]);
603
		break;
604
	case Qsnoop:
605
		if(c->flag & COPEN)
606
			decref(&f->p[PROTO(c->qid)]->conv[CONV(c->qid)]->snoopers);
607
		break;
608
	}
609
	free(((IPaux*)c->aux)->owner);
610
	free(c->aux);
611
}
612
 
613
enum
614
{
615
	Statelen=	32*1024,
616
};
617
 
618
static long
619
ipread(Chan *ch, void *a, long n, vlong off)
620
{
621
	Conv *c;
622
	Proto *x;
623
	char *buf, *p;
624
	long rv;
625
	Fs *f;
626
	ulong offset = off;
627
 
628
	f = ipfs[ch->dev];
629
 
630
	p = a;
631
	switch(TYPE(ch->qid)) {
632
	default:
633
		error(Eperm);
634
	case Qtopdir:
635
	case Qprotodir:
636
	case Qconvdir:
637
		return devdirread(ch, a, n, 0, 0, ipgen);
638
	case Qarp:
639
		return arpread(f->arp, a, offset, n);
640
 	case Qbootp:
641
 		return bootpread(a, offset, n);
642
 	case Qndb:
643
		return readstr(offset, a, n, f->ndb);
644
	case Qiproute:
645
		return routeread(f, a, offset, n);
646
	case Qipselftab:
647
		return ipselftabread(f, a, offset, n);
648
	case Qlog:
649
		return netlogread(f, a, offset, n);
650
	case Qctl:
651
		buf = smalloc(16);
652
		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*
710
ipbread(Chan* ch, long n, ulong offset)
711
{
712
	Conv *c;
713
	Proto *x;
714
	Fs *f;
715
 
716
	switch(TYPE(ch->qid)){
717
	case Qdata:
718
		f = ipfs[ch->dev];
719
		x = f->p[PROTO(ch->qid)];
720
		c = x->conv[CONV(ch->qid)];
721
		return qbread(c->rq, n);
722
	default:
723
		return devbread(ch, n, offset);
724
	}
725
}
726
 
727
/*
728
 *  set local address to be that of the ifc closest to remote address
729
 */
730
static void
731
setladdr(Conv* c)
732
{
733
	findlocalip(c->p->f, c->laddr, c->raddr);
734
}
735
 
736
/*
737
 *  set a local port making sure the quad of raddr,rport,laddr,lport is unique
738
 */
739
char*
740
setluniqueport(Conv* c, int lport)
741
{
742
	Proto *p;
743
	Conv *xp;
744
	int x;
745
 
746
	p = c->p;
747
 
748
	qlock(p);
749
	for(x = 0; x < p->nc; x++){
750
		xp = p->conv[x];
751
		if(xp == nil)
752
			break;
753
		if(xp == c)
754
			continue;
755
		if((xp->state == Connected || xp->state == Announced)
756
		&& xp->lport == lport
757
		&& xp->rport == c->rport
758
		&& ipcmp(xp->raddr, c->raddr) == 0
759
		&& ipcmp(xp->laddr, c->laddr) == 0){
760
			qunlock(p);
761
			return "address in use";
762
		}
763
	}
764
	c->lport = lport;
765
	qunlock(p);
766
	return nil;
767
}
768
 
769
/*
770
 * is lport in use by anyone?
771
 */
772
static int
773
lportinuse(Proto *p, ushort lport)
774
{
775
	int x;
776
 
777
	for(x = 0; x < p->nc && p->conv[x]; x++)
778
		if(p->conv[x]->lport == lport)
779
			return 1;
780
	return 0;
781
}
782
 
783
/*
784
 *  pick a local port and set it
785
 */
786
char *
787
setlport(Conv* c)
788
{
789
	Proto *p;
790
	int i, port;
791
 
792
	p = c->p;
793
	qlock(p);
794
	if(c->restricted){
795
		/* Restricted ports cycle between 600 and 1024. */
796
		for(i=0; i<1024-600; i++){
797
			if(p->nextrport >= 1024 || p->nextrport < 600)
798
				p->nextrport = 600;
799
			port = p->nextrport++;
800
			if(!lportinuse(p, port))
801
				goto chosen;
802
		}
803
	}else{
804
		/*
805
		 * Unrestricted ports are chosen randomly
806
		 * between 2^15 and 2^16.  There are at most
807
		 * 4*Nchan = 4096 ports in use at any given time,
808
		 * so even in the worst case, a random probe has a
809
		 * 1 - 4096/2^15 = 87% chance of success.
810
		 * If 64 successive probes fail, there is a bug somewhere
811
		 * (or a once in 10^58 event has happened, but that's
812
		 * less likely than a venti collision).
813
		 */
814
		for(i=0; i<64; i++){
815
			port = (1<<15) + nrand(1<<15);
816
			if(!lportinuse(p, port))
817
				goto chosen;
818
		}
819
	}
820
	qunlock(p);
821
	/*
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*
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*
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*
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
955
connected(void* a)
956
{
957
	return ((Conv*)a)->state == Connected;
958
}
959
static void
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*
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
1008
announced(void* a)
1009
{
1010
	return ((Conv*)a)->state == Announced;
1011
}
1012
static void
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*
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
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
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
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
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
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
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
1272
Fsbuiltinproto(Fs* f, uchar proto)
1273
{
1274
	return f->t2p[proto] != nil;
1275
}
1276
 
1277
/*
1278
 *  called with protocol locked
1279
 */
1280
Conv*
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
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*
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*
1384
Fsrcvpcolx(Fs *f, uchar proto)
1385
{
1386
	return f->t2p[proto];
1387
}
1388
 
1389
/*
1390
 *  called with protocol locked
1391
 */
1392
Conv*
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
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
1452
scalednconv(void)
1453
{
1454
	if(cpuserver && conf.npage*BY2PG >= 128*MB)
1455
		return Nchans*4;
1456
	return Nchans;
1457
}