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 "sockutils.h"
40 #include "rpcap-protocol.h"
41 #include "pcap-rpcap-int.h"
42 #include <errno.h> // for the errno variable
43 #include <stdlib.h> // for malloc(), free(), ...
44 #include <string.h> // for strstr, etc
47 #include <dirent.h> // for readdir
50 /* Keeps a list of all the opened connections in the active mode. */
51 extern struct activehosts
*activeHosts
;
54 * \brief Keeps the main socket identifier when we want to accept a new remote connection (active mode only).
55 * See the documentation of pcap_remoteact_accept() and pcap_remoteact_cleanup() for more details.
59 /* String identifier to be used in the pcap_findalldevs_ex() */
60 #define PCAP_TEXT_SOURCE_FILE "File"
61 /* String identifier to be used in the pcap_findalldevs_ex() */
62 #define PCAP_TEXT_SOURCE_ADAPTER "Network adapter"
64 /* String identifier to be used in the pcap_findalldevs_ex() */
65 #define PCAP_TEXT_SOURCE_ON_LOCAL_HOST "on local host"
67 /****************************************************
71 ****************************************************/
73 int pcap_findalldevs_ex(char *source
, struct pcap_rmtauth
*auth
, pcap_if_t
**alldevs
, char *errbuf
)
76 char name
[PCAP_BUF_SIZE
], path
[PCAP_BUF_SIZE
], filename
[PCAP_BUF_SIZE
];
78 char tmpstring
[PCAP_BUF_SIZE
+ 1]; /* Needed to convert names and descriptions from 'old' syntax to the 'new' one */
79 pcap_if_t
*dev
; /* Previous device into the pcap_if_t chain */
83 if (strlen(source
) > PCAP_BUF_SIZE
)
85 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "The source string is too long. Cannot handle it correctly.");
90 * Determine the type of the source (file, local, remote)
91 * There are some differences if pcap_findalldevs_ex() is called to list files and remote adapters.
92 * In the first case, the name of the directory we have to look into must be present (therefore
93 * the 'name' parameter of the pcap_parsesrcstr() is present).
94 * In the second case, the name of the adapter is not required (we need just the host). So, we have
95 * to use a first time this function to get the source type, and a second time to get the appropriate
96 * info, which depends on the source type.
98 if (pcap_parsesrcstr(source
, &type
, NULL
, NULL
, NULL
, errbuf
) == -1)
103 case PCAP_SRC_IFLOCAL
:
104 if (pcap_parsesrcstr(source
, &type
, NULL
, NULL
, NULL
, errbuf
) == -1)
107 /* Initialize temporary string */
108 tmpstring
[PCAP_BUF_SIZE
] = 0;
110 /* The user wants to retrieve adapters from a local host */
111 if (pcap_findalldevs(alldevs
, errbuf
) == -1)
114 if ((alldevs
== NULL
) || (*alldevs
== NULL
))
116 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
,
117 "No interfaces found! Make sure libpcap/WinPcap is properly installed"
118 " on the local machine.");
122 /* Scan all the interfaces and modify name and description */
123 /* This is a trick in order to avoid the re-implementation of the pcap_findalldevs here */
127 /* Create the new device identifier */
128 if (pcap_createsrcstr(tmpstring
, PCAP_SRC_IFLOCAL
, NULL
, NULL
, dev
->name
, errbuf
) == -1)
131 /* Delete the old pointer */
134 /* Make a copy of the new device identifier */
135 dev
->name
= strdup(tmpstring
);
136 if (dev
->name
== NULL
)
138 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "malloc() failed: %s", pcap_strerror(errno
));
142 /* Create the new device description */
143 if ((dev
->description
== NULL
) || (dev
->description
[0] == 0))
144 pcap_snprintf(tmpstring
, sizeof(tmpstring
) - 1, "%s '%s' %s", PCAP_TEXT_SOURCE_ADAPTER
,
145 dev
->name
, PCAP_TEXT_SOURCE_ON_LOCAL_HOST
);
147 pcap_snprintf(tmpstring
, sizeof(tmpstring
) - 1, "%s '%s' %s", PCAP_TEXT_SOURCE_ADAPTER
,
148 dev
->description
, PCAP_TEXT_SOURCE_ON_LOCAL_HOST
);
150 /* Delete the old pointer */
151 free(dev
->description
);
153 /* Make a copy of the description */
154 dev
->description
= strdup(tmpstring
);
155 if (dev
->description
== NULL
)
157 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "malloc() failed: %s", pcap_strerror(errno
));
170 WIN32_FIND_DATA filedata
;
173 struct dirent
*filedata
;
177 if (pcap_parsesrcstr(source
, &type
, NULL
, NULL
, name
, errbuf
) == -1)
180 /* Check that the filename is correct */
181 stringlen
= strlen(name
);
183 /* The directory must end with '\' in Win32 and '/' in UNIX */
185 #define ENDING_CHAR '\\'
187 #define ENDING_CHAR '/'
190 if (name
[stringlen
- 1] != ENDING_CHAR
)
192 name
[stringlen
] = ENDING_CHAR
;
193 name
[stringlen
+ 1] = 0;
198 /* Save the path for future reference */
199 pcap_snprintf(path
, sizeof(path
), "%s", name
);
202 /* To perform directory listing, Win32 must have an 'asterisk' as ending char */
203 if (name
[stringlen
- 1] != '*')
205 name
[stringlen
] = '*';
206 name
[stringlen
+ 1] = 0;
209 filehandle
= FindFirstFile(name
, &filedata
);
211 if (filehandle
== INVALID_HANDLE_VALUE
)
213 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "Error when listing files: does folder '%s' exist?", path
);
218 /* opening the folder */
219 unixdir
= opendir(path
);
221 /* get the first file into it */
222 filedata
= readdir(unixdir
);
224 if (filedata
== NULL
)
226 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "Error when listing files: does folder '%s' exist?", path
);
235 pcap_snprintf(filename
, sizeof(filename
), "%s%s", path
, filedata
.cFileName
);
237 pcap_snprintf(filename
, sizeof(filename
), "%s%s", path
, filedata
->d_name
);
240 fp
= pcap_open_offline(filename
, errbuf
);
244 /* allocate the main structure */
245 if (*alldevs
== NULL
) /* This is in case it is the first file */
247 (*alldevs
) = (pcap_if_t
*)malloc(sizeof(pcap_if_t
));
252 dev
->next
= (pcap_if_t
*)malloc(sizeof(pcap_if_t
));
256 /* check that the malloc() didn't fail */
259 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "malloc() failed: %s", pcap_strerror(errno
));
263 /* Initialize the structure to 'zero' */
264 memset(dev
, 0, sizeof(pcap_if_t
));
266 /* Create the new source identifier */
267 if (pcap_createsrcstr(tmpstring
, PCAP_SRC_FILE
, NULL
, NULL
, filename
, errbuf
) == -1)
270 stringlen
= strlen(tmpstring
);
272 dev
->name
= (char *)malloc(stringlen
+ 1);
273 if (dev
->name
== NULL
)
275 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "malloc() failed: %s", pcap_strerror(errno
));
279 strlcpy(dev
->name
, tmpstring
, stringlen
);
281 dev
->name
[stringlen
] = 0;
283 /* Create the description */
284 pcap_snprintf(tmpstring
, sizeof(tmpstring
) - 1, "%s '%s' %s", PCAP_TEXT_SOURCE_FILE
,
285 filename
, PCAP_TEXT_SOURCE_ON_LOCAL_HOST
);
287 stringlen
= strlen(tmpstring
);
289 dev
->description
= (char *)malloc(stringlen
+ 1);
291 if (dev
->description
== NULL
)
293 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "malloc() failed: %s", pcap_strerror(errno
));
297 /* Copy the new device description into the correct memory location */
298 strlcpy(dev
->description
, tmpstring
, stringlen
+ 1);
304 while (FindNextFile(filehandle
, &filedata
) != 0);
306 while ( (filedata
= readdir(unixdir
)) != NULL
);
311 /* Close the search handle. */
312 FindClose(filehandle
);
318 case PCAP_SRC_IFREMOTE
:
319 return pcap_findalldevs_ex_remote(source
, auth
, alldevs
, errbuf
);
322 strlcpy(errbuf
, "Source type not supported", PCAP_ERRBUF_SIZE
);
327 int pcap_createsrcstr(char *source
, int type
, const char *host
, const char *port
, const char *name
, char *errbuf
)
333 strlcpy(source
, PCAP_SRC_FILE_STRING
, PCAP_BUF_SIZE
);
334 if ((name
) && (*name
))
336 strlcat(source
, name
, PCAP_BUF_SIZE
);
341 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "The file name cannot be NULL.");
346 case PCAP_SRC_IFREMOTE
:
348 strlcpy(source
, PCAP_SRC_IF_STRING
, PCAP_BUF_SIZE
);
349 if ((host
) && (*host
))
351 if ((strcspn(host
, "aAbBcCdDeEfFgGhHjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ")) == strlen(host
))
353 /* the host name does not contains alphabetic chars. So, it is a numeric address */
354 /* In this case we have to include it between square brackets */
355 strlcat(source
, "[", PCAP_BUF_SIZE
);
356 strlcat(source
, host
, PCAP_BUF_SIZE
);
357 strlcat(source
, "]", PCAP_BUF_SIZE
);
360 strlcat(source
, host
, PCAP_BUF_SIZE
);
362 if ((port
) && (*port
))
364 strlcat(source
, ":", PCAP_BUF_SIZE
);
365 strlcat(source
, port
, PCAP_BUF_SIZE
);
368 strlcat(source
, "/", PCAP_BUF_SIZE
);
372 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "The host name cannot be NULL.");
376 if ((name
) && (*name
))
377 strlcat(source
, name
, PCAP_BUF_SIZE
);
382 case PCAP_SRC_IFLOCAL
:
384 strlcpy(source
, PCAP_SRC_IF_STRING
, PCAP_BUF_SIZE
);
386 if ((name
) && (*name
))
387 strlcat(source
, name
, PCAP_BUF_SIZE
);
394 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "The interface type is not valid.");
400 int pcap_parsesrcstr(const char *source
, int *type
, char *host
, char *port
, char *name
, char *errbuf
)
404 char tmpname
[PCAP_BUF_SIZE
];
405 char tmphost
[PCAP_BUF_SIZE
];
406 char tmpport
[PCAP_BUF_SIZE
];
409 /* Initialization stuff */
421 /* Look for a 'rpcap://' identifier */
422 if ((ptr
= strstr(source
, PCAP_SRC_IF_STRING
)) != NULL
)
424 if (strlen(PCAP_SRC_IF_STRING
) == strlen(source
))
426 /* The source identifier contains only the 'rpcap://' string. */
427 /* So, this is a local capture. */
428 *type
= PCAP_SRC_IFLOCAL
;
432 ptr
+= strlen(PCAP_SRC_IF_STRING
);
434 if (strchr(ptr
, '[')) /* This is probably a numeric address */
436 ntoken
= sscanf(ptr
, "[%[1234567890:.]]:%[^/]/%s", tmphost
, tmpport
, tmpname
);
438 if (ntoken
== 1) /* probably the port is missing */
439 ntoken
= sscanf(ptr
, "[%[1234567890:.]]/%s", tmphost
, tmpname
);
441 tmptype
= PCAP_SRC_IFREMOTE
;
445 ntoken
= sscanf(ptr
, "%[^/:]:%[^/]/%s", tmphost
, tmpport
, tmpname
);
450 * This can be due to two reasons:
451 * - we want a remote capture, but the network port is missing
452 * - we want to do a local capture
453 * To distinguish between the two, we look for the '/' char
455 if (strchr(ptr
, '/'))
457 /* We're on a remote capture */
458 sscanf(ptr
, "%[^/]/%s", tmphost
, tmpname
);
459 tmptype
= PCAP_SRC_IFREMOTE
;
463 /* We're on a local capture */
465 strlcpy(tmpname
, ptr
, PCAP_BUF_SIZE
);
467 /* Clean the host name, since it is a remote capture */
468 /* NOTE: the host name has been assigned in the previous "ntoken= sscanf(...)" line */
471 tmptype
= PCAP_SRC_IFLOCAL
;
475 tmptype
= PCAP_SRC_IFREMOTE
;
479 strlcpy(host
, tmphost
, PCAP_BUF_SIZE
);
481 strlcpy(port
, tmpport
, PCAP_BUF_SIZE
);
488 * If the user wants the host name, but it cannot be located into the source string, return error
489 * However, if the user is not interested in the interface name (e.g. if we're called by
490 * pcap_findalldevs_ex(), which does not have interface name, do not return error
494 strlcpy(name
, tmpname
, PCAP_BUF_SIZE
);
499 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "The interface name has not been specified in the source string.");
508 /* Look for a 'file://' identifier */
509 if ((ptr
= strstr(source
, PCAP_SRC_FILE_STRING
)) != NULL
)
511 ptr
+= strlen(PCAP_SRC_FILE_STRING
);
515 strlcpy(name
, ptr
, PCAP_BUF_SIZE
);
518 *type
= PCAP_SRC_FILE
;
525 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "The file name has not been specified in the source string.");
532 /* Backward compatibility; the user didn't use the 'rpcap://, file://' specifiers */
533 if ((source
) && (*source
))
536 strlcpy(name
, source
, PCAP_BUF_SIZE
);
539 *type
= PCAP_SRC_IFLOCAL
;
546 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "The interface name has not been specified in the source string.");
552 pcap_t
*pcap_open(const char *source
, int snaplen
, int flags
, int read_timeout
, struct pcap_rmtauth
*auth
, char *errbuf
)
554 char name
[PCAP_BUF_SIZE
];
559 if (strlen(source
) > PCAP_BUF_SIZE
)
561 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "The source string is too long. Cannot handle it correctly.");
566 * Determine the type of the source (file, local, remote) and,
567 * if it's file or local, the name of the file or capture device.
569 if (pcap_parsesrcstr(source
, &type
, NULL
, NULL
, name
, errbuf
) == -1)
575 fp
= pcap_open_offline(name
, errbuf
);
578 case PCAP_SRC_IFLOCAL
:
579 fp
= pcap_create(source
, errbuf
);
582 status
= pcap_set_snaplen(fp
, snaplen
);
585 if (flags
& PCAP_OPENFLAG_PROMISCUOUS
)
587 status
= pcap_set_promisc(fp
, 1);
591 if (flags
& PCAP_OPENFLAG_MAX_RESPONSIVENESS
)
593 status
= pcap_set_immediate_mode(fp
, 1);
597 status
= pcap_set_timeout(fp
, read_timeout
);
600 status
= pcap_activate(fp
);
605 * This flag is supported on Windows only.
606 * XXX - is there a way to support it with
607 * the capture mechanisms on UN*X? It's not
608 * exactly a "set direction" operation; I
609 * think it means "do not capture packets
610 * injected with pcap_sendpacket() or
613 if (fp
->adapter
!= NULL
)
615 /* disable loopback capture if requested */
616 if (flags
& PCAP_OPENFLAG_NOCAPTURE_LOCAL
)
618 if (!PacketSetLoopbackBehavior(fp
->adapter
, NPF_DISABLE_LOOPBACK
))
620 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "Unable to disable the capture of loopback packets.");
630 if (status
== PCAP_ERROR
)
631 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "%s: %s",
633 else if (status
== PCAP_ERROR_NO_SUCH_DEVICE
||
634 status
== PCAP_ERROR_PERM_DENIED
||
635 status
== PCAP_ERROR_PROMISC_PERM_DENIED
)
636 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "%s: %s (%s)",
637 source
, pcap_statustostr(status
), fp
->errbuf
);
639 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "%s: %s",
640 source
, pcap_statustostr(status
));
644 case PCAP_SRC_IFREMOTE
:
646 * Although we already have host, port and iface, we prefer
647 * to pass only 'source' to pcap_open_rpcap(), so that it
648 * has to call pcap_parsesrcstr() again.
649 * This is less optimized, but much clearer.
651 fp
= pcap_open_rpcap(source
, snaplen
, flags
, read_timeout
, auth
, errbuf
);
655 strlcpy(errbuf
, "Source type not supported", PCAP_ERRBUF_SIZE
);
661 struct pcap_samp
*pcap_setsampling(pcap_t
*p
)
666 SOCKET
pcap_remoteact_accept(const char *address
, const char *port
, const char *hostlist
, char *connectinghost
, struct pcap_rmtauth
*auth
, char *errbuf
)
668 /* socket-related variables */
669 struct addrinfo hints
; /* temporary struct to keep settings needed to open the new socket */
670 struct addrinfo
*addrinfo
; /* keeps the addrinfo chain; required to open a new socket */
671 struct sockaddr_storage from
; /* generic sockaddr_storage variable */
672 socklen_t fromlen
; /* keeps the length of the sockaddr_storage variable */
673 SOCKET sockctrl
; /* keeps the main socket identifier */
674 struct activehosts
*temp
, *prev
; /* temp var needed to scan he host list chain */
676 *connectinghost
= 0; /* just in case */
678 /* Prepare to open a new server socket */
679 memset(&hints
, 0, sizeof(struct addrinfo
));
680 /* WARNING Currently it supports only ONE socket family among ipv4 and IPv6 */
681 hints
.ai_family
= AF_INET
; /* PF_UNSPEC to have both IPv4 and IPv6 server */
682 hints
.ai_flags
= AI_PASSIVE
; /* Ready to a bind() socket */
683 hints
.ai_socktype
= SOCK_STREAM
;
685 /* Warning: this call can be the first one called by the user. */
686 /* For this reason, we have to initialize the WinSock support. */
687 if (sock_init(errbuf
, PCAP_ERRBUF_SIZE
) == -1)
691 if ((port
== NULL
) || (port
[0] == 0))
693 if (sock_initaddress(address
, RPCAP_DEFAULT_NETPORT_ACTIVE
, &hints
, &addrinfo
, errbuf
, PCAP_ERRBUF_SIZE
) == -1)
695 SOCK_ASSERT(errbuf
, 1);
701 if (sock_initaddress(address
, port
, &hints
, &addrinfo
, errbuf
, PCAP_ERRBUF_SIZE
) == -1)
703 SOCK_ASSERT(errbuf
, 1);
709 if ((sockmain
= sock_open(addrinfo
, SOCKOPEN_SERVER
, 1, errbuf
, PCAP_ERRBUF_SIZE
)) == -1)
711 SOCK_ASSERT(errbuf
, 1);
715 /* Connection creation */
716 fromlen
= sizeof(struct sockaddr_storage
);
718 sockctrl
= accept(sockmain
, (struct sockaddr
*) &from
, &fromlen
);
720 /* We're not using sock_close, since we do not want to send a shutdown */
721 /* (which is not allowed on a non-connected socket) */
722 closesocket(sockmain
);
727 sock_geterror("accept(): ", errbuf
, PCAP_ERRBUF_SIZE
);
731 /* Get the numeric for of the name of the connecting host */
732 if (getnameinfo((struct sockaddr
*) &from
, fromlen
, connectinghost
, RPCAP_HOSTLIST_SIZE
, NULL
, 0, NI_NUMERICHOST
))
734 sock_geterror("getnameinfo(): ", errbuf
, PCAP_ERRBUF_SIZE
);
735 rpcap_senderror(sockctrl
, errbuf
, PCAP_ERR_REMOTEACCEPT
, NULL
);
736 sock_close(sockctrl
, NULL
, 0);
740 /* checks if the connecting host is among the ones allowed */
741 if (sock_check_hostlist((char *)hostlist
, RPCAP_HOSTLIST_SEP
, &from
, errbuf
, PCAP_ERRBUF_SIZE
) < 0)
743 rpcap_senderror(sockctrl
, errbuf
, PCAP_ERR_REMOTEACCEPT
, NULL
);
744 sock_close(sockctrl
, NULL
, 0);
748 /* Send authentication to the remote machine */
749 if (rpcap_sendauth(sockctrl
, auth
, errbuf
) == -1)
751 rpcap_senderror(sockctrl
, errbuf
, PCAP_ERR_REMOTEACCEPT
, NULL
);
752 sock_close(sockctrl
, NULL
, 0);
756 /* Checks that this host does not already have a cntrl connection in place */
758 /* Initialize pointers */
764 /* This host already has an active connection in place, so I don't have to update the host list */
765 if (sock_cmpaddr(&temp
->host
, &from
) == 0)
772 /* The host does not exist in the list; so I have to update the list */
775 prev
->next
= (struct activehosts
*) malloc(sizeof(struct activehosts
));
780 activeHosts
= (struct activehosts
*) malloc(sizeof(struct activehosts
));
786 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "malloc() failed: %s", pcap_strerror(errno
));
787 rpcap_senderror(sockctrl
, errbuf
, PCAP_ERR_REMOTEACCEPT
, NULL
);
788 sock_close(sockctrl
, NULL
, 0);
792 memcpy(&temp
->host
, &from
, fromlen
);
793 temp
->sockctrl
= sockctrl
;
799 int pcap_remoteact_close(const char *host
, char *errbuf
)
801 struct activehosts
*temp
, *prev
; /* temp var needed to scan the host list chain */
802 struct addrinfo hints
, *addrinfo
, *ai_next
; /* temp var needed to translate between hostname to its address */
808 /* retrieve the network address corresponding to 'host' */
810 memset(&hints
, 0, sizeof(struct addrinfo
));
811 hints
.ai_family
= PF_UNSPEC
;
812 hints
.ai_socktype
= SOCK_STREAM
;
814 retval
= getaddrinfo(host
, "0", &hints
, &addrinfo
);
817 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "getaddrinfo() %s", gai_strerror(retval
));
826 if (sock_cmpaddr(&temp
->host
, (struct sockaddr_storage
*) ai_next
->ai_addr
) == 0)
828 struct rpcap_header header
;
830 /* Close this connection */
831 rpcap_createhdr(&header
, RPCAP_MSG_CLOSE
, 0, 0);
833 /* I don't check for errors, since I'm going to close everything */
834 sock_send(temp
->sockctrl
, (char *)&header
, sizeof(struct rpcap_header
), errbuf
, PCAP_ERRBUF_SIZE
);
836 if (sock_close(temp
->sockctrl
, errbuf
, PCAP_ERRBUF_SIZE
))
838 /* To avoid inconsistencies in the number of sock_init() */
845 prev
->next
= temp
->next
;
847 activeHosts
= temp
->next
;
849 freeaddrinfo(addrinfo
);
853 /* To avoid inconsistencies in the number of sock_init() */
859 ai_next
= ai_next
->ai_next
;
866 freeaddrinfo(addrinfo
);
868 /* To avoid inconsistencies in the number of sock_init() */
871 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "The host you want to close the active connection is not known");
875 void pcap_remoteact_cleanup(void)
877 /* Very dirty, but it works */
880 closesocket(sockmain
);
882 /* To avoid inconsistencies in the number of sock_init() */
888 int pcap_remoteact_list(char *hostlist
, char sep
, int size
, char *errbuf
)
890 struct activehosts
*temp
; /* temp var needed to scan the host list chain */
892 char hoststr
[RPCAP_HOSTLIST_SIZE
+ 1];
901 /*int sock_getascii_addrport(const struct sockaddr_storage *sockaddr, char *address, int addrlen, char *port, int portlen, int flags, char *errbuf, int errbuflen) */
903 /* Get the numeric form of the name of the connecting host */
904 if (sock_getascii_addrport((struct sockaddr_storage
*) &temp
->host
, hoststr
,
905 RPCAP_HOSTLIST_SIZE
, NULL
, 0, NI_NUMERICHOST
, errbuf
, PCAP_ERRBUF_SIZE
) != -1)
906 /* if (getnameinfo( (struct sockaddr *) &temp->host, sizeof (struct sockaddr_storage), hoststr, */
907 /* RPCAP_HOSTLIST_SIZE, NULL, 0, NI_NUMERICHOST) ) */
909 /* sock_geterror("getnameinfo(): ", errbuf, PCAP_ERRBUF_SIZE); */
913 len
= len
+ strlen(hoststr
) + 1 /* the separator */;
915 if ((size
< 0) || (len
>= (size_t)size
))
917 pcap_snprintf(errbuf
, PCAP_ERRBUF_SIZE
, "The string you provided is not able to keep "
918 "the hostnames for all the active connections");
922 strlcat(hostlist
, hoststr
, PCAP_ERRBUF_SIZE
);
923 hostlist
[len
- 1] = sep
;