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