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