PageRenderTime 56ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/erts/epmd/src/epmd_srv.c

https://github.com/bsmr-erlang/otp
C | 1583 lines | 1163 code | 240 blank | 180 comment | 272 complexity | e0460e389079419d814ac749f47b3311 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.1, MPL-2.0-no-copyleft-exception, Apache-2.0
  1. /* -*- c-indent-level: 2; c-continued-statement-offset: 2 -*- */
  2. /*
  3. * %CopyrightBegin%
  4. *
  5. * Copyright Ericsson AB 1998-2016. All Rights Reserved.
  6. *
  7. * Licensed under the Apache License, Version 2.0 (the "License");
  8. * you may not use this file except in compliance with the License.
  9. * You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing, software
  14. * distributed under the License is distributed on an "AS IS" BASIS,
  15. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16. * See the License for the specific language governing permissions and
  17. * limitations under the License.
  18. *
  19. * %CopyrightEnd%
  20. */
  21. #ifdef HAVE_CONFIG_H
  22. # include "config.h"
  23. #endif
  24. #include "epmd.h" /* Renamed from 'epmd_r4.h' */
  25. #include "epmd_int.h"
  26. #include "erl_printf.h" /* erts_snprintf */
  27. #ifndef INADDR_NONE
  28. # define INADDR_NONE 0xffffffff
  29. #endif
  30. /*
  31. *
  32. * This server is a local name server for Erlang nodes. Erlang nodes can
  33. * ask this server for the listening port of other Erlang nodes on the
  34. * machine EPMD is running on. New distributed nodes that are started
  35. * register their names with this server.
  36. *
  37. * To be accessible to all Erlang nodes this server listens to a well
  38. * known port EPMD_PORT_NO (curently port 4369) where requests
  39. * for connections can be sent.
  40. *
  41. * To keep track of when registered Erlang nodes are terminated this
  42. * server keeps the socket open where the request for registration was
  43. * made.
  44. *
  45. * The protocol is briefly documented in the ERTS User's Guide, see
  46. * http://www.erlang.org/doc/apps/erts/erl_dist_protocol.html
  47. *
  48. * All requests to this server are done with a packet
  49. *
  50. * 2 n
  51. * +--------+---------+
  52. * | Length | Request |
  53. * +--------+---------+
  54. *
  55. */
  56. /* We use separate data structures for node names and connections
  57. so that a request will not use a slot with a name that we
  58. want to resuse later incrementing the "creation" */
  59. /* forward declarations */
  60. static void do_request(EpmdVars*,int,Connection*,char*,int);
  61. static int do_accept(EpmdVars*,int);
  62. static void do_read(EpmdVars*,Connection*);
  63. static time_t current_time(EpmdVars*);
  64. static Connection *conn_init(EpmdVars*);
  65. static int conn_open(EpmdVars*,int);
  66. static int conn_local_peer_check(EpmdVars*, int);
  67. static int conn_close_fd(EpmdVars*,int);
  68. static void node_init(EpmdVars*);
  69. static Node *node_reg2(EpmdVars*, int, char*, int, int, unsigned char, unsigned char, int, int, int, char*);
  70. static int node_unreg(EpmdVars*,char*);
  71. static int node_unreg_sock(EpmdVars*,int);
  72. static int reply(EpmdVars*,int,char *,int);
  73. static void dbg_print_buf(EpmdVars*,char *,int);
  74. static void print_names(EpmdVars*);
  75. static int is_same_str(char *x, char *y)
  76. {
  77. int i = 0;
  78. /*
  79. * Using strcmp() == 0 is probably ok, but just to be sure,
  80. * since we got UTF-8 strings, we do it ourselves.
  81. *
  82. * We assume null-terminated correctly encoded UTF-8.
  83. */
  84. while (x[i] == y[i]) {
  85. if (x[i] == '\0')
  86. return 1;
  87. i++;
  88. }
  89. return 0;
  90. }
  91. static int copy_str(char *x, char *y)
  92. {
  93. int i = 0;
  94. /*
  95. * Using strcpy() is probably ok, but just to be sure,
  96. * since we got UTF-8 strings, we do it ourselves.
  97. *
  98. * We assume null-terminated correctly encoded UTF-8.
  99. */
  100. while (1) {
  101. x[i] = y[i];
  102. if (y[i] == '\0')
  103. return i;
  104. i++;
  105. }
  106. }
  107. static int length_str(char *x)
  108. {
  109. int i = 0;
  110. /*
  111. * Using strlen is probably ok, but just to be sure,
  112. * since we got UTF-8 strings, we do it ourselves.
  113. *
  114. * We assume null-terminated correctly encoded UTF-8.
  115. */
  116. while (x[i])
  117. i++;
  118. return i;
  119. }
  120. static int verify_utf8(const char *src, int sz, int null_term)
  121. {
  122. unsigned char *source = (unsigned char *) src;
  123. int size = sz;
  124. int num_chars = 0;
  125. while (size) {
  126. if (null_term && (*source) == 0)
  127. return num_chars;
  128. if (((*source) & ((unsigned char) 0x80)) == 0) {
  129. source++;
  130. --size;
  131. } else if (((*source) & ((unsigned char) 0xE0)) == 0xC0) {
  132. if (size < 2)
  133. return -1;
  134. if (((source[1] & ((unsigned char) 0xC0)) != 0x80) ||
  135. ((*source) < 0xC2) /* overlong */) {
  136. return -1;
  137. }
  138. source += 2;
  139. size -= 2;
  140. } else if (((*source) & ((unsigned char) 0xF0)) == 0xE0) {
  141. if (size < 3)
  142. return -1;
  143. if (((source[1] & ((unsigned char) 0xC0)) != 0x80) ||
  144. ((source[2] & ((unsigned char) 0xC0)) != 0x80) ||
  145. (((*source) == 0xE0) && (source[1] < 0xA0)) /* overlong */ ) {
  146. return -1;
  147. }
  148. if ((((*source) & ((unsigned char) 0xF)) == 0xD) &&
  149. ((source[1] & 0x20) != 0)) {
  150. return -1;
  151. }
  152. source += 3;
  153. size -= 3;
  154. } else if (((*source) & ((unsigned char) 0xF8)) == 0xF0) {
  155. if (size < 4)
  156. return -1;
  157. if (((source[1] & ((unsigned char) 0xC0)) != 0x80) ||
  158. ((source[2] & ((unsigned char) 0xC0)) != 0x80) ||
  159. ((source[3] & ((unsigned char) 0xC0)) != 0x80) ||
  160. (((*source) == 0xF0) && (source[1] < 0x90)) /* overlong */) {
  161. return -1;
  162. }
  163. if ((((*source) & ((unsigned char)0x7)) > 0x4U) ||
  164. ((((*source) & ((unsigned char)0x7)) == 0x4U) &&
  165. ((source[1] & ((unsigned char)0x3F)) > 0xFU))) {
  166. return -1;
  167. }
  168. source += 4;
  169. size -= 4;
  170. } else {
  171. return -1;
  172. }
  173. ++num_chars;
  174. }
  175. return num_chars;
  176. }
  177. static EPMD_INLINE void select_fd_set(EpmdVars* g, int fd)
  178. {
  179. FD_SET(fd, &g->orig_read_mask);
  180. if (fd >= g->select_fd_top) {
  181. g->select_fd_top = fd + 1;
  182. }
  183. }
  184. void run(EpmdVars *g)
  185. {
  186. struct EPMD_SOCKADDR_IN iserv_addr[MAX_LISTEN_SOCKETS];
  187. int listensock[MAX_LISTEN_SOCKETS];
  188. int num_sockets = 0;
  189. int i;
  190. int opt;
  191. unsigned short sport = g->port;
  192. int bound = 0;
  193. node_init(g);
  194. g->conn = conn_init(g);
  195. #ifdef HAVE_SYSTEMD_DAEMON
  196. if (g->is_systemd)
  197. {
  198. int n;
  199. dbg_printf(g,2,"try to obtain sockets from systemd");
  200. n = sd_listen_fds(0);
  201. if (n < 0)
  202. {
  203. dbg_perror(g,"cannot obtain sockets from systemd");
  204. epmd_cleanup_exit(g,1);
  205. }
  206. else if (n == 0)
  207. {
  208. dbg_tty_printf(g,0,"systemd provides no sockets");
  209. epmd_cleanup_exit(g,1);
  210. }
  211. else if (n > MAX_LISTEN_SOCKETS)
  212. {
  213. dbg_tty_printf(g,0,"cannot listen on more than %d IP addresses", MAX_LISTEN_SOCKETS);
  214. epmd_cleanup_exit(g,1);
  215. }
  216. num_sockets = n;
  217. for (i = 0; i < num_sockets; i++)
  218. {
  219. g->listenfd[i] = listensock[i] = SD_LISTEN_FDS_START + i;
  220. }
  221. }
  222. else
  223. {
  224. #endif /* HAVE_SYSTEMD_DAEMON */
  225. dbg_printf(g,2,"try to initiate listening port %d", g->port);
  226. if (g->addresses != NULL && /* String contains non-separator characters if: */
  227. g->addresses[strspn(g->addresses," ,")] != '\000')
  228. {
  229. char *tmp = NULL;
  230. char *token = NULL;
  231. /* Always listen on the loopback. */
  232. SET_ADDR(iserv_addr[num_sockets],htonl(INADDR_LOOPBACK),sport);
  233. num_sockets++;
  234. #if defined(EPMD6)
  235. SET_ADDR6(iserv_addr[num_sockets],in6addr_loopback,sport);
  236. num_sockets++;
  237. #endif
  238. if ((tmp = strdup(g->addresses)) == NULL)
  239. {
  240. dbg_perror(g,"cannot allocate memory");
  241. epmd_cleanup_exit(g,1);
  242. }
  243. for(token = strtok(tmp,", ");
  244. token != NULL;
  245. token = strtok(NULL,", "))
  246. {
  247. struct in_addr addr;
  248. #if defined(EPMD6)
  249. struct in6_addr addr6;
  250. struct sockaddr_storage *sa = &iserv_addr[num_sockets];
  251. if (inet_pton(AF_INET6,token,&addr6) == 1)
  252. {
  253. SET_ADDR6(iserv_addr[num_sockets],addr6,sport);
  254. }
  255. else if (inet_pton(AF_INET,token,&addr) == 1)
  256. {
  257. SET_ADDR(iserv_addr[num_sockets],addr.s_addr,sport);
  258. }
  259. else
  260. #else
  261. if ((addr.s_addr = inet_addr(token)) != INADDR_NONE)
  262. {
  263. SET_ADDR(iserv_addr[num_sockets],addr.s_addr,sport);
  264. }
  265. else
  266. #endif
  267. {
  268. dbg_tty_printf(g,0,"cannot parse IP address \"%s\"",token);
  269. epmd_cleanup_exit(g,1);
  270. }
  271. #if defined(EPMD6)
  272. if (sa->ss_family == AF_INET6 && IN6_IS_ADDR_LOOPBACK(&addr6))
  273. continue;
  274. if (sa->ss_family == AF_INET)
  275. #endif
  276. if (IS_ADDR_LOOPBACK(addr))
  277. continue;
  278. num_sockets++;
  279. if (num_sockets >= MAX_LISTEN_SOCKETS)
  280. {
  281. dbg_tty_printf(g,0,"cannot listen on more than %d IP addresses",
  282. MAX_LISTEN_SOCKETS);
  283. epmd_cleanup_exit(g,1);
  284. }
  285. }
  286. free(tmp);
  287. }
  288. else
  289. {
  290. SET_ADDR(iserv_addr[num_sockets],htonl(INADDR_ANY),sport);
  291. num_sockets++;
  292. #if defined(EPMD6)
  293. SET_ADDR6(iserv_addr[num_sockets],in6addr_any,sport);
  294. num_sockets++;
  295. #endif
  296. }
  297. #ifdef HAVE_SYSTEMD_DAEMON
  298. }
  299. #endif /* HAVE_SYSTEMD_DAEMON */
  300. #if !defined(__WIN32__)
  301. /* We ignore the SIGPIPE signal that is raised when we call write
  302. twice on a socket closed by the other end. */
  303. signal(SIGPIPE, SIG_IGN);
  304. #endif
  305. /*
  306. * Initialize number of active file descriptors.
  307. * Stdin, stdout, and stderr are still open.
  308. */
  309. g->active_conn = 3 + num_sockets;
  310. g->max_conn -= num_sockets;
  311. FD_ZERO(&g->orig_read_mask);
  312. g->select_fd_top = 0;
  313. #ifdef HAVE_SYSTEMD_DAEMON
  314. if (g->is_systemd)
  315. for (i = 0; i < num_sockets; i++)
  316. select_fd_set(g, listensock[i]);
  317. else
  318. {
  319. #endif /* HAVE_SYSTEMD_DAEMON */
  320. for (i = 0; i < num_sockets; i++)
  321. {
  322. struct sockaddr *sa = (struct sockaddr *)&iserv_addr[i];
  323. #if defined(EPMD6)
  324. size_t salen = (sa->sa_family == AF_INET6 ?
  325. sizeof(struct sockaddr_in6) :
  326. sizeof(struct sockaddr_in));
  327. #else
  328. size_t salen = sizeof(struct sockaddr_in);
  329. #endif
  330. if ((listensock[i] = socket(sa->sa_family,SOCK_STREAM,0)) < 0)
  331. {
  332. switch (errno) {
  333. case EAFNOSUPPORT:
  334. case EPROTONOSUPPORT:
  335. continue;
  336. default:
  337. dbg_perror(g,"error opening stream socket");
  338. epmd_cleanup_exit(g,1);
  339. }
  340. }
  341. g->listenfd[bound++] = listensock[i];
  342. #if HAVE_DECL_IPV6_V6ONLY
  343. opt = 1;
  344. if (sa->sa_family == AF_INET6 &&
  345. setsockopt(listensock[i],IPPROTO_IPV6,IPV6_V6ONLY,&opt,
  346. sizeof(opt)) <0)
  347. {
  348. dbg_perror(g,"can't set IPv6 only socket option");
  349. epmd_cleanup_exit(g,1);
  350. }
  351. #endif
  352. /*
  353. * Note that we must not enable the SO_REUSEADDR on Windows,
  354. * because addresses will be reused even if they are still in use.
  355. */
  356. #if !defined(__WIN32__)
  357. opt = 1;
  358. if (setsockopt(listensock[i],SOL_SOCKET,SO_REUSEADDR,(char* ) &opt,
  359. sizeof(opt)) <0)
  360. {
  361. dbg_perror(g,"can't set sockopt");
  362. epmd_cleanup_exit(g,1);
  363. }
  364. #endif
  365. /* In rare cases select returns because there is someone
  366. to accept but the request is withdrawn before the
  367. accept function is called. We set the listen socket
  368. to be non blocking to prevent us from being hanging
  369. in accept() waiting for the next request. */
  370. #if (defined(__WIN32__) || defined(NO_FCNTL))
  371. opt = 1;
  372. /* Gives warning in VxWorks */
  373. if (ioctl(listensock[i], FIONBIO, &opt) != 0)
  374. #else
  375. opt = fcntl(listensock[i], F_GETFL, 0);
  376. if (fcntl(listensock[i], F_SETFL, opt | O_NONBLOCK) == -1)
  377. #endif /* __WIN32__ || VXWORKS */
  378. dbg_perror(g,"failed to set non-blocking mode of listening socket %d",
  379. listensock[i]);
  380. if (bind(listensock[i], (struct sockaddr*) &iserv_addr[i], salen) < 0)
  381. {
  382. if (errno == EADDRINUSE)
  383. {
  384. dbg_tty_printf(g,1,"there is already a epmd running at port %d",
  385. g->port);
  386. epmd_cleanup_exit(g,0);
  387. }
  388. else
  389. {
  390. dbg_perror(g,"failed to bind socket");
  391. epmd_cleanup_exit(g,1);
  392. }
  393. }
  394. if(listen(listensock[i], SOMAXCONN) < 0) {
  395. dbg_perror(g,"failed to listen on socket");
  396. epmd_cleanup_exit(g,1);
  397. }
  398. select_fd_set(g, listensock[i]);
  399. }
  400. if (bound == 0) {
  401. dbg_perror(g,"unable to bind any address");
  402. epmd_cleanup_exit(g,1);
  403. }
  404. num_sockets = bound;
  405. #ifdef HAVE_SYSTEMD_DAEMON
  406. }
  407. if (g->is_systemd) {
  408. sd_notifyf(0, "READY=1\n"
  409. "STATUS=Processing port mapping requests...\n"
  410. "MAINPID=%lu", (unsigned long) getpid());
  411. }
  412. #endif /* HAVE_SYSTEMD_DAEMON */
  413. dbg_tty_printf(g,2,"entering the main select() loop");
  414. select_again:
  415. while(1)
  416. {
  417. fd_set read_mask = g->orig_read_mask;
  418. struct timeval timeout;
  419. int ret;
  420. /* If we are idle we time out now and then to enable the code
  421. below to close connections that are old and probably
  422. hanging. Make sure that select will return often enough. */
  423. timeout.tv_sec = (g->packet_timeout < IDLE_TIMEOUT) ? 1 : IDLE_TIMEOUT;
  424. timeout.tv_usec = 0;
  425. if ((ret = select(g->select_fd_top,
  426. &read_mask, (fd_set *)0,(fd_set *)0,&timeout)) < 0) {
  427. dbg_perror(g,"error in select ");
  428. switch (errno) {
  429. case EAGAIN:
  430. case EINTR:
  431. break;
  432. default:
  433. epmd_cleanup_exit(g,1);
  434. }
  435. }
  436. else {
  437. time_t now;
  438. if (ret == 0) {
  439. FD_ZERO(&read_mask);
  440. }
  441. if (g->delay_accept) { /* Test of busy server */
  442. sleep(g->delay_accept);
  443. }
  444. for (i = 0; i < num_sockets; i++)
  445. if (FD_ISSET(g->listenfd[i],&read_mask)) {
  446. if (do_accept(g, g->listenfd[i]) && g->active_conn < g->max_conn) {
  447. /*
  448. * The accept() succeeded, and we have at least one file
  449. * descriptor still free, which means that another accept()
  450. * could succeed. Go do do another select(), in case there
  451. * are more incoming connections waiting to be accepted.
  452. */
  453. goto select_again;
  454. }
  455. }
  456. /* Check all open streams marked by select for data or a
  457. close. We also close all open sockets except ALIVE
  458. with no activity for a long period */
  459. now = current_time(g);
  460. for (i = 0; i < g->max_conn; i++) {
  461. if (g->conn[i].open == EPMD_TRUE) {
  462. if (FD_ISSET(g->conn[i].fd,&read_mask))
  463. do_read(g,&g->conn[i]);
  464. else if ((g->conn[i].keep == EPMD_FALSE) &&
  465. ((g->conn[i].mod_time + g->packet_timeout) < now)) {
  466. dbg_tty_printf(g,1,"closing because timed out on receive");
  467. epmd_conn_close(g,&g->conn[i]);
  468. }
  469. }
  470. }
  471. }
  472. }
  473. }
  474. /*
  475. * This routine read as much of the packet as possible and
  476. * if completed calls "do_request()" to fullfill the request.
  477. *
  478. */
  479. static void do_read(EpmdVars *g,Connection *s)
  480. {
  481. int val, pack_size;
  482. if (s->open == EPMD_FALSE)
  483. {
  484. dbg_printf(g,0,"read on unknown socket");
  485. return;
  486. }
  487. /* Check if we already got the whole packet but we keep the
  488. connection alive to find out when a node is terminated. We then
  489. want to check for a close */
  490. if (s->keep == EPMD_TRUE)
  491. {
  492. val = read(s->fd, s->buf, INBUF_SIZE);
  493. if (val == 0)
  494. {
  495. node_unreg_sock(g,s->fd);
  496. epmd_conn_close(g,s);
  497. }
  498. else if (val < 0)
  499. {
  500. dbg_tty_printf(g,1,"error on ALIVE socket %d (%d; errno=0x%x)",
  501. s->fd, val, errno);
  502. node_unreg_sock(g,s->fd);
  503. epmd_conn_close(g,s);
  504. }
  505. else
  506. {
  507. dbg_tty_printf(g,1,"got more than expected on ALIVE socket %d (%d)",
  508. s->fd,val);
  509. dbg_print_buf(g,s->buf,val);
  510. node_unreg_sock(g,s->fd);
  511. epmd_conn_close(g,s);
  512. }
  513. return;
  514. }
  515. /* If unknown size we request the whole buffer - what we got - 1
  516. We subtract 1 because we will add a "\0" in "do_request()".
  517. This is not needed for R3A or higher versions of Erlang,
  518. because the '\0' is included in the request,
  519. but is kept for backwards compatibility to allow R2D to use
  520. this epmd. */
  521. pack_size = s->want ? s->want : INBUF_SIZE - 1;
  522. val = read(s->fd, s->buf + s->got, pack_size - s->got);
  523. if (val == 0)
  524. {
  525. /* A close when we haven't got all data */
  526. dbg_printf(g,0,"got partial packet only on file descriptor %d (%d)",
  527. s->fd,s->got);
  528. epmd_conn_close(g,s);
  529. return;
  530. }
  531. if (val < 0)
  532. {
  533. dbg_perror(g,"error in read");
  534. epmd_conn_close(g,s);
  535. return;
  536. }
  537. dbg_print_buf(g,s->buf,val);
  538. s->got += val;
  539. if ((s->want == 0) && (s->got >= 2))
  540. {
  541. /* The two byte header that specify the length of the packet
  542. doesn't count the header as part of the packet so we add 2
  543. to "s->want" to make us talk about all bytes we get. */
  544. s->want = get_int16(s->buf) + 2;
  545. if ((s->want < 3) || (s->want >= INBUF_SIZE))
  546. {
  547. dbg_printf(g,0,"invalid packet size (%d)",s->want - 2);
  548. epmd_conn_close(g,s);
  549. return;
  550. }
  551. if (s->got > s->want)
  552. {
  553. dbg_printf(g,0,"got %d bytes in packet, expected %d",
  554. s->got - 2, s->want - 2);
  555. epmd_conn_close(g,s);
  556. return;
  557. }
  558. }
  559. s->mod_time = current_time(g); /* Note activity */
  560. if (s->want == s->got)
  561. {
  562. /* Do action and close up */
  563. /* Skip header bytes */
  564. do_request(g, s->fd, s, s->buf + 2, s->got - 2);
  565. if (!s->keep)
  566. epmd_conn_close(g,s); /* Normal close */
  567. }
  568. }
  569. static int do_accept(EpmdVars *g,int listensock)
  570. {
  571. int msgsock;
  572. struct EPMD_SOCKADDR_IN icli_addr; /* workaround for QNX bug - cannot */
  573. int icli_addr_len; /* handle NULL pointers to accept. */
  574. icli_addr_len = sizeof(icli_addr);
  575. msgsock = accept(listensock,(struct sockaddr*) &icli_addr,
  576. (unsigned int*) &icli_addr_len);
  577. if (msgsock < 0) {
  578. dbg_perror(g,"error in accept");
  579. switch (errno) {
  580. case EAGAIN:
  581. case ECONNABORTED:
  582. case EINTR:
  583. return EPMD_FALSE;
  584. default:
  585. epmd_cleanup_exit(g,1);
  586. }
  587. }
  588. return conn_open(g,msgsock);
  589. }
  590. /* buf is actually one byte larger than bsize,
  591. giving place for null termination */
  592. static void do_request(g, fd, s, buf, bsize)
  593. EpmdVars *g;
  594. int fd;
  595. Connection *s;
  596. char *buf;
  597. int bsize;
  598. {
  599. char wbuf[OUTBUF_SIZE]; /* Buffer for writing */
  600. int i;
  601. buf[bsize] = '\0'; /* Needed for strcmp in PORT2 and STOP requests
  602. buf is always large enough */
  603. switch (*buf)
  604. {
  605. case EPMD_ALIVE2_REQ:
  606. dbg_printf(g,1,"** got ALIVE2_REQ");
  607. if (!s->local_peer) {
  608. dbg_printf(g,0,"ALIVE2_REQ from non local address");
  609. return;
  610. }
  611. /* The packet has the format "axxyyyyyy" where xx is port, given
  612. in network byte order, and yyyyyy is symname, possibly null
  613. terminated. */
  614. if (bsize <= 13) /* at least one character for the node name */
  615. {
  616. dbg_printf(g,0,"packet to small for request ALIVE2_REQ (%d)",bsize);
  617. return;
  618. }
  619. {
  620. Node *node;
  621. int eport;
  622. unsigned char nodetype;
  623. unsigned char protocol;
  624. unsigned short highvsn;
  625. unsigned short lowvsn;
  626. int namelen;
  627. int extralen;
  628. char *name;
  629. char *extra;
  630. eport = get_int16(&buf[1]);
  631. nodetype = buf[3];
  632. protocol = buf[4];
  633. highvsn = get_int16(&buf[5]);
  634. lowvsn = get_int16(&buf[7]);
  635. namelen = get_int16(&buf[9]);
  636. if (namelen + 13 > bsize) {
  637. dbg_printf(g,0,"Node name size error in ALIVE2_REQ");
  638. return;
  639. }
  640. extralen = get_int16(&buf[11+namelen]);
  641. if (extralen + namelen + 13 > bsize) {
  642. dbg_printf(g,0,"Extra info size error in ALIVE2_REQ");
  643. return;
  644. }
  645. for (i = 11 ; i < 11 + namelen; i ++)
  646. if (buf[i] == '\000') {
  647. dbg_printf(g,0,"node name contains ascii 0 in ALIVE2_REQ");
  648. return;
  649. }
  650. name = &buf[11];
  651. name[namelen]='\000';
  652. extra = &buf[11+namelen+2];
  653. extra[extralen]='\000';
  654. wbuf[0] = EPMD_ALIVE2_RESP;
  655. if ((node = node_reg2(g, namelen, name, fd, eport, nodetype, protocol,
  656. highvsn, lowvsn, extralen, extra)) == NULL) {
  657. wbuf[1] = 1; /* error */
  658. put_int16(99, wbuf+2);
  659. } else {
  660. wbuf[1] = 0; /* ok */
  661. put_int16(node->creation, wbuf+2);
  662. }
  663. if (!reply(g, fd, wbuf, 4))
  664. {
  665. node_unreg(g, name);
  666. dbg_tty_printf(g,1,"** failed to send ALIVE2_RESP for \"%s\"",
  667. name);
  668. return;
  669. }
  670. dbg_tty_printf(g,1,"** sent ALIVE2_RESP for \"%s\"",name);
  671. s->keep = EPMD_TRUE; /* Don't close on inactivity */
  672. }
  673. break;
  674. case EPMD_PORT2_REQ:
  675. dbg_printf(g,1,"** got PORT2_REQ");
  676. if (buf[bsize - 1] == '\000') /* Skip null termination */
  677. bsize--;
  678. if (bsize <= 1)
  679. {
  680. dbg_printf(g,0,"packet too small for request PORT2_REQ (%d)", bsize);
  681. return;
  682. }
  683. for (i = 1; i < bsize; i++)
  684. if (buf[i] == '\000')
  685. {
  686. dbg_printf(g,0,"node name contains ascii 0 in PORT2_REQ");
  687. return;
  688. }
  689. {
  690. char *name = &buf[1]; /* Points to node name */
  691. int nsz;
  692. Node *node;
  693. nsz = verify_utf8(name, bsize, 0);
  694. if (nsz < 1 || 255 < nsz) {
  695. dbg_printf(g,0,"invalid node name in PORT2_REQ");
  696. return;
  697. }
  698. wbuf[0] = EPMD_PORT2_RESP;
  699. for (node = g->nodes.reg; node; node = node->next) {
  700. int offset;
  701. if (is_same_str(node->symname, name)) {
  702. wbuf[1] = 0; /* ok */
  703. put_int16(node->port,wbuf+2);
  704. wbuf[4] = node->nodetype;
  705. wbuf[5] = node->protocol;
  706. put_int16(node->highvsn,wbuf+6);
  707. put_int16(node->lowvsn,wbuf+8);
  708. put_int16(length_str(node->symname),wbuf+10);
  709. offset = 12;
  710. offset += copy_str(wbuf + offset,node->symname);
  711. put_int16(node->extralen,wbuf + offset);
  712. offset += 2;
  713. memcpy(wbuf + offset,node->extra,node->extralen);
  714. offset += node->extralen;
  715. if (!reply(g, fd, wbuf, offset))
  716. {
  717. dbg_tty_printf(g,1,"** failed to send PORT2_RESP (ok) for \"%s\"",name);
  718. return;
  719. }
  720. dbg_tty_printf(g,1,"** sent PORT2_RESP (ok) for \"%s\"",name);
  721. return;
  722. }
  723. }
  724. wbuf[1] = 1; /* error */
  725. if (!reply(g, fd, wbuf, 2))
  726. {
  727. dbg_tty_printf(g,1,"** failed to send PORT2_RESP (error) for \"%s\"",name);
  728. return;
  729. }
  730. dbg_tty_printf(g,1,"** sent PORT2_RESP (error) for \"%s\"",name);
  731. return;
  732. }
  733. break;
  734. case EPMD_NAMES_REQ:
  735. dbg_printf(g,1,"** got NAMES_REQ");
  736. {
  737. Node *node;
  738. i = htonl(g->port);
  739. memcpy(wbuf,&i,4);
  740. if (!reply(g, fd,wbuf,4))
  741. {
  742. dbg_tty_printf(g,1,"failed to send NAMES_RESP");
  743. return;
  744. }
  745. for (node = g->nodes.reg; node; node = node->next)
  746. {
  747. int len = 0;
  748. int r;
  749. /* CAREFUL!!! These are parsed by "erl_epmd.erl" so a slight
  750. change in syntax will break < OTP R3A */
  751. len += copy_str(&wbuf[len], "name ");
  752. len += copy_str(&wbuf[len], node->symname);
  753. r = erts_snprintf(&wbuf[len], sizeof(wbuf)-len,
  754. " at port %d\n", node->port);
  755. if (r < 0)
  756. goto failed_names_resp;
  757. len += r;
  758. if (!reply(g, fd, wbuf, len))
  759. {
  760. failed_names_resp:
  761. dbg_tty_printf(g,1,"failed to send NAMES_RESP");
  762. return;
  763. }
  764. }
  765. }
  766. dbg_tty_printf(g,1,"** sent NAMES_RESP");
  767. break;
  768. case EPMD_DUMP_REQ:
  769. dbg_printf(g,1,"** got DUMP_REQ");
  770. if (!s->local_peer) {
  771. dbg_printf(g,0,"DUMP_REQ from non local address");
  772. return;
  773. }
  774. {
  775. Node *node;
  776. i = htonl(g->port);
  777. memcpy(wbuf,&i,4);
  778. if (!reply(g, fd,wbuf,4))
  779. {
  780. dbg_tty_printf(g,1,"failed to send DUMP_RESP");
  781. return;
  782. }
  783. for (node = g->nodes.reg; node; node = node->next)
  784. {
  785. int len = 0, r;
  786. /* CAREFUL!!! These are parsed by "erl_epmd.erl" so a slight
  787. change in syntax will break < OTP R3A */
  788. len += copy_str(&wbuf[len], "active name <");
  789. len += copy_str(&wbuf[len], node->symname);
  790. r = erts_snprintf(&wbuf[len], sizeof(wbuf)-len,
  791. "> at port %d, fd = %d\n",
  792. node->port, node->fd);
  793. if (r < 0)
  794. goto failed_dump_resp;
  795. len += r + 1;
  796. if (!reply(g, fd,wbuf,len))
  797. {
  798. failed_dump_resp:
  799. dbg_tty_printf(g,1,"failed to send DUMP_RESP");
  800. return;
  801. }
  802. }
  803. for (node = g->nodes.unreg; node; node = node->next)
  804. {
  805. int len = 0, r;
  806. /* CAREFUL!!! These are parsed by "erl_epmd.erl" so a slight
  807. change in syntax will break < OTP R3A */
  808. len += copy_str(&wbuf[len], "old/unused name <");
  809. len += copy_str(&wbuf[len], node->symname);
  810. r = erts_snprintf(&wbuf[len], sizeof(wbuf)-len,
  811. ">, port = %d, fd = %d \n",
  812. node->port, node->fd);
  813. if (r < 0)
  814. goto failed_dump_resp2;
  815. len += r + 1;
  816. if (!reply(g, fd,wbuf,len))
  817. {
  818. failed_dump_resp2:
  819. dbg_tty_printf(g,1,"failed to send DUMP_RESP");
  820. return;
  821. }
  822. }
  823. }
  824. dbg_tty_printf(g,1,"** sent DUMP_RESP");
  825. break;
  826. case EPMD_KILL_REQ:
  827. if (!s->local_peer) {
  828. dbg_printf(g,0,"KILL_REQ from non local address");
  829. return;
  830. }
  831. dbg_printf(g,1,"** got KILL_REQ");
  832. if (!g->brutal_kill && (g->nodes.reg != NULL)) {
  833. dbg_printf(g,0,"Disallowed KILL_REQ, live nodes");
  834. if (!reply(g, fd,"NO",2))
  835. dbg_printf(g,0,"failed to send reply to KILL_REQ");
  836. return;
  837. }
  838. if (!reply(g, fd,"OK",2))
  839. dbg_printf(g,0,"failed to send reply to KILL_REQ");
  840. dbg_tty_printf(g,1,"epmd killed");
  841. conn_close_fd(g,fd); /* We never return to caller so close here */
  842. dbg_printf(g,0,"got KILL_REQ - terminates normal");
  843. epmd_cleanup_exit(g,0); /* Normal exit */
  844. case EPMD_STOP_REQ:
  845. dbg_printf(g,1,"** got STOP_REQ");
  846. if (!s->local_peer) {
  847. dbg_printf(g,0,"STOP_REQ from non local address");
  848. return;
  849. }
  850. if (!g->brutal_kill) {
  851. dbg_printf(g,0,"Disallowed STOP_REQ, no relaxed_command_check");
  852. return;
  853. }
  854. if (bsize <= 1 )
  855. {
  856. dbg_printf(g,0,"packet too small for request STOP_REQ (%d)",bsize);
  857. return;
  858. }
  859. {
  860. char *name = &buf[1]; /* Points to node name */
  861. int node_fd;
  862. if ((node_fd = node_unreg(g,name)) < 0)
  863. {
  864. if (!reply(g, fd,"NOEXIST",7))
  865. {
  866. dbg_tty_printf(g,1,"failed to send STOP_RESP NOEXIST");
  867. return;
  868. }
  869. dbg_tty_printf(g,1,"** sent STOP_RESP NOEXIST");
  870. }
  871. conn_close_fd(g,node_fd);
  872. dbg_tty_printf(g,1,"epmd connection stopped");
  873. if (!reply(g, fd,"STOPPED",7))
  874. {
  875. dbg_tty_printf(g,1,"failed to send STOP_RESP STOPPED");
  876. return;
  877. }
  878. dbg_tty_printf(g,1,"** sent STOP_RESP STOPPED");
  879. }
  880. break;
  881. default:
  882. dbg_printf(g,0,"got garbage ");
  883. }
  884. }
  885. /****************************************************************************
  886. *
  887. * Handle database with data for each socket to read
  888. *
  889. ****************************************************************************/
  890. static Connection *conn_init(EpmdVars *g)
  891. {
  892. int nbytes = g->max_conn * sizeof(Connection);
  893. Connection *connections = (Connection *)malloc(nbytes);
  894. if (connections == NULL)
  895. {
  896. dbg_printf(g,0,"epmd: Insufficient memory");
  897. #ifdef DONT_USE_MAIN
  898. free(g->argv);
  899. #endif
  900. exit(1);
  901. }
  902. memzero(connections, nbytes);
  903. return connections;
  904. }
  905. static int conn_open(EpmdVars *g,int fd)
  906. {
  907. int i;
  908. Connection *s;
  909. #ifdef VXWORKS
  910. /*
  911. * Since file descriptors are global on VxWorks, we might get an fd that
  912. * does not fit in the FD_SET.
  913. *
  914. * Note: This test would be harmless on Unix, but would fail on Windows
  915. * because socket are numbered differently and FD_SETs are implemented
  916. * differently.
  917. */
  918. if (fd >= FD_SETSIZE) {
  919. dbg_tty_printf(g,0,"file descriptor %d: too high for FD_SETSIZE=%d",
  920. fd,FD_SETSIZE);
  921. close(fd);
  922. return EPMD_FALSE;
  923. }
  924. #endif
  925. for (i = 0; i < g->max_conn; i++) {
  926. if (g->conn[i].open == EPMD_FALSE) {
  927. g->active_conn++;
  928. s = &g->conn[i];
  929. /* From now on we want to know if there are data to be read */
  930. select_fd_set(g, fd);
  931. s->fd = fd;
  932. s->open = EPMD_TRUE;
  933. s->keep = EPMD_FALSE;
  934. s->local_peer = conn_local_peer_check(g, s->fd);
  935. dbg_tty_printf(g,2,(s->local_peer) ? "Local peer connected" :
  936. "Non-local peer connected");
  937. s->want = 0; /* Currently unknown */
  938. s->got = 0;
  939. s->mod_time = current_time(g); /* Note activity */
  940. s->buf = malloc(INBUF_SIZE);
  941. if (s->buf == NULL) {
  942. dbg_printf(g,0,"epmd: Insufficient memory");
  943. close(fd);
  944. return EPMD_FALSE;
  945. }
  946. dbg_tty_printf(g,2,"opening connection on file descriptor %d",fd);
  947. return EPMD_TRUE;
  948. }
  949. }
  950. dbg_tty_printf(g,0,"failed opening connection on file descriptor %d",fd);
  951. close(fd);
  952. return EPMD_FALSE;
  953. }
  954. static int conn_local_peer_check(EpmdVars *g, int fd)
  955. {
  956. struct EPMD_SOCKADDR_IN si;
  957. struct EPMD_SOCKADDR_IN di;
  958. struct sockaddr_in *si4 = (struct sockaddr_in *)&si;
  959. struct sockaddr_in *di4 = (struct sockaddr_in *)&di;
  960. #if defined(EPMD6)
  961. struct sockaddr_in6 *si6 = (struct sockaddr_in6 *)&si;
  962. struct sockaddr_in6 *di6 = (struct sockaddr_in6 *)&di;
  963. #endif
  964. #ifdef HAVE_SOCKLEN_T
  965. socklen_t st;
  966. #else
  967. int st;
  968. #endif
  969. st = sizeof(si);
  970. /* Determine if connection is from localhost */
  971. if (getpeername(fd,(struct sockaddr*) &si,&st) ||
  972. st > sizeof(si)) {
  973. /* Failure to get peername is regarded as non local host */
  974. return EPMD_FALSE;
  975. }
  976. /* Only 127.x.x.x and connections from the host's IP address
  977. allowed, no false positives */
  978. #if defined(EPMD6)
  979. if (si.ss_family == AF_INET6 && IN6_IS_ADDR_LOOPBACK(&(si6->sin6_addr)))
  980. return EPMD_TRUE;
  981. if (si.ss_family == AF_INET)
  982. #endif
  983. if ((((unsigned) ntohl(si4->sin_addr.s_addr)) & 0xFF000000U) ==
  984. 0x7F000000U)
  985. return EPMD_TRUE;
  986. if (getsockname(fd,(struct sockaddr*) &di,&st))
  987. return EPMD_FALSE;
  988. #if defined(EPMD6)
  989. if (si.ss_family == AF_INET6)
  990. return IN6_ARE_ADDR_EQUAL( &(si6->sin6_addr), &(di6->sin6_addr));
  991. if (si.ss_family == AF_INET)
  992. #endif
  993. return si4->sin_addr.s_addr == di4->sin_addr.s_addr;
  994. #if defined(EPMD6)
  995. return EPMD_FALSE;
  996. #endif
  997. }
  998. static int conn_close_fd(EpmdVars *g,int fd)
  999. {
  1000. int i;
  1001. for (i = 0; i < g->max_conn; i++)
  1002. if (g->conn[i].fd == fd)
  1003. {
  1004. epmd_conn_close(g,&g->conn[i]);
  1005. return EPMD_TRUE;
  1006. }
  1007. return EPMD_FALSE;
  1008. }
  1009. int epmd_conn_close(EpmdVars *g,Connection *s)
  1010. {
  1011. dbg_tty_printf(g,2,"closing connection on file descriptor %d",s->fd);
  1012. FD_CLR(s->fd,&g->orig_read_mask);
  1013. /* we don't bother lowering g->select_fd_top */
  1014. close(s->fd); /* Sometimes already closed but close anyway */
  1015. s->open = EPMD_FALSE;
  1016. if (s->buf != NULL) { /* Should never be NULL but test anyway */
  1017. free(s->buf);
  1018. }
  1019. g->active_conn--;
  1020. return EPMD_TRUE;
  1021. }
  1022. /****************************************************************************
  1023. *
  1024. * Handle database with data for each registered node
  1025. *
  1026. ****************************************************************************/
  1027. static void node_init(EpmdVars *g)
  1028. {
  1029. g->nodes.reg = NULL;
  1030. g->nodes.unreg = NULL;
  1031. g->nodes.unreg_tail = NULL;
  1032. g->nodes.unreg_count = 0;
  1033. }
  1034. /* We have got a close on a connection and it may be a
  1035. EPMD_ALIVE_CLOSE_REQ. Note that this call should be called
  1036. *before* calling conn_close() */
  1037. static int node_unreg(EpmdVars *g,char *name)
  1038. {
  1039. Node **prev = &g->nodes.reg; /* Point to cell pointing to... */
  1040. Node *node = g->nodes.reg; /* Point to first node */
  1041. for (; node; prev = &node->next, node = node->next)
  1042. if (is_same_str(node->symname, name))
  1043. {
  1044. dbg_tty_printf(g,1,"unregistering '%s:%d', port %d",
  1045. node->symname, node->creation, node->port);
  1046. *prev = node->next; /* Link out from "reg" list */
  1047. if (g->nodes.unreg == NULL) /* Link into "unreg" list */
  1048. g->nodes.unreg = g->nodes.unreg_tail = node;
  1049. else
  1050. {
  1051. g->nodes.unreg_tail->next = node;
  1052. g->nodes.unreg_tail = node;
  1053. }
  1054. g->nodes.unreg_count++;
  1055. node->next = NULL; /* Last in list == first in FIFO queue */
  1056. print_names(g);
  1057. return node->fd;
  1058. }
  1059. dbg_tty_printf(g,1,"trying to unregister node with unknown name %s", name);
  1060. return -1;
  1061. }
  1062. static int node_unreg_sock(EpmdVars *g,int fd)
  1063. {
  1064. Node **prev = &g->nodes.reg; /* Point to cell pointing to... */
  1065. Node *node = g->nodes.reg; /* Point to first node */
  1066. for (; node; prev = &node->next, node = node->next)
  1067. if (node->fd == fd)
  1068. {
  1069. dbg_tty_printf(g,1,"unregistering '%s:%d', port %d",
  1070. node->symname, node->creation, node->port);
  1071. *prev = node->next; /* Link out from "reg" list */
  1072. if (g->nodes.unreg == NULL) /* Link into "unreg" list */
  1073. g->nodes.unreg = g->nodes.unreg_tail = node;
  1074. else
  1075. {
  1076. g->nodes.unreg_tail->next = node;
  1077. g->nodes.unreg_tail = node;
  1078. }
  1079. g->nodes.unreg_count++;
  1080. node->next = NULL; /* Last in list == first in FIFO queue */
  1081. print_names(g);
  1082. return node->fd;
  1083. }
  1084. dbg_tty_printf(g,1,
  1085. "trying to unregister node with unknown file descriptor %d",
  1086. fd);
  1087. return -1;
  1088. }
  1089. /*
  1090. * Finding a node slot and a (name,creation) name is a bit tricky.
  1091. * We try in order
  1092. *
  1093. * 1. If the name was used before and we can reuse that slot but use
  1094. * a new "creation" digit in the range 1..3.
  1095. *
  1096. * 2. We try to find a new unused slot.
  1097. *
  1098. * 3. We try to use an used slot this isn't used any longer.
  1099. * FIXME: The criteria for *what* slot to steal should be improved.
  1100. * Perhaps use the oldest or something.
  1101. */
  1102. static Node *node_reg2(EpmdVars *g,
  1103. int namelen,
  1104. char* name,
  1105. int fd,
  1106. int port,
  1107. unsigned char nodetype,
  1108. unsigned char protocol,
  1109. int highvsn,
  1110. int lowvsn,
  1111. int extralen,
  1112. char* extra)
  1113. {
  1114. Node *prev; /* Point to previous node or NULL */
  1115. Node *node; /* Point to first node */
  1116. int sz;
  1117. /* Can be NULL; means old style */
  1118. if (extra == NULL)
  1119. extra = "";
  1120. /* Fail if node name is too long */
  1121. if (namelen > MAXSYMLEN)
  1122. {
  1123. too_long_name:
  1124. dbg_printf(g,0,"node name is too long (%d) %s", namelen, name);
  1125. return NULL;
  1126. }
  1127. sz = verify_utf8(name, namelen, 0);
  1128. if (sz > 255)
  1129. goto too_long_name;
  1130. if (sz < 0) {
  1131. dbg_printf(g,0,"invalid node name encoding");
  1132. return NULL;
  1133. }
  1134. if (extralen > MAXSYMLEN)
  1135. {
  1136. #if 0
  1137. too_long_extra:
  1138. #endif
  1139. dbg_printf(g,0,"extra data is too long (%d) %s", extralen, extra);
  1140. return NULL;
  1141. }
  1142. #if 0 /* Should we require valid utf8 here? */
  1143. sz = verify_utf8(extra, extralen, 0);
  1144. if (sz > 255)
  1145. goto too_long_extra;
  1146. if (sz < 0) {
  1147. dbg_printf(g,0,"invalid extra data encoding");
  1148. return NULL;
  1149. }
  1150. #endif
  1151. /* Fail if it is already registered */
  1152. for (node = g->nodes.reg; node; node = node->next)
  1153. if (is_same_str(node->symname, name))
  1154. {
  1155. dbg_printf(g,0,"node name already occupied %s", name);
  1156. return NULL;
  1157. }
  1158. /* Try to find the name in the used queue so that we
  1159. can change "creation" number 1..3 */
  1160. prev = NULL;
  1161. for (node = g->nodes.unreg; node; prev = node, node = node->next)
  1162. if (is_same_str(node->symname, name))
  1163. {
  1164. dbg_tty_printf(g,1,"reusing slot with same name '%s'", node->symname);
  1165. if (prev == NULL) /* First in list matched */
  1166. {
  1167. if (node->next == NULL) /* Only one element */
  1168. g->nodes.unreg = g->nodes.unreg_tail = NULL;
  1169. else
  1170. g->nodes.unreg = node->next;
  1171. }
  1172. else
  1173. {
  1174. if (node->next == NULL) /* Last in list */
  1175. {
  1176. g->nodes.unreg_tail = prev; /* Point to new last */
  1177. prev->next = NULL; /* New last has no next */
  1178. }
  1179. else
  1180. prev->next = node->next; /* Simple link out from list */
  1181. }
  1182. g->nodes.unreg_count--;
  1183. /* When reusing we change the "creation" number 1..3 */
  1184. node->creation = node->creation % 3 + 1;
  1185. break;
  1186. }
  1187. if (node == NULL)
  1188. {
  1189. /* A new name. If the "unreg" list is too long we steal the
  1190. oldest node structure and use it for the new node, else
  1191. we allocate a new node structure */
  1192. if ((g->nodes.unreg_count > MAX_UNREG_COUNT) ||
  1193. (g->debug && (g->nodes.unreg_count > DEBUG_MAX_UNREG_COUNT)))
  1194. {
  1195. /* MAX_UNREG_COUNT > 1 so no need to check unreg_tail */
  1196. node = g->nodes.unreg; /* Take first == oldest */
  1197. g->nodes.unreg = node->next; /* Link out */
  1198. g->nodes.unreg_count--;
  1199. }
  1200. else
  1201. {
  1202. if ((node = (Node *)malloc(sizeof(Node))) == NULL)
  1203. {
  1204. dbg_printf(g,0,"epmd: Insufficient memory");
  1205. exit(1);
  1206. }
  1207. node->creation = (current_time(g) % 3) + 1; /* "random" 1-3 */
  1208. }
  1209. }
  1210. node->next = g->nodes.reg; /* Link into "reg" queue */
  1211. g->nodes.reg = node;
  1212. node->fd = fd;
  1213. node->port = port;
  1214. node->nodetype = nodetype;
  1215. node->protocol = protocol;
  1216. node->highvsn = highvsn;
  1217. node->lowvsn = lowvsn;
  1218. node->extralen = extralen;
  1219. memcpy(node->extra,extra,extralen);
  1220. copy_str(node->symname,name);
  1221. select_fd_set(g, fd);
  1222. if (highvsn == 0) {
  1223. dbg_tty_printf(g,1,"registering '%s:%d', port %d",
  1224. node->symname, node->creation, node->port);
  1225. } else {
  1226. dbg_tty_printf(g,1,"registering '%s:%d', port %d",
  1227. node->symname, node->creation, node->port);
  1228. dbg_tty_printf(g,1,"type %d proto %d highvsn %d lowvsn %d",
  1229. nodetype, protocol, highvsn, lowvsn);
  1230. }
  1231. print_names(g);
  1232. return node;
  1233. }
  1234. static time_t current_time(EpmdVars *g)
  1235. {
  1236. time_t t = time((time_t *)0);
  1237. dbg_printf(g,3,"time in seconds: %d",t);
  1238. return t;
  1239. }
  1240. static int reply(EpmdVars *g,int fd,char *buf,int len)
  1241. {
  1242. char* p = buf;
  1243. int nbytes = len;
  1244. int val, ret;
  1245. if (len < 0)
  1246. {
  1247. dbg_printf(g,0,"Invalid length in write %d",len);
  1248. return -1;
  1249. }
  1250. if (g->delay_write) /* Test of busy server */
  1251. sleep(g->delay_write);
  1252. for (;;) {
  1253. val = write(fd, p, nbytes);
  1254. if (val == nbytes) {
  1255. ret = 1;
  1256. break;
  1257. }
  1258. if (val < 0) {
  1259. if (errno == EINTR)
  1260. continue;
  1261. dbg_perror(g,"error in write, errno=%d", errno);
  1262. ret = 0;
  1263. break;
  1264. }
  1265. dbg_printf(g,0,"could only send %d bytes out of %d to fd %d",val,nbytes,fd);
  1266. p += val;
  1267. nbytes -= val;
  1268. }
  1269. dbg_print_buf(g,buf,len);
  1270. return ret;
  1271. }
  1272. #define LINEBYTECOUNT 16
  1273. static void print_buf_hex(unsigned char *buf,int len,char *prefix)
  1274. {
  1275. int rows, row;
  1276. rows = len / LINEBYTECOUNT; /* Number of rows */
  1277. if (len % LINEBYTECOUNT)
  1278. rows++; /* If leftovers, add a line for them */
  1279. for (row = 0; row < rows; row++)
  1280. {
  1281. int rowstart = row * LINEBYTECOUNT;
  1282. int rowend = rowstart + LINEBYTECOUNT;
  1283. int i;
  1284. fprintf(stderr,"%s%.8x",prefix,rowstart);
  1285. for (i = rowstart; i < rowend; i++)
  1286. {
  1287. if ((i % (LINEBYTECOUNT/2)) == 0)
  1288. fprintf(stderr," ");
  1289. if (i < len)
  1290. fprintf(stderr," %.2x",buf[i]);
  1291. else
  1292. fprintf(stderr," ");
  1293. }
  1294. fprintf(stderr," |");
  1295. for (i = rowstart; (i < rowend) && (i < len); i++)
  1296. {
  1297. int c = buf[i];
  1298. /* Used to be isprint(c) but we want ascii only */
  1299. if ((c >= 32) && (c <= 126))
  1300. fprintf(stderr,"%c",c);
  1301. else
  1302. fprintf(stderr,".");
  1303. }
  1304. fprintf(stderr,"|\r\n");
  1305. }
  1306. }
  1307. static void dbg_print_buf(EpmdVars *g,char *buf,int len)
  1308. {
  1309. int plen;
  1310. if ((g->is_daemon) || /* Don't want to write to stderr if daemon */
  1311. (g->debug < 2)) /* or debug level too low */
  1312. return;
  1313. dbg_tty_printf(g,1,"got %d bytes",len);
  1314. plen = len > 1024 ? 1024 : len; /* Limit the number of chars to print */
  1315. print_buf_hex((unsigned char*)buf,plen,"***** ");
  1316. if (len != plen)
  1317. fprintf(stderr,"***** ......and more\r\n");
  1318. }
  1319. static void print_names(EpmdVars *g)
  1320. {
  1321. int count = 0;
  1322. Node *node;
  1323. if ((g->is_daemon) || /* Don't want to write to stderr if daemon */
  1324. (g->debug < 3)) /* or debug level too low */
  1325. return;
  1326. for (node = g->nodes.reg; node; node = node->next)
  1327. {
  1328. fprintf(stderr,"***** active name \"%s#%d\" at port %d, fd = %d\r\n",
  1329. node->symname, node->creation, node->port, node->fd);
  1330. count ++;
  1331. }
  1332. fprintf(stderr, "***** reg calculated count : %d\r\n", count);
  1333. count = 0;
  1334. for (node = g->nodes.unreg; node; node = node->next)
  1335. {
  1336. fprintf(stderr,"***** old/unused name \"%s#%d\"\r\n",
  1337. node->symname, node->creation);
  1338. count ++;
  1339. }
  1340. fprintf(stderr, "***** unreg counter : %d\r\n",
  1341. g->nodes.unreg_count);
  1342. fprintf(stderr, "***** unreg calculated count: %d\r\n", count);
  1343. }