devip.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119
  1. #include "dat.h"
  2. #include "fns.h"
  3. #include "error.h"
  4. #include "ip.h"
  5. enum
  6. {
  7. Qtopdir = 1, /* top level directory */
  8. Qtopbase,
  9. Qarp= Qtopbase,
  10. /* Qiproute, */
  11. /* Qipselftab, */
  12. Qndb,
  13. Qprotodir, /* directory for a protocol */
  14. Qprotobase,
  15. Qclone= Qprotobase,
  16. Qstats,
  17. Qconvdir, /* directory for a conversation */
  18. Qconvbase,
  19. Qctl= Qconvbase,
  20. Qdata,
  21. Qlisten,
  22. Qlocal,
  23. Qremote,
  24. Qstatus,
  25. Logtype= 5,
  26. Masktype= (1<<Logtype)-1,
  27. Logconv= 12,
  28. Maskconv= (1<<Logconv)-1,
  29. Shiftconv= Logtype,
  30. Logproto= 8,
  31. Maskproto= (1<<Logproto)-1,
  32. Shiftproto= Logtype + Logconv,
  33. Statelen = 256,
  34. Nfs= 1,
  35. Maxproto = 4,
  36. MAXCONV = 4096
  37. };
  38. #define TYPE(x) ( ((ulong)(x).path) & Masktype )
  39. #define CONV(x) ( (((ulong)(x).path) >> Shiftconv) & Maskconv )
  40. #define PROTO(x) ( (((ulong)(x).path) >> Shiftproto) & Maskproto )
  41. #define QID(p, c, y) ( ((p)<<(Shiftproto)) | ((c)<<Shiftconv) | (y) )
  42. enum
  43. {
  44. Idle= 0,
  45. Announcing= 1,
  46. Announced= 2,
  47. Connecting= 3,
  48. Connected= 4,
  49. Hungup= 5,
  50. };
  51. struct Conv
  52. {
  53. QLock l;
  54. int x; /* conversation index */
  55. Proto* p;
  56. uchar laddr[IPaddrlen]; /* local IP address */
  57. uchar raddr[IPaddrlen]; /* remote IP address */
  58. int restricted; /* remote port is restricted */
  59. ushort lport; /* local port number */
  60. ushort rport; /* remote port number */
  61. char* owner; /* protections */
  62. int perm;
  63. int inuse; /* opens of listen/data/ctl */
  64. int state;
  65. /* udp specific */
  66. int headers; /* data src/dst headers in udp */
  67. char cerr[ERRMAX];
  68. QLock listenq;
  69. void* ptcl; /* protocol specific stuff */
  70. int sfd;
  71. QLock wlock; /* prevent data from being split by concurrent writes */
  72. };
  73. struct Proto
  74. {
  75. QLock l;
  76. int x;
  77. int ipproto;
  78. int stype;
  79. char* name;
  80. int maxconv;
  81. Fs* f; /* file system this proto is part of */
  82. Conv** conv; /* array of conversations */
  83. int pctlsize; /* size of per protocol ctl block */
  84. int nc; /* number of conversations */
  85. int ac;
  86. Qid qid; /* qid for protocol directory */
  87. /* port allocation isn't done here when hosted */
  88. void* priv;
  89. };
  90. /*
  91. * one per IP protocol stack
  92. */
  93. struct Fs
  94. {
  95. RWlock l;
  96. int dev;
  97. int np;
  98. Proto* p[Maxproto+1]; /* list of supported protocols */
  99. Proto* t2p[256]; /* vector of all protocols */
  100. char ndb[1024]; /* an ndb entry for this interface */
  101. int ndbvers;
  102. long ndbmtime;
  103. };
  104. static Fs *ipfs[Nfs]; /* attached fs's */
  105. static char network[] = "network";
  106. static char* ipstates[] = {
  107. "Closed", /* Idle */
  108. "Announcing",
  109. "Announced",
  110. "Connecting",
  111. "Established", /* Connected */
  112. "Closed", /* Hungup */
  113. };
  114. static Conv* protoclone(Proto*, char*, int);
  115. static Conv* newconv(Proto*, Conv **);
  116. static void setladdr(Conv*);
  117. static int
  118. ip3gen(Chan *c, int i, Dir *dp)
  119. {
  120. Qid q;
  121. Conv *cv;
  122. char *p;
  123. cv = ipfs[c->dev]->p[PROTO(c->qid)]->conv[CONV(c->qid)];
  124. if(cv->owner == nil)
  125. kstrdup(&cv->owner, eve);
  126. mkqid(&q, QID(PROTO(c->qid), CONV(c->qid), i), 0, QTFILE);
  127. switch(i) {
  128. default:
  129. return -1;
  130. case Qctl:
  131. devdir(c, q, "ctl", 0, cv->owner, cv->perm, dp);
  132. return 1;
  133. case Qdata:
  134. devdir(c, q, "data", 0, cv->owner, cv->perm, dp);
  135. return 1;
  136. case Qlisten:
  137. devdir(c, q, "listen", 0, cv->owner, cv->perm, dp);
  138. return 1;
  139. case Qlocal:
  140. p = "local";
  141. break;
  142. case Qremote:
  143. p = "remote";
  144. break;
  145. case Qstatus:
  146. p = "status";
  147. break;
  148. }
  149. devdir(c, q, p, 0, cv->owner, 0444, dp);
  150. return 1;
  151. }
  152. static int
  153. ip2gen(Chan *c, int i, Dir *dp)
  154. {
  155. Qid q;
  156. switch(i) {
  157. case Qclone:
  158. mkqid(&q, QID(PROTO(c->qid), 0, Qclone), 0, QTFILE);
  159. devdir(c, q, "clone", 0, network, 0666, dp);
  160. return 1;
  161. case Qstats:
  162. mkqid(&q, QID(PROTO(c->qid), 0, Qstats), 0, QTFILE);
  163. devdir(c, q, "stats", 0, network, 0444, dp);
  164. return 1;
  165. }
  166. return -1;
  167. }
  168. static int
  169. ip1gen(Chan *c, int i, Dir *dp)
  170. {
  171. Qid q;
  172. char *p;
  173. int prot;
  174. int len = 0;
  175. Fs *f;
  176. extern ulong kerndate;
  177. f = ipfs[c->dev];
  178. prot = 0664;
  179. mkqid(&q, QID(0, 0, i), 0, QTFILE);
  180. switch(i) {
  181. default:
  182. return -1;
  183. case Qarp:
  184. p = "arp";
  185. break;
  186. case Qndb:
  187. p = "ndb";
  188. len = strlen(ipfs[c->dev]->ndb);
  189. break;
  190. /* case Qiproute:
  191. p = "iproute";
  192. break;
  193. case Qipselftab:
  194. p = "ipselftab";
  195. prot = 0444;
  196. break;
  197. case Qiprouter:
  198. p = "iprouter";
  199. break;
  200. case Qlog:
  201. p = "log";
  202. break;
  203. */
  204. }
  205. devdir(c, q, p, len, network, prot, dp);
  206. if(i == Qndb && f->ndbmtime > kerndate)
  207. dp->mtime = f->ndbmtime;
  208. return 1;
  209. }
  210. static int
  211. ipgen(Chan *c, char *name, Dirtab *tab, int x, int s, Dir *dp)
  212. {
  213. Qid q;
  214. Conv *cv;
  215. Fs *f;
  216. USED(name);
  217. USED(tab);
  218. USED(x);
  219. f = ipfs[c->dev];
  220. switch(TYPE(c->qid)) {
  221. case Qtopdir:
  222. if(s == DEVDOTDOT){
  223. mkqid(&q, QID(0, 0, Qtopdir), 0, QTDIR);
  224. sprint(up->genbuf, "#I%lud", c->dev);
  225. devdir(c, q, up->genbuf, 0, network, 0555, dp);
  226. return 1;
  227. }
  228. if(s < f->np) {
  229. /* if(f->p[s]->connect == nil)
  230. return 0; /* protocol with no user interface */
  231. mkqid(&q, QID(s, 0, Qprotodir), 0, QTDIR);
  232. devdir(c, q, f->p[s]->name, 0, network, 0555, dp);
  233. return 1;
  234. }
  235. s -= f->np;
  236. return ip1gen(c, s+Qtopbase, dp);
  237. case Qarp:
  238. case Qndb:
  239. /* case Qiproute:
  240. case Qiprouter:
  241. case Qipselftab: */
  242. return ip1gen(c, TYPE(c->qid), dp);
  243. case Qprotodir:
  244. if(s == DEVDOTDOT){
  245. mkqid(&q, QID(0, 0, Qtopdir), 0, QTDIR);
  246. sprint(up->genbuf, "#I%lud", c->dev);
  247. devdir(c, q, up->genbuf, 0, network, 0555, dp);
  248. return 1;
  249. }
  250. if(s < f->p[PROTO(c->qid)]->ac) {
  251. cv = f->p[PROTO(c->qid)]->conv[s];
  252. sprint(up->genbuf, "%d", s);
  253. mkqid(&q, QID(PROTO(c->qid), s, Qconvdir), 0, QTDIR);
  254. devdir(c, q, up->genbuf, 0, cv->owner, 0555, dp);
  255. return 1;
  256. }
  257. s -= f->p[PROTO(c->qid)]->ac;
  258. return ip2gen(c, s+Qprotobase, dp);
  259. case Qclone:
  260. case Qstats:
  261. return ip2gen(c, TYPE(c->qid), dp);
  262. case Qconvdir:
  263. if(s == DEVDOTDOT){
  264. s = PROTO(c->qid);
  265. mkqid(&q, QID(s, 0, Qprotodir), 0, QTDIR);
  266. devdir(c, q, f->p[s]->name, 0, network, 0555, dp);
  267. return 1;
  268. }
  269. return ip3gen(c, s+Qconvbase, dp);
  270. case Qctl:
  271. case Qdata:
  272. case Qlisten:
  273. case Qlocal:
  274. case Qremote:
  275. case Qstatus:
  276. return ip3gen(c, TYPE(c->qid), dp);
  277. }
  278. return -1;
  279. }
  280. static void
  281. newproto(char *name, int type, int maxconv)
  282. {
  283. Proto *p;
  284. p = smalloc(sizeof(*p));
  285. p->name = name;
  286. p->stype = type;
  287. p->ipproto = type+1; /* temporary */
  288. p->nc = maxconv;
  289. if(Fsproto(ipfs[0], p))
  290. panic("can't newproto %s", name);
  291. }
  292. void
  293. ipinit(void)
  294. {
  295. ipfs[0] = malloc(sizeof(Fs));
  296. if(ipfs[0] == nil)
  297. panic("no memory for IP stack");
  298. newproto("udp", S_UDP, 64);
  299. newproto("tcp", S_TCP, 2048);
  300. fmtinstall('i', eipfmt);
  301. fmtinstall('I', eipfmt);
  302. fmtinstall('E', eipfmt);
  303. fmtinstall('V', eipfmt);
  304. fmtinstall('M', eipfmt);
  305. }
  306. Chan *
  307. ipattach(char *spec)
  308. {
  309. Chan *c;
  310. if(atoi(spec) != 0)
  311. error("bad specification");
  312. c = devattach('I', spec);
  313. mkqid(&c->qid, QID(0, 0, Qtopdir), 0, QTDIR);
  314. c->dev = 0;
  315. return c;
  316. }
  317. static Walkqid*
  318. ipwalk(Chan* c, Chan *nc, char **name, int nname)
  319. {
  320. return devwalk(c, nc, name, nname, nil, 0, ipgen);
  321. }
  322. static int
  323. ipstat(Chan *c, uchar *db, int n)
  324. {
  325. return devstat(c, db, n, 0, 0, ipgen);
  326. }
  327. static int m2p[] = {
  328. 4,
  329. 2,
  330. 6,
  331. };
  332. static Chan *
  333. ipopen(Chan *c, int omode)
  334. {
  335. Conv *cv, *nc;
  336. Proto *p;
  337. uchar raddr[IPaddrlen];
  338. ushort rport;
  339. int perm, sfd;
  340. Fs *f;
  341. perm = m2p[omode&3];
  342. f = ipfs[c->dev];
  343. switch(TYPE(c->qid)) {
  344. default:
  345. break;
  346. case Qtopdir:
  347. case Qprotodir:
  348. case Qconvdir:
  349. case Qstatus:
  350. case Qremote:
  351. case Qlocal:
  352. case Qstats:
  353. /* case Qipselftab: */
  354. if(omode != OREAD)
  355. error(Eperm);
  356. break;
  357. case Qndb:
  358. if(omode & (OWRITE|OTRUNC) && !iseve())
  359. error(Eperm);
  360. if((omode & (OWRITE|OTRUNC)) == (OWRITE|OTRUNC)){
  361. f->ndb[0] = 0;
  362. f->ndbvers++;
  363. }
  364. break;
  365. case Qclone:
  366. p = f->p[PROTO(c->qid)];
  367. cv = protoclone(p, up->env->user, -1);
  368. if(cv == 0)
  369. error(Enodev);
  370. mkqid(&c->qid, QID(p->x, cv->x, Qctl), 0, QTFILE);
  371. break;
  372. case Qdata:
  373. case Qctl:
  374. p = f->p[PROTO(c->qid)];
  375. qlock(&p->l);
  376. cv = p->conv[CONV(c->qid)];
  377. qlock(&cv->l);
  378. if(waserror()){
  379. qunlock(&cv->l);
  380. qunlock(&p->l);
  381. nexterror();
  382. }
  383. if((perm & (cv->perm>>6)) != perm) {
  384. if(strcmp(up->env->user, cv->owner) != 0)
  385. error(Eperm);
  386. if((perm & cv->perm) != perm)
  387. error(Eperm);
  388. }
  389. cv->inuse++;
  390. if(cv->inuse == 1) {
  391. kstrdup(&cv->owner, up->env->user);
  392. cv->perm = 0660;
  393. if(cv->sfd < 0)
  394. cv->sfd = so_socket(p->stype);
  395. }
  396. poperror();
  397. qunlock(&cv->l);
  398. qunlock(&p->l);
  399. break;
  400. case Qlisten:
  401. p = f->p[PROTO(c->qid)];
  402. cv = p->conv[CONV(c->qid)];
  403. if((perm & (cv->perm>>6)) != perm){
  404. if(strcmp(up->env->user, cv->owner) != 0)
  405. error(Eperm);
  406. if((perm & cv->perm) != perm)
  407. error(Eperm);
  408. }
  409. if(cv->state != Announced)
  410. error("not announced");
  411. qlock(&cv->listenq);
  412. if(waserror()){
  413. qunlock(&cv->listenq);
  414. nexterror();
  415. }
  416. sfd = so_accept(cv->sfd, raddr, &rport);
  417. nc = protoclone(p, up->env->user, sfd);
  418. if(nc == 0) {
  419. so_close(sfd);
  420. error(Enodev);
  421. }
  422. memmove(nc->raddr, raddr, IPaddrlen);
  423. nc->rport = rport;
  424. setladdr(nc);
  425. nc->state = Connected;
  426. mkqid(&c->qid, QID(PROTO(c->qid), nc->x, Qctl), 0, QTFILE);
  427. poperror();
  428. qunlock(&cv->listenq);
  429. break;
  430. }
  431. c->mode = openmode(omode);
  432. c->flag |= COPEN;
  433. c->offset = 0;
  434. return c;
  435. }
  436. static void
  437. closeconv(Conv *cv)
  438. {
  439. int fd;
  440. qlock(&cv->l);
  441. if(--cv->inuse > 0) {
  442. qunlock(&cv->l);
  443. return;
  444. }
  445. if(waserror()){
  446. qunlock(&cv->l);
  447. return;
  448. }
  449. kstrdup(&cv->owner, network);
  450. cv->perm = 0660;
  451. /* cv->p->close(cv); */
  452. cv->state = Idle;
  453. cv->restricted = 0;
  454. fd = cv->sfd;
  455. cv->sfd = -1;
  456. if(fd >= 0)
  457. so_close(fd);
  458. poperror();
  459. qunlock(&cv->l);
  460. }
  461. static void
  462. ipclose(Chan *c)
  463. {
  464. Fs *f;
  465. f = ipfs[c->dev];
  466. switch(TYPE(c->qid)) {
  467. case Qdata:
  468. case Qctl:
  469. if(c->flag & COPEN)
  470. closeconv(f->p[PROTO(c->qid)]->conv[CONV(c->qid)]);
  471. break;
  472. }
  473. }
  474. static long
  475. ipread(Chan *ch, void *a, long n, vlong off)
  476. {
  477. int r;
  478. Conv *c;
  479. Proto *x;
  480. char *p, *s;
  481. Fs *f;
  482. ulong offset = off;
  483. f = ipfs[ch->dev];
  484. p = a;
  485. switch(TYPE(ch->qid)) {
  486. default:
  487. error(Eperm);
  488. case Qprotodir:
  489. case Qtopdir:
  490. case Qconvdir:
  491. return devdirread(ch, a, n, 0, 0, ipgen);
  492. case Qarp:
  493. error(Eperm); /* TO DO */
  494. case Qndb:
  495. return readstr(off, a, n, f->ndb);
  496. case Qctl:
  497. sprint(up->genbuf, "%lud", CONV(ch->qid));
  498. return readstr(offset, p, n, up->genbuf);
  499. case Qremote:
  500. x = f->p[PROTO(ch->qid)];
  501. c = x->conv[CONV(ch->qid)];
  502. sprint(up->genbuf, "%I!%d\n", c->raddr, c->rport);
  503. return readstr(offset, p, n, up->genbuf);
  504. case Qlocal:
  505. x = f->p[PROTO(ch->qid)];
  506. c = x->conv[CONV(ch->qid)];
  507. sprint(up->genbuf, "%I!%d\n", c->laddr, c->lport);
  508. return readstr(offset, p, n, up->genbuf);
  509. case Qstatus:
  510. x = f->p[PROTO(ch->qid)];
  511. c = x->conv[CONV(ch->qid)];
  512. s = smalloc(Statelen);
  513. if(waserror()){
  514. free(s);
  515. nexterror();
  516. }
  517. snprint(s, Statelen, "%s\n", ipstates[c->state]);
  518. n = readstr(offset, p, n, s);
  519. poperror();
  520. free(s);
  521. return n;
  522. case Qdata:
  523. x = f->p[PROTO(ch->qid)];
  524. c = x->conv[CONV(ch->qid)];
  525. if(c->sfd < 0)
  526. error(Ehungup);
  527. if(c->headers) {
  528. if(n < c->headers)
  529. error(Ebadarg);
  530. p = a;
  531. r = so_recv(c->sfd, p + c->headers, n - c->headers, p, c->headers);
  532. if(r >= 0)
  533. r += c->headers;
  534. } else
  535. r = so_recv(c->sfd, a, n, nil, 0);
  536. if(r < 0)
  537. oserror();
  538. return r;
  539. case Qstats:
  540. error("stats not implemented");
  541. return n;
  542. }
  543. }
  544. static void
  545. setladdr(Conv *c)
  546. {
  547. /* TO DO: this can't be right for hosts with several addresses before connect/accept */
  548. so_getsockname(c->sfd, c->laddr, &c->lport);
  549. }
  550. /*
  551. * pick a local port and set it
  552. */
  553. static void
  554. setlport(Conv *c)
  555. {
  556. uchar laddr[IPaddrlen];
  557. ushort p;
  558. so_bind(c->sfd, c->restricted, c->laddr, c->lport);
  559. if(c->lport == 0 || ipcmp(c->laddr, IPnoaddr) == 0){
  560. so_getsockname(c->sfd, laddr, &p);
  561. if(c->lport == 0)
  562. c->lport = p;
  563. if(ipcmp(c->laddr, IPnoaddr) == 0)
  564. memmove(c->laddr, laddr, sizeof laddr);
  565. }
  566. }
  567. static int
  568. portno(char *p)
  569. {
  570. long n;
  571. char *e;
  572. n = strtoul(p, &e, 0);
  573. if(p == e)
  574. error("non-numeric port number");
  575. return n;
  576. }
  577. /*
  578. * set a local address and port from a string of the form
  579. * [address!]port[!r]
  580. */
  581. static void
  582. setladdrport(Conv *c, char *str, int announcing)
  583. {
  584. char *p;
  585. int lport;
  586. /*
  587. * ignore restricted part if it exists. it's
  588. * meaningless on local ports.
  589. */
  590. p = strchr(str, '!');
  591. if(p != nil){
  592. *p++ = 0;
  593. if(strcmp(p, "r") == 0)
  594. p = nil;
  595. }
  596. c->lport = 0;
  597. if(p == nil){
  598. if(announcing)
  599. ipmove(c->laddr, IPnoaddr);
  600. else if(0)
  601. setladdr(c);
  602. p = str;
  603. } else {
  604. if(strcmp(str, "*") == 0)
  605. ipmove(c->laddr, IPnoaddr);
  606. else if(parseip(c->laddr, str) == 0)
  607. error("invalid IP address");
  608. }
  609. if(announcing && strcmp(p, "*") == 0){
  610. if(!iseve())
  611. error(Eperm);
  612. c->lport = 0;
  613. setlport(c);
  614. return;
  615. }
  616. lport = portno(p);
  617. if(lport <= 0)
  618. c->lport = 0;
  619. else
  620. c->lport = lport;
  621. setlport(c);
  622. }
  623. static char*
  624. setraddrport(Conv *c, char *str)
  625. {
  626. char *p;
  627. p = strchr(str, '!');
  628. if(p == nil)
  629. return "malformed address";
  630. *p++ = 0;
  631. if(parseip(c->raddr, str) == 0)
  632. return "invalid IP address";
  633. c->rport = portno(p);
  634. p = strchr(p, '!');
  635. if(p){
  636. if(strstr(p, "!r") != nil)
  637. c->restricted = 1;
  638. }
  639. return nil;
  640. }
  641. static void
  642. connectctlmsg(Proto *x, Conv *c, Cmdbuf *cb)
  643. {
  644. char *p;
  645. USED(x);
  646. if(c->state != Idle)
  647. error(Econinuse);
  648. c->state = Connecting;
  649. c->cerr[0] = '\0';
  650. switch(cb->nf) {
  651. default:
  652. error("bad args to connect");
  653. case 2:
  654. p = setraddrport(c, cb->f[1]);
  655. if(p != nil)
  656. error(p);
  657. break;
  658. case 3:
  659. p = setraddrport(c, cb->f[1]);
  660. if(p != nil)
  661. error(p);
  662. c->lport = portno(cb->f[2]);
  663. setlport(c);
  664. break;
  665. }
  666. qunlock(&c->l);
  667. if(waserror()){
  668. qlock(&c->l);
  669. c->state = Connected; /* sic */
  670. nexterror();
  671. }
  672. /* p = x->connect(c, cb->f, cb->nf); */
  673. so_connect(c->sfd, c->raddr, c->rport);
  674. qlock(&c->l);
  675. poperror();
  676. setladdr(c);
  677. c->state = Connected;
  678. }
  679. static void
  680. announcectlmsg(Proto *x, Conv *c, Cmdbuf *cb)
  681. {
  682. if(c->state != Idle)
  683. error(Econinuse);
  684. c->state = Announcing;
  685. c->cerr[0] = '\0';
  686. ipmove(c->raddr, IPnoaddr);
  687. c->rport = 0;
  688. switch(cb->nf){
  689. default:
  690. error("bad args to announce");
  691. case 2:
  692. setladdrport(c, cb->f[1], 1);
  693. break;
  694. }
  695. USED(x);
  696. /* p = x->announce(c, cb->f, cb->nf); */
  697. if(c->p->stype != S_UDP){
  698. qunlock(&c->l);
  699. if(waserror()){
  700. c->state = Announced; /* sic */
  701. qlock(&c->l);
  702. nexterror();
  703. }
  704. so_listen(c->sfd);
  705. qlock(&c->l);
  706. poperror();
  707. }
  708. c->state = Announced;
  709. }
  710. static void
  711. bindctlmsg(Proto *x, Conv *c, Cmdbuf *cb)
  712. {
  713. USED(x);
  714. switch(cb->nf){
  715. default:
  716. error("bad args to bind");
  717. case 2:
  718. setladdrport(c, cb->f[1], 0);
  719. break;
  720. }
  721. }
  722. static long
  723. ipwrite(Chan *ch, void *a, long n, vlong off)
  724. {
  725. Conv *c;
  726. Proto *x;
  727. char *p;
  728. Cmdbuf *cb;
  729. Fs *f;
  730. f = ipfs[ch->dev];
  731. switch(TYPE(ch->qid)) {
  732. default:
  733. error(Eperm);
  734. case Qdata:
  735. x = f->p[PROTO(ch->qid)];
  736. c = x->conv[CONV(ch->qid)];
  737. if(c->sfd < 0)
  738. error(Ehungup);
  739. qlock(&c->wlock);
  740. if(waserror()){
  741. qunlock(&c->wlock);
  742. nexterror();
  743. }
  744. if(c->headers) {
  745. if(n < c->headers)
  746. error(Eshort);
  747. p = a;
  748. n = so_send(c->sfd, p + c->headers, n - c->headers, p, c->headers);
  749. if(n >= 0)
  750. n += c->headers;
  751. } else
  752. n = so_send(c->sfd, a, n, nil, 0);
  753. poperror();
  754. qunlock(&c->wlock);
  755. if(n < 0)
  756. oserror();
  757. break;
  758. case Qarp:
  759. return arpwrite(a, n);
  760. case Qndb:
  761. if(off > strlen(f->ndb))
  762. error(Eio);
  763. if(off+n >= sizeof(f->ndb)-1)
  764. error(Eio);
  765. memmove(f->ndb+off, a, n);
  766. f->ndb[off+n] = 0;
  767. f->ndbvers++;
  768. f->ndbmtime = seconds();
  769. break;
  770. case Qctl:
  771. x = f->p[PROTO(ch->qid)];
  772. c = x->conv[CONV(ch->qid)];
  773. cb = parsecmd(a, n);
  774. qlock(&c->l);
  775. if(waserror()){
  776. qunlock(&c->l);
  777. free(cb);
  778. nexterror();
  779. }
  780. if(cb->nf < 1)
  781. error("short control request");
  782. if(strcmp(cb->f[0], "connect") == 0)
  783. connectctlmsg(x, c, cb);
  784. else if(strcmp(cb->f[0], "announce") == 0)
  785. announcectlmsg(x, c, cb);
  786. else if(strcmp(cb->f[0], "bind") == 0)
  787. bindctlmsg(x, c, cb);
  788. else if(strcmp(cb->f[0], "ttl") == 0){
  789. /* ignored */
  790. } else if(strcmp(cb->f[0], "tos") == 0){
  791. /* ignored */
  792. } else if(strcmp(cb->f[0], "ignoreadvice") == 0){
  793. /* ignored */
  794. } else if(strcmp(cb->f[0], "headers4") == 0){
  795. if(c->p->stype != S_UDP)
  796. error(Enoctl);
  797. c->headers = OUdphdrlenv4;
  798. } else if(strcmp(cb->f[0], "oldheaders") == 0){
  799. if(c->p->stype != S_UDP)
  800. error(Enoctl);
  801. c->headers = OUdphdrlen;
  802. } else if(strcmp(cb->f[0], "headers") == 0){
  803. if(c->p->stype != S_UDP)
  804. error(Enoctl);
  805. c->headers = Udphdrlen;
  806. } else if(strcmp(cb->f[0], "hangup") == 0){
  807. if(c->p->stype != S_TCP)
  808. error(Enoctl);
  809. qunlock(&c->l);
  810. if(waserror()){
  811. qlock(&c->l);
  812. nexterror();
  813. }
  814. /* TO DO: check fd status if socket close/hangup interrupted */
  815. if(c->sfd >= 0 && so_hangup(c->sfd, 1) < 0)
  816. oserror();
  817. qlock(&c->l);
  818. poperror();
  819. c->sfd = -1;
  820. c->state = Hungup;
  821. } else if(strcmp(cb->f[0], "keepalive") == 0){
  822. if(c->p->stype != S_TCP)
  823. error(Enoctl);
  824. if(c->sfd < 0)
  825. error("not connected");
  826. so_keepalive(c->sfd, cb->nf>1? atoi(cb->f[1]): 0);
  827. } else
  828. error(Enoctl);
  829. poperror();
  830. qunlock(&c->l);
  831. free(cb);
  832. break;
  833. }
  834. return n;
  835. }
  836. static int
  837. ipwstat(Chan *c, uchar *dp, int n)
  838. {
  839. Dir *d;
  840. Conv *cv;
  841. Proto *p;
  842. Fs *f;
  843. f = ipfs[c->dev];
  844. switch(TYPE(c->qid)) {
  845. default:
  846. error(Eperm);
  847. break;
  848. case Qctl:
  849. case Qdata:
  850. break;
  851. }
  852. d = smalloc(sizeof(*d)+n);
  853. if(waserror()){
  854. free(d);
  855. nexterror();
  856. }
  857. n = convM2D(dp, n, d, (char*)&d[1]);
  858. if(n == 0)
  859. error(Eshortstat);
  860. p = f->p[PROTO(c->qid)];
  861. cv = p->conv[CONV(c->qid)];
  862. if(!iseve() && strcmp(up->env->user, cv->owner) != 0)
  863. error(Eperm);
  864. if(!emptystr(d->uid))
  865. kstrdup(&cv->owner, d->uid);
  866. if(d->mode != ~0UL)
  867. cv->perm = d->mode & 0777;
  868. poperror();
  869. free(d);
  870. return n;
  871. }
  872. static Conv*
  873. protoclone(Proto *p, char *user, int nfd)
  874. {
  875. Conv *c, **pp, **ep, **np;
  876. int maxconv;
  877. c = 0;
  878. qlock(&p->l);
  879. if(waserror()) {
  880. qunlock(&p->l);
  881. nexterror();
  882. }
  883. ep = &p->conv[p->nc];
  884. for(pp = p->conv; pp < ep; pp++) {
  885. c = *pp;
  886. if(c == 0) {
  887. c = newconv(p, pp);
  888. break;
  889. }
  890. if(canqlock(&c->l)){
  891. if(c->inuse == 0)
  892. break;
  893. qunlock(&c->l);
  894. }
  895. }
  896. if(pp >= ep) {
  897. if(p->nc >= MAXCONV) {
  898. qunlock(&p->l);
  899. poperror();
  900. return 0;
  901. }
  902. maxconv = 2 * p->nc;
  903. if(maxconv > MAXCONV)
  904. maxconv = MAXCONV;
  905. np = realloc(p->conv, sizeof(Conv*) * maxconv);
  906. if(np == nil)
  907. error(Enomem);
  908. p->conv = np;
  909. pp = &p->conv[p->nc];
  910. memset(pp, 0, sizeof(Conv*)*(maxconv - p->nc));
  911. p->nc = maxconv;
  912. c = newconv(p, pp);
  913. }
  914. c->inuse = 1;
  915. kstrdup(&c->owner, user);
  916. c->perm = 0660;
  917. c->state = Idle;
  918. ipmove(c->laddr, IPnoaddr);
  919. ipmove(c->raddr, IPnoaddr);
  920. c->lport = 0;
  921. c->rport = 0;
  922. c->restricted = 0;
  923. c->headers = 0;
  924. c->sfd = nfd;
  925. if(nfd == -1)
  926. c->sfd = so_socket(p->stype);
  927. qunlock(&c->l);
  928. qunlock(&p->l);
  929. poperror();
  930. return c;
  931. }
  932. static Conv*
  933. newconv(Proto *p, Conv **pp)
  934. {
  935. Conv *c;
  936. *pp = c = malloc(sizeof(Conv));
  937. if(c == 0)
  938. error(Enomem);
  939. qlock(&c->l);
  940. c->inuse = 1;
  941. c->p = p;
  942. c->x = pp - p->conv;
  943. p->ac++;
  944. return c;
  945. }
  946. int
  947. arpwrite(char *s, int len)
  948. {
  949. int n;
  950. char *f[4], buf[256];
  951. if(len >= sizeof(buf))
  952. len = sizeof(buf)-1;
  953. memmove(buf, s, len);
  954. buf[len] = 0;
  955. if(len > 0 && buf[len-1] == '\n')
  956. buf[len-1] = 0;
  957. n = getfields(buf, f, 4, 1, " ");
  958. if(strcmp(f[0], "add") == 0) {
  959. if(n == 3) {
  960. arpadd(f[1], f[2], n);
  961. return len;
  962. }
  963. }
  964. error("bad arp request");
  965. return len;
  966. }
  967. Dev ipdevtab = {
  968. 'I',
  969. "ip",
  970. ipinit,
  971. ipattach,
  972. ipwalk,
  973. ipstat,
  974. ipopen,
  975. devcreate,
  976. ipclose,
  977. ipread,
  978. devbread,
  979. ipwrite,
  980. devbwrite,
  981. devremove,
  982. ipwstat
  983. };
  984. int
  985. Fsproto(Fs *f, Proto *p)
  986. {
  987. if(f->np >= Maxproto)
  988. return -1;
  989. p->f = f;
  990. if(p->ipproto > 0){
  991. if(f->t2p[p->ipproto] != nil)
  992. return -1;
  993. f->t2p[p->ipproto] = p;
  994. }
  995. p->qid.type = QTDIR;
  996. p->qid.path = QID(f->np, 0, Qprotodir);
  997. p->conv = malloc(sizeof(Conv*)*(p->nc+1));
  998. if(p->conv == nil)
  999. panic("Fsproto");
  1000. p->x = f->np;
  1001. f->p[f->np++] = p;
  1002. return 0;
  1003. }
  1004. /*
  1005. * return true if this protocol is
  1006. * built in
  1007. */
  1008. int
  1009. Fsbuiltinproto(Fs* f, uchar proto)
  1010. {
  1011. return f->t2p[proto] != nil;
  1012. }