1 /* vi:ai:et:ts=8 sw=2
2 */
3 /*
4 * wzdftpd - a modular and cool ftp server
5 * Copyright (C) 2002-2004 Pierre Chifflier
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 *
21 * As a special exemption, Pierre Chifflier
22 * and other respective copyright holders give permission to link this program
23 * with OpenSSL, and distribute the resulting executable, without including
24 * the source code for OpenSSL in the source distribution.
25 */
26
27 #include "wzd_all.h"
28
29 #ifndef WZD_USE_PCH
30
31 #if defined(WIN32) || (defined __CYGWIN__ && defined WINSOCK_SUPPORT)
32 #include <winsock2.h>
33 #else
34 #include <unistd.h>
35 #include <sys/socket.h>
36 #include <netinet/in.h>
37 #include <arpa/inet.h>
38 #include <netdb.h>
39 #endif
40
41 #include <stdio.h>
42 #include <stdlib.h>
43 #define __USE_GNU /* avoid warning for strndup */
44 #include <string.h>
45 #include <fcntl.h>
46 #include <sys/stat.h>
47
48 #include "wzd_structs.h"
49 #include "wzd_log.h"
50 #include "wzd_misc.h"
51
52 #endif /* WZD_USE_PCH */
53
54 #ifdef HAVE_EXECINFO_H
55 # include <execinfo.h>
56 #endif
57
58 /* uncomment to trace ALL fd registration operations */
59 /*#define WZD_DBG_FD*/
60
61
62 #define FD_SIG 0xbf07a4fbUL
63 #define WZD_MAX_FD 1024
64
65 #ifdef DEBUG
66 struct wzd_fd {
67 unsigned long sig;
68 int fd;
69 char file[256];
70 unsigned int line;
71 char function[256];
72 char desc[256];
73 };
74
75 static struct wzd_fd _wzd_fd_table[WZD_MAX_FD];
76
77 static void fd_init(void);
78
79 #endif
80
81 int fd_register(int fd, const char *desc, const char *file, unsigned int line, const char *function);
82 int fd_unregister(int fd, const char *desc, const char *file, unsigned int line, const char *function);
83 void fd_dump(void);
84
85 size_t wzd_strnlen (const char *s, size_t n);
86
87 /** init all debug functions */
wzd_debug_init(void)88 void wzd_debug_init(void)
89 {
90 #ifdef DEBUG
91 fd_init();
92 #endif
93 }
94
95 /** end all debug functions */
wzd_debug_fini(void)96 void wzd_debug_fini(void)
97 {
98 #ifdef DEBUG
99 fd_dump();
100 #endif
101 }
102
103 /** Check if fd is a valid file descriptor */
fd_is_valid(int fd)104 int fd_is_valid(int fd)
105 {
106 /* cygwin does NOT accept testing winsock fd's */
107 #if defined(_MSC_VER) || (defined(__CYGWIN__) && defined(WINSOCK_SUPPORT))
108 return 1;
109 #else
110 static struct statbuf s;
111
112 if (fs_fstat(fd,&s)<0) return 0;
113 return 1;
114 #endif
115 }
116
117 /* Memory allocation */
wzd_malloc(size_t size)118 /*@null@*/ void * wzd_malloc(size_t size)
119 {
120 return (void*)malloc(size);
121 }
122
123 /* Memory reallocation */
wzd_realloc(void * ptr,size_t size)124 void * wzd_realloc(void * ptr, size_t size)
125 {
126 return (void*)realloc(ptr, size);
127 }
128
129 /** \brief Copy memory area. The memory areas may overlap. */
wzd_memmove(void * dst,const void * src,size_t size)130 void * wzd_memmove(void * dst, const void * src, size_t size)
131 {
132 return memmove(dst,src,size);
133 }
134
135 /** \brief Free memory allocated by wzd_malloc */
wzd_free(void * ptr)136 void wzd_free(void *ptr)
137 {
138 free(ptr);
139 }
140
141 /** \brief Copy with allocation */
wzd_strdup(const char * s)142 char * wzd_strdup(const char *s)
143 {
144 return strdup(s);
145 }
146
147 /** \brief Copy with allocation, at most \a n bytes */
wzd_strndup(const char * s,size_t n)148 char * wzd_strndup(const char *s, size_t n)
149 {
150 #ifdef HAVE_STRNDUP
151 return strndup(s,n);
152 #else
153 size_t len = wzd_strnlen(s, n);
154 char * new = wzd_malloc (len + 1);
155
156 new[len] = '\0';
157
158 return memcpy(new, s, len);
159 #endif
160 }
161
162 /** same as strncpy, but write only one zero at end of string */
wzd_strncpy(char * dst,const char * src,size_t n)163 char * wzd_strncpy(char *dst, const char *src, size_t n)
164 {
165 if (n != 0)
166 {
167 register char *d = dst;
168 register const char *s = src;
169
170 do {
171 if ( (*d++ = *s++) == 0 ) break;
172 } while (--n != 0);
173 }
174 return dst;
175 }
176
177 /** Find the length of \a s , but scan at most \a n characters. */
wzd_strnlen(const char * s,size_t n)178 size_t wzd_strnlen (const char *s, size_t n)
179 {
180 const char *end = memchr (s, '\0', n);
181 return end ? (size_t)(end - s) : n;
182 }
183
184 #ifdef DEBUG
185 /** Initializes fd debug table */
fd_init(void)186 static void fd_init(void)
187 {
188 unsigned int i;
189 for (i=0; i<WZD_MAX_FD; i++) {
190 _wzd_fd_table[i].sig = FD_SIG;
191 _wzd_fd_table[i].fd = -1;
192 }
193 }
194 #endif /* DEBUG */
195
fd_register(int fd,const char * desc,const char * file,unsigned int line,const char * function)196 int fd_register(int fd, const char *desc, const char *file, unsigned int line, const char *function)
197 {
198 #ifdef DEBUG
199 if (fd < 0) return 1;
200 if (fd >= WZD_MAX_FD) return 2;
201
202 /* fd already registered ? */
203 if (_wzd_fd_table[fd].fd != -1) {
204 out_err(LEVEL_HIGH,"A file descriptor is already present at index %d\n",fd);
205 out_err(LEVEL_HIGH,"current fd: %d [%s]\n\t%s:%d (%s)\n",
206 _wzd_fd_table[fd].fd,
207 _wzd_fd_table[fd].desc,
208 _wzd_fd_table[fd].file,
209 _wzd_fd_table[fd].line,
210 _wzd_fd_table[fd].function);
211 out_err(LEVEL_HIGH,"offending fd: %d [%s]\n\t%s:%d (%s)\n",
212 fd,
213 desc,
214 file,
215 line,
216 function);
217 return 3;
218 }
219
220 _wzd_fd_table[fd].fd = fd;
221 strncpy(_wzd_fd_table[fd].desc,desc,sizeof(_wzd_fd_table[fd].desc));
222 strncpy(_wzd_fd_table[fd].file,file,sizeof(_wzd_fd_table[fd].file));
223 _wzd_fd_table[fd].line = line;
224 strncpy(_wzd_fd_table[fd].function,function,sizeof(_wzd_fd_table[fd].function));
225 #ifdef WZD_DBG_FD
226 out_err(LEVEL_HIGH,"added fd: %d [%s]\n\t%s:%d (%s)\n",
227 fd,
228 desc,
229 file,
230 line,
231 function);
232 #endif
233
234 #endif
235 return 0;
236 }
237
fd_unregister(int fd,const char * desc,const char * file,unsigned int line,const char * function)238 int fd_unregister(int fd, const char *desc, const char *file, unsigned int line, const char *function)
239 {
240 #ifdef DEBUG
241 if (fd < 0) return 1;
242 if (fd >= WZD_MAX_FD) return 2;
243
244 /* fd already registered ? */
245 if (_wzd_fd_table[fd].fd == -1) {
246 out_err(LEVEL_HIGH,"No file descriptor at index %d\n",fd);
247 out_err(LEVEL_HIGH,"offending fd: %d [%s]\n\t%s:%d (%s)\n",
248 fd,
249 desc,
250 file,
251 line,
252 function);
253 return 3;
254 }
255
256 _wzd_fd_table[fd].fd = -1;
257 memset(_wzd_fd_table[fd].desc,0,sizeof(_wzd_fd_table[fd].desc));
258 memset(_wzd_fd_table[fd].file,0,sizeof(_wzd_fd_table[fd].file));
259 _wzd_fd_table[fd].line = 0;
260 memset(_wzd_fd_table[fd].function,0,sizeof(_wzd_fd_table[fd].function));
261 #ifdef WZD_DBG_FD
262 out_err(LEVEL_HIGH,"removed fd: %d [%s]\n\t%s:%d (%s)\n",
263 fd,
264 desc,
265 file,
266 line,
267 function);
268 #endif
269
270 #endif
271 return 0;
272 }
273
fd_dump(void)274 void fd_dump(void)
275 {
276 #ifdef DEBUG
277 unsigned int i;
278 out_err(LEVEL_HIGH,"starting fd list dump:\n");
279 for (i=0; i<WZD_MAX_FD; i++) {
280 if (_wzd_fd_table[i].fd == -1) continue;
281
282 out_err(LEVEL_HIGH,"fd: %d [%s]\n\t%s:%d (%s)\n",
283 _wzd_fd_table[i].fd,
284 _wzd_fd_table[i].desc,
285 _wzd_fd_table[i].file,
286 _wzd_fd_table[i].line,
287 _wzd_fd_table[i].function);
288 }
289 out_err(LEVEL_HIGH,"end of fd list dump:\n");
290 #endif
291 }
292
dump_backtrace(void)293 void dump_backtrace(void)
294 {
295 #ifdef HAVE_BACKTRACE
296 void *bt[25];
297 char **ptr;
298 int i, size;
299
300 if ((size=backtrace(bt,25))>0) {
301 if ((ptr=backtrace_symbols(bt,25))) {
302 for (i=0; i<size; i++) {
303 if (ptr[i])
304 out_err(LEVEL_HIGH,"frame %d: %s\n",i,ptr[i]);
305 }
306 }
307 }
308 #endif
309 }
310
311 /** \brief Check current context for corruptions */
check_context(wzd_context_t * context)312 int check_context(wzd_context_t * context)
313 {
314 if (GetMyContext() != context)
315 {
316 out_err(LEVEL_CRITICAL,"CRITICAL GetMyContext does not match context !\n");
317 out_err(LEVEL_CRITICAL,"CRITICAL GetMyContext %p\n",GetMyContext());
318 out_err(LEVEL_CRITICAL,"CRITICAL context %p\n",context);
319 return 1;
320 }
321 if (!context->magic == CONTEXT_MAGIC)
322 {
323 out_err(LEVEL_CRITICAL,"CRITICAL context->magic is invalid, context may be corrupted\n");
324 return 1;
325 }
326 if (context->controlfd == (fd_t)-1 || !fd_is_valid(context->controlfd)) {
327 out_err(LEVEL_CRITICAL,"Trying to set invalid sockfd (%d) %s:%d\n",
328 context->controlfd,__FILE__,__LINE__);
329 return 1;
330 }
331
332 return 0;
333 }
334
335