2 * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)
3 * Copyright (c) 2005 - 2008 CACE Technologies, Davis (California)
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the Politecnico di Torino, CACE Technologies
16 * nor the names of its contributors may be used to endorse or promote
17 * products derived from this software without specific prior written
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 #include "diag-control.h"
42 * sockutils.h may include <crtdbg.h> on Windows, and pcap-int.h will
43 * include portability.h, and portability.h, on Windows, expects that
44 * <crtdbg.h> has already been included, so include sockutils.h first.
46 #include "sockutils.h"
47 #include "pcap-int.h" // for the details of the pcap_t structure
48 #include "pcap-rpcap.h"
49 #include "rpcap-protocol.h"
50 #include <errno.h> // for the errno variable
51 #include <stdlib.h> // for malloc(), free(), ...
52 #include <string.h> // for strstr, etc
55 #include <dirent.h> // for readdir
58 /* String identifier to be used in the pcap_findalldevs_ex() */
59 #define PCAP_TEXT_SOURCE_FILE "File"
60 #define PCAP_TEXT_SOURCE_FILE_LEN (sizeof PCAP_TEXT_SOURCE_FILE - 1)
61 /* String identifier to be used in the pcap_findalldevs_ex() */
62 #define PCAP_TEXT_SOURCE_ADAPTER "Network adapter"
63 #define PCAP_TEXT_SOURCE_ADAPTER_LEN (sizeof "Network adapter" - 1)
65 /* String identifier to be used in the pcap_findalldevs_ex() */
66 #define PCAP_TEXT_SOURCE_ON_LOCAL_HOST "on local host"
67 #define PCAP_TEXT_SOURCE_ON_LOCAL_HOST_LEN (sizeof PCAP_TEXT_SOURCE_ON_LOCAL_HOST + 1)
69 /****************************************************
73 ****************************************************/
75 int pcap_findalldevs_ex(const char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf)
78 char name[PCAP_BUF_SIZE], path[PCAP_BUF_SIZE], filename[PCAP_BUF_SIZE];
82 char tmpstring[PCAP_BUF_SIZE + 1]; /* Needed to convert names and descriptions from 'old' syntax to the 'new' one */
83 pcap_if_t *lastdev; /* Last device in the pcap_if_t list */
84 pcap_if_t *dev; /* Device we're adding to the pcap_if_t list */
86 /* List starts out empty. */
90 if (strlen(source) > PCAP_BUF_SIZE)
92 snprintf(errbuf, PCAP_ERRBUF_SIZE, "The source string is too long. Cannot handle it correctly.");
97 * Determine the type of the source (file, local, remote)
98 * There are some differences if pcap_findalldevs_ex() is called to list files and remote adapters.
99 * In the first case, the name of the directory we have to look into must be present (therefore
100 * the 'name' parameter of the pcap_parsesrcstr() is present).
101 * In the second case, the name of the adapter is not required (we need just the host). So, we have
102 * to use a first time this function to get the source type, and a second time to get the appropriate
103 * info, which depends on the source type.
105 if (pcap_parsesrcstr(source, &type, NULL, NULL, NULL, errbuf) == -1)
110 case PCAP_SRC_IFLOCAL:
111 if (pcap_parsesrcstr(source, &type, NULL, NULL, NULL, errbuf) == -1)
114 /* Initialize temporary string */
115 tmpstring[PCAP_BUF_SIZE] = 0;
117 /* The user wants to retrieve adapters from a local host */
118 if (pcap_findalldevs(alldevs, errbuf) == -1)
121 if (*alldevs == NULL)
123 snprintf(errbuf, PCAP_ERRBUF_SIZE,
124 "No interfaces found! Make sure libpcap/Npcap is properly installed"
125 " on the local machine.");
129 /* Scan all the interfaces and modify name and description */
130 /* This is a trick in order to avoid the re-implementation of the pcap_findalldevs here */
134 char *localdesc, *desc;
136 /* Create the new device identifier */
137 if (pcap_createsrcstr(tmpstring, PCAP_SRC_IFLOCAL, NULL, NULL, dev->name, errbuf) == -1)
140 /* Delete the old pointer */
143 /* Make a copy of the new device identifier */
144 dev->name = strdup(tmpstring);
145 if (dev->name == NULL)
147 pcap_fmt_errmsg_for_errno(errbuf,
148 PCAP_ERRBUF_SIZE, errno,
150 pcap_freealldevs(*alldevs);
155 * Create the description.
157 if ((dev->description == NULL) || (dev->description[0] == 0))
158 localdesc = dev->name;
160 localdesc = dev->description;
161 if (pcap_asprintf(&desc, "%s '%s' %s",
162 PCAP_TEXT_SOURCE_ADAPTER, localdesc,
163 PCAP_TEXT_SOURCE_ON_LOCAL_HOST) == -1)
165 pcap_fmt_errmsg_for_errno(errbuf,
166 PCAP_ERRBUF_SIZE, errno,
168 pcap_freealldevs(*alldevs);
172 /* Now overwrite the description */
173 free(dev->description);
174 dev->description = desc;
184 WIN32_FIND_DATA filedata;
187 struct dirent *filedata;
191 if (pcap_parsesrcstr(source, &type, NULL, NULL, name, errbuf) == -1)
194 /* Check that the filename is correct */
195 stringlen = strlen(name);
197 /* The directory must end with '\' in Win32 and '/' in UNIX */
199 #define ENDING_CHAR '\\'
201 #define ENDING_CHAR '/'
204 if (name[stringlen - 1] != ENDING_CHAR)
206 name[stringlen] = ENDING_CHAR;
207 name[stringlen + 1] = 0;
212 /* Save the path for future reference */
213 snprintf(path, sizeof(path), "%s", name);
214 pathlen = strlen(path);
217 /* To perform directory listing, Win32 must have an 'asterisk' as ending char */
218 if (name[stringlen - 1] != '*')
220 name[stringlen] = '*';
221 name[stringlen + 1] = 0;
224 filehandle = FindFirstFile(name, &filedata);
226 if (filehandle == INVALID_HANDLE_VALUE)
228 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error when listing files: does folder '%s' exist?", path);
233 /* opening the folder */
234 unixdir= opendir(path);
236 /* get the first file into it */
237 filedata= readdir(unixdir);
239 if (filedata == NULL)
241 DIAG_OFF_FORMAT_TRUNCATION
242 snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error when listing files: does folder '%s' exist?", path);
243 DIAG_ON_FORMAT_TRUNCATION
249 /* Add all files we find to the list. */
253 /* Skip the file if the pathname won't fit in the buffer */
254 if (pathlen + strlen(filedata.cFileName) >= sizeof(filename))
256 snprintf(filename, sizeof(filename), "%s%s", path, filedata.cFileName);
258 if (pathlen + strlen(filedata->d_name) >= sizeof(filename))
260 DIAG_OFF_FORMAT_TRUNCATION
261 snprintf(filename, sizeof(filename), "%s%s", path, filedata->d_name);
262 DIAG_ON_FORMAT_TRUNCATION
265 fp = pcap_open_offline(filename, errbuf);
269 /* allocate the main structure */
270 dev = (pcap_if_t *)malloc(sizeof(pcap_if_t));
273 pcap_fmt_errmsg_for_errno(errbuf,
274 PCAP_ERRBUF_SIZE, errno,
276 pcap_freealldevs(*alldevs);
278 FindClose(filehandle);
285 /* Initialize the structure to 'zero' */
286 memset(dev, 0, sizeof(pcap_if_t));
288 /* Append it to the list. */
292 * List is empty, so it's also
300 * Append after the last device.
304 /* It's now the last device. */
307 /* Create the new source identifier */
308 if (pcap_createsrcstr(tmpstring, PCAP_SRC_FILE, NULL, NULL, filename, errbuf) == -1)
310 pcap_freealldevs(*alldevs);
312 FindClose(filehandle);
319 dev->name = strdup(tmpstring);
320 if (dev->name == NULL)
322 pcap_fmt_errmsg_for_errno(errbuf,
323 PCAP_ERRBUF_SIZE, errno,
325 pcap_freealldevs(*alldevs);
327 FindClose(filehandle);
335 * Create the description.
337 if (pcap_asprintf(&dev->description,
338 "%s '%s' %s", PCAP_TEXT_SOURCE_FILE,
339 filename, PCAP_TEXT_SOURCE_ON_LOCAL_HOST) == -1)
341 pcap_fmt_errmsg_for_errno(errbuf,
342 PCAP_ERRBUF_SIZE, errno,
344 pcap_freealldevs(*alldevs);
346 FindClose(filehandle);
357 while (FindNextFile(filehandle, &filedata) != 0);
359 while ( (filedata= readdir(unixdir)) != NULL);
363 /* Close the search handle. */
365 FindClose(filehandle);
373 case PCAP_SRC_IFREMOTE:
374 return pcap_findalldevs_ex_remote(source, auth, alldevs, errbuf);
377 pcap_strlcpy(errbuf, "Source type not supported", PCAP_ERRBUF_SIZE);
382 pcap_t *pcap_open(const char *source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth *auth, char *errbuf)
384 char name[PCAP_BUF_SIZE];
390 * A null device name is equivalent to the "any" device -
391 * which might not be supported on this platform, but
392 * this means that you'll get a "not supported" error
393 * rather than, say, a crash when we try to dereference
399 if (strlen(source) > PCAP_BUF_SIZE)
401 snprintf(errbuf, PCAP_ERRBUF_SIZE, "The source string is too long. Cannot handle it correctly.");
406 * Determine the type of the source (file, local, remote) and,
407 * if it's file or local, the name of the file or capture device.
409 if (pcap_parsesrcstr(source, &type, NULL, NULL, name, errbuf) == -1)
415 return pcap_open_offline(name, errbuf);
417 case PCAP_SRC_IFLOCAL:
418 fp = pcap_create(name, errbuf);
421 case PCAP_SRC_IFREMOTE:
423 * Although we already have host, port and iface, we prefer
424 * to pass only 'source' to pcap_open_rpcap(), so that it
425 * has to call pcap_parsesrcstr() again.
426 * This is less optimized, but much clearer.
428 return pcap_open_rpcap(source, snaplen, flags, read_timeout, auth, errbuf);
431 pcap_strlcpy(errbuf, "Source type not supported", PCAP_ERRBUF_SIZE);
437 status = pcap_set_snaplen(fp, snaplen);
440 if (flags & PCAP_OPENFLAG_PROMISCUOUS)
442 status = pcap_set_promisc(fp, 1);
446 if (flags & PCAP_OPENFLAG_MAX_RESPONSIVENESS)
448 status = pcap_set_immediate_mode(fp, 1);
454 * This flag is supported on Windows only.
455 * XXX - is there a way to support it with
456 * the capture mechanisms on UN*X? It's not
457 * exactly a "set direction" operation; I
458 * think it means "do not capture packets
459 * injected with pcap_sendpacket() or
462 /* disable loopback capture if requested */
463 if (flags & PCAP_OPENFLAG_NOCAPTURE_LOCAL)
464 fp->opt.nocapture_local = 1;
466 status = pcap_set_timeout(fp, read_timeout);
469 status = pcap_activate(fp);
475 DIAG_OFF_FORMAT_TRUNCATION
476 if (status == PCAP_ERROR)
477 snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
479 else if (status == PCAP_ERROR_NO_SUCH_DEVICE ||
480 status == PCAP_ERROR_PERM_DENIED ||
481 status == PCAP_ERROR_PROMISC_PERM_DENIED)
482 snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%s)",
483 name, pcap_statustostr(status), fp->errbuf);
485 snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
486 name, pcap_statustostr(status));
487 DIAG_ON_FORMAT_TRUNCATION
492 struct pcap_samp *pcap_setsampling(pcap_t *p)