check_function_exists(strlcat HAVE_STRLCAT)
check_function_exists(snprintf HAVE_SNPRINTF)
check_function_exists(vsnprintf HAVE_VSNPRINTF)
+check_function_exists(asprintf HAVE_ASPRINTF)
+check_function_exists(vasprintf HAVE_VASPRINTF)
check_function_exists(strtok_r HAVE_STRTOK_R)
if(NOT WIN32)
check_function_exists(vsyslog HAVE_VSYSLOG)
)
if(WIN32)
- set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} missing/win_snprintf.c)
+ #
+ # For now, we assume we don't have snprintf() or that it's not one
+ # that behaves enough like C99's snprintf() for our purposes (i.e.,
+ # it doesn't null-terminate the string if it truncates it to fit in
+ # the buffer), so we have to provide our own (a wrapper around
+ # _snprintf() that null-terminates the buffer).
+ #
+ # We also assume we don't have asprintf(), and provide an implementation
+ # that uses _vscprintf() to determine how big the string needs to be.
+ #
+ set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C}
+ missing/win_snprintf.c, missing/win_asprintf.c)
else()
+ #
+ # Either:
+ #
+ # we have snprintf() and vsnprintf(), and have asprintf() and
+ # vasprintf();
+ #
+ # we have snprintf() and vsnprintf(), but don't have asprintf()
+ # or vasprintf();
+ #
+ # we have neither snprintf() nor vsnprintf(), and don't have
+ # asprintf() or vasprintf(), either.
+ #
+ # We assume that if we have asprintf() we have vasprintf(), as well
+ # as snprintf() and vsnprintf(), and that if we have snprintf() we
+ # have vsnprintf().
+ #
+ # For the first case, we don't need any replacement routines.
+ # For the second case, we need replacement asprintf()/vasprintf()
+ # routines.
+ # For the third case, we need replacement snprintf()/vsnprintf() and
+ # asprintf()/vasprintf() routines.
+ #
if(NOT HAVE_SNPRINTF)
+ #
+ # We assume we have none of them; missing/snprintf.c supplies
+ # all of them.
+ #
set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} missing/snprintf.c)
- endif(NOT HAVE_SNPRINTF)
+ elif(NOT HAVE_ASPRINTF)
+ #
+ # We assume we have snprintf()/vsnprintf() but lack
+ # asprintf()/vasprintf(); missing/asprintf.c supplies
+ # the latter (using vsnprintf()).
+ #
+ set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} missing/asprintf.c)
+ endif()
if(NOT HAVE_STRLCAT)
set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} missing/strlcat.c)
endif(NOT HAVE_STRLCAT)
lbl/os-sunos4.h \
lbl/os-ultrix4.h \
libpcap.pc.in \
+ missing/asprintf.c \
missing/getopt.c \
missing/getopt.h \
missing/snprintf.c \
missing/strlcat.c \
missing/strlcpy.c \
missing/strtok_r.c \
+ missing/win_asprintf.c \
missing/win_snprintf.c \
mkdep \
msdos/bin2c.c \
gencode.o: $(srcdir)/gencode.c grammar.h scanner.h
$(CC) $(FULL_CFLAGS) -c $(srcdir)/gencode.c
+asprintf.o: $(srcdir)/missing/asprintf.c
+ $(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/asprintf.c
+
snprintf.o: $(srcdir)/missing/snprintf.c
$(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/snprintf.c
/* define if we have the AIX getprotobyname_r() */
#cmakedefine HAVE_AIX_GETPROTOBYNAME_R 1
+/* Define to 1 if you have the `asprintf' function. */
+#cmakedefine HAVE_ASPRINTF 1
+
/* define if you have the DAG API */
#cmakedefine HAVE_DAG_API 1
/* Define to 1 if you have the <unistd.h> header file. */
#cmakedefine HAVE_UNISTD_H 1
+/* Define to 1 if you have the `vasprintf' function. */
+#cmakedefine HAVE_VASPRINTF 1
+
/* Define to 1 if you have the `vsnprintf' function. */
#cmakedefine HAVE_VSNPRINTF 1
/* define if we have the AIX getprotobyname_r() */
#undef HAVE_AIX_GETPROTOBYNAME_R
+/* Define to 1 if you have the `asprintf' function. */
+#undef HAVE_ASPRINTF
+
/* Define to 1 if you have the <dagapi.h> header file. */
#undef HAVE_DAGAPI_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
+/* Define to 1 if you have the `vasprintf' function. */
+#undef HAVE_VASPRINTF
+
/* Define to 1 if you have the `vsnprintf' function. */
#undef HAVE_VSNPRINTF
done
+#
+# Either:
+#
+# we have snprintf() and vsnprintf(), and have asprintf() and
+# vasprintf();
+#
+# we have snprintf() and vsnprintf(), but don't have asprintf()
+# or vasprintf();
+#
+# we have neither snprintf() nor vsnprintf(), and don't have
+# asprintf() or vasprintf(), either.
+#
+# We assume that if we have asprintf() we have vasprintf(), as well
+# as snprintf() and vsnprintf(), and that if we have snprintf() we
+# have vsnprintf().
+#
+# For the first case, we don't need any replacement routines.
+# For the second case, we need replacement asprintf()/vasprintf()
+# routines.
+# For the third case, we need replacement snprintf()/vsnprintf() and
+# asprintf()/vasprintf() routines.
+#
needsnprintf=no
for ac_func in vsnprintf snprintf
do :
fi
done
+needasprintf=no
+for ac_func in vasprintf asprintf
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+ needasprintf=yes
+fi
+done
+
if test $needsnprintf = yes; then
+ #
+ # We assume we have none of them; missing/snprintf.c supplies
+ # all of them.
+ #
case " $LIBOBJS " in
*" snprintf.$ac_objext "* ) ;;
*) LIBOBJS="$LIBOBJS snprintf.$ac_objext"
;;
esac
+elif test $needasprintf = yes; then
+ #
+ # We assume we have snprintf()/vsnprintf() but lack
+ # asprintf()/vasprintf(); missing/asprintf.c supplies
+ # the latter (using vsnprintf()).
+ #
+ case " $LIBOBJS " in
+ *" asprintf.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS asprintf.$ac_objext"
+ ;;
+esac
+
fi
needstrlcat=no
#
AC_CHECK_FUNCS(vsyslog)
+#
+# Either:
+#
+# we have snprintf() and vsnprintf(), and have asprintf() and
+# vasprintf();
+#
+# we have snprintf() and vsnprintf(), but don't have asprintf()
+# or vasprintf();
+#
+# we have neither snprintf() nor vsnprintf(), and don't have
+# asprintf() or vasprintf(), either.
+#
+# We assume that if we have asprintf() we have vasprintf(), as well
+# as snprintf() and vsnprintf(), and that if we have snprintf() we
+# have vsnprintf().
+#
+# For the first case, we don't need any replacement routines.
+# For the second case, we need replacement asprintf()/vasprintf()
+# routines.
+# For the third case, we need replacement snprintf()/vsnprintf() and
+# asprintf()/vasprintf() routines.
+#
needsnprintf=no
AC_CHECK_FUNCS(vsnprintf snprintf,,
[needsnprintf=yes])
+needasprintf=no
+AC_CHECK_FUNCS(vasprintf asprintf,,
+ [needasprintf=yes])
if test $needsnprintf = yes; then
+ #
+ # We assume we have none of them; missing/snprintf.c supplies
+ # all of them.
+ #
AC_LIBOBJ([snprintf])
+elif test $needasprintf = yes; then
+ #
+ # We assume we have snprintf()/vsnprintf() but lack
+ # asprintf()/vasprintf(); missing/asprintf.c supplies
+ # the latter (using vsnprintf()).
+ #
+ AC_LIBOBJ([asprintf])
fi
needstrlcat=no
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "portability.h"
+
+/*
+ * vasprintf() and asprintf() for platforms with a C99-compliant
+ * snprintf() - so that, if you format into a 1-byte buffer, it
+ * will return how many characters it would have produced had
+ * it been given an infinite-sized buffer.
+ */
+int
+pcap_vasprintf(char **strp, const char *format, va_list args)
+{
+ char buf;
+ int len;
+ size_t str_size;
+ char *str;
+ int ret;
+
+ /*
+ * XXX - the C99 standard says, in section 7.19.6.5 "Thes
+ * nprintf function":
+ *
+ * The snprintf function is equivalent to fprintf, except that
+ * the output is written into an array (specified by argument s)
+ * rather than to a stream. If n is zero, nothing is written,
+ * and s may be a null pointer. Otherwise, output characters
+ * beyond the n-1st are discarded rather than being written
+ * to the array, and a null character is written at the end
+ * of the characters actually written into the array.
+ *
+ * ...
+ *
+ * The snprintf function returns the number of characters that
+ * would have been written had n been sufficiently large, not
+ * counting the terminating null character, or a negative value
+ * if an encoding error occurred. Thus, the null-terminated
+ * output has been completely written if and only if the returned
+ * value is nonnegative and less than n.
+ *
+ * That doesn't make it entirely clear whether, if a null buffer
+ * pointer and a zero count are passed, it will return the number
+ * of characters that would have been written had a buffer been
+ * passed.
+ *
+ * And, even if C99 *does*, in fact, say it has to work, it
+ * doesn't work in Solaris 8, for example - it returns -1 for
+ * NULL/0, but returns the correct character count for a 1-byte
+ * buffer.
+ *
+ * So we pass a one-character pointer in order to find out how
+ * many characters this format and those arguments will need
+ * without actually generating any more of those characters
+ * than we need.
+ *
+ * (The fact that it might happen to work with GNU libc or with
+ * various BSD libcs is completely uninteresting, as those tend
+ * to have asprintf() already and thus don't even *need* this
+ * code; this is for use in those UN*Xes that *don't* have
+ * asprintf().)
+ */
+ len = vsnprintf(&buf, sizeof buf, format, args);
+ if (len == -1) {
+ *strp = NULL;
+ return (-1);
+ }
+ str_size = len + 1;
+ str = malloc(str_size);
+ if (str == NULL) {
+ *strp = NULL;
+ return (-1);
+ }
+ ret = vsnprintf(str, str_size, format, args);
+ if (ret == -1) {
+ free(str);
+ *strp = NULL;
+ return (-1);
+ }
+ *strp = str;
+ /*
+ * vsnprintf() shouldn't truncate the string, as we have
+ * allocated a buffer large enough to hold the string, so its
+ * return value should be the number of characters written.
+ */
+ return (ret);
+}
+
+int
+pcap_asprintf(char **strp, const char *format, ...)
+{
+ va_list args;
+ int ret;
+
+ va_start(args, format);
+ ret = pcap_vasprintf(strp, format, args);
+ va_end(args);
+ return (ret);
+}
+
* SUCH DAMAGE.
*/
+/*
+ * We use this for platforms that don't have snprintf() at all.
+ */
+
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <ctype.h>
#include <sys/types.h>
-#include <pcap-int.h>
+#include "portability.h"
enum format_flags {
minus_flag = 1,
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "portability.h"
+
+int
+pcap_vasprintf(char **strp, const char *format, va_list args)
+{
+ int len;
+ size_t str_size;
+ char *str;
+ int ret;
+
+ len = _vscprintf(format, args);
+ if (len == -1) {
+ *strp = NULL;
+ return (-1);
+ }
+ str_size = len + 1;
+ str = malloc(str_size);
+ if (str == NULL) {
+ *strp = NULL;
+ return (-1);
+ }
+ ret = pcap_vsnprintf(str, str_size, format, args);
+ if (ret == -1) {
+ free(str);
+ *strp = NULL;
+ return (-1);
+ }
+ *strp = str;
+ /*
+ * pcap_vsnprintf() shouldn't truncate the string, as we have
+ * allocated a buffer large enough to hold the string, so its
+ * return value should be the number of characters printed.
+ */
+ return (ret);
+}
+
+int
+pcap_asprintf(char **strp, const char *format, ...)
+{
+ va_list args;
+ int ret;
+
+ va_start(args, format);
+ ret = pcap_vasprintf(strp, format, args);
+ va_end(args);
+ return (ret);
+}
#include <stdio.h>
#include <stdarg.h>
+#include "portability.h"
+
int
pcap_vsnprintf(char *str, size_t str_size, const char *format, va_list args)
{
* that str is null-terminated, but C99's vsnprintf()
* and snprintf() do, and we want to offer C99 behavior,
* so forcibly null-terminate the string.
+ *
+ * We don't, however, offer C99 behavior for the return
+ * value; _vsnprintf_s() returns -1, not the number of
+ * characters that would have been put into the buffer
+ * had it been large enough, if the string is truncated.
+ * The only way to get that value is to use _vscprintf();
+ * getting that count isn't worth the re-formatting.
+ *
+ * XXX - does _vsnprintf_s() return -1 on a formatting
+ * error?
*/
str[str_size - 1] = '\0';
return (ret);
/*
* Create the description.
- * First, allocate a buffer large enough
- * for the name.
*/
if ((dev->description == NULL) || (dev->description[0] == 0))
localdesc = dev->name;
else
localdesc = dev->description;
- stringlen = PCAP_TEXT_SOURCE_ADAPTER_LEN
- + 1 + 1 /* space and ' */
- + strlen(localdesc)
- + 1 + 1 /* ' and space */
- + PCAP_TEXT_SOURCE_ON_LOCAL_HOST_LEN
- + 1; /* terminating '\0' */
- desc = (char *)malloc(stringlen);
- if (desc == NULL)
+ if (pcap_asprintf(&desc, "%s '%s' %s",
+ PCAP_TEXT_SOURCE_ADAPTER, localdesc,
+ PCAP_TEXT_SOURCE_ON_LOCAL_HOST) == -1)
{
pcap_fmt_errmsg_for_errno(errbuf,
PCAP_ERRBUF_SIZE, errno,
pcap_freealldevs(*alldevs);
return -1;
}
- pcap_snprintf(desc, stringlen, "%s '%s' %s",
- PCAP_TEXT_SOURCE_ADAPTER, localdesc,
- PCAP_TEXT_SOURCE_ON_LOCAL_HOST);
/* Now overwrite the description */
free(dev->description);
/*
* Create the description.
- * First, allocate a buffer large enough
- * for the name.
*/
- stringlen = PCAP_TEXT_SOURCE_FILE_LEN
- + 1 + 1 /* space and ' */
- + strlen(filename)
- + 1 + 1 /* ' and space */
- + PCAP_TEXT_SOURCE_ON_LOCAL_HOST_LEN
- + 1; /* terminating '\0' */
- dev->description = (char *)malloc(stringlen);
- if (dev->description == NULL)
+ if (pcap_asprintf(&dev->description,
+ "%s '%s' %s", PCAP_TEXT_SOURCE_FILE,
+ filename, PCAP_TEXT_SOURCE_ON_LOCAL_HOST) == -1)
{
pcap_fmt_errmsg_for_errno(errbuf,
PCAP_ERRBUF_SIZE, errno,
return -1;
}
- /*
- * Now format the new device description
- * into that buffer.
- */
- pcap_snprintf(dev->description, stringlen,
- "%s '%s' %s", PCAP_TEXT_SOURCE_FILE,
- filename, PCAP_TEXT_SOURCE_ON_LOCAL_HOST);
-
pcap_close(fp);
}
}
static const char pcap_version_string[] =
WINPCAP_PRODUCT_NAME " version " WINPCAP_VER_STRING ", based on " PCAP_VERSION_STRING;
-static const char pcap_version_string_packet_dll_fmt[] =
- WINPCAP_PRODUCT_NAME " version " WINPCAP_VER_STRING " (packet.dll version %s), based on " PCAP_VERSION_STRING;
const char *
pcap_lib_version(void)
{
- char *packet_version_string;
- size_t full_pcap_version_string_len;
- char *full_pcap_version_string;
-
if (pcap_lib_version_string == NULL) {
/*
* Generate the version string.
*/
- packet_version_string = PacketGetVersion();
+ char *packet_version_string = PacketGetVersion();
+
if (strcmp(WINPCAP_VER_STRING, packet_version_string) == 0) {
/*
* WinPcap version string and packet.dll version
* case (the two libraries should come from the
* same version of WinPcap), so we report both
* versions.
- *
- * The -2 is for the %s in the format string,
- * which will be replaced by packet_version_string.
*/
- full_pcap_version_string_len =
- (sizeof pcap_version_string_packet_dll_fmt - 2) +
- strlen(packet_version_string);
- full_pcap_version_string = malloc(full_pcap_version_string_len);
- if (full_pcap_version_string == NULL)
- return (NULL);
- pcap_snprintf(full_pcap_version_string,
- full_pcap_version_string_len,
- pcap_version_string_packet_dll_fmt,
- packet_version_string);
+ if (pcap_asprintf(&pcap_lib_version_string,
+ WINPCAP_PRODUCT_NAME " version " WINPCAP_VER_STRING " (packet.dll version %s), based on " PCAP_VERSION_STRING,
+ packet_version_string) == -1) {
+ /* Failed. */
+ pcap_lib_version_string = NULL;
+ }
}
- pcap_lib_version_string = full_pcap_version_string;
}
return (pcap_lib_version_string);
}
* libpcap being built for Windows, not as part of a WinPcap/Npcap source
* tree.
*/
-static const char pcap_version_string_packet_dll_fmt[] =
- PCAP_VERSION_STRING " (packet.dll version %s)";
const char *
pcap_lib_version(void)
{
- char *packet_version_string;
- size_t full_pcap_version_string_len;
- char *full_pcap_version_string;
-
if (pcap_lib_version_string == NULL) {
/*
* Generate the version string. Report the packet.dll
* version.
- *
- * The -2 is for the %s in the format string, which will
- * be replaced by packet_version_string.
*/
- packet_version_string = PacketGetVersion();
- full_pcap_version_string_len =
- (sizeof pcap_version_string_packet_dll_fmt - 2) +
- strlen(packet_version_string);
- full_pcap_version_string = malloc(full_pcap_version_string_len);
- if (full_pcap_version_string == NULL)
- return (NULL);
- pcap_snprintf(full_pcap_version_string,
- full_pcap_version_string_len,
- pcap_version_string_packet_dll_fmt,
- packet_version_string);
- pcap_lib_version_string = full_pcap_version_string;
+ if (pcap_asprintf(&pcap_lib_version_string,
+ PCAP_VERSION_STRING " (packet.dll version %s)",
+ PacketGetVersion()) == -1) {
+ /* Failed. */
+ pcap_lib_version_string = NULL;
+ }
}
return (pcap_lib_version_string);
}
char peeraddress[128];
char peerctrlport[128];
char *newfilter;
- const int newstringsize = 1024;
- size_t currentfiltersize;
/* Get the name/port of our peer */
saddrlen = sizeof(struct sockaddr_storage);
return -1;
}
- currentfiltersize = pr->currentfilter ? strlen(pr->currentfilter) : 0;
-
- newfilter = (char *)malloc(currentfiltersize + newstringsize + 1);
-
- if (currentfiltersize)
+ if (pr->currentfilter && pr->currentfilter[0] != '\0')
{
- pcap_snprintf(newfilter, currentfiltersize + newstringsize,
- "(%s) and not (host %s and host %s and port %s and port %s) and not (host %s and host %s and port %s)",
- pr->currentfilter, myaddress, peeraddress, myctrlport, peerctrlport, myaddress, peeraddress, mydataport);
+ /*
+ * We have a current filter; add items to it to
+ * filter out this rpcap session.
+ */
+ if (pcap_asprintf(&newfilter,
+ "(%s) and not (host %s and host %s and port %s and port %s) and not (host %s and host %s and port %s)",
+ pr->currentfilter, myaddress, peeraddress,
+ myctrlport, peerctrlport, myaddress, peeraddress,
+ mydataport) == -1)
+ {
+ /* Failed. */
+ pcap_snprintf(fp->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't allocate memory for new filter");
+ return -1;
+ }
}
else
{
- pcap_snprintf(newfilter, currentfiltersize + newstringsize,
- "not (host %s and host %s and port %s and port %s) and not (host %s and host %s and port %s)",
- myaddress, peeraddress, myctrlport, peerctrlport, myaddress, peeraddress, mydataport);
+ /*
+ * We have no current filter; construct a filter to
+ * filter out this rpcap session.
+ */
+ if (pcap_asprintf(&newfilter,
+ "not (host %s and host %s and port %s and port %s) and not (host %s and host %s and port %s)",
+ myaddress, peeraddress, myctrlport, peerctrlport,
+ myaddress, peeraddress, mydataport) == -1)
+ {
+ /* Failed. */
+ pcap_snprintf(fp->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't allocate memory for new filter");
+ return -1;
+ }
}
- newfilter[currentfiltersize + newstringsize] = 0;
-
/*
* This is only an hack to prevent the save_current_filter
* routine, which will be called when we call pcap_compile(),
{
struct rpcap_findalldevs_if findalldevs_if;
char tmpstring2[PCAP_BUF_SIZE + 1]; /* Needed to convert names and descriptions from 'old' syntax to the 'new' one */
- size_t stringlen;
struct pcap_addr *addr, *prevaddr;
tmpstring2[PCAP_BUF_SIZE] = 0;
tmpstring[findalldevs_if.desclen] = 0;
- stringlen = PCAP_TEXT_SOURCE_ADAPTER_LEN
- + 1 + 1 /* space and ' */
- + strlen(tmpstring)
- + 1 + 1 /* ' and space */
- + PCAP_TEXT_SOURCE_ON_REMOTE_HOST_LEN
- + 1 /* space */
- + strlen(host)
- + 1; /* terminating '\0' */
- dev->description = (char *)malloc(stringlen);
- if (dev->description == NULL)
+ if (pcap_asprintf(&dev->description,
+ "%s '%s' %s %s", PCAP_TEXT_SOURCE_ADAPTER,
+ tmpstring, PCAP_TEXT_SOURCE_ON_REMOTE_HOST, host) == -1)
{
pcap_fmt_errmsg_for_errno(errbuf,
PCAP_ERRBUF_SIZE, errno, "malloc() failed");
goto error;
}
-
- /*
- * Now format the new device description into
- * that buffer.
- */
- pcap_snprintf(dev->description, stringlen,
- "%s '%s' %s %s", PCAP_TEXT_SOURCE_ADAPTER,
- tmpstring, PCAP_TEXT_SOURCE_ON_REMOTE_HOST, host);
}
dev->flags = ntohl(findalldevs_if.flags);
* OK, it's a valid number that's not
* bigger than INT_MAX. Construct
* a description from it.
+ * (If that fails, we don't worry about
+ * it, we just return NULL.)
*/
- static const char descr_prefix[] = "USB bus number ";
- size_t descr_size;
-
- /*
- * Allow enough room for a 32-bit bus number.
- * sizeof (descr_prefix) includes the
- * terminating NUL.
- */
- descr_size = sizeof (descr_prefix) + 10;
- description = malloc(descr_size);
- if (description != NULL) {
- pcap_snprintf(description, descr_size,
- "%s%ld", descr_prefix, busnum);
+ if (pcap_asprintf(&description,
+ "USB bus number %ld", busnum) == -1) {
+ /* Failed. */
+ description = NULL;
}
}
}
* Helpers for portability between Windows and UN*X and between different
* flavors of UN*X.
*/
+#include <stdarg.h> /* we declare varargs functions on some platforms */
#include "pcap/funcattrs.h"
extern int pcap_vsnprintf(char *, size_t, const char *, va_list ap);
#endif
+/*
+ * We also want asprintf(), for some cases where we use it to construct
+ * dynamically-allocated variable-length strings.
+ */
+#ifdef HAVE_ASPRINTF
+#define pcap_asprintf asprintf
+#else
+extern int pcap_asprintf(char **, PCAP_FORMAT_STRING(const char *), ...)
+ PCAP_PRINTFLIKE(2, 3);
+#endif
+
+#ifdef HAVE_VASPRINTF
+#define pcap_vasprintf vasprintf
+#else
+extern int pcap_vasprintf(char **, const char *, va_list ap);
+#endif
+
#ifdef HAVE_STRTOK_R
#define pcap_strtok_r strtok_r
#else