~ubuntu-branches/ubuntu/trusty/xprobe/trusty

« back to all changes in this revision

Viewing changes to libs-external/USI++/src/icmp.cc

  • Committer: Bazaar Package Importer
  • Author(s): Richard Atterer
  • Date: 2005-02-22 22:54:24 UTC
  • mfrom: (1.2.1 upstream) (2.1.2 hoary)
  • Revision ID: james.westby@ubuntu.com-20050222225424-6cqy8rr45pkna819
Tags: 0.2.2-1
New upstream version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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.
 
6
 ***  
 
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.
 
10
 ***/
 
11
 
 
12
#include "usi++/usi-structs.h"
 
13
#include "usi++/datalink.h"
 
14
#include "usi++/icmp.h"
 
15
#include "usi++/ip.h"
 
16
 
 
17
#include <string.h>
 
18
#include <errno.h>
 
19
#include <iostream>
 
20
 
 
21
namespace usipp {
 
22
 
 
23
ICMP::ICMP(const char* host) 
 
24
#ifndef IPPROTO_ICMP
 
25
#define IPPROTO_ICMP 1
 
26
#endif
 
27
      : IP(host, IPPROTO_ICMP)
 
28
{        
 
29
        // clear memory
 
30
        memset(&icmphdr, 0, sizeof(icmphdr));
 
31
                
 
32
}
 
33
 
 
34
ICMP::ICMP(u_int32_t dst) : IP(dst, IPPROTO_ICMP)
 
35
{
 
36
        memset(&icmphdr, 0, sizeof(icmphdr));
 
37
}
 
38
                
 
39
 
 
40
ICMP::~ICMP()
 
41
{
 
42
}
 
43
 
 
44
ICMP::ICMP(const ICMP &rhs)
 
45
        : IP(rhs)
 
46
{
 
47
        if (this == &rhs)
 
48
                return;
 
49
        
 
50
        this->icmphdr = rhs.icmphdr;
 
51
}
 
52
 
 
53
ICMP &ICMP::operator=(const ICMP &rhs)
 
54
{
 
55
        if (this == &rhs)
 
56
                return *this;
 
57
 
 
58
        IP::operator=(rhs);
 
59
        this->icmphdr  = rhs.icmphdr;
 
60
        return *this;
 
61
}
 
62
 
 
63
 
 
64
ICMP &ICMP::operator=(const IP &rhs)
 
65
{
 
66
    iphdr iph;
 
67
        if (this == &rhs)
 
68
                return *this;
 
69
        IP::operator=(rhs);
 
70
    iph = IP::get_iphdr();
 
71
        icmphdr = *(struct icmphdr *)((char *)&iph + IP::get_hlen() * 4);
 
72
        return *this;
 
73
}
 
74
 
 
75
 
 
76
/* Set the type-field in the actuall ICMP-packet.
 
77
 */
 
78
int ICMP::set_type(u_int8_t t)
 
79
{       
 
80
        icmphdr.type = t;
 
81
        return 0;
 
82
}
 
83
 
 
84
/*! Get the type-field from the actuall ICMP-packet.
 
85
 */
 
86
u_int8_t ICMP::get_type()
 
87
{
 
88
        return icmphdr.type;
 
89
}
 
90
 
 
91
/* Set ICMP-code.
 
92
 */
 
93
int ICMP::set_code(u_int8_t c)
 
94
{
 
95
        icmphdr.code = c;
 
96
        return 0;
 
97
}
 
98
 
 
99
/* Get ICMP-code.
 
100
 */
 
101
u_int8_t ICMP::get_code()
 
102
{
 
103
        return icmphdr.code;
 
104
}
 
105
 
 
106
int ICMP::set_gateway(u_int32_t g)
 
107
{
 
108
        icmphdr.un.gateway = htonl(g);
 
109
        return 0;
 
110
}
 
111
 
 
112
u_int32_t ICMP::get_gateway()
 
113
{
 
114
        return ntohl(icmphdr.un.gateway);
 
115
}
 
116
 
 
117
int ICMP::set_mtu(u_int16_t mtu)
 
118
{
 
119
        icmphdr.un.frag.mtu = mtu;
 
120
        return 0;
 
121
}
 
122
 
 
123
u_int16_t ICMP::get_mtu()
 
124
{
 
125
        return icmphdr.un.frag.mtu;
 
126
}
 
127
 
 
128
/* Set id field in the actuall ICMP-packet 
 
129
 */
 
130
int ICMP::set_icmpId(u_int16_t id)
 
131
{
 
132
        icmphdr.un.echo.id = id;
 
133
        return 0;
 
134
}
 
135
 
 
136
/* Get the id field from actuall ICMP-packet.
 
137
 */
 
138
u_int16_t ICMP::get_icmpId()
 
139
{
 
140
        return icmphdr.un.echo.id;
 
141
}
 
142
 
 
143
/* Set the sequecenumber of the actuall ICMP-packet.
 
144
 */
 
145
int ICMP::set_seq(u_int16_t s)
 
146
{
 
147
        icmphdr.un.echo.sequence = s;
 
148
        return 0;
 
149
}
 
150
 
 
151
/* Get the sequence-number of actuall ICMP-packet
 
152
 */
 
153
u_int16_t ICMP::get_seq()
 
154
{
 
155
        return icmphdr.un.echo.sequence;
 
156
}
 
157
 
 
158
/* get orig datagram from icmp unreachable
 
159
 *
 
160
 */
 
161
iphdr ICMP::get_orig() {
 
162
    iphdr iph = *(iphdr *)((char *)(&icmphdr + 1));
 
163
    return iph;
 
164
}
 
165
 
 
166
 
 
167
/* send an ICMP-packet containing 'payload' which
 
168
 *  is 'paylen' bytes long
 
169
 */
 
170
int ICMP::sendpack(void *payload, size_t paylen)
 
171
{
 
172
        size_t len = sizeof(struct icmphdr) + paylen;   // the packetlenght
 
173
                
 
174
        struct icmphdr *i;
 
175
 
 
176
        // s will be our packet
 
177
        char *s = new char[len];
 
178
        memset(s, 0, len);
 
179
        
 
180
        // copy ICMP header to packet
 
181
        memcpy((char*)s, (struct icmphdr*)&this->icmphdr, sizeof(icmphdr));
 
182
 
 
183
        if (payload)
 
184
                memcpy(s+sizeof(icmphdr), payload, paylen);
 
185
 
 
186
        i = (struct icmphdr*)s;
 
187
        
 
188
        // calc checksum over packet
 
189
        //i->sum = 0;
 
190
        
 
191
        if (i->sum == 0)
 
192
                i->sum = in_cksum((unsigned short*)s, len, 0);
 
193
        
 
194
        int r = IP::sendpack(s, len);
 
195
        delete[] s;
 
196
        return r;    
 
197
}
 
198
 
 
199
/* send a ICMP-packet with string 'payload' as payload.
 
200
 */
 
201
int ICMP::sendpack(char *payload)
 
202
{
 
203
        return sendpack(payload, strlen(payload));
 
204
}
 
205
 
 
206
/* send standard UNIX-like ICMP echo request payload 
 
207
 */
 
208
int ICMP::send_ping_payload()
 
209
{
 
210
        struct _Timestamp {
 
211
                u_int sec;
 
212
                u_int usec;
 
213
        } Timestamp;
 
214
        struct timeval tv;
 
215
        int tocopy, iii=0;
 
216
        char payload[PING_PAYLOAD_SIZE];
 
217
 
 
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;
 
223
        while (tocopy > 0) {
 
224
                payload[iii] = iii;
 
225
                tocopy--;
 
226
                iii++;
 
227
        }
 
228
        memcpy (payload, &Timestamp, sizeof(Timestamp));
 
229
        return sendpack(payload, PING_PAYLOAD_SIZE);
 
230
}
 
231
 
 
232
int ICMP::send_timestamp_payload() 
 
233
{
 
234
        struct timeval tv;
 
235
        char payload[TIMESTAMP_PAYLOAD_SIZE];
 
236
 
 
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);
 
243
}
 
