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