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.
38 #include "pcap-int.h" // for the details of the pcap_t structure
39 #include "pcap-rpcap.h"
40 #include "sockutils.h"
41 #include <errno.h> // for the errno variable
42 #include <stdlib.h> // for malloc(), free(), ...
43 #include <string.h> // for strstr, etc
46 #include <dirent.h> // for readdir
49 /* Keeps a list of all the opened connections in the active mode. */
50 extern struct activehosts
*activeHosts
;
53 * \brief Keeps the main socket identifier when we want to accept a new remote connection (active mode only).
54 * See the documentation of pcap_remoteact_accept() and pcap_remoteact_cleanup() for more details.
58 /* String identifier to be used in the pcap_findalldevs_ex() */
59 #define PCAP_TEXT_SOURCE_FILE "File"
60 /* String identifier to be used in the pcap_findalldevs_ex() */
61 #define PCAP_TEXT_SOURCE_ADAPTER "Network adapter"
63 /* String identifier to be used in the pcap_findalldevs_ex() */
64 #define PCAP_TEXT_SOURCE_ON_LOCAL_HOST "on local host"
66 /****************************************************
70 ****************************************************/
72 int pcap_findalldevs_ex(char *source
, struct pcap_rmtauth
*auth
, pcap_if_t
**alldevs
, char *errbuf
)
75 char name
[PCAP_BUF_SIZE
], path
[PCAP_BUF_SIZE
], filename
[PCAP_BUF_SIZE
];
77 char tmpstring
[PCAP_BUF_SIZE
+ 1]; /* Needed to convert names and descriptions from 'old' syntax to the 'new' one */
78 pcap_if_t
*dev
; /* Previous device into the pcap_if_t chain */
82 if (strlen(source
) > PCAP_BUF_SIZE
)
84 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "The source string is too long. Cannot handle it correctly.");
89 * Determine the type of the source (file, local, remote)
90 * There are some differences if pcap_findalldevs_ex() is called to list files and remote adapters.
91 * In the first case, the name of the directory we have to look into must be present (therefore
92 * the 'name' parameter of the pcap_parsesrcstr() is present).
93 * In the second case, the name of the adapter is not required (we need just the host). So, we have
94 * to use a first time this function to get the source type, and a second time to get the appropriate
95 * info, which depends on the source type.
97 if (pcap_parsesrcstr(source
, &type
, NULL
, NULL
, NULL
, errbuf
) == -1)
102 case PCAP_SRC_IFLOCAL
:
103 if (pcap_parsesrcstr(source
, &type
, NULL
, NULL
, NULL
, errbuf
) == -1)
106 /* Initialize temporary string */
107 tmpstring
[PCAP_BUF_SIZE
] = 0;
109 /* The user wants to retrieve adapters from a local host */
110 if (pcap_findalldevs(alldevs
, errbuf
) == -1)
113 if ((alldevs
== NULL
) || (*alldevs
== NULL
))
115 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
,
116 "No interfaces found! Make sure libpcap/WinPcap is properly installed"
117 " on the local machine.");
121 /* Scan all the interfaces and modify name and description */
122 /* This is a trick in order to avoid the re-implementation of the pcap_findalldevs here */
126 /* Create the new device identifier */
127 if (pcap_createsrcstr(tmpstring
, PCAP_SRC_IFLOCAL
, NULL
, NULL
, dev
->name
, errbuf
) == -1)
130 /* Delete the old pointer */
133 /* Make a copy of the new device identifier */
134 dev
->name
= strdup(tmpstring
);
135 if (dev
->name
== NULL
)
137 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "malloc() failed: %s", pcap_strerror(errno
));
141 /* Create the new device description */
142 if ((dev
->description
== NULL
) || (dev
->description
[0] == 0))
143 pcap_snprintf(tmpstring
, sizeof(tmpstring
) - 1, "%s '%s' %s", PCAP_TEXT_SOURCE_ADAPTER
,
144 dev
->name
, PCAP_TEXT_SOURCE_ON_LOCAL_HOST
);
146 pcap_snprintf(tmpstring
, sizeof(tmpstring
) - 1, "%s '%s' %s", PCAP_TEXT_SOURCE_ADAPTER
,
147 dev
->description
, PCAP_TEXT_SOURCE_ON_LOCAL_HOST
);
149 /* Delete the old pointer */
150 free(dev
->description
);
152 /* Make a copy of the description */
153 dev
->description
= strdup(tmpstring
);
154 if (dev
->description
== NULL
)
156 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "malloc() failed: %s", pcap_strerror(errno
));
169 WIN32_FIND_DATA filedata
;
172 struct dirent
*filedata
;
176 if (pcap_parsesrcstr(source
, &type
, NULL
, NULL
, name
, errbuf
) == -1)
179 /* Check that the filename is correct */
180 stringlen
= strlen(name
);
182 /* The directory must end with '\' in Win32 and '/' in UNIX */
184 #define ENDING_CHAR '\\'
186 #define ENDING_CHAR '/'
189 if (name
[stringlen
- 1] != ENDING_CHAR
)
191 name
[stringlen
] = ENDING_CHAR
;
192 name
[stringlen
+ 1] = 0;
197 /* Save the path for future reference */
198 pcap_snprintf(path
, sizeof(path
), "%s", name
);
201 /* To perform directory listing, Win32 must have an 'asterisk' as ending char */
202 if (name
[stringlen
- 1] != '*')
204 name
[stringlen
] = '*';
205 name
[stringlen
+ 1] = 0;
208 filehandle
= FindFirstFile(name
, &filedata
);
210 if (filehandle
== INVALID_HANDLE_VALUE
)
212 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "Error when listing files: does folder '%s' exist?", path
);
217 /* opening the folder */
218 unixdir
= opendir(path
);
220 /* get the first file into it */
221 filedata
= readdir(unixdir
);
223 if (filedata
== NULL
)
225 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "Error when listing files: does folder '%s' exist?", path
);
234 pcap_snprintf(filename
, sizeof(filename
), "%s%s", path
, filedata
.cFileName
);
236 pcap_snprintf(filename
, sizeof(filename
), "%s%s", path
, filedata
->d_name
);
239 fp
= pcap_open_offline(filename
, errbuf
);
243 /* allocate the main structure */
244 if (*alldevs
== NULL
) /* This is in case it is the first file */
246 (*alldevs
) = (pcap_if_t
*)malloc(sizeof(pcap_if_t
));
251 dev
->next
= (pcap_if_t
*)malloc(sizeof(pcap_if_t
));
255 /* check that the malloc() didn't fail */
258 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "malloc() failed: %s", pcap_strerror(errno
));
262 /* Initialize the structure to 'zero' */
263 memset(dev
, 0, sizeof(pcap_if_t
));
265 /* Create the new source identifier */
266 if (pcap_createsrcstr(tmpstring
, PCAP_SRC_FILE
, NULL
, NULL
, filename
, errbuf
) == -1)
269 stringlen
= strlen(tmpstring
);
271 dev
->name
= (char *)malloc(stringlen
+ 1);
272 if (dev
->name
== NULL
)
274 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "malloc() failed: %s", pcap_strerror(errno
));
278 strlcpy(dev
->name
, tmpstring
, stringlen
);
280 dev
->name
[stringlen
] = 0;
282 /* Create the description */
283 pcap_snprintf(tmpstring
, sizeof(tmpstring
) - 1, "%s '%s' %s", PCAP_TEXT_SOURCE_FILE
,
284 filename
, PCAP_TEXT_SOURCE_ON_LOCAL_HOST
);
286 stringlen
= strlen(tmpstring
);
288 dev
->description
= (char *)malloc(stringlen
+ 1);
290 if (dev
->description
== NULL
)
292 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "malloc() failed: %s", pcap_strerror(errno
));
296 /* Copy the new device description into the correct memory location */
297 strlcpy(dev
->description
, tmpstring
, stringlen
+ 1);
303 while (FindNextFile(filehandle
, &filedata
) != 0);
305 while ( (filedata
= readdir(unixdir
)) != NULL
);
310 /* Close the search handle. */
311 FindClose(filehandle
);
317 case PCAP_SRC_IFREMOTE
:
318 return pcap_findalldevs_ex_remote(source
, auth
, alldevs
, errbuf
);
321 strlcpy(errbuf
, "Source type not supported", PCAP_ERRBUF_SIZE
);
326 int pcap_createsrcstr(char *source
, int type
, const char *host
, const char *port
, const char *name
, char *errbuf
)
332 strlcpy(source
, PCAP_SRC_FILE_STRING
, PCAP_BUF_SIZE
);
333 if ((name
) && (*name
))
335 strlcat(source
, name
, PCAP_BUF_SIZE
);
340 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "The file name cannot be NULL.");
345 case PCAP_SRC_IFREMOTE
:
347 strlcpy(source
, PCAP_SRC_IF_STRING
, PCAP_BUF_SIZE
);
348 if ((host
) && (*host
))
350 if ((strcspn(host
, "aAbBcCdDeEfFgGhHjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ")) == strlen(host
))
352 /* the host name does not contains alphabetic chars. So, it is a numeric address */
353 /* In this case we have to include it between square brackets */
354 strlcat(source
, "[", PCAP_BUF_SIZE
);
355 strlcat(source
, host
, PCAP_BUF_SIZE
);
356 strlcat(source
, "]", PCAP_BUF_SIZE
);
359 strlcat(source
, host
, PCAP_BUF_SIZE
);
361 if ((port
) && (*port
))
363 strlcat(source
, ":", PCAP_BUF_SIZE
);
364 strlcat(source
, port
, PCAP_BUF_SIZE
);
367 strlcat(source
, "/", PCAP_BUF_SIZE
);
371 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "The host name cannot be NULL.");
375 if ((name
) && (*name
))
376 strlcat(source
, name
, PCAP_BUF_SIZE
);
381 case PCAP_SRC_IFLOCAL
:
383 strlcpy(source
, PCAP_SRC_IF_STRING
, PCAP_BUF_SIZE
);
385 if ((name
) && (*name
))
386 strlcat(source
, name
, PCAP_BUF_SIZE
);
393 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "The interface type is not valid.");
399 int pcap_parsesrcstr(const char *source
, int *type
, char *host
, char *port
, char *name
, char *errbuf
)
403 char tmpname
[PCAP_BUF_SIZE
];
404 char tmphost
[PCAP_BUF_SIZE
];
405 char tmpport
[PCAP_BUF_SIZE
];
408 /* Initialization stuff */
420 /* Look for a 'rpcap://' identifier */
421 if ((ptr
= strstr(source
, PCAP_SRC_IF_STRING
)) != NULL
)
423 if (strlen(PCAP_SRC_IF_STRING
) == strlen(source
))
425 /* The source identifier contains only the 'rpcap://' string. */
426 /* So, this is a local capture. */
427 *type
= PCAP_SRC_IFLOCAL
;
431 ptr
+= strlen(PCAP_SRC_IF_STRING
);
433 if (strchr(ptr
, '[')) /* This is probably a numeric address */
435 ntoken
= sscanf(ptr
, "[%[1234567890:.]]:%[^/]/%s", tmphost
, tmpport
, tmpname
);
437 if (ntoken
== 1) /* probably the port is missing */
438 ntoken
= sscanf(ptr
, "[%[1234567890:.]]/%s", tmphost
, tmpname
);
440 tmptype
= PCAP_SRC_IFREMOTE
;
444 ntoken
= sscanf(ptr
, "%[^/:]:%[^/]/%s", tmphost
, tmpport
, tmpname
);
449 * This can be due to two reasons:
450 * - we want a remote capture, but the network port is missing
451 * - we want to do a local capture
452 * To distinguish between the two, we look for the '/' char
454 if (strchr(ptr
, '/'))
456 /* We're on a remote capture */
457 sscanf(ptr
, "%[^/]/%s", tmphost
, tmpname
);
458 tmptype
= PCAP_SRC_IFREMOTE
;
462 /* We're on a local capture */
464 strlcpy(tmpname
, ptr
, PCAP_BUF_SIZE
);
466 /* Clean the host name, since it is a remote capture */
467 /* NOTE: the host name has been assigned in the previous "ntoken= sscanf(...)" line */
470 tmptype
= PCAP_SRC_IFLOCAL
;
474 tmptype
= PCAP_SRC_IFREMOTE
;
478 strlcpy(host
, tmphost
, PCAP_BUF_SIZE
);
480 strlcpy(port
, tmpport
, PCAP_BUF_SIZE
);
487 * If the user wants the host name, but it cannot be located into the source string, return error
488 * However, if the user is not interested in the interface name (e.g. if we're called by
489 * pcap_findalldevs_ex(), which does not have interface name, do not return error
493 strlcpy(name
, tmpname
, PCAP_BUF_SIZE
);
498 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "The interface name has not been specified in the source string.");
507 /* Look for a 'file://' identifier */
508 if ((ptr
= strstr(source
, PCAP_SRC_FILE_STRING
)) != NULL
)
510 ptr
+= strlen(PCAP_SRC_FILE_STRING
);
514 strlcpy(name
, ptr
, PCAP_BUF_SIZE
);
517 *type
= PCAP_SRC_FILE
;
524 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "The file name has not been specified in the source string.");
531 /* Backward compatibility; the user didn't use the 'rpcap://, file://' specifiers */
532 if ((source
) && (*source
))
535 strlcpy(name
, source
, PCAP_BUF_SIZE
);
538 *type
= PCAP_SRC_IFLOCAL
;
545 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "The interface name has not been specified in the source string.");
551 pcap_t
*pcap_open(const char *source
, int snaplen
, int flags
, int read_timeout
, struct pcap_rmtauth
*auth
, char *errbuf
)
553 char name
[PCAP_BUF_SIZE
];
557 if (strlen(source
) > PCAP_BUF_SIZE
)
559 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "The source string is too long. Cannot handle it correctly.");
564 * Determine the type of the source (file, local, remote) and,
565 * if it's file or local, the name of the file or capture device.
567 if (pcap_parsesrcstr(source
, &type
, NULL
, NULL
, name
, errbuf
) == -1)
573 fp
= pcap_open_offline(name
, errbuf
);
576 case PCAP_SRC_IFREMOTE
:
578 * Although we already have host, port and iface, we prefer
579 * to pass only 'source' to pcap_open_rpcap(), so that it
580 * has to call pcap_parsesrcstr() again.
581 * This is less optimized, but much clearer.
583 fp
= pcap_open_rpcap(source
, snaplen
, flags
, read_timeout
, auth
, errbuf
);
586 case PCAP_SRC_IFLOCAL
:
587 fp
= pcap_open_live(name
, snaplen
, (flags
& PCAP_OPENFLAG_PROMISCUOUS
), read_timeout
, errbuf
);
591 * these flags are supported on Windows only
593 if (fp
!= NULL
&& fp
->adapter
!= NULL
)
595 /* disable loopback capture if requested */
596 if (flags
& PCAP_OPENFLAG_NOCAPTURE_LOCAL
)
598 if (!PacketSetLoopbackBehavior(fp
->adapter
, NPF_DISABLE_LOOPBACK
))
600 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "Unable to disable the capture of loopback packets.");
606 /* set mintocopy to zero if requested */
607 if (flags
& PCAP_OPENFLAG_MAX_RESPONSIVENESS
)
609 if (!PacketSetMinToCopy(fp
->adapter
, 0))
611 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "Unable to set max responsiveness.");
622 strlcpy(errbuf
, "Source type not supported", PCAP_ERRBUF_SIZE
);
628 struct pcap_samp
*pcap_setsampling(pcap_t
*p
)
633 SOCKET
pcap_remoteact_accept(const char *address
, const char *port
, const char *hostlist
, char *connectinghost
, struct pcap_rmtauth
*auth
, char *errbuf
)
635 /* socket-related variables */
636 struct addrinfo hints
; /* temporary struct to keep settings needed to open the new socket */
637 struct addrinfo
*addrinfo
; /* keeps the addrinfo chain; required to open a new socket */
638 struct sockaddr_storage from
; /* generic sockaddr_storage variable */
639 socklen_t fromlen
; /* keeps the length of the sockaddr_storage variable */
640 SOCKET sockctrl
; /* keeps the main socket identifier */
641 struct activehosts
*temp
, *prev
; /* temp var needed to scan he host list chain */
643 *connectinghost
= 0; /* just in case */
645 /* Prepare to open a new server socket */
646 memset(&hints
, 0, sizeof(struct addrinfo
));
647 /* WARNING Currently it supports only ONE socket family among ipv4 and IPv6 */
648 hints
.ai_family
= AF_INET
; /* PF_UNSPEC to have both IPv4 and IPv6 server */
649 hints
.ai_flags
= AI_PASSIVE
; /* Ready to a bind() socket */
650 hints
.ai_socktype
= SOCK_STREAM
;
652 /* Warning: this call can be the first one called by the user. */
653 /* For this reason, we have to initialize the WinSock support. */
654 if (sock_init(errbuf
, PCAP_ERRBUF_SIZE
) == -1)
658 if ((port
== NULL
) || (port
[0] == 0))
660 if (sock_initaddress(address
, RPCAP_DEFAULT_NETPORT_ACTIVE
, &hints
, &addrinfo
, errbuf
, PCAP_ERRBUF_SIZE
) == -1)
662 SOCK_ASSERT(errbuf
, 1);
668 if (sock_initaddress(address
, port
, &hints
, &addrinfo
, errbuf
, PCAP_ERRBUF_SIZE
) == -1)
670 SOCK_ASSERT(errbuf
, 1);
676 if ((sockmain
= sock_open(addrinfo
, SOCKOPEN_SERVER
, 1, errbuf
, PCAP_ERRBUF_SIZE
)) == -1)
678 SOCK_ASSERT(errbuf
, 1);
682 /* Connection creation */
683 fromlen
= sizeof(struct sockaddr_storage
);
685 sockctrl
= accept(sockmain
, (struct sockaddr
*) &from
, &fromlen
);
687 /* We're not using sock_close, since we do not want to send a shutdown */
688 /* (which is not allowed on a non-connected socket) */
689 closesocket(sockmain
);
694 sock_geterror("accept(): ", errbuf
, PCAP_ERRBUF_SIZE
);
698 /* Get the numeric for of the name of the connecting host */
699 if (getnameinfo((struct sockaddr
*) &from
, fromlen
, connectinghost
, RPCAP_HOSTLIST_SIZE
, NULL
, 0, NI_NUMERICHOST
))
701 sock_geterror("getnameinfo(): ", errbuf
, PCAP_ERRBUF_SIZE
);
702 rpcap_senderror(sockctrl
, errbuf
, PCAP_ERR_REMOTEACCEPT
, NULL
);
703 sock_close(sockctrl
, NULL
, 0);
707 /* checks if the connecting host is among the ones allowed */
708 if (sock_check_hostlist((char *)hostlist
, RPCAP_HOSTLIST_SEP
, &from
, errbuf
, PCAP_ERRBUF_SIZE
) < 0)
710 rpcap_senderror(sockctrl
, errbuf
, PCAP_ERR_REMOTEACCEPT
, NULL
);
711 sock_close(sockctrl
, NULL
, 0);
715 /* Send authentication to the remote machine */
716 if (rpcap_sendauth(sockctrl
, auth
, errbuf
) == -1)
718 rpcap_senderror(sockctrl
, errbuf
, PCAP_ERR_REMOTEACCEPT
, NULL
);
719 sock_close(sockctrl
, NULL
, 0);
723 /* Checks that this host does not already have a cntrl connection in place */
725 /* Initialize pointers */
731 /* This host already has an active connection in place, so I don't have to update the host list */
732 if (sock_cmpaddr(&temp
->host
, &from
) == 0)
739 /* The host does not exist in the list; so I have to update the list */
742 prev
->next
= (struct activehosts
*) malloc(sizeof(struct activehosts
));
747 activeHosts
= (struct activehosts
*) malloc(sizeof(struct activehosts
));
753 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "malloc() failed: %s", pcap_strerror(errno
));
754 rpcap_senderror(sockctrl
, errbuf
, PCAP_ERR_REMOTEACCEPT
, NULL
);
755 sock_close(sockctrl
, NULL
, 0);
759 memcpy(&temp
->host
, &from
, fromlen
);
760 temp
->sockctrl
= sockctrl
;
766 int pcap_remoteact_close(const char *host
, char *errbuf
)
768 struct activehosts
*temp
, *prev
; /* temp var needed to scan the host list chain */
769 struct addrinfo hints
, *addrinfo
, *ai_next
; /* temp var needed to translate between hostname to its address */
775 /* retrieve the network address corresponding to 'host' */
777 memset(&hints
, 0, sizeof(struct addrinfo
));
778 hints
.ai_family
= PF_UNSPEC
;
779 hints
.ai_socktype
= SOCK_STREAM
;
781 retval
= getaddrinfo(host
, "0", &hints
, &addrinfo
);
784 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "getaddrinfo() %s", gai_strerror(retval
));
793 if (sock_cmpaddr(&temp
->host
, (struct sockaddr_storage
*) ai_next
->ai_addr
) == 0)
795 struct rpcap_header header
;
797 /* Close this connection */
798 rpcap_createhdr(&header
, RPCAP_MSG_CLOSE
, 0, 0);
800 /* I don't check for errors, since I'm going to close everything */
801 sock_send(temp
->sockctrl
, (char *)&header
, sizeof(struct rpcap_header
), errbuf
, PCAP_ERRBUF_SIZE
);
803 if (sock_close(temp
->sockctrl
, errbuf
, PCAP_ERRBUF_SIZE
))
805 /* To avoid inconsistencies in the number of sock_init() */
812 prev
->next
= temp
->next
;
814 activeHosts
= temp
->next
;
816 freeaddrinfo(addrinfo
);
820 /* To avoid inconsistencies in the number of sock_init() */
826 ai_next
= ai_next
->ai_next
;
833 freeaddrinfo(addrinfo
);
835 /* To avoid inconsistencies in the number of sock_init() */
838 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "The host you want to close the active connection is not known");
842 void pcap_remoteact_cleanup(void)
844 /* Very dirty, but it works */
847 closesocket(sockmain
);
849 /* To avoid inconsistencies in the number of sock_init() */
855 int pcap_remoteact_list(char *hostlist
, char sep
, int size
, char *errbuf
)
857 struct activehosts
*temp
; /* temp var needed to scan the host list chain */
859 char hoststr
[RPCAP_HOSTLIST_SIZE
+ 1];
868 /*int sock_getascii_addrport(const struct sockaddr_storage *sockaddr, char *address, int addrlen, char *port, int portlen, int flags, char *errbuf, int errbuflen) */
870 /* Get the numeric form of the name of the connecting host */
871 if (sock_getascii_addrport((struct sockaddr_storage
*) &temp
->host
, hoststr
,
872 RPCAP_HOSTLIST_SIZE
, NULL
, 0, NI_NUMERICHOST
, errbuf
, PCAP_ERRBUF_SIZE
) != -1)
873 /* if (getnameinfo( (struct sockaddr *) &temp->host, sizeof (struct sockaddr_storage), hoststr, */
874 /* RPCAP_HOSTLIST_SIZE, NULL, 0, NI_NUMERICHOST) ) */
876 /* sock_geterror("getnameinfo(): ", errbuf, PCAP_ERRBUF_SIZE); */
880 len
= len
+ strlen(hoststr
) + 1 /* the separator */;
882 if ((size
< 0) || (len
>= (size_t)size
))
884 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "The string you provided is not able to keep "
885 "the hostnames for all the active connections");
889 strlcat(hostlist
, hoststr
, PCAP_ERRBUF_SIZE
);
890 hostlist
[len
- 1] = sep
;