244
 
 
245
int ICMP::send_addrmask_payload()
 
246
{
 
247
        char payload[ADDRMASK_PAYLOAD_SIZE];
 
248
        memset (payload, 0, ADDRMASK_PAYLOAD_SIZE);
 
249
        return sendpack(payload, ADDRMASK_PAYLOAD_SIZE);
 
250
}
 
251
 
 
252
/* handle packets, that are NOT actually for the
 
253
 *  local adress!
 
254
 */
 
255
int ICMP::sniffpack(void *s, size_t len)
 
256
{
 
257
        size_t plen = len + sizeof(struct icmphdr);
 
258
        char *tmp = new char[plen];
 
259
        int r = 0;
 
260
        memset(s, 0, len);
 
261
        memset(tmp, 0, plen);
 
262
        
 
263
        r = IP::sniffpack(tmp, plen);
 
264
 
 
265
        if (r == 0 && Layer2::timeout()) {      // timeout
 
266
                delete[] tmp;
 
267
                return 0;
 
268
        }
 
269
        
 
270
        // point to ICMP header
 
271
        struct icmphdr *icmph = (struct icmphdr*)(tmp);
 
272
 
 
273
        memset(&icmphdr, 0, sizeof(icmphdr));
 
274
 
 
275
        // save ICMP header for public functions
 
276
        memcpy(&icmphdr, icmph, sizeof(struct icmphdr));
 
277
        
 
278
        // and give user the payload
 
279
        if (s)
 
280
                memcpy(s, ++icmph, len);
 
281
        
 
282
        delete[] tmp;
 
283
        return r - sizeof(struct icmphdr);
 
284
}    
 
285
 
 
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.
 
290
 */
 
291
int ICMP::init_device(char *dev, int promisc, size_t snaplen)
 
292
{
 
293
        int r = Layer2::init_device(dev, promisc, snaplen);
 
294
        if (r < 0)
 
295
                die("ICMP::init_device", STDERR, 1);
 
296
        r = Layer2::setfilter("icmp");
 
297
        if (r < 0)
 
298
                die("ICMP::init_device", STDERR, 1);
 
299
        return r;
 
300
}
 
301
 
 
302
} // namespace usipp
 
303