1 /*
2 * $Id:$
3 */
4
5 #include "default.h"
6 #include <sys/types.h>
7 #include <stdio.h>
8 #ifdef HAVE_UNISTD_H
9 # include <unistd.h>
10 #endif
11 #include <stdlib.h>
12 #include <stdarg.h>
13 #include <time.h>
14 #include <libnet.h>
15 #include "network.h"
16 #include "network_raw.h"
17 #include "thcrut.h"
18 #include "thcrut_pcap.h"
19 #include "packets.h"
20 #include "icmp_main.h"
21 #include "thcrut_pcap.h"
22
23 static void init_defaults(void);
24 static void init_vars(void);
25 static void do_getopt(int argc, char *argv[], struct _state_icmp *state);
26 static void usage(void);
27 static void icmp_filter(unsigned char *u, struct pcap_pkthdr *p, unsigned char *packet);
28 static void dis_timeout(struct _state *state);
29 static void cb_filter(void);
30 static int sendicmp(struct _state_icmp *state, char *data, size_t len);
31
32 static char packet_echo[20 + 8 + 8];
33 static char packet_amask[20 + 8 + 4];
34 static char packet_rsol[20 + 8];
35
36 #define DFL_HOSTS_PARALLEL (200)
37
38 #define STATE_RESET (0)
39 #define STATE_ICMPI (1)
40 #define STATE_ICMPII (2)
41 #define STATE_ICMPIII (3)
42
43 extern int rawsox;
44 extern struct _opt opt;
45
46 static void
init_defaults(void)47 init_defaults(void)
48 {
49 if (opt.hosts_parallel == 0)
50 opt.hosts_parallel = DFL_HOSTS_PARALLEL;
51 }
52
53 static void
init_vars(void)54 init_vars(void)
55 {
56 opt.ip_socket = init_pcap(opt.device, 1, "icmp", &opt.net, &opt.bcast, &opt.dlt_len);
57
58 rawsox = net_sock_raw();
59 if (rawsox < 0)
60 {
61 fprintf(stderr, "socket: %s\n", strerror(errno));
62 exit(-1);
63 }
64
65 icmp_gen_packets(packet_echo, sizeof packet_echo, packet_amask, sizeof packet_amask, packet_rsol, sizeof packet_rsol);
66 }
67
68 static void
usage(void)69 usage(void)
70 {
71 fprintf(stderr, ""
72 "usage: icmp [options] [IP range] ...\n"
73 " -P ICMP echo request (default)\n"
74 " -A ICMP Address mask request (default)\n"
75 " -R ICMP MCAST Router solicitation request\n"
76 /* Spoofing not possible because we dont reply to arp requests */
77 //" -s <ip> Source ip to use\n"
78 " -l <n> Hosts in parallel (%d)\n"
79 "", DFL_HOSTS_PARALLEL);
80
81 exit(0);
82 }
83
84
85 static void
do_getopt(int argc,char * argv[],struct _state_icmp * state)86 do_getopt(int argc, char *argv[], struct _state_icmp *state)
87 {
88 int c;
89
90 optind = 1;
91 while ( (c = getopt(argc, argv, "+PARh:l:")) != -1)
92 {
93 switch (c)
94 {
95 case 'P':
96 state->flags |= FL_ST_ECHO;
97 break;
98 case 'A':
99 state->flags |= FL_ST_AMASK;
100 break;
101 case 'R':
102 state->flags |= FL_ST_RSOL;
103 break;
104 case 'l':
105 opt.hosts_parallel = atoi(optarg);
106 break;
107 default:
108 usage();
109 break;
110 }
111 }
112
113 opt.argvlist = &argv[optind];
114 opt.argc = argc - optind;
115
116 if (opt.argc <= 0)
117 usage();
118
119 if (!(state->flags & (FL_ST_ECHO | FL_ST_AMASK | FL_ST_RSOL)))
120 state->flags |= FL_ST_AMASK | FL_ST_ECHO;
121 }
122
123 /*
124 * Return 0 if blocked.
125 * FIXME: Can happen that we always get blocked after second
126 * ICMP type is send out. In any case do we repeat and send
127 * first ICMP type again.
128 */
129 static int
sendpackets(struct _state_icmp * state,unsigned int seq)130 sendpackets(struct _state_icmp *state, unsigned int seq)
131 {
132 struct icmp *icmp;
133 struct timeval *tv;
134
135 if (state->flags == 0)
136 {
137 fprintf(stderr, "%s:%d SHOULD NOT HAPPEN\n", __func__, __LINE__);
138 abort();
139 }
140
141
142 if (state->flags & FL_ST_ECHO)
143 {
144 icmp = (struct icmp *)(packet_echo + 20);
145 icmp->icmp_hun.ih_idseq.icd_seq = htons(seq);
146 tv = (struct timeval *)(packet_echo + 20 + 8);
147 gettimeofday(tv, NULL);
148 if (sendicmp(state, packet_echo, sizeof packet_echo) == 0)
149 return 0;
150 }
151 if (state->flags & FL_ST_AMASK)
152 {
153 icmp = (struct icmp *)(packet_amask + 20);
154 icmp->icmp_hun.ih_idseq.icd_seq = htons(seq);
155 if (sendicmp(state, packet_amask, sizeof packet_amask) == 0)
156 return 0;
157 }
158
159 if (state->flags & FL_ST_RSOL)
160 if (sendicmp(state, packet_rsol, sizeof packet_rsol) == 0)
161 return 0;
162 return 1;
163 }
164
165 /*
166 * FIXME: On block'ed send we should use wfds to see when socket
167 * becomes writeable again. (But this would delay our queue :/).
168 */
169 static void
dis_timeout(struct _state * state)170 dis_timeout(struct _state *state)
171 {
172 struct _state_icmp *state_icmp = (struct _state_icmp *)state;
173
174 /* Switch state if we send successfully, otherwise
175 * stay in state to try again.
176 */
177 switch (STATE_current(state))
178 {
179 case STATE_RESET:
180 if (sendpackets(state_icmp, 0) != 0)
181 STATE_current(state) = STATE_ICMPI;
182 break;
183 case STATE_ICMPI:
184 if (sendpackets(state_icmp, 1) != 0)
185 STATE_current(state) = STATE_ICMPII;
186 break;
187 case STATE_ICMPII:
188 if (sendpackets(state_icmp, 2) != 0)
189 STATE_current(state) = STATE_ICMPIII;
190 break;
191 case STATE_ICMPIII:
192 STATE_reset(state);
193 break;
194 default:
195 fprintf(stderr, "Unknown state: %d\n", STATE_current(state));
196 STATE_reset(state);
197 break;
198 }
199 }
200
201 static void
cb_filter(void)202 cb_filter(void)
203 {
204 if (pcap_dispatch(opt.ip_socket, -1, (pcap_handler) icmp_filter, NULL) < 0)
205 {
206 pcap_perror(opt.ip_socket, "pcap_dispatch");
207 exit(-1);
208 }
209 }
210
211 #ifndef LIBNET_IPV4_H
212 # define LIBNET_IPV4_H 0x14
213 #endif
214
215 /*
216 * Return number 0 if blocked, -1 on error >0 otherwise.
217 */
218 static int
sendicmp(struct _state_icmp * state,char * data,size_t len)219 sendicmp(struct _state_icmp *state, char *data, size_t len)
220 {
221 struct ip *ip = (struct ip *)(data);
222
223 ip->ip_dst.s_addr = htonl(STATE_ip(state));
224 DEBUGF("ip len= %d\n", ntohs(ip->ip_len));
225 /* ICMP checksum is mandatory */
226 libnet_do_checksum(data, IPPROTO_ICMP, len - LIBNET_IPV4_H);
227 return net_send(rawsox, data, len);
228 }
229
230 static void
icmp_filter(unsigned char * u,struct pcap_pkthdr * p,unsigned char * packet)231 icmp_filter(unsigned char *u, struct pcap_pkthdr *p, unsigned char *packet)
232 {
233 char buf[128];
234 struct ip *ip = (struct ip *)(buf);
235 struct _state_icmp *state;
236 int len;
237 unsigned short options = 0;
238 struct icmp *icmp;
239 struct timeval diff, *tv;
240
241 /*
242 * At least...
243 */
244 if (p->caplen < (opt.dlt_len + 20 + 8))
245 return;
246
247 len = p->caplen - opt.dlt_len;
248 if (len > sizeof buf)
249 len = sizeof buf;
250
251 memcpy(buf, packet + opt.dlt_len, len);
252 if (vrfy_ip(ip, len, &options) != 0)
253 return;
254 if (!(state = (struct _state_icmp *)STATE_by_ip(&opt.sq, ntohl(ip->ip_src.s_addr))))
255 return;
256
257 if (ntohs(ip->ip_len) > len)
258 return;
259 len = ntohs(ip->ip_len) - 20 - options;
260
261 icmp = (struct icmp *)(buf + 20 + options);
262 if (((icmp->icmp_type == 0) && (icmp->icmp_code == 0)) && (len >= 8 + 8))
263 {
264 if (state->flags & FL_ST_ECHO)
265 {
266 state->flags &= ~FL_ST_ECHO;
267 tv = (struct timeval *)((char *)icmp + 8);
268 SQ_TV_diff(&diff, tv, &p->ts);
269 /* ttl= time= xx.yyy msec */
270 printf("%-16s %d bytes reply icmp_seq=%d ttl=%03d time=", int_ntoa(ip->ip_src.s_addr), 20 + options + len, ntohs(icmp->icmp_hun.ih_idseq.icd_seq), ip->ip_ttl);
271 if (diff.tv_sec)
272 printf("%ld.%03ld sec\n", diff.tv_sec, diff.tv_usec / 1000);
273 else if (diff.tv_usec / 1000)
274 printf("%ld.%03ld msec\n", diff.tv_usec / 1000, diff.tv_usec % 1000);
275 else
276 printf("%ld usec\n", diff.tv_usec % 1000);
277 }
278 goto end;
279 }
280 if ((icmp->icmp_type == 18) && (len >= 8 + 4))
281 {
282 if (state->flags & FL_ST_AMASK)
283 {
284 state->flags &= ~FL_ST_AMASK;
285 printf("%-16s icmp_seq=%d ttl=%03d mask=", int_ntoa(ip->ip_src.s_addr), ntohs(icmp->icmp_hun.ih_idseq.icd_seq), ip->ip_ttl);
286 printf("%s\n", int_ntoa(*(long *)((char *)icmp + 8)));
287 }
288 goto end;
289 }
290 if (icmp->icmp_type == 9)
291 {
292 if (state->flags & FL_ST_RSOL)
293 {
294 state->flags &= FL_ST_RSOL;
295 printf("%s ROUTER SOLICITATION. DECODING NOT IMPLEMENTED. FIXME\n", int_ntoa(ip->ip_src.s_addr));
296 }
297 goto end;
298 }
299 #if 0
300 /* We dont sniff for this one */
301 DEBUGF("type %d, code %d\n", icmp->type, icmp->code);
302 hexdump(buf, 24);
303 #endif
304 end:
305 if (!state->flags)
306 STATE_reset(state);
307 }
308
309 int
icmp_main(int argc,char * argv[])310 icmp_main(int argc, char *argv[])
311 {
312 struct _ipranges ipr;
313 struct _state_icmp state;
314 struct pcap_stat ps;
315 int ret;
316
317 init_defaults();
318 memset(&state, 0, sizeof state);
319 do_getopt(argc, argv, &state);
320 init_vars();
321 IP_init(&ipr, opt.argvlist, (opt.flags & FL_OPT_SPREADMODE)?IPR_MODE_SPREAD:0);
322
323 if (!SQ_init(&opt.sq, opt.hosts_parallel, sizeof state, pcap_fileno(opt.ip_socket), dis_timeout, cb_filter))
324 {
325 fprintf(stderr, "Failed to init states: %s\n", strerror(errno));
326 exit(-1);
327 }
328
329 while (1)
330 {
331 IP_next(&ipr);
332 if (IP_current(&ipr))
333 {
334 STATE_ip(&state) = IP_current(&ipr);
335 ret = STATE_wait(&opt.sq, (struct _state *)&state);
336 } else
337 ret = STATE_wait(&opt.sq, NULL);
338
339 if (ret != 0)
340 break;
341 }
342
343 if (thcrut_pcap_stats(opt.ip_socket, &ps) == 0)
344 fprintf(stderr, "%u packets received by filter, %u packets dropped by kernel\n", ps.ps_recv, ps.ps_drop);
345
346 return 0;
347 }
348
349