1
0
mirror of https://github.com/nmap/nmap.git synced 2025-12-20 22:49:01 +00:00

Update to libpcap 1.9.1 (initial commit, no Nmap-specific patches)

This commit is contained in:
dmiller
2019-11-19 17:53:36 +00:00
parent 42bb2feed8
commit f1107301e8
125 changed files with 7238 additions and 13624 deletions

View File

@@ -130,44 +130,15 @@ static int sock_ismcastaddr(const struct sockaddr *saddr);
*/
void sock_fmterror(const char *caller, int errcode, char *errbuf, int errbuflen)
{
if (errbuf == NULL)
return;
#ifdef _WIN32
int retval;
char message[SOCK_ERRBUF_SIZE]; /* We're forcing "ANSI" */
if (errbuf == NULL)
return;
retval = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS |
FORMAT_MESSAGE_MAX_WIDTH_MASK,
NULL, errcode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
message, sizeof(message) / sizeof(TCHAR), NULL);
if (retval == 0)
{
if ((caller) && (*caller))
pcap_snprintf(errbuf, errbuflen, "%sUnable to get the exact error message", caller);
else
pcap_snprintf(errbuf, errbuflen, "Unable to get the exact error message");
}
else
{
if ((caller) && (*caller))
pcap_snprintf(errbuf, errbuflen, "%s%s (code %d)", caller, message, errcode);
else
pcap_snprintf(errbuf, errbuflen, "%s (code %d)", message, errcode);
}
pcap_fmt_errmsg_for_win32_err(errbuf, errbuflen, errcode,
"%s", caller);
#else
char *message;
if (errbuf == NULL)
return;
message = strerror(errcode);
if ((caller) && (*caller))
pcap_snprintf(errbuf, errbuflen, "%s%s (code %d)", caller, message, errcode);
else
pcap_snprintf(errbuf, errbuflen, "%s (code %d)", message, errcode);
pcap_fmt_errmsg_for_errno(errbuf, errbuflen, errcode,
"%s", caller);
#endif
}
@@ -180,7 +151,7 @@ void sock_fmterror(const char *caller, int errcode, char *errbuf, int errbuflen)
*
* \param caller: a pointer to a user-allocated string which contains a message that has
* to be printed *before* the true error message. It could be, for example, 'this error
* comes from the recv() call at line 31'. It may be NULL.
* comes from the recv() call at line 31'.
*
* \param errbuf: a pointer to an user-allocated buffer that will contain the complete
* error message. This buffer has to be at least 'errbuflen' in length.
@@ -194,31 +165,30 @@ void sock_fmterror(const char *caller, int errcode, char *errbuf, int errbuflen)
void sock_geterror(const char *caller, char *errbuf, int errbuflen)
{
#ifdef _WIN32
if (errbuf == NULL)
return;
sock_fmterror(caller, GetLastError(), errbuf, errbuflen);
#else
if (errbuf == NULL)
return;
sock_fmterror(caller, errno, errbuf, errbuflen);
#endif
}
/*
* \brief It initializes sockets.
* \brief This function initializes the socket mechanism if it hasn't
* already been initialized or reinitializes it after it has been
* cleaned up.
*
* This function is pretty useless on UNIX, since socket initialization is not required.
* However it is required on Win32. In UNIX, this function appears to be completely empty.
* On UN*Xes, it doesn't need to do anything; on Windows, it needs to
* initialize Winsock.
*
* \param errbuf: a pointer to an user-allocated buffer that will contain the complete
* error message. This buffer has to be at least 'errbuflen' in length.
* It can be NULL; in this case the error cannot be printed.
* \param errbuf: a pointer to an user-allocated buffer that will contain
* the complete error message. This buffer has to be at least 'errbuflen'
* in length. It can be NULL; in this case no error message is supplied.
*
* \param errbuflen: length of the buffer that will contains the error. The error message cannot be
* larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
* \param errbuflen: length of the buffer that will contains the error.
* The error message cannot be larger than 'errbuflen - 1' because the
* last char is reserved for the string terminator.
*
* \return '0' if everything is fine, '-1' if some errors occurred. The error message is returned
* in the 'errbuf' variable.
* \return '0' if everything is fine, '-1' if some errors occurred. The
* error message is returned in the buffer pointed to by 'errbuf' variable.
*/
#ifdef _WIN32
int sock_init(char *errbuf, int errbuflen)
@@ -240,18 +210,24 @@ int sock_init(char *errbuf, int errbuflen)
}
sockcount++;
return 0;
}
#else
int sock_init(char *errbuf _U_, int errbuflen _U_)
{
#endif
/*
* Nothing to do on UN*Xes.
*/
return 0;
}
#endif
/*
* \brief It deallocates sockets.
* \brief This function cleans up the socket mechanism if we have no
* sockets left open.
*
* This function is pretty useless on UNIX, since socket deallocation is not required.
* However it is required on Win32. In UNIX, this function appears to be completely empty.
* On UN*Xes, it doesn't need to do anything; on Windows, it needs
* to clean up Winsock.
*
* \return No error values.
*/
@@ -327,7 +303,7 @@ SOCKET sock_open(struct addrinfo *addrinfo, int server, int nconn, char *errbuf,
sock = socket(addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol);
if (sock == INVALID_SOCKET)
{
sock_geterror("socket(): ", errbuf, errbuflen);
sock_geterror("socket()", errbuf, errbuflen);
return INVALID_SOCKET;
}
@@ -350,6 +326,16 @@ SOCKET sock_open(struct addrinfo *addrinfo, int server, int nconn, char *errbuf,
/* This is a server socket */
if (server)
{
/*
* Allow a new server to bind the socket after the old one
* exited, even if lingering sockets are still present.
*
* Don't treat an error as a failure.
*/
int optval = 1;
(void)setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
(char *)&optval, sizeof (optval));
#if defined(IPV6_V6ONLY) || defined(IPV6_BINDV6ONLY)
/*
* Force the use of IPv6-only addresses.
@@ -399,7 +385,7 @@ SOCKET sock_open(struct addrinfo *addrinfo, int server, int nconn, char *errbuf,
/* WARNING: if the address is a mcast one, I should place the proper Win32 code here */
if (bind(sock, addrinfo->ai_addr, (int) addrinfo->ai_addrlen) != 0)
{
sock_geterror("bind(): ", errbuf, errbuflen);
sock_geterror("bind()", errbuf, errbuflen);
closesocket(sock);
return INVALID_SOCKET;
}
@@ -407,7 +393,7 @@ SOCKET sock_open(struct addrinfo *addrinfo, int server, int nconn, char *errbuf,
if (addrinfo->ai_socktype == SOCK_STREAM)
if (listen(sock, nconn) == -1)
{
sock_geterror("listen(): ", errbuf, errbuflen);
sock_geterror("listen()", errbuf, errbuflen);
closesocket(sock);
return INVALID_SOCKET;
}
@@ -444,13 +430,14 @@ SOCKET sock_open(struct addrinfo *addrinfo, int server, int nconn, char *errbuf,
* We have to retrieve the error message before any other socket call completes, otherwise
* the error message is lost
*/
sock_geterror(NULL, SocketErrorMessage, sizeof(SocketErrorMessage));
sock_geterror("Connect to socket failed",
SocketErrorMessage, sizeof(SocketErrorMessage));
/* Returns the numeric address of the host that triggered the error */
sock_getascii_addrport((struct sockaddr_storage *) tempaddrinfo->ai_addr, TmpBuffer, sizeof(TmpBuffer), NULL, 0, NI_NUMERICHOST, TmpBuffer, sizeof(TmpBuffer));
pcap_snprintf(errbufptr, bufspaceleft,
"Is the server properly installed on %s? connect() failed: %s", TmpBuffer, SocketErrorMessage);
"Is the server properly installed on %s? %s", TmpBuffer, SocketErrorMessage);
/* In case more then one 'connect' fails, we manage to keep all the error messages */
msglen = strlen(errbufptr);
@@ -508,7 +495,7 @@ int sock_close(SOCKET sock, char *errbuf, int errbuflen)
*/
if (shutdown(sock, SHUT_WR))
{
sock_geterror("shutdown(): ", errbuf, errbuflen);
sock_geterror("shutdown()", errbuf, errbuflen);
/* close the socket anyway */
closesocket(sock);
return -1;
@@ -518,6 +505,157 @@ int sock_close(SOCKET sock, char *errbuf, int errbuflen)
return 0;
}
/*
* gai_errstring() has some problems:
*
* 1) on Windows, Microsoft explicitly says it's not thread-safe;
* 2) on UN*X, the Single UNIX Specification doesn't say it *is*
* thread-safe, so an implementation might use a static buffer
* for unknown error codes;
* 3) the error message for the most likely error, EAI_NONAME, is
* truly horrible on several platforms ("nodename nor servname
* provided, or not known"? It's typically going to be "not
* known", not "oopsie, I passed null pointers for the host name
* and service name", not to mention they forgot the "neither");
*
* so we roll our own.
*/
static void
get_gai_errstring(char *errbuf, int errbuflen, const char *prefix, int err,
const char *hostname, const char *portname)
{
char hostport[PCAP_ERRBUF_SIZE];
if (hostname != NULL && portname != NULL)
pcap_snprintf(hostport, PCAP_ERRBUF_SIZE, "%s:%s",
hostname, portname);
else if (hostname != NULL)
pcap_snprintf(hostport, PCAP_ERRBUF_SIZE, "%s",
hostname);
else if (portname != NULL)
pcap_snprintf(hostport, PCAP_ERRBUF_SIZE, ":%s",
portname);
else
pcap_snprintf(hostport, PCAP_ERRBUF_SIZE, "<no host or port!>");
switch (err)
{
#ifdef EAI_ADDRFAMILY
case EAI_ADDRFAMILY:
pcap_snprintf(errbuf, errbuflen,
"%sAddress family for %s not supported",
prefix, hostport);
break;
#endif
case EAI_AGAIN:
pcap_snprintf(errbuf, errbuflen,
"%s%s could not be resolved at this time",
prefix, hostport);
break;
case EAI_BADFLAGS:
pcap_snprintf(errbuf, errbuflen,
"%sThe ai_flags parameter for looking up %s had an invalid value",
prefix, hostport);
break;
case EAI_FAIL:
pcap_snprintf(errbuf, errbuflen,
"%sA non-recoverable error occurred when attempting to resolve %s",
prefix, hostport);
break;
case EAI_FAMILY:
pcap_snprintf(errbuf, errbuflen,
"%sThe address family for looking up %s was not recognized",
prefix, hostport);
break;
case EAI_MEMORY:
pcap_snprintf(errbuf, errbuflen,
"%sOut of memory trying to allocate storage when looking up %s",
prefix, hostport);
break;
/*
* RFC 2553 had both EAI_NODATA and EAI_NONAME.
*
* RFC 3493 has only EAI_NONAME.
*
* Some implementations define EAI_NODATA and EAI_NONAME
* to the same value, others don't. If EAI_NODATA is
* defined and isn't the same as EAI_NONAME, we handle
* EAI_NODATA.
*/
#if defined(EAI_NODATA) && EAI_NODATA != EAI_NONAME
case EAI_NODATA:
pcap_snprintf(errbuf, errbuflen,
"%sNo address associated with %s",
prefix, hostport);
break;
#endif
case EAI_NONAME:
pcap_snprintf(errbuf, errbuflen,
"%sThe host name %s couldn't be resolved",
prefix, hostport);
break;
case EAI_SERVICE:
pcap_snprintf(errbuf, errbuflen,
"%sThe service value specified when looking up %s as not recognized for the socket type",
prefix, hostport);
break;
case EAI_SOCKTYPE:
pcap_snprintf(errbuf, errbuflen,
"%sThe socket type specified when looking up %s as not recognized",
prefix, hostport);
break;
#ifdef EAI_SYSTEM
case EAI_SYSTEM:
/*
* Assumed to be UN*X.
*/
pcap_snprintf(errbuf, errbuflen,
"%sAn error occurred when looking up %s: %s",
prefix, hostport, pcap_strerror(errno));
break;
#endif
#ifdef EAI_BADHINTS
case EAI_BADHINTS:
pcap_snprintf(errbuf, errbuflen,
"%sInvalid value for hints when looking up %s",
prefix, hostport);
break;
#endif
#ifdef EAI_PROTOCOL
case EAI_PROTOCOL:
pcap_snprintf(errbuf, errbuflen,
"%sResolved protocol when looking up %s is unknown",
prefix, hostport);
break;
#endif
#ifdef EAI_OVERFLOW
case EAI_OVERFLOW:
pcap_snprintf(errbuf, errbuflen,
"%sArgument buffer overflow when looking up %s",
prefix, hostport);
break;
#endif
default:
pcap_snprintf(errbuf, errbuflen,
"%sgetaddrinfo() error %d when looking up %s",
prefix, err, hostport);
break;
}
}
/*
* \brief Checks that the address, port and flags given are valids and it returns an 'addrinfo' structure.
*
@@ -564,17 +702,10 @@ int sock_initaddress(const char *host, const char *port,
retval = getaddrinfo(host, port, hints, addrinfo);
if (retval != 0)
{
/*
* if the getaddrinfo() fails, you have to use gai_strerror(), instead of using the standard
* error routines (errno) in UNIX; Winsock suggests using the GetLastError() instead.
*/
if (errbuf)
{
#ifdef _WIN32
sock_geterror("getaddrinfo(): ", errbuf, errbuflen);
#else
pcap_snprintf(errbuf, errbuflen, "getaddrinfo() %s", gai_strerror(retval));
#endif
get_gai_errstring(errbuf, errbuflen, "", retval,
host, port);
}
return -1;
}
@@ -655,7 +786,7 @@ int sock_send(SOCKET sock, const char *buffer, size_t size,
if (errbuf)
{
pcap_snprintf(errbuf, errbuflen,
"Can't send more than %u bytes with sock_recv",
"Can't send more than %u bytes with sock_send",
INT_MAX);
}
return -1;
@@ -697,7 +828,7 @@ int sock_send(SOCKET sock, const char *buffer, size_t size,
*/
return -2;
}
sock_fmterror("send(): ", errcode, errbuf, errbuflen);
sock_fmterror("send()", errcode, errbuf, errbuflen);
#else
errcode = errno;
if (errcode == ECONNRESET || errcode == EPIPE)
@@ -709,7 +840,7 @@ int sock_send(SOCKET sock, const char *buffer, size_t size,
*/
return -2;
}
sock_fmterror("send(): ", errcode, errbuf, errbuflen);
sock_fmterror("send()", errcode, errbuf, errbuflen);
#endif
return -1;
}
@@ -848,7 +979,6 @@ int sock_recv(SOCKET sock, void *buffer, size_t size, int flags,
if (size == 0)
{
SOCK_DEBUG_MESSAGE("I have been requested to read zero bytes");
return 0;
}
if (size > INT_MAX)
@@ -878,7 +1008,7 @@ int sock_recv(SOCKET sock, void *buffer, size_t size, int flags,
if (errno == EINTR)
return -3;
#endif
sock_geterror("recv(): ", errbuf, errbuflen);
sock_geterror("recv()", errbuf, errbuflen);
return -1;
}
@@ -939,7 +1069,6 @@ int sock_recv_dgram(SOCKET sock, void *buffer, size_t size,
if (size == 0)
{
SOCK_DEBUG_MESSAGE("I have been requested to read zero bytes");
return 0;
}
if (size > INT_MAX)
@@ -975,7 +1104,7 @@ int sock_recv_dgram(SOCKET sock, void *buffer, size_t size,
* supplied to us, the excess data is discarded,
* and we'll report an error.
*/
sock_geterror("recv(): ", errbuf, errbuflen);
sock_geterror("recv()", errbuf, errbuflen);
return -1;
}
#else /* _WIN32 */
@@ -1008,7 +1137,7 @@ int sock_recv_dgram(SOCKET sock, void *buffer, size_t size,
{
if (errno == EINTR)
return -3;
sock_geterror("recv(): ", errbuf, errbuflen);
sock_geterror("recv()", errbuf, errbuflen);
return -1;
}
#ifdef HAVE_STRUCT_MSGHDR_MSG_FLAGS
@@ -1095,8 +1224,6 @@ int sock_discard(SOCKET sock, int size, char *errbuf, int errbuflen)
return -1;
}
SOCK_DEBUG_MESSAGE("I'm currently discarding data\n");
return 0;
}
@@ -1137,6 +1264,7 @@ int sock_check_hostlist(char *hostlist, const char *sep, struct sockaddr_storage
struct addrinfo *addrinfo, *ai_next;
char *temphostlist;
char *lasts;
int getaddrinfo_failed = 0;
/*
* The problem is that strtok modifies the original variable by putting '0' at the end of each token
@@ -1164,13 +1292,19 @@ int sock_check_hostlist(char *hostlist, const char *sep, struct sockaddr_storage
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
retval = getaddrinfo(token, "0", &hints, &addrinfo);
retval = getaddrinfo(token, NULL, &hints, &addrinfo);
if (retval != 0)
{
if (errbuf)
pcap_snprintf(errbuf, errbuflen, "getaddrinfo() %s", gai_strerror(retval));
get_gai_errstring(errbuf, errbuflen,
"Allowed host list error: ",
retval, token, NULL);
SOCK_DEBUG_MESSAGE(errbuf);
/*
* Note that at least one call to getaddrinfo()
* failed.
*/
getaddrinfo_failed = 1;
/* Get next token */
token = pcap_strtok_r(NULL, sep, &lasts);
@@ -1208,11 +1342,25 @@ int sock_check_hostlist(char *hostlist, const char *sep, struct sockaddr_storage
addrinfo = NULL;
}
if (errbuf)
pcap_snprintf(errbuf, errbuflen, "The host is not in the allowed host list. Connection refused.");
free(temphostlist);
return -1;
if (getaddrinfo_failed) {
/*
* At least one getaddrinfo() call failed;
* treat that as an error, so rpcapd knows
* that it should log it locally as well
* as telling the client about it.
*/
return -2;
} else {
/*
* All getaddrinfo() calls succeeded, but
* the host wasn't in the list.
*/
if (errbuf)
pcap_snprintf(errbuf, errbuflen, "The host is not in the allowed host list. Connection refused.");
return -1;
}
}
/* No hostlist, so we have to return 'empty list' */
@@ -1311,7 +1459,7 @@ int sock_getmyinfo(SOCKET sock, char *address, int addrlen, char *port, int port
if (getsockname(sock, (struct sockaddr *) &mysockaddr, &sockaddrlen) == -1)
{
sock_geterror("getsockname(): ", errbuf, errbuflen);
sock_geterror("getsockname()", errbuf, errbuflen);
return 0;
}
@@ -1389,7 +1537,7 @@ int sock_getascii_addrport(const struct sockaddr_storage *sockaddr, char *addres
(memcmp(&((struct sockaddr_in6 *) sockaddr)->sin6_addr, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", sizeof(struct in6_addr)) == 0))
{
if (address)
strlcpy(address, SOCKET_NAME_NULL_DAD, addrlen);
pcap_strlcpy(address, SOCKET_NAME_NULL_DAD, addrlen);
return retval;
}
}
@@ -1399,19 +1547,19 @@ int sock_getascii_addrport(const struct sockaddr_storage *sockaddr, char *addres
/* If the user wants to receive an error message */
if (errbuf)
{
sock_geterror("getnameinfo(): ", errbuf, errbuflen);
sock_geterror("getnameinfo()", errbuf, errbuflen);
errbuf[errbuflen - 1] = 0;
}
if (address)
{
strlcpy(address, SOCKET_NO_NAME_AVAILABLE, addrlen);
pcap_strlcpy(address, SOCKET_NO_NAME_AVAILABLE, addrlen);
address[addrlen - 1] = 0;
}
if (port)
{
strlcpy(port, SOCKET_NO_PORT_AVAILABLE, portlen);
pcap_strlcpy(port, SOCKET_NO_PORT_AVAILABLE, portlen);
port[portlen - 1] = 0;
}