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.
41 * sockutils.h may include <crtdbg.h> on Windows, and pcap-int.h will
42 * include portability.h, and portability.h, on Windows, expects that
43 * <crtdbg.h> has already been included, so include sockutils.h first.
45 #include "sockutils.h"
46 #include "pcap-int.h" // for the details of the pcap_t structure
47 #include "pcap-rpcap.h"
48 #include "rpcap-protocol.h"
49 #include <errno.h> // for the errno variable
50 #include <stdlib.h> // for malloc(), free(), ...
51 #include <string.h> // for strstr, etc
54 #include <dirent.h> // for readdir
57 /* String identifier to be used in the pcap_findalldevs_ex() */
58 #define PCAP_TEXT_SOURCE_FILE "File"
59 #define PCAP_TEXT_SOURCE_FILE_LEN (sizeof PCAP_TEXT_SOURCE_FILE - 1)
60 /* String identifier to be used in the pcap_findalldevs_ex() */
61 #define PCAP_TEXT_SOURCE_ADAPTER "Network adapter"
62 #define PCAP_TEXT_SOURCE_ADAPTER_LEN (sizeof "Network adapter" - 1)
64 /* String identifier to be used in the pcap_findalldevs_ex() */
65 #define PCAP_TEXT_SOURCE_ON_LOCAL_HOST "on local host"
66 #define PCAP_TEXT_SOURCE_ON_LOCAL_HOST_LEN (sizeof PCAP_TEXT_SOURCE_ON_LOCAL_HOST + 1)
68 /****************************************************
72 ****************************************************/
74 int pcap_findalldevs_ex(const char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf)
77 char name[PCAP_BUF_SIZE], path[PCAP_BUF_SIZE], filename[PCAP_BUF_SIZE];
81 char tmpstring[PCAP_BUF_SIZE + 1]; /* Needed to convert names and descriptions from 'old' syntax to the 'new' one */
82 pcap_if_t *lastdev; /* Last device in the pcap_if_t list */
83 pcap_if_t *dev; /* Device we're adding to the pcap_if_t list */
85 /* List starts out empty. */
89 if (strlen(source) > PCAP_BUF_SIZE)
91 pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The source string is too long. Cannot handle it correctly.");
96 * Determine the type of the source (file, local, remote)
97 * There are some differences if pcap_findalldevs_ex() is called to list files and remote adapters.
98 * In the first case, the name of the directory we have to look into must be present (therefore
99 * the 'name' parameter of the pcap_parsesrcstr() is present).
100 * In the second case, the name of the adapter is not required (we need just the host). So, we have
101 * to use a first time this function to get the source type, and a second time to get the appropriate
102 * info, which depends on the source type.
104 if (pcap_parsesrcstr(source, &type, NULL, NULL, NULL, errbuf) == -1)
109 case PCAP_SRC_IFLOCAL:
110 if (pcap_parsesrcstr(source, &type, NULL, NULL, NULL, errbuf) == -1)
113 /* Initialize temporary string */
114 tmpstring[PCAP_BUF_SIZE] = 0;
116 /* The user wants to retrieve adapters from a local host */
117 if (pcap_findalldevs(alldevs, errbuf) == -1)
120 if (*alldevs == NULL)
122 pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
123 "No interfaces found! Make sure libpcap/Npcap is properly installed"
124 " on the local machine.");
128 /* Scan all the interfaces and modify name and description */
129 /* This is a trick in order to avoid the re-implementation of the pcap_findalldevs here */
133 char *localdesc, *desc;
135 /* Create the new device identifier */
136 if (pcap_createsrcstr(tmpstring, PCAP_SRC_IFLOCAL, NULL, NULL, dev->name, errbuf) == -1)
139 /* Delete the old pointer */
142 /* Make a copy of the new device identifier */
143 dev->name = strdup(tmpstring);
144 if (dev->name == NULL)
146 pcap_fmt_errmsg_for_errno(errbuf,
147 PCAP_ERRBUF_SIZE, errno,
149 pcap_freealldevs(*alldevs);
154 * Create the description.
156 if ((dev->description == NULL) || (dev->description[0] == 0))
157 localdesc = dev->name;
159 localdesc = dev->description;
160 if (pcap_asprintf(&desc, "%s '%s' %s",
161 PCAP_TEXT_SOURCE_ADAPTER, localdesc,
162 PCAP_TEXT_SOURCE_ON_LOCAL_HOST) == -1)
164 pcap_fmt_errmsg_for_errno(errbuf,
165 PCAP_ERRBUF_SIZE, errno,
167 pcap_freealldevs(*alldevs);
171 /* Now overwrite the description */
172 free(dev->description);
173 dev->description = desc;
183 WIN32_FIND_DATA filedata;
186 struct dirent *filedata;
190 if (pcap_parsesrcstr(source, &type, NULL, NULL, name, errbuf) == -1)
193 /* Check that the filename is correct */
194 stringlen = strlen(name);
196 /* The directory must end with '\' in Win32 and '/' in UNIX */
198 #define ENDING_CHAR '\\'
200 #define ENDING_CHAR '/'
203 if (name[stringlen - 1] != ENDING_CHAR)
205 name[stringlen] = ENDING_CHAR;
206 name[stringlen + 1] = 0;
211 /* Save the path for future reference */
212 pcap_snprintf(path, sizeof(path), "%s", name);
213 pathlen = strlen(path);
216 /* To perform directory listing, Win32 must have an 'asterisk' as ending char */
217 if (name[stringlen - 1] != '*')
219 name[stringlen] = '*';
220 name[stringlen + 1] = 0;
223 filehandle = FindFirstFile(name, &filedata);
225 if (filehandle == INVALID_HANDLE_VALUE)
227 pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error when listing files: does folder '%s' exist?", path);
232 /* opening the folder */
233 unixdir= opendir(path);
235 /* get the first file into it */
236 filedata= readdir(unixdir);
238 if (filedata == NULL)
240 pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error when listing files: does folder '%s' exist?", path);
245 /* Add all files we find to the list. */
249 /* Skip the file if the pathname won't fit in the buffer */
250 if (pathlen + strlen(filedata.cFileName) >= sizeof(filename))
252 pcap_snprintf(filename, sizeof(filename), "%s%s", path, filedata.cFileName);
254 if (pathlen + strlen(filedata->d_name) >= sizeof(filename))
256 pcap_snprintf(filename, sizeof(filename), "%s%s", path, filedata->d_name);
259 fp = pcap_open_offline(filename, errbuf);
263 /* allocate the main structure */
264 dev = (pcap_if_t *)malloc(sizeof(pcap_if_t));
267 pcap_fmt_errmsg_for_errno(errbuf,
268 PCAP_ERRBUF_SIZE, errno,
270 pcap_freealldevs(*alldevs);
274 /* Initialize the structure to 'zero' */
275 memset(dev, 0, sizeof(pcap_if_t));
277 /* Append it to the list. */
281 * List is empty, so it's also
289 * Append after the last device.
293 /* It's now the last device. */
296 /* Create the new source identifier */
297 if (pcap_createsrcstr(tmpstring, PCAP_SRC_FILE, NULL, NULL, filename, errbuf) == -1)
299 pcap_freealldevs(*alldevs);
303 dev->name = strdup(tmpstring);
304 if (dev->name == NULL)
306 pcap_fmt_errmsg_for_errno(errbuf,
307 PCAP_ERRBUF_SIZE, errno,
309 pcap_freealldevs(*alldevs);
314 * Create the description.
316 if (pcap_asprintf(&dev->description,
317 "%s '%s' %s", PCAP_TEXT_SOURCE_FILE,
318 filename, PCAP_TEXT_SOURCE_ON_LOCAL_HOST) == -1)
320 pcap_fmt_errmsg_for_errno(errbuf,
321 PCAP_ERRBUF_SIZE, errno,
323 pcap_freealldevs(*alldevs);
331 while (FindNextFile(filehandle, &filedata) != 0);
333 while ( (filedata= readdir(unixdir)) != NULL);
338 /* Close the search handle. */
339 FindClose(filehandle);
345 case PCAP_SRC_IFREMOTE:
346 return pcap_findalldevs_ex_remote(source, auth, alldevs, errbuf);
349 pcap_strlcpy(errbuf, "Source type not supported", PCAP_ERRBUF_SIZE);
354 pcap_t *pcap_open(const char *source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth *auth, char *errbuf)
356 char name[PCAP_BUF_SIZE];
362 * A null device name is equivalent to the "any" device -
363 * which might not be supported on this platform, but
364 * this means that you'll get a "not supported" error
365 * rather than, say, a crash when we try to dereference
371 if (strlen(source) > PCAP_BUF_SIZE)
373 pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The source string is too long. Cannot handle it correctly.");
378 * Determine the type of the source (file, local, remote) and,
379 * if it's file or local, the name of the file or capture device.
381 if (pcap_parsesrcstr(source, &type, NULL, NULL, name, errbuf) == -1)
387 return pcap_open_offline(name, errbuf);
389 case PCAP_SRC_IFLOCAL:
390 fp = pcap_create(name, errbuf);
393 case PCAP_SRC_IFREMOTE:
395 * Although we already have host, port and iface, we prefer
396 * to pass only 'source' to pcap_open_rpcap(), so that it
397 * has to call pcap_parsesrcstr() again.
398 * This is less optimized, but much clearer.
400 return pcap_open_rpcap(source, snaplen, flags, read_timeout, auth, errbuf);
403 pcap_strlcpy(errbuf, "Source type not supported", PCAP_ERRBUF_SIZE);
409 status = pcap_set_snaplen(fp, snaplen);
412 if (flags & PCAP_OPENFLAG_PROMISCUOUS)
414 status = pcap_set_promisc(fp, 1);
418 if (flags & PCAP_OPENFLAG_MAX_RESPONSIVENESS)
420 status = pcap_set_immediate_mode(fp, 1);
426 * This flag is supported on Windows only.
427 * XXX - is there a way to support it with
428 * the capture mechanisms on UN*X? It's not
429 * exactly a "set direction" operation; I
430 * think it means "do not capture packets
431 * injected with pcap_sendpacket() or
434 /* disable loopback capture if requested */
435 if (flags & PCAP_OPENFLAG_NOCAPTURE_LOCAL)
436 fp->opt.nocapture_local = 1;
438 status = pcap_set_timeout(fp, read_timeout);
441 status = pcap_activate(fp);
447 if (status == PCAP_ERROR)
448 pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
450 else if (status == PCAP_ERROR_NO_SUCH_DEVICE ||
451 status == PCAP_ERROR_PERM_DENIED ||
452 status == PCAP_ERROR_PROMISC_PERM_DENIED)
453 pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%s)",
454 name, pcap_statustostr(status), fp->errbuf);
456 pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
457 name, pcap_statustostr(status));
462 struct pcap_samp *pcap_setsampling(pcap_t *p)