+/*
+ * Do whatever initialization is needed for libpcap.
+ *
+ * The argument specifies whether we use the local code page or UTF-8
+ * for strings; on UN*X, we just assume UTF-8 in places where the encoding
+ * would matter, whereas, on Windows, we use the local code page for
+ * PCAP_CHAR_ENC_LOCAL and UTF-8 for PCAP_CHAR_ENC_UTF_8.
+ *
+ * On Windows, we also disable the hack in pcap_create() to deal with
+ * being handed UTF-16 strings, because if the user calls this they're
+ * explicitly declaring that they will either be passing local code
+ * page strings or UTF-8 strings, so we don't need to allow UTF-16LE
+ * strings to be passed. For good measure, on Windows *and* UN*X,
+ * we disable pcap_lookupdev(), to prevent anybody from even
+ * *trying* to pass the result of pcap_lookupdev() - which might be
+ * UTF-16LE on Windows, for ugly compatibility reasons - to pcap_create()
+ * or pcap_open_live() or pcap_open().
+ *
+ * Returns 0 on success, -1 on error.
+ */
+int pcap_new_api; /* pcap_lookupdev() always fails */
+int pcap_utf_8_mode; /* Strings should be in UTF-8. */
+
+int
+pcap_init(unsigned int opts, char *errbuf)
+{
+ static int initialized;
+
+ /*
+ * Don't allow multiple calls that set different modes; that
+ * may mean a library is initializing pcap in one mode and
+ * a program using that library, or another library used by
+ * that program, is initializing it in another mode.
+ */
+ switch (opts) {
+
+ case PCAP_CHAR_ENC_LOCAL:
+ /* Leave "UTF-8 mode" off. */
+ if (initialized) {
+ if (pcap_utf_8_mode) {
+ snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "Multiple pcap_init calls with different character encodings");
+ return (PCAP_ERROR);
+ }
+ }
+ break;
+
+ case PCAP_CHAR_ENC_UTF_8:
+ /* Turn on "UTF-8 mode". */
+ if (initialized) {
+ if (!pcap_utf_8_mode) {
+ snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "Multiple pcap_init calls with different character encodings");
+ return (PCAP_ERROR);
+ }
+ }
+ pcap_utf_8_mode = 1;
+ break;
+
+ default:
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, "Unknown options specified");
+ return (PCAP_ERROR);
+ }
+
+ /*
+ * Turn the appropriate mode on for error messages; those routines
+ * are also used in rpcapd, which has no access to pcap's internal
+ * UTF-8 mode flag, so we have to call a routine to set its
+ * UTF-8 mode flag.
+ */
+ pcap_fmt_set_encoding(opts);
+
+ if (initialized) {
+ /*
+ * Nothing more to do; for example, on Windows, we've
+ * already initialized Winsock.
+ */
+ return (0);
+ }
+
+#ifdef _WIN32
+ /*
+ * Now set up Winsock.
+ */
+ if (internal_wsockinit(errbuf) == -1) {
+ /* Failed. */
+ return (PCAP_ERROR);
+ }
+#endif
+
+ /*
+ * We're done.
+ */
+ initialized = 1;
+ pcap_new_api = 1;
+ return (0);
+}
+