1b00ab754SHans Petter Selasky /* 2b00ab754SHans Petter Selasky * Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998 3b00ab754SHans Petter Selasky * The Regents of the University of California. All rights reserved. 4b00ab754SHans Petter Selasky * 5b00ab754SHans Petter Selasky * Redistribution and use in source and binary forms, with or without 6b00ab754SHans Petter Selasky * modification, are permitted provided that the following conditions 7b00ab754SHans Petter Selasky * are met: 8b00ab754SHans Petter Selasky * 1. Redistributions of source code must retain the above copyright 9b00ab754SHans Petter Selasky * notice, this list of conditions and the following disclaimer. 10b00ab754SHans Petter Selasky * 2. Redistributions in binary form must reproduce the above copyright 11b00ab754SHans Petter Selasky * notice, this list of conditions and the following disclaimer in the 12b00ab754SHans Petter Selasky * documentation and/or other materials provided with the distribution. 13b00ab754SHans Petter Selasky * 3. All advertising materials mentioning features or use of this software 14b00ab754SHans Petter Selasky * must display the following acknowledgement: 15b00ab754SHans Petter Selasky * This product includes software developed by the Computer Systems 16b00ab754SHans Petter Selasky * Engineering Group at Lawrence Berkeley Laboratory. 17b00ab754SHans Petter Selasky * 4. Neither the name of the University nor of the Laboratory may be used 18b00ab754SHans Petter Selasky * to endorse or promote products derived from this software without 19b00ab754SHans Petter Selasky * specific prior written permission. 20b00ab754SHans Petter Selasky * 21b00ab754SHans Petter Selasky * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22b00ab754SHans Petter Selasky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23b00ab754SHans Petter Selasky * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24b00ab754SHans Petter Selasky * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25b00ab754SHans Petter Selasky * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26b00ab754SHans Petter Selasky * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27b00ab754SHans Petter Selasky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28b00ab754SHans Petter Selasky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29b00ab754SHans Petter Selasky * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30b00ab754SHans Petter Selasky * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31b00ab754SHans Petter Selasky * SUCH DAMAGE. 32b00ab754SHans Petter Selasky */ 33b00ab754SHans Petter Selasky 34b00ab754SHans Petter Selasky /* 35b00ab754SHans Petter Selasky * Utilities for message formatting used both by libpcap and rpcapd. 36b00ab754SHans Petter Selasky */ 37b00ab754SHans Petter Selasky 38b00ab754SHans Petter Selasky #ifdef HAVE_CONFIG_H 39b00ab754SHans Petter Selasky #include <config.h> 40b00ab754SHans Petter Selasky #endif 41b00ab754SHans Petter Selasky 42b00ab754SHans Petter Selasky #include "ftmacros.h" 43b00ab754SHans Petter Selasky 44b00ab754SHans Petter Selasky #include <stddef.h> 45b00ab754SHans Petter Selasky #include <stdarg.h> 46b00ab754SHans Petter Selasky #include <stdio.h> 47b00ab754SHans Petter Selasky #include <string.h> 48b00ab754SHans Petter Selasky #include <errno.h> 49b00ab754SHans Petter Selasky 50b00ab754SHans Petter Selasky #include <pcap/pcap.h> 51b00ab754SHans Petter Selasky 52b00ab754SHans Petter Selasky #include "portability.h" 53b00ab754SHans Petter Selasky 54b00ab754SHans Petter Selasky #include "fmtutils.h" 55b00ab754SHans Petter Selasky 56b00ab754SHans Petter Selasky /* 57b00ab754SHans Petter Selasky * Generate an error message based on a format, arguments, and an 58b00ab754SHans Petter Selasky * errno, with a message for the errno after the formatted output. 59b00ab754SHans Petter Selasky */ 60b00ab754SHans Petter Selasky void 61b00ab754SHans Petter Selasky pcap_fmt_errmsg_for_errno(char *errbuf, size_t errbuflen, int errnum, 62b00ab754SHans Petter Selasky const char *fmt, ...) 63b00ab754SHans Petter Selasky { 64b00ab754SHans Petter Selasky va_list ap; 65b00ab754SHans Petter Selasky size_t msglen; 66b00ab754SHans Petter Selasky char *p; 67b00ab754SHans Petter Selasky size_t errbuflen_remaining; 68b00ab754SHans Petter Selasky 69b00ab754SHans Petter Selasky va_start(ap, fmt); 70b00ab754SHans Petter Selasky pcap_vsnprintf(errbuf, errbuflen, fmt, ap); 71b00ab754SHans Petter Selasky va_end(ap); 72b00ab754SHans Petter Selasky msglen = strlen(errbuf); 73b00ab754SHans Petter Selasky 74b00ab754SHans Petter Selasky /* 75b00ab754SHans Petter Selasky * Do we have enough space to append ": "? 76b00ab754SHans Petter Selasky * Including the terminating '\0', that's 3 bytes. 77b00ab754SHans Petter Selasky */ 78b00ab754SHans Petter Selasky if (msglen + 3 > errbuflen) { 79b00ab754SHans Petter Selasky /* No - just give them what we've produced. */ 80b00ab754SHans Petter Selasky return; 81b00ab754SHans Petter Selasky } 82b00ab754SHans Petter Selasky p = errbuf + msglen; 83b00ab754SHans Petter Selasky errbuflen_remaining = errbuflen - msglen; 84b00ab754SHans Petter Selasky *p++ = ':'; 85b00ab754SHans Petter Selasky *p++ = ' '; 86b00ab754SHans Petter Selasky *p = '\0'; 87b00ab754SHans Petter Selasky msglen += 2; 88b00ab754SHans Petter Selasky errbuflen_remaining -= 2; 89b00ab754SHans Petter Selasky 90b00ab754SHans Petter Selasky /* 91b00ab754SHans Petter Selasky * Now append the string for the error code. 92b00ab754SHans Petter Selasky */ 93b00ab754SHans Petter Selasky #if defined(HAVE_STRERROR_S) 94*57e22627SCy Schubert /* 95*57e22627SCy Schubert * We have a Windows-style strerror_s(). 96*57e22627SCy Schubert */ 97*57e22627SCy Schubert errno_t err = strerror_s(p, errbuflen_remaining, errnum); 98b00ab754SHans Petter Selasky if (err != 0) { 99b00ab754SHans Petter Selasky /* 100b00ab754SHans Petter Selasky * It doesn't appear to be documented anywhere obvious 101b00ab754SHans Petter Selasky * what the error returns from strerror_s(). 102b00ab754SHans Petter Selasky */ 103b00ab754SHans Petter Selasky pcap_snprintf(p, errbuflen_remaining, "Error %d", errnum); 104b00ab754SHans Petter Selasky } 105*57e22627SCy Schubert #elif defined(HAVE_GNU_STRERROR_R) 106*57e22627SCy Schubert /* 107*57e22627SCy Schubert * We have a GNU-style strerror_r(), which is *not* guaranteed to 108*57e22627SCy Schubert * do anything to the buffer handed to it, and which returns a 109*57e22627SCy Schubert * pointer to the error string, which may or may not be in 110*57e22627SCy Schubert * the buffer. 111*57e22627SCy Schubert * 112*57e22627SCy Schubert * It is, however, guaranteed to succeed. 113*57e22627SCy Schubert */ 114*57e22627SCy Schubert char strerror_buf[PCAP_ERRBUF_SIZE]; 115*57e22627SCy Schubert char *errstring = strerror_r(errnum, strerror_buf, PCAP_ERRBUF_SIZE); 116*57e22627SCy Schubert pcap_snprintf(p, errbuflen_remaining, "%s", errstring); 117*57e22627SCy Schubert #elif defined(HAVE_POSIX_STRERROR_R) 118*57e22627SCy Schubert /* 119*57e22627SCy Schubert * We have a POSIX-style strerror_r(), which is guaranteed to fill 120*57e22627SCy Schubert * in the buffer, but is not guaranteed to succeed. 121*57e22627SCy Schubert */ 122*57e22627SCy Schubert int err = strerror_r(errnum, p, errbuflen_remaining); 123b00ab754SHans Petter Selasky if (err == EINVAL) { 124b00ab754SHans Petter Selasky /* 125b00ab754SHans Petter Selasky * UNIX 03 says this isn't guaranteed to produce a 126b00ab754SHans Petter Selasky * fallback error message. 127b00ab754SHans Petter Selasky */ 128b00ab754SHans Petter Selasky pcap_snprintf(p, errbuflen_remaining, "Unknown error: %d", 129b00ab754SHans Petter Selasky errnum); 130b00ab754SHans Petter Selasky } else if (err == ERANGE) { 131b00ab754SHans Petter Selasky /* 132b00ab754SHans Petter Selasky * UNIX 03 says this isn't guaranteed to produce a 133b00ab754SHans Petter Selasky * fallback error message. 134b00ab754SHans Petter Selasky */ 135b00ab754SHans Petter Selasky pcap_snprintf(p, errbuflen_remaining, 136b00ab754SHans Petter Selasky "Message for error %d is too long", errnum); 137b00ab754SHans Petter Selasky } 138b00ab754SHans Petter Selasky #else 139b00ab754SHans Petter Selasky /* 140b00ab754SHans Petter Selasky * We have neither strerror_s() nor strerror_r(), so we're 141b00ab754SHans Petter Selasky * stuck with using pcap_strerror(). 142b00ab754SHans Petter Selasky */ 143b00ab754SHans Petter Selasky pcap_snprintf(p, errbuflen_remaining, "%s", pcap_strerror(errnum)); 144b00ab754SHans Petter Selasky #endif 145b00ab754SHans Petter Selasky } 146*57e22627SCy Schubert 147*57e22627SCy Schubert #ifdef _WIN32 148*57e22627SCy Schubert /* 149*57e22627SCy Schubert * Generate an error message based on a format, arguments, and a 150*57e22627SCy Schubert * Win32 error, with a message for the Win32 error after the formatted output. 151*57e22627SCy Schubert */ 152*57e22627SCy Schubert void 153*57e22627SCy Schubert pcap_fmt_errmsg_for_win32_err(char *errbuf, size_t errbuflen, DWORD errnum, 154*57e22627SCy Schubert const char *fmt, ...) 155*57e22627SCy Schubert { 156*57e22627SCy Schubert va_list ap; 157*57e22627SCy Schubert size_t msglen; 158*57e22627SCy Schubert char *p; 159*57e22627SCy Schubert size_t errbuflen_remaining; 160*57e22627SCy Schubert DWORD retval; 161*57e22627SCy Schubert char win32_errbuf[PCAP_ERRBUF_SIZE+1]; 162*57e22627SCy Schubert 163*57e22627SCy Schubert va_start(ap, fmt); 164*57e22627SCy Schubert pcap_vsnprintf(errbuf, errbuflen, fmt, ap); 165*57e22627SCy Schubert va_end(ap); 166*57e22627SCy Schubert msglen = strlen(errbuf); 167*57e22627SCy Schubert 168*57e22627SCy Schubert /* 169*57e22627SCy Schubert * Do we have enough space to append ": "? 170*57e22627SCy Schubert * Including the terminating '\0', that's 3 bytes. 171*57e22627SCy Schubert */ 172*57e22627SCy Schubert if (msglen + 3 > errbuflen) { 173*57e22627SCy Schubert /* No - just give them what we've produced. */ 174*57e22627SCy Schubert return; 175*57e22627SCy Schubert } 176*57e22627SCy Schubert p = errbuf + msglen; 177*57e22627SCy Schubert errbuflen_remaining = errbuflen - msglen; 178*57e22627SCy Schubert *p++ = ':'; 179*57e22627SCy Schubert *p++ = ' '; 180*57e22627SCy Schubert *p = '\0'; 181*57e22627SCy Schubert msglen += 2; 182*57e22627SCy Schubert errbuflen_remaining -= 2; 183*57e22627SCy Schubert 184*57e22627SCy Schubert /* 185*57e22627SCy Schubert * Now append the string for the error code. 186*57e22627SCy Schubert * 187*57e22627SCy Schubert * XXX - what language ID to use? 188*57e22627SCy Schubert * 189*57e22627SCy Schubert * For UN*Xes, pcap_strerror() may or may not return localized 190*57e22627SCy Schubert * strings. 191*57e22627SCy Schubert * 192*57e22627SCy Schubert * We currently don't have localized messages for libpcap, but 193*57e22627SCy Schubert * we might want to do so. On the other hand, if most of these 194*57e22627SCy Schubert * messages are going to be read by libpcap developers and 195*57e22627SCy Schubert * perhaps by developers of libpcap-based applications, English 196*57e22627SCy Schubert * might be a better choice, so the developer doesn't have to 197*57e22627SCy Schubert * get the message translated if it's in a language they don't 198*57e22627SCy Schubert * happen to understand. 199*57e22627SCy Schubert */ 200*57e22627SCy Schubert retval = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|FORMAT_MESSAGE_MAX_WIDTH_MASK, 201*57e22627SCy Schubert NULL, errnum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 202*57e22627SCy Schubert win32_errbuf, PCAP_ERRBUF_SIZE, NULL); 203*57e22627SCy Schubert if (retval == 0) { 204*57e22627SCy Schubert /* 205*57e22627SCy Schubert * Failed. 206*57e22627SCy Schubert */ 207*57e22627SCy Schubert pcap_snprintf(p, errbuflen_remaining, 208*57e22627SCy Schubert "Couldn't get error message for error (%lu)", errnum); 209*57e22627SCy Schubert return; 210*57e22627SCy Schubert } 211*57e22627SCy Schubert 212*57e22627SCy Schubert pcap_snprintf(p, errbuflen_remaining, "%s (%lu)", win32_errbuf, errnum); 213*57e22627SCy Schubert } 214*57e22627SCy Schubert #endif 215