3 * Copyright (C) 2008 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
4 * Copyright (C) 2010 Tomas 'ZeXx86' Jedrzejek (zexx86@zexos.org)
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #include <net/packet.h>
30 #include <net/checksum.h>
32 extern unsigned long timer_ticks
;
34 static unsigned net_icmp_ping
= 0;
36 static proto_ip_t proto_ip_prealloc
;
37 static char proto_icmp_prealloc
[sizeof (proto_icmp_t
)+57];
38 static packet_t packet_prealloc
;
39 static char buf_icmp_prealloc
[NET_PACKET_MTU
+ sizeof (proto_icmp_t
) + 1];
42 unsigned net_proto_icmp_reply (netif_t
*netif
, packet_t
*packet
, proto_ip_t
*ip
, proto_icmp_t
*icmp
, char *buf
, unsigned len
);
43 unsigned net_proto_icmp_request (netif_t
*netif
, net_ipv4 dest
);
45 unsigned net_proto_icmp_ping (netif_t
*netif
, net_ipv4 ip
)
50 unsigned ret
= net_proto_icmp_request (netif
, ip
);
55 unsigned long time
= timer_ticks
;
57 while (!net_icmp_ping
) {
58 /* timeout 1s - 1000ms */
59 if ((timer_ticks
-time
) > 1000)
70 unsigned net_proto_icmp_handler (packet_t
*packet
, proto_ip_t
*ip
, char *buf
, unsigned len
)
72 proto_icmp_t
*icmp
= (proto_icmp_t
*) buf
;
74 if (icmp
->type
== NET_ICMP_TYPE_PING_REQUEST
) {
75 //kprintf ("ICMP->Request !\n");
77 /* TODO: melo by to projit vsechny rozhrani */
78 netif_t
*netif
= netif_findbyname ("eth0");
80 if (ip
->ip_dest
== netif
->ip
) {
81 //printf ("ICMP->Request from ");
82 //net_proto_ip_print (ip->ip_source);
85 return net_proto_icmp_reply (netif
, packet
, ip
, icmp
, buf
+8, len
-12);
91 if (icmp
->type
== NET_ICMP_TYPE_PING_REPLY
) {
92 /* TODO: make it better :) */
100 unsigned net_proto_icmp_request (netif_t
*netif
, net_ipv4 dest
)
102 //printf ("ICMP request: (%d) %s\n", len, buf);
105 unsigned get
= arp_cache_get (dest
, &mac_dest
);
108 arp_send_request (netif
, dest
);
111 /* 100ms for waiting on ARP reply */
113 get
= arp_cache_get (dest
, &mac_dest
);
118 /* TODO: make better waiting for ARP reply */
131 packet_t
*packet
= (packet_t
*) &packet_prealloc
;
136 memcpy (&packet
->mac_source
, netif
->dev
->dev_addr
, 6);
137 memcpy (&packet
->mac_dest
, mac_dest
, 6);
138 packet
->type
= NET_PACKET_TYPE_IPV4
;
141 proto_ip_t
*ip
= (proto_ip_t
*) &proto_ip_prealloc
;
146 /* there are some fixed values - yeah it is horrible */
149 ip
->total_len
= swap16 (84);
154 ip
->proto
= NET_PROTO_IP_TYPE_ICMP
;
155 ip
->ip_source
= netif
->ip
;
159 proto_icmp_t
*icmp
= (proto_icmp_t
*) &proto_icmp_prealloc
;
164 memset ((char *) icmp
+8, 0, 56);
166 icmp
->type
= NET_ICMP_TYPE_PING_REQUEST
;
171 icmp
->checksum
= checksum16 (icmp
, sizeof (proto_icmp_t
)+56);
173 return net_proto_ip_send (netif
, packet
, ip
, (char *) icmp
, sizeof (proto_icmp_t
)+56);
176 unsigned net_proto_icmp_reply (netif_t
*netif
, packet_t
*packet
, proto_ip_t
*ip
, proto_icmp_t
*icmp
, char *buf
, unsigned len
)
178 //printf ("ICMP reply: (%d) %s\n", len, buf);
181 mac_addr_t mac_source
;
183 /* cross mac and ip address, because this packet have to go back */
184 memcpy (&mac_dest
, packet
->mac_source
, 6);
185 memcpy (&mac_source
, packet
->mac_dest
, 6);
187 net_ipv4 ip_dest
= ip
->ip_source
;
188 net_ipv4 ip_source
= ip
->ip_dest
;
190 /* assign new values to old structures */
191 memcpy (&packet
->mac_source
, mac_source
, 6);
192 memcpy (&packet
->mac_dest
, mac_dest
, 6);
194 /* TODO: identification, flags, etc */
196 ip
->ip_dest
= ip_dest
;
197 ip
->ip_source
= ip_source
;
200 icmp
->type
= NET_ICMP_TYPE_PING_REPLY
;
203 char *buf_icmp
= (char *) &buf_icmp_prealloc
;
208 unsigned l
= sizeof (proto_icmp_t
);
210 memcpy (buf_icmp
, (char *) icmp
, l
);
211 memcpy (buf_icmp
+l
, buf
, len
);
213 buf_icmp
[l
+len
] = '\0';
215 /* calculate checksum and put it to icmp header */
216 proto_icmp_t
*icmp_
= (proto_icmp_t
*) buf_icmp
;
217 icmp_
->checksum
= checksum16 (buf_icmp
, len
+l
);
219 return net_proto_ip_send (netif
, packet
, ip
, buf_icmp
, len
+l
);