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/>.
29 #include <net/packet.h>
31 #include <net/socket.h>
36 extern netif_t netif_list
;
37 proto_udp6_conn_t proto_udp6_conn_list
;
40 proto_udp6_conn_t
*net_proto_udp6_conn_check (net_ipv6 ip_source
, net_port port_source
, net_ipv6 ip_dest
, net_port port_dest
, unsigned char *ret
);
41 int net_proto_udp6_read_cache (proto_udp6_conn_t
*conn
, char *data
, unsigned len
);
42 int net_proto_udp6_write (proto_udp6_conn_t
*conn
, char *data
, unsigned len
);
43 proto_udp6_conn_t
*net_proto_udp6_conn_find (int fd
);
44 int net_proto_udp6_conn_set (proto_udp6_conn_t
*conn
, netif_t
*eth
, net_port port_source
, net_ipv6 ip_dest
, net_port port_dest
);
45 unsigned net_proto_udp6_conn_del (proto_udp6_conn_t
*conn
);
46 int net_proto_udp6_conn_add ();
49 * User-friendly socket functions
51 int net_proto_udp6_socket (fd_t
*fd
)
53 return net_proto_udp6_conn_add (fd
);
56 int net_proto_udp6_connect (int fd
, sockaddr_in6
*addr
)
60 proto_udp6_conn_t
*conn
= net_proto_udp6_conn_find (fd
);
66 for (netif
= netif_list
.next
; netif
!= &netif_list
; netif
= netif
->next
) {
67 ret
= net_proto_udp6_conn_set (conn
, netif
, swap16 (netif_port_get ()), addr
->sin6_addr
, addr
->sin6_port
);
69 /* TODO: connect timeout */
72 if (!(conn
->flags
& O_NONBLOCK
)) {
76 /* non-blocking mode */
85 int net_proto_udp6_send (int fd
, char *msg
, unsigned size
)
87 proto_udp6_conn_t
*conn
= net_proto_udp6_conn_find (fd
);
92 int ret
= net_proto_udp6_write (conn
, msg
, size
);
96 if (!(conn
->flags
& O_NONBLOCK
)) {
99 /* non-blocking mode */
108 int net_proto_udp6_sendto (int fd
, char *msg
, unsigned size
, sockaddr_in6
*to
)
110 proto_udp6_conn_t
*conn
= net_proto_udp6_conn_find (fd
);
115 //int ip = conn->ip_dest;
117 /*net_proto_ip_print (conn->ip_dest);
119 net_proto_ip_print (conn->ip_source);*/
121 //conn->ip_source = to->sin6_addr;
123 int ret
= net_proto_udp6_write (conn
, msg
, size
);
125 //conn->ip_dest = ip;
129 if (!(conn
->flags
& O_NONBLOCK
)) {
132 /* non-blocking mode */
141 extern unsigned long timer_ticks
;
142 int net_proto_udp6_recv (int fd
, char *msg
, unsigned size
)
144 proto_udp6_conn_t
*conn
= net_proto_udp6_conn_find (fd
);
155 if (!(conn
->flags
& O_NONBLOCK
)) {
156 unsigned long stime
= timer_ticks
;
159 if ((stime
+10000) < timer_ticks
)
172 if (conn
->len
>= size
)
178 memcpy (msg
, conn
->data
, conn
->len
);
187 int net_proto_udp6_recvfrom (int fd
, char *msg
, unsigned size
, sockaddr_in6
*from
)
189 proto_udp6_conn_t
*conn
= net_proto_udp6_conn_find (fd
);
199 //int ip = conn->ip_dest;
201 memcpy (from
->sin6_addr
, (void *) conn
->ip_dest
, sizeof (net_ipv6
));
202 //kprintf ("recvfrom -> ip: 0x%x\n", from->sin6_addr);
205 if (!(conn
->flags
& O_NONBLOCK
)) {
211 //conn->ip_dest = ip;
216 //conn->ip_dest = ip; // return old ip address back to structure
221 if (conn
->len
>= size
)
227 memcpy (msg
, conn
->data
, conn
->len
);
236 int net_proto_udp6_close (int fd
)
238 proto_udp6_conn_t
*conn
= net_proto_udp6_conn_find (fd
);
243 int ret
= net_proto_udp6_conn_del (conn
);
248 int net_proto_udp6_fcntl (int fd
, int cmd
, long arg
)
250 proto_udp6_conn_t
*conn
= net_proto_udp6_conn_find (fd
);
266 int net_proto_udp6_bind (int fd
, sockaddr_in6
*addr
, socklen_t len
)
268 proto_udp6_conn_t
*conn
= net_proto_udp6_conn_find (fd
);
274 for (netif
= netif_list
.next
; netif
!= &netif_list
; netif
= netif
->next
) {
275 net_proto_udp6_conn_set (conn
, netif
, addr
->sin6_port
, 0, 0);
283 int net_proto_udp6_select (int readfd
, int writefd
, int exceptfd
)
294 proto_udp6_conn_t
*conn
= net_proto_udp6_conn_find (fd
);
299 /* Are some data available ? */
311 /* handler for received udp datagrams */
312 unsigned net_proto_udp6_handler (packet_t
*packet
, proto_ipv6_t
*ip
, char *buf
, unsigned len
)
315 proto_udp_t
*udp
= (proto_udp_t
*) buf
;
317 /* First check ip address and ports, that we want this data */
318 proto_udp6_conn_t
*conn
= net_proto_udp6_conn_check (ip
->ip_dest
, udp
->port_dest
, ip
->ip_source
, udp
->port_source
, &ret
);
320 if (!conn
&& ret
== 0)
324 memcpy (conn
->ip_dest
, (void *) ip
->ip_source
, sizeof (net_ipv6
));
326 /* HACK: very ugly */
327 conn
->port_dest
= udp
->port_source
;
329 /* save data to buffer; +8 because udp packet is 8byte header and then data */
330 int ret2
= net_proto_udp6_read_cache (conn
, buf
+8, len
-8);
338 /* save received data to buffer */
339 int net_proto_udp6_read_cache (proto_udp6_conn_t
*conn
, char *data
, unsigned len
)
341 if (!data
|| !conn
|| !len
)
345 conn
->data
= (char *) kmalloc (sizeof (char) * (len
+ 1));
347 conn
->data
= (char *) krealloc (conn
->data
, (sizeof (char) * (conn
->len
+len
)));
352 memcpy (conn
->data
+conn
->len
, data
, len
);
356 //conn->data[conn->len] = '\0';
361 int net_proto_udp6_write (proto_udp6_conn_t
*conn
, char *data
, unsigned len
)
363 if (!conn
|| !len
|| !data
)
367 if (!tun6_addr_get ()) {
368 unsigned get
= ndp_cache_get (conn
->ip_dest
, &mac_dest
);
371 ndp_send_nbrequest (conn
->netif
, conn
->ip_dest
);
374 /* 100ms for waiting on ARP reply */
376 get
= ndp_cache_get (conn
->ip_dest
, &mac_dest
);
381 /* TODO: make better waiting for ARP reply */
393 /* IPv6 tunnel stuff */
394 net_ipv4 tunnel
= tun6_addr_get ();
395 unsigned get
= arp_cache_get (tunnel
, &mac_dest
);
398 arp_send_request (conn
->netif
, tunnel
);
401 /* 100ms for waiting on ARP reply */
403 get
= arp_cache_get (tunnel
, &mac_dest
);
408 /* TODO: make better waiting for ARP reply */
422 packet_t
*packet
= (packet_t
*) kmalloc (sizeof (packet_t
));
427 memcpy (&packet
->mac_source
, conn
->netif
->dev
->dev_addr
, 6);
428 memcpy (&packet
->mac_dest
, mac_dest
, 6);
429 packet
->type
= NET_PACKET_TYPE_IPV6
;
432 proto_ipv6_t
*ip
= (proto_ipv6_t
*) kmalloc (sizeof (proto_ipv6_t
));
437 /* there are some fixed values - yeah it is horrible */
441 ip
->pl_len
= swap16 (len
);
442 ip
->nhead
= NET_PROTO_IP_TYPE_UDP6
;
444 memcpy (ip
->ip_source
, (void *) conn
->ip_source
, sizeof (net_ipv6
));
445 memcpy (ip
->ip_dest
, (void *) conn
->ip_dest
, sizeof (net_ipv6
));
448 proto_udp_t
*udp
= (proto_udp_t
*) kmalloc (sizeof (proto_udp_t
));
453 udp
->port_source
= conn
->port_source
;
454 udp
->port_dest
= conn
->port_dest
;
456 udp
->len
= ip
->pl_len
;
461 /* calculate total length of packet (udp/ip) */
464 char *buf_udp
= (char *) kmalloc ((9 + len
) * sizeof (char));
469 memcpy (buf_udp
, (char *) udp
, 8);
470 memcpy (buf_udp
+8, data
, len
);
472 buf_udp
[8 + len
] = '\0';
474 /* calculate checksum and put it to udp header */
475 proto_udp_t
*udp_
= (proto_udp_t
*) buf_udp
;
476 udp_
->checksum
= checksum16_ipv6 (conn
->ip_source
, conn
->ip_dest
, buf_udp
, 8 + len
, NET_PROTO_IP_TYPE_UDP6
);
480 /* send udp header+data to ip layer */
481 if (!tun6_addr_get ())
482 ret
= net_proto_ipv6_send (conn
->netif
, packet
, ip
, (char *) buf_udp
, 8 + len
);
484 ret
= net_proto_tun6_send (conn
->netif
, packet
, ip
, (char *) buf_udp
, 8 + len
);
495 /* Create new UDP connection */
496 int net_proto_udp6_conn_add (fd_t
*fd
)
498 proto_udp6_conn_t
*conn
;
500 /* alloc and init context */
501 conn
= (proto_udp6_conn_t
*) kmalloc (sizeof (proto_udp6_conn_t
));
508 memset (conn
, 0, sizeof (proto_udp6_conn_t
));
515 conn
->next
= &proto_udp6_conn_list
;
516 conn
->prev
= proto_udp6_conn_list
.prev
;
517 conn
->prev
->next
= conn
;
518 conn
->next
->prev
= conn
;
523 /* Setup new connection */
524 int net_proto_udp6_conn_set (proto_udp6_conn_t
*conn
, netif_t
*eth
, net_port port_source
, net_ipv6 ip_dest
, net_port port_dest
)
529 memcpy (conn
->ip_source
, (void *) eth
->ipv6
, sizeof (net_ipv6
));
530 memcpy (conn
->ip_dest
, (void *) ip_dest
, sizeof (net_ipv6
));
532 conn
->port_source
= port_source
;
533 conn
->port_dest
= port_dest
;
545 /* Delete existing connection from list */
546 unsigned net_proto_udp6_conn_del (proto_udp6_conn_t
*conn
)
556 conn
->next
->prev
= conn
->prev
;
557 conn
->prev
->next
= conn
->next
;
564 proto_udp6_conn_t
*net_proto_udp6_conn_check (net_ipv6 ip_source
, net_port port_source
, net_ipv6 ip_dest
, net_port port_dest
, unsigned char *ret
)
567 proto_udp6_conn_t
*conn
= NULL
;
568 proto_udp6_conn_t
*conn_ret
= NULL
;
570 for (conn
= proto_udp6_conn_list
.next
; conn
!= &proto_udp6_conn_list
; conn
= conn
->next
) {
571 if (conn
->ip_source
== ip_source
&& conn
->port_source
== port_source
) {
572 if (conn
->ip_dest
== ip_dest
/*&& conn->port_dest == port_dest*/) {
584 if (!conn_ret
->bind
) {
587 for (conn
= proto_udp6_conn_list
.next
; conn
!= &proto_udp6_conn_list
; conn
= conn
->next
) {
589 if (conn
->ip_source
== ip_source
&& conn
->port_source
== port_source
)
598 proto_udp6_conn_t
*net_proto_udp6_conn_find (int fd
)
600 proto_udp6_conn_t
*conn
= NULL
;
601 for (conn
= proto_udp6_conn_list
.next
; conn
!= &proto_udp6_conn_list
; conn
= conn
->next
) {
609 /* init of udpv6 protocol */
610 unsigned init_net_proto_udp6 ()
612 proto_udp6_conn_list
.next
= &proto_udp6_conn_list
;
613 proto_udp6_conn_list
.prev
= &proto_udp6_conn_list
;