]> git.saurik.com Git - apple/network_cmds.git/blob - ecnprobe/capture.c
network_cmds-481.20.1.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 = 0;
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 device = pcap_lookupdev(errbuf);
86 if (device == NULL) {
87 fprintf(stderr, "Can't find capture device: %s\n", errbuf);
88 exit(-1);
89 }
90 }
91
92 if (captureDebug) {
93 printf("Device name is %s\n", device);
94 }
95 pc = pcap_open_live(device, snaplen, promisc, timeout, errbuf);
96 if (pc == NULL) {
97 fprintf(stderr,"Can't open capture device %s: %s\n",device, errbuf);
98 exit(-1);
99 }
100
101 /* XXX why do we need to do this? */
102 i = pcap_snapshot(pc);
103 if (snaplen < i) {
104 fprintf(stderr, "Warning: snaplen raised to %d from %d",
105 snaplen, i);
106 }
107
108 if ((i = pcap_datalink(pc)) < 0) {
109 fprintf(stderr,"Unable to determine datalink type for %s: %s\n",
110 device, errbuf);
111 exit(-1);
112 }
113
114 switch(i) {
115
116 case DLT_EN10MB: datalinkOffset = 14; break;
117 case DLT_IEEE802: datalinkOffset = 22; break;
118 case DLT_NULL: datalinkOffset = 4; break;
119 case DLT_SLIP:
120 case DLT_PPP: datalinkOffset = 24; break;
121 case DLT_RAW: datalinkOffset = 0; break;
122 default:
123 fprintf(stderr,"Unknown datalink type %d\n",i);
124 exit(-1);
125 break;
126
127 }
128
129 if (InetAddress(sourceIP) < 0) {
130 fprintf(stderr, "Invalid source IP address (%d)\n", sourceIP);
131 exit(-1);
132 }
133
134 strncpy(source, InetAddress(sourceIP), sizeof(source) - 1);
135 strncpy(target, InetAddress(targetIP), sizeof(target) - 1);
136
137 /* Setup initial filter */
138 sprintf(filtercmds,
139 "(host %s && host %s && port %d) || icmp\n",
140 source, target, targetPort);
141
142 if (captureDebug) {
143 printf("datalinkOffset = %d\n", datalinkOffset);
144 printf("filter = %s\n", filtercmds);
145 }
146 if (pcap_compile(pc, &filter, filtercmds, 1, netmask) < 0) {
147 printf("Error: %s", pcap_geterr(pc));
148 exit(-1);
149 }
150
151 if (pcap_setfilter(pc, &filter) < 0) {
152 fprintf(stderr, "Can't set filter: %s",pcap_geterr(pc));
153 exit(-1);
154 }
155
156 if (captureDebug) {
157 printf("Listening on %s...\n", device);
158 }
159
160 }
161
162 char *CaptureGetPacket(struct pcap_pkthdr *pi)
163 {
164
165 const u_char *p;
166
167 p = pcap_next(pc, (struct pcap_pkthdr *)pi);
168
169 if (p != NULL) {
170 p += datalinkOffset;
171 }
172
173 pi->ts.tv_sec = (pi->ts.tv_sec + thisTimeZone) % 86400;
174
175 return (char *)p;
176
177 }
178
179
180 void CaptureEnd()
181 {
182 struct pcap_stat stat;
183
184 if (pcap_stats(pc, &stat) < 0) {
185 (void)fprintf(stderr, "pcap_stats: %s\n", pcap_geterr(pc));
186 }
187 else {
188 (void)fprintf(stderr, "%d packets received by filter\n", stat.ps_recv);
189 (void)fprintf(stderr, "%d packets dropped by kernel\n", stat.ps_drop);
190 }
191
192 pcap_close(pc);
193 }
194