2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2010,2011 Free Software Foundation, Inc.
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.
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.
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/>.
20 #include <grub/net/ip.h>
21 #include <grub/net/tcp.h>
22 #include <grub/net/netbuff.h>
23 #include <grub/time.h>
24 #include <grub/priority_queue.h>
26 #define TCP_SYN_RETRANSMISSION_TIMEOUT GRUB_NET_INTERVAL
27 #define TCP_SYN_RETRANSMISSION_COUNT GRUB_NET_TRIES
28 #define TCP_RETRANSMISSION_TIMEOUT GRUB_NET_INTERVAL
29 #define TCP_RETRANSMISSION_COUNT GRUB_NET_TRIES
34 struct unacked
**prev
;
35 struct grub_net_buff
*nb
;
36 grub_uint64_t last_try
;
50 struct grub_net_tcp_socket
52 struct grub_net_tcp_socket
*next
;
53 struct grub_net_tcp_socket
**prev
;
64 grub_uint32_t my_start_seq
;
65 grub_uint32_t my_cur_seq
;
66 grub_uint32_t their_start_seq
;
67 grub_uint32_t their_cur_seq
;
68 grub_uint16_t my_window
;
69 struct unacked
*unack_first
;
70 struct unacked
*unack_last
;
71 grub_err_t (*recv_hook
) (grub_net_tcp_socket_t sock
, struct grub_net_buff
*nb
,
73 void (*error_hook
) (grub_net_tcp_socket_t sock
, void *recv
);
74 void (*fin_hook
) (grub_net_tcp_socket_t sock
, void *recv
);
76 grub_net_network_level_address_t out_nla
;
77 grub_net_link_level_address_t ll_target_addr
;
78 struct grub_net_network_level_interface
*inf
;
79 grub_net_packets_t packs
;
80 grub_priority_queue_t pq
;
83 struct grub_net_tcp_listen
85 struct grub_net_tcp_listen
*next
;
86 struct grub_net_tcp_listen
**prev
;
89 const struct grub_net_network_level_interface
*inf
;
91 grub_err_t (*listen_hook
) (grub_net_tcp_listen_t listen
,
92 grub_net_tcp_socket_t sock
,
104 grub_uint16_t window
;
105 grub_uint16_t checksum
;
106 grub_uint16_t urgent
;
115 grub_uint16_t tcp_length
;
118 struct tcp6_pseudohdr
120 grub_uint64_t src
[2];
121 grub_uint64_t dst
[2];
122 grub_uint32_t tcp_length
;
123 grub_uint8_t zero
[3];
127 static struct grub_net_tcp_socket
*tcp_sockets
;
128 static struct grub_net_tcp_listen
*tcp_listens
;
130 #define FOR_TCP_SOCKETS(var) FOR_LIST_ELEMENTS (var, tcp_sockets)
131 #define FOR_TCP_LISTENS(var) FOR_LIST_ELEMENTS (var, tcp_listens)
133 grub_net_tcp_listen_t
134 grub_net_tcp_listen (grub_uint16_t port
,
135 const struct grub_net_network_level_interface
*inf
,
136 grub_err_t (*listen_hook
) (grub_net_tcp_listen_t listen
,
137 grub_net_tcp_socket_t sock
,
141 grub_net_tcp_listen_t ret
;
142 ret
= grub_malloc (sizeof (*ret
));
145 ret
->listen_hook
= listen_hook
;
146 ret
->hook_data
= hook_data
;
149 grub_list_push (GRUB_AS_LIST_P (&tcp_listens
), GRUB_AS_LIST (ret
));
154 grub_net_tcp_stop_listen (grub_net_tcp_listen_t listen
)
156 grub_list_remove (GRUB_AS_LIST (listen
));
160 tcp_socket_register (grub_net_tcp_socket_t sock
)
162 grub_list_push (GRUB_AS_LIST_P (&tcp_sockets
),
163 GRUB_AS_LIST (sock
));
167 error (grub_net_tcp_socket_t sock
)
169 struct unacked
*unack
, *next
;
171 if (sock
->error_hook
)
172 sock
->error_hook (sock
, sock
->hook_data
);
174 for (unack
= sock
->unack_first
; unack
; unack
= next
)
177 grub_netbuff_free (unack
->nb
);
181 sock
->unack_first
= NULL
;
182 sock
->unack_last
= NULL
;
186 tcp_send (struct grub_net_buff
*nb
, grub_net_tcp_socket_t socket
)
190 struct unacked
*unack
;
194 tcph
= (struct tcphdr
*) nb
->data
;
196 tcph
->seqnr
= grub_cpu_to_be32 (socket
->my_cur_seq
);
197 size
= (nb
->tail
- nb
->data
- (grub_be_to_cpu16 (tcph
->flags
) >> 12) * 4);
198 if (grub_be_to_cpu16 (tcph
->flags
) & TCP_FIN
)
200 socket
->my_cur_seq
+= size
;
201 tcph
->src
= grub_cpu_to_be16 (socket
->in_port
);
202 tcph
->dst
= grub_cpu_to_be16 (socket
->out_port
);
204 tcph
->checksum
= grub_net_ip_transport_checksum (nb
, GRUB_NET_IP_TCP
,
205 &socket
->inf
->address
,
210 unack
= grub_malloc (sizeof (*unack
));
216 unack
->try_count
= 1;
217 unack
->last_try
= grub_get_time_ms ();
218 if (!socket
->unack_last
)
219 socket
->unack_first
= socket
->unack_last
= unack
;
221 socket
->unack_last
->next
= unack
;
224 err
= grub_net_send_ip_packet (socket
->inf
, &(socket
->out_nla
),
225 &(socket
->ll_target_addr
), nb
,
231 grub_netbuff_free (nb
);
232 return GRUB_ERR_NONE
;
236 grub_net_tcp_close (grub_net_tcp_socket_t sock
,
237 int discard_received
)
239 struct grub_net_buff
*nb_fin
;
240 struct tcphdr
*tcph_fin
;
243 if (discard_received
!= GRUB_NET_TCP_CONTINUE_RECEIVING
)
245 sock
->recv_hook
= NULL
;
246 sock
->error_hook
= NULL
;
247 sock
->fin_hook
= NULL
;
250 if (discard_received
== GRUB_NET_TCP_ABORT
)
258 nb_fin
= grub_netbuff_alloc (sizeof (*tcph_fin
)
259 + GRUB_NET_OUR_MAX_IP_HEADER_SIZE
260 + GRUB_NET_MAX_LINK_HEADER_SIZE
);
263 err
= grub_netbuff_reserve (nb_fin
, GRUB_NET_OUR_MAX_IP_HEADER_SIZE
264 + GRUB_NET_MAX_LINK_HEADER_SIZE
);
267 grub_netbuff_free (nb_fin
);
268 grub_dprintf ("net", "error closing socket\n");
269 grub_errno
= GRUB_ERR_NONE
;
273 err
= grub_netbuff_put (nb_fin
, sizeof (*tcph_fin
));
276 grub_netbuff_free (nb_fin
);
277 grub_dprintf ("net", "error closing socket\n");
278 grub_errno
= GRUB_ERR_NONE
;
281 tcph_fin
= (void *) nb_fin
->data
;
282 tcph_fin
->ack
= grub_cpu_to_be32 (sock
->their_cur_seq
);
283 tcph_fin
->flags
= grub_cpu_to_be16_compile_time ((5 << 12) | TCP_FIN
285 tcph_fin
->window
= grub_cpu_to_be16_compile_time (0);
286 tcph_fin
->urgent
= 0;
287 err
= tcp_send (nb_fin
, sock
);
290 grub_netbuff_free (nb_fin
);
291 grub_dprintf ("net", "error closing socket\n");
292 grub_errno
= GRUB_ERR_NONE
;
298 ack_real (grub_net_tcp_socket_t sock
, int res
)
300 struct grub_net_buff
*nb_ack
;
301 struct tcphdr
*tcph_ack
;
304 nb_ack
= grub_netbuff_alloc (sizeof (*tcph_ack
) + 128);
307 err
= grub_netbuff_reserve (nb_ack
, 128);
310 grub_netbuff_free (nb_ack
);
311 grub_dprintf ("net", "error closing socket\n");
312 grub_errno
= GRUB_ERR_NONE
;
316 err
= grub_netbuff_put (nb_ack
, sizeof (*tcph_ack
));
319 grub_netbuff_free (nb_ack
);
320 grub_dprintf ("net", "error closing socket\n");
321 grub_errno
= GRUB_ERR_NONE
;
324 tcph_ack
= (void *) nb_ack
->data
;
327 tcph_ack
->ack
= grub_cpu_to_be32_compile_time (0);
328 tcph_ack
->flags
= grub_cpu_to_be16_compile_time ((5 << 12) | TCP_RST
);
329 tcph_ack
->window
= grub_cpu_to_be16_compile_time (0);
333 tcph_ack
->ack
= grub_cpu_to_be32 (sock
->their_cur_seq
);
334 tcph_ack
->flags
= grub_cpu_to_be16_compile_time ((5 << 12) | TCP_ACK
);
335 tcph_ack
->window
= !sock
->i_stall
? grub_cpu_to_be16 (sock
->my_window
)
338 tcph_ack
->urgent
= 0;
339 tcph_ack
->src
= grub_cpu_to_be16 (sock
->in_port
);
340 tcph_ack
->dst
= grub_cpu_to_be16 (sock
->out_port
);
341 err
= tcp_send (nb_ack
, sock
);
344 grub_dprintf ("net", "error acking socket\n");
345 grub_errno
= GRUB_ERR_NONE
;
350 ack (grub_net_tcp_socket_t sock
)
356 reset (grub_net_tcp_socket_t sock
)
362 grub_net_tcp_retransmit (void)
364 grub_net_tcp_socket_t sock
;
365 grub_uint64_t ctime
= grub_get_time_ms ();
366 grub_uint64_t limit_time
= ctime
- TCP_RETRANSMISSION_TIMEOUT
;
368 FOR_TCP_SOCKETS (sock
)
370 struct unacked
*unack
;
371 for (unack
= sock
->unack_first
; unack
; unack
= unack
->next
)
377 if (unack
->last_try
> limit_time
)
380 if (unack
->try_count
> TCP_RETRANSMISSION_COUNT
)
386 unack
->last_try
= ctime
;
387 nbd
= unack
->nb
->data
;
388 tcph
= (struct tcphdr
*) nbd
;
390 if ((tcph
->flags
& grub_cpu_to_be16_compile_time (TCP_ACK
))
391 && tcph
->ack
!= grub_cpu_to_be32 (sock
->their_cur_seq
))
394 tcph
->checksum
= grub_net_ip_transport_checksum (unack
->nb
,
400 err
= grub_net_send_ip_packet (sock
->inf
, &(sock
->out_nla
),
401 &(sock
->ll_target_addr
), unack
->nb
,
403 unack
->nb
->data
= nbd
;
406 grub_dprintf ("net", "TCP retransmit failed: %s\n", grub_errmsg
);
407 grub_errno
= GRUB_ERR_NONE
;
414 grub_net_ip_transport_checksum (struct grub_net_buff
*nb
,
416 const grub_net_network_level_address_t
*src
,
417 const grub_net_network_level_address_t
*dst
)
419 grub_uint16_t a
, b
= 0;
421 a
= ~grub_be_to_cpu16 (grub_net_ip_chksum ((void *) nb
->data
,
422 nb
->tail
- nb
->data
));
426 case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4
:
428 struct tcp_pseudohdr ph
;
432 ph
.tcp_length
= grub_cpu_to_be16 (nb
->tail
- nb
->data
);
434 b
= ~grub_be_to_cpu16 (grub_net_ip_chksum ((void *) &ph
, sizeof (ph
)));
437 case GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6
:
439 struct tcp6_pseudohdr ph
;
440 grub_memcpy (ph
.src
, src
->ipv6
, sizeof (ph
.src
));
441 grub_memcpy (ph
.dst
, dst
->ipv6
, sizeof (ph
.dst
));
442 grub_memset (ph
.zero
, 0, sizeof (ph
.zero
));
443 ph
.tcp_length
= grub_cpu_to_be32 (nb
->tail
- nb
->data
);
445 b
= ~grub_be_to_cpu16 (grub_net_ip_chksum ((void *) &ph
, sizeof (ph
)));
448 case GRUB_NET_NETWORK_LEVEL_PROTOCOL_DHCP_RECV
:
452 c
= (grub_uint32_t
) a
+ (grub_uint32_t
) b
;
455 return grub_cpu_to_be16 (~c
);
458 /* FIXME: overflow. */
460 cmp (const void *a__
, const void *b__
)
462 struct grub_net_buff
*a_
= *(struct grub_net_buff
**) a__
;
463 struct grub_net_buff
*b_
= *(struct grub_net_buff
**) b__
;
464 struct tcphdr
*a
= (struct tcphdr
*) a_
->data
;
465 struct tcphdr
*b
= (struct tcphdr
*) b_
->data
;
466 /* We want the first elements to be on top. */
467 if (grub_be_to_cpu32 (a
->seqnr
) < grub_be_to_cpu32 (b
->seqnr
))
469 if (grub_be_to_cpu32 (a
->seqnr
) > grub_be_to_cpu32 (b
->seqnr
))
475 destroy_pq (grub_net_tcp_socket_t sock
)
477 struct grub_net_buff
**nb_p
;
478 while ((nb_p
= grub_priority_queue_top (sock
->pq
)))
480 grub_netbuff_free (*nb_p
);
481 grub_priority_queue_pop (sock
->pq
);
484 grub_priority_queue_destroy (sock
->pq
);
488 grub_net_tcp_accept (grub_net_tcp_socket_t sock
,
489 grub_err_t (*recv_hook
) (grub_net_tcp_socket_t sock
,
490 struct grub_net_buff
*nb
,
492 void (*error_hook
) (grub_net_tcp_socket_t sock
,
494 void (*fin_hook
) (grub_net_tcp_socket_t sock
,
498 struct grub_net_buff
*nb_ack
;
502 sock
->recv_hook
= recv_hook
;
503 sock
->error_hook
= error_hook
;
504 sock
->fin_hook
= fin_hook
;
505 sock
->hook_data
= hook_data
;
506 nb_ack
= grub_netbuff_alloc (sizeof (*tcph
)
507 + GRUB_NET_OUR_MAX_IP_HEADER_SIZE
508 + GRUB_NET_MAX_LINK_HEADER_SIZE
);
511 err
= grub_netbuff_reserve (nb_ack
, GRUB_NET_OUR_MAX_IP_HEADER_SIZE
512 + GRUB_NET_MAX_LINK_HEADER_SIZE
);
515 grub_netbuff_free (nb_ack
);
519 err
= grub_netbuff_put (nb_ack
, sizeof (*tcph
));
522 grub_netbuff_free (nb_ack
);
525 tcph
= (void *) nb_ack
->data
;
526 tcph
->ack
= grub_cpu_to_be32 (sock
->their_cur_seq
);
527 tcph
->flags
= grub_cpu_to_be16_compile_time ((5 << 12) | TCP_SYN
| TCP_ACK
);
528 tcph
->window
= grub_cpu_to_be16 (sock
->my_window
);
530 sock
->established
= 1;
531 tcp_socket_register (sock
);
532 err
= tcp_send (nb_ack
, sock
);
536 return GRUB_ERR_NONE
;
539 grub_net_tcp_socket_t
540 grub_net_tcp_open (char *server
,
541 grub_uint16_t out_port
,
542 grub_err_t (*recv_hook
) (grub_net_tcp_socket_t sock
,
543 struct grub_net_buff
*nb
,
545 void (*error_hook
) (grub_net_tcp_socket_t sock
,
547 void (*fin_hook
) (grub_net_tcp_socket_t sock
,
552 grub_net_network_level_address_t addr
;
553 struct grub_net_network_level_interface
*inf
;
554 grub_net_network_level_address_t gateway
;
555 grub_net_tcp_socket_t socket
;
556 static grub_uint16_t in_port
= 21550;
557 struct grub_net_buff
*nb
;
561 grub_net_link_level_address_t ll_target_addr
;
563 err
= grub_net_resolve_address (server
, &addr
);
567 if (addr
.type
!= GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4
568 && addr
.type
!= GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV6
)
570 grub_error (GRUB_ERR_BUG
, "not an IP address");
574 err
= grub_net_route_address (addr
, &gateway
, &inf
);
578 err
= grub_net_link_layer_resolve (inf
, &gateway
, &ll_target_addr
);
582 socket
= grub_zalloc (sizeof (*socket
));
586 socket
->out_port
= out_port
;
588 socket
->out_nla
= addr
;
589 socket
->ll_target_addr
= ll_target_addr
;
590 socket
->in_port
= in_port
++;
591 socket
->recv_hook
= recv_hook
;
592 socket
->error_hook
= error_hook
;
593 socket
->fin_hook
= fin_hook
;
594 socket
->hook_data
= hook_data
;
596 nb
= grub_netbuff_alloc (sizeof (*tcph
) + 128);
599 err
= grub_netbuff_reserve (nb
, 128);
602 grub_netbuff_free (nb
);
606 err
= grub_netbuff_put (nb
, sizeof (*tcph
));
609 grub_netbuff_free (nb
);
612 socket
->pq
= grub_priority_queue_new (sizeof (struct grub_net_buff
*), cmp
);
615 grub_netbuff_free (nb
);
619 tcph
= (void *) nb
->data
;
620 socket
->my_start_seq
= grub_get_time_ms ();
621 socket
->my_cur_seq
= socket
->my_start_seq
+ 1;
622 socket
->my_window
= 8192;
623 tcph
->seqnr
= grub_cpu_to_be32 (socket
->my_start_seq
);
624 tcph
->ack
= grub_cpu_to_be32_compile_time (0);
625 tcph
->flags
= grub_cpu_to_be16_compile_time ((5 << 12) | TCP_SYN
);
626 tcph
->window
= grub_cpu_to_be16 (socket
->my_window
);
628 tcph
->src
= grub_cpu_to_be16 (socket
->in_port
);
629 tcph
->dst
= grub_cpu_to_be16 (socket
->out_port
);
631 tcph
->checksum
= grub_net_ip_transport_checksum (nb
, GRUB_NET_IP_TCP
,
632 &socket
->inf
->address
,
635 tcp_socket_register (socket
);
638 for (i
= 0; i
< TCP_SYN_RETRANSMISSION_COUNT
; i
++)
642 err
= grub_net_send_ip_packet (socket
->inf
, &(socket
->out_nla
),
643 &(socket
->ll_target_addr
), nb
,
647 grub_list_remove (GRUB_AS_LIST (socket
));
649 grub_netbuff_free (nb
);
652 for (j
= 0; (j
< TCP_SYN_RETRANSMISSION_TIMEOUT
/ 50
653 && !socket
->established
); j
++)
654 grub_net_poll_cards (50, &socket
->established
);
655 if (socket
->established
)
658 if (!socket
->established
)
660 grub_list_remove (GRUB_AS_LIST (socket
));
661 if (socket
->they_reseted
)
662 grub_error (GRUB_ERR_NET_PORT_CLOSED
,
663 N_("connection refused"));
665 grub_error (GRUB_ERR_NET_NO_ANSWER
,
666 N_("connection timeout"));
668 grub_netbuff_free (nb
);
674 grub_netbuff_free (nb
);
679 grub_net_send_tcp_packet (const grub_net_tcp_socket_t socket
,
680 struct grub_net_buff
*nb
, int push
)
684 grub_ssize_t fraglen
;
685 COMPILE_TIME_ASSERT (sizeof (struct tcphdr
) == GRUB_NET_TCP_HEADER_SIZE
);
686 if (socket
->out_nla
.type
== GRUB_NET_NETWORK_LEVEL_PROTOCOL_IPV4
)
687 fraglen
= (socket
->inf
->card
->mtu
- GRUB_NET_OUR_IPV4_HEADER_SIZE
690 fraglen
= 1280 - GRUB_NET_OUR_IPV6_HEADER_SIZE
;
692 while (nb
->tail
- nb
->data
> fraglen
)
694 struct grub_net_buff
*nb2
;
696 nb2
= grub_netbuff_alloc (fraglen
+ sizeof (*tcph
)
697 + GRUB_NET_OUR_MAX_IP_HEADER_SIZE
698 + GRUB_NET_MAX_LINK_HEADER_SIZE
);
701 err
= grub_netbuff_reserve (nb2
, GRUB_NET_MAX_LINK_HEADER_SIZE
702 + GRUB_NET_OUR_MAX_IP_HEADER_SIZE
);
705 err
= grub_netbuff_put (nb2
, sizeof (*tcph
));
709 tcph
= (struct tcphdr
*) nb2
->data
;
710 tcph
->ack
= grub_cpu_to_be32 (socket
->their_cur_seq
);
711 tcph
->flags
= grub_cpu_to_be16_compile_time ((5 << 12) | TCP_ACK
);
712 tcph
->window
= !socket
->i_stall
? grub_cpu_to_be16 (socket
->my_window
)
715 err
= grub_netbuff_put (nb2
, fraglen
);
718 grub_memcpy (tcph
+ 1, nb
->data
, fraglen
);
719 err
= grub_netbuff_pull (nb
, fraglen
);
723 err
= tcp_send (nb2
, socket
);
728 err
= grub_netbuff_push (nb
, sizeof (*tcph
));
732 tcph
= (struct tcphdr
*) nb
->data
;
733 tcph
->ack
= grub_cpu_to_be32 (socket
->their_cur_seq
);
734 tcph
->flags
= (grub_cpu_to_be16_compile_time ((5 << 12) | TCP_ACK
)
735 | (push
? grub_cpu_to_be16_compile_time (TCP_PUSH
) : 0));
736 tcph
->window
= !socket
->i_stall
? grub_cpu_to_be16 (socket
->my_window
) : 0;
738 return tcp_send (nb
, socket
);
742 grub_net_recv_tcp_packet (struct grub_net_buff
*nb
,
743 struct grub_net_network_level_interface
*inf
,
744 const grub_net_network_level_address_t
*source
)
747 grub_net_tcp_socket_t sock
;
750 /* Ignore broadcast. */
753 grub_netbuff_free (nb
);
754 return GRUB_ERR_NONE
;
757 tcph
= (struct tcphdr
*) nb
->data
;
758 if ((grub_be_to_cpu16 (tcph
->flags
) >> 12) < 5)
760 grub_dprintf ("net", "TCP header too short: %u\n",
761 grub_be_to_cpu16 (tcph
->flags
) >> 12);
762 grub_netbuff_free (nb
);
763 return GRUB_ERR_NONE
;
765 if (nb
->tail
- nb
->data
< (grub_ssize_t
) ((grub_be_to_cpu16 (tcph
->flags
)
766 >> 12) * sizeof (grub_uint32_t
)))
768 grub_dprintf ("net", "TCP packet too short: %" PRIuGRUB_SIZE
"\n",
769 (grub_size_t
) (nb
->tail
- nb
->data
));
770 grub_netbuff_free (nb
);
771 return GRUB_ERR_NONE
;
774 FOR_TCP_SOCKETS (sock
)
776 if (!(grub_be_to_cpu16 (tcph
->dst
) == sock
->in_port
777 && grub_be_to_cpu16 (tcph
->src
) == sock
->out_port
779 && grub_net_addr_cmp (source
, &sock
->out_nla
) == 0))
783 grub_uint16_t chk
, expected
;
784 chk
= tcph
->checksum
;
786 expected
= grub_net_ip_transport_checksum (nb
, GRUB_NET_IP_TCP
,
788 &sock
->inf
->address
);
791 grub_dprintf ("net", "Invalid TCP checksum. "
792 "Expected %x, got %x\n",
793 grub_be_to_cpu16 (expected
),
794 grub_be_to_cpu16 (chk
));
795 grub_netbuff_free (nb
);
796 return GRUB_ERR_NONE
;
798 tcph
->checksum
= chk
;
801 if ((grub_be_to_cpu16 (tcph
->flags
) & TCP_SYN
)
802 && (grub_be_to_cpu16 (tcph
->flags
) & TCP_ACK
)
803 && !sock
->established
)
805 sock
->their_start_seq
= grub_be_to_cpu32 (tcph
->seqnr
);
806 sock
->their_cur_seq
= sock
->their_start_seq
+ 1;
807 sock
->established
= 1;
810 if (grub_be_to_cpu16 (tcph
->flags
) & TCP_RST
)
812 sock
->they_reseted
= 1;
816 grub_netbuff_free (nb
);
818 return GRUB_ERR_NONE
;
821 if (grub_be_to_cpu16 (tcph
->flags
) & TCP_ACK
)
823 struct unacked
*unack
, *next
;
824 grub_uint32_t acked
= grub_be_to_cpu32 (tcph
->ack
);
825 for (unack
= sock
->unack_first
; unack
; unack
= next
)
828 struct tcphdr
*unack_tcph
;
830 seqnr
= grub_be_to_cpu32 (((struct tcphdr
*) unack
->nb
->data
)
832 unack_tcph
= (struct tcphdr
*) unack
->nb
->data
;
833 seqnr
+= (unack
->nb
->tail
- unack
->nb
->data
834 - (grub_be_to_cpu16 (unack_tcph
->flags
) >> 12) * 4);
835 if (grub_be_to_cpu16 (unack_tcph
->flags
) & TCP_FIN
)
840 grub_netbuff_free (unack
->nb
);
843 sock
->unack_first
= unack
;
844 if (!sock
->unack_first
)
845 sock
->unack_last
= NULL
;
848 if (grub_be_to_cpu32 (tcph
->seqnr
) < sock
->their_cur_seq
)
851 grub_netbuff_free (nb
);
852 return GRUB_ERR_NONE
;
854 if (sock
->i_reseted
&& (nb
->tail
- nb
->data
855 - (grub_be_to_cpu16 (tcph
->flags
)
856 >> 12) * sizeof (grub_uint32_t
)) > 0)
861 err
= grub_priority_queue_push (sock
->pq
, &nb
);
864 grub_netbuff_free (nb
);
869 struct grub_net_buff
**nb_top_p
, *nb_top
;
874 nb_top_p
= grub_priority_queue_top (sock
->pq
);
876 return GRUB_ERR_NONE
;
878 tcph
= (struct tcphdr
*) nb_top
->data
;
879 if (grub_be_to_cpu32 (tcph
->seqnr
) >= sock
->their_cur_seq
)
881 grub_netbuff_free (nb_top
);
882 grub_priority_queue_pop (sock
->pq
);
884 if (grub_be_to_cpu32 (tcph
->seqnr
) != sock
->their_cur_seq
)
885 return GRUB_ERR_NONE
;
888 nb_top_p
= grub_priority_queue_top (sock
->pq
);
892 tcph
= (struct tcphdr
*) nb_top
->data
;
894 if (grub_be_to_cpu32 (tcph
->seqnr
) != sock
->their_cur_seq
)
896 grub_priority_queue_pop (sock
->pq
);
898 err
= grub_netbuff_pull (nb_top
, (grub_be_to_cpu16 (tcph
->flags
)
899 >> 12) * sizeof (grub_uint32_t
));
902 grub_netbuff_free (nb_top
);
906 sock
->their_cur_seq
+= (nb_top
->tail
- nb_top
->data
);
907 if (grub_be_to_cpu16 (tcph
->flags
) & TCP_FIN
)
909 sock
->they_closed
= 1;
911 sock
->their_cur_seq
++;
914 /* If there is data, puts packet in socket list. */
915 if ((nb_top
->tail
- nb_top
->data
) > 0)
917 grub_net_put_packet (&sock
->packs
, nb_top
);
921 grub_netbuff_free (nb_top
);
925 while (sock
->packs
.first
)
927 nb
= sock
->packs
.first
->nb
;
929 sock
->recv_hook (sock
, sock
->packs
.first
->nb
, sock
->hook_data
);
931 grub_netbuff_free (nb
);
932 grub_net_remove_packet (sock
->packs
.first
);
935 if (sock
->fin_hook
&& just_closed
)
936 sock
->fin_hook (sock
, sock
->hook_data
);
939 return GRUB_ERR_NONE
;
941 if (grub_be_to_cpu16 (tcph
->flags
) & TCP_SYN
)
943 grub_net_tcp_listen_t listen
;
945 FOR_TCP_LISTENS (listen
)
947 if (!(grub_be_to_cpu16 (tcph
->dst
) == listen
->port
948 && (inf
== listen
->inf
|| listen
->inf
== NULL
)))
950 sock
= grub_zalloc (sizeof (*sock
));
954 sock
->out_port
= grub_be_to_cpu16 (tcph
->src
);
955 sock
->in_port
= grub_be_to_cpu16 (tcph
->dst
);
957 sock
->out_nla
= *source
;
958 sock
->their_start_seq
= grub_be_to_cpu32 (tcph
->seqnr
);
959 sock
->their_cur_seq
= sock
->their_start_seq
+ 1;
960 sock
->my_cur_seq
= sock
->my_start_seq
= grub_get_time_ms ();
961 sock
->my_window
= 8192;
963 sock
->pq
= grub_priority_queue_new (sizeof (struct grub_net_buff
*),
967 grub_netbuff_free (nb
);
971 err
= listen
->listen_hook (listen
, sock
, listen
->hook_data
);
973 grub_netbuff_free (nb
);
978 grub_netbuff_free (nb
);
979 return GRUB_ERR_NONE
;
983 grub_net_tcp_stall (grub_net_tcp_socket_t sock
)
992 grub_net_tcp_unstall (grub_net_tcp_socket_t sock
)