devip-unix.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864
  1. #include <stdio.h> /* for sys_errlist, of course */
  2. #include <sys/types.h>
  3. #include <sys/socket.h>
  4. #include <netinet/in.h>
  5. #include <netinet/tcp.h>
  6. #include <netdb.h>
  7. #include <errno.h>
  8. #include "lib9.h"
  9. #include "sys.h"
  10. #include "error.h"
  11. #undef listen
  12. #undef accept
  13. #undef bind
  14. enum
  15. {
  16. S_TCP,
  17. S_UDP
  18. };
  19. int so_socket(int type);
  20. void so_connect(int, unsigned long, unsigned short);
  21. void so_getsockname(int, unsigned long*, unsigned short*);
  22. void so_bind(int, int, unsigned short);
  23. void so_listen(int);
  24. int so_accept(int, unsigned long*, unsigned short*);
  25. int so_getservbyname(char*, char*, char*);
  26. int so_gethostbyname(char*, char**, int);
  27. static void hnputl(void *p, unsigned long v);
  28. static void hnputs(void *p, unsigned short v);
  29. static unsigned long nhgetl(void *p);
  30. static unsigned short nhgets(void *p);
  31. static unsigned long parseip(char *to, char *from);
  32. enum
  33. {
  34. Qtopdir = 1, /* top level directory */
  35. Qprotodir, /* directory for a protocol */
  36. Qclonus,
  37. Qconvdir, /* directory for a conversation */
  38. Qdata,
  39. Qctl,
  40. Qstatus,
  41. Qremote,
  42. Qlocal,
  43. Qlisten,
  44. MAXPROTO = 4
  45. };
  46. #define TYPE(x) ((x).path & 0xf)
  47. #define CONV(x) (((x).path >> 4)&0xfff)
  48. #define PROTO(x) (((x).path >> 16)&0xff)
  49. #define QID(p, c, y) (((p)<<16) | ((c)<<4) | (y))
  50. typedef struct Proto Proto;
  51. typedef struct Conv Conv;
  52. struct Conv
  53. {
  54. int x;
  55. Ref r;
  56. int sfd;
  57. int perm;
  58. char owner[NAMELEN];
  59. char* state;
  60. ulong laddr;
  61. ushort lport;
  62. ulong raddr;
  63. ushort rport;
  64. int restricted;
  65. char cerr[NAMELEN];
  66. Proto* p;
  67. };
  68. struct Proto
  69. {
  70. Lock l;
  71. int x;
  72. int stype;
  73. char name[NAMELEN];
  74. int nc;
  75. int maxconv;
  76. Conv** conv;
  77. Qid qid;
  78. };
  79. static int np;
  80. static Proto proto[MAXPROTO];
  81. static int eipconv(va_list*, Fconv*);
  82. static Conv* protoclone(Proto*, char*, int);
  83. static void setladdr(Conv*);
  84. int
  85. ipgen(Chan *c, Dirtab *d, int nd, int s, Dir *dp)
  86. {
  87. Qid q;
  88. Conv *cv;
  89. char name[16], *p;
  90. q.vers = 0;
  91. switch(TYPE(c->qid)) {
  92. case Qtopdir:
  93. if(s >= np)
  94. return -1;
  95. q.path = QID(s, 0, Qprotodir)|CHDIR;
  96. devdir(c, q, proto[s].name, 0, "network", CHDIR|0555, dp);
  97. return 1;
  98. case Qprotodir:
  99. if(s < proto[PROTO(c->qid)].nc) {
  100. cv = proto[PROTO(c->qid)].conv[s];
  101. sprint(name, "%d", s);
  102. q.path = QID(PROTO(c->qid), s, Qconvdir)|CHDIR;
  103. devdir(c, q, name, 0, cv->owner, CHDIR|0555, dp);
  104. return 1;
  105. }
  106. s -= proto[PROTO(c->qid)].nc;
  107. switch(s) {
  108. default:
  109. return -1;
  110. case 0:
  111. p = "clone";
  112. q.path = QID(PROTO(c->qid), 0, Qclonus);
  113. break;
  114. }
  115. devdir(c, q, p, 0, "network", 0555, dp);
  116. return 1;
  117. case Qconvdir:
  118. cv = proto[PROTO(c->qid)].conv[CONV(c->qid)];
  119. switch(s) {
  120. default:
  121. return -1;
  122. case 0:
  123. q.path = QID(PROTO(c->qid), CONV(c->qid), Qdata);
  124. devdir(c, q, "data", 0, cv->owner, cv->perm, dp);
  125. return 1;
  126. case 1:
  127. q.path = QID(PROTO(c->qid), CONV(c->qid), Qctl);
  128. devdir(c, q, "ctl", 0, cv->owner, cv->perm, dp);
  129. return 1;
  130. case 2:
  131. p = "status";
  132. q.path = QID(PROTO(c->qid), CONV(c->qid), Qstatus);
  133. break;
  134. case 3:
  135. p = "remote";
  136. q.path = QID(PROTO(c->qid), CONV(c->qid), Qremote);
  137. break;
  138. case 4:
  139. p = "local";
  140. q.path = QID(PROTO(c->qid), CONV(c->qid), Qlocal);
  141. break;
  142. case 5:
  143. p = "listen";
  144. q.path = QID(PROTO(c->qid), CONV(c->qid), Qlisten);
  145. break;
  146. }
  147. devdir(c, q, p, 0, cv->owner, 0444, dp);
  148. return 1;
  149. }
  150. return -1;
  151. }
  152. static void
  153. newproto(char *name, int type, int maxconv)
  154. {
  155. int l;
  156. Proto *p;
  157. if(np >= MAXPROTO) {
  158. print("no %s: increase MAXPROTO", name);
  159. return;
  160. }
  161. p = &proto[np];
  162. strcpy(p->name, name);
  163. p->stype = type;
  164. p->qid.path = CHDIR|QID(np, 0, Qprotodir);
  165. p->x = np++;
  166. p->maxconv = maxconv;
  167. l = sizeof(Conv*)*(p->maxconv+1);
  168. p->conv = mallocz(l);
  169. if(p->conv == 0)
  170. panic("no memory");
  171. }
  172. void
  173. ipinit(void)
  174. {
  175. gethostname(sysname, sizeof(sysname));
  176. newproto("udp", S_UDP, 10);
  177. newproto("tcp", S_TCP, 30);
  178. fmtinstall('i', eipconv);
  179. fmtinstall('I', eipconv);
  180. fmtinstall('E', eipconv);
  181. }
  182. Chan *
  183. ipattach(void *spec)
  184. {
  185. Chan *c;
  186. c = devattach('I', spec);
  187. c->qid.path = QID(0, 0, Qtopdir)|CHDIR;
  188. c->qid.vers = 0;
  189. return c;
  190. }
  191. Chan *
  192. ipclone(Chan *c, Chan *nc)
  193. {
  194. return devclone(c, nc);
  195. }
  196. int
  197. ipwalk(Chan *c, char *name)
  198. {
  199. return devwalk(c, name, 0, 0, ipgen);
  200. }
  201. void
  202. ipstat(Chan *c, char *db)
  203. {
  204. devstat(c, db, 0, 0, ipgen);
  205. }
  206. Chan *
  207. ipopen(Chan *c, int omode)
  208. {
  209. Proto *p;
  210. ulong raddr;
  211. ushort rport;
  212. int perm, sfd;
  213. Conv *cv, *lcv;
  214. omode &= 3;
  215. switch(omode) {
  216. case OREAD:
  217. perm = 4;
  218. break;
  219. case OWRITE:
  220. perm = 2;
  221. break;
  222. case ORDWR:
  223. perm = 6;
  224. break;
  225. }
  226. switch(TYPE(c->qid)) {
  227. default:
  228. break;
  229. case Qtopdir:
  230. case Qprotodir:
  231. case Qconvdir:
  232. case Qstatus:
  233. case Qremote:
  234. case Qlocal:
  235. if(omode != OREAD)
  236. error(Eperm);
  237. break;
  238. case Qclonus:
  239. p = &proto[PROTO(c->qid)];
  240. cv = protoclone(p, up->user, -1);
  241. if(cv == 0)
  242. error(Enodev);
  243. c->qid.path = QID(p->x, cv->x, Qctl);
  244. c->qid.vers = 0;
  245. break;
  246. case Qdata:
  247. case Qctl:
  248. p = &proto[PROTO(c->qid)];
  249. lock(&p->l);
  250. cv = p->conv[CONV(c->qid)];
  251. lock(&cv->r.l);
  252. if((perm & (cv->perm>>6)) != perm) {
  253. if(strcmp(up->user, cv->owner) != 0 ||
  254. (perm & cv->perm) != perm) {
  255. unlock(&cv->r.l);
  256. unlock(&p->l);
  257. error(Eperm);
  258. }
  259. }
  260. cv->r.ref++;
  261. if(cv->r.ref == 1) {
  262. memmove(cv->owner, up->user, NAMELEN);
  263. cv->perm = 0660;
  264. }
  265. unlock(&cv->r.l);
  266. unlock(&p->l);
  267. break;
  268. case Qlisten:
  269. p = &proto[PROTO(c->qid)];
  270. lcv = p->conv[CONV(c->qid)];
  271. sfd = so_accept(lcv->sfd, &raddr, &rport);
  272. cv = protoclone(p, up->user, sfd);
  273. if(cv == 0) {
  274. close(sfd);
  275. error(Enodev);
  276. }
  277. cv->raddr = raddr;
  278. cv->rport = rport;
  279. setladdr(cv);
  280. cv->state = "Established";
  281. c->qid.path = QID(p->x, cv->x, Qctl);
  282. break;
  283. }
  284. c->mode = openmode(omode);
  285. c->flag |= COPEN;
  286. c->offset = 0;
  287. return c;
  288. }
  289. void
  290. ipcreate(Chan *c, char *name, int mode, ulong perm)
  291. {
  292. error(Eperm);
  293. }
  294. void
  295. ipremove(Chan *c)
  296. {
  297. error(Eperm);
  298. }
  299. void
  300. ipwstat(Chan *c, char *buf)
  301. {
  302. error(Eperm);
  303. }
  304. void
  305. ipclose(Chan *c)
  306. {
  307. Conv *cc;
  308. switch(TYPE(c->qid)) {
  309. case Qdata:
  310. case Qctl:
  311. if((c->flag & COPEN) == 0)
  312. break;
  313. cc = proto[PROTO(c->qid)].conv[CONV(c->qid)];
  314. if(refdec(&cc->r) != 0)
  315. break;
  316. strcpy(cc->owner, "network");
  317. cc->perm = 0666;
  318. cc->state = "Closed";
  319. cc->laddr = 0;
  320. cc->raddr = 0;
  321. cc->lport = 0;
  322. cc->rport = 0;
  323. close(cc->sfd);
  324. break;
  325. }
  326. }
  327. long
  328. ipread(Chan *ch, void *a, long n, ulong offset)
  329. {
  330. int r;
  331. Conv *c;
  332. Proto *x;
  333. uchar ip[4];
  334. char buf[128], *p;
  335. p = a;
  336. switch(TYPE(ch->qid)) {
  337. default:
  338. error(Eperm);
  339. case Qprotodir:
  340. case Qtopdir:
  341. case Qconvdir:
  342. return devdirread(ch, a, n, 0, 0, ipgen);
  343. case Qctl:
  344. sprint(buf, "%d", CONV(ch->qid));
  345. return readstr(offset, p, n, buf);
  346. case Qremote:
  347. c = proto[PROTO(ch->qid)].conv[CONV(ch->qid)];
  348. hnputl(ip, c->raddr);
  349. sprint(buf, "%I!%d\n", ip, c->rport);
  350. return readstr(offset, p, n, buf);
  351. case Qlocal:
  352. c = proto[PROTO(ch->qid)].conv[CONV(ch->qid)];
  353. hnputl(ip, c->laddr);
  354. sprint(buf, "%I!%d\n", ip, c->lport);
  355. return readstr(offset, p, n, buf);
  356. case Qstatus:
  357. x = &proto[PROTO(ch->qid)];
  358. c = x->conv[CONV(ch->qid)];
  359. sprint(buf, "%s/%d %d %s \n",
  360. c->p->name, c->x, c->r.ref, c->state);
  361. return readstr(offset, p, n, buf);
  362. case Qdata:
  363. c = proto[PROTO(ch->qid)].conv[CONV(ch->qid)];
  364. r = recv(c->sfd, a, n, 0);
  365. if(r < 0)
  366. error(strerror(errno));
  367. return r;
  368. }
  369. }
  370. static void
  371. setladdr(Conv *c)
  372. {
  373. so_getsockname(c->sfd, &c->laddr, &c->lport);
  374. }
  375. static void
  376. setlport(Conv *c)
  377. {
  378. if(c->restricted == 0 && c->lport == 0)
  379. return;
  380. so_bind(c->sfd, c->restricted, c->lport);
  381. }
  382. static void
  383. setladdrport(Conv *c, char *str)
  384. {
  385. char *p, addr[4];
  386. p = strchr(str, '!');
  387. if(p == 0) {
  388. p = str;
  389. c->laddr = 0;
  390. }
  391. else {
  392. *p++ = 0;
  393. parseip(addr, str);
  394. c->laddr = nhgetl((uchar*)addr);
  395. }
  396. if(*p == '*')
  397. c->lport = 0;
  398. else
  399. c->lport = atoi(p);
  400. setlport(c);
  401. }
  402. static char*
  403. setraddrport(Conv *c, char *str)
  404. {
  405. char *p, addr[4];
  406. p = strchr(str, '!');
  407. if(p == 0)
  408. return "malformed address";
  409. *p++ = 0;
  410. parseip(addr, str);
  411. c->raddr = nhgetl((uchar*)addr);
  412. c->rport = atoi(p);
  413. p = strchr(p, '!');
  414. if(p) {
  415. if(strcmp(p, "!r") == 0)
  416. c->restricted = 1;
  417. }
  418. return 0;
  419. }
  420. long
  421. ipwrite(Chan *ch, void *a, long n, ulong offset)
  422. {
  423. Conv *c;
  424. Proto *x;
  425. int r, nf;
  426. char *p, *fields[3], buf[128];
  427. switch(TYPE(ch->qid)) {
  428. default:
  429. error(Eperm);
  430. case Qctl:
  431. x = &proto[PROTO(ch->qid)];
  432. c = x->conv[CONV(ch->qid)];
  433. if(n > sizeof(buf)-1)
  434. n = sizeof(buf)-1;
  435. memmove(buf, a, n);
  436. buf[n] = '\0';
  437. nf = getfields(buf, fields, 3, 1, " ");
  438. if(strcmp(fields[0], "connect") == 0){
  439. switch(nf) {
  440. default:
  441. error("bad args to connect");
  442. case 2:
  443. p = setraddrport(c, fields[1]);
  444. if(p != 0)
  445. error(p);
  446. break;
  447. case 3:
  448. p = setraddrport(c, fields[1]);
  449. if(p != 0)
  450. error(p);
  451. c->lport = atoi(fields[2]);
  452. setlport(c);
  453. break;
  454. }
  455. so_connect(c->sfd, c->raddr, c->rport);
  456. setladdr(c);
  457. c->state = "Established";
  458. return n;
  459. }
  460. if(strcmp(fields[0], "announce") == 0) {
  461. switch(nf){
  462. default:
  463. error("bad args to announce");
  464. case 2:
  465. setladdrport(c, fields[1]);
  466. break;
  467. }
  468. so_listen(c->sfd);
  469. c->state = "Announced";
  470. return n;
  471. }
  472. if(strcmp(fields[0], "bind") == 0){
  473. switch(nf){
  474. default:
  475. error("bad args to bind");
  476. case 2:
  477. c->lport = atoi(fields[1]);
  478. break;
  479. }
  480. setlport(c);
  481. return n;
  482. }
  483. error("bad control message");
  484. case Qdata:
  485. x = &proto[PROTO(ch->qid)];
  486. c = x->conv[CONV(ch->qid)];
  487. r = send(c->sfd, a, n, 0);
  488. if(r < 0)
  489. error(strerror(errno));
  490. return r;
  491. }
  492. return n;
  493. }
  494. static Conv*
  495. protoclone(Proto *p, char *user, int nfd)
  496. {
  497. Conv *c, **pp, **ep;
  498. c = 0;
  499. lock(&p->l);
  500. if(waserror()) {
  501. unlock(&p->l);
  502. nexterror();
  503. }
  504. ep = &p->conv[p->maxconv];
  505. for(pp = p->conv; pp < ep; pp++) {
  506. c = *pp;
  507. if(c == 0) {
  508. c = mallocz(sizeof(Conv));
  509. if(c == 0)
  510. error(Enomem);
  511. lock(&c->r.l);
  512. c->r.ref = 1;
  513. c->p = p;
  514. c->x = pp - p->conv;
  515. p->nc++;
  516. *pp = c;
  517. break;
  518. }
  519. lock(&c->r.l);
  520. if(c->r.ref == 0) {
  521. c->r.ref++;
  522. break;
  523. }
  524. unlock(&c->r.l);
  525. }
  526. if(pp >= ep) {
  527. unlock(&p->l);
  528. poperror();
  529. return 0;
  530. }
  531. strcpy(c->owner, user);
  532. c->perm = 0660;
  533. c->state = "Closed";
  534. c->restricted = 0;
  535. c->laddr = 0;
  536. c->raddr = 0;
  537. c->lport = 0;
  538. c->rport = 0;
  539. c->sfd = nfd;
  540. if(nfd == -1)
  541. c->sfd = so_socket(p->stype);
  542. unlock(&c->r.l);
  543. unlock(&p->l);
  544. poperror();
  545. return c;
  546. }
  547. static int
  548. eipconv(va_list *v, Fconv *f)
  549. {
  550. static char buf[64];
  551. static char *efmt = "%.2lux%.2lux%.2lux%.2lux%.2lux%.2lux";
  552. static char *ifmt = "%d.%d.%d.%d";
  553. uchar *p, ip[4];
  554. switch(f->chr) {
  555. case 'E': /* Ethernet address */
  556. p = va_arg(*v, uchar*);
  557. sprint(buf, efmt, p[0], p[1], p[2], p[3], p[4], p[5]);
  558. break;
  559. case 'I': /* Ip address */
  560. p = va_arg(*v, uchar*);
  561. sprint(buf, ifmt, p[0], p[1], p[2], p[3]);
  562. break;
  563. case 'i':
  564. hnputl(ip, va_arg(*v, ulong));
  565. sprint(buf, ifmt, ip[0], ip[1], ip[2], ip[3]);
  566. break;
  567. default:
  568. strcpy(buf, "(eipconv)");
  569. }
  570. strconv(buf, f);
  571. return 0;
  572. }
  573. int
  574. so_socket(int type)
  575. {
  576. int fd, one;
  577. switch(type) {
  578. default:
  579. error("bad protocol type");
  580. case S_TCP:
  581. type = SOCK_STREAM;
  582. break;
  583. case S_UDP:
  584. type = SOCK_DGRAM;
  585. break;
  586. }
  587. fd = socket(AF_INET, type, 0);
  588. if(fd < 0)
  589. error(strerror(errno));
  590. one = 1;
  591. if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof(one)) > 0)
  592. print("setsockopt: %s", strerror(errno));
  593. return fd;
  594. }
  595. void
  596. so_connect(int fd, unsigned long raddr, unsigned short rport)
  597. {
  598. struct sockaddr_in sin;
  599. memset(&sin, 0, sizeof(sin));
  600. sin.sin_family = AF_INET;
  601. hnputs(&sin.sin_port, rport);
  602. hnputl(&sin.sin_addr.s_addr, raddr);
  603. if(connect(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
  604. error(strerror(errno));
  605. }
  606. void
  607. so_getsockname(int fd, unsigned long *laddr, unsigned short *lport)
  608. {
  609. int len;
  610. struct sockaddr_in sin;
  611. len = sizeof(sin);
  612. if(getsockname(fd, (struct sockaddr*)&sin, &len) < 0)
  613. error(strerror(errno));
  614. if(sin.sin_family != AF_INET || len != sizeof(sin))
  615. error("not AF_INET");
  616. *laddr = nhgetl(&sin.sin_addr.s_addr);
  617. *lport = nhgets(&sin.sin_port);
  618. }
  619. void
  620. so_listen(int fd)
  621. {
  622. if(listen(fd, 5) < 0)
  623. error(strerror(errno));
  624. }
  625. int
  626. so_accept(int fd, unsigned long *raddr, unsigned short *rport)
  627. {
  628. int nfd, len;
  629. struct sockaddr_in sin;
  630. len = sizeof(sin);
  631. nfd = accept(fd, (struct sockaddr*)&sin, &len);
  632. if(nfd < 0)
  633. error(strerror(errno));
  634. if(sin.sin_family != AF_INET || len != sizeof(sin))
  635. error("not AF_INET");
  636. *raddr = nhgetl(&sin.sin_addr.s_addr);
  637. *rport = nhgets(&sin.sin_port);
  638. return nfd;
  639. }
  640. void
  641. so_bind(int fd, int su, unsigned short port)
  642. {
  643. int i, one;
  644. struct sockaddr_in sin;
  645. one = 1;
  646. if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)) < 0)
  647. print("setsockopt: %s", strerror(errno));
  648. if(su) {
  649. for(i = 600; i < 1024; i++) {
  650. memset(&sin, 0, sizeof(sin));
  651. sin.sin_family = AF_INET;
  652. sin.sin_port = i;
  653. if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) >= 0)
  654. return;
  655. }
  656. error(strerror(errno));
  657. }
  658. memset(&sin, 0, sizeof(sin));
  659. sin.sin_family = AF_INET;
  660. hnputs(&sin.sin_port, port);
  661. if(bind(fd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
  662. error(strerror(errno));
  663. }
  664. int
  665. so_gethostbyname(char *host, char**hostv, int n)
  666. {
  667. int i;
  668. char buf[32];
  669. unsigned char *p;
  670. struct hostent *hp;
  671. hp = gethostbyname(host);
  672. if(hp == 0)
  673. return 0;
  674. for(i = 0; hp->h_addr_list[i] && i < n; i++) {
  675. p = (unsigned char*)hp->h_addr_list[i];
  676. sprint(buf, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
  677. hostv[i] = strdup(buf);
  678. if(hostv[i] == 0)
  679. break;
  680. }
  681. return i;
  682. }
  683. char*
  684. hostlookup(char *host)
  685. {
  686. char buf[100];
  687. uchar *p;
  688. struct hostent *he;
  689. he = gethostbyname(host);
  690. if(he != 0 && he->h_addr_list[0]) {
  691. p = (uchar*)he->h_addr_list[0];
  692. sprint(buf, "%ud.%ud.%ud.%ud", p[0], p[1], p[2], p[3]);
  693. } else
  694. strcpy(buf, host);
  695. return strdup(buf);
  696. }
  697. int
  698. so_getservbyname(char *service, char *net, char *port)
  699. {
  700. struct servent *s;
  701. s = getservbyname(service, net);
  702. if(s == 0)
  703. return -1;
  704. sprint(port, "%d", nhgets(&s->s_port));
  705. return 0;
  706. }
  707. void
  708. hnputl(void *p, unsigned long v)
  709. {
  710. unsigned char *a;
  711. a = p;
  712. a[0] = v>>24;
  713. a[1] = v>>16;
  714. a[2] = v>>8;
  715. a[3] = v;
  716. }
  717. void
  718. hnputs(void *p, unsigned short v)
  719. {
  720. unsigned char *a;
  721. a = p;
  722. a[0] = v>>8;
  723. a[1] = v;
  724. }
  725. unsigned long
  726. nhgetl(void *p)
  727. {
  728. unsigned char *a;
  729. a = p;
  730. return (a[0]<<24)|(a[1]<<16)|(a[2]<<8)|(a[3]<<0);
  731. }
  732. unsigned short
  733. nhgets(void *p)
  734. {
  735. unsigned char *a;
  736. a = p;
  737. return (a[0]<<8)|(a[1]<<0);
  738. }
  739. #define CLASS(p) ((*(unsigned char*)(p))>>6)
  740. unsigned long
  741. parseip(char *to, char *from)
  742. {
  743. int i;
  744. char *p;
  745. p = from;
  746. memset(to, 0, 4);
  747. for(i = 0; i < 4 && *p; i++){
  748. to[i] = strtoul(p, &p, 0);
  749. if(*p == '.')
  750. p++;
  751. }
  752. switch(CLASS(to)){
  753. case 0: /* class A - 1 byte net */
  754. case 1:
  755. if(i == 3){
  756. to[3] = to[2];
  757. to[2] = to[1];
  758. to[1] = 0;
  759. } else if (i == 2){
  760. to[3] = to[1];
  761. to[1] = 0;
  762. }
  763. break;
  764. case 2: /* class B - 2 byte net */
  765. if(i == 3){
  766. to[3] = to[2];
  767. to[2] = 0;
  768. }
  769. break;
  770. }
  771. return nhgetl(to);
  772. }