nexmon – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | /* pingreply.c - Ping reply |
2 | * |
||
3 | * DESCIPTION |
||
4 | * |
||
5 | * Replies to all ping requests. Useful for testing sniffing/injecting |
||
6 | * packets with airtun-ng. |
||
7 | * |
||
8 | * USAGE |
||
9 | * |
||
10 | * ./pingreply <iface> |
||
11 | * |
||
12 | * INSTALL |
||
13 | * |
||
14 | * cc -lpcap -o pingreply pingreply.c |
||
15 | * |
||
16 | * LICENSE |
||
17 | * |
||
18 | * Copyright (c) 2015, Jorn van Engelen <spamme@quzart.com> |
||
19 | * All rights reserved. |
||
20 | * |
||
21 | * Redistribution and use in source and binary forms, with or without |
||
22 | * modification, are permitted provided that the following conditions |
||
23 | * are met: |
||
24 | * 1. Redistributions of source code must retain the above copyright |
||
25 | * notice unmodified, this list of conditions, and the following |
||
26 | * disclaimer. |
||
27 | * 2. Redistributions in binary form must reproduce the above copyright |
||
28 | * notice, this list of conditions and the following disclaimer in the |
||
29 | * documentation and/or other materials provided with the distribution. |
||
30 | * |
||
31 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
||
32 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
||
33 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
||
34 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
||
35 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
||
36 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
||
37 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
||
38 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||
39 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
||
40 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
41 | */ |
||
42 | |||
43 | #include <stdio.h> |
||
44 | #include <stdlib.h> |
||
45 | #include <string.h> |
||
46 | #include <assert.h> |
||
47 | #include <unistd.h> |
||
48 | #include <pcap.h> |
||
49 | #include <arpa/inet.h> |
||
50 | |||
51 | |||
52 | struct eth_hdr { |
||
53 | unsigned char dst[6]; |
||
54 | unsigned char src[6]; |
||
55 | unsigned short type; |
||
56 | }; |
||
57 | |||
58 | struct ip_hdr { |
||
59 | unsigned char vhl; |
||
60 | unsigned char tos; |
||
61 | unsigned short length; |
||
62 | unsigned short id; |
||
63 | unsigned short off; |
||
64 | unsigned char ttl; |
||
65 | unsigned char proto; |
||
66 | unsigned short chksum; |
||
67 | unsigned char src[4]; |
||
68 | unsigned char dst[4]; |
||
69 | }; |
||
70 | |||
71 | struct icmp_hdr { |
||
72 | unsigned char type; |
||
73 | unsigned char code; |
||
74 | unsigned short chksum; |
||
75 | unsigned short id; |
||
76 | unsigned short seq; |
||
77 | unsigned char data[]; |
||
78 | }; |
||
79 | |||
80 | struct eth_ip_icmp_reply { |
||
81 | struct eth_hdr eth; |
||
82 | struct ip_hdr ip; |
||
83 | struct icmp_hdr icmp; |
||
84 | }; |
||
85 | |||
86 | |||
87 | |||
88 | pcap_t *p; |
||
89 | char errbuf[PCAP_ERRBUF_SIZE]; |
||
90 | |||
91 | |||
92 | short internet_chksum( unsigned char *hdr, int len ) |
||
93 | { |
||
94 | unsigned int sum = 0; |
||
95 | |||
96 | while ( len > 1 ) |
||
97 | { |
||
98 | sum += * (unsigned short*) hdr; |
||
99 | hdr += 2; |
||
100 | len -= 2; |
||
101 | } |
||
102 | |||
103 | if ( len > 0 ) |
||
104 | sum += * (unsigned char*) hdr; |
||
105 | |||
106 | while ( sum >> 16 ) |
||
107 | sum = (sum >> 16) + (sum & 0xffff); |
||
108 | |||
109 | return ~sum; |
||
110 | } |
||
111 | |||
112 | void reply_icmp_echo( |
||
113 | const struct eth_hdr *eth, |
||
114 | const struct ip_hdr *ip, |
||
115 | const struct icmp_hdr *icmp, |
||
116 | int len) |
||
117 | { |
||
118 | unsigned char *ptr; |
||
119 | struct eth_ip_icmp_reply *reply; |
||
120 | |||
121 | reply = (struct eth_ip_icmp_reply*) calloc( sizeof(struct eth_ip_icmp_reply) + len, 1 ); |
||
122 | assert( reply != NULL ); |
||
123 | |||
124 | memcpy( reply->eth.src, eth->dst, 6 ); |
||
125 | memcpy( reply->eth.dst, eth->src, 6 ); |
||
126 | reply->eth.type = htons(0x0800); |
||
127 | |||
128 | reply->ip.vhl = 0x45; |
||
129 | reply->ip.length = htons(sizeof(struct ip_hdr) + sizeof(struct icmp_hdr) + len); |
||
130 | reply->ip.id = htons(0xCAFE); |
||
131 | reply->ip.ttl = 0x80; |
||
132 | reply->ip.proto = 0x01; |
||
133 | memcpy( reply->ip.src, ip->dst, 4 ); |
||
134 | memcpy( reply->ip.dst, ip->src, 4 ); |
||
135 | |||
136 | reply->icmp.type = 0x00; |
||
137 | reply->icmp.code = 0x00; |
||
138 | reply->icmp.id = icmp->id; |
||
139 | reply->icmp.seq = icmp->seq; |
||
140 | memcpy( reply->icmp.data, icmp->data, len ); |
||
141 | |||
142 | reply->ip.chksum = internet_chksum( (unsigned char*) &(reply->ip), sizeof(struct ip_hdr) ); |
||
143 | reply->icmp.chksum = internet_chksum( (unsigned char*) &(reply->icmp), sizeof(struct icmp_hdr) + len ); |
||
144 | |||
145 | printf( "Sent icmp echo reply to: %i.%i.%i.%i.\n", ip->src[0], ip->src[1], ip->src[2], ip->src[3] ); |
||
146 | |||
147 | if ( pcap_inject( p, reply, sizeof(struct eth_ip_icmp_reply) + len ) == -1 ) |
||
148 | { |
||
149 | fprintf( stderr, "Could not inject packet: %s\n", pcap_geterr( p ) ); |
||
150 | } |
||
151 | |||
152 | free( reply ); |
||
153 | } |
||
154 | |||
155 | |||
156 | void receive_packet( |
||
157 | unsigned char *args, |
||
158 | const struct pcap_pkthdr *header, |
||
159 | const unsigned char *packet) |
||
160 | { |
||
161 | int len = header->caplen; |
||
162 | int ip_hdr_len; |
||
163 | const struct eth_hdr *eth; |
||
164 | const struct ip_hdr *ip; |
||
165 | const struct icmp_hdr *icmp; |
||
166 | |||
167 | len -= sizeof(struct eth_hdr); |
||
168 | if ( len < 0 ) |
||
169 | return; |
||
170 | |||
171 | eth = (struct eth_hdr*) packet; |
||
172 | packet += sizeof(struct eth_hdr); |
||
173 | |||
174 | /* Packet must be IPv4 */ |
||
175 | if ( ntohs(eth->type) != 0x0800 ) |
||
176 | return; |
||
177 | |||
178 | if ( len < sizeof(struct ip_hdr) ) |
||
179 | return; |
||
180 | |||
181 | ip = (struct ip_hdr*) packet; |
||
182 | if ( ntohs( ip->length ) != len ) |
||
183 | return; |
||
184 | if ( ip->vhl >> 4 != 4 ) |
||
185 | return; |
||
186 | |||
187 | ip_hdr_len = ( ip->vhl & 0x0F ) * 4; |
||
188 | if ( ip_hdr_len < sizeof(struct ip_hdr) ) |
||
189 | return; |
||
190 | |||
191 | len -= ip_hdr_len; |
||
192 | if ( len < 0 ) |
||
193 | return; |
||
194 | |||
195 | packet += ip_hdr_len; |
||
196 | |||
197 | /* Packet must be ICMP */ |
||
198 | if ( ip->proto != 0x01 ) |
||
199 | return; |
||
200 | |||
201 | len -= sizeof(struct icmp_hdr); |
||
202 | if ( len < 0 ) |
||
203 | return; |
||
204 | |||
205 | icmp = (struct icmp_hdr*) packet; |
||
206 | packet += sizeof(struct icmp_hdr); |
||
207 | |||
208 | /* Packet must be echo request */ |
||
209 | if ( ! ( icmp->type == 0x08 && icmp->code == 0x00 ) ) |
||
210 | return; |
||
211 | |||
212 | usleep( 2000 ); |
||
213 | |||
214 | reply_icmp_echo( eth, ip, icmp, len ); |
||
215 | } |
||
216 | |||
217 | int main( int argc, char *argv[] ) |
||
218 | { |
||
219 | struct bpf_program fp; |
||
220 | |||
221 | if ( argc != 2 ) |
||
222 | { |
||
223 | fprintf( stderr, "Usage: pingrep <dev>\n" ); |
||
224 | return 2; |
||
225 | } |
||
226 | |||
227 | p = pcap_open_live( argv[1], 1024, 1, 0, errbuf ); |
||
228 | if ( p == NULL ) |
||
229 | { |
||
230 | fprintf( stderr, "Could not open device %s: %s\n", argv[1], errbuf ); |
||
231 | return 2; |
||
232 | } |
||
233 | |||
234 | if ( pcap_datalink( p ) != DLT_EN10MB ) |
||
235 | { |
||
236 | fprintf( stderr, "Expected Ethernet from device %s.\n", argv[1] ); |
||
237 | return 2; |
||
238 | } |
||
239 | |||
240 | if ( pcap_compile( p, &fp, "icmp[icmptype] = icmp-echo", 0, PCAP_NETMASK_UNKNOWN ) == -1 ) |
||
241 | { |
||
242 | fprintf( stderr, "Could not parse filter: %s\n", pcap_geterr( p ) ); |
||
243 | return 2; |
||
244 | } |
||
245 | |||
246 | if ( pcap_setfilter( p, &fp ) == -1 ) |
||
247 | { |
||
248 | fprintf( stderr, "Could not install filter: %s\n", pcap_geterr( p ) ); |
||
249 | return 2; |
||
250 | } |
||
251 | |||
252 | printf( "Receiving packets ...\n" ); |
||
253 | pcap_loop( p, 0, receive_packet, NULL ); |
||
254 | |||
255 | pcap_freecode( &fp ); |
||
256 | pcap_close( p ); |
||
257 | |||
258 | printf( "Done.\n" ); |
||
259 | |||
260 | return 0; |
||
261 | } |