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