Fixed possible memory corruption in commands exec and netexec; fixed command netcp...
[ZeXOS.git] / kernel / core / net / icmp.c
blobd87273576d6cbc8565b4e5c336dbb44746fda823
1 /*
2 * ZeX/OS
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/>.
21 #include <system.h>
22 #include <string.h>
23 #include <dev.h>
24 #include <net/eth.h>
25 #include <net/net.h>
26 #include <net/if.h>
27 #include <net/packet.h>
28 #include <net/ip.h>
29 #include <net/icmp.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];
41 /* prototype */
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)
47 if (!netif)
48 return 2;
50 unsigned ret = net_proto_icmp_request (netif, ip);
52 if (!ret)
53 return 0;
55 unsigned long time = timer_ticks;
57 while (!net_icmp_ping) {
58 /* timeout 1s - 1000ms */
59 if ((timer_ticks-time) > 1000)
60 return 0;
62 schedule ();
65 net_icmp_ping = 0;
67 return 1;
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);
83 //printf (" !\n");
85 return net_proto_icmp_reply (netif, packet, ip, icmp, buf+8, len-12);
88 return 0;
91 if (icmp->type == NET_ICMP_TYPE_PING_REPLY) {
92 /* TODO: make it better :) */
93 net_icmp_ping = 1;
94 return 1;
97 return 0;
100 unsigned net_proto_icmp_request (netif_t *netif, net_ipv4 dest)
102 //printf ("ICMP request: (%d) %s\n", len, buf);
104 mac_addr_t mac_dest;
105 unsigned get = arp_cache_get (dest, &mac_dest);
107 if (!get) {
108 arp_send_request (netif, dest);
110 unsigned i = 0;
111 /* 100ms for waiting on ARP reply */
112 while (i < 100) {
113 get = arp_cache_get (dest, &mac_dest);
115 if (get)
116 break;
118 /* TODO: make better waiting for ARP reply */
119 timer_wait (1);
121 schedule ();
123 i ++;
126 if (!get)
127 return 0;
130 /* packet header */
131 packet_t *packet = (packet_t *) &packet_prealloc;
133 if (!packet)
134 return 0;
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;
140 /* ip layer */
141 proto_ip_t *ip = (proto_ip_t *) &proto_ip_prealloc;
143 if (!ip)
144 return 0;
146 /* there are some fixed values - yeah it is horrible */
147 ip->ver = 4;
148 ip->head_len = 5;
149 ip->total_len = swap16 (84);
150 ip->flags = 0;
151 ip->frag = 0;
152 ip->ttl = 64;
153 ip->checksum = 0;
154 ip->proto = NET_PROTO_IP_TYPE_ICMP;
155 ip->ip_source = netif->ip;
156 ip->ip_dest = dest;
158 /* icmp layer */
159 proto_icmp_t *icmp = (proto_icmp_t *) &proto_icmp_prealloc;
161 if (!icmp)
162 return 0;
164 memset ((char *) icmp+8, 0, 56);
166 icmp->type = NET_ICMP_TYPE_PING_REQUEST;
167 icmp->code = 0;
168 icmp->seq = 0;
169 icmp->checksum = 0;
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);
180 mac_addr_t mac_dest;
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;
198 ip->checksum = 0;
200 icmp->type = NET_ICMP_TYPE_PING_REPLY;
201 icmp->checksum = 0;
203 char *buf_icmp = (char *) &buf_icmp_prealloc;
205 if (!buf_icmp)
206 return 0;
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);