1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
#include "inet.h"
#include "icmp.h"
#include "ipv4.h"
#include "log.h"
#include "kmalloc.h"
#include "lib/string/string.h"
uint32_t icmp_generic(struct netdev *dev, uint32_t ip, uint8_t type, uint8_t* pos,uint8_t *end)
{
pos-=4; //we need 32 bytes
struct icmp_v4 *icmp=pos;
icmp->type=type;
icmp->code=0;
icmp->csum=0;
icmp->csum=checksum(icmp,end-pos);
return ipv4_generic(dev,ip,IPV4_P_ICMP,pos,end);
}
uint32_t icmp_ping(struct netdev *dev, uint32_t ip, uint16_t* pos,uint32_t *end)
{
// payload
for(int i=0;i<64;i++)
{
pos--;
*pos=0xbeef;
}
// id and sequence number
pos-=2; // we need 32 bytes
struct icmp_v4_echo *ping=pos;
ping->id=htons(0xabcd); // some random number
ping->seq=htons(0); // we just send one single ping with id 1 for now
return icmp_generic(dev,ip,ICMP_ECHO_REQUEST,pos,end);
}
bool icmp_reply(struct netdev *dev,struct eth_hdr *hdr)
{
unsigned char tmp[6];
memcpy(tmp,hdr->dmac,6);
memcpy(hdr->dmac,hdr->smac,6);
memcpy(hdr->smac,tmp,6);
struct ipv4_hdr *ipv4=hdr->payload;
uint32_t tmp2;
tmp2=ipv4->saddr;
ipv4->saddr=ipv4->daddr;
ipv4->daddr=tmp2;
uint32_t daddr; // destination ip address
struct icmp_v4 *data=(uint32_t *)ipv4+ipv4->ihl;
data->type=ICMP_ECHO_REPLY;
data->csum=0;
ipv4->csum=0;
data->csum=(checksum(data,ntohs(ipv4->len)-ipv4->ihl*4));
ipv4->csum=(checksum(ipv4,ntohs(ipv4->len)));
dev->transmit(hdr,ntohs(ipv4->len)+14); // 14bytes for link2
return true;
}
bool icmp_incoming(struct netdev *dev,struct eth_hdr *hdr)
{
struct ipv4_hdr *ipv4=hdr->payload;
struct icmp_v4 *data=(uint32_t *)ipv4+ipv4->ihl;
// klog ("icmp type=%d",data->type);
// klog ("icmp code=%d",data->code);
// klog ("icmp csum=0x%04x",ntohs(data->csum));
data->csum=0;
// klog("expected checksum = 0x%04X",checksum(data,ntohs(ipv4->len)-ipv4->ihl*4));
if(data->type==ICMP_ECHO_REQUEST) // echo request
{
struct icmp_v4_echo *echo=data->data;
//klog ("received echo request id=%d, seq=%d, data=%d ",ntohs(echo->id),ntohs(echo->seq),echo->data);
icmp_reply(dev,hdr); /// TODO watchout that this is the memory managed by the network card we are dealing with!!. fix this later.
}
return true;
}
|