tcp.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026
  1. /*
  2. * GRUB -- GRand Unified Bootloader
  3. * Copyright (C) 2010,2011 Free Software Foundation, Inc.
  4. *
  5. * GRUB is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation, either version 3 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * GRUB is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. #include <grub/net.h>
  19. #include <grub/net/ip.h>
  20. #include <grub/net/tcp.h>
  21. #include <grub/net/netbuff.h>
  22. #include <grub/time.h>
  23. #include <grub/priority_queue.h>
  24. #define TCP_SYN_RETRANSMISSION_TIMEOUT GRUB_NET_INTERVAL
  25. #define TCP_SYN_RETRANSMISSION_COUNT GRUB_NET_TRIES
  26. #define TCP_RETRANSMISSION_TIMEOUT GRUB_NET_INTERVAL
  27. #define TCP_RETRANSMISSION_COUNT GRUB_NET_TRIES
  28. struct unacked
  29. {
  30. struct unacked *next;
  31. struct unacked **prev;
  32. struct grub_net_buff *nb;
  33. grub_uint64_t last_try;
  34. int try_count;
  35. };
  36. enum
  37. {
  38. TCP_FIN = 0x1,
  39. TCP_SYN = 0x2,
  40. TCP_RST = 0x4,
  41. TCP_PUSH = 0x8,
  42. TCP_ACK = 0x10,
  43. TCP_URG = 0x20,
  44. };
  45. struct grub_net_tcp_socket
  46. {
  47. struct grub_net_tcp_socket *next;
  48. struct grub_net_tcp_socket **prev;
  49. int established;
  50. int i_closed;
  51. int they_closed;
  52. int in_port;
  53. int out_port;
  54. int errors;
  55. int they_reseted;
  56. int i_reseted;
  57. int i_stall;
  58. grub_uint32_t my_start_seq;
  59. grub_uint32_t my_cur_seq;
  60. grub_uint32_t their_start_seq;
  61. grub_uint32_t their_cur_seq;
  62. grub_uint16_t my_window;
  63. struct unacked *unack_first;
  64. struct unacked *unack_last;
  65. grub_err_t (*recv_hook) (grub_net_tcp_socket_t sock, struct grub_net_buff *nb,
  66. void *recv);
  67. void (*error_hook) (grub_net_tcp_socket_t sock, void *recv);
  68. void (*fin_hook) (grub_net_tcp_socket_t sock, void *recv);
  69. void *hook_data;
  70. grub_net_network_level_address_t out_nla;
  71. grub_net_link_level_address_t ll_target_addr;
  72. struct grub_net_network_level_interface *inf;
  73. grub_net_packets_t packs;
  74. grub_priority_queue_t pq;
  75. };
  76. struct grub_net_tcp_listen
  77. {
  78. struct grub_net_tcp_listen *next;
  79. struct grub_net_tcp_listen **prev;
  80. grub_uint16_t port;
  81. const struct grub_net_network_level_interface *inf;
  82. grub_err_t (*listen_hook) (grub_net_tcp_listen_t listen,
  83. grub_net_tcp_socket_t sock,
  84. void *data);
  85. void *hook_data;
  86. };
  87. struct tcphdr
  88. {
  89. grub_uint16_t src;
  90. grub_uint16_t dst;
  91. grub_uint32_t seqnr;
  92. grub_uint32_t ack;
  93. grub_uint16_t flags;
  94. grub_uint16_t window;
  95. grub_uint16_t checksum;
  96. grub_uint16_t urgent;
  97. } GRUB_PACKED;
  98. struct tcp_pseudohdr
  99. {
  100. grub_uint32_t src;
  101. grub_uint32_t dst;
  102. grub_uint8_t zero;
  103. grub_uint8_t proto;
  104. grub_uint16_t tcp_length;
  105. } GRUB_PACKED;
  106. struct tcp6_pseudohdr
  107. {
  108. grub_uint64_t src[2];
  109. grub_uint64_t dst[2];
  110. grub_uint32_t tcp_length;
  111. grub_uint8_t zero[3];
  112. grub_uint8_t proto;
  113. } GRUB_PACKED;
  114. static struct grub_net_tcp_socket *tcp_sockets;
  115. static struct grub_net_tcp_listen *tcp_listens;
  116. #define FOR_TCP_SOCKETS(var) FOR_LIST_ELEMENTS (var, tcp_sockets)
  117. #define FOR_TCP_LISTENS(var) FOR_LIST_ELEMENTS (var, tcp_listens)
  118. grub_net_tcp_listen_t
  119. grub_net_tcp_listen (grub_uint16_t port,
  120. const struct grub_net_network_level_interface *inf,
  121. grub_err_t (*listen_hook) (grub_net_tcp_listen_t listen,
  122. grub_net_tcp_socket_t sock,
  123. void *data),
  124. void *hook_data)
  125. {
  126. grub_net_tcp_listen_t ret;
  127. ret = grub_malloc (sizeof (*ret));
  128. if (!ret)
  129. return NULL;
  130. ret->listen_hook = listen_hook;
  131. ret->hook_data = hook_data;
  132. ret->port = port;
  133. ret->inf = inf;
  134. grub_list_push (GRUB_AS_LIST_P (&tcp_listens), GRUB_AS_LIST (ret));
  135. return ret;
  136. }
  137. void
  138. grub_net_tcp_stop_listen (grub_net_tcp_listen_t listen)
  139. {
  140. grub_list_remove (GRUB_AS_LIST (listen));
  141. }
  142. static inline void
  143. tcp_socket_register (grub_net_tcp_socket_t sock)
  144. {
  145. grub_list_push (GRUB_AS_LIST_P (&tcp_sockets),
  146. GRUB_AS_LIST (sock));
  147. }
  148. static void
  149. error (grub_net_tcp_socket_t sock)
  150. {
  151. struct unacked *unack, *next;
  152. if (sock->error_hook)
  153. sock->error_hook (sock, sock->hook_data);
  154. for (unack = sock->unack_first; unack; unack = next)
  155. {
  156. next = unack->next;
  157. grub_netbuff_free (unack->nb);
  158. grub_free (unack);
  159. }
  160. sock->unack_first = NULL;
  161. sock->unack_last = NULL;
  162. }
  163. static grub_err_t
  164. tcp_send (struct grub_net_buff *nb, grub_net_tcp_socket_t socket)
  165. {
  166. grub_err_t err;
  167. grub_uint8_t *nbd;
  168. struct unacked *unack;
  169. struct tcphdr *tcph;
  170. grub_size_t size;
  171. tcph = (struct tcphdr *) nb->data;
  172. tcph->seqnr = grub_cpu_to_be32 (socket->my_cur_seq);
  173. size = (nb->tail - nb->data - (grub_be_to_cpu16 (tcph->flags) >> 12) * 4);
  174. if (grub_be_to_cpu16 (tcph->flags) & TCP_FIN)
  175. size++;
  176. socket->my_cur_seq += size;
  177. tcph->src = grub_cpu_to_be16 (socket->in_port);
  178. tcph->dst = grub_cpu_to_be16 (socket->out_port);
  179. tcph->checksum = 0;
  180. tcph->checksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_TCP,
  181. &socket->inf->address,
  182. &socket->out_nla);
  183. nbd = nb->data;
  184. if (size)
  185. {
  186. unack = grub_malloc (sizeof (*unack));
  187. if (!unack)
  188. return grub_errno;
  189. unack->next = NULL;
  190. unack->nb = nb;
  191. unack->try_count = 1;
  192. unack->last_try = grub_get_time_ms ();
  193. if (!socket->unack_last)
  194. socket->unack_first = socket->unack_last = unack;
  195. else
  196. socket->unack_last->next = unack;
  197. }
  198. err = grub_net_send_ip_packet (socket->inf, &(socket->out_nla),
  199. &(socket->ll_target_addr), nb,
  200. GRUB_NET_IP_TCP);
  201. if (err)
  202. return err;
  203. nb->data = nbd;
  204. if (!size)
  205. grub_netbuff_free (nb);
  206. return GRUB_ERR_NONE;
  207. }
  208. void
  209. grub_net_tcp_close (grub_net_tcp_socket_t sock,
  210. int discard_received)
  211. {
  212. struct grub_net_buff *nb_fin;
  213. struct tcphdr *tcph_fin;
  214. grub_err_t err;
  215. if (discard_received != GRUB_NET_TCP_CONTINUE_RECEIVING)
  216. {
  217. sock->recv_hook = NULL;
  218. sock->error_hook = NULL;
  219. sock->fin_hook = NULL;
  220. }
  221. if (discard_received == GRUB_NET_TCP_ABORT)
  222. sock->i_reseted = 1;
  223. if (sock->i_closed)
  224. return;
  225. sock->i_closed = 1;
  226. nb_fin = grub_netbuff_alloc (sizeof (*tcph_fin)
  227. + GRUB_NET_OUR_MAX_IP_HEADER_SIZE
  228. + GRUB_NET_MAX_LINK_HEADER_SIZE);
  229. if (!nb_fin)
  230. return;
  231. err = grub_netbuff_reserve (nb_fin, GRUB_NET_OUR_MAX_IP_HEADER_SIZE
  232. + GRUB_NET_MAX_LINK_HEADER_SIZE);
  233. if (err)
  234. {
  235. grub_netbuff_free (nb_fin);
  236. grub_dprintf ("net", "error closing socket\n");
  237. grub_errno = GRUB_ERR_NONE;
  238. return;
  239. }
  240. err = grub_netbuff_put (nb_fin, sizeof (*tcph_fin));
  241. if (err)
  242. {
  243. grub_netbuff_free (nb_fin);
  244. grub_dprintf ("net", "error closing socket\n");
  245. grub_errno = GRUB_ERR_NONE;
  246. return;
  247. }
  248. tcph_fin = (void *) nb_fin->data;
  249. tcph_fin->ack = grub_cpu_to_be32 (sock->their_cur_seq);
  250. tcph_fin->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_FIN
  251. | TCP_ACK);
  252. tcph_fin->window = grub_cpu_to_be16_compile_time (0);
  253. tcph_fin->urgent = 0;
  254. err = tcp_send (nb_fin, sock);
  255. if (err)
  256. {
  257. grub_netbuff_free (nb_fin);
  258. grub_dprintf ("net", "error closing socket\n");
  259. grub_errno = GRUB_ERR_NONE;
  260. }
  261. return;
  262. }
  263. static void
  264. ack_real (grub_net_tcp_socket_t sock, int res)
  265. {
  266. struct grub_net_buff *nb_ack;
  267. struct tcphdr *tcph_ack;
  268. grub_err_t err;
  269. nb_ack = grub_netbuff_alloc (sizeof (*tcph_ack) + 128);
  270. if (!nb_ack)
  271. return;
  272. err = grub_netbuff_reserve (nb_ack, 128);
  273. if (err)
  274. {
  275. grub_netbuff_free (nb_ack);
  276. grub_dprintf ("net", "error closing socket\n");
  277. grub_errno = GRUB_ERR_NONE;
  278. return;
  279. }
  280. err = grub_netbuff_put (nb_ack, sizeof (*tcph_ack));
  281. if (err)
  282. {
  283. grub_netbuff_free (nb_ack);
  284. grub_dprintf ("net", "error closing socket\n");
  285. grub_errno = GRUB_ERR_NONE;
  286. return;
  287. }
  288. tcph_ack = (void *) nb_ack->data;
  289. if (res)
  290. {
  291. tcph_ack->ack = grub_cpu_to_be32_compile_time (0);
  292. tcph_ack->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_RST);
  293. tcph_ack->window = grub_cpu_to_be16_compile_time (0);
  294. }
  295. else
  296. {
  297. tcph_ack->ack = grub_cpu_to_be32 (sock->their_cur_seq);
  298. tcph_ack->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_ACK);
  299. tcph_ack->window = !sock->i_stall ? grub_cpu_to_be16 (sock->my_window)
  300. : 0;
  301. }
  302. tcph_ack->urgent = 0;
  303. tcph_ack->src = grub_cpu_to_be16 (sock->in_port);
  304. tcph_ack->dst = grub_cpu_to_be16 (sock->out_port);
  305. err = tcp_send (nb_ack, sock);
  306. if (err)
  307. {
  308. grub_dprintf ("net", "error acking socket\n");
  309. grub_errno = GRUB_ERR_NONE;
  310. }
  311. }
  312. static void
  313. ack (grub_net_tcp_socket_t sock)
  314. {
  315. ack_real (sock, 0);
  316. }
  317. static void
  318. reset (grub_net_tcp_socket_t sock)
  319. {
  320. ack_real (sock, 1);
  321. }
  322. void
  323. grub_net_tcp_retransmit (void)
  324. {
  325. grub_net_tcp_socket_t sock;
  326. grub_uint64_t ctime = 0, limit_time = 0;
  327. if (tcp_sockets != NULL)
  328. {
  329. ctime = grub_get_time_ms ();
  330. limit_time = ctime - TCP_RETRANSMISSION_TIMEOUT;
  331. }
  332. FOR_TCP_SOCKETS (sock)
  333. {
  334. struct unacked *unack;
  335. for (unack = sock->unack_first; unack; unack = unack->next)
  336. {
  337. struct tcphdr *tcph;
  338. grub_uint8_t *nbd;
  339. grub_err_t err;
  340. if (unack->last_try > limit_time)
  341. continue;
  342. if (unack->try_count > TCP_RETRANSMISSION_COUNT)
  343. {
  344. error (sock);
  345. break;
  346. }
  347. unack->try_count++;
  348. unack->last_try = ctime;
  349. nbd = unack->nb->data;
  350. tcph = (struct tcphdr *) nbd;
  351. if ((tcph->flags & grub_cpu_to_be16_compile_time (TCP_ACK))
  352. && tcph->ack != grub_cpu_to_be32 (sock->their_cur_seq))
  353. {
  354. tcph->checksum = 0;
  355. tcph->checksum = grub_net_ip_transport_checksum (unack->nb,
  356. GRUB_NET_IP_TCP,
  357. &sock->inf->address,
  358. &sock->out_nla);
  359. }
  360. err = grub_net_send_ip_packet (sock->inf, &(sock->out_nla),
  361. &(sock->ll_target_addr), unack->nb,
  362. GRUB_NET_IP_TCP);
  363. unack->nb->data = nbd;
  364. if (err)
  365. {
  366. grub_dprintf ("net", "TCP retransmit failed: %s\n", grub_errmsg);
  367. grub_errno = GRUB_ERR_NONE;
  368. }
  369. }
  370. }
  371. }
  372. grub_uint16_t
  373. grub_net_ip_transport_checksum (struct grub_net_buff *nb,
  374. grub_uint16_t proto,
  375. const grub_net_network_level_address_t *src,
  376. const grub_net_network_level_address_t *dst)
  377. {
  378. grub_uint16_t a, b = 0;
  379. grub_uint32_t c;
  380. a = ~grub_be_to_cpu16 (grub_net_ip_chksum ((void *) nb->data,
  381. nb->tail - nb->data));
  382. switch (dst->type)
  383. {
  384. case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
  385. {
  386. struct tcp_pseudohdr ph;
  387. ph.src = src->ipv4;
  388. ph.dst = dst->ipv4;
  389. ph.zero = 0;
  390. ph.tcp_length = grub_cpu_to_be16 (nb->tail - nb->data);
  391. ph.proto = proto;
  392. b = ~grub_be_to_cpu16 (grub_net_ip_chksum ((void *) &ph, sizeof (ph)));
  393. break;
  394. }
  395. case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6:
  396. {
  397. struct tcp6_pseudohdr ph;
  398. grub_memcpy (ph.src, src->ipv6, sizeof (ph.src));
  399. grub_memcpy (ph.dst, dst->ipv6, sizeof (ph.dst));
  400. grub_memset (ph.zero, 0, sizeof (ph.zero));
  401. ph.tcp_length = grub_cpu_to_be32 (nb->tail - nb->data);
  402. ph.proto = proto;
  403. b = ~grub_be_to_cpu16 (grub_net_ip_chksum ((void *) &ph, sizeof (ph)));
  404. break;
  405. }
  406. case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV:
  407. b = 0;
  408. break;
  409. }
  410. c = (grub_uint32_t) a + (grub_uint32_t) b;
  411. if (c >= 0xffff)
  412. c -= 0xffff;
  413. return grub_cpu_to_be16 (~c);
  414. }
  415. /* FIXME: overflow. */
  416. static int
  417. cmp (const void *a__, const void *b__)
  418. {
  419. struct grub_net_buff *a_ = *(struct grub_net_buff **) a__;
  420. struct grub_net_buff *b_ = *(struct grub_net_buff **) b__;
  421. struct tcphdr *a = (struct tcphdr *) a_->data;
  422. struct tcphdr *b = (struct tcphdr *) b_->data;
  423. /* We want the first elements to be on top. */
  424. if (grub_be_to_cpu32 (a->seqnr) < grub_be_to_cpu32 (b->seqnr))
  425. return +1;
  426. if (grub_be_to_cpu32 (a->seqnr) > grub_be_to_cpu32 (b->seqnr))
  427. return -1;
  428. return 0;
  429. }
  430. static void
  431. destroy_pq (grub_net_tcp_socket_t sock)
  432. {
  433. struct grub_net_buff **nb_p;
  434. while ((nb_p = grub_priority_queue_top (sock->pq)))
  435. {
  436. grub_netbuff_free (*nb_p);
  437. grub_priority_queue_pop (sock->pq);
  438. }
  439. grub_priority_queue_destroy (sock->pq);
  440. }
  441. grub_err_t
  442. grub_net_tcp_accept (grub_net_tcp_socket_t sock,
  443. grub_err_t (*recv_hook) (grub_net_tcp_socket_t sock,
  444. struct grub_net_buff *nb,
  445. void *data),
  446. void (*error_hook) (grub_net_tcp_socket_t sock,
  447. void *data),
  448. void (*fin_hook) (grub_net_tcp_socket_t sock,
  449. void *data),
  450. void *hook_data)
  451. {
  452. struct grub_net_buff *nb_ack;
  453. struct tcphdr *tcph;
  454. grub_err_t err;
  455. grub_net_network_level_address_t gateway;
  456. struct grub_net_network_level_interface *inf;
  457. sock->recv_hook = recv_hook;
  458. sock->error_hook = error_hook;
  459. sock->fin_hook = fin_hook;
  460. sock->hook_data = hook_data;
  461. err = grub_net_route_address (sock->out_nla, &gateway, &inf);
  462. if (err)
  463. return err;
  464. err = grub_net_link_layer_resolve (sock->inf, &gateway, &(sock->ll_target_addr));
  465. if (err)
  466. return err;
  467. nb_ack = grub_netbuff_alloc (sizeof (*tcph)
  468. + GRUB_NET_OUR_MAX_IP_HEADER_SIZE
  469. + GRUB_NET_MAX_LINK_HEADER_SIZE);
  470. if (!nb_ack)
  471. return grub_errno;
  472. err = grub_netbuff_reserve (nb_ack, GRUB_NET_OUR_MAX_IP_HEADER_SIZE
  473. + GRUB_NET_MAX_LINK_HEADER_SIZE);
  474. if (err)
  475. {
  476. grub_netbuff_free (nb_ack);
  477. return err;
  478. }
  479. err = grub_netbuff_put (nb_ack, sizeof (*tcph));
  480. if (err)
  481. {
  482. grub_netbuff_free (nb_ack);
  483. return err;
  484. }
  485. tcph = (void *) nb_ack->data;
  486. tcph->ack = grub_cpu_to_be32 (sock->their_cur_seq);
  487. tcph->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_SYN | TCP_ACK);
  488. tcph->window = grub_cpu_to_be16 (sock->my_window);
  489. tcph->urgent = 0;
  490. sock->established = 1;
  491. tcp_socket_register (sock);
  492. err = tcp_send (nb_ack, sock);
  493. if (err)
  494. return err;
  495. sock->my_cur_seq++;
  496. return GRUB_ERR_NONE;
  497. }
  498. grub_net_tcp_socket_t
  499. grub_net_tcp_open (char *server,
  500. grub_uint16_t out_port,
  501. grub_err_t (*recv_hook) (grub_net_tcp_socket_t sock,
  502. struct grub_net_buff *nb,
  503. void *data),
  504. void (*error_hook) (grub_net_tcp_socket_t sock,
  505. void *data),
  506. void (*fin_hook) (grub_net_tcp_socket_t sock,
  507. void *data),
  508. void *hook_data)
  509. {
  510. grub_err_t err;
  511. grub_net_network_level_address_t addr;
  512. struct grub_net_network_level_interface *inf;
  513. grub_net_network_level_address_t gateway;
  514. grub_net_tcp_socket_t socket;
  515. static grub_uint16_t in_port = 21550;
  516. struct grub_net_buff *nb;
  517. struct tcphdr *tcph;
  518. int i;
  519. grub_uint8_t *nbd;
  520. grub_net_link_level_address_t ll_target_addr;
  521. err = grub_net_resolve_address (server, &addr);
  522. if (err)
  523. return NULL;
  524. if (addr.type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4
  525. && addr.type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6)
  526. {
  527. grub_error (GRUB_ERR_BUG, "not an IP address");
  528. return NULL;
  529. }
  530. err = grub_net_route_address (addr, &gateway, &inf);
  531. if (err)
  532. return NULL;
  533. err = grub_net_link_layer_resolve (inf, &gateway, &ll_target_addr);
  534. if (err)
  535. return NULL;
  536. socket = grub_zalloc (sizeof (*socket));
  537. if (socket == NULL)
  538. return NULL;
  539. socket->out_port = out_port;
  540. socket->inf = inf;
  541. socket->out_nla = addr;
  542. socket->ll_target_addr = ll_target_addr;
  543. socket->in_port = in_port++;
  544. socket->recv_hook = recv_hook;
  545. socket->error_hook = error_hook;
  546. socket->fin_hook = fin_hook;
  547. socket->hook_data = hook_data;
  548. nb = grub_netbuff_alloc (sizeof (*tcph) + 128);
  549. if (!nb)
  550. {
  551. grub_free (socket);
  552. return NULL;
  553. }
  554. err = grub_netbuff_reserve (nb, 128);
  555. if (err)
  556. {
  557. grub_free (socket);
  558. grub_netbuff_free (nb);
  559. return NULL;
  560. }
  561. err = grub_netbuff_put (nb, sizeof (*tcph));
  562. if (err)
  563. {
  564. grub_free (socket);
  565. grub_netbuff_free (nb);
  566. return NULL;
  567. }
  568. socket->pq = grub_priority_queue_new (sizeof (struct grub_net_buff *), cmp);
  569. if (!socket->pq)
  570. {
  571. grub_free (socket);
  572. grub_netbuff_free (nb);
  573. return NULL;
  574. }
  575. tcph = (void *) nb->data;
  576. socket->my_start_seq = grub_get_time_ms ();
  577. socket->my_cur_seq = socket->my_start_seq + 1;
  578. socket->my_window = 8192;
  579. tcph->seqnr = grub_cpu_to_be32 (socket->my_start_seq);
  580. tcph->ack = grub_cpu_to_be32_compile_time (0);
  581. tcph->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_SYN);
  582. tcph->window = grub_cpu_to_be16 (socket->my_window);
  583. tcph->urgent = 0;
  584. tcph->src = grub_cpu_to_be16 (socket->in_port);
  585. tcph->dst = grub_cpu_to_be16 (socket->out_port);
  586. tcph->checksum = 0;
  587. tcph->checksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_TCP,
  588. &socket->inf->address,
  589. &socket->out_nla);
  590. tcp_socket_register (socket);
  591. nbd = nb->data;
  592. for (i = 0; i < TCP_SYN_RETRANSMISSION_COUNT; i++)
  593. {
  594. int j;
  595. nb->data = nbd;
  596. err = grub_net_send_ip_packet (socket->inf, &(socket->out_nla),
  597. &(socket->ll_target_addr), nb,
  598. GRUB_NET_IP_TCP);
  599. if (err)
  600. {
  601. grub_list_remove (GRUB_AS_LIST (socket));
  602. grub_free (socket);
  603. grub_netbuff_free (nb);
  604. return NULL;
  605. }
  606. for (j = 0; (j < TCP_SYN_RETRANSMISSION_TIMEOUT / 50
  607. && !socket->established); j++)
  608. grub_net_poll_cards (50, &socket->established);
  609. if (socket->established)
  610. break;
  611. }
  612. if (!socket->established)
  613. {
  614. grub_list_remove (GRUB_AS_LIST (socket));
  615. if (socket->they_reseted)
  616. grub_error (GRUB_ERR_NET_PORT_CLOSED,
  617. N_("connection refused"));
  618. else
  619. grub_error (GRUB_ERR_NET_NO_ANSWER,
  620. N_("connection timeout"));
  621. grub_netbuff_free (nb);
  622. destroy_pq (socket);
  623. grub_free (socket);
  624. return NULL;
  625. }
  626. grub_netbuff_free (nb);
  627. return socket;
  628. }
  629. grub_err_t
  630. grub_net_send_tcp_packet (const grub_net_tcp_socket_t socket,
  631. struct grub_net_buff *nb, int push)
  632. {
  633. struct tcphdr *tcph;
  634. grub_err_t err;
  635. grub_ssize_t fraglen;
  636. COMPILE_TIME_ASSERT (sizeof (struct tcphdr) == GRUB_NET_TCP_HEADER_SIZE);
  637. if (socket->out_nla.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4)
  638. fraglen = (socket->inf->card->mtu - GRUB_NET_OUR_IPV4_HEADER_SIZE
  639. - sizeof (*tcph));
  640. else
  641. fraglen = 1280 - GRUB_NET_OUR_IPV6_HEADER_SIZE;
  642. while (nb->tail - nb->data > fraglen)
  643. {
  644. struct grub_net_buff *nb2;
  645. nb2 = grub_netbuff_alloc (fraglen + sizeof (*tcph)
  646. + GRUB_NET_OUR_MAX_IP_HEADER_SIZE
  647. + GRUB_NET_MAX_LINK_HEADER_SIZE);
  648. if (!nb2)
  649. return grub_errno;
  650. err = grub_netbuff_reserve (nb2, GRUB_NET_MAX_LINK_HEADER_SIZE
  651. + GRUB_NET_OUR_MAX_IP_HEADER_SIZE);
  652. if (err)
  653. return err;
  654. err = grub_netbuff_put (nb2, sizeof (*tcph));
  655. if (err)
  656. return err;
  657. tcph = (struct tcphdr *) nb2->data;
  658. tcph->ack = grub_cpu_to_be32 (socket->their_cur_seq);
  659. tcph->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_ACK);
  660. tcph->window = !socket->i_stall ? grub_cpu_to_be16 (socket->my_window)
  661. : 0;
  662. tcph->urgent = 0;
  663. err = grub_netbuff_put (nb2, fraglen);
  664. if (err)
  665. return err;
  666. grub_memcpy (tcph + 1, nb->data, fraglen);
  667. err = grub_netbuff_pull (nb, fraglen);
  668. if (err)
  669. return err;
  670. err = tcp_send (nb2, socket);
  671. if (err)
  672. return err;
  673. }
  674. err = grub_netbuff_push (nb, sizeof (*tcph));
  675. if (err)
  676. return err;
  677. tcph = (struct tcphdr *) nb->data;
  678. tcph->ack = grub_cpu_to_be32 (socket->their_cur_seq);
  679. tcph->flags = (grub_cpu_to_be16_compile_time ((5 << 12) | TCP_ACK)
  680. | (push ? grub_cpu_to_be16_compile_time (TCP_PUSH) : 0));
  681. tcph->window = !socket->i_stall ? grub_cpu_to_be16 (socket->my_window) : 0;
  682. tcph->urgent = 0;
  683. return tcp_send (nb, socket);
  684. }
  685. grub_err_t
  686. grub_net_recv_tcp_packet (struct grub_net_buff *nb,
  687. struct grub_net_network_level_interface *inf,
  688. const grub_net_network_level_address_t *source)
  689. {
  690. struct tcphdr *tcph;
  691. grub_net_tcp_socket_t sock;
  692. grub_err_t err;
  693. /* Ignore broadcast. */
  694. if (!inf)
  695. {
  696. grub_netbuff_free (nb);
  697. return GRUB_ERR_NONE;
  698. }
  699. tcph = (struct tcphdr *) nb->data;
  700. if ((grub_be_to_cpu16 (tcph->flags) >> 12) < 5)
  701. {
  702. grub_dprintf ("net", "TCP header too short: %u\n",
  703. grub_be_to_cpu16 (tcph->flags) >> 12);
  704. grub_netbuff_free (nb);
  705. return GRUB_ERR_NONE;
  706. }
  707. if (nb->tail - nb->data < (grub_ssize_t) ((grub_be_to_cpu16 (tcph->flags)
  708. >> 12) * sizeof (grub_uint32_t)))
  709. {
  710. grub_dprintf ("net", "TCP packet too short: %" PRIuGRUB_SIZE "\n",
  711. (grub_size_t) (nb->tail - nb->data));
  712. grub_netbuff_free (nb);
  713. return GRUB_ERR_NONE;
  714. }
  715. FOR_TCP_SOCKETS (sock)
  716. {
  717. if (!(grub_be_to_cpu16 (tcph->dst) == sock->in_port
  718. && grub_be_to_cpu16 (tcph->src) == sock->out_port
  719. && inf == sock->inf
  720. && grub_net_addr_cmp (source, &sock->out_nla) == 0))
  721. continue;
  722. if (tcph->checksum)
  723. {
  724. grub_uint16_t chk, expected;
  725. chk = tcph->checksum;
  726. tcph->checksum = 0;
  727. expected = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_TCP,
  728. &sock->out_nla,
  729. &sock->inf->address);
  730. if (expected != chk)
  731. {
  732. grub_dprintf ("net", "Invalid TCP checksum. "
  733. "Expected %x, got %x\n",
  734. grub_be_to_cpu16 (expected),
  735. grub_be_to_cpu16 (chk));
  736. grub_netbuff_free (nb);
  737. return GRUB_ERR_NONE;
  738. }
  739. tcph->checksum = chk;
  740. }
  741. if ((grub_be_to_cpu16 (tcph->flags) & TCP_SYN)
  742. && (grub_be_to_cpu16 (tcph->flags) & TCP_ACK)
  743. && !sock->established)
  744. {
  745. sock->their_start_seq = grub_be_to_cpu32 (tcph->seqnr);
  746. sock->their_cur_seq = sock->their_start_seq + 1;
  747. sock->established = 1;
  748. }
  749. if (grub_be_to_cpu16 (tcph->flags) & TCP_RST)
  750. {
  751. sock->they_reseted = 1;
  752. error (sock);
  753. grub_netbuff_free (nb);
  754. return GRUB_ERR_NONE;
  755. }
  756. if (grub_be_to_cpu16 (tcph->flags) & TCP_ACK)
  757. {
  758. struct unacked *unack, *next;
  759. grub_uint32_t acked = grub_be_to_cpu32 (tcph->ack);
  760. for (unack = sock->unack_first; unack; unack = next)
  761. {
  762. grub_uint32_t seqnr;
  763. struct tcphdr *unack_tcph;
  764. next = unack->next;
  765. seqnr = grub_be_to_cpu32 (((struct tcphdr *) unack->nb->data)
  766. ->seqnr);
  767. unack_tcph = (struct tcphdr *) unack->nb->data;
  768. seqnr += (unack->nb->tail - unack->nb->data
  769. - (grub_be_to_cpu16 (unack_tcph->flags) >> 12) * 4);
  770. if (grub_be_to_cpu16 (unack_tcph->flags) & TCP_FIN)
  771. seqnr++;
  772. if (seqnr > acked)
  773. break;
  774. grub_netbuff_free (unack->nb);
  775. grub_free (unack);
  776. }
  777. sock->unack_first = unack;
  778. if (!sock->unack_first)
  779. sock->unack_last = NULL;
  780. }
  781. if (grub_be_to_cpu32 (tcph->seqnr) < sock->their_cur_seq)
  782. {
  783. ack (sock);
  784. grub_netbuff_free (nb);
  785. return GRUB_ERR_NONE;
  786. }
  787. if (sock->i_reseted && (nb->tail - nb->data
  788. - (grub_be_to_cpu16 (tcph->flags)
  789. >> 12) * sizeof (grub_uint32_t)) > 0)
  790. {
  791. reset (sock);
  792. }
  793. err = grub_priority_queue_push (sock->pq, &nb);
  794. if (err)
  795. {
  796. grub_netbuff_free (nb);
  797. return err;
  798. }
  799. {
  800. struct grub_net_buff **nb_top_p, *nb_top;
  801. int do_ack = 0;
  802. int just_closed = 0;
  803. while (1)
  804. {
  805. nb_top_p = grub_priority_queue_top (sock->pq);
  806. if (!nb_top_p)
  807. return GRUB_ERR_NONE;
  808. nb_top = *nb_top_p;
  809. tcph = (struct tcphdr *) nb_top->data;
  810. if (grub_be_to_cpu32 (tcph->seqnr) >= sock->their_cur_seq)
  811. break;
  812. grub_netbuff_free (nb_top);
  813. grub_priority_queue_pop (sock->pq);
  814. }
  815. if (grub_be_to_cpu32 (tcph->seqnr) != sock->their_cur_seq)
  816. {
  817. ack (sock);
  818. return GRUB_ERR_NONE;
  819. }
  820. while (1)
  821. {
  822. nb_top_p = grub_priority_queue_top (sock->pq);
  823. if (!nb_top_p)
  824. break;
  825. nb_top = *nb_top_p;
  826. tcph = (struct tcphdr *) nb_top->data;
  827. if (grub_be_to_cpu32 (tcph->seqnr) != sock->their_cur_seq)
  828. break;
  829. grub_priority_queue_pop (sock->pq);
  830. err = grub_netbuff_pull (nb_top, (grub_be_to_cpu16 (tcph->flags)
  831. >> 12) * sizeof (grub_uint32_t));
  832. if (err)
  833. {
  834. grub_netbuff_free (nb_top);
  835. return err;
  836. }
  837. sock->their_cur_seq += (nb_top->tail - nb_top->data);
  838. if (grub_be_to_cpu16 (tcph->flags) & TCP_FIN)
  839. {
  840. sock->they_closed = 1;
  841. just_closed = 1;
  842. sock->their_cur_seq++;
  843. do_ack = 1;
  844. }
  845. /* If there is data, puts packet in socket list. */
  846. if ((nb_top->tail - nb_top->data) > 0)
  847. {
  848. grub_net_put_packet (&sock->packs, nb_top);
  849. do_ack = 1;
  850. }
  851. else
  852. grub_netbuff_free (nb_top);
  853. }
  854. if (do_ack)
  855. ack (sock);
  856. while (sock->packs.first)
  857. {
  858. nb = sock->packs.first->nb;
  859. if (sock->recv_hook)
  860. sock->recv_hook (sock, sock->packs.first->nb, sock->hook_data);
  861. else
  862. grub_netbuff_free (nb);
  863. grub_net_remove_packet (sock->packs.first);
  864. }
  865. if (sock->fin_hook && just_closed)
  866. sock->fin_hook (sock, sock->hook_data);
  867. }
  868. return GRUB_ERR_NONE;
  869. }
  870. if (grub_be_to_cpu16 (tcph->flags) & TCP_SYN)
  871. {
  872. grub_net_tcp_listen_t listen;
  873. FOR_TCP_LISTENS (listen)
  874. {
  875. if (!(grub_be_to_cpu16 (tcph->dst) == listen->port
  876. && (inf == listen->inf || listen->inf == NULL)))
  877. continue;
  878. sock = grub_zalloc (sizeof (*sock));
  879. if (sock == NULL)
  880. return grub_errno;
  881. sock->out_port = grub_be_to_cpu16 (tcph->src);
  882. sock->in_port = grub_be_to_cpu16 (tcph->dst);
  883. sock->inf = inf;
  884. sock->out_nla = *source;
  885. sock->their_start_seq = grub_be_to_cpu32 (tcph->seqnr);
  886. sock->their_cur_seq = sock->their_start_seq + 1;
  887. sock->my_cur_seq = sock->my_start_seq = grub_get_time_ms ();
  888. sock->my_window = 8192;
  889. sock->pq = grub_priority_queue_new (sizeof (struct grub_net_buff *),
  890. cmp);
  891. if (!sock->pq)
  892. {
  893. grub_free (sock);
  894. grub_netbuff_free (nb);
  895. return grub_errno;
  896. }
  897. err = listen->listen_hook (listen, sock, listen->hook_data);
  898. grub_netbuff_free (nb);
  899. return err;
  900. }
  901. }
  902. grub_netbuff_free (nb);
  903. return GRUB_ERR_NONE;
  904. }
  905. void
  906. grub_net_tcp_stall (grub_net_tcp_socket_t sock)
  907. {
  908. if (sock->i_stall)
  909. return;
  910. sock->i_stall = 1;
  911. ack (sock);
  912. }
  913. void
  914. grub_net_tcp_unstall (grub_net_tcp_socket_t sock)
  915. {
  916. if (!sock->i_stall)
  917. return;
  918. sock->i_stall = 0;
  919. ack (sock);
  920. }