1 /* helpers.h - Various helper functions
2
3 Copyright (C) 2000, 2001 Thomas Moestl
4 Copyright (C) 2002, 2003, 2004, 2007, 2009, 2011 Paul A. Rombouts
5
6 This file is part of the pdnsd package.
7
8 pdnsd is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 pdnsd is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with pdnsd; see the file COPYING. If not, see
20 <http://www.gnu.org/licenses/>.
21 */
22
23
24 #ifndef HELPERS_H
25 #define HELPERS_H
26
27 #include <config.h>
28 #include <pthread.h>
29 #include <unistd.h>
30 #include <string.h>
31 #include <ctype.h>
32 #include "cache.h"
33 #include "pdnsd_assert.h"
34
35 #define SOFTLOCK_MAXTRIES 1000
36
37 int run_as(const char *user);
38 void pdnsd_exit(void);
39 int softlock_mutex(pthread_mutex_t *mutex);
40
41 #if 0
42 inline static int isdchar (unsigned char c)
43 {
44 return ((c>='a' && c<='z') || (c>='A' && c<='Z') || (c>='0' && c<='9') || c=='-'
45 #ifdef UNDERSCORE
46 || c=='_'
47 #endif
48 );
49 }
50 #endif
51
52 const unsigned char *rhn2str(const unsigned char *rhn, unsigned char *str, unsigned int size);
53 int str2rhn(const unsigned char *str, unsigned char *rhn);
54 const char *parsestr2rhn(const unsigned char *str, unsigned int len, unsigned char *rhn);
55
56 /* Note added by Paul Rombouts:
57 Compared to the definition used by Thomas Moestl (strlen(rhn)+1), the following definition of rhnlen
58 may yield a different result in certain error situations (when a domain name segment contains a null byte).
59 */
60 inline static unsigned int rhnlen(const unsigned char *rhn)
61 __attribute__((always_inline));
rhnlen(const unsigned char * rhn)62 inline static unsigned int rhnlen(const unsigned char *rhn)
63 {
64 unsigned int i=0,lb;
65
66 while((lb=rhn[i++]))
67 i+=lb;
68 return i;
69 }
70
71 /* Skip k segments in a name in length-byte string notation. */
72 inline static const unsigned char *skipsegs(const unsigned char *nm, unsigned k)
73 __attribute__((always_inline));
skipsegs(const unsigned char * nm,unsigned k)74 inline static const unsigned char *skipsegs(const unsigned char *nm, unsigned k)
75 {
76 unsigned lb;
77 for(;k && (lb= *nm); --k) {
78 nm += lb+1;
79 }
80 return nm;
81 }
82
83 /* Skip a name in length-byte string notation and return a pointer to the
84 position right after the terminating null byte.
85 */
86 inline static unsigned char *skiprhn(unsigned char *rhn)
87 __attribute__((always_inline));
skiprhn(unsigned char * rhn)88 inline static unsigned char *skiprhn(unsigned char *rhn)
89 {
90 unsigned lb;
91
92 while((lb= *rhn++))
93 rhn += lb;
94 return rhn;
95 }
96
97 /* count the number of name segments of a name in length-byte string notation. */
98 inline static unsigned int rhnsegcnt(const unsigned char *rhn)
99 __attribute__((always_inline));
rhnsegcnt(const unsigned char * rhn)100 inline static unsigned int rhnsegcnt(const unsigned char *rhn)
101 {
102 unsigned int res=0,lb;
103
104 while((lb= *rhn)) {
105 ++res;
106 rhn += lb+1;
107 }
108 return res;
109 }
110
111 unsigned int rhncpy(unsigned char *dst, const unsigned char *src);
112 int isnormalencdomname(const unsigned char *rhn, unsigned maxlen);
113
114 inline static int is_inaddr_any(pdnsd_a *a) __attribute__((always_inline));
is_inaddr_any(pdnsd_a * a)115 inline static int is_inaddr_any(pdnsd_a *a)
116 {
117 return SEL_IPVER( a->ipv4.s_addr==INADDR_ANY,
118 IN6_IS_ADDR_UNSPECIFIED(&a->ipv6) );
119 }
120
121 /* Same as is_inaddr_any(), but for the pdnsd_a2 type. */
122 inline static int is_inaddr2_any(pdnsd_a2 *a) __attribute__((always_inline));
is_inaddr2_any(pdnsd_a2 * a)123 inline static int is_inaddr2_any(pdnsd_a2 *a)
124 {
125 return SEL_IPVER( a->ipv4.s_addr==INADDR_ANY,
126 IN6_IS_ADDR_UNSPECIFIED(&a->ipv6) );
127 }
128
129
130 inline static int same_inaddr(pdnsd_a *a, pdnsd_a *b)
131 __attribute__((always_inline));
same_inaddr(pdnsd_a * a,pdnsd_a * b)132 inline static int same_inaddr(pdnsd_a *a, pdnsd_a *b)
133 {
134 return SEL_IPVER( a->ipv4.s_addr==b->ipv4.s_addr,
135 IN6_ARE_ADDR_EQUAL(&a->ipv6,&b->ipv6) );
136 }
137
138 /* Compare a pdnsd_a* with a pdnsd_a2*. */
139 inline static int same_inaddr2(pdnsd_a *a, pdnsd_a2 *b)
140 __attribute__((always_inline));
same_inaddr2(pdnsd_a * a,pdnsd_a2 * b)141 inline static int same_inaddr2(pdnsd_a *a, pdnsd_a2 *b)
142 {
143 return SEL_IPVER( a->ipv4.s_addr==b->ipv4.s_addr,
144 IN6_ARE_ADDR_EQUAL(&a->ipv6,&b->ipv6) && b->ipv4.s_addr==INADDR_ANY );
145 }
146
147 inline static int equiv_inaddr2(pdnsd_a *a, pdnsd_a2 *b)
148 __attribute__((always_inline));
equiv_inaddr2(pdnsd_a * a,pdnsd_a2 * b)149 inline static int equiv_inaddr2(pdnsd_a *a, pdnsd_a2 *b)
150 {
151 return SEL_IPVER( a->ipv4.s_addr==b->ipv4.s_addr,
152 IN6_ARE_ADDR_EQUAL(&a->ipv6,&b->ipv6) ||
153 (b->ipv4.s_addr!=INADDR_ANY && ADDR_EQUIV6_4(&a->ipv6,&b->ipv4)) );
154 }
155
156 int str2pdnsd_a(const char *addr, pdnsd_a *a);
157 const char *pdnsd_a2str(pdnsd_a *a, char *buf, int maxlen);
158
159 int init_rng(void);
160 #ifdef RANDOM_DEVICE
161 extern FILE *rand_file;
162 /* Because this is usually empty, it is now defined as a macro to save overhead.*/
163 #define free_rng() {if (rand_file) fclose(rand_file);}
164 #else
165 #define free_rng()
166 #endif
167
168 unsigned short get_rand16(void);
169
170 int fsprintf(int fd, const char *format, ...) printfunc(2, 3);
171 #if !defined(CPP_C99_VARIADIC_MACROS)
172 /* GNU C Macro Varargs style. */
173 # define fsprintf_or_return(args...) {int _retval; if((_retval=fsprintf(args))<0) return _retval;}
174 #else
175 /* ANSI C99 style variadic macro. */
176 # define fsprintf_or_return(...) {int _retval; if((_retval=fsprintf(__VA_ARGS__))<0) return _retval;}
177 #endif
178
179 /* Added by Paul Rombouts */
180 inline static ssize_t write_all(int fd,const void *data,size_t n)
181 __attribute__((always_inline));
write_all(int fd,const void * data,size_t n)182 inline static ssize_t write_all(int fd,const void *data,size_t n)
183 {
184 ssize_t written=0;
185
186 while(written<n) {
187 ssize_t m=write(fd,(const void*)(((const char*)data)+written),n-written);
188
189 if(m<0)
190 return m;
191
192 written+=m;
193 }
194
195 return written;
196 }
197
198 void hexdump(const void *data, int dlen, char *buf, int buflen);
199 int escapestr(const char *in, int ilen, char *str, int size);
200
201 #if 0
202 inline static int stricomp(const char *a, const char *b)
203 {
204 return !strcasecmp(a,b);
205 }
206 #endif
207
208 /* compare two names in length byte - string format
209 rhnicmp returns 1 if the names are the same (ignoring upper/lower case),
210 0 otherwise.
211 */
212 inline static int rhnicmp(const unsigned char *a, const unsigned char *b)
213 __attribute__((always_inline));
rhnicmp(const unsigned char * a,const unsigned char * b)214 inline static int rhnicmp(const unsigned char *a, const unsigned char *b)
215 {
216 unsigned int i=0;
217 unsigned char lb;
218 for(;;) {
219 lb=a[i];
220 if(lb!=b[i]) return 0;
221 if(!lb) break;
222 ++i;
223 do {
224 if(tolower(a[i])!=tolower(b[i])) return 0;
225 ++i;
226 } while(--lb);
227 }
228 return 1;
229 }
230
231 /* Bah. I want strlcpy. */
232 inline static int strncp(char *dst, const char *src, size_t dstsz)
233 __attribute__((always_inline));
strncp(char * dst,const char * src,size_t dstsz)234 inline static int strncp(char *dst, const char *src, size_t dstsz)
235 {
236 #ifdef HAVE_STRLCPY
237 return (strlcpy(dst,src,dstsz)<dstsz);
238 #else
239 #ifdef HAVE_STPNCPY
240 char *p=stpncpy(dst,src,dstsz);
241 if(p<dst+dstsz) return 1;
242 *(p-1)='\0';
243 return 0;
244 #else
245 strncpy(dst,src,dstsz);
246 if(strlen(src)<dstsz) return 1;
247 dst[dstsz-1]='\0';
248 return 0;
249 #endif
250 #endif
251 }
252
253 #ifndef HAVE_STRDUP
254 inline static char *strdup(const char *s)
255 __attribute__((always_inline));
strdup(const char * s)256 inline static char *strdup(const char *s)
257 {
258 size_t sz=strlen(s)+1;
259 char *cp=malloc(sz);
260 if(cp)
261 memcpy(cp,s,sz);
262 return cp;
263 }
264 #endif
265
266 #ifndef HAVE_STRNDUP
267 /* This version may allocate a buffer that is unnecessarily large,
268 but I'm always going to use it with n<strlen(s)
269 */
270 inline static char *strndup(const char *s, size_t n)
271 __attribute__((always_inline));
strndup(const char * s,size_t n)272 inline static char *strndup(const char *s, size_t n)
273 {
274 char *cp;
275 cp=malloc(n+1);
276 if(cp) {
277 memcpy(cp,s,n);
278 cp[n]='\0';
279 }
280 return cp;
281 }
282 #endif
283
284 #ifndef HAVE_STPCPY
285 inline static char *stpcpy (char *dest, const char *src)
286 __attribute__((always_inline));
stpcpy(char * dest,const char * src)287 inline static char *stpcpy (char *dest, const char *src)
288 {
289 register char *d = dest;
290 register const char *s = src;
291
292 while ((*d++ = *s++) != '\0');
293
294 return d - 1;
295 }
296 #endif
297
298 #ifndef HAVE_MEMPCPY
299 inline static void *mempcpy(void *dest, const void *src, size_t len)
300 __attribute__((always_inline));
mempcpy(void * dest,const void * src,size_t len)301 inline static void *mempcpy(void *dest, const void *src, size_t len)
302 {
303 memcpy(dest,src,len);
304 return ((char *)dest)+len;
305 }
306 #endif
307
308 #ifndef HAVE_GETLINE
309 int getline(char **lineptr, size_t *n, FILE *stream);
310 #endif
311
312 #ifndef HAVE_ASPRINTF
313 int asprintf (char **lineptr, const char *format, ...);
314 #endif
315
316 #ifndef HAVE_VASPRINTF
317 #include <stdarg.h>
318 int vasprintf (char **lineptr, const char *format, va_list va);
319 #endif
320
321 #ifndef HAVE_INET_NTOP
322 const char *inet_ntop(int af, const void *src, char *dst, size_t size);
323 #endif
324
325 #define strlitlen(strlit) (sizeof(strlit)-1)
326
327 #endif /* HELPERS_H */
328