trampoline.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include <ndb.h>
  5. #include <fcall.h>
  6. enum
  7. {
  8. Maxpath= 128,
  9. };
  10. typedef struct Endpoints Endpoints;
  11. struct Endpoints
  12. {
  13. char *net;
  14. char *lsys;
  15. char *lserv;
  16. char *rsys;
  17. char *rserv;
  18. };
  19. void xfer(int, int);
  20. void xfer9p(int, int);
  21. Endpoints* getendpoints(char*);
  22. void freeendpoints(Endpoints*);
  23. char* iptomac(char*, char*);
  24. int macok(char*);
  25. void
  26. usage(void)
  27. {
  28. fprint(2, "usage: trampoline [-9] [-a addr] [-m netdir] addr\n");
  29. exits("usage");
  30. }
  31. void
  32. main(int argc, char **argv)
  33. {
  34. char *altaddr, *checkmac, *mac;
  35. int fd, fd0, fd1;
  36. void (*x)(int, int);
  37. Endpoints *ep;
  38. checkmac = nil;
  39. altaddr = nil;
  40. x = xfer;
  41. ARGBEGIN{
  42. case '9':
  43. x = xfer9p;
  44. break;
  45. case 'a':
  46. altaddr = EARGF(usage());
  47. break;
  48. case 'm':
  49. checkmac = EARGF(usage());
  50. break;
  51. default:
  52. usage();
  53. }ARGEND;
  54. if(argc != 1)
  55. usage();
  56. if(checkmac){
  57. ep = getendpoints(checkmac);
  58. mac = iptomac(ep->rsys, ep->net);
  59. if(!macok(mac)){
  60. syslog(0, "trampoline", "badmac %s from %s!%s for %s!%s on %s",
  61. mac, ep->rsys, ep->rserv, ep->lsys, ep->lserv, ep->net);
  62. exits("bad mac");
  63. }
  64. }
  65. fd0 = 0;
  66. fd1 = 1;
  67. if(altaddr){
  68. fd0 = dial(altaddr, 0, 0, 0);
  69. if(fd0 < 0)
  70. sysfatal("dial %s: %r", altaddr);
  71. fd1 = fd0;
  72. }
  73. fd = dial(argv[0], 0, 0, 0);
  74. if(fd < 0)
  75. sysfatal("dial %s: %r", argv[0]);
  76. rfork(RFNOTEG);
  77. switch(fork()){
  78. case -1:
  79. fprint(2, "%s: fork: %r\n", argv0);
  80. exits("dial");
  81. case 0:
  82. (*x)(fd0, fd);
  83. break;
  84. default:
  85. (*x)(fd, fd1);
  86. break;
  87. }
  88. postnote(PNGROUP, getpid(), "die yankee pig dog");
  89. exits(0);
  90. }
  91. void
  92. xfer(int from, int to)
  93. {
  94. char buf[12*1024];
  95. int n;
  96. while((n = read(from, buf, sizeof buf)) > 0)
  97. if(write(to, buf, n) < 0)
  98. break;
  99. }
  100. void
  101. xfer9p(int from, int to)
  102. {
  103. uchar *buf;
  104. uint nbuf;
  105. int n;
  106. nbuf = 256;
  107. buf = malloc(nbuf);
  108. if(buf == nil)
  109. sysfatal("xfer: malloc %ud: %r", nbuf);
  110. for(;;){
  111. if(readn(from, buf, 4) != 4)
  112. break;
  113. n = GBIT32(buf);
  114. if(n > nbuf){
  115. nbuf = n+8192;
  116. buf = realloc(buf, nbuf);
  117. if(buf == nil)
  118. sysfatal("xfer: realloc %ud: %r", nbuf);
  119. }
  120. if(readn(from, buf+4, n-4) != n-4)
  121. break;
  122. if(write(to, buf, n) != n){
  123. sysfatal("oops: %r");
  124. break;
  125. }
  126. }
  127. }
  128. void
  129. getendpoint(char *dir, char *file, char **sysp, char **servp)
  130. {
  131. int fd, n;
  132. char buf[Maxpath];
  133. char *sys, *serv;
  134. sys = serv = 0;
  135. snprint(buf, sizeof buf, "%s/%s", dir, file);
  136. fd = open(buf, OREAD);
  137. if(fd >= 0){
  138. n = read(fd, buf, sizeof(buf)-1);
  139. if(n>0){
  140. buf[n-1] = 0;
  141. serv = strchr(buf, '!');
  142. if(serv){
  143. *serv++ = 0;
  144. serv = strdup(serv);
  145. }
  146. sys = strdup(buf);
  147. }
  148. close(fd);
  149. }
  150. if(serv == 0)
  151. serv = strdup("unknown");
  152. if(sys == 0)
  153. sys = strdup("unknown");
  154. *servp = serv;
  155. *sysp = sys;
  156. }
  157. Endpoints *
  158. getendpoints(char *dir)
  159. {
  160. Endpoints *ep;
  161. char *p;
  162. ep = malloc(sizeof(*ep));
  163. ep->net = strdup(dir);
  164. p = strchr(ep->net+1, '/');
  165. if(p == nil){
  166. free(ep->net);
  167. ep->net = "/net";
  168. } else
  169. *p = 0;
  170. getendpoint(dir, "local", &ep->lsys, &ep->lserv);
  171. getendpoint(dir, "remote", &ep->rsys, &ep->rserv);
  172. return ep;
  173. }
  174. void
  175. freeendpoints(Endpoints *ep)
  176. {
  177. free(ep->lsys);
  178. free(ep->rsys);
  179. free(ep->lserv);
  180. free(ep->rserv);
  181. free(ep);
  182. }
  183. char*
  184. iptomac(char *ip, char *net)
  185. {
  186. char file[Maxpath];
  187. Biobuf *b;
  188. char *p;
  189. char *f[5];
  190. snprint(file, sizeof(file), "%s/arp", net);
  191. b = Bopen(file, OREAD);
  192. if(b == nil)
  193. return nil;
  194. while((p = Brdline(b, '\n')) != nil){
  195. p[Blinelen(b)-1] = 0;
  196. if(tokenize(p, f, nelem(f)) < 4)
  197. continue;
  198. if(strcmp(f[1], "OK") == 0
  199. && strcmp(f[2], ip) == 0){
  200. p = strdup(f[3]);
  201. Bterm(b);
  202. return p;
  203. }
  204. }
  205. Bterm(b);
  206. return nil;
  207. }
  208. int
  209. macok(char *mac)
  210. {
  211. char *p;
  212. if(mac == nil)
  213. return 0;
  214. free(p = csgetvalue("/net", "ether", mac, "trampok", nil));
  215. return !(p == nil);
  216. }