1
/******************************************************************************
2
* Copyright (c) 2004, 2008 IBM Corporation
4
* This program and the accompanying materials
5
* are made available under the terms of the BSD License
6
* which accompanies this distribution, and is available at
7
* http://www.opensource.org/licenses/bsd-license.php
10
* IBM Corporation - initial implementation
11
*****************************************************************************/
14
/*>>>>>>>>>>>>>>>>>>>>> DEFINITIONS & DECLARATIONS <<<<<<<<<<<<<<<<<<<<<<*/
20
#include <sys/socket.h>
23
/* ARP Message types */
27
/* ARP talbe size (+1) */
28
#define ARP_ENTRIES 10
30
/* ICMP Message types */
31
#define ICMP_ECHO_REPLY 0
32
#define ICMP_DST_UNREACHABLE 3
33
#define ICMP_SRC_QUENCH 4
34
#define ICMP_REDIRECT 5
35
#define ICMP_ECHO_REQUEST 8
36
#define ICMP_TIME_EXCEEDED 11
37
#define ICMP_PARAMETER_PROBLEM 12
38
#define ICMP_TIMESTAMP_REQUEST 13
39
#define ICMP_TIMESTAMP_REPLY 14
40
#define ICMP_INFORMATION_REQUEST 15
41
#define ICMP_INFORMATION_REPLY 16
44
* A entry that describes a mapping between IPv4- and MAC-address.
46
typedef struct arp_entry arp_entry_t;
50
uint8_t eth_frame[ETH_MTU_SIZE];
60
unsigned short int checksum;
62
/* for type 3 "Destination Unreachable" */
64
/* for type 0 and 8 */
66
unsigned short int id;
67
unsigned short int seq;
71
/* payload for destination unreachable */
73
unsigned char iphdr[20];
74
unsigned char data[64];
76
/* payload for echo or echo reply */
77
/* maximum size supported is 84 */
78
unsigned char data[84];
82
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>> PROTOTYPES <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<*/
85
checksum(unsigned short *packet, int words);
88
arp_send_request(uint32_t dest_ip);
91
arp_send_reply(uint32_t src_ip, uint8_t * src_mac);
94
fill_arphdr(uint8_t * packet, uint8_t opcode,
95
const uint8_t * src_mac, uint32_t src_ip,
96
const uint8_t * dest_mac, uint32_t dest_ip);
99
lookup_mac_addr(uint32_t ipv4_addr);
102
fill_udp_checksum(struct iphdr *ipv4_hdr);
105
handle_icmp(struct iphdr * iph, uint8_t * packet, int32_t packetsize);
107
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>>> LOCAL VARIABLES <<<<<<<<<<<<<<<<<<<<<<<<<*/
109
/* Routing parameters */
110
static uint32_t own_ip = 0;
111
static uint32_t multicast_ip = 0;
112
static uint32_t router_ip = 0;
113
static uint32_t subnet_mask = 0;
115
/* helper variables */
116
static uint32_t ping_dst_ip;
117
static const uint8_t null_mac_addr[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
118
static const uint8_t broadcast_mac[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
119
static uint8_t multicast_mac[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
121
/* There are only (ARP_ENTRIES-1) effective entries because
122
* the entry that is pointed by arp_producer is never used.
124
static unsigned int arp_consumer = 0;
125
static unsigned int arp_producer = 0;
126
static arp_entry_t arp_table[ARP_ENTRIES];
128
/* Function pointer send_ip. Points either to send_ipv4() or send_ipv6() */
129
int (*send_ip) (void *, int);
131
/*>>>>>>>>>>>>>>>>>>>>>>>>>>>> IMPLEMENTATION <<<<<<<<<<<<<<<<<<<<<<<<<<<*/
134
* IPv4: Initialize the environment for the IPv4 layer.
146
for(i=0; i<ARP_ENTRIES; ++i) {
147
arp_table[i].ipv4_addr = 0;
148
memset(arp_table[i].mac_addr, 0, 6);
149
arp_table[i].eth_len = 0;
152
/* Set IP send function to send_ipv4() */
153
send_ip = &send_ipv4;
157
* IPv4: Set the own IPv4 address.
159
* @param _own_ip client IPv4 address (e.g. 127.0.0.1)
162
set_ipv4_address(uint32_t _own_ip)
169
* IPv4: Get the own IPv4 address.
171
* @return client IPv4 address (e.g. 127.0.0.1)
174
get_ipv4_address(void)
180
* IPv4: Set the IPv4 multicast address.
182
* @param _own_ip multicast IPv4 address (224.0.0.0 - 239.255.255.255)
185
set_ipv4_multicast(uint32_t _multicast_ip)
187
// is this IP Multicast out of range (224.0.0.0 - 239.255.255.255)
188
if((htonl(_multicast_ip) < 0xE0000000)
189
|| (htonl(_multicast_ip) > 0xEFFFFFFF)) {
191
memset(multicast_mac, 0xFF, 6);
195
multicast_ip = _multicast_ip;
196
multicast_mac[0] = 0x01;
197
multicast_mac[1] = 0x00;
198
multicast_mac[2] = 0x5E;
199
multicast_mac[3] = (uint8_t) 0x7F & (multicast_ip >> 16);
200
multicast_mac[4] = (uint8_t) 0xFF & (multicast_ip >> 8);
201
multicast_mac[5] = (uint8_t) 0xFF & (multicast_ip >> 0);
205
* IPv4: Get the IPv4 multicast address.
207
* @return multicast IPv4 address (224.0.0.0 - 239.255.255.255 or 0 if not set)
210
get_ipv4_multicast(void)
216
* IPv4: Set the routers IPv4 address.
218
* @param _router_ip router IPv4 address
221
set_ipv4_router(uint32_t _router_ip)
223
router_ip = _router_ip;
228
* IPv4: Get the routers IPv4 address.
230
* @return router IPv4 address
233
get_ipv4_router(void)
239
* IPv4: Set the subnet mask.
241
* @param _subnet_mask netmask of the own IPv4 address
244
set_ipv4_netmask(uint32_t _subnet_mask)
246
subnet_mask = _subnet_mask;
251
* IPv4: Get the subnet mask.
253
* @return netmask of the own IPv4 address
256
get_ipv4_netmask(void)
262
* IPv4: Creates IP-packet. Places IP-header in a packet and fills it
263
* with corresponding information.
265
* Use this function with similar functions for other network layers
266
* (fill_ethhdr, fill_udphdr, fill_dnshdr, fill_btphdr).
268
* @param packet Points to the place where IP-header must be placed.
269
* @param packetsize Size of the packet in bytes incl. this hdr and data.
270
* @param ip_proto Type of the next level protocol (e.g. UDP).
271
* @param ip_src Sender IP address
272
* @param ip_dst Receiver IP address
280
fill_iphdr(uint8_t * packet, uint16_t packetsize,
281
uint8_t ip_proto, uint32_t ip_src, uint32_t ip_dst) {
282
struct iphdr * iph = (struct iphdr *) packet;
284
iph -> ip_hlv = 0x45;
285
iph -> ip_tos = 0x10;
286
iph -> ip_len = htons(packetsize);
287
iph -> ip_id = htons(0);
289
iph -> ip_ttl = 0xFF;
290
iph -> ip_p = ip_proto;
291
iph -> ip_src = htonl(ip_src);
292
iph -> ip_dst = htonl(ip_dst);
297
* IPv4: Handles IPv4-packets according to Receive-handle diagram.
299
* @param ip_packet IP-packet to be handled
300
* @param packetsize Length of the packet
301
* @return ZERO - packet handled successfully;
302
* NON ZERO - packet was not handled (e.g. bad format)
307
handle_ipv4(uint8_t * ip_packet, int32_t packetsize)
311
static uint8_t ip_heap[65536 + ETH_MTU_SIZE];
313
if (packetsize < sizeof(struct iphdr))
314
return -1; // packet is too small
316
iph = (struct iphdr * ) ip_packet;
318
/* Drop it if destination IPv4 address is no IPv4 Broadcast, no
319
* registered IPv4 Multicast and not our Unicast address
321
if((multicast_ip == 0 && iph->ip_dst >= 0xE0000000 && iph->ip_dst <= 0xEFFFFFFF)
322
|| (multicast_ip != iph->ip_dst && iph->ip_dst != 0xFFFFFFFF &&
323
own_ip != 0 && iph->ip_dst != own_ip)) {
327
old_sum = iph -> ip_sum;
329
if (old_sum != checksum((uint16_t *) iph, sizeof (struct iphdr) >> 1))
330
return -1; // Wrong IP checksum
332
// is it the first fragment in a packet?
333
if (((iph -> ip_off) & 0x1FFF) == 0) {
334
// is it part of more fragments?
335
if (((iph -> ip_off) & 0x2000) == 0x2000) {
336
memcpy(ip_heap, ip_packet, iph->ip_len);
340
// it's not the first fragment
342
// get the first fragment
343
struct iphdr * iph_first = (struct iphdr * ) ip_heap;
345
// is this fragment not part of the first one, then exit
346
if ((iph_first->ip_id != iph->ip_id ) ||
347
(iph_first->ip_p != iph->ip_p ) ||
348
(iph_first->ip_src != iph->ip_src) ||
349
(iph_first->ip_dst != iph->ip_dst)) {
353
// this fragment is part of the first one!
354
memcpy(ip_heap + sizeof(struct iphdr) +
355
((iph -> ip_off) & 0x1FFF) * 8,
356
ip_packet + sizeof(struct iphdr),
357
iph -> ip_len - sizeof(struct iphdr));
359
// is it part of more fragments? Then return.
360
if (((iph -> ip_off) & 0x2000) == 0x2000) {
364
// packet is completly reassambled now!
366
// recalculate ip_len and set iph and ip_packet to the
367
iph_first->ip_len = iph->ip_len + ((iph->ip_off) & 0x1FFF) * 8;
369
// set iph and ip_packet to the resulting packet.
371
iph = (struct iphdr * ) ip_packet;
374
switch (iph -> ip_p) {
376
return handle_icmp(iph, ip_packet + sizeof(struct iphdr),
377
iph -> ip_len - sizeof(struct iphdr));
379
return handle_udp(ip_packet + sizeof(struct iphdr),
380
iph -> ip_len - sizeof(struct iphdr));
382
return handle_tcp(ip_packet + sizeof(struct iphdr),
383
iph -> ip_len - sizeof(struct iphdr));
387
return -1; // Unknown protocol
391
* IPv4: Send IPv4-packets.
393
* Before the packet is sent there are some patcches performed:
394
* - IPv4 source address is replaced by our unicast IPV4 address
395
* if it is set to 0 or 1
396
* - IPv4 destination address is replaced by our multicast IPV4 address
398
* - IPv4 checksum is calculaded.
399
* - If payload type is UDP, then the UDP checksum is calculated also.
401
* We sent an ARP request first, if this is the first packet sent to
402
* the declared IPv4 destination address. In this case we store the
403
* the packet and sent it later if we receive the ARP response.
404
* If the MAC address is known already, then we send the packet immediatly.
405
* If there is already an ARP request pending, then we drop this packet
406
* and send again an ARP request.
408
* @param ip_packet IP-packet to be handled
409
* @param packetsize Length of the packet
410
* @return -2 - packet dropped (MAC address not resolved - ARP request pending)
411
* -1 - packet dropped (bad format)
412
* 0 - packet stored (ARP request sent - packet will be sent if
413
* ARP response is received)
414
* >0 - packet send (number of transmitted bytes is returned)
420
send_ipv4(void* buffer, int len)
422
arp_entry_t *arp_entry;
424
const uint8_t *mac_addr = 0;
426
if(len + sizeof(struct ethhdr) > ETH_MTU_SIZE)
429
ip = (struct iphdr *) buffer;
431
/* Replace source IPv4 address with our own unicast IPv4 address
432
* if it's 0 (= own unicast source address not specified).
434
if(ip->ip_src == 0) {
435
ip->ip_src = htonl( own_ip );
437
/* Replace source IPv4 address with our unicast IPv4 address and
438
* replace destination IPv4 address with our multicast IPv4 address
439
* if source address is set to 1.
441
else if(ip->ip_src == 1) {
442
ip->ip_src = htonl( own_ip );
443
ip->ip_dst = htonl( multicast_ip );
446
// Calculate the IPv4 checksum
448
ip->ip_sum = checksum((uint16_t *) ip, sizeof (struct iphdr) >> 1);
450
// if payload type is UDP, then we need to calculate the
451
// UDP checksum that depends on the IP header
452
if(ip->ip_p == IPTYPE_UDP) {
453
fill_udp_checksum(ip);
456
// Check if the MAC address is already cached
458
|| ( ((~subnet_mask) & ip->ip_dst) == ~subnet_mask &&
459
( subnet_mask & ip->ip_dst) == (subnet_mask & own_ip))) {
460
arp_entry = &arp_table[arp_producer];
461
mac_addr = broadcast_mac;
463
else if(ip->ip_dst == multicast_ip) {
464
arp_entry = &arp_table[arp_producer];
465
mac_addr = multicast_mac;
468
// Check if IP address is in the same subnet as we are
469
if((subnet_mask & own_ip) == (subnet_mask & ip->ip_dst))
470
arp_entry = lookup_mac_addr(ip->ip_dst);
471
// if not then we need to know the router's IP address
473
arp_entry = lookup_mac_addr(router_ip);
474
if(arp_entry && memcmp(arp_entry->mac_addr, null_mac_addr, 6) != 0)
475
mac_addr = arp_entry->mac_addr;
478
// If we could not resolv the MAC address by our own...
480
// send the ARP request
481
arp_send_request(ip->ip_dst);
483
// drop the current packet if there is already a ARP request pending
487
// take the next entry in the ARP table to prepare a the new ARP entry.
488
arp_entry = &arp_table[arp_producer];
489
arp_producer = (arp_producer+1)%ARP_ENTRIES;
491
// if ARP table is full then we must drop the oldes entry.
492
if(arp_consumer == arp_producer)
493
arp_consumer = (arp_consumer+1)%ARP_ENTRIES;
495
// store the packet to be send if the ARP reply is received
496
arp_entry->ipv4_addr = ip->ip_dst;
497
memset(arp_entry->mac_addr, 0, 6);
498
fill_ethhdr (arp_entry->eth_frame, htons(ETHERTYPE_IP),
499
get_mac_address(), null_mac_addr);
500
memcpy(&arp_entry->eth_frame[sizeof(struct ethhdr)],
502
arp_entry->eth_len = len + sizeof(struct ethhdr);
507
// Send the packet with the known MAC address
508
fill_ethhdr(arp_entry->eth_frame, htons(ETHERTYPE_IP),
509
get_mac_address(), mac_addr);
510
memcpy(&arp_entry->eth_frame[sizeof(struct ethhdr)], buffer, len);
511
return send_ether(arp_entry->eth_frame, len + sizeof(struct ethhdr));
515
* IPv4: Calculate UDP checksum. Places the result into the UDP-header.
517
* Use this function after filling the UDP payload.
519
* @param ipv4_hdr Points to the place where IPv4-header starts.
523
fill_udp_checksum(struct iphdr *ipv4_hdr)
526
unsigned long checksum = 0;
531
udp_hdr = (udp_hdr_t *) (ipv4_hdr + 1);
534
memset(&ip_hdr, 0, sizeof(struct iphdr));
535
ip_hdr.ip_src = ipv4_hdr->ip_src;
536
ip_hdr.ip_dst = ipv4_hdr->ip_dst;
537
ip_hdr.ip_len = udp_hdr->uh_ulen;
538
ip_hdr.ip_p = ipv4_hdr->ip_p;
540
ptr = (char*) udp_hdr;
541
for (i = 0; i < udp_hdr->uh_ulen; i+=2)
542
checksum += *((uint16_t*) &ptr[i]);
544
ptr = (char*) &ip_hdr;
545
for (i = 0; i < sizeof(struct iphdr); i+=2)
546
checksum += *((uint16_t*) &ptr[i]);
548
checksum = (checksum >> 16) + (checksum & 0xffff);
549
checksum += (checksum >> 16);
550
udp_hdr->uh_sum = ~checksum;
554
* IPv4: Calculates checksum for IP header.
556
* @param packet Points to the IP-header
557
* @param words Size of the packet in words incl. IP-header and data.
561
static unsigned short
562
checksum(unsigned short * packet, int words)
564
unsigned long checksum;
566
for (checksum = 0; words > 0; words--)
567
checksum += *packet++;
568
checksum = (checksum >> 16) + (checksum & 0xffff);
569
checksum += (checksum >> 16);
575
lookup_mac_addr(uint32_t ipv4_addr)
579
for(i=arp_consumer; i != arp_producer; i = ((i+1)%ARP_ENTRIES) ) {
580
if(arp_table[i].ipv4_addr == ipv4_addr)
581
return &arp_table[i];
588
* ARP: Sends an ARP-request package.
589
* For given IPv4 retrieves MAC via ARP (makes several attempts)
591
* @param dest_ip IP of the host which MAC should be obtained
594
arp_send_request(uint32_t dest_ip)
596
arp_entry_t *arp_entry = &arp_table[arp_producer];
598
memset(arp_entry->eth_frame, 0, sizeof(struct ethhdr) + sizeof(struct arphdr));
599
fill_arphdr(&arp_entry->eth_frame[sizeof(struct ethhdr)], ARP_REQUEST,
600
get_mac_address(), own_ip, broadcast_mac, dest_ip);
601
fill_ethhdr(arp_entry->eth_frame, ETHERTYPE_ARP,
602
get_mac_address(), broadcast_mac);
604
send_ether(arp_entry->eth_frame,
605
sizeof(struct ethhdr) + sizeof(struct arphdr));
609
* ARP: Sends an ARP-reply package.
610
* This package is used to serve foreign requests (in case IP in
611
* foreign request matches our host IP).
613
* @param src_ip requester IP address (foreign IP)
614
* @param src_mac requester MAC address (foreign MAC)
617
arp_send_reply(uint32_t src_ip, uint8_t * src_mac)
619
arp_entry_t *arp_entry = &arp_table[arp_producer];
621
memset(arp_entry->eth_frame, 0, sizeof(struct ethhdr) + sizeof(struct arphdr));
622
fill_ethhdr(arp_entry->eth_frame, ETHERTYPE_ARP,
623
get_mac_address(), src_mac);
624
fill_arphdr(&arp_entry->eth_frame[sizeof(struct ethhdr)], ARP_REPLY,
625
get_mac_address(), own_ip, src_mac, src_ip);
627
send_ether(arp_entry->eth_frame,
628
sizeof(struct ethhdr) + sizeof(struct arphdr));
632
* ARP: Creates ARP package. Places ARP-header in a packet and fills it
633
* with corresponding information.
635
* Use this function with similar functions for other network layers
638
* @param packet Points to the place where ARP-header must be placed.
639
* @param opcode Identifies is it request (ARP_REQUEST)
640
* or reply (ARP_REPLY) package.
641
* @param src_mac sender MAC address
642
* @param src_ip sender IP address
643
* @param dest_mac receiver MAC address
644
* @param dest_ip receiver IP address
649
fill_arphdr(uint8_t * packet, uint8_t opcode,
650
const uint8_t * src_mac, uint32_t src_ip,
651
const uint8_t * dest_mac, uint32_t dest_ip)
653
struct arphdr * arph = (struct arphdr *) packet;
655
arph -> hw_type = htons(1);
656
arph -> proto_type = htons(ETHERTYPE_IP);
658
arph -> proto_len = 4;
659
arph -> opcode = htons(opcode);
661
memcpy(arph->src_mac, src_mac, 6);
662
arph->src_ip = htonl(src_ip);
663
memcpy(arph->dest_mac, dest_mac, 6);
664
arph->dest_ip = htonl(dest_ip);
668
* ARP: Handles ARP-messages according to Receive-handle diagram.
669
* Updates arp_table for outstanding ARP requests (see arp_getmac).
671
* @param packet ARP-packet to be handled
672
* @param packetsize length of the packet
673
* @return ZERO - packet handled successfully;
674
* NON ZERO - packet was not handled (e.g. bad format)
680
handle_arp(uint8_t * packet, int32_t packetsize)
682
struct arphdr * arph = (struct arphdr *) packet;
684
if (packetsize < sizeof(struct arphdr))
685
return -1; // Packet is too small
687
if (arph -> hw_type != htons(1) || arph -> proto_type != htons(ETHERTYPE_IP))
688
return -1; // Unknown hardware or unsupported protocol
690
if (arph -> dest_ip != htonl(own_ip))
691
return -1; // receiver IP doesn't match our IP
693
switch(htons(arph -> opcode)) {
697
arp_send_reply(htonl(arph->src_ip), arph -> src_mac);
698
return 0; // no error
701
// if it is not for us -> return immediately
702
if(memcmp(get_mac_address(), arph->dest_mac, 6)) {
703
return 0; // no error
706
if(arph->src_ip == 0) {
707
// we are not interested for a MAC address if
708
// the IPv4 address is 0.0.0.0 or ff.ff.ff.ff
712
// now let's find the corresponding entry in the ARP table
714
for(i=arp_consumer; i != arp_producer; i = ((i+1)%ARP_ENTRIES) ) {
715
if(arp_table[i].ipv4_addr == arph->src_ip)
718
if(i == arp_producer || memcmp(arp_table[i].mac_addr, null_mac_addr, 6) != 0) {
719
// we have not asked to resolve this IPv4 address !
723
memcpy(arp_table[i].mac_addr, arph->src_mac, 6);
725
// do we have something to send
726
if(arp_table[i].eth_len > 0) {
727
struct ethhdr * ethh = (struct ethhdr *) arp_table[i].eth_frame;
728
memcpy(ethh -> dest_mac, arp_table[i].mac_addr, 6);
730
send_ether(arp_table[i].eth_frame, arp_table[i].eth_len);
731
arp_table[i].eth_len = 0;
733
return 0; // no error
738
return -1; // Invalid message type
742
* ICMP: Send an ICMP Echo request to destination IPv4 address.
743
* This function does also set a global variable to the
744
* destination IPv4 address. If there is an ICMP Echo Reply
745
* received later then the variable is set back to 0.
746
* In other words, reading a value of 0 form this variable
747
* means that an answer to the request has been arrived.
749
* @param _ping_dst_ip destination IPv4 address
752
ping_ipv4(uint32_t _ping_dst_ip)
754
unsigned char packet[sizeof(struct iphdr) + sizeof(struct icmphdr)];
755
struct icmphdr *icmp;
757
ping_dst_ip = _ping_dst_ip;
762
fill_iphdr(packet, sizeof(struct iphdr) + sizeof(struct icmphdr), IPTYPE_ICMP,
764
icmp = (struct icmphdr *) (packet + sizeof(struct iphdr));
765
icmp->type = ICMP_ECHO_REQUEST;
768
icmp->options.echo.id = 0xd476;
769
icmp->options.echo.seq = 1;
771
memset(icmp->payload.data, '*', sizeof(icmp->payload.data));
774
checksum((unsigned short *) icmp, sizeof(struct icmphdr) >> 1);
775
send_ipv4(packet, sizeof(struct iphdr) + sizeof(struct icmphdr));
779
* ICMP: Return host IPv4 address that we are waiting for a
780
* ICMP Echo reply message. If this value is 0 then we have
783
* @return ping_dst_ip host IPv4 address
792
* ICMP: Handles ICMP-packets according to Receive-handle diagram.
794
* @param icmp_packet ICMP-packet to be handled
795
* @param packetsize Length of the packet
796
* @return ZERO - packet handled successfully;
797
* NON ZERO - packet was not handled (e.g. bad format)
801
handle_icmp(struct iphdr * iph, uint8_t * packet, int32_t packetsize)
803
struct icmphdr *icmp = (struct icmphdr *) packet;
806
case ICMP_ECHO_REPLY:
807
if (icmp->options.echo.id != 0xd476)
809
if (icmp->options.echo.seq != 1)
811
if(ping_dst_ip != iph->ip_src
816
case ICMP_DST_UNREACHABLE: {
817
// We've got Destination Unreachable msg
818
// Inform corresponding upper network layers
819
struct iphdr * bad_iph = (struct iphdr * ) &icmp->payload;
821
switch(bad_iph->ip_p) {
823
handle_tcp_dun((uint8_t *) (bad_iph + 1), packetsize
824
- sizeof(struct icmphdr)
825
- sizeof(struct iphdr), icmp->code);
828
handle_udp_dun((uint8_t *) (bad_iph + 1), packetsize
829
- sizeof(struct icmphdr)
830
- sizeof(struct iphdr), icmp->code);
835
case ICMP_SRC_QUENCH:
839
case ICMP_ECHO_REQUEST: {
840
// We've got an Echo Request - answer with Echo Replay msg
841
unsigned char reply_packet[sizeof(struct iphdr) + packetsize];
842
struct icmphdr *reply_icmph;
844
fill_iphdr(reply_packet, sizeof(struct iphdr) + packetsize,
845
IPTYPE_ICMP, 0, iph->ip_src);
847
reply_icmph = (struct icmphdr *) &reply_packet[sizeof(struct iphdr)];
848
memcpy(reply_icmph, packet, packetsize);
849
reply_icmph -> type = ICMP_ECHO_REPLY;
850
reply_icmph -> checksum = 0;
851
reply_icmph->checksum = checksum((unsigned short *) reply_icmph,
852
sizeof(struct icmphdr) >> 1);
854
send_ipv4(reply_packet, sizeof(struct iphdr) + packetsize);
857
case ICMP_TIME_EXCEEDED:
859
case ICMP_PARAMETER_PROBLEM:
861
case ICMP_TIMESTAMP_REQUEST:
863
case ICMP_TIMESTAMP_REPLY:
865
case ICMP_INFORMATION_REQUEST:
867
case ICMP_INFORMATION_REPLY: