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