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
nr_get_filename(base,name,namep)62 int nr_get_filename(base,name,namep)
63 char *base;
64 char *name;
65 char **namep;
66 {
67 int len=strlen(base)+strlen(name)+2;
68 char *ret=0;
69 int _status;
70
71 if(!(ret=(char *)RMALLOC(len)))
72 ABORT(R_NO_MEMORY);
73 if(base[strlen(base)-1]!='/'){
74 sprintf(ret,"%s/%s",base,name);
75 }
76 else{
77 sprintf(ret,"%s%s",base,name);
78 }
79 *namep=ret;
80 _status=0;
81 abort:
82 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
nr_errprintf_log(const char * format,...)117 void nr_errprintf_log(const char *format,...)
118 {
119 va_list ap;
120
121 va_start(ap,format);
122
123 r_vlog(nr_util_default_log_facility,LOG_ERR,format,ap);
124
125 va_end(ap);
126 }
127
nr_errprintf_log2(void * ignore,const char * format,...)128 void nr_errprintf_log2(void *ignore, const char *format,...)
129 {
130 va_list ap;
131
132 va_start(ap,format);
133
134 r_vlog(nr_util_default_log_facility,LOG_ERR,format,ap);
135
136 va_end(ap);
137 }
138
139
nr_fwrite_all(FILE * fp,UCHAR * buf,int len)140 int nr_fwrite_all(FILE *fp,UCHAR *buf,int len)
141 {
142 int r,_status;
143
144 while(len){
145 r=fwrite(buf,1,len,fp);
146 if(r==0)
147 ABORT(R_IO_ERROR);
148
149 len-=r;
150 buf+=r;
151 }
152
153 _status=0;
154 abort:
155 return(_status);
156 }
157
nr_read_data(fd,buf,len)158 int nr_read_data(fd,buf,len)
159 int fd;
160 char *buf;
161 int len;
162 {
163 int r,_status;
164
165 while(len){
166 r=NR_SOCKET_READ(fd,buf,len);
167 if(r<=0)
168 ABORT(R_EOD);
169
170 buf+=r;
171 len-=r;
172 }
173
174
175 _status=0;
176 abort:
177 return(_status);
178 }
179
180 #ifdef WIN32
181 // TODO
182 #else
nr_drop_privileges(char * username)183 int nr_drop_privileges(char *username)
184 {
185 int _status;
186
187 /* Drop privileges */
188 if ((getuid() == 0) || geteuid()==0) {
189 struct passwd *passwd;
190
191 if ((passwd = getpwnam(CAPTURE_USER)) == 0){
192 r_log(LOG_GENERIC,LOG_EMERG,"Couldn't get user %s",CAPTURE_USER);
193 ABORT(R_INTERNAL);
194 }
195
196 if(setuid(passwd->pw_uid)!=0){
197 r_log(LOG_GENERIC,LOG_EMERG,"Couldn't drop privileges");
198 ABORT(R_INTERNAL);
199 }
200 }
201
202 _status=0;
203 abort:
204 return(_status);
205 }
206 #endif
207
nr_bin2hex(UCHAR * in,int len,UCHAR * out)208 int nr_bin2hex(UCHAR *in,int len,UCHAR *out)
209 {
210 while(len){
211 sprintf((char*)out,"%.2x",in[0] & 0xff);
212
213 in+=1;
214 out+=2;
215
216 len--;
217 }
218
219 return(0);
220 }
221
nr_hex_ascii_dump(Data * data)222 int nr_hex_ascii_dump(Data *data)
223 {
224 UCHAR *ptr=data->data;
225 int len=data->len;
226
227 while(len){
228 int i;
229 int bytes=MIN(len,16);
230
231 for(i=0;i<bytes;i++)
232 printf("%.2x ",ptr[i]&255);
233 /* Fill */
234 for(i=0;i<(16-bytes);i++)
235 printf(" ");
236 printf(" ");
237
238 for(i=0;i<bytes;i++){
239 if(isprint(ptr[i]))
240 printf("%c",ptr[i]);
241 else
242 printf(".");
243 }
244 printf("\n");
245
246 len-=bytes;
247 ptr+=bytes;
248 }
249 return(0);
250 }
251
252 #ifdef OPENSSL
nr_sha1_file(char * filename,UCHAR * out)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
nr_write_pid_file(char * pid_filename)351 int nr_write_pid_file(char *pid_filename)
352 {
353 FILE *fp;
354 int _status;
355
356 if(!pid_filename)
357 ABORT(R_BAD_ARGS);
358
359 unlink(pid_filename);
360
361 if(!(fp=fopen(pid_filename,"w"))){
362 r_log(LOG_GENERIC,LOG_CRIT,"Couldn't open PID file: %s",strerror(errno));
363 ABORT(R_NOT_FOUND);
364 }
365
366 fprintf(fp,"%d\n",getpid());
367
368 fclose(fp);
369
370 chmod(pid_filename,S_IRUSR | S_IRGRP | S_IROTH);
371
372 _status=0;
373 abort:
374 return(_status);
375 }
376 #endif
377
nr_reg_uint4_fetch_and_check(NR_registry key,UINT4 min,UINT4 max,int log_fac,int die,UINT4 * val)378 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 if(r=NR_reg_get_uint4(key,&my_val)){
384 r_log(log_fac,LOG_ERR,"Couldn't get key '%s', error %d",key,r);
385 ABORT(r);
386 }
387
388 if((min>0) && (my_val<min)){
389 r_log(log_fac,LOG_ERR,"Invalid value for key '%s'=%lu, (min = %lu)",key,(unsigned long)my_val,(unsigned long)min);
390 ABORT(R_BAD_DATA);
391 }
392
393 if(my_val>max){
394 r_log(log_fac,LOG_ERR,"Invalid value for key '%s'=%lu, (max = %lu)",key,(unsigned long)my_val,(unsigned long)max);
395 ABORT(R_BAD_DATA);
396 }
397
398 *val=my_val;
399 _status=0;
400
401 abort:
402 if(die && _status){
403 r_log(log_fac,LOG_CRIT,"Exiting due to invalid configuration (key '%s')",key);
404 exit(1);
405 }
406 return(_status);
407 }
408
nr_reg_uint8_fetch_and_check(NR_registry key,UINT8 min,UINT8 max,int log_fac,int die,UINT8 * val)409 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 if(r=NR_reg_get_uint8(key,&my_val)){
415 r_log(log_fac,LOG_ERR,"Couldn't get key '%s', error %d",key,r);
416 ABORT(r);
417 }
418
419 if(my_val<min){
420 r_log(log_fac,LOG_ERR,"Invalid value for key '%s'=%llu, (min = %llu)",key,my_val,min);
421 ABORT(R_BAD_DATA);
422 }
423
424 if(my_val>max){
425 r_log(log_fac,LOG_ERR,"Invalid value for key '%s'=%llu, (max = %llu)",key,my_val,max);
426 ABORT(R_BAD_DATA);
427 }
428
429 *val=my_val;
430 _status=0;
431
432 abort:
433 if(die && _status){
434 r_log(log_fac,LOG_CRIT,"Exiting due to invalid configuration (key '%s')",key);
435 exit(1);
436 }
437 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
strlcat(dst,src,siz)477 strlcat(dst, src, siz)
478 char *dst;
479 const char *src;
480 size_t siz;
481 {
482 char *d = dst;
483 const char *s = src;
484 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 while (n-- != 0 && *d != '\0')
489 d++;
490 dlen = d - dst;
491 n = siz - dlen;
492
493 if (n == 0)
494 return(dlen + strlen(s));
495 while (*s != '\0') {
496 if (n != 1) {
497 *d++ = *s;
498 n--;
499 }
500 s++;
501 }
502 *d = '\0';
503
504 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 *
inet_ntop(int af,const void * src,char * dst,size_t size)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 *
inet_ntop4(const unsigned char * src,char * dst,size_t size)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 *
inet_ntop6(const unsigned char * src,char * dst,size_t size)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> */
inet_pton(int af,const char * src,void * dst)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
gettimeofday(struct timeval * tv,void * tz)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
779