xref: /plan9/sys/src/cmd/srvold9p/fcall.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
1*9a747e4fSDavid du Colombier #include <u.h>
2*9a747e4fSDavid du Colombier #include <libc.h>
3*9a747e4fSDavid du Colombier #include <auth.h>
4*9a747e4fSDavid du Colombier #include <fcall.h>
5*9a747e4fSDavid du Colombier #include "9p1.h"
6*9a747e4fSDavid du Colombier 
7*9a747e4fSDavid du Colombier #define	MAXFDATA	(8*1024)
8*9a747e4fSDavid du Colombier #define	MAXRPC		(MAXFDATA+160)
9*9a747e4fSDavid du Colombier 
10*9a747e4fSDavid du Colombier /*
11*9a747e4fSDavid du Colombier  * reassemble 9P messages for stream based protocols
12*9a747e4fSDavid du Colombier  * interposed between devmnt and the network by srv for tcp connections
13*9a747e4fSDavid du Colombier  * fcall expects devmnt on fd0, network fd1
14*9a747e4fSDavid du Colombier  */
15*9a747e4fSDavid du Colombier uchar msglen[256] =
16*9a747e4fSDavid du Colombier {
17*9a747e4fSDavid du Colombier 	[Tnop9p1]		3,
18*9a747e4fSDavid du Colombier 	[Rnop9p1]		3,
19*9a747e4fSDavid du Colombier 	[Tsession9p1]	3+CHALLEN,
20*9a747e4fSDavid du Colombier 	[Rsession9p1]	3+NAMEREC+DOMLEN+CHALLEN,
21*9a747e4fSDavid du Colombier 	[Terror9p1]	0,
22*9a747e4fSDavid du Colombier 	[Rerror9p1]	67,
23*9a747e4fSDavid du Colombier 	[Tflush9p1]	5,
24*9a747e4fSDavid du Colombier 	[Rflush9p1]	3,
25*9a747e4fSDavid du Colombier 	[Tattach9p1]	5+2*NAMEREC+TICKETLEN+AUTHENTLEN,
26*9a747e4fSDavid du Colombier 	[Rattach9p1]	13+AUTHENTLEN,
27*9a747e4fSDavid du Colombier 	[Tclone9p1]	7,
28*9a747e4fSDavid du Colombier 	[Rclone9p1]	5,
29*9a747e4fSDavid du Colombier 	[Twalk9p1]		33,
30*9a747e4fSDavid du Colombier 	[Rwalk9p1]		13,
31*9a747e4fSDavid du Colombier 	[Topen9p1]		6,
32*9a747e4fSDavid du Colombier 	[Ropen9p1]		13,
33*9a747e4fSDavid du Colombier 	[Tcreate9p1]	38,
34*9a747e4fSDavid du Colombier 	[Rcreate9p1]	13,
35*9a747e4fSDavid du Colombier 	[Tread9p1]		15,
36*9a747e4fSDavid du Colombier 	[Rread9p1]		8,
37*9a747e4fSDavid du Colombier 	[Twrite9p1]	16,
38*9a747e4fSDavid du Colombier 	[Rwrite9p1]	7,
39*9a747e4fSDavid du Colombier 	[Tclunk9p1]	5,
40*9a747e4fSDavid du Colombier 	[Rclunk9p1]	5,
41*9a747e4fSDavid du Colombier 	[Tremove9p1]	5,
42*9a747e4fSDavid du Colombier 	[Rremove9p1]	5,
43*9a747e4fSDavid du Colombier 	[Tstat9p1]		5,
44*9a747e4fSDavid du Colombier 	[Rstat9p1]		121,
45*9a747e4fSDavid du Colombier 	[Twstat9p1]	121,
46*9a747e4fSDavid du Colombier 	[Rwstat9p1]	5,
47*9a747e4fSDavid du Colombier 	[Tclwalk9p1]	35,
48*9a747e4fSDavid du Colombier 	[Rclwalk9p1]	13,
49*9a747e4fSDavid du Colombier };
50*9a747e4fSDavid du Colombier 
51*9a747e4fSDavid du Colombier enum
52*9a747e4fSDavid du Colombier {
53*9a747e4fSDavid du Colombier 	Twritehdr	= 16,	/* Min bytes for Twrite */
54*9a747e4fSDavid du Colombier 	Rreadhdr	= 8,	/* Min bytes for Rread */
55*9a747e4fSDavid du Colombier 	Twritecnt	= 13,	/* Offset in byte stream of write count */
56*9a747e4fSDavid du Colombier 	Rreadcnt	= 5,	/* Offset for Readcnt */
57*9a747e4fSDavid du Colombier };
58*9a747e4fSDavid du Colombier 
59*9a747e4fSDavid du Colombier int
mntrpclen(uchar * d,int n)60*9a747e4fSDavid du Colombier mntrpclen(uchar *d, int n)
61*9a747e4fSDavid du Colombier {
62*9a747e4fSDavid du Colombier 	uchar t;
63*9a747e4fSDavid du Colombier 	int len, off;
64*9a747e4fSDavid du Colombier 
65*9a747e4fSDavid du Colombier 	if(n < 1)
66*9a747e4fSDavid du Colombier 		return 0;
67*9a747e4fSDavid du Colombier 
68*9a747e4fSDavid du Colombier 	t = d[0];
69*9a747e4fSDavid du Colombier 	switch(t) {			/* This is the type */
70*9a747e4fSDavid du Colombier 	default:
71*9a747e4fSDavid du Colombier 		len = msglen[t];
72*9a747e4fSDavid du Colombier 		if(len == 0)		/* Illegal type so consume */
73*9a747e4fSDavid du Colombier 			return n;
74*9a747e4fSDavid du Colombier 		if(n < len)
75*9a747e4fSDavid du Colombier 			return 0;
76*9a747e4fSDavid du Colombier 		return len;
77*9a747e4fSDavid du Colombier 	case Twrite9p1:			/* Fmt: TGGFFOOOOOOOOCC */
78*9a747e4fSDavid du Colombier 		len = Twritehdr;	/* T = type, G = tag, F = fid */
79*9a747e4fSDavid du Colombier 		off = Twritecnt;	/* O = offset, C = count */
80*9a747e4fSDavid du Colombier 		break;
81*9a747e4fSDavid du Colombier 	case Rread9p1:			/* Fmt: TGGFFCC */
82*9a747e4fSDavid du Colombier 		len = Rreadhdr;
83*9a747e4fSDavid du Colombier 		off = Rreadcnt;
84*9a747e4fSDavid du Colombier 		break;
85*9a747e4fSDavid du Colombier 	}
86*9a747e4fSDavid du Colombier 	if(n < off+2)
87*9a747e4fSDavid du Colombier 		return 0;
88*9a747e4fSDavid du Colombier 
89*9a747e4fSDavid du Colombier 	len += d[off]|(d[off+1]<<8);
90*9a747e4fSDavid du Colombier 	if(n < len)
91*9a747e4fSDavid du Colombier 		return 0;
92*9a747e4fSDavid du Colombier 
93*9a747e4fSDavid du Colombier 	return len;
94*9a747e4fSDavid du Colombier }
95*9a747e4fSDavid du Colombier 
96*9a747e4fSDavid du Colombier int
fcall(int fd)97*9a747e4fSDavid du Colombier fcall(int fd)
98*9a747e4fSDavid du Colombier {
99*9a747e4fSDavid du Colombier 	int i, r, n, l;
100*9a747e4fSDavid du Colombier 	uchar *p, *buf;
101*9a747e4fSDavid du Colombier 	int pipefd[2];
102*9a747e4fSDavid du Colombier 
103*9a747e4fSDavid du Colombier 	if(pipe(pipefd) < 0)
104*9a747e4fSDavid du Colombier 		fatal("fcall pipe: %r");
105*9a747e4fSDavid du Colombier 
106*9a747e4fSDavid du Colombier 	buf = malloc(MAXRPC);
107*9a747e4fSDavid du Colombier 	if(buf == nil)
108*9a747e4fSDavid du Colombier 		fatal("fcall malloc");
109*9a747e4fSDavid du Colombier 
110*9a747e4fSDavid du Colombier 	switch(rfork(RFPROC|RFMEM|RFFDG|RFCNAMEG)){
111*9a747e4fSDavid du Colombier 	default:
112*9a747e4fSDavid du Colombier 		return pipefd[0];	/* parent returns fd */
113*9a747e4fSDavid du Colombier 	case 0:
114*9a747e4fSDavid du Colombier 		break;	/* child builds buffers */
115*9a747e4fSDavid du Colombier 	case -1:
116*9a747e4fSDavid du Colombier 		fatal("fcall fork: %r");
117*9a747e4fSDavid du Colombier 	}
118*9a747e4fSDavid du Colombier 
119*9a747e4fSDavid du Colombier 	/* close file descriptors */
120*9a747e4fSDavid du Colombier 	for(i=0; i<20; i++)
121*9a747e4fSDavid du Colombier 		if(i!=fd && i!=pipefd[1])
122*9a747e4fSDavid du Colombier 			close(i);
123*9a747e4fSDavid du Colombier 
124*9a747e4fSDavid du Colombier 	l = MAXRPC;
125*9a747e4fSDavid du Colombier 	p = buf;
126*9a747e4fSDavid du Colombier 	for(;;) {
127*9a747e4fSDavid du Colombier 		n = read(fd, p, l);
128*9a747e4fSDavid du Colombier 		if(n < 0)
129*9a747e4fSDavid du Colombier 			break;
130*9a747e4fSDavid du Colombier 		p += n;
131*9a747e4fSDavid du Colombier 		l -= n;
132*9a747e4fSDavid du Colombier 
133*9a747e4fSDavid du Colombier 		for(;;) {
134*9a747e4fSDavid du Colombier 			r = mntrpclen(buf, p - buf);
135*9a747e4fSDavid du Colombier 			if(r == 0)
136*9a747e4fSDavid du Colombier 				break;
137*9a747e4fSDavid du Colombier 
138*9a747e4fSDavid du Colombier 			if(write(pipefd[1], buf, r) < 0)
139*9a747e4fSDavid du Colombier 				break;
140*9a747e4fSDavid du Colombier 
141*9a747e4fSDavid du Colombier 			n = (p - buf) - r;
142*9a747e4fSDavid du Colombier 			memmove(buf, buf+r, n);
143*9a747e4fSDavid du Colombier 			p = buf+n;
144*9a747e4fSDavid du Colombier 			l = MAXRPC - n;
145*9a747e4fSDavid du Colombier 		}
146*9a747e4fSDavid du Colombier 	}
147*9a747e4fSDavid du Colombier 	close(pipefd[1]);
148*9a747e4fSDavid du Colombier 	fatal(nil);
149*9a747e4fSDavid du Colombier 	return -1;
150*9a747e4fSDavid du Colombier }
151