nexmon – Blame information for rev 1

Subversion Repositories:
Rev:
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 }