3 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
4 * Copyright (C) 2009 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
5 * Copyright (C) 2010 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
28 #include <net/packet.h>
33 #include <net/socket.h>
38 /* Mutex for socket function */
39 MUTEX_CREATE (mutex_tcp6_accept
);
40 MUTEX_CREATE (mutex_tcp6_read_cache
);
42 proto_tcp6_conn_t proto_tcp6_conn_list
;
43 proto_tcp6_backlog_t proto_tcp6_backlog_list
;
45 extern netif_t netif_list
;
47 static unsigned short proto_tcp6_dup
;
48 static unsigned proto_tcp6_seq
;
49 static proto_ipv6_t proto_ipv6_prealloc
;
50 static proto_tcp_t proto_tcp_prealloc
;
51 static packet_t packet_prealloc
;
52 static char buf_tcp_prealloc
[NET_PACKET_MTU
+ sizeof (proto_tcp_t
) + 1];
55 proto_tcp6_conn_t
*net_proto_tcp6_conn_check (net_ipv6 ip_source
, net_port port_source
, net_ipv6 ip_dest
, net_port port_dest
, unsigned char *ret
);
56 int net_proto_tcp6_conn_add ();
57 int net_proto_tcp6_conn_set (proto_tcp6_conn_t
*conn
, netif_t
*eth
, net_port port_source
, net_ipv6 ip_dest
, net_port port_dest
);
58 int net_proto_tcp6_conn_estabilish (proto_tcp6_conn_t
*conn
, netif_t
*eth
, net_ipv6 ip_dest
, net_port port_dest
);
59 int net_proto_tcp6_conn_estabilish_reply (proto_tcp6_conn_t
*conn
, proto_ipv6_t
*ip_old
, proto_tcp_t
*tcp_old
);
60 int net_proto_tcp6_read_cache (proto_tcp6_conn_t
*conn
, char *data
, unsigned len
);
61 int net_proto_tcp6_read_ok (proto_tcp6_conn_t
*conn
, proto_ipv6_t
*ip_old
, proto_tcp_t
*tcp_old
, unsigned len
);
62 int net_proto_tcp6_write (netif_t
*eth
, net_ipv6 dest
, proto_tcp_t
*tcp
, char *data
, unsigned len
);
63 int net_proto_tcp6_write_data (proto_tcp6_conn_t
*conn
, char *data
, unsigned len
);
64 int net_proto_tcp6_write_data_ok (proto_tcp6_conn_t
*conn
, proto_ipv6_t
*ip_old
, proto_tcp_t
*tcp_old
);
65 int net_proto_tcp6_conn_disconnected (proto_tcp6_conn_t
*conn
, proto_ipv6_t
*ip_old
, proto_tcp_t
*tcp_old
);
66 int net_proto_tcp6_conn_close (proto_tcp6_conn_t
*conn
);
67 unsigned net_proto_tcp6_conn_del (proto_tcp6_conn_t
*conn
);
68 proto_tcp6_conn_t
*net_proto_tcp6_conn_find (int fd
);
69 int net_proto_tcp6_backlog_add (proto_tcp6_conn_t
*conn
, net_ipv6 ip
, net_port port
, unsigned seq
);
70 int net_proto_tcp6_conn_invite (proto_tcp6_conn_t
*conn
, net_ipv6 ip
, net_port port
, unsigned seq
);
73 * User-friendly socket functions
75 int net_proto_tcp6_socket (fd_t
*fd
)
77 return net_proto_tcp6_conn_add (fd
);
80 extern unsigned long timer_ticks
;
81 int net_proto_tcp6_connect (int fd
, sockaddr_in6
*addr
)
85 proto_tcp6_conn_t
*conn
= net_proto_tcp6_conn_find (fd
);
91 for (netif
= netif_list
.next
; netif
!= &netif_list
; netif
= netif
->next
) {
92 ret
= net_proto_tcp6_conn_estabilish (conn
, netif
, addr
->sin6_addr
, addr
->sin6_port
);
94 unsigned long stime
= timer_ticks
;
97 if (!(conn
->flags
& O_NONBLOCK
)) {
105 if ((stime
+3000) < timer_ticks
)
108 if (conn
->state
== PROTO_TCP_CONN_STATE_ESTABILISHED
)
111 /* when connection cant be accepted succefully first time, try it again */
112 if (conn
->state
== PROTO_TCP_CONN_STATE_ESTABILISHERROR
) {
113 ret
= net_proto_tcp6_conn_estabilish (conn
, netif
, addr
->sin6_addr
, addr
->sin6_port
);
114 conn
->state
= PROTO_TCP_CONN_STATE_ESTABILISH
;
118 /* non-blocking mode */
127 int net_proto_tcp6_send (int fd
, char *msg
, unsigned size
)
129 proto_tcp6_conn_t
*conn
= net_proto_tcp6_conn_find (fd
);
136 unsigned mtu_tcp
= NET_PACKET_MTU
- sizeof (proto_tcp_t
) - sizeof (net_ipv6
) - 16;
139 if (size
> mtu_tcp
) {
140 int r
= net_proto_tcp_send (fd
, msg
, mtu_tcp
);
151 int ret
= net_proto_tcp6_write_data (conn
, msg
, size
);
154 unsigned long stime
= timer_ticks
;
157 if (!(conn
->flags
& O_NONBLOCK
)) {
158 while (conn
->state
!= PROTO_TCP_CONN_STATE_READY
) {
161 /* timeout for 350ms */
162 if ((stime
+350) < timer_ticks
)
166 /* non-blocking mode */
169 while (conn
->state
!= PROTO_TCP_CONN_STATE_READY
) {
172 /* timeout for 100ms */
173 if ((stime
+100) < timer_ticks
)
183 int net_proto_tcp6_recv (int fd
, char *msg
, unsigned size
)
185 proto_tcp6_conn_t
*conn
= net_proto_tcp6_conn_find (fd
);
192 //kprintf ("recv () - %d\n", fd);
195 if (!(conn
->flags
& O_NONBLOCK
)) {
196 unsigned long stime
= timer_ticks
;
198 while (!conn
->len
/* || conn->state != PROTO_TCP_CONN_STATE_READY*/) {
199 if ((stime
+10000) < timer_ticks
)
202 if (conn
->state
== PROTO_TCP_CONN_STATE_CLOSE
) {
203 if (net_proto_tcp6_conn_del (conn
));
210 if (conn
->state
== PROTO_TCP_CONN_STATE_CLOSE
) {
211 if (net_proto_tcp6_conn_del (conn
));
219 if ((conn
->len
-conn
->offset
) > size
) {
220 memcpy (msg
, conn
->data
+conn
->offset
, size
);
221 //printf ("msg: %d %d\n", conn->offset, size);
222 conn
->offset
+= size
;
226 ret
= conn
->len
-conn
->offset
;
228 memcpy (msg
, conn
->data
+conn
->offset
, conn
->len
-conn
->offset
);
229 //printf ("msg2: %d %d\n", conn->offset, size);
236 //kprintf ("recv () - %d -- DATA: %d\n", fd, ret);
241 int net_proto_tcp6_close (int fd
)
243 proto_tcp6_conn_t
*conn
= net_proto_tcp6_conn_find (fd
);
248 if (conn
->state
== PROTO_TCP_CONN_STATE_DISCONNECTED
)
251 int ret
= net_proto_tcp6_conn_close (conn
);
256 int net_proto_tcp6_fcntl (int fd
, int cmd
, long arg
)
258 proto_tcp6_conn_t
*conn
= net_proto_tcp6_conn_find (fd
);
274 int net_proto_tcp6_bind (int fd
, sockaddr_in6
*addr
, socklen_t len
)
276 proto_tcp6_conn_t
*conn
= net_proto_tcp6_conn_find (fd
);
282 for (netif
= netif_list
.next
; netif
!= &netif_list
; netif
= netif
->next
) {
283 net_proto_tcp6_conn_set (conn
, netif
, addr
->sin6_port
, 0, 0);
291 int net_proto_tcp6_listen (int fd
, int backlog
)
293 proto_tcp6_conn_t
*conn
= net_proto_tcp6_conn_find (fd
);
301 int net_proto_tcp6_accept (int fd
, sockaddr_in6
*addr
, socklen_t
*addrlen
)
303 proto_tcp6_conn_t
*conn
= net_proto_tcp6_conn_find (fd
);
310 proto_tcp6_backlog_t
*backlog
= 0;
313 if (!(conn
->flags
& O_NONBLOCK
)) {
315 for (backlog
= proto_tcp6_backlog_list
.next
; backlog
!= &proto_tcp6_backlog_list
; backlog
= backlog
->next
) {
316 if (backlog
->conn
== conn
) {
325 /* non-blocking mode */
326 for (backlog
= proto_tcp6_backlog_list
.next
; backlog
!= &proto_tcp6_backlog_list
; backlog
= backlog
->next
) {
327 if (backlog
->conn
== conn
) {
334 //printf ("accept ()\n");
340 memcpy (ip
, backlog
->ip
, sizeof (net_ipv6
));
342 net_port port
= backlog
->port
;
343 unsigned seq
= backlog
->seq
;
345 int ret
= net_proto_tcp6_conn_invite (conn
, ip
, port
, seq
);
347 /* remove from queue accepted connection */
348 backlog
->next
->prev
= backlog
->prev
;
349 backlog
->prev
->next
= backlog
->next
;
356 fd_t
*fd_new
= fd_create (FD_SOCK
);
361 net_proto_tcp6_conn_add (fd_new
);
363 proto_tcp6_conn_t
*conn_new
= net_proto_tcp6_conn_find (fd_new
->id
);
368 net_proto_tcp6_conn_set (conn_new
, conn
->netif
, conn
->port_source
, conn
->netif
->ipv6
, port
);
370 memcpy (conn_new
->ip_dest
, ip
, sizeof (net_ipv6
));
372 memcpy (addr
->sin6_addr
, ip
, sizeof (net_ipv6
));
373 addr
->sin6_port
= port
;
374 addr
->sin6_family
= AF_INET6
;
379 int net_proto_tcp6_select (int readfd
, int writefd
, int exceptfd
)
390 proto_tcp6_conn_t
*conn
= net_proto_tcp6_conn_find (fd
);
395 /* check for incoming connections */
397 proto_tcp6_backlog_t
*backlog
= 0;
399 for (backlog
= proto_tcp6_backlog_list
.next
; backlog
!= &proto_tcp6_backlog_list
; backlog
= backlog
->next
) {
400 if (backlog
->conn
== conn
)
407 /* Is socket closed ? */
408 if (conn
->state
== PROTO_TCP_CONN_STATE_CLOSE
)
411 /* Are some data available ? */
419 * Hardcore code - syn, ack, psh, fin, etc :P
421 unsigned net_proto_tcp6_handler (packet_t
*packet
, proto_ipv6_t
*ip
, char *buf
, unsigned len
, unsigned flags
)
423 proto_tcp_t
*tcp
= (proto_tcp_t
*) buf
;
425 unsigned char ret
= 0;
427 /* First check ip address and ports, that we want this data */
428 proto_tcp6_conn_t
*conn
= net_proto_tcp6_conn_check (ip
->ip_dest
, tcp
->port_dest
, ip
->ip_source
, tcp
->port_source
, &ret
);
430 //printf ("hmm: %d - %d - %d\n", len, swap16 (tcp->port_dest), ret);
432 if (!conn
&& ret
== 0)
435 //printf ("tcp6->flags: 0x%x, ret: %d, conn: 0x%x, fd: %d\n", tcp->flags, ret, conn, conn->fd);
437 /* connection from client before accept () */
439 /* client want connect to our server */
440 if (tcp
->flags
== 0x02) {
441 mutex_lock (&mutex_tcp6_accept
);
443 unsigned ret
= net_proto_tcp6_backlog_add (conn
, ip
->ip_source
, tcp
->port_source
, tcp
->seq
);
445 mutex_unlock (&mutex_tcp6_accept
);
453 unsigned data_cache
= 0;
456 if (tcp
->flags
& 0x08) {
457 /* needed for calculate real offset from 4bit number */
458 unsigned offset
= tcp
->data_offset
* 4;
459 unsigned size
= len
- offset
;
461 //kprintf (">>>> %d : %d : %d\n", offset, size, len);
462 //mutex_lock (&mutex_tcp6_read_cache);
463 net_proto_tcp6_read_cache (conn
, buf
+offset
, size
);
464 //mutex_unlock (&mutex_tcp6_read_cache);
466 net_proto_tcp6_read_ok (conn
, ip
, tcp
, size
);
471 /* sended data was delivered succefully */
472 if (tcp
->flags
& 0x10) {
473 /* HACK: It is interesting, that no push flag, and there could be some data to read */
475 /* needed for calculate real offset from 4bit number */
476 unsigned offset
= tcp
->data_offset
* 4;
477 unsigned size
= len
- offset
;
479 /* there are data for read */
481 /* data was cached, so no need cache it again */
483 //kprintf (">>>>2 %d : %d : %d\n", offset, size, len);
484 mutex_lock (&mutex_tcp6_read_cache
);
485 net_proto_tcp6_read_cache (conn
, buf
+offset
, size
);
486 mutex_unlock (&mutex_tcp6_read_cache
);
488 net_proto_tcp6_read_ok (conn
, ip
, tcp
, size
);
491 /* when data are'nt available, lets normal work - acknowledgement */
492 if (conn
->state
== PROTO_TCP_CONN_STATE_ESTABILISH
) {
493 conn
->state
= PROTO_TCP_CONN_STATE_ESTABILISHERROR
;
494 net_proto_tcp6_write_data_ok (conn
, ip
, tcp
);
496 net_proto_tcp6_write_data_ok (conn
, ip
, tcp
);
500 /* connection estabilish respond */
501 if (tcp
->flags
== 0x12) {
502 return net_proto_tcp6_conn_estabilish_reply (conn
, ip
, tcp
);
505 /* another side close connection */
506 if (tcp
->flags
& 0x01) {
507 DPRINT (DBG_NET
| DBG_SOCKET
| DBG_TCP
, "TCP -> fd %d connection closed by remote host\n", conn
->fd
);
508 net_proto_tcp6_conn_disconnected (conn
, ip
, tcp
); // FIXME: problem in server with hangind the whole program
511 /* another side close connection */
512 if (tcp
->flags
& 0x04) {
513 DPRINT (DBG_NET
| DBG_SOCKET
| DBG_TCP
, "TCP -> fd %d connection reseted by peer\n", conn
->fd
);
514 net_proto_tcp6_conn_disconnected (conn
, ip
, tcp
);
520 int net_proto_tcp6_read_cache (proto_tcp6_conn_t
*conn
, char *data
, unsigned len
)
522 if (!data
|| !conn
|| !len
)
526 conn
->data
= (char *) kmalloc (sizeof (char) * (len
+ 1));
528 memcpy (conn
->data
, data
, len
);
530 char *newdata
= (char *) kmalloc (sizeof (char) * (conn
->len
+ len
+ 1));
535 memcpy (newdata
, conn
->data
, conn
->len
);
536 memcpy (newdata
+conn
->len
, data
, len
);
540 conn
->data
= newdata
;
546 //kprintf ("DATA: %d - #'%s'#\n", len, data);
550 conn
->data
[conn
->len
] = '\0';
555 int net_proto_tcp6_read_ok (proto_tcp6_conn_t
*conn
, proto_ipv6_t
*ip_old
, proto_tcp_t
*tcp_old
, unsigned len
)
557 if (!ip_old
|| !tcp_old
|| !conn
)
560 proto_tcp_t
*tcp
= (proto_tcp_t
*) kmalloc (sizeof (proto_tcp_t
));
565 tcp
->port_source
= conn
->port_source
; // increase client port too
566 tcp
->port_dest
= conn
->port_dest
;
568 tcp
->seq
= tcp_old
->ack
;
570 /* this small thing did bad work when e.g. 10 10 10 fe get to calculation,
571 it returns 10 10 10 08, no 10 10 11 08 */
572 unsigned seq
= swap32 (tcp_old
->seq
);
575 tcp
->ack
= swap32 (seq
);
578 tcp
->data_offset
= 5;
580 tcp
->window
= tcp_old
->window
+ swap16 (64);
583 int ret
= net_proto_tcp6_write (conn
->netif
, conn
->ip_dest
, tcp
, 0, 0);
585 /*if (proto_tcp6_dup == tcp_old->checksum) {
586 printf ("Duplicated packet :)");
591 //printf ("read_ok: seq: 0x%x | ack: 0x%x\n", conn->seq, conn->ack);
593 conn
->seq
= tcp
->ack
;
594 conn
->ack
= tcp
->seq
;
596 //printf ("read_ok2: seq: 0x%x | ack: 0x%x\n", conn->seq, conn->ack);
598 proto_tcp6_dup
= tcp_old
->checksum
;
608 int net_proto_tcp6_write (netif_t
*eth
, net_ipv6 dest
, proto_tcp_t
*tcp
, char *data
, unsigned len
)
611 printf ("!eth || !tcp\n");
621 if (!tun6_addr_get ()) {
622 unsigned get
= ndp_cache_get (dest
, &mac_dest
);
625 ndp_send_nbrequest (eth
, dest
);
628 /* 200ms for waiting on NDP reply */
630 get
= ndp_cache_get (dest
, &mac_dest
);
635 /* TODO: make better waiting for NDP reply */
649 /* IPv6 tunnel stuff */
650 net_ipv4 tunnel
= tun6_addr_get ();
651 unsigned get
= arp_cache_get (tunnel
, &mac_dest
);
654 arp_send_request (eth
, tunnel
);
657 /* 100ms for waiting on ARP reply */
659 get
= arp_cache_get (tunnel
, &mac_dest
);
664 /* TODO: make better waiting for ARP reply */
680 packet_t
*packet
= &packet_prealloc
;
683 printf ("!packet\n");
687 memcpy (&packet
->mac_source
, eth
->dev
->dev_addr
, 6);
688 memcpy (&packet
->mac_dest
, mac_dest
, 6);
689 packet
->type
= NET_PACKET_TYPE_IPV6
;
691 unsigned l
= (tcp
->data_offset
*4);
694 proto_ipv6_t
*ip
= &proto_ipv6_prealloc
;
701 /* there are some fixed values - yeah it is horrible */
705 ip
->pl_len
= swap16 (l
+len
);
706 ip
->nhead
= NET_PROTO_IP_TYPE_TCP6
;
708 memcpy (ip
->ip_source
, (void *) eth
->ipv6
, sizeof (net_ipv6
));
709 memcpy (ip
->ip_dest
, (void *) dest
, sizeof (net_ipv6
));
711 if (len
+l
> NET_PACKET_MTU
+ sizeof (proto_tcp_t
)) {
712 DPRINT (DBG_NET
| DBG_SOCKET
| DBG_TCP
, "TCP -> data lenght is exceed: %d/%d bytes", len
+l
, NET_PACKET_MTU
+ sizeof (proto_tcp_t
) + 1);
716 char *buf_tcp
= (char *) &buf_tcp_prealloc
;
719 printf ("!buf_tcp\n");
723 memcpy (buf_tcp
, (char *) tcp
, l
);
726 memcpy (buf_tcp
+l
, data
, len
);
728 buf_tcp
[l
+len
] = '\0';
730 /* calculate checksum and put it to tcp header */
731 proto_tcp_t
*tcp_
= (proto_tcp_t
*) buf_tcp
;
735 tcp_
->checksum
= checksum16_ipv6 (eth
->ipv6
, dest
, buf_tcp
, l
+len
, NET_PROTO_IP_TYPE_TCP6
);
737 /* send tcp header+data to ip layer */
738 if (!tun6_addr_get ())
739 ret
= net_proto_ipv6_send (eth
, packet
, ip
, (char *) buf_tcp
, l
+len
);
741 ret
= net_proto_tun6_send (eth
, packet
, ip
, (char *) buf_tcp
, l
+len
);
746 int net_proto_tcp6_write_data (proto_tcp6_conn_t
*conn
, char *data
, unsigned len
)
748 if (!conn
|| !len
|| !data
)
751 proto_tcp_t
*tcp
= &proto_tcp_prealloc
;
756 tcp
->port_source
= conn
->port_source
;
757 tcp
->port_dest
= conn
->port_dest
;
759 unsigned seq
= swap32 (proto_tcp6_seq
);
762 //tcp->ack = swap32 (seq);
764 proto_tcp6_seq
= swap32 (seq
);
767 tcp
->seq
= conn
->seq
;
768 tcp
->ack
= conn
->ack
;
770 tcp
->seq
= conn
->ack
;
771 tcp
->ack
= conn
->seq
;
776 //printf ("TCP -> seq: 0x%x | ack: 0x%x | proto_seq: 0x%x\n", tcp->seq, conn->ack, proto_tcp6_seq);
779 tcp
->data_offset
= 5;
781 tcp
->window
= swap16 (32768);
784 int ret
= net_proto_tcp6_write (conn
->netif
, conn
->ip_dest
, tcp
, data
, len
);
787 conn
->state
= PROTO_TCP_CONN_STATE_WAIT
;
792 int net_proto_tcp6_write_data_ok (proto_tcp6_conn_t
*conn
, proto_ipv6_t
*ip_old
, proto_tcp_t
*tcp_old
)
794 if (!ip_old
|| !tcp_old
|| !conn
)
797 /* cross - because we change now sides :) */
798 conn
->seq
= tcp_old
->ack
;
799 conn
->ack
= tcp_old
->seq
;
801 //printf ("data_ok: seq: 0x%x | ack: 0x%x\n", tcp_old->ack, tcp_old->seq);
803 conn
->state
= PROTO_TCP_CONN_STATE_READY
;
808 /* try connect to server */
809 int net_proto_tcp6_conn_estabilish (proto_tcp6_conn_t
*conn
, netif_t
*eth
, net_ipv6 ip_dest
, net_port port_dest
)
814 proto_tcp_t
*tcp
= (proto_tcp_t
*) kmalloc (sizeof (proto_tcp_t
));
819 tcp
->port_source
= swap16 (netif_port_get ()); // increase client port too
820 tcp
->port_dest
= port_dest
;
822 /* setup new connection */
823 net_proto_tcp6_conn_set (conn
, eth
, tcp
->port_source
, ip_dest
, tcp
->port_dest
);
825 tcp
->seq
= conn
->seq
;
826 tcp
->ack
= conn
->ack
;
829 tcp
->data_offset
= 5;
831 tcp
->window
= swap16 (32792);
834 int ret
= net_proto_tcp6_write (eth
, ip_dest
, tcp
, 0, 0);
839 net_proto_tcp6_conn_del (conn
);
846 int net_proto_tcp6_conn_estabilish_reply (proto_tcp6_conn_t
*conn
, proto_ipv6_t
*ip_old
, proto_tcp_t
*tcp_old
)
848 if (!ip_old
|| !tcp_old
|| !conn
)
851 proto_tcp_t
*tcp
= (proto_tcp_t
*) kmalloc (sizeof (proto_tcp_t
));
856 tcp
->port_source
= conn
->port_source
; // increase client port too
857 tcp
->port_dest
= conn
->port_dest
;
859 tcp
->seq
= tcp_old
->ack
;
860 tcp
->ack
= tcp_old
->seq
+ swap32 (1);
863 tcp
->data_offset
= 5;
865 tcp
->window
= tcp_old
->window
+ swap16 (64);
868 int ret
= net_proto_tcp6_write (conn
->netif
, conn
->ip_dest
, tcp
, 0, 0);
871 conn
->seq
= tcp
->seq
;
872 conn
->ack
= tcp
->ack
;
873 conn
->state
= PROTO_TCP_CONN_STATE_ESTABILISHED
;
876 DPRINT (DBG_NET
| DBG_SOCKET
| DBG_TCP
, "TCP -> fd %d connected to server succefully\n", conn
->fd
);
883 int net_proto_tcp6_conn_disconnected (proto_tcp6_conn_t
*conn
, proto_ipv6_t
*ip_old
, proto_tcp_t
*tcp_old
)
885 if (!ip_old
|| !tcp_old
|| !conn
)
888 if (conn
->state
== PROTO_TCP_CONN_STATE_CLOSE
)
889 return net_proto_tcp6_conn_del (conn
);
891 proto_tcp_t
*tcp
= (proto_tcp_t
*) kmalloc (sizeof (proto_tcp_t
));
896 tcp
->port_source
= conn
->port_source
; // increase client port too
897 tcp
->port_dest
= conn
->port_dest
;
899 tcp
->seq
= tcp_old
->ack
;
900 tcp
->ack
= tcp_old
->seq
+ swap32 (1);
903 tcp
->data_offset
= 5;
905 tcp
->window
= tcp_old
->window
+ swap16 (64);
908 int ret
= net_proto_tcp6_write (conn
->netif
, conn
->ip_dest
, tcp
, 0, 0);
913 conn
->state
= PROTO_TCP_CONN_STATE_CLOSE
; //ret = net_proto_tcp6_conn_del (conn);
920 int net_proto_tcp6_conn_close (proto_tcp6_conn_t
*conn
)
922 return 0; /* FIXME: close () is faster then send () sometime :-B */
927 if (conn
->state
== PROTO_TCP_CONN_STATE_CLOSE
)
930 proto_tcp_t
*tcp
= (proto_tcp_t
*) kmalloc (sizeof (proto_tcp_t
));
935 tcp
->port_source
= conn
->port_source
; // increase client port too
936 tcp
->port_dest
= conn
->port_dest
;
938 tcp
->seq
= conn
->seq
;
939 tcp
->ack
= conn
->ack
;
942 tcp
->data_offset
= 5;
944 tcp
->window
= swap16 (32832);
947 int ret
= net_proto_tcp6_write (conn
->netif
, conn
->ip_dest
, tcp
, 0, 0);
952 conn
->state
= PROTO_TCP_CONN_STATE_CLOSE
;
958 /* client wants to connect */
959 net_proto_tcp6_conn_invite (proto_tcp6_conn_t
*conn
, net_ipv6 ip
, net_port port
, unsigned seq
)
964 proto_tcp_t
*tcp
= (proto_tcp_t
*) kmalloc (sizeof (proto_tcp_t
));
969 tcp
->port_source
= conn
->port_source
;
970 tcp
->port_dest
= port
;
972 tcp
->seq
= proto_tcp6_seq
++;
973 tcp
->ack
= seq
+ swap32 (1);
976 tcp
->data_offset
= 5;
978 tcp
->window
= swap16 (5816);
981 int ret
= net_proto_tcp6_write (conn
->netif
, ip
, tcp
, 0, 0);
986 conn
->state
= PROTO_TCP_CONN_STATE_READY
;
995 /* Create new TCP connection */
996 int net_proto_tcp6_conn_add (fd_t
*fd
)
998 proto_tcp6_conn_t
*conn
;
1000 /* alloc and init context */
1001 conn
= (proto_tcp6_conn_t
*) kmalloc (sizeof (proto_tcp6_conn_t
));
1008 memset (conn
, 0, sizeof (proto_tcp6_conn_t
));
1018 conn
->next
= &proto_tcp6_conn_list
;
1019 conn
->prev
= proto_tcp6_conn_list
.prev
;
1020 conn
->prev
->next
= conn
;
1021 conn
->next
->prev
= conn
;
1026 /* Setup new connection */
1027 int net_proto_tcp6_conn_set (proto_tcp6_conn_t
*conn
, netif_t
*eth
, net_port port_source
, net_ipv6 ip_dest
, net_port port_dest
)
1032 memcpy (conn
->ip_source
, eth
->ipv6
, sizeof (net_ipv6
));
1033 memcpy (conn
->ip_dest
, ip_dest
, sizeof (net_ipv6
));
1035 conn
->port_source
= port_source
;
1036 conn
->port_dest
= port_dest
;
1038 proto_tcp6_seq
+= swap32 (1);
1040 conn
->seq
= proto_tcp6_seq
++;
1043 conn
->state
= PROTO_TCP_CONN_STATE_ESTABILISH
;
1054 /* Delete existing connection from list */
1055 unsigned net_proto_tcp6_conn_del (proto_tcp6_conn_t
*conn
)
1060 conn
->state
= PROTO_TCP_CONN_STATE_DISCONNECTED
;
1067 conn
->next
->prev
= conn
->prev
;
1068 conn
->prev
->next
= conn
->next
;
1075 proto_tcp6_conn_t
*net_proto_tcp6_conn_check (net_ipv6 ip_source
, net_port port_source
, net_ipv6 ip_dest
, net_port port_dest
, unsigned char *ret
)
1078 proto_tcp6_conn_t
*conn
= NULL
;
1079 proto_tcp6_conn_t
*conn_ret
= NULL
;
1080 //printf ("-------------------------\n");
1081 for (conn
= proto_tcp6_conn_list
.next
; conn
!= &proto_tcp6_conn_list
; conn
= conn
->next
) {
1083 net_proto_ipv6_print (conn->ip_source);
1085 net_proto_ipv6_print (ip_source);
1087 net_proto_ipv6_print (conn->ip_dest);
1089 net_proto_ipv6_print (ip_dest);
1090 printf ("\nporty: %d / %d\n", swap16 (conn->port_source), swap16 (port_source));
1091 printf ("porty2: %d / %d\n", swap16 (conn->port_dest), swap16 (port_dest));*/
1093 if (net_proto_ipv6_cmp (conn
->ip_source
, ip_source
) && conn
->port_source
== port_source
) {
1094 if (net_proto_ipv6_cmp (conn
->ip_dest
, ip_dest
) && conn
->port_dest
== port_dest
) {
1106 if (!conn_ret
->bind
) {
1109 for (conn
= proto_tcp6_conn_list
.next
; conn
!= &proto_tcp6_conn_list
; conn
= conn
->next
) {
1111 if (net_proto_ipv6_cmp (conn
->ip_source
, ip_source
) && conn
->port_source
== port_source
)
1120 proto_tcp6_conn_t
*net_proto_tcp6_conn_find (int fd
)
1122 proto_tcp6_conn_t
*conn
= NULL
;
1123 for (conn
= proto_tcp6_conn_list
.next
; conn
!= &proto_tcp6_conn_list
; conn
= conn
->next
) {
1131 /* Create new TCP backlog stamp */
1132 int net_proto_tcp6_backlog_add (proto_tcp6_conn_t
*conn
, net_ipv6 ip
, net_port port
, unsigned seq
)
1137 proto_tcp6_backlog_t
*backlog
;
1139 /* alloc and init context */
1140 backlog
= (proto_tcp6_backlog_t
*) kmalloc (sizeof (proto_tcp6_backlog_t
));
1145 backlog
->conn
= conn
;
1146 memcpy (backlog
->ip
, ip
, sizeof (net_ipv6
));
1147 backlog
->port
= port
;
1151 backlog
->next
= &proto_tcp6_backlog_list
;
1152 backlog
->prev
= proto_tcp6_backlog_list
.prev
;
1153 backlog
->prev
->next
= backlog
;
1154 backlog
->next
->prev
= backlog
;
1159 /* init of tcp protocol */
1160 unsigned init_net_proto_tcp6 ()
1162 proto_tcp6_conn_list
.next
= &proto_tcp6_conn_list
;
1163 proto_tcp6_conn_list
.prev
= &proto_tcp6_conn_list
;
1165 proto_tcp6_backlog_list
.next
= &proto_tcp6_backlog_list
;
1166 proto_tcp6_backlog_list
.prev
= &proto_tcp6_backlog_list
;
1168 proto_tcp6_dup
= 0x0;
1169 proto_tcp6_seq
= 0x1;