1
/*** This Programs/Libraries are (C)opyright by Sebastian Krahmer.
2
*** You may use it under the terms of the GPL. You should have
3
*** already received the file COPYING that shows you your rights. If not,
4
*** you can get it at http://www.cs.uni-potsdam.de/homepages/students/linuxer
5
*** the logit-package. You will also find some other nice utillities there.
7
*** THERE IS ABSOLUTELY NO WARRANTY. SO YOU USE IT AT YOUR OWN RISK.
8
*** IT WAS WRITTEN IN THE HOPE THAT IT WILL BE USEFULL. I AM NOT RESPONSIBLE
9
*** FOR ANY DAMAGE YOU MAYBE GET DUE TO USING MY PROGRAMS.
12
#include "usi++/usi-structs.h"
13
#include "usi++/datalink.h"
14
#include "usi++/icmp.h"
23
ICMP::ICMP(const char* host)
25
#define IPPROTO_ICMP 1
27
: IP(host, IPPROTO_ICMP)
30
memset(&icmphdr, 0, sizeof(icmphdr));
34
ICMP::ICMP(u_int32_t dst) : IP(dst, IPPROTO_ICMP)
36
memset(&icmphdr, 0, sizeof(icmphdr));
44
ICMP::ICMP(const ICMP &rhs)
50
this->icmphdr = rhs.icmphdr;
53
ICMP &ICMP::operator=(const ICMP &rhs)
59
this->icmphdr = rhs.icmphdr;
64
ICMP &ICMP::operator=(const IP &rhs)
70
iph = IP::get_iphdr();
71
icmphdr = *(struct icmphdr *)((char *)&iph + IP::get_hlen() * 4);
76
/* Set the type-field in the actuall ICMP-packet.
78
int ICMP::set_type(u_int8_t t)
84
/*! Get the type-field from the actuall ICMP-packet.
86
u_int8_t ICMP::get_type()
93
int ICMP::set_code(u_int8_t c)
101
u_int8_t ICMP::get_code()
106
int ICMP::set_gateway(u_int32_t g)
108
icmphdr.un.gateway = htonl(g);
112
u_int32_t ICMP::get_gateway()
114
return ntohl(icmphdr.un.gateway);
117
int ICMP::set_mtu(u_int16_t mtu)
119
icmphdr.un.frag.mtu = mtu;
123
u_int16_t ICMP::get_mtu()
125
return icmphdr.un.frag.mtu;
128
/* Set id field in the actuall ICMP-packet
130
int ICMP::set_icmpId(u_int16_t id)
132
icmphdr.un.echo.id = id;
136
/* Get the id field from actuall ICMP-packet.
138
u_int16_t ICMP::get_icmpId()
140
return icmphdr.un.echo.id;
143
/* Set the sequecenumber of the actuall ICMP-packet.
145
int ICMP::set_seq(u_int16_t s)
147
icmphdr.un.echo.sequence = s;
151
/* Get the sequence-number of actuall ICMP-packet
153
u_int16_t ICMP::get_seq()
155
return icmphdr.un.echo.sequence;
158
/* get orig datagram from icmp unreachable
161
iphdr ICMP::get_orig() {
162
iphdr iph = *(iphdr *)((char *)(&icmphdr + 1));
167
/* send an ICMP-packet containing 'payload' which
168
* is 'paylen' bytes long
170
int ICMP::sendpack(void *payload, size_t paylen)
172
size_t len = sizeof(struct icmphdr) + paylen; // the packetlenght
176
// s will be our packet
177
char *s = new char[len];
180
// copy ICMP header to packet
181
memcpy((char*)s, (struct icmphdr*)&this->icmphdr, sizeof(icmphdr));
184
memcpy(s+sizeof(icmphdr), payload, paylen);
186
i = (struct icmphdr*)s;
188
// calc checksum over packet
192
i->sum = in_cksum((unsigned short*)s, len, 0);
194
int r = IP::sendpack(s, len);
199
/* send a ICMP-packet with string 'payload' as payload.
201
int ICMP::sendpack(char *payload)
203
return sendpack(payload, strlen(payload));
206
/* send standard UNIX-like ICMP echo request payload
208
int ICMP::send_ping_payload()
216
char payload[PING_PAYLOAD_SIZE];
218
if ((gettimeofday(&tv, NULL)) < 0)
219
die ("ICMP::send_ping_payload: gettimeofday()", PERROR, 1);
220
Timestamp.sec = htonl(tv.tv_sec);
221
Timestamp.usec = htonl(tv.tv_usec);
222
tocopy = PING_PAYLOAD_SIZE;
228
memcpy (payload, &Timestamp, sizeof(Timestamp));
229
return sendpack(payload, PING_PAYLOAD_SIZE);
232
int ICMP::send_timestamp_payload()
235
char payload[TIMESTAMP_PAYLOAD_SIZE];
237
if ((gettimeofday(&tv, NULL)) < 0)
238
die("ICMP::send_timestamp_payload: gettimeofday()", PERROR, 1);
239
memset (payload, 0, TIMESTAMP_PAYLOAD_SIZE);
240
tv.tv_usec = htonl(tv.tv_usec);
241
memcpy(payload, &tv.tv_usec, sizeof(tv.tv_usec));
242
return sendpack(payload, TIMESTAMP_PAYLOAD_SIZE);
245
int ICMP::send_addrmask_payload()
247
char payload[ADDRMASK_PAYLOAD_SIZE];
248
memset (payload, 0, ADDRMASK_PAYLOAD_SIZE);
249
return sendpack(payload, ADDRMASK_PAYLOAD_SIZE);
252
/* handle packets, that are NOT actually for the
255
int ICMP::sniffpack(void *s, size_t len)
257
size_t plen = len + sizeof(struct icmphdr);
258
char *tmp = new char[plen];
261
memset(tmp, 0, plen);
263
r = IP::sniffpack(tmp, plen);
265
if (r == 0 && Layer2::timeout()) { // timeout
270
// point to ICMP header
271
struct icmphdr *icmph = (struct icmphdr*)(tmp);
273
memset(&icmphdr, 0, sizeof(icmphdr));
275
// save ICMP header for public functions
276
memcpy(&icmphdr, icmph, sizeof(struct icmphdr));
278
// and give user the payload
280
memcpy(s, ++icmph, len);
283
return r - sizeof(struct icmphdr);
286
/* Initialize a device ("eth0" for example) for packet-
287
* capturing. It MUST be called before sniffpack() is launched.
288
* Set 'promisc' to 1 if you want the device running in promiscous mode.
289
* Fetch at most 'snaplen' bytes per call.
291
int ICMP::init_device(char *dev, int promisc, size_t snaplen)
293
int r = Layer2::init_device(dev, promisc, snaplen);
295
die("ICMP::init_device", STDERR, 1);
296
r = Layer2::setfilter("icmp");
298
die("ICMP::init_device", STDERR, 1);