]> git.saurik.com Git - apple/network_cmds.git/blob - ecnprobe/capture.c
network_cmds-606.100.3.tar.gz
[apple/network_cmds.git] / ecnprobe / capture.c
1 /*
2 Copyright (c) 2000
3 International Computer Science Institute
4 All rights reserved.
5
6 This file may contain software code originally developed for the
7 Sting project. The Sting software carries the following copyright:
8
9 Copyright (c) 1998, 1999
10 Stefan Savage and the University of Washington.
11 All rights reserved.
12
13 Redistribution and use in source and binary forms, with or without
14 modification, are permitted provided that the following conditions
15 are met:
16 1. Redistributions of source code must retain the above copyright
17 notice, this list of conditions and the following disclaimer.
18 2. Redistributions in binary form must reproduce the above copyright
19 notice, this list of conditions and the following disclaimer in the
20 documentation and/or other materials provided with the distribution.
21 3. All advertising materials mentioning features or use of this software
22 must display the following acknowledgment:
23 This product includes software developed by ACIRI, the AT&T
24 Center for Internet Research at ICSI (the International Computer
25 Science Institute). This product may also include software developed
26 by Stefan Savage at the University of Washington.
27 4. The names of ACIRI, ICSI, Stefan Savage and University of Washington
28 may not be used to endorse or promote products derived from this software
29 without specific prior written permission.
30
31 THIS SOFTWARE IS PROVIDED BY ICSI AND CONTRIBUTORS ``AS IS'' AND
32 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34 ARE DISCLAIMED. IN NO EVENT SHALL ICSI OR CONTRIBUTORS BE LIABLE
35 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
40 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 SUCH DAMAGE.
42 */
43 #include <sys/types.h>
44 #include <sys/param.h>
45 #include <sys/time.h>
46 #include <string.h>
47 #include <stdlib.h>
48 #include <stdio.h>
49 #include "gmt2local.h"
50 #include "pcap.h"
51 #include "inet.h"
52 #include "capture.h"
53
54 /* set snaplen to max etherenet packet size */
55 #define DEFAULT_SNAPLEN 1500
56
57 pcap_t *pc; /* pcap device */
58 int datalinkOffset; /* offset of ip packet from datalink packet */
59 int captureDebug = 1;
60 unsigned int thisTimeZone;
61
62 void CaptureInit(u_int32_t sourceIP, u_int16_t sourcePort,
63 u_int32_t targetIP, u_int16_t targetPort, char *dev)
64 {
65
66 char *device = NULL;
67 char errbuf[PCAP_ERRBUF_SIZE];
68 int snaplen = DEFAULT_SNAPLEN;
69 int promisc = 1;
70 int timeout = 10; /* timeout in 1 second (10 ms) */
71 char filtercmds[255];
72 bpf_u_int32 netmask = 0;
73 struct bpf_program filter;
74 char source[18];
75 char target[18];
76 int i;
77
78 /* Get local time zone for interpreting timestamps */
79 /* XXX - does this belong here? */
80 thisTimeZone = gmt2local(0);
81
82 if (dev != NULL) {
83 device = dev;
84 } else {
85 pcap_if_t *devlist;
86 /*
87 * Find the list of interfaces, and pick
88 * the first interface.
89 */
90 if (pcap_findalldevs(&devlist, errbuf) >= 0 &&
91 devlist != NULL) {
92 device = strdup(devlist->name);
93 pcap_freealldevs(devlist);
94 }
95
96 if (device == NULL) {
97 fprintf(stderr, "Can't find capture device: %s\n", errbuf);
98 exit(-1);
99 }
100 }
101
102 if (captureDebug) {
103 printf("Device name is %s\n", device);
104 }
105 pc = pcap_open_live(device, snaplen, promisc, timeout, errbuf);
106 if (pc == NULL) {
107 fprintf(stderr,"Can't open capture device %s: %s\n",device, errbuf);
108 exit(-1);
109 }
110
111 /* XXX why do we need to do this? */
112 i = pcap_snapshot(pc);
113 if (snaplen < i) {
114 fprintf(stderr, "Warning: snaplen raised to %d from %d",
115 snaplen, i);
116 }
117
118 if ((i = pcap_datalink(pc)) < 0) {
119 fprintf(stderr,"Unable to determine datalink type for %s: %s\n",
120 device, errbuf);
121 exit(-1);
122 }
123
124 switch(i) {
125
126 case DLT_EN10MB: datalinkOffset = 14; break;
127 case DLT_IEEE802: datalinkOffset = 22; break;
128 case DLT_NULL: datalinkOffset = 4; break;
129 case DLT_SLIP:
130 case DLT_PPP: datalinkOffset = 24; break;
131 case DLT_RAW: datalinkOffset = 0; break;
132 default:
133 fprintf(stderr,"Unknown datalink type %d\n",i);
134 exit(-1);
135 break;
136
137 }
138
139 if (InetAddress(sourceIP) < 0) {
140 fprintf(stderr, "Invalid source IP address (%d)\n", sourceIP);
141 exit(-1);
142 }
143
144 strlcpy(source, InetAddress(sourceIP), sizeof(source));
145 strlcpy(target, InetAddress(targetIP), sizeof(target));
146
147 /* Setup initial filter */
148 sprintf(filtercmds,
149 "(host %s && host %s && port %d) || icmp\n",
150 source, target, targetPort);
151
152 if (captureDebug) {
153 printf("datalinkOffset = %d\n", datalinkOffset);
154 printf("filter = %s\n", filtercmds);
155 }
156 if (pcap_compile(pc, &filter, filtercmds, 1, netmask) < 0) {
157 printf("Error: %s", pcap_geterr(pc));
158 exit(-1);
159 }
160
161 if (pcap_setfilter(pc, &filter) < 0) {
162 fprintf(stderr, "Can't set filter: %s",pcap_geterr(pc));
163 exit(-1);
164 }
165
166 if (captureDebug) {
167 printf("Listening on %s...\n", device);
168 }
169
170 }
171
172 char *CaptureGetPacket(struct pcap_pkthdr *pi)
173 {
174
175 const u_char *p;
176
177 p = pcap_next(pc, (struct pcap_pkthdr *)pi);
178
179 if (p != NULL) {
180 p += datalinkOffset;
181 }
182
183 pi->ts.tv_sec = (pi->ts.tv_sec + thisTimeZone) % 86400;
184
185 return (char *)p;
186
187 }
188
189
190 void CaptureEnd()
191 {
192 struct pcap_stat stat;
193
194 if (pcap_stats(pc, &stat) < 0) {
195 (void)fprintf(stderr, "pcap_stats: %s\n", pcap_geterr(pc));
196 }
197 else {
198 (void)fprintf(stderr, "%d packets received by filter\n", stat.ps_recv);
199 (void)fprintf(stderr, "%d packets dropped by kernel\n", stat.ps_drop);
200 }
201
202 pcap_close(pc);
203 }
204