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/checksum.h>
35 extern unsigned long timer_ticks
;
37 static unsigned net_icmp6_ping
= 0;
39 static proto_ipv6_t proto_ipv6_prealloc
;
40 static char proto_icmp_prealloc
[sizeof (proto_icmp_t
)+65];
41 static packet_t packet_prealloc
;
42 static char buf_icmp_prealloc
[NET_PACKET_MTU
+ sizeof (proto_icmp_t
) + 1];
45 unsigned net_proto_icmp6_reply (netif_t
*netif
, packet_t
*packet
, proto_ipv6_t
*ip
, proto_icmp_t
*icmp
, char *buf
, unsigned len
);
46 unsigned net_proto_icmp6_request (netif_t
*netif
, net_ipv6 dest
);
48 unsigned net_proto_icmp6_ping (netif_t
*netif
, net_ipv6 ip
)
53 unsigned ret
= net_proto_icmp6_request (netif
, ip
);
58 unsigned long time
= timer_ticks
;
60 while (!net_icmp6_ping
) {
61 /* timeout 1s - 1000ms */
62 if ((timer_ticks
-time
) > 1000)
73 unsigned net_proto_icmp6_handler (packet_t
*packet
, proto_ipv6_t
*ip
, char *buf
, unsigned len
)
75 proto_icmp_t
*icmp
= (proto_icmp_t
*) buf
;
77 if (icmp
->type
== NET_ICMP6_TYPE_PING_REQUEST
) {
78 //kprintf ("ICMP->Request !\n");
80 /* TODO: melo by to projit vsechny rozhrani */
81 netif_t
*netif
= netif_findbyname ("eth0");
83 if (net_proto_ipv6_cmp (ip
->ip_dest
, netif
->ipv6
))
84 return net_proto_icmp6_reply (netif
, packet
, ip
, icmp
, buf
+8, len
-8);
89 if (icmp
->type
== NET_ICMP6_TYPE_PING_REPLY
) {
90 /* TODO: make it better :) */
95 /* ICMPv6 - NDP protocol handler */
96 if (icmp
->type
== NET_NDP_TYPE_NBADVERT
) {
97 netif_t
*netif
= netif_findbyname ("eth0");
99 proto_ndp_adv_t
*ndp
= (proto_ndp_adv_t
*) buf
;
101 if (net_proto_ipv6_cmp (ip
->ip_dest
, netif
->ipv6
))
102 return ndp_cache_add (ndp
->ll_mac
, ndp
->target
);
107 if (icmp
->type
== NET_NDP_TYPE_NBSOL
) {
108 netif_t
*netif
= netif_findbyname ("eth0");
110 proto_ndp_adv_t
*ndp
= (proto_ndp_adv_t
*) buf
;
113 if (net_proto_ipv6_cmp (ndp
->target
, netif
->ipv6
)) {
114 ndp_cache_add (ndp
->ll_mac
, ip
->ip_source
);
115 return ndp_send_nbreply (netif
, ndp
->ll_mac
, ip
->ip_source
);
119 if (icmp
->type
== NET_NDP_TYPE_RADVERT
) {
120 netif_t
*netif
= netif_findbyname ("eth0");
122 proto_icmp_ndp2_t
*ndp
= (proto_icmp_ndp2_t
*) buf
;
125 return ndp_send_rreply (netif
, ndp
, ip
->ip_source
, ip
->ip_dest
);
132 unsigned net_proto_icmp6_request (netif_t
*netif
, net_ipv6 dest
)
136 if (!tun6_addr_get ()) {
137 unsigned get
= ndp_cache_get (dest
, &mac_dest
);
140 ndp_send_nbrequest (netif
, dest
);
143 /* 200ms for waiting on NDP reply */
145 get
= ndp_cache_get (dest
, &mac_dest
);
150 /* TODO: make better waiting for ARP reply */
162 /* IPv6 tunnel stuff */
163 net_ipv4 tunnel
= tun6_addr_get ();
164 unsigned get
= arp_cache_get (tunnel
, &mac_dest
);
167 arp_send_request (netif
, tunnel
);
170 /* 100ms for waiting on ARP reply */
172 get
= arp_cache_get (tunnel
, &mac_dest
);
177 /* TODO: make better waiting for ARP reply */
191 packet_t
*packet
= (packet_t
*) &packet_prealloc
;
196 memcpy (&packet
->mac_source
, netif
->dev
->dev_addr
, 6);
197 memcpy (&packet
->mac_dest
, mac_dest
, 6);
198 packet
->type
= NET_PACKET_TYPE_IPV6
;
201 proto_ipv6_t
*ip
= (proto_ipv6_t
*) &proto_ipv6_prealloc
;
206 /* there are some fixed values - yeah it is horrible */
210 ip
->pl_len
= swap16 (64);
211 ip
->nhead
= NET_PROTO_IP_TYPE_ICMP6
;
213 memcpy (ip
->ip_source
, (void *) netif
->ipv6
, sizeof (net_ipv6
));
214 memcpy (ip
->ip_dest
, (void *) dest
, sizeof (net_ipv6
));
217 proto_icmp_t
*icmp
= (proto_icmp_t
*) &proto_icmp_prealloc
;
222 memset ((char *) icmp
, 0, 64);
224 icmp
->type
= NET_ICMP6_TYPE_PING_REQUEST
;
230 icmp
->checksum
= checksum16_ipv6 (ip
->ip_source
, ip
->ip_dest
, icmp
, sizeof (proto_icmp_t
)+56, NET_PROTO_IP_TYPE_ICMP6
);
232 if (!tun6_addr_get ())
233 ret
= net_proto_ipv6_send (netif
, packet
, ip
, (char *) icmp
, sizeof (proto_icmp_t
)+56);
234 else /* tunnel mode */
235 ret
= net_proto_tun6_send (netif
, packet
, ip
, (char *) icmp
, sizeof (proto_icmp_t
)+56);
240 unsigned net_proto_icmp6_reply (netif_t
*netif
, packet_t
*packet
, proto_ipv6_t
*ip
, proto_icmp_t
*icmp
, char *buf
, unsigned len
)
243 mac_addr_t mac_source
;
245 /* cross mac and ip address, because this packet have to go back */
246 memcpy (&mac_dest
, packet
->mac_source
, 6);
247 memcpy (&mac_source
, packet
->mac_dest
, 6);
249 /* assign new values to old structures */
250 memcpy (&packet
->mac_source
, mac_source
, 6);
251 memcpy (&packet
->mac_dest
, mac_dest
, 6);
253 /* TODO: identification, flags, etc */
257 memcpy (tmp
, (void *) ip
->ip_dest
, sizeof (net_ipv6
));
259 memcpy (ip
->ip_dest
, (void *) ip
->ip_source
, sizeof (net_ipv6
));
260 memcpy (ip
->ip_source
, (void *) tmp
, sizeof (net_ipv6
));
262 icmp
->type
= NET_ICMP6_TYPE_PING_REPLY
;
265 char *buf_icmp
= (char *) &buf_icmp_prealloc
;
270 unsigned l
= sizeof (proto_icmp_t
);
272 memcpy (buf_icmp
, (char *) icmp
, l
);
273 memcpy (buf_icmp
+l
, buf
, len
);
275 buf_icmp
[l
+len
] = '\0';
279 /* calculate checksum and put it to icmp header */
280 proto_icmp_t
*icmp_
= (proto_icmp_t
*) buf_icmp
;
282 icmp_
->checksum
= checksum16_ipv6 (ip
->ip_source
, ip
->ip_dest
, buf_icmp
, len
+l
, NET_PROTO_IP_TYPE_ICMP6
);
284 if (!tun6_addr_get ())
285 ret
= net_proto_ipv6_send (netif
, packet
, ip
, buf_icmp
, len
+l
);
287 ret
= net_proto_tun6_send (netif
, packet
, ip
, buf_icmp
, len
+l
);