devip.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938
  1. #include "u.h"
  2. #include "lib.h"
  3. #include "dat.h"
  4. #include "fns.h"
  5. #include "error.h"
  6. #include "devip.h"
  7. void hnputl(void *p, unsigned long v);
  8. void hnputs(void *p, unsigned short v);
  9. unsigned long nhgetl(void *p);
  10. unsigned short nhgets(void *p);
  11. unsigned long parseip(char *to, char *from);
  12. void csclose(Chan*);
  13. long csread(Chan*, void*, long, vlong);
  14. long cswrite(Chan*, void*, long, vlong);
  15. void osipinit(void);
  16. enum
  17. {
  18. Qtopdir = 1, /* top level directory */
  19. Qcs,
  20. Qprotodir, /* directory for a protocol */
  21. Qclonus,
  22. Qconvdir, /* directory for a conversation */
  23. Qdata,
  24. Qctl,
  25. Qstatus,
  26. Qremote,
  27. Qlocal,
  28. Qlisten,
  29. MAXPROTO = 4
  30. };
  31. #define TYPE(x) ((int)((x).path & 0xf))
  32. #define CONV(x) ((int)(((x).path >> 4)&0xfff))
  33. #define PROTO(x) ((int)(((x).path >> 16)&0xff))
  34. #define QID(p, c, y) (((p)<<16) | ((c)<<4) | (y))
  35. typedef struct Proto Proto;
  36. typedef struct Conv Conv;
  37. struct Conv
  38. {
  39. int x;
  40. Ref r;
  41. int sfd;
  42. int perm;
  43. char owner[KNAMELEN];
  44. char* state;
  45. ulong laddr;
  46. ushort lport;
  47. ulong raddr;
  48. ushort rport;
  49. int restricted;
  50. char cerr[KNAMELEN];
  51. Proto* p;
  52. };
  53. struct Proto
  54. {
  55. Lock l;
  56. int x;
  57. int stype;
  58. char name[KNAMELEN];
  59. int nc;
  60. int maxconv;
  61. Conv** conv;
  62. Qid qid;
  63. };
  64. static int np;
  65. static Proto proto[MAXPROTO];
  66. int eipfmt(Fmt*);
  67. static Conv* protoclone(Proto*, char*, int);
  68. static void setladdr(Conv*);
  69. int
  70. ipgen(Chan *c, char *nname, Dirtab *d, int nd, int s, Dir *dp)
  71. {
  72. Qid q;
  73. Conv *cv;
  74. char *p;
  75. USED(nname);
  76. q.vers = 0;
  77. q.type = 0;
  78. switch(TYPE(c->qid)) {
  79. case Qtopdir:
  80. if(s >= 1+np)
  81. return -1;
  82. if(s == 0){
  83. q.path = QID(s, 0, Qcs);
  84. devdir(c, q, "cs", 0, "network", 0666, dp);
  85. }else{
  86. s--;
  87. q.path = QID(s, 0, Qprotodir);
  88. q.type = QTDIR;
  89. devdir(c, q, proto[s].name, 0, "network", DMDIR|0555, dp);
  90. }
  91. return 1;
  92. case Qprotodir:
  93. if(s < proto[PROTO(c->qid)].nc) {
  94. cv = proto[PROTO(c->qid)].conv[s];
  95. sprint(up->genbuf, "%d", s);
  96. q.path = QID(PROTO(c->qid), s, Qconvdir);
  97. q.type = QTDIR;
  98. devdir(c, q, up->genbuf, 0, cv->owner, DMDIR|0555, dp);
  99. return 1;
  100. }
  101. s -= proto[PROTO(c->qid)].nc;
  102. switch(s) {
  103. default:
  104. return -1;
  105. case 0:
  106. p = "clone";
  107. q.path = QID(PROTO(c->qid), 0, Qclonus);
  108. break;
  109. }
  110. devdir(c, q, p, 0, "network", 0555, dp);
  111. return 1;
  112. case Qconvdir:
  113. cv = proto[PROTO(c->qid)].conv[CONV(c->qid)];
  114. switch(s) {
  115. default:
  116. return -1;
  117. case 0:
  118. q.path = QID(PROTO(c->qid), CONV(c->qid), Qdata);
  119. devdir(c, q, "data", 0, cv->owner, cv->perm, dp);
  120. return 1;
  121. case 1:
  122. q.path = QID(PROTO(c->qid), CONV(c->qid), Qctl);
  123. devdir(c, q, "ctl", 0, cv->owner, cv->perm, dp);
  124. return 1;
  125. case 2:
  126. p = "status";
  127. q.path = QID(PROTO(c->qid), CONV(c->qid), Qstatus);
  128. break;
  129. case 3:
  130. p = "remote";
  131. q.path = QID(PROTO(c->qid), CONV(c->qid), Qremote);
  132. break;
  133. case 4:
  134. p = "local";
  135. q.path = QID(PROTO(c->qid), CONV(c->qid), Qlocal);
  136. break;
  137. case 5:
  138. p = "listen";
  139. q.path = QID(PROTO(c->qid), CONV(c->qid), Qlisten);
  140. break;
  141. }
  142. devdir(c, q, p, 0, cv->owner, 0444, dp);
  143. return 1;
  144. }
  145. return -1;
  146. }
  147. static void
  148. newproto(char *name, int type, int maxconv)
  149. {
  150. int l;
  151. Proto *p;
  152. if(np >= MAXPROTO) {
  153. print("no %s: increase MAXPROTO", name);
  154. return;
  155. }
  156. p = &proto[np];
  157. strcpy(p->name, name);
  158. p->stype = type;
  159. p->qid.path = QID(np, 0, Qprotodir);
  160. p->qid.type = QTDIR;
  161. p->x = np++;
  162. p->maxconv = maxconv;
  163. l = sizeof(Conv*)*(p->maxconv+1);
  164. p->conv = mallocz(l, 1);
  165. if(p->conv == 0)
  166. panic("no memory");
  167. }
  168. void
  169. ipinit(void)
  170. {
  171. osipinit();
  172. newproto("udp", S_UDP, 10);
  173. newproto("tcp", S_TCP, 30);
  174. fmtinstall('I', eipfmt);
  175. fmtinstall('E', eipfmt);
  176. }
  177. Chan *
  178. ipattach(char *spec)
  179. {
  180. Chan *c;
  181. c = devattach('I', spec);
  182. c->qid.path = QID(0, 0, Qtopdir);
  183. c->qid.type = QTDIR;
  184. c->qid.vers = 0;
  185. return c;
  186. }
  187. static Walkqid*
  188. ipwalk(Chan *c, Chan *nc, char **name, int nname)
  189. {
  190. return devwalk(c, nc, name, nname, 0, 0, ipgen);
  191. }
  192. int
  193. ipstat(Chan *c, uchar *dp, int n)
  194. {
  195. return devstat(c, dp, n, 0, 0, ipgen);
  196. }
  197. Chan *
  198. ipopen(Chan *c, int omode)
  199. {
  200. Proto *p;
  201. ulong raddr;
  202. ushort rport;
  203. int perm, sfd;
  204. Conv *cv, *lcv;
  205. omode &= 3;
  206. perm = 0;
  207. switch(omode) {
  208. case OREAD:
  209. perm = 4;
  210. break;
  211. case OWRITE:
  212. perm = 2;
  213. break;
  214. case ORDWR:
  215. perm = 6;
  216. break;
  217. }
  218. switch(TYPE(c->qid)) {
  219. default:
  220. break;
  221. case Qtopdir:
  222. case Qprotodir:
  223. case Qconvdir:
  224. case Qstatus:
  225. case Qremote:
  226. case Qlocal:
  227. if(omode != OREAD)
  228. error(Eperm);
  229. break;
  230. case Qclonus:
  231. p = &proto[PROTO(c->qid)];
  232. cv = protoclone(p, up->user, -1);
  233. if(cv == 0)
  234. error(Enodev);
  235. c->qid.path = QID(p->x, cv->x, Qctl);
  236. c->qid.vers = 0;
  237. break;
  238. case Qdata:
  239. case Qctl:
  240. p = &proto[PROTO(c->qid)];
  241. lock(&p->l);
  242. cv = p->conv[CONV(c->qid)];
  243. lock(&cv->r.lk);
  244. if((perm & (cv->perm>>6)) != perm) {
  245. if(strcmp(up->user, cv->owner) != 0 ||
  246. (perm & cv->perm) != perm) {
  247. unlock(&cv->r.lk);
  248. unlock(&p->l);
  249. error(Eperm);
  250. }
  251. }
  252. cv->r.ref++;
  253. if(cv->r.ref == 1) {
  254. memmove(cv->owner, up->user, KNAMELEN);
  255. cv->perm = 0660;
  256. }
  257. unlock(&cv->r.lk);
  258. unlock(&p->l);
  259. break;
  260. case Qlisten:
  261. p = &proto[PROTO(c->qid)];
  262. lcv = p->conv[CONV(c->qid)];
  263. sfd = so_accept(lcv->sfd, &raddr, &rport);
  264. cv = protoclone(p, up->user, sfd);
  265. if(cv == 0) {
  266. close(sfd);
  267. error(Enodev);
  268. }
  269. cv->raddr = raddr;
  270. cv->rport = rport;
  271. setladdr(cv);
  272. cv->state = "Established";
  273. c->qid.path = QID(p->x, cv->x, Qctl);
  274. break;
  275. }
  276. c->mode = openmode(omode);
  277. c->flag |= COPEN;
  278. c->offset = 0;
  279. return c;
  280. }
  281. void
  282. ipclose(Chan *c)
  283. {
  284. Conv *cc;
  285. switch(TYPE(c->qid)) {
  286. case Qcs:
  287. csclose(c);
  288. break;
  289. case Qdata:
  290. case Qctl:
  291. if((c->flag & COPEN) == 0)
  292. break;
  293. cc = proto[PROTO(c->qid)].conv[CONV(c->qid)];
  294. if(decref(&cc->r) != 0)
  295. break;
  296. strcpy(cc->owner, "network");
  297. cc->perm = 0666;
  298. cc->state = "Closed";
  299. cc->laddr = 0;
  300. cc->raddr = 0;
  301. cc->lport = 0;
  302. cc->rport = 0;
  303. close(cc->sfd);
  304. break;
  305. }
  306. }
  307. long
  308. ipread(Chan *ch, void *a, long n, vlong offset)
  309. {
  310. int r;
  311. Conv *c;
  312. Proto *x;
  313. uchar ip[4];
  314. char buf[128], *p;
  315. /*print("ipread %s %lux\n", c2name(ch), (long)ch->qid.path);*/
  316. p = a;
  317. switch(TYPE(ch->qid)) {
  318. default:
  319. error(Eperm);
  320. case Qcs:
  321. return csread(ch, a, n, offset);
  322. case Qprotodir:
  323. case Qtopdir:
  324. case Qconvdir:
  325. return devdirread(ch, a, n, 0, 0, ipgen);
  326. case Qctl:
  327. sprint(buf, "%d", CONV(ch->qid));
  328. return readstr(offset, p, n, buf);
  329. case Qremote:
  330. c = proto[PROTO(ch->qid)].conv[CONV(ch->qid)];
  331. hnputl(ip, c->raddr);
  332. sprint(buf, "%I!%d\n", ip, c->rport);
  333. return readstr(offset, p, n, buf);
  334. case Qlocal:
  335. c = proto[PROTO(ch->qid)].conv[CONV(ch->qid)];
  336. hnputl(ip, c->laddr);
  337. sprint(buf, "%I!%d\n", ip, c->lport);
  338. return readstr(offset, p, n, buf);
  339. case Qstatus:
  340. x = &proto[PROTO(ch->qid)];
  341. c = x->conv[CONV(ch->qid)];
  342. sprint(buf, "%s/%d %d %s \n",
  343. c->p->name, c->x, c->r.ref, c->state);
  344. return readstr(offset, p, n, buf);
  345. case Qdata:
  346. c = proto[PROTO(ch->qid)].conv[CONV(ch->qid)];
  347. r = so_recv(c->sfd, a, n, 0);
  348. if(r < 0){
  349. oserrstr();
  350. nexterror();
  351. }
  352. return r;
  353. }
  354. }
  355. static void
  356. setladdr(Conv *c)
  357. {
  358. so_getsockname(c->sfd, &c->laddr, &c->lport);
  359. }
  360. static void
  361. setlport(Conv *c)
  362. {
  363. if(c->restricted == 0 && c->lport == 0)
  364. return;
  365. so_bind(c->sfd, c->restricted, c->lport);
  366. }
  367. static void
  368. setladdrport(Conv *c, char *str)
  369. {
  370. char *p, addr[4];
  371. p = strchr(str, '!');
  372. if(p == 0) {
  373. p = str;
  374. c->laddr = 0;
  375. }
  376. else {
  377. *p++ = 0;
  378. parseip(addr, str);
  379. c->laddr = nhgetl((uchar*)addr);
  380. }
  381. if(*p == '*')
  382. c->lport = 0;
  383. else
  384. c->lport = atoi(p);
  385. setlport(c);
  386. }
  387. static char*
  388. setraddrport(Conv *c, char *str)
  389. {
  390. char *p, addr[4];
  391. p = strchr(str, '!');
  392. if(p == 0)
  393. return "malformed address";
  394. *p++ = 0;
  395. parseip(addr, str);
  396. c->raddr = nhgetl((uchar*)addr);
  397. c->rport = atoi(p);
  398. p = strchr(p, '!');
  399. if(p) {
  400. if(strcmp(p, "!r") == 0)
  401. c->restricted = 1;
  402. }
  403. return 0;
  404. }
  405. long
  406. ipwrite(Chan *ch, void *a, long n, vlong offset)
  407. {
  408. Conv *c;
  409. Proto *x;
  410. int r, nf;
  411. char *p, *fields[3], buf[128];
  412. switch(TYPE(ch->qid)) {
  413. default:
  414. error(Eperm);
  415. case Qcs:
  416. return cswrite(ch, a, n, offset);
  417. case Qctl:
  418. x = &proto[PROTO(ch->qid)];
  419. c = x->conv[CONV(ch->qid)];
  420. if(n > sizeof(buf)-1)
  421. n = sizeof(buf)-1;
  422. memmove(buf, a, n);
  423. buf[n] = '\0';
  424. nf = tokenize(buf, fields, 3);
  425. if(strcmp(fields[0], "connect") == 0){
  426. switch(nf) {
  427. default:
  428. error("bad args to connect");
  429. case 2:
  430. p = setraddrport(c, fields[1]);
  431. if(p != 0)
  432. error(p);
  433. break;
  434. case 3:
  435. p = setraddrport(c, fields[1]);
  436. if(p != 0)
  437. error(p);
  438. c->lport = atoi(fields[2]);
  439. setlport(c);
  440. break;
  441. }
  442. so_connect(c->sfd, c->raddr, c->rport);
  443. setladdr(c);
  444. c->state = "Established";
  445. return n;
  446. }
  447. if(strcmp(fields[0], "announce") == 0) {
  448. switch(nf){
  449. default:
  450. error("bad args to announce");
  451. case 2:
  452. setladdrport(c, fields[1]);
  453. break;
  454. }
  455. so_listen(c->sfd);
  456. c->state = "Announced";
  457. return n;
  458. }
  459. if(strcmp(fields[0], "bind") == 0){
  460. switch(nf){
  461. default:
  462. error("bad args to bind");
  463. case 2:
  464. c->lport = atoi(fields[1]);
  465. break;
  466. }
  467. setlport(c);
  468. return n;
  469. }
  470. error("bad control message");
  471. case Qdata:
  472. x = &proto[PROTO(ch->qid)];
  473. c = x->conv[CONV(ch->qid)];
  474. r = so_send(c->sfd, a, n, 0);
  475. if(r < 0){
  476. oserrstr();
  477. nexterror();
  478. }
  479. return r;
  480. }
  481. return n;
  482. }
  483. static Conv*
  484. protoclone(Proto *p, char *user, int nfd)
  485. {
  486. Conv *c, **pp, **ep;
  487. c = 0;
  488. lock(&p->l);
  489. if(waserror()) {
  490. unlock(&p->l);
  491. nexterror();
  492. }
  493. ep = &p->conv[p->maxconv];
  494. for(pp = p->conv; pp < ep; pp++) {
  495. c = *pp;
  496. if(c == 0) {
  497. c = mallocz(sizeof(Conv), 1);
  498. if(c == 0)
  499. error(Enomem);
  500. lock(&c->r.lk);
  501. c->r.ref = 1;
  502. c->p = p;
  503. c->x = pp - p->conv;
  504. p->nc++;
  505. *pp = c;
  506. break;
  507. }
  508. lock(&c->r.lk);
  509. if(c->r.ref == 0) {
  510. c->r.ref++;
  511. break;
  512. }
  513. unlock(&c->r.lk);
  514. }
  515. if(pp >= ep) {
  516. unlock(&p->l);
  517. poperror();
  518. return 0;
  519. }
  520. strcpy(c->owner, user);
  521. c->perm = 0660;
  522. c->state = "Closed";
  523. c->restricted = 0;
  524. c->laddr = 0;
  525. c->raddr = 0;
  526. c->lport = 0;
  527. c->rport = 0;
  528. c->sfd = nfd;
  529. if(nfd == -1)
  530. c->sfd = so_socket(p->stype);
  531. unlock(&c->r.lk);
  532. unlock(&p->l);
  533. poperror();
  534. return c;
  535. }
  536. enum
  537. {
  538. Isprefix= 16,
  539. };
  540. uchar prefixvals[256] =
  541. {
  542. /*0x00*/ 0 | Isprefix,
  543. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  544. /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  545. /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  546. /*0x30*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  547. /*0x40*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  548. /*0x50*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  549. /*0x60*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  550. /*0x70*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  551. /*0x80*/ 1 | Isprefix,
  552. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  553. /*0x90*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  554. /*0xA0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  555. /*0xB0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  556. /*0xC0*/ 2 | Isprefix,
  557. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  558. /*0xD0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  559. /*0xE0*/ 3 | Isprefix,
  560. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  561. /*0xF0*/ 4 | Isprefix,
  562. 0, 0, 0, 0, 0, 0, 0,
  563. /*0xF8*/ 5 | Isprefix,
  564. 0, 0, 0,
  565. /*0xFC*/ 6 | Isprefix,
  566. 0,
  567. /*0xFE*/ 7 | Isprefix,
  568. /*0xFF*/ 8 | Isprefix,
  569. };
  570. int
  571. eipfmt(Fmt *f)
  572. {
  573. char buf[5*8];
  574. static char *efmt = "%.2lux%.2lux%.2lux%.2lux%.2lux%.2lux";
  575. static char *ifmt = "%d.%d.%d.%d";
  576. uchar *p, ip[16];
  577. ulong ul;
  578. switch(f->r) {
  579. case 'E': /* Ethernet address */
  580. p = va_arg(f->args, uchar*);
  581. snprint(buf, sizeof buf, efmt, p[0], p[1], p[2], p[3], p[4], p[5]);
  582. return fmtstrcpy(f, buf);
  583. case 'I':
  584. ul = va_arg(f->args, ulong);
  585. hnputl(ip, ul);
  586. snprint(buf, sizeof buf, ifmt, ip[0], ip[1], ip[2], ip[3]);
  587. return fmtstrcpy(f, buf);
  588. }
  589. return fmtstrcpy(f, "(eipfmt)");
  590. }
  591. void
  592. hnputl(void *p, unsigned long v)
  593. {
  594. unsigned char *a;
  595. a = p;
  596. a[0] = v>>24;
  597. a[1] = v>>16;
  598. a[2] = v>>8;
  599. a[3] = v;
  600. }
  601. void
  602. hnputs(void *p, unsigned short v)
  603. {
  604. unsigned char *a;
  605. a = p;
  606. a[0] = v>>8;
  607. a[1] = v;
  608. }
  609. unsigned long
  610. nhgetl(void *p)
  611. {
  612. unsigned char *a;
  613. a = p;
  614. return (a[0]<<24)|(a[1]<<16)|(a[2]<<8)|(a[3]<<0);
  615. }
  616. unsigned short
  617. nhgets(void *p)
  618. {
  619. unsigned char *a;
  620. a = p;
  621. return (a[0]<<8)|(a[1]<<0);
  622. }
  623. #define CLASS(p) ((*(unsigned char*)(p))>>6)
  624. unsigned long
  625. parseip(char *to, char *from)
  626. {
  627. int i;
  628. char *p;
  629. p = from;
  630. memset(to, 0, 4);
  631. for(i = 0; i < 4 && *p; i++){
  632. to[i] = strtoul(p, &p, 10);
  633. if(*p != '.' && *p != 0){
  634. memset(to, 0, 4);
  635. return 0;
  636. }
  637. if(*p == '.')
  638. p++;
  639. }
  640. switch(CLASS(to)){
  641. case 0: /* class A - 1 byte net */
  642. case 1:
  643. if(i == 3){
  644. to[3] = to[2];
  645. to[2] = to[1];
  646. to[1] = 0;
  647. } else if (i == 2){
  648. to[3] = to[1];
  649. to[1] = 0;
  650. }
  651. break;
  652. case 2: /* class B - 2 byte net */
  653. if(i == 3){
  654. to[3] = to[2];
  655. to[2] = 0;
  656. }
  657. break;
  658. }
  659. return nhgetl(to);
  660. }
  661. void
  662. csclose(Chan *c)
  663. {
  664. free(c->aux);
  665. }
  666. long
  667. csread(Chan *c, void *a, long n, vlong offset)
  668. {
  669. if(c->aux == nil)
  670. return 0;
  671. return readstr(offset, a, n, c->aux);
  672. }
  673. static struct
  674. {
  675. char *name;
  676. uint num;
  677. } tab[] = {
  678. "cs", 1,
  679. "echo", 7,
  680. "discard", 9,
  681. "systat", 11,
  682. "daytime", 13,
  683. "netstat", 15,
  684. "chargen", 19,
  685. "ftp-data", 20,
  686. "ftp", 21,
  687. "ssh", 22,
  688. "telnet", 23,
  689. "smtp", 25,
  690. "time", 37,
  691. "whois", 43,
  692. "dns", 53,
  693. "domain", 53,
  694. "uucp", 64,
  695. "gopher", 70,
  696. "rje", 77,
  697. "finger", 79,
  698. "http", 80,
  699. "link", 87,
  700. "supdup", 95,
  701. "hostnames", 101,
  702. "iso-tsap", 102,
  703. "x400", 103,
  704. "x400-snd", 104,
  705. "csnet-ns", 105,
  706. "pop-2", 109,
  707. "pop3", 110,
  708. "portmap", 111,
  709. "uucp-path", 117,
  710. "nntp", 119,
  711. "netbios", 139,
  712. "imap4", 143,
  713. "NeWS", 144,
  714. "print-srv", 170,
  715. "z39.50", 210,
  716. "fsb", 400,
  717. "sysmon", 401,
  718. "proxy", 402,
  719. "proxyd", 404,
  720. "https", 443,
  721. "cifs", 445,
  722. "ssmtp", 465,
  723. "rexec", 512,
  724. "login", 513,
  725. "shell", 514,
  726. "printer", 515,
  727. "courier", 530,
  728. "cscan", 531,
  729. "uucp", 540,
  730. "snntp", 563,
  731. "9fs", 564,
  732. "whoami", 565,
  733. "guard", 566,
  734. "ticket", 567,
  735. "dlsftp", 666,
  736. "fmclient", 729,
  737. "imaps", 993,
  738. "pop3s", 995,
  739. "ingreslock", 1524,
  740. "pptp", 1723,
  741. "nfs", 2049,
  742. "webster", 2627,
  743. "weather", 3000,
  744. "secstore", 5356,
  745. "Xdisplay", 6000,
  746. "styx", 6666,
  747. "mpeg", 6667,
  748. "rstyx", 6668,
  749. "infdb", 6669,
  750. "infsigner", 6671,
  751. "infcsigner", 6672,
  752. "inflogin", 6673,
  753. "bandt", 7330,
  754. "face", 32000,
  755. "dhashgate", 11978,
  756. "exportfs", 17007,
  757. "rexexec", 17009,
  758. "ncpu", 17010,
  759. "cpu", 17013,
  760. "glenglenda1", 17020,
  761. "glenglenda2", 17021,
  762. "glenglenda3", 17022,
  763. "glenglenda4", 17023,
  764. "glenglenda5", 17024,
  765. "glenglenda6", 17025,
  766. "glenglenda7", 17026,
  767. "glenglenda8", 17027,
  768. "glenglenda9", 17028,
  769. "glenglenda10", 17029,
  770. "flyboy", 17032,
  771. "dlsftp", 17033,
  772. "venti", 17034,
  773. "wiki", 17035,
  774. "vica", 17036,
  775. 0
  776. };
  777. static int
  778. lookupport(char *s)
  779. {
  780. int i;
  781. char buf[10], *p;
  782. i = strtol(s, &p, 0);
  783. if(*s && *p == 0)
  784. return i;
  785. i = so_getservbyname(s, "tcp", buf);
  786. if(i != -1)
  787. return atoi(buf);
  788. for(i=0; tab[i].name; i++)
  789. if(strcmp(s, tab[i].name) == 0)
  790. return tab[i].num;
  791. return 0;
  792. }
  793. static ulong
  794. lookuphost(char *s)
  795. {
  796. char to[4];
  797. ulong ip;
  798. memset(to, 0, sizeof to);
  799. parseip(to, s);
  800. ip = nhgetl(to);
  801. if(ip != 0)
  802. return ip;
  803. if((s = hostlookup(s)) == nil)
  804. return 0;
  805. parseip(to, s);
  806. ip = nhgetl(to);
  807. free(s);
  808. return ip;
  809. }
  810. long
  811. cswrite(Chan *c, void *a, long n, vlong offset)
  812. {
  813. char *f[4];
  814. char *s, *ns;
  815. ulong ip;
  816. int nf, port;
  817. s = malloc(n+1);
  818. if(s == nil)
  819. error(Enomem);
  820. if(waserror()){
  821. free(s);
  822. nexterror();
  823. }
  824. memmove(s, a, n);
  825. s[n] = 0;
  826. nf = getfields(s, f, nelem(f), 0, "!");
  827. if(nf != 3)
  828. error("can't translate");
  829. port = lookupport(f[2]);
  830. if(port <= 0)
  831. error("no translation for port found");
  832. ip = lookuphost(f[1]);
  833. if(ip == 0)
  834. error("no translation for host found");
  835. ns = smprint("/net/%s/clone %I!%d", f[0], ip, port);
  836. if(ns == nil)
  837. error(Enomem);
  838. free(c->aux);
  839. c->aux = ns;
  840. poperror();
  841. free(s);
  842. return n;
  843. }
  844. Dev ipdevtab =
  845. {
  846. 'I',
  847. "ip",
  848. devreset,
  849. ipinit,
  850. devshutdown,
  851. ipattach,
  852. ipwalk,
  853. ipstat,
  854. ipopen,
  855. devcreate,
  856. ipclose,
  857. ipread,
  858. devbread,
  859. ipwrite,
  860. devbwrite,
  861. devremove,
  862. devwstat,
  863. };