Line data Source code
1 : /**
2 : util.c
3 :
4 :
5 : Copyright (C) 2001-2003, Network Resonance, Inc.
6 : Copyright (C) 2006, Network Resonance, Inc.
7 : All Rights Reserved
8 :
9 : Redistribution and use in source and binary forms, with or without
10 : modification, are permitted provided that the following conditions
11 : are met:
12 :
13 : 1. Redistributions of source code must retain the above copyright
14 : notice, this list of conditions and the following disclaimer.
15 : 2. Redistributions in binary form must reproduce the above copyright
16 : notice, this list of conditions and the following disclaimer in the
17 : documentation and/or other materials provided with the distribution.
18 : 3. Neither the name of Network Resonance, Inc. nor the name of any
19 : contributors to this software may be used to endorse or promote
20 : products derived from this software without specific prior written
21 : permission.
22 :
23 : THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
24 : AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 : IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 : ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
27 : LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 : CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 : SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 : INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 : CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 : ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 : POSSIBILITY OF SUCH DAMAGE.
34 :
35 :
36 : ekr@rtfm.com Wed Dec 26 17:19:36 2001
37 : */
38 :
39 :
40 : static char *RCSSTRING __UNUSED__ ="$Id: util.c,v 1.5 2007/11/21 00:09:13 adamcain Exp $";
41 :
42 : #ifndef WIN32
43 : #include <sys/uio.h>
44 : #include <pwd.h>
45 : #include <dirent.h>
46 : #endif
47 : #include <string.h>
48 : #include <errno.h>
49 : #include <ctype.h>
50 : #include <sys/stat.h>
51 : #ifdef OPENSSL
52 : #include <openssl/evp.h>
53 : #endif
54 : #include "nr_common.h"
55 : #include "r_common.h"
56 : #include "registry.h"
57 : #include "util.h"
58 : #include "r_log.h"
59 :
60 : int nr_util_default_log_facility=LOG_COMMON;
61 :
62 0 : int nr_get_filename(base,name,namep)
63 : char *base;
64 : char *name;
65 : char **namep;
66 : {
67 0 : int len=strlen(base)+strlen(name)+2;
68 0 : char *ret=0;
69 : int _status;
70 :
71 0 : if(!(ret=(char *)RMALLOC(len)))
72 0 : ABORT(R_NO_MEMORY);
73 0 : if(base[strlen(base)-1]!='/'){
74 0 : sprintf(ret,"%s/%s",base,name);
75 : }
76 : else{
77 0 : sprintf(ret,"%s%s",base,name);
78 : }
79 0 : *namep=ret;
80 0 : _status=0;
81 : abort:
82 0 : return(_status);
83 : }
84 :
85 : #if 0
86 : int read_RSA_private_key(base,name,keyp)
87 : char *base;
88 : char *name;
89 : RSA **keyp;
90 : {
91 : char *keyfile=0;
92 : BIO *bio=0;
93 : FILE *fp=0;
94 : RSA *rsa=0;
95 : int r,_status;
96 :
97 : /* Load the keyfile */
98 : if(r=get_filename(base,name,&keyfile))
99 : ABORT(r);
100 : if(!(fp=fopen(keyfile,"r")))
101 : ABORT(R_NOT_FOUND);
102 : if(!(bio=BIO_new(BIO_s_file())))
103 : ABORT(R_NO_MEMORY);
104 : BIO_set_fp(bio,fp,BIO_NOCLOSE);
105 :
106 : if(!(rsa=PEM_read_bio_RSAPrivateKey(bio,0,0,0)))
107 : ABORT(R_NOT_FOUND);
108 :
109 : *keyp=rsa;
110 : _status=0;
111 : abort:
112 : return(_status);
113 : }
114 : #endif
115 :
116 :
117 0 : void nr_errprintf_log(const char *format,...)
118 : {
119 : va_list ap;
120 :
121 0 : va_start(ap,format);
122 :
123 0 : r_vlog(nr_util_default_log_facility,LOG_ERR,format,ap);
124 :
125 0 : va_end(ap);
126 0 : }
127 :
128 0 : void nr_errprintf_log2(void *ignore, const char *format,...)
129 : {
130 : va_list ap;
131 :
132 0 : va_start(ap,format);
133 :
134 0 : r_vlog(nr_util_default_log_facility,LOG_ERR,format,ap);
135 :
136 0 : va_end(ap);
137 0 : }
138 :
139 :
140 0 : int nr_fwrite_all(FILE *fp,UCHAR *buf,int len)
141 : {
142 : int r,_status;
143 :
144 0 : while(len){
145 0 : r=fwrite(buf,1,len,fp);
146 0 : if(r==0)
147 0 : ABORT(R_IO_ERROR);
148 :
149 0 : len-=r;
150 0 : buf+=r;
151 : }
152 :
153 0 : _status=0;
154 : abort:
155 0 : return(_status);
156 : }
157 :
158 0 : int nr_read_data(fd,buf,len)
159 : int fd;
160 : char *buf;
161 : int len;
162 : {
163 : int r,_status;
164 :
165 0 : while(len){
166 0 : r=NR_SOCKET_READ(fd,buf,len);
167 0 : if(r<=0)
168 0 : ABORT(R_EOD);
169 :
170 0 : buf+=r;
171 0 : len-=r;
172 : }
173 :
174 :
175 0 : _status=0;
176 : abort:
177 0 : return(_status);
178 : }
179 :
180 : #ifdef WIN32
181 : // TODO
182 : #else
183 0 : int nr_drop_privileges(char *username)
184 : {
185 : int _status;
186 :
187 : /* Drop privileges */
188 0 : if ((getuid() == 0) || geteuid()==0) {
189 : struct passwd *passwd;
190 :
191 0 : if ((passwd = getpwnam(CAPTURE_USER)) == 0){
192 0 : r_log(LOG_GENERIC,LOG_EMERG,"Couldn't get user %s",CAPTURE_USER);
193 0 : ABORT(R_INTERNAL);
194 : }
195 :
196 0 : if(setuid(passwd->pw_uid)!=0){
197 0 : r_log(LOG_GENERIC,LOG_EMERG,"Couldn't drop privileges");
198 0 : ABORT(R_INTERNAL);
199 : }
200 : }
201 :
202 0 : _status=0;
203 : abort:
204 0 : return(_status);
205 : }
206 : #endif
207 :
208 0 : int nr_bin2hex(UCHAR *in,int len,UCHAR *out)
209 : {
210 0 : while(len){
211 0 : sprintf((char*)out,"%.2x",in[0] & 0xff);
212 :
213 0 : in+=1;
214 0 : out+=2;
215 :
216 0 : len--;
217 : }
218 :
219 0 : return(0);
220 : }
221 :
222 0 : int nr_hex_ascii_dump(Data *data)
223 : {
224 0 : UCHAR *ptr=data->data;
225 0 : int len=data->len;
226 :
227 0 : while(len){
228 : int i;
229 0 : int bytes=MIN(len,16);
230 :
231 0 : for(i=0;i<bytes;i++)
232 0 : printf("%.2x ",ptr[i]&255);
233 : /* Fill */
234 0 : for(i=0;i<(16-bytes);i++)
235 0 : printf(" ");
236 0 : printf(" ");
237 :
238 0 : for(i=0;i<bytes;i++){
239 0 : if(isprint(ptr[i]))
240 0 : printf("%c",ptr[i]);
241 : else
242 0 : printf(".");
243 : }
244 0 : printf("\n");
245 :
246 0 : len-=bytes;
247 0 : ptr+=bytes;
248 : }
249 0 : return(0);
250 : }
251 :
252 : #ifdef OPENSSL
253 : int nr_sha1_file(char *filename,UCHAR *out)
254 : {
255 : EVP_MD_CTX md_ctx;
256 : FILE *fp=0;
257 : int r,_status;
258 : UCHAR buf[1024];
259 : int out_len;
260 :
261 : EVP_MD_CTX_init(&md_ctx);
262 :
263 : if(!(fp=fopen(filename,"r"))){
264 : r_log(LOG_COMMON,LOG_ERR,"Couldn't open file %s",filename);
265 : ABORT(R_NOT_FOUND);
266 : }
267 :
268 : EVP_DigestInit_ex(&md_ctx,EVP_sha1(),0);
269 :
270 : while(1){
271 : r=fread(buf,1,sizeof(buf),fp);
272 :
273 : if(r<0){
274 : r_log(LOG_COMMON,LOG_ERR,"Error reading from %s",filename);
275 : ABORT(R_INTERNAL);
276 : }
277 :
278 : if(!r)
279 : break;
280 :
281 : EVP_DigestUpdate(&md_ctx,buf,r);
282 : }
283 :
284 : EVP_DigestFinal(&md_ctx,out,(unsigned int*)&out_len);
285 : if(out_len!=20)
286 : ABORT(R_INTERNAL);
287 :
288 : _status=0;
289 : abort:
290 : EVP_MD_CTX_cleanup(&md_ctx);
291 : if(fp) fclose(fp);
292 :
293 : return(_status);
294 : }
295 :
296 : #endif
297 :
298 : #ifdef WIN32
299 : // TODO
300 : #else
301 :
302 : #if 0
303 :
304 : #include <fts.h>
305 :
306 : int nr_rm_tree(char *path)
307 : {
308 : FTS *fts=0;
309 : FTSENT *p;
310 : int failed=0;
311 : int _status;
312 : char *argv[2];
313 :
314 : argv[0]=path;
315 : argv[1]=0;
316 :
317 : if(!(fts=fts_open(argv,0,NULL))){
318 : r_log_e(LOG_COMMON,LOG_ERR,"Couldn't open directory %s",path);
319 : ABORT(R_FAILED);
320 : }
321 :
322 : while(p=fts_read(fts)){
323 : switch(p->fts_info){
324 : case FTS_D:
325 : break;
326 : case FTS_DOT:
327 : break;
328 : case FTS_ERR:
329 : r_log_e(LOG_COMMON,LOG_ERR,"Problem reading %s",p->fts_path);
330 : break;
331 : default:
332 : r_log(LOG_COMMON,LOG_DEBUG,"Removing %s",p->fts_path);
333 : errno=0;
334 : if(remove(p->fts_path)){
335 : r_log_e(LOG_COMMON,LOG_ERR,"Problem removing %s",p->fts_path);
336 : failed=1;
337 : }
338 : }
339 : }
340 :
341 : if(failed)
342 : ABORT(R_FAILED);
343 :
344 : _status=0;
345 : abort:
346 : if(fts) fts_close(fts);
347 : return(_status);
348 : }
349 : #endif
350 :
351 0 : int nr_write_pid_file(char *pid_filename)
352 : {
353 : FILE *fp;
354 : int _status;
355 :
356 0 : if(!pid_filename)
357 0 : ABORT(R_BAD_ARGS);
358 :
359 0 : unlink(pid_filename);
360 :
361 0 : if(!(fp=fopen(pid_filename,"w"))){
362 0 : r_log(LOG_GENERIC,LOG_CRIT,"Couldn't open PID file: %s",strerror(errno));
363 0 : ABORT(R_NOT_FOUND);
364 : }
365 :
366 0 : fprintf(fp,"%d\n",getpid());
367 :
368 0 : fclose(fp);
369 :
370 0 : chmod(pid_filename,S_IRUSR | S_IRGRP | S_IROTH);
371 :
372 0 : _status=0;
373 : abort:
374 0 : return(_status);
375 : }
376 : #endif
377 :
378 0 : int nr_reg_uint4_fetch_and_check(NR_registry key, UINT4 min, UINT4 max, int log_fac, int die, UINT4 *val)
379 : {
380 : int r,_status;
381 : UINT4 my_val;
382 :
383 0 : if(r=NR_reg_get_uint4(key,&my_val)){
384 0 : r_log(log_fac,LOG_ERR,"Couldn't get key '%s', error %d",key,r);
385 0 : ABORT(r);
386 : }
387 :
388 0 : if((min>0) && (my_val<min)){
389 0 : r_log(log_fac,LOG_ERR,"Invalid value for key '%s'=%lu, (min = %lu)",key,(unsigned long)my_val,(unsigned long)min);
390 0 : ABORT(R_BAD_DATA);
391 : }
392 :
393 0 : if(my_val>max){
394 0 : r_log(log_fac,LOG_ERR,"Invalid value for key '%s'=%lu, (max = %lu)",key,(unsigned long)my_val,(unsigned long)max);
395 0 : ABORT(R_BAD_DATA);
396 : }
397 :
398 0 : *val=my_val;
399 0 : _status=0;
400 :
401 : abort:
402 0 : if(die && _status){
403 0 : r_log(log_fac,LOG_CRIT,"Exiting due to invalid configuration (key '%s')",key);
404 0 : exit(1);
405 : }
406 0 : return(_status);
407 : }
408 :
409 0 : int nr_reg_uint8_fetch_and_check(NR_registry key, UINT8 min, UINT8 max, int log_fac, int die, UINT8 *val)
410 : {
411 : int r,_status;
412 : UINT8 my_val;
413 :
414 0 : if(r=NR_reg_get_uint8(key,&my_val)){
415 0 : r_log(log_fac,LOG_ERR,"Couldn't get key '%s', error %d",key,r);
416 0 : ABORT(r);
417 : }
418 :
419 0 : if(my_val<min){
420 0 : r_log(log_fac,LOG_ERR,"Invalid value for key '%s'=%llu, (min = %llu)",key,my_val,min);
421 0 : ABORT(R_BAD_DATA);
422 : }
423 :
424 0 : if(my_val>max){
425 0 : r_log(log_fac,LOG_ERR,"Invalid value for key '%s'=%llu, (max = %llu)",key,my_val,max);
426 0 : ABORT(R_BAD_DATA);
427 : }
428 :
429 0 : *val=my_val;
430 0 : _status=0;
431 :
432 : abort:
433 0 : if(die && _status){
434 0 : r_log(log_fac,LOG_CRIT,"Exiting due to invalid configuration (key '%s')",key);
435 0 : exit(1);
436 : }
437 0 : return(_status);
438 : }
439 :
440 : #if defined(LINUX) || defined(WIN32)
441 : /*-
442 : * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
443 : * All rights reserved.
444 : *
445 : * Redistribution and use in source and binary forms, with or without
446 : * modification, are permitted provided that the following conditions
447 : * are met:
448 : * 1. Redistributions of source code must retain the above copyright
449 : * notice, this list of conditions and the following disclaimer.
450 : * 2. Redistributions in binary form must reproduce the above copyright
451 : * notice, this list of conditions and the following disclaimer in the
452 : * documentation and/or other materials provided with the distribution.
453 : * 3. The name of the author may not be used to endorse or promote products
454 : * derived from this software without specific prior written permission.
455 : *
456 : * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
457 : * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
458 : * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
459 : * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
460 : * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
461 : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
462 : * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
463 : * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
464 : * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
465 : * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
466 : */
467 :
468 :
469 : /*
470 : * Appends src to string dst of size siz (unlike strncat, siz is the
471 : * full size of dst, not space left). At most siz-1 characters
472 : * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
473 : * Returns strlen(src) + MIN(siz, strlen(initial dst)).
474 : * If retval >= siz, truncation occurred.
475 : */
476 : size_t
477 0 : strlcat(dst, src, siz)
478 : char *dst;
479 : const char *src;
480 : size_t siz;
481 : {
482 0 : char *d = dst;
483 0 : const char *s = src;
484 0 : size_t n = siz;
485 : size_t dlen;
486 :
487 : /* Find the end of dst and adjust bytes left but don't go past end */
488 0 : while (n-- != 0 && *d != '\0')
489 0 : d++;
490 0 : dlen = d - dst;
491 0 : n = siz - dlen;
492 :
493 0 : if (n == 0)
494 0 : return(dlen + strlen(s));
495 0 : while (*s != '\0') {
496 0 : if (n != 1) {
497 0 : *d++ = *s;
498 0 : n--;
499 : }
500 0 : s++;
501 : }
502 0 : *d = '\0';
503 :
504 0 : return(dlen + (s - src)); /* count does not include NUL */
505 : }
506 :
507 : #endif /* LINUX or WIN32 */
508 :
509 : #if defined(USE_OWN_INET_NTOP) || (defined(WIN32) && WINVER < 0x0600)
510 : #include <errno.h>
511 : #ifdef WIN32
512 : #include <Ws2ipdef.h>
513 : #ifndef EAFNOSUPPORT
514 : #define EAFNOSUPPORT WSAEAFNOSUPPORT
515 : #endif
516 : #else
517 : #include <sys/socket.h>
518 : #endif
519 : #define INET6
520 :
521 : /* inet_ntop implementation from NetBSD */
522 :
523 : /*
524 : * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
525 : * Copyright (c) 1996-1999 by Internet Software Consortium.
526 : *
527 : * Permission to use, copy, modify, and distribute this software for any
528 : * purpose with or without fee is hereby granted, provided that the above
529 : * copyright notice and this permission notice appear in all copies.
530 : *
531 : * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
532 : * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
533 : * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
534 : * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
535 : * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
536 : * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
537 : * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
538 : */
539 :
540 : #if !defined(NS_INADDRSZ)
541 : # define NS_INADDRSZ 4
542 : #endif
543 : #if !defined(NS_IN6ADDRSZ)
544 : # define NS_IN6ADDRSZ 16
545 : #endif
546 : #if !defined(NS_INT16SZ)
547 : # define NS_INT16SZ 2
548 : #endif
549 :
550 : /*
551 : * WARNING: Don't even consider trying to compile this on a system where
552 : * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
553 : */
554 :
555 : static const char *inet_ntop4(const unsigned char *src, char *dst, size_t size);
556 : #ifdef INET6
557 : static const char *inet_ntop6(const unsigned char *src, char *dst, size_t size);
558 : #endif /* INET6 */
559 :
560 : /* char *
561 : * inet_ntop(af, src, dst, size)
562 : * convert a network format address to presentation format.
563 : * return:
564 : * pointer to presentation format address (`dst'), or NULL (see errno).
565 : * author:
566 : * Paul Vixie, 1996.
567 : */
568 : const char *
569 : inet_ntop(int af, const void *src, char *dst, size_t size)
570 : {
571 :
572 : switch (af) {
573 : case AF_INET:
574 : return (inet_ntop4(src, dst, size));
575 : #ifdef INET6
576 : case AF_INET6:
577 : return (inet_ntop6(src, dst, size));
578 : #endif /* INET6 */
579 : default:
580 : errno = EAFNOSUPPORT;
581 : return (NULL);
582 : }
583 : /* NOTREACHED */
584 : }
585 :
586 : /* const char *
587 : * inet_ntop4(src, dst, size)
588 : * format an IPv4 address, more or less like inet_ntoa()
589 : * return:
590 : * `dst' (as a const)
591 : * notes:
592 : * (1) uses no statics
593 : * (2) takes a unsigned char* not an in_addr as input
594 : * author:
595 : * Paul Vixie, 1996.
596 : */
597 : static const char *
598 : inet_ntop4(const unsigned char *src, char *dst, size_t size)
599 : {
600 : char tmp[sizeof "255.255.255.255"];
601 : int l;
602 :
603 : l = snprintf(tmp, sizeof(tmp), "%u.%u.%u.%u",
604 : src[0], src[1], src[2], src[3]);
605 : if (l <= 0 || (size_t) l >= size) {
606 : errno = ENOSPC;
607 : return (NULL);
608 : }
609 : strlcpy(dst, tmp, size);
610 : return (dst);
611 : }
612 :
613 : #ifdef INET6
614 : /* const char *
615 : * inet_ntop6(src, dst, size)
616 : * convert IPv6 binary address into presentation (printable) format
617 : * author:
618 : * Paul Vixie, 1996.
619 : */
620 : static const char *
621 : inet_ntop6(const unsigned char *src, char *dst, size_t size)
622 : {
623 : /*
624 : * Note that int32_t and int16_t need only be "at least" large enough
625 : * to contain a value of the specified size. On some systems, like
626 : * Crays, there is no such thing as an integer variable with 16 bits.
627 : * Keep this in mind if you think this function should have been coded
628 : * to use pointer overlays. All the world's not a VAX.
629 : */
630 : char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
631 : char *tp, *ep;
632 : struct { int base, len; } best, cur;
633 : unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ];
634 : int i;
635 : int advance;
636 :
637 : /*
638 : * Preprocess:
639 : * Copy the input (bytewise) array into a wordwise array.
640 : * Find the longest run of 0x00's in src[] for :: shorthanding.
641 : */
642 : memset(words, '\0', sizeof words);
643 : for (i = 0; i < NS_IN6ADDRSZ; i++)
644 : words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
645 : best.base = -1;
646 : cur.base = -1;
647 : best.len = -1; /* XXX gcc */
648 : cur.len = -1; /* XXX gcc */
649 : for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
650 : if (words[i] == 0) {
651 : if (cur.base == -1)
652 : cur.base = i, cur.len = 1;
653 : else
654 : cur.len++;
655 : } else {
656 : if (cur.base != -1) {
657 : if (best.base == -1 || cur.len > best.len)
658 : best = cur;
659 : cur.base = -1;
660 : }
661 : }
662 : }
663 : if (cur.base != -1) {
664 : if (best.base == -1 || cur.len > best.len)
665 : best = cur;
666 : }
667 : if (best.base != -1 && best.len < 2)
668 : best.base = -1;
669 :
670 : /*
671 : * Format the result.
672 : */
673 : tp = tmp;
674 : ep = tmp + sizeof(tmp);
675 : for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
676 : /* Are we inside the best run of 0x00's? */
677 : if (best.base != -1 && i >= best.base &&
678 : i < (best.base + best.len)) {
679 : if (i == best.base)
680 : *tp++ = ':';
681 : continue;
682 : }
683 : /* Are we following an initial run of 0x00s or any real hex? */
684 : if (i != 0) {
685 : if (tp + 1 >= ep)
686 : return (NULL);
687 : *tp++ = ':';
688 : }
689 : /* Is this address an encapsulated IPv4? */
690 : if (i == 6 && best.base == 0 &&
691 : (best.len == 6 ||
692 : (best.len == 7 && words[7] != 0x0001) ||
693 : (best.len == 5 && words[5] == 0xffff))) {
694 : if (!inet_ntop4(src+12, tp, (size_t)(ep - tp)))
695 : return (NULL);
696 : tp += strlen(tp);
697 : break;
698 : }
699 : advance = snprintf(tp, (size_t)(ep - tp), "%x", words[i]);
700 : if (advance <= 0 || advance >= ep - tp)
701 : return (NULL);
702 : tp += advance;
703 : }
704 : /* Was it a trailing run of 0x00's? */
705 : if (best.base != -1 && (best.base + best.len) ==
706 : (NS_IN6ADDRSZ / NS_INT16SZ)) {
707 : if (tp + 1 >= ep)
708 : return (NULL);
709 : *tp++ = ':';
710 : }
711 : if (tp + 1 >= ep)
712 : return (NULL);
713 : *tp++ = '\0';
714 :
715 : /*
716 : * Check for overflow, copy, and we're done.
717 : */
718 : if ((size_t)(tp - tmp) > size) {
719 : errno = ENOSPC;
720 : return (NULL);
721 : }
722 : strlcpy(dst, tmp, size);
723 : return (dst);
724 : }
725 : #endif /* INET6 */
726 :
727 : #ifdef WIN32
728 : /* Not exactly, will forgive stuff like <addr>:<port> */
729 : int inet_pton(int af, const char *src, void *dst)
730 : {
731 : struct sockaddr_storage ss;
732 : int addrlen = sizeof(ss);
733 :
734 : if (af != AF_INET && af != AF_INET6) {
735 : return -1;
736 : }
737 :
738 : if (!WSAStringToAddressA(src, af, NULL, (struct sockaddr*)&ss, &addrlen)) {
739 : if (af == AF_INET) {
740 : struct sockaddr_in *in = (struct sockaddr_in*)&ss;
741 : memcpy(dst, &in->sin_addr, sizeof(struct in_addr));
742 : } else {
743 : struct sockaddr_in6 *in6 = (struct sockaddr_in6*)&ss;
744 : memcpy(dst, &in6->sin6_addr, sizeof(struct in6_addr));
745 : }
746 : return 1;
747 : }
748 : return 0;
749 : }
750 : #endif /* WIN32 */
751 :
752 : #endif
753 :
754 : #ifdef WIN32
755 : #include <time.h>
756 : /* this is only millisecond-accurate, but that should be OK */
757 :
758 : int gettimeofday(struct timeval *tv, void *tz)
759 : {
760 : SYSTEMTIME st;
761 : FILETIME ft;
762 : ULARGE_INTEGER u;
763 :
764 : GetLocalTime (&st);
765 :
766 : /* strangely, the FILETIME is the number of 100 nanosecond (0.1 us) intervals
767 : * since the Epoch */
768 : SystemTimeToFileTime(&st, &ft);
769 : u.HighPart = ft.dwHighDateTime;
770 : u.LowPart = ft.dwLowDateTime;
771 :
772 : tv->tv_sec = (long) (u.QuadPart / 10000000L);
773 : tv->tv_usec = (long) (st.wMilliseconds * 1000);;
774 :
775 : return 0;
776 : }
777 : #endif
778 :
|