libpcap  1.10.1
About: libpcap is a packet filter library used by tools like tcpdump.
  Fossies Dox: libpcap-1.10.1.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

pcap-nit.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996
3  * The Regents of the University of California. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that: (1) source code distributions
7  * retain the above copyright notice and this paragraph in its entirety, (2)
8  * distributions including binary code include the above copyright notice and
9  * this paragraph in its entirety in the documentation or other materials
10  * provided with the distribution, and (3) all advertising materials mentioning
11  * features or use of this software display the following acknowledgement:
12  * ``This product includes software developed by the University of California,
13  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14  * the University nor the names of its contributors may be used to endorse
15  * or promote products derived from this software without specific prior
16  * written permission.
17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20  */
21 
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 
26 #include <sys/types.h>
27 #include <sys/time.h>
28 #include <sys/timeb.h>
29 #include <sys/file.h>
30 #include <sys/ioctl.h>
31 #include <sys/socket.h>
32 
33 #include <net/if.h>
34 #include <net/nit.h>
35 
36 #include <netinet/in.h>
37 #include <netinet/in_systm.h>
38 #include <netinet/ip.h>
39 #include <netinet/if_ether.h>
40 #include <netinet/ip_var.h>
41 #include <netinet/udp.h>
42 #include <netinet/udp_var.h>
43 #include <netinet/tcp.h>
44 #include <netinet/tcpip.h>
45 
46 #include <errno.h>
47 #include <stdio.h>
48 
49 #include "pcap-int.h"
50 
51 #ifdef HAVE_OS_PROTO_H
52 #include "os-proto.h"
53 #endif
54 
55 /*
56  * The chunk size for NIT. This is the amount of buffering
57  * done for read calls.
58  */
59 #define CHUNKSIZE (2*1024)
60 
61 /*
62  * The total buffer space used by NIT.
63  */
64 #define BUFSPACE (4*CHUNKSIZE)
65 
66 /* Forwards */
67 static int nit_setflags(int, int, int, char *);
68 
69 /*
70  * Private data for capturing on NIT devices.
71  */
72 struct pcap_nit {
73  struct pcap_stat stat;
74 };
75 
76 static int
78 {
79  struct pcap_nit *pn = p->priv;
80 
81  /*
82  * "ps_recv" counts packets handed to the filter, not packets
83  * that passed the filter. As filtering is done in userland,
84  * this does not include packets dropped because we ran out
85  * of buffer space.
86  *
87  * "ps_drop" presumably counts packets dropped by the socket
88  * because of flow control requirements or resource exhaustion;
89  * it doesn't count packets dropped by the interface driver.
90  * As filtering is done in userland, it counts packets regardless
91  * of whether they would've passed the filter.
92  *
93  * These statistics don't include packets not yet read from the
94  * kernel by libpcap or packets not yet read from libpcap by the
95  * application.
96  */
97  *ps = pn->stat;
98  return (0);
99 }
100 
101 static int
102 pcap_read_nit(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
103 {
104  struct pcap_nit *pn = p->priv;
105  register int cc, n;
106  register u_char *bp, *cp, *ep;
107  register struct nit_hdr *nh;
108  register int caplen;
109 
110  cc = p->cc;
111  if (cc == 0) {
112  cc = read(p->fd, (char *)p->buffer, p->bufsize);
113  if (cc < 0) {
114  if (errno == EWOULDBLOCK)
115  return (0);
116  pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
117  errno, "pcap_read");
118  return (-1);
119  }
120  bp = (u_char *)p->buffer;
121  } else
122  bp = p->bp;
123 
124  /*
125  * Loop through each packet. The increment expression
126  * rounds up to the next int boundary past the end of
127  * the previous packet.
128  */
129  n = 0;
130  ep = bp + cc;
131  while (bp < ep) {
132  /*
133  * Has "pcap_breakloop()" been called?
134  * If so, return immediately - if we haven't read any
135  * packets, clear the flag and return -2 to indicate
136  * that we were told to break out of the loop, otherwise
137  * leave the flag set, so that the *next* call will break
138  * out of the loop without having read any packets, and
139  * return the number of packets we've processed so far.
140  */
141  if (p->break_loop) {
142  if (n == 0) {
143  p->break_loop = 0;
144  return (-2);
145  } else {
146  p->cc = ep - bp;
147  p->bp = bp;
148  return (n);
149  }
150  }
151 
152  nh = (struct nit_hdr *)bp;
153  cp = bp + sizeof(*nh);
154 
155  switch (nh->nh_state) {
156 
157  case NIT_CATCH:
158  break;
159 
160  case NIT_NOMBUF:
161  case NIT_NOCLUSTER:
162  case NIT_NOSPACE:
163  pn->stat.ps_drop = nh->nh_dropped;
164  continue;
165 
166  case NIT_SEQNO:
167  continue;
168 
169  default:
170  snprintf(p->errbuf, sizeof(p->errbuf),
171  "bad nit state %d", nh->nh_state);
172  return (-1);
173  }
174  ++pn->stat.ps_recv;
175  bp += ((sizeof(struct nit_hdr) + nh->nh_datalen +
176  sizeof(int) - 1) & ~(sizeof(int) - 1));
177 
178  caplen = nh->nh_wirelen;
179  if (caplen > p->snapshot)
180  caplen = p->snapshot;
181  if (pcap_filter(p->fcode.bf_insns, cp, nh->nh_wirelen, caplen)) {
182  struct pcap_pkthdr h;
183  h.ts = nh->nh_timestamp;
184  h.len = nh->nh_wirelen;
185  h.caplen = caplen;
186  (*callback)(user, &h, cp);
187  if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
188  p->cc = ep - bp;
189  p->bp = bp;
190  return (n);
191  }
192  }
193  }
194  p->cc = 0;
195  return (n);
196 }
197 
198 static int
199 pcap_inject_nit(pcap_t *p, const void *buf, int size)
200 {
201  struct sockaddr sa;
202  int ret;
203 
204  memset(&sa, 0, sizeof(sa));
205  strncpy(sa.sa_data, device, sizeof(sa.sa_data));
206  ret = sendto(p->fd, buf, size, 0, &sa, sizeof(sa));
207  if (ret == -1) {
209  errno, "send");
210  return (-1);
211  }
212  return (ret);
213 }
214 
215 static int
217 {
218  struct nit_ioc nioc;
219 
220  memset(&nioc, 0, sizeof(nioc));
221  nioc.nioc_typetomatch = NT_ALLTYPES;
222  nioc.nioc_snaplen = p->snapshot;
223  nioc.nioc_bufalign = sizeof(int);
224  nioc.nioc_bufoffset = 0;
225 
226  if (p->opt.buffer_size != 0)
227  nioc.nioc_bufspace = p->opt.buffer_size;
228  else {
229  /* Default buffer size */
230  nioc.nioc_bufspace = BUFSPACE;
231  }
232 
233  if (p->opt.immediate) {
234  /*
235  * XXX - will this cause packets to be delivered immediately?
236  * XXX - given that this is for SunOS prior to 4.0, do
237  * we care?
238  */
239  nioc.nioc_chunksize = 0;
240  } else
241  nioc.nioc_chunksize = CHUNKSIZE;
242  if (p->opt.timeout != 0) {
243  nioc.nioc_flags |= NF_TIMEOUT;
244  nioc.nioc_timeout.tv_sec = p->opt.timeout / 1000;
245  nioc.nioc_timeout.tv_usec = (p->opt.timeout * 1000) % 1000000;
246  }
247  if (p->opt.promisc)
248  nioc.nioc_flags |= NF_PROMISC;
249 
250  if (ioctl(p->fd, SIOCSNIT, &nioc) < 0) {
252  errno, "SIOCSNIT");
253  return (-1);
254  }
255  return (0);
256 }
257 
258 static int
260 {
261  int fd;
262  struct sockaddr_nit snit;
263 
264  if (p->opt.rfmon) {
265  /*
266  * No monitor mode on SunOS 3.x or earlier (no
267  * Wi-Fi *devices* for the hardware that supported
268  * them!).
269  */
270  return (PCAP_ERROR_RFMON_NOTSUP);
271  }
272 
273  /*
274  * Turn a negative snapshot value (invalid), a snapshot value of
275  * 0 (unspecified), or a value bigger than the normal maximum
276  * value, into the maximum allowed value.
277  *
278  * If some application really *needs* a bigger snapshot
279  * length, we should just increase MAXIMUM_SNAPLEN.
280  */
281  if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
283 
284  if (p->snapshot < 96)
285  /*
286  * NIT requires a snapshot length of at least 96.
287  */
288  p->snapshot = 96;
289 
290  memset(p, 0, sizeof(*p));
291  p->fd = fd = socket(AF_NIT, SOCK_RAW, NITPROTO_RAW);
292  if (fd < 0) {
294  errno, "socket");
295  goto bad;
296  }
297  snit.snit_family = AF_NIT;
298  (void)strncpy(snit.snit_ifname, p->opt.device, NITIFSIZ);
299 
300  if (bind(fd, (struct sockaddr *)&snit, sizeof(snit))) {
301  /*
302  * XXX - there's probably a particular bind error that
303  * means "there's no such device" and a particular bind
304  * error that means "that device doesn't support NIT";
305  * they might be the same error, if they both end up
306  * meaning "NIT doesn't know about that device".
307  */
309  errno, "bind: %s", snit.snit_ifname);
310  goto bad;
311  }
312  if (nit_setflags(p) < 0)
313  goto bad;
314 
315  /*
316  * NIT supports only ethernets.
317  */
318  p->linktype = DLT_EN10MB;
319 
320  p->bufsize = BUFSPACE;
321  p->buffer = malloc(p->bufsize);
322  if (p->buffer == NULL) {
324  errno, "malloc");
325  goto bad;
326  }
327 
328  /*
329  * "p->fd" is a socket, so "select()" should work on it.
330  */
331  p->selectable_fd = p->fd;
332 
333  /*
334  * This is (presumably) a real Ethernet capture; give it a
335  * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
336  * that an application can let you choose it, in case you're
337  * capturing DOCSIS traffic that a Cisco Cable Modem
338  * Termination System is putting out onto an Ethernet (it
339  * doesn't put an Ethernet header onto the wire, it puts raw
340  * DOCSIS frames out on the wire inside the low-level
341  * Ethernet framing).
342  */
343  p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
344  /*
345  * If that fails, just leave the list empty.
346  */
347  if (p->dlt_list != NULL) {
348  p->dlt_list[0] = DLT_EN10MB;
349  p->dlt_list[1] = DLT_DOCSIS;
350  p->dlt_count = 2;
351  }
352 
353  p->read_op = pcap_read_nit;
355  p->setfilter_op = install_bpf_program; /* no kernel filtering */
356  p->setdirection_op = NULL; /* Not implemented. */
357  p->set_datalink_op = NULL; /* can't change data link type */
361 
362  return (0);
363  bad:
365  return (PCAP_ERROR);
366 }
367 
368 pcap_t *
369 pcap_create_interface(const char *device _U_, char *ebuf)
370 {
371  pcap_t *p;
372 
373  p = PCAP_CREATE_COMMON(ebuf, struct pcap_nit);
374  if (p == NULL)
375  return (NULL);
376 
378  return (p);
379 }
380 
381 /*
382  * XXX - there's probably a particular bind error that means "that device
383  * doesn't support NIT"; if so, we should try a bind and use that.
384  */
385 static int
386 can_be_bound(const char *name _U_)
387 {
388  return (1);
389 }
390 
391 static int
392 get_if_flags(const char *name _U_, bpf_u_int32 *flags _U_, char *errbuf _U_)
393 {
394  /*
395  * Nothing we can do.
396  * XXX - is there a way to find out whether an adapter has
397  * something plugged into it?
398  */
399  return (0);
400 }
401 
402 int
403 pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
404 {
405  return (pcap_findalldevs_interfaces(devlistp, errbuf, can_be_bound,
406  get_if_flags));
407 }
408 
409 /*
410  * Libpcap version string.
411  */
412 const char *
414 {
415  return (PCAP_VERSION_STRING);
416 }
u_int bpf_u_int32
Definition: bpf.h:98
u_int pcap_filter(const struct bpf_insn *pc, const u_char *p, u_int wirelen, u_int buflen)
Definition: bpf_filter.c:391
#define DLT_EN10MB
Definition: dlt.h:63
#define DLT_DOCSIS
Definition: dlt.h:465
int pcap_findalldevs_interfaces(pcap_if_list_t *devlistp, char *errbuf, int(*check_usable)(const char *), get_if_flags_func get_flags_func)
Definition: fad-getad.c:146
void pcap_fmt_errmsg_for_errno(char *errbuf, size_t errbuflen, int errnum, const char *fmt,...)
Definition: fmtutils.c:269
int install_bpf_program(pcap_t *p, struct bpf_program *fp)
Definition: optimize.c:2939
int snprintf(char *, size_t, const char *,...)
int ioctl(int, int, caddr_t)
int read(int, char *, u_int)
int sendto(int, char *, u_int, int, struct sockaddr *, int)
int socket(int, int, int)
int bind(int, struct sockaddr *, int)
#define _U_
Definition: pcap-dos.h:93
int errno
#define MAXIMUM_SNAPLEN
Definition: pcap-int.h:131
#define PACKET_COUNT_IS_UNLIMITED(count)
Definition: pcap-int.h:444
void pcap_cleanup_live_common(pcap_t *)
Definition: pcap.c:3987
int pcap_getnonblock_fd(pcap_t *)
Definition: pcap.c:3537
int pcap_setnonblock_fd(pcap_t *p, int)
Definition: pcap.c:3583
#define PCAP_VERSION_STRING
Definition: pcap-int.h:59
#define PCAP_CREATE_COMMON(ebuf, type)
Definition: pcap-int.h:474
static int get_if_flags(const char *name, bpf_u_int32 *flags, char *errbuf)
Definition: pcap-nit.c:392
#define CHUNKSIZE
Definition: pcap-nit.c:59
const char * pcap_lib_version(void)
Definition: pcap-nit.c:413
static int pcap_read_nit(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
Definition: pcap-nit.c:102
static int nit_setflags(int, int, int, char *)
static int pcap_stats_nit(pcap_t *p, struct pcap_stat *ps)
Definition: pcap-nit.c:77
int pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
Definition: pcap-nit.c:403
pcap_t * pcap_create_interface(const char *device, char *ebuf)
Definition: pcap-nit.c:369
static int can_be_bound(const char *name)
Definition: pcap-nit.c:386
static int pcap_activate_nit(pcap_t *p)
Definition: pcap-nit.c:259
#define BUFSPACE
Definition: pcap-nit.c:64
static int pcap_inject_nit(pcap_t *p, const void *buf, int size)
Definition: pcap-nit.c:199
#define PCAP_ERROR_RFMON_NOTSUP
Definition: pcap.h:344
void(* pcap_handler)(u_char *, const struct pcap_pkthdr *, const u_char *)
Definition: pcap.h:330
#define PCAP_ERRBUF_SIZE
Definition: pcap.h:152
#define PCAP_ERROR
Definition: pcap.h:339
struct bpf_insn * bf_insns
Definition: bpf.h:119
struct pcap_stat stat
Definition: pcap-nit.c:73
int timeout
Definition: pcap-int.h:147
char * device
Definition: pcap-int.h:146
int rfmon
Definition: pcap-int.h:150
int immediate
Definition: pcap-int.h:151
int promisc
Definition: pcap-int.h:149
u_int buffer_size
Definition: pcap-int.h:148
bpf_u_int32 caplen
Definition: pcap.h:247
struct timeval ts
Definition: pcap.h:246
bpf_u_int32 len
Definition: pcap.h:248
u_int ps_drop
Definition: pcap.h:256
u_int ps_recv
Definition: pcap.h:255
Definition: pcap-int.h:200
stats_op_t stats_op
Definition: pcap-int.h:320
activate_op_t activate_op
Definition: pcap-int.h:311
setnonblock_op_t setnonblock_op
Definition: pcap-int.h:319
setfilter_op_t setfilter_op
Definition: pcap-int.h:315
sig_atomic_t break_loop
Definition: pcap-int.h:225
int dlt_count
Definition: pcap-int.h:299
u_int bufsize
Definition: pcap-int.h:220
void * priv
Definition: pcap-int.h:227
getnonblock_op_t getnonblock_op
Definition: pcap-int.h:318
u_int * dlt_list
Definition: pcap-int.h:300
read_op_t read_op
Definition: pcap-int.h:204
void * buffer
Definition: pcap-int.h:221
u_char * bp
Definition: pcap-int.h:222
int snapshot
Definition: pcap-int.h:247
setdirection_op_t setdirection_op
Definition: pcap-int.h:316
inject_op_t inject_op
Definition: pcap-int.h:313
int cc
Definition: pcap-int.h:223
struct bpf_program fcode
Definition: pcap-int.h:293
set_datalink_op_t set_datalink_op
Definition: pcap-int.h:317
char errbuf[256+1]
Definition: pcap-int.h:295
int linktype
Definition: pcap-int.h:248
int selectable_fd
Definition: pcap-int.h:274
int fd
Definition: pcap-int.h:214
struct pcap_opt opt
Definition: pcap-int.h:254