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