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
|
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <linux/ip.h>
#include <linux/icmp.h>
#include <linux/tcp.h>
#include "icmp.h"
#define BUFSIZE (10*1024)
static int icmp_socket = -1;
guint16 ipsum(guint8 *p, guint l) {
guint32 sum = 0;
guint i;
for (i = 0; i < l-1; i += 2)
sum += (p[i] << 8) + p[i+1];
if (i < l)
sum += p[i] << 8;
sum = (sum & 0xFFFF) + (sum >> 16);
sum = (sum & 0xFFFF) + (sum >> 16);
return ~sum;
}
int reply_icmp_error(ipq_packet_msg_t *m, int code) {
static guint8 buf[BUFSIZE];
struct iphdr* ip = (struct iphdr*) m->payload;
struct icmphdr *icmp = (struct icmphdr*) buf;
guint l, tl;
struct sockaddr_in sa;
icmp->type = 3;
icmp->code = code;
icmp->checksum = 0;
icmp->un.frag.__unused = 0;
icmp->un.frag.mtu = 0;
l = ip->ihl*4 + 8;
memcpy(&buf[sizeof(struct icmphdr)], m->payload, l);
tl = l + sizeof(struct icmphdr);
icmp->checksum = htons(ipsum((guint8*) icmp, tl));
sa.sin_family = AF_INET;
sa.sin_port = 0;
sa.sin_addr.s_addr = ip->saddr;
if (sendto(icmp_socket, icmp, tl, 0, (struct sockaddr*) &sa, sizeof(sa)) < 0) {
perror("sendto()");
return -1;
}
return 0;
}
int icmp_init() {
int enable = 1;
if ((icmp_socket = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0) {
perror("socket(PF_INET, SOCK_RAW, IPPROTO_ICMP)");
return -1;
}
if (setsockopt(icmp_socket, SOL_SOCKET, SO_BROADCAST, (char *)&enable, sizeof(enable)) < 0) {
perror("setsockopt(.., SOL_SOCKET, SO_BROADCAST)");
return -1;
}
return 0;
}
void icmp_done() {
if (icmp_socket >= 0)
close(icmp_socket);
icmp_socket = -1;
}
|