netio.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  1. #include "netio.h"
  2. #include "list.h"
  3. #include "dbutil.h"
  4. #include "session.h"
  5. #include "debug.h"
  6. struct dropbear_progress_connection {
  7. struct addrinfo *res;
  8. struct addrinfo *res_iter;
  9. char *remotehost, *remoteport; /* For error reporting */
  10. connect_callback cb;
  11. void *cb_data;
  12. struct Queue *writequeue; /* A queue of encrypted packets to send with TCP fastopen,
  13. or NULL. */
  14. int sock;
  15. char* errstring;
  16. };
  17. /* Deallocate a progress connection. Removes from the pending list if iter!=NULL.
  18. Does not close sockets */
  19. static void remove_connect(struct dropbear_progress_connection *c, m_list_elem *iter) {
  20. if (c->res) {
  21. freeaddrinfo(c->res);
  22. }
  23. m_free(c->remotehost);
  24. m_free(c->remoteport);
  25. m_free(c->errstring);
  26. m_free(c);
  27. if (iter) {
  28. list_remove(iter);
  29. }
  30. }
  31. static void cancel_callback(int result, int sock, void* UNUSED(data), const char* UNUSED(errstring)) {
  32. if (result == DROPBEAR_SUCCESS)
  33. {
  34. m_close(sock);
  35. }
  36. }
  37. void cancel_connect(struct dropbear_progress_connection *c) {
  38. c->cb = cancel_callback;
  39. c->cb_data = NULL;
  40. }
  41. static void connect_try_next(struct dropbear_progress_connection *c) {
  42. struct addrinfo *r;
  43. int res = 0;
  44. int fastopen = 0;
  45. #ifdef DROPBEAR_CLIENT_TCP_FAST_OPEN
  46. struct msghdr message;
  47. #endif
  48. for (r = c->res_iter; r; r = r->ai_next)
  49. {
  50. dropbear_assert(c->sock == -1);
  51. c->sock = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
  52. if (c->sock < 0) {
  53. continue;
  54. }
  55. ses.maxfd = MAX(ses.maxfd, c->sock);
  56. set_sock_nodelay(c->sock);
  57. setnonblocking(c->sock);
  58. #ifdef DROPBEAR_CLIENT_TCP_FAST_OPEN
  59. fastopen = (c->writequeue != NULL);
  60. if (fastopen) {
  61. memset(&message, 0x0, sizeof(message));
  62. message.msg_name = r->ai_addr;
  63. message.msg_namelen = r->ai_addrlen;
  64. /* 6 is arbitrary, enough to hold initial packets */
  65. unsigned int iovlen = 6; /* Linux msg_iovlen is a size_t */
  66. struct iovec iov[6];
  67. packet_queue_to_iovec(c->writequeue, iov, &iovlen);
  68. message.msg_iov = iov;
  69. message.msg_iovlen = iovlen;
  70. res = sendmsg(c->sock, &message, MSG_FASTOPEN);
  71. /* Returns EINPROGRESS if FASTOPEN wasn't available */
  72. if (res < 0) {
  73. if (errno != EINPROGRESS) {
  74. m_free(c->errstring);
  75. c->errstring = m_strdup(strerror(errno));
  76. /* Not entirely sure which kind of errors are normal - 2.6.32 seems to
  77. return EPIPE for any (nonblocking?) sendmsg(). just fall back */
  78. TRACE(("sendmsg tcp_fastopen failed, falling back. %s", strerror(errno)));
  79. /* No kernel MSG_FASTOPEN support. Fall back below */
  80. fastopen = 0;
  81. /* Set to NULL to avoid trying again */
  82. c->writequeue = NULL;
  83. }
  84. } else {
  85. packet_queue_consume(c->writequeue, res);
  86. }
  87. }
  88. #endif
  89. /* Normal connect(), used as fallback for TCP fastopen too */
  90. if (!fastopen) {
  91. res = connect(c->sock, r->ai_addr, r->ai_addrlen);
  92. }
  93. if (res < 0 && errno != EINPROGRESS) {
  94. /* failure */
  95. m_free(c->errstring);
  96. c->errstring = m_strdup(strerror(errno));
  97. close(c->sock);
  98. c->sock = -1;
  99. continue;
  100. } else {
  101. /* new connection was successful, wait for it to complete */
  102. break;
  103. }
  104. }
  105. if (r) {
  106. c->res_iter = r->ai_next;
  107. } else {
  108. c->res_iter = NULL;
  109. }
  110. }
  111. /* Connect via TCP to a host. */
  112. struct dropbear_progress_connection *connect_remote(const char* remotehost, const char* remoteport,
  113. connect_callback cb, void* cb_data)
  114. {
  115. struct dropbear_progress_connection *c = NULL;
  116. int err;
  117. struct addrinfo hints;
  118. c = m_malloc(sizeof(*c));
  119. c->remotehost = m_strdup(remotehost);
  120. c->remoteport = m_strdup(remoteport);
  121. c->sock = -1;
  122. c->cb = cb;
  123. c->cb_data = cb_data;
  124. list_append(&ses.conn_pending, c);
  125. memset(&hints, 0, sizeof(hints));
  126. hints.ai_socktype = SOCK_STREAM;
  127. hints.ai_family = AF_UNSPEC;
  128. err = getaddrinfo(remotehost, remoteport, &hints, &c->res);
  129. if (err) {
  130. int len;
  131. len = 100 + strlen(gai_strerror(err));
  132. c->errstring = (char*)m_malloc(len);
  133. snprintf(c->errstring, len, "Error resolving '%s' port '%s'. %s",
  134. remotehost, remoteport, gai_strerror(err));
  135. TRACE(("Error resolving: %s", gai_strerror(err)))
  136. } else {
  137. c->res_iter = c->res;
  138. }
  139. return c;
  140. }
  141. void remove_connect_pending() {
  142. while (ses.conn_pending.first) {
  143. struct dropbear_progress_connection *c = ses.conn_pending.first->item;
  144. remove_connect(c, ses.conn_pending.first);
  145. }
  146. }
  147. void set_connect_fds(fd_set *writefd) {
  148. m_list_elem *iter;
  149. TRACE(("enter set_connect_fds"))
  150. iter = ses.conn_pending.first;
  151. while (iter) {
  152. m_list_elem *next_iter = iter->next;
  153. struct dropbear_progress_connection *c = iter->item;
  154. /* Set one going */
  155. while (c->res_iter && c->sock < 0) {
  156. connect_try_next(c);
  157. }
  158. if (c->sock >= 0) {
  159. FD_SET(c->sock, writefd);
  160. } else {
  161. /* Final failure */
  162. if (!c->errstring) {
  163. c->errstring = m_strdup("unexpected failure");
  164. }
  165. c->cb(DROPBEAR_FAILURE, -1, c->cb_data, c->errstring);
  166. remove_connect(c, iter);
  167. }
  168. iter = next_iter;
  169. }
  170. }
  171. void handle_connect_fds(fd_set *writefd) {
  172. m_list_elem *iter;
  173. TRACE(("enter handle_connect_fds"))
  174. for (iter = ses.conn_pending.first; iter; iter = iter->next) {
  175. int val;
  176. socklen_t vallen = sizeof(val);
  177. struct dropbear_progress_connection *c = iter->item;
  178. if (c->sock < 0 || !FD_ISSET(c->sock, writefd)) {
  179. continue;
  180. }
  181. TRACE(("handling %s port %s socket %d", c->remotehost, c->remoteport, c->sock));
  182. if (getsockopt(c->sock, SOL_SOCKET, SO_ERROR, &val, &vallen) != 0) {
  183. TRACE(("handle_connect_fds getsockopt(%d) SO_ERROR failed: %s", c->sock, strerror(errno)))
  184. /* This isn't expected to happen - Unix has surprises though, continue gracefully. */
  185. m_close(c->sock);
  186. c->sock = -1;
  187. } else if (val != 0) {
  188. /* Connect failed */
  189. TRACE(("connect to %s port %s failed.", c->remotehost, c->remoteport))
  190. m_close(c->sock);
  191. c->sock = -1;
  192. m_free(c->errstring);
  193. c->errstring = m_strdup(strerror(val));
  194. } else {
  195. /* New connection has been established */
  196. c->cb(DROPBEAR_SUCCESS, c->sock, c->cb_data, NULL);
  197. remove_connect(c, iter);
  198. TRACE(("leave handle_connect_fds - success"))
  199. /* Must return here - remove_connect() invalidates iter */
  200. return;
  201. }
  202. }
  203. TRACE(("leave handle_connect_fds - end iter"))
  204. }
  205. void connect_set_writequeue(struct dropbear_progress_connection *c, struct Queue *writequeue) {
  206. c->writequeue = writequeue;
  207. }
  208. void packet_queue_to_iovec(struct Queue *queue, struct iovec *iov, unsigned int *iov_count) {
  209. struct Link *l;
  210. unsigned int i;
  211. int len;
  212. buffer *writebuf;
  213. #ifndef IOV_MAX
  214. #define IOV_MAX UIO_MAXIOV
  215. #endif
  216. *iov_count = MIN(MIN(queue->count, IOV_MAX), *iov_count);
  217. for (l = queue->head, i = 0; i < *iov_count; l = l->link, i++)
  218. {
  219. writebuf = (buffer*)l->item;
  220. len = writebuf->len - 1 - writebuf->pos;
  221. dropbear_assert(len > 0);
  222. TRACE2(("write_packet writev #%d type %d len %d/%d", i, writebuf->data[writebuf->len-1],
  223. len, writebuf->len-1))
  224. iov[i].iov_base = buf_getptr(writebuf, len);
  225. iov[i].iov_len = len;
  226. }
  227. }
  228. void packet_queue_consume(struct Queue *queue, ssize_t written) {
  229. buffer *writebuf;
  230. int len;
  231. while (written > 0) {
  232. writebuf = (buffer*)examine(queue);
  233. len = writebuf->len - 1 - writebuf->pos;
  234. if (len > written) {
  235. /* partial buffer write */
  236. buf_incrpos(writebuf, written);
  237. written = 0;
  238. } else {
  239. written -= len;
  240. dequeue(queue);
  241. buf_free(writebuf);
  242. }
  243. }
  244. }
  245. void set_sock_nodelay(int sock) {
  246. int val;
  247. /* disable nagle */
  248. val = 1;
  249. setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void*)&val, sizeof(val));
  250. }
  251. #ifdef DROPBEAR_SERVER_TCP_FAST_OPEN
  252. void set_listen_fast_open(int sock) {
  253. int qlen = MAX(MAX_UNAUTH_PER_IP, 5);
  254. if (setsockopt(sock, SOL_TCP, TCP_FASTOPEN, &qlen, sizeof(qlen)) != 0) {
  255. TRACE(("set_listen_fast_open failed for socket %d: %s", sock, strerror(errno)))
  256. }
  257. }
  258. #endif
  259. void set_sock_priority(int sock, enum dropbear_prio prio) {
  260. int rc;
  261. #ifdef IPTOS_LOWDELAY
  262. int iptos_val = 0;
  263. #endif
  264. #ifdef SO_PRIORITY
  265. int so_prio_val = 0;
  266. #endif
  267. /* Don't log ENOTSOCK errors so that this can harmlessly be called
  268. * on a client '-J' proxy pipe */
  269. /* set the TOS bit for either ipv4 or ipv6 */
  270. #ifdef IPTOS_LOWDELAY
  271. if (prio == DROPBEAR_PRIO_LOWDELAY) {
  272. iptos_val = IPTOS_LOWDELAY;
  273. } else if (prio == DROPBEAR_PRIO_BULK) {
  274. iptos_val = IPTOS_THROUGHPUT;
  275. }
  276. #if defined(IPPROTO_IPV6) && defined(IPV6_TCLASS)
  277. rc = setsockopt(sock, IPPROTO_IPV6, IPV6_TCLASS, (void*)&iptos_val, sizeof(iptos_val));
  278. if (rc < 0 && errno != ENOTSOCK) {
  279. TRACE(("Couldn't set IPV6_TCLASS (%s)", strerror(errno)));
  280. }
  281. #endif
  282. rc = setsockopt(sock, IPPROTO_IP, IP_TOS, (void*)&iptos_val, sizeof(iptos_val));
  283. if (rc < 0 && errno != ENOTSOCK) {
  284. TRACE(("Couldn't set IP_TOS (%s)", strerror(errno)));
  285. }
  286. #endif
  287. #ifdef SO_PRIORITY
  288. if (prio == DROPBEAR_PRIO_LOWDELAY) {
  289. so_prio_val = TC_PRIO_INTERACTIVE;
  290. } else if (prio == DROPBEAR_PRIO_BULK) {
  291. so_prio_val = TC_PRIO_BULK;
  292. }
  293. /* linux specific, sets QoS class. see tc-prio(8) */
  294. rc = setsockopt(sock, SOL_SOCKET, SO_PRIORITY, (void*) &so_prio_val, sizeof(so_prio_val));
  295. if (rc < 0 && errno != ENOTSOCK)
  296. dropbear_log(LOG_WARNING, "Couldn't set SO_PRIORITY (%s)",
  297. strerror(errno));
  298. #endif
  299. }
  300. /* Listen on address:port.
  301. * Special cases are address of "" listening on everything,
  302. * and address of NULL listening on localhost only.
  303. * Returns the number of sockets bound on success, or -1 on failure. On
  304. * failure, if errstring wasn't NULL, it'll be a newly malloced error
  305. * string.*/
  306. int dropbear_listen(const char* address, const char* port,
  307. int *socks, unsigned int sockcount, char **errstring, int *maxfd) {
  308. struct addrinfo hints, *res = NULL, *res0 = NULL;
  309. int err;
  310. unsigned int nsock;
  311. struct linger linger;
  312. int val;
  313. int sock;
  314. TRACE(("enter dropbear_listen"))
  315. memset(&hints, 0, sizeof(hints));
  316. hints.ai_family = AF_UNSPEC; /* TODO: let them flag v4 only etc */
  317. hints.ai_socktype = SOCK_STREAM;
  318. /* for calling getaddrinfo:
  319. address == NULL and !AI_PASSIVE: local loopback
  320. address == NULL and AI_PASSIVE: all interfaces
  321. address != NULL: whatever the address says */
  322. if (!address) {
  323. TRACE(("dropbear_listen: local loopback"))
  324. } else {
  325. if (address[0] == '\0') {
  326. TRACE(("dropbear_listen: all interfaces"))
  327. address = NULL;
  328. }
  329. hints.ai_flags = AI_PASSIVE;
  330. }
  331. err = getaddrinfo(address, port, &hints, &res0);
  332. if (err) {
  333. if (errstring != NULL && *errstring == NULL) {
  334. int len;
  335. len = 20 + strlen(gai_strerror(err));
  336. *errstring = (char*)m_malloc(len);
  337. snprintf(*errstring, len, "Error resolving: %s", gai_strerror(err));
  338. }
  339. if (res0) {
  340. freeaddrinfo(res0);
  341. res0 = NULL;
  342. }
  343. TRACE(("leave dropbear_listen: failed resolving"))
  344. return -1;
  345. }
  346. nsock = 0;
  347. for (res = res0; res != NULL && nsock < sockcount;
  348. res = res->ai_next) {
  349. /* Get a socket */
  350. socks[nsock] = socket(res->ai_family, res->ai_socktype,
  351. res->ai_protocol);
  352. sock = socks[nsock]; /* For clarity */
  353. if (sock < 0) {
  354. err = errno;
  355. TRACE(("socket() failed"))
  356. continue;
  357. }
  358. /* Various useful socket options */
  359. val = 1;
  360. /* set to reuse, quick timeout */
  361. setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*) &val, sizeof(val));
  362. linger.l_onoff = 1;
  363. linger.l_linger = 5;
  364. setsockopt(sock, SOL_SOCKET, SO_LINGER, (void*)&linger, sizeof(linger));
  365. #if defined(IPPROTO_IPV6) && defined(IPV6_V6ONLY)
  366. if (res->ai_family == AF_INET6) {
  367. int on = 1;
  368. if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
  369. &on, sizeof(on)) == -1) {
  370. dropbear_log(LOG_WARNING, "Couldn't set IPV6_V6ONLY");
  371. }
  372. }
  373. #endif
  374. set_sock_nodelay(sock);
  375. if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) {
  376. err = errno;
  377. close(sock);
  378. TRACE(("bind(%s) failed", port))
  379. continue;
  380. }
  381. if (listen(sock, DROPBEAR_LISTEN_BACKLOG) < 0) {
  382. err = errno;
  383. close(sock);
  384. TRACE(("listen() failed"))
  385. continue;
  386. }
  387. *maxfd = MAX(*maxfd, sock);
  388. nsock++;
  389. }
  390. if (res0) {
  391. freeaddrinfo(res0);
  392. res0 = NULL;
  393. }
  394. if (nsock == 0) {
  395. if (errstring != NULL && *errstring == NULL) {
  396. int len;
  397. len = 20 + strlen(strerror(err));
  398. *errstring = (char*)m_malloc(len);
  399. snprintf(*errstring, len, "Error listening: %s", strerror(err));
  400. }
  401. TRACE(("leave dropbear_listen: failure, %s", strerror(err)))
  402. return -1;
  403. }
  404. TRACE(("leave dropbear_listen: success, %d socks bound", nsock))
  405. return nsock;
  406. }
  407. void get_socket_address(int fd, char **local_host, char **local_port,
  408. char **remote_host, char **remote_port, int host_lookup)
  409. {
  410. struct sockaddr_storage addr;
  411. socklen_t addrlen;
  412. if (local_host || local_port) {
  413. addrlen = sizeof(addr);
  414. if (getsockname(fd, (struct sockaddr*)&addr, &addrlen) < 0) {
  415. dropbear_exit("Failed socket address: %s", strerror(errno));
  416. }
  417. getaddrstring(&addr, local_host, local_port, host_lookup);
  418. }
  419. if (remote_host || remote_port) {
  420. addrlen = sizeof(addr);
  421. if (getpeername(fd, (struct sockaddr*)&addr, &addrlen) < 0) {
  422. dropbear_exit("Failed socket address: %s", strerror(errno));
  423. }
  424. getaddrstring(&addr, remote_host, remote_port, host_lookup);
  425. }
  426. }
  427. /* Return a string representation of the socket address passed. The return
  428. * value is allocated with malloc() */
  429. void getaddrstring(struct sockaddr_storage* addr,
  430. char **ret_host, char **ret_port,
  431. int host_lookup) {
  432. char host[NI_MAXHOST+1], serv[NI_MAXSERV+1];
  433. unsigned int len;
  434. int ret;
  435. int flags = NI_NUMERICSERV | NI_NUMERICHOST;
  436. #ifndef DO_HOST_LOOKUP
  437. host_lookup = 0;
  438. #endif
  439. if (host_lookup) {
  440. flags = NI_NUMERICSERV;
  441. }
  442. len = sizeof(struct sockaddr_storage);
  443. /* Some platforms such as Solaris 8 require that len is the length
  444. * of the specific structure. Some older linux systems (glibc 2.1.3
  445. * such as debian potato) have sockaddr_storage.__ss_family instead
  446. * but we'll ignore them */
  447. #ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY
  448. if (addr->ss_family == AF_INET) {
  449. len = sizeof(struct sockaddr_in);
  450. }
  451. #ifdef AF_INET6
  452. if (addr->ss_family == AF_INET6) {
  453. len = sizeof(struct sockaddr_in6);
  454. }
  455. #endif
  456. #endif
  457. ret = getnameinfo((struct sockaddr*)addr, len, host, sizeof(host)-1,
  458. serv, sizeof(serv)-1, flags);
  459. if (ret != 0) {
  460. if (host_lookup) {
  461. /* On some systems (Darwin does it) we get EINTR from getnameinfo
  462. * somehow. Eew. So we'll just return the IP, since that doesn't seem
  463. * to exhibit that behaviour. */
  464. getaddrstring(addr, ret_host, ret_port, 0);
  465. return;
  466. } else {
  467. /* if we can't do a numeric lookup, something's gone terribly wrong */
  468. dropbear_exit("Failed lookup: %s", gai_strerror(ret));
  469. }
  470. }
  471. if (ret_host) {
  472. *ret_host = m_strdup(host);
  473. }
  474. if (ret_port) {
  475. *ret_port = m_strdup(serv);
  476. }
  477. }