tcp.c 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021
  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 = grub_get_time_ms ();
  327. grub_uint64_t limit_time = ctime - TCP_RETRANSMISSION_TIMEOUT;
  328. FOR_TCP_SOCKETS (sock)
  329. {
  330. struct unacked *unack;
  331. for (unack = sock->unack_first; unack; unack = unack->next)
  332. {
  333. struct tcphdr *tcph;
  334. grub_uint8_t *nbd;
  335. grub_err_t err;
  336. if (unack->last_try > limit_time)
  337. continue;
  338. if (unack->try_count > TCP_RETRANSMISSION_COUNT)
  339. {
  340. error (sock);
  341. break;
  342. }
  343. unack->try_count++;
  344. unack->last_try = ctime;
  345. nbd = unack->nb->data;
  346. tcph = (struct tcphdr *) nbd;
  347. if ((tcph->flags & grub_cpu_to_be16_compile_time (TCP_ACK))
  348. && tcph->ack != grub_cpu_to_be32 (sock->their_cur_seq))
  349. {
  350. tcph->checksum = 0;
  351. tcph->checksum = grub_net_ip_transport_checksum (unack->nb,
  352. GRUB_NET_IP_TCP,
  353. &sock->inf->address,
  354. &sock->out_nla);
  355. }
  356. err = grub_net_send_ip_packet (sock->inf, &(sock->out_nla),
  357. &(sock->ll_target_addr), unack->nb,
  358. GRUB_NET_IP_TCP);
  359. unack->nb->data = nbd;
  360. if (err)
  361. {
  362. grub_dprintf ("net", "TCP retransmit failed: %s\n", grub_errmsg);
  363. grub_errno = GRUB_ERR_NONE;
  364. }
  365. }
  366. }
  367. }
  368. grub_uint16_t
  369. grub_net_ip_transport_checksum (struct grub_net_buff *nb,
  370. grub_uint16_t proto,
  371. const grub_net_network_level_address_t *src,
  372. const grub_net_network_level_address_t *dst)
  373. {
  374. grub_uint16_t a, b = 0;
  375. grub_uint32_t c;
  376. a = ~grub_be_to_cpu16 (grub_net_ip_chksum ((void *) nb->data,
  377. nb->tail - nb->data));
  378. switch (dst->type)
  379. {
  380. case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4:
  381. {
  382. struct tcp_pseudohdr ph;
  383. ph.src = src->ipv4;
  384. ph.dst = dst->ipv4;
  385. ph.zero = 0;
  386. ph.tcp_length = grub_cpu_to_be16 (nb->tail - nb->data);
  387. ph.proto = proto;
  388. b = ~grub_be_to_cpu16 (grub_net_ip_chksum ((void *) &ph, sizeof (ph)));
  389. break;
  390. }
  391. case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6:
  392. {
  393. struct tcp6_pseudohdr ph;
  394. grub_memcpy (ph.src, src->ipv6, sizeof (ph.src));
  395. grub_memcpy (ph.dst, dst->ipv6, sizeof (ph.dst));
  396. grub_memset (ph.zero, 0, sizeof (ph.zero));
  397. ph.tcp_length = grub_cpu_to_be32 (nb->tail - nb->data);
  398. ph.proto = proto;
  399. b = ~grub_be_to_cpu16 (grub_net_ip_chksum ((void *) &ph, sizeof (ph)));
  400. break;
  401. }
  402. case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV:
  403. b = 0;
  404. break;
  405. }
  406. c = (grub_uint32_t) a + (grub_uint32_t) b;
  407. if (c >= 0xffff)
  408. c -= 0xffff;
  409. return grub_cpu_to_be16 (~c);
  410. }
  411. /* FIXME: overflow. */
  412. static int
  413. cmp (const void *a__, const void *b__)
  414. {
  415. struct grub_net_buff *a_ = *(struct grub_net_buff **) a__;
  416. struct grub_net_buff *b_ = *(struct grub_net_buff **) b__;
  417. struct tcphdr *a = (struct tcphdr *) a_->data;
  418. struct tcphdr *b = (struct tcphdr *) b_->data;
  419. /* We want the first elements to be on top. */
  420. if (grub_be_to_cpu32 (a->seqnr) < grub_be_to_cpu32 (b->seqnr))
  421. return +1;
  422. if (grub_be_to_cpu32 (a->seqnr) > grub_be_to_cpu32 (b->seqnr))
  423. return -1;
  424. return 0;
  425. }
  426. static void
  427. destroy_pq (grub_net_tcp_socket_t sock)
  428. {
  429. struct grub_net_buff **nb_p;
  430. while ((nb_p = grub_priority_queue_top (sock->pq)))
  431. {
  432. grub_netbuff_free (*nb_p);
  433. grub_priority_queue_pop (sock->pq);
  434. }
  435. grub_priority_queue_destroy (sock->pq);
  436. }
  437. grub_err_t
  438. grub_net_tcp_accept (grub_net_tcp_socket_t sock,
  439. grub_err_t (*recv_hook) (grub_net_tcp_socket_t sock,
  440. struct grub_net_buff *nb,
  441. void *data),
  442. void (*error_hook) (grub_net_tcp_socket_t sock,
  443. void *data),
  444. void (*fin_hook) (grub_net_tcp_socket_t sock,
  445. void *data),
  446. void *hook_data)
  447. {
  448. struct grub_net_buff *nb_ack;
  449. struct tcphdr *tcph;
  450. grub_err_t err;
  451. grub_net_network_level_address_t gateway;
  452. struct grub_net_network_level_interface *inf;
  453. sock->recv_hook = recv_hook;
  454. sock->error_hook = error_hook;
  455. sock->fin_hook = fin_hook;
  456. sock->hook_data = hook_data;
  457. err = grub_net_route_address (sock->out_nla, &gateway, &inf);
  458. if (err)
  459. return err;
  460. err = grub_net_link_layer_resolve (sock->inf, &gateway, &(sock->ll_target_addr));
  461. if (err)
  462. return err;
  463. nb_ack = grub_netbuff_alloc (sizeof (*tcph)
  464. + GRUB_NET_OUR_MAX_IP_HEADER_SIZE
  465. + GRUB_NET_MAX_LINK_HEADER_SIZE);
  466. if (!nb_ack)
  467. return grub_errno;
  468. err = grub_netbuff_reserve (nb_ack, GRUB_NET_OUR_MAX_IP_HEADER_SIZE
  469. + GRUB_NET_MAX_LINK_HEADER_SIZE);
  470. if (err)
  471. {
  472. grub_netbuff_free (nb_ack);
  473. return err;
  474. }
  475. err = grub_netbuff_put (nb_ack, sizeof (*tcph));
  476. if (err)
  477. {
  478. grub_netbuff_free (nb_ack);
  479. return err;
  480. }
  481. tcph = (void *) nb_ack->data;
  482. tcph->ack = grub_cpu_to_be32 (sock->their_cur_seq);
  483. tcph->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_SYN | TCP_ACK);
  484. tcph->window = grub_cpu_to_be16 (sock->my_window);
  485. tcph->urgent = 0;
  486. sock->established = 1;
  487. tcp_socket_register (sock);
  488. err = tcp_send (nb_ack, sock);
  489. if (err)
  490. return err;
  491. sock->my_cur_seq++;
  492. return GRUB_ERR_NONE;
  493. }
  494. grub_net_tcp_socket_t
  495. grub_net_tcp_open (char *server,
  496. grub_uint16_t out_port,
  497. grub_err_t (*recv_hook) (grub_net_tcp_socket_t sock,
  498. struct grub_net_buff *nb,
  499. void *data),
  500. void (*error_hook) (grub_net_tcp_socket_t sock,
  501. void *data),
  502. void (*fin_hook) (grub_net_tcp_socket_t sock,
  503. void *data),
  504. void *hook_data)
  505. {
  506. grub_err_t err;
  507. grub_net_network_level_address_t addr;
  508. struct grub_net_network_level_interface *inf;
  509. grub_net_network_level_address_t gateway;
  510. grub_net_tcp_socket_t socket;
  511. static grub_uint16_t in_port = 21550;
  512. struct grub_net_buff *nb;
  513. struct tcphdr *tcph;
  514. int i;
  515. grub_uint8_t *nbd;
  516. grub_net_link_level_address_t ll_target_addr;
  517. err = grub_net_resolve_address (server, &addr);
  518. if (err)
  519. return NULL;
  520. if (addr.type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4
  521. && addr.type != GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6)
  522. {
  523. grub_error (GRUB_ERR_BUG, "not an IP address");
  524. return NULL;
  525. }
  526. err = grub_net_route_address (addr, &gateway, &inf);
  527. if (err)
  528. return NULL;
  529. err = grub_net_link_layer_resolve (inf, &gateway, &ll_target_addr);
  530. if (err)
  531. return NULL;
  532. socket = grub_zalloc (sizeof (*socket));
  533. if (socket == NULL)
  534. return NULL;
  535. socket->out_port = out_port;
  536. socket->inf = inf;
  537. socket->out_nla = addr;
  538. socket->ll_target_addr = ll_target_addr;
  539. socket->in_port = in_port++;
  540. socket->recv_hook = recv_hook;
  541. socket->error_hook = error_hook;
  542. socket->fin_hook = fin_hook;
  543. socket->hook_data = hook_data;
  544. nb = grub_netbuff_alloc (sizeof (*tcph) + 128);
  545. if (!nb)
  546. {
  547. grub_free (socket);
  548. return NULL;
  549. }
  550. err = grub_netbuff_reserve (nb, 128);
  551. if (err)
  552. {
  553. grub_free (socket);
  554. grub_netbuff_free (nb);
  555. return NULL;
  556. }
  557. err = grub_netbuff_put (nb, sizeof (*tcph));
  558. if (err)
  559. {
  560. grub_free (socket);
  561. grub_netbuff_free (nb);
  562. return NULL;
  563. }
  564. socket->pq = grub_priority_queue_new (sizeof (struct grub_net_buff *), cmp);
  565. if (!socket->pq)
  566. {
  567. grub_free (socket);
  568. grub_netbuff_free (nb);
  569. return NULL;
  570. }
  571. tcph = (void *) nb->data;
  572. socket->my_start_seq = grub_get_time_ms ();
  573. socket->my_cur_seq = socket->my_start_seq + 1;
  574. socket->my_window = 8192;
  575. tcph->seqnr = grub_cpu_to_be32 (socket->my_start_seq);
  576. tcph->ack = grub_cpu_to_be32_compile_time (0);
  577. tcph->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_SYN);
  578. tcph->window = grub_cpu_to_be16 (socket->my_window);
  579. tcph->urgent = 0;
  580. tcph->src = grub_cpu_to_be16 (socket->in_port);
  581. tcph->dst = grub_cpu_to_be16 (socket->out_port);
  582. tcph->checksum = 0;
  583. tcph->checksum = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_TCP,
  584. &socket->inf->address,
  585. &socket->out_nla);
  586. tcp_socket_register (socket);
  587. nbd = nb->data;
  588. for (i = 0; i < TCP_SYN_RETRANSMISSION_COUNT; i++)
  589. {
  590. int j;
  591. nb->data = nbd;
  592. err = grub_net_send_ip_packet (socket->inf, &(socket->out_nla),
  593. &(socket->ll_target_addr), nb,
  594. GRUB_NET_IP_TCP);
  595. if (err)
  596. {
  597. grub_list_remove (GRUB_AS_LIST (socket));
  598. grub_free (socket);
  599. grub_netbuff_free (nb);
  600. return NULL;
  601. }
  602. for (j = 0; (j < TCP_SYN_RETRANSMISSION_TIMEOUT / 50
  603. && !socket->established); j++)
  604. grub_net_poll_cards (50, &socket->established);
  605. if (socket->established)
  606. break;
  607. }
  608. if (!socket->established)
  609. {
  610. grub_list_remove (GRUB_AS_LIST (socket));
  611. if (socket->they_reseted)
  612. grub_error (GRUB_ERR_NET_PORT_CLOSED,
  613. N_("connection refused"));
  614. else
  615. grub_error (GRUB_ERR_NET_NO_ANSWER,
  616. N_("connection timeout"));
  617. grub_netbuff_free (nb);
  618. destroy_pq (socket);
  619. grub_free (socket);
  620. return NULL;
  621. }
  622. grub_netbuff_free (nb);
  623. return socket;
  624. }
  625. grub_err_t
  626. grub_net_send_tcp_packet (const grub_net_tcp_socket_t socket,
  627. struct grub_net_buff *nb, int push)
  628. {
  629. struct tcphdr *tcph;
  630. grub_err_t err;
  631. grub_ssize_t fraglen;
  632. COMPILE_TIME_ASSERT (sizeof (struct tcphdr) == GRUB_NET_TCP_HEADER_SIZE);
  633. if (socket->out_nla.type == GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4)
  634. fraglen = (socket->inf->card->mtu - GRUB_NET_OUR_IPV4_HEADER_SIZE
  635. - sizeof (*tcph));
  636. else
  637. fraglen = 1280 - GRUB_NET_OUR_IPV6_HEADER_SIZE;
  638. while (nb->tail - nb->data > fraglen)
  639. {
  640. struct grub_net_buff *nb2;
  641. nb2 = grub_netbuff_alloc (fraglen + sizeof (*tcph)
  642. + GRUB_NET_OUR_MAX_IP_HEADER_SIZE
  643. + GRUB_NET_MAX_LINK_HEADER_SIZE);
  644. if (!nb2)
  645. return grub_errno;
  646. err = grub_netbuff_reserve (nb2, GRUB_NET_MAX_LINK_HEADER_SIZE
  647. + GRUB_NET_OUR_MAX_IP_HEADER_SIZE);
  648. if (err)
  649. return err;
  650. err = grub_netbuff_put (nb2, sizeof (*tcph));
  651. if (err)
  652. return err;
  653. tcph = (struct tcphdr *) nb2->data;
  654. tcph->ack = grub_cpu_to_be32 (socket->their_cur_seq);
  655. tcph->flags = grub_cpu_to_be16_compile_time ((5 << 12) | TCP_ACK);
  656. tcph->window = !socket->i_stall ? grub_cpu_to_be16 (socket->my_window)
  657. : 0;
  658. tcph->urgent = 0;
  659. err = grub_netbuff_put (nb2, fraglen);
  660. if (err)
  661. return err;
  662. grub_memcpy (tcph + 1, nb->data, fraglen);
  663. err = grub_netbuff_pull (nb, fraglen);
  664. if (err)
  665. return err;
  666. err = tcp_send (nb2, socket);
  667. if (err)
  668. return err;
  669. }
  670. err = grub_netbuff_push (nb, sizeof (*tcph));
  671. if (err)
  672. return err;
  673. tcph = (struct tcphdr *) nb->data;
  674. tcph->ack = grub_cpu_to_be32 (socket->their_cur_seq);
  675. tcph->flags = (grub_cpu_to_be16_compile_time ((5 << 12) | TCP_ACK)
  676. | (push ? grub_cpu_to_be16_compile_time (TCP_PUSH) : 0));
  677. tcph->window = !socket->i_stall ? grub_cpu_to_be16 (socket->my_window) : 0;
  678. tcph->urgent = 0;
  679. return tcp_send (nb, socket);
  680. }
  681. grub_err_t
  682. grub_net_recv_tcp_packet (struct grub_net_buff *nb,
  683. struct grub_net_network_level_interface *inf,
  684. const grub_net_network_level_address_t *source)
  685. {
  686. struct tcphdr *tcph;
  687. grub_net_tcp_socket_t sock;
  688. grub_err_t err;
  689. /* Ignore broadcast. */
  690. if (!inf)
  691. {
  692. grub_netbuff_free (nb);
  693. return GRUB_ERR_NONE;
  694. }
  695. tcph = (struct tcphdr *) nb->data;
  696. if ((grub_be_to_cpu16 (tcph->flags) >> 12) < 5)
  697. {
  698. grub_dprintf ("net", "TCP header too short: %u\n",
  699. grub_be_to_cpu16 (tcph->flags) >> 12);
  700. grub_netbuff_free (nb);
  701. return GRUB_ERR_NONE;
  702. }
  703. if (nb->tail - nb->data < (grub_ssize_t) ((grub_be_to_cpu16 (tcph->flags)
  704. >> 12) * sizeof (grub_uint32_t)))
  705. {
  706. grub_dprintf ("net", "TCP packet too short: %" PRIuGRUB_SIZE "\n",
  707. (grub_size_t) (nb->tail - nb->data));
  708. grub_netbuff_free (nb);
  709. return GRUB_ERR_NONE;
  710. }
  711. FOR_TCP_SOCKETS (sock)
  712. {
  713. if (!(grub_be_to_cpu16 (tcph->dst) == sock->in_port
  714. && grub_be_to_cpu16 (tcph->src) == sock->out_port
  715. && inf == sock->inf
  716. && grub_net_addr_cmp (source, &sock->out_nla) == 0))
  717. continue;
  718. if (tcph->checksum)
  719. {
  720. grub_uint16_t chk, expected;
  721. chk = tcph->checksum;
  722. tcph->checksum = 0;
  723. expected = grub_net_ip_transport_checksum (nb, GRUB_NET_IP_TCP,
  724. &sock->out_nla,
  725. &sock->inf->address);
  726. if (expected != chk)
  727. {
  728. grub_dprintf ("net", "Invalid TCP checksum. "
  729. "Expected %x, got %x\n",
  730. grub_be_to_cpu16 (expected),
  731. grub_be_to_cpu16 (chk));
  732. grub_netbuff_free (nb);
  733. return GRUB_ERR_NONE;
  734. }
  735. tcph->checksum = chk;
  736. }
  737. if ((grub_be_to_cpu16 (tcph->flags) & TCP_SYN)
  738. && (grub_be_to_cpu16 (tcph->flags) & TCP_ACK)
  739. && !sock->established)
  740. {
  741. sock->their_start_seq = grub_be_to_cpu32 (tcph->seqnr);
  742. sock->their_cur_seq = sock->their_start_seq + 1;
  743. sock->established = 1;
  744. }
  745. if (grub_be_to_cpu16 (tcph->flags) & TCP_RST)
  746. {
  747. sock->they_reseted = 1;
  748. error (sock);
  749. grub_netbuff_free (nb);
  750. return GRUB_ERR_NONE;
  751. }
  752. if (grub_be_to_cpu16 (tcph->flags) & TCP_ACK)
  753. {
  754. struct unacked *unack, *next;
  755. grub_uint32_t acked = grub_be_to_cpu32 (tcph->ack);
  756. for (unack = sock->unack_first; unack; unack = next)
  757. {
  758. grub_uint32_t seqnr;
  759. struct tcphdr *unack_tcph;
  760. next = unack->next;
  761. seqnr = grub_be_to_cpu32 (((struct tcphdr *) unack->nb->data)
  762. ->seqnr);
  763. unack_tcph = (struct tcphdr *) unack->nb->data;
  764. seqnr += (unack->nb->tail - unack->nb->data
  765. - (grub_be_to_cpu16 (unack_tcph->flags) >> 12) * 4);
  766. if (grub_be_to_cpu16 (unack_tcph->flags) & TCP_FIN)
  767. seqnr++;
  768. if (seqnr > acked)
  769. break;
  770. grub_netbuff_free (unack->nb);
  771. grub_free (unack);
  772. }
  773. sock->unack_first = unack;
  774. if (!sock->unack_first)
  775. sock->unack_last = NULL;
  776. }
  777. if (grub_be_to_cpu32 (tcph->seqnr) < sock->their_cur_seq)
  778. {
  779. ack (sock);
  780. grub_netbuff_free (nb);
  781. return GRUB_ERR_NONE;
  782. }
  783. if (sock->i_reseted && (nb->tail - nb->data
  784. - (grub_be_to_cpu16 (tcph->flags)
  785. >> 12) * sizeof (grub_uint32_t)) > 0)
  786. {
  787. reset (sock);
  788. }
  789. err = grub_priority_queue_push (sock->pq, &nb);
  790. if (err)
  791. {
  792. grub_netbuff_free (nb);
  793. return err;
  794. }
  795. {
  796. struct grub_net_buff **nb_top_p, *nb_top;
  797. int do_ack = 0;
  798. int just_closed = 0;
  799. while (1)
  800. {
  801. nb_top_p = grub_priority_queue_top (sock->pq);
  802. if (!nb_top_p)
  803. return GRUB_ERR_NONE;
  804. nb_top = *nb_top_p;
  805. tcph = (struct tcphdr *) nb_top->data;
  806. if (grub_be_to_cpu32 (tcph->seqnr) >= sock->their_cur_seq)
  807. break;
  808. grub_netbuff_free (nb_top);
  809. grub_priority_queue_pop (sock->pq);
  810. }
  811. if (grub_be_to_cpu32 (tcph->seqnr) != sock->their_cur_seq)
  812. {
  813. ack (sock);
  814. return GRUB_ERR_NONE;
  815. }
  816. while (1)
  817. {
  818. nb_top_p = grub_priority_queue_top (sock->pq);
  819. if (!nb_top_p)
  820. break;
  821. nb_top = *nb_top_p;
  822. tcph = (struct tcphdr *) nb_top->data;
  823. if (grub_be_to_cpu32 (tcph->seqnr) != sock->their_cur_seq)
  824. break;
  825. grub_priority_queue_pop (sock->pq);
  826. err = grub_netbuff_pull (nb_top, (grub_be_to_cpu16 (tcph->flags)
  827. >> 12) * sizeof (grub_uint32_t));
  828. if (err)
  829. {
  830. grub_netbuff_free (nb_top);
  831. return err;
  832. }
  833. sock->their_cur_seq += (nb_top->tail - nb_top->data);
  834. if (grub_be_to_cpu16 (tcph->flags) & TCP_FIN)
  835. {
  836. sock->they_closed = 1;
  837. just_closed = 1;
  838. sock->their_cur_seq++;
  839. do_ack = 1;
  840. }
  841. /* If there is data, puts packet in socket list. */
  842. if ((nb_top->tail - nb_top->data) > 0)
  843. {
  844. grub_net_put_packet (&sock->packs, nb_top);
  845. do_ack = 1;
  846. }
  847. else
  848. grub_netbuff_free (nb_top);
  849. }
  850. if (do_ack)
  851. ack (sock);
  852. while (sock->packs.first)
  853. {
  854. nb = sock->packs.first->nb;
  855. if (sock->recv_hook)
  856. sock->recv_hook (sock, sock->packs.first->nb, sock->hook_data);
  857. else
  858. grub_netbuff_free (nb);
  859. grub_net_remove_packet (sock->packs.first);
  860. }
  861. if (sock->fin_hook && just_closed)
  862. sock->fin_hook (sock, sock->hook_data);
  863. }
  864. return GRUB_ERR_NONE;
  865. }
  866. if (grub_be_to_cpu16 (tcph->flags) & TCP_SYN)
  867. {
  868. grub_net_tcp_listen_t listen;
  869. FOR_TCP_LISTENS (listen)
  870. {
  871. if (!(grub_be_to_cpu16 (tcph->dst) == listen->port
  872. && (inf == listen->inf || listen->inf == NULL)))
  873. continue;
  874. sock = grub_zalloc (sizeof (*sock));
  875. if (sock == NULL)
  876. return grub_errno;
  877. sock->out_port = grub_be_to_cpu16 (tcph->src);
  878. sock->in_port = grub_be_to_cpu16 (tcph->dst);
  879. sock->inf = inf;
  880. sock->out_nla = *source;
  881. sock->their_start_seq = grub_be_to_cpu32 (tcph->seqnr);
  882. sock->their_cur_seq = sock->their_start_seq + 1;
  883. sock->my_cur_seq = sock->my_start_seq = grub_get_time_ms ();
  884. sock->my_window = 8192;
  885. sock->pq = grub_priority_queue_new (sizeof (struct grub_net_buff *),
  886. cmp);
  887. if (!sock->pq)
  888. {
  889. grub_free (sock);
  890. grub_netbuff_free (nb);
  891. return grub_errno;
  892. }
  893. err = listen->listen_hook (listen, sock, listen->hook_data);
  894. grub_netbuff_free (nb);
  895. return err;
  896. }
  897. }
  898. grub_netbuff_free (nb);
  899. return GRUB_ERR_NONE;
  900. }
  901. void
  902. grub_net_tcp_stall (grub_net_tcp_socket_t sock)
  903. {
  904. if (sock->i_stall)
  905. return;
  906. sock->i_stall = 1;
  907. ack (sock);
  908. }
  909. void
  910. grub_net_tcp_unstall (grub_net_tcp_socket_t sock)
  911. {
  912. if (!sock->i_stall)
  913. return;
  914. sock->i_stall = 0;
  915. ack (sock);
  916. }