media/mtransport/third_party/nrappkit/src/util/util.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/media/mtransport/third_party/nrappkit/src/util/util.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,765 @@
     1.4 +/**
     1.5 +   util.c
     1.6 +
     1.7 +
     1.8 +   Copyright (C) 2001-2003, Network Resonance, Inc.
     1.9 +   Copyright (C) 2006, Network Resonance, Inc.
    1.10 +   All Rights Reserved
    1.11 +
    1.12 +   Redistribution and use in source and binary forms, with or without
    1.13 +   modification, are permitted provided that the following conditions
    1.14 +   are met:
    1.15 +
    1.16 +   1. Redistributions of source code must retain the above copyright
    1.17 +      notice, this list of conditions and the following disclaimer.
    1.18 +   2. Redistributions in binary form must reproduce the above copyright
    1.19 +      notice, this list of conditions and the following disclaimer in the
    1.20 +      documentation and/or other materials provided with the distribution.
    1.21 +   3. Neither the name of Network Resonance, Inc. nor the name of any
    1.22 +      contributors to this software may be used to endorse or promote
    1.23 +      products derived from this software without specific prior written
    1.24 +      permission.
    1.25 +
    1.26 +   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
    1.27 +   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    1.28 +   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    1.29 +   ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
    1.30 +   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    1.31 +   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    1.32 +   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    1.33 +   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    1.34 +   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    1.35 +   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    1.36 +   POSSIBILITY OF SUCH DAMAGE.
    1.37 +
    1.38 +
    1.39 +   ekr@rtfm.com  Wed Dec 26 17:19:36 2001
    1.40 + */
    1.41 +
    1.42 +
    1.43 +static char *RCSSTRING __UNUSED__ ="$Id: util.c,v 1.5 2007/11/21 00:09:13 adamcain Exp $";
    1.44 +
    1.45 +#ifndef WIN32
    1.46 +#include <sys/uio.h>
    1.47 +#include <pwd.h>
    1.48 +#include <dirent.h>
    1.49 +#endif
    1.50 +#include <string.h>
    1.51 +#include <errno.h>
    1.52 +#include <ctype.h>
    1.53 +#include <sys/stat.h>
    1.54 +#ifdef OPENSSL
    1.55 +#include <openssl/evp.h>
    1.56 +#endif
    1.57 +#include "nr_common.h"
    1.58 +#include "r_common.h"
    1.59 +#include "registry.h"
    1.60 +#include "util.h"
    1.61 +#include "r_log.h"
    1.62 +
    1.63 +int nr_util_default_log_facility=LOG_COMMON;
    1.64 +
    1.65 +int nr_get_filename(base,name,namep)
    1.66 +  char *base;
    1.67 +  char *name;
    1.68 +  char **namep;
    1.69 +  {
    1.70 +    int len=strlen(base)+strlen(name)+2;
    1.71 +    char *ret=0;
    1.72 +    int _status;
    1.73 +
    1.74 +    if(!(ret=(char *)RMALLOC(len)))
    1.75 +      ABORT(R_NO_MEMORY);
    1.76 +    if(base[strlen(base)-1]!='/'){
    1.77 +      sprintf(ret,"%s/%s",base,name);
    1.78 +    }
    1.79 +    else{
    1.80 +      sprintf(ret,"%s%s",base,name);
    1.81 +    }
    1.82 +    *namep=ret;
    1.83 +    _status=0;
    1.84 +  abort:
    1.85 +    return(_status);
    1.86 +  }
    1.87 +
    1.88 +#if 0
    1.89 +int read_RSA_private_key(base,name,keyp)
    1.90 +  char *base;
    1.91 +  char *name;
    1.92 +  RSA **keyp;
    1.93 +  {
    1.94 +    char *keyfile=0;
    1.95 +    BIO *bio=0;
    1.96 +    FILE *fp=0;
    1.97 +    RSA *rsa=0;
    1.98 +    int r,_status;
    1.99 +
   1.100 +    /* Load the keyfile */
   1.101 +    if(r=get_filename(base,name,&keyfile))
   1.102 +      ABORT(r);
   1.103 +    if(!(fp=fopen(keyfile,"r")))
   1.104 +      ABORT(R_NOT_FOUND);
   1.105 +    if(!(bio=BIO_new(BIO_s_file())))
   1.106 +      ABORT(R_NO_MEMORY);
   1.107 +    BIO_set_fp(bio,fp,BIO_NOCLOSE);
   1.108 +
   1.109 +    if(!(rsa=PEM_read_bio_RSAPrivateKey(bio,0,0,0)))
   1.110 +      ABORT(R_NOT_FOUND);
   1.111 +
   1.112 +    *keyp=rsa;
   1.113 +    _status=0;
   1.114 +  abort:
   1.115 +    return(_status);
   1.116 +  }
   1.117 +#endif
   1.118 +
   1.119 +
   1.120 +void nr_errprintf_log(const char *format,...)
   1.121 +  {
   1.122 +    va_list ap;
   1.123 +
   1.124 +    va_start(ap,format);
   1.125 +
   1.126 +    r_vlog(nr_util_default_log_facility,LOG_ERR,format,ap);
   1.127 +
   1.128 +    va_end(ap);
   1.129 +  }
   1.130 +
   1.131 +void nr_errprintf_log2(void *ignore, const char *format,...)
   1.132 +  {
   1.133 +    va_list ap;
   1.134 +
   1.135 +    va_start(ap,format);
   1.136 +
   1.137 +    r_vlog(nr_util_default_log_facility,LOG_ERR,format,ap);
   1.138 +
   1.139 +    va_end(ap);
   1.140 +  }
   1.141 +
   1.142 +
   1.143 +int nr_fwrite_all(FILE *fp,UCHAR *buf,int len)
   1.144 +  {
   1.145 +    int r,_status;
   1.146 +
   1.147 +    while(len){
   1.148 +      r=fwrite(buf,1,len,fp);
   1.149 +      if(r==0)
   1.150 +        ABORT(R_IO_ERROR);
   1.151 +
   1.152 +      len-=r;
   1.153 +      buf+=r;
   1.154 +    }
   1.155 +
   1.156 +    _status=0;
   1.157 +  abort:
   1.158 +    return(_status);
   1.159 +  }
   1.160 +
   1.161 +int nr_read_data(fd,buf,len)
   1.162 +  int fd;
   1.163 +  char *buf;
   1.164 +  int len;
   1.165 +  {
   1.166 +    int r,_status;
   1.167 +
   1.168 +    while(len){
   1.169 +      r=NR_SOCKET_READ(fd,buf,len);
   1.170 +      if(r<=0)
   1.171 +        ABORT(R_EOD);
   1.172 +
   1.173 +      buf+=r;
   1.174 +      len-=r;
   1.175 +    }
   1.176 +
   1.177 +
   1.178 +    _status=0;
   1.179 +  abort:
   1.180 +    return(_status);
   1.181 +  }
   1.182 +
   1.183 +#ifdef WIN32
   1.184 +  // TODO
   1.185 +#else
   1.186 +int nr_drop_privileges(char *username)
   1.187 +  {
   1.188 +    int _status;
   1.189 +
   1.190 +    /* Drop privileges */
   1.191 +    if ((getuid() == 0) || geteuid()==0) {
   1.192 +      struct passwd *passwd;
   1.193 +
   1.194 +      if ((passwd = getpwnam(CAPTURE_USER)) == 0){
   1.195 +        r_log(LOG_GENERIC,LOG_EMERG,"Couldn't get user %s",CAPTURE_USER);
   1.196 +        ABORT(R_INTERNAL);
   1.197 +      }
   1.198 +
   1.199 +      if(setuid(passwd->pw_uid)!=0){
   1.200 +        r_log(LOG_GENERIC,LOG_EMERG,"Couldn't drop privileges");
   1.201 +        ABORT(R_INTERNAL);
   1.202 +      }
   1.203 +    }
   1.204 +
   1.205 +    _status=0;
   1.206 +  abort:
   1.207 +    return(_status);
   1.208 +  }
   1.209 +#endif
   1.210 +
   1.211 +int nr_bin2hex(UCHAR *in,int len,UCHAR *out)
   1.212 +  {
   1.213 +    while(len){
   1.214 +      sprintf((char*)out,"%.2x",in[0] & 0xff);
   1.215 +
   1.216 +      in+=1;
   1.217 +      out+=2;
   1.218 +
   1.219 +      len--;
   1.220 +    }
   1.221 +
   1.222 +    return(0);
   1.223 +  }
   1.224 +
   1.225 +int nr_hex_ascii_dump(Data *data)
   1.226 +  {
   1.227 +    UCHAR *ptr=data->data;
   1.228 +    int len=data->len;
   1.229 +
   1.230 +    while(len){
   1.231 +      int i;
   1.232 +      int bytes=MIN(len,16);
   1.233 +
   1.234 +      for(i=0;i<bytes;i++)
   1.235 +        printf("%.2x ",ptr[i]&255);
   1.236 +      /* Fill */
   1.237 +      for(i=0;i<(16-bytes);i++)
   1.238 +        printf("   ");
   1.239 +      printf("   ");
   1.240 +
   1.241 +      for(i=0;i<bytes;i++){
   1.242 +        if(isprint(ptr[i]))
   1.243 +          printf("%c",ptr[i]);
   1.244 +        else
   1.245 +          printf(".");
   1.246 +      }
   1.247 +      printf("\n");
   1.248 +
   1.249 +      len-=bytes;
   1.250 +      ptr+=bytes;
   1.251 +    }
   1.252 +    return(0);
   1.253 +  }
   1.254 +
   1.255 +#ifdef OPENSSL
   1.256 +int nr_sha1_file(char *filename,UCHAR *out)
   1.257 +  {
   1.258 +    EVP_MD_CTX md_ctx;
   1.259 +    FILE *fp=0;
   1.260 +    int r,_status;
   1.261 +    UCHAR buf[1024];
   1.262 +    int out_len;
   1.263 +
   1.264 +    EVP_MD_CTX_init(&md_ctx);
   1.265 +
   1.266 +    if(!(fp=fopen(filename,"r"))){
   1.267 +      r_log(LOG_COMMON,LOG_ERR,"Couldn't open file %s",filename);
   1.268 +      ABORT(R_NOT_FOUND);
   1.269 +    }
   1.270 +
   1.271 +    EVP_DigestInit_ex(&md_ctx,EVP_sha1(),0);
   1.272 +
   1.273 +    while(1){
   1.274 +      r=fread(buf,1,sizeof(buf),fp);
   1.275 +
   1.276 +      if(r<0){
   1.277 +        r_log(LOG_COMMON,LOG_ERR,"Error reading from %s",filename);
   1.278 +        ABORT(R_INTERNAL);
   1.279 +      }
   1.280 +
   1.281 +      if(!r)
   1.282 +        break;
   1.283 +
   1.284 +      EVP_DigestUpdate(&md_ctx,buf,r);
   1.285 +    }
   1.286 +
   1.287 +    EVP_DigestFinal(&md_ctx,out,(unsigned int*)&out_len);
   1.288 +    if(out_len!=20)
   1.289 +      ABORT(R_INTERNAL);
   1.290 +
   1.291 +    _status=0;
   1.292 +  abort:
   1.293 +    EVP_MD_CTX_cleanup(&md_ctx);
   1.294 +    if(fp) fclose(fp);
   1.295 +
   1.296 +    return(_status);
   1.297 +  }
   1.298 +
   1.299 +#endif
   1.300 +
   1.301 +#ifdef WIN32
   1.302 +  // TODO
   1.303 +#else
   1.304 +
   1.305 +#if 0
   1.306 +
   1.307 +#include <fts.h>
   1.308 +
   1.309 +int nr_rm_tree(char *path)
   1.310 +  {
   1.311 +    FTS *fts=0;
   1.312 +    FTSENT *p;
   1.313 +    int failed=0;
   1.314 +    int _status;
   1.315 +    char *argv[2];
   1.316 +
   1.317 +    argv[0]=path;
   1.318 +    argv[1]=0;
   1.319 +
   1.320 +    if(!(fts=fts_open(argv,0,NULL))){
   1.321 +      r_log_e(LOG_COMMON,LOG_ERR,"Couldn't open directory %s",path);
   1.322 +      ABORT(R_FAILED);
   1.323 +    }
   1.324 +
   1.325 +    while(p=fts_read(fts)){
   1.326 +      switch(p->fts_info){
   1.327 +        case FTS_D:
   1.328 +          break;
   1.329 +        case FTS_DOT:
   1.330 +          break;
   1.331 +        case FTS_ERR:
   1.332 +          r_log_e(LOG_COMMON,LOG_ERR,"Problem reading %s",p->fts_path);
   1.333 +          break;
   1.334 +        default:
   1.335 +          r_log(LOG_COMMON,LOG_DEBUG,"Removing %s",p->fts_path);
   1.336 +          errno=0;
   1.337 +          if(remove(p->fts_path)){
   1.338 +            r_log_e(LOG_COMMON,LOG_ERR,"Problem removing %s",p->fts_path);
   1.339 +            failed=1;
   1.340 +          }
   1.341 +      }
   1.342 +    }
   1.343 +
   1.344 +    if(failed)
   1.345 +      ABORT(R_FAILED);
   1.346 +
   1.347 +    _status=0;
   1.348 +  abort:
   1.349 +    if(fts) fts_close(fts);
   1.350 +    return(_status);
   1.351 +  }
   1.352 +#endif
   1.353 +
   1.354 +int nr_write_pid_file(char *pid_filename)
   1.355 +  {
   1.356 +    FILE *fp;
   1.357 +    int _status;
   1.358 +
   1.359 +    if(!pid_filename)
   1.360 +      ABORT(R_BAD_ARGS);
   1.361 +
   1.362 +    unlink(pid_filename);
   1.363 +
   1.364 +    if(!(fp=fopen(pid_filename,"w"))){
   1.365 +      r_log(LOG_GENERIC,LOG_CRIT,"Couldn't open PID file: %s",strerror(errno));
   1.366 +      ABORT(R_NOT_FOUND);
   1.367 +    }
   1.368 +
   1.369 +    fprintf(fp,"%d\n",getpid());
   1.370 +
   1.371 +    fclose(fp);
   1.372 +
   1.373 +    chmod(pid_filename,S_IRUSR | S_IRGRP | S_IROTH);
   1.374 +
   1.375 +    _status=0;
   1.376 +  abort:
   1.377 +    return(_status);
   1.378 +  }
   1.379 +#endif
   1.380 +
   1.381 +int nr_reg_uint4_fetch_and_check(NR_registry key, UINT4 min, UINT4 max, int log_fac, int die, UINT4 *val)
   1.382 +  {
   1.383 +    int r,_status;
   1.384 +    UINT4 my_val;
   1.385 +
   1.386 +    if(r=NR_reg_get_uint4(key,&my_val)){
   1.387 +      r_log(log_fac,LOG_ERR,"Couldn't get key '%s', error %d",key,r);
   1.388 +      ABORT(r);
   1.389 +    }
   1.390 +
   1.391 +    if((min>0) && (my_val<min)){
   1.392 +      r_log(log_fac,LOG_ERR,"Invalid value for key '%s'=%lu, (min = %lu)",key,(unsigned long)my_val,(unsigned long)min);
   1.393 +      ABORT(R_BAD_DATA);
   1.394 +    }
   1.395 +
   1.396 +    if(my_val>max){
   1.397 +      r_log(log_fac,LOG_ERR,"Invalid value for key '%s'=%lu, (max = %lu)",key,(unsigned long)my_val,(unsigned long)max);
   1.398 +      ABORT(R_BAD_DATA);
   1.399 +    }
   1.400 +
   1.401 +    *val=my_val;
   1.402 +    _status=0;
   1.403 +
   1.404 +  abort:
   1.405 +    if(die && _status){
   1.406 +      r_log(log_fac,LOG_CRIT,"Exiting due to invalid configuration (key '%s')",key);
   1.407 +      exit(1);
   1.408 +    }
   1.409 +    return(_status);
   1.410 +  }
   1.411 +
   1.412 +int nr_reg_uint8_fetch_and_check(NR_registry key, UINT8 min, UINT8 max, int log_fac, int die, UINT8 *val)
   1.413 +  {
   1.414 +    int r,_status;
   1.415 +    UINT8 my_val;
   1.416 +
   1.417 +    if(r=NR_reg_get_uint8(key,&my_val)){
   1.418 +      r_log(log_fac,LOG_ERR,"Couldn't get key '%s', error %d",key,r);
   1.419 +      ABORT(r);
   1.420 +    }
   1.421 +
   1.422 +    if(my_val<min){
   1.423 +      r_log(log_fac,LOG_ERR,"Invalid value for key '%s'=%llu, (min = %llu)",key,my_val,min);
   1.424 +      ABORT(R_BAD_DATA);
   1.425 +    }
   1.426 +
   1.427 +    if(my_val>max){
   1.428 +      r_log(log_fac,LOG_ERR,"Invalid value for key '%s'=%llu, (max = %llu)",key,my_val,max);
   1.429 +      ABORT(R_BAD_DATA);
   1.430 +    }
   1.431 +
   1.432 +    *val=my_val;
   1.433 +    _status=0;
   1.434 +
   1.435 +  abort:
   1.436 +    if(die && _status){
   1.437 +      r_log(log_fac,LOG_CRIT,"Exiting due to invalid configuration (key '%s')",key);
   1.438 +      exit(1);
   1.439 +    }
   1.440 +    return(_status);
   1.441 +  }
   1.442 +
   1.443 +#if defined(LINUX) || defined(WIN32)
   1.444 +/*-
   1.445 + * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
   1.446 + * All rights reserved.
   1.447 + *
   1.448 + * Redistribution and use in source and binary forms, with or without
   1.449 + * modification, are permitted provided that the following conditions
   1.450 + * are met:
   1.451 + * 1. Redistributions of source code must retain the above copyright
   1.452 + *    notice, this list of conditions and the following disclaimer.
   1.453 + * 2. Redistributions in binary form must reproduce the above copyright
   1.454 + *    notice, this list of conditions and the following disclaimer in the
   1.455 + *    documentation and/or other materials provided with the distribution.
   1.456 + * 3. The name of the author may not be used to endorse or promote products
   1.457 + *    derived from this software without specific prior written permission.
   1.458 + *
   1.459 + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
   1.460 + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
   1.461 + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
   1.462 + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   1.463 + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   1.464 + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
   1.465 + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   1.466 + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   1.467 + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   1.468 + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   1.469 + */
   1.470 +
   1.471 +
   1.472 +/*
   1.473 + * Appends src to string dst of size siz (unlike strncat, siz is the
   1.474 + * full size of dst, not space left).  At most siz-1 characters
   1.475 + * will be copied.  Always NUL terminates (unless siz <= strlen(dst)).
   1.476 + * Returns strlen(src) + MIN(siz, strlen(initial dst)).
   1.477 + * If retval >= siz, truncation occurred.
   1.478 + */
   1.479 +size_t
   1.480 +strlcat(dst, src, siz)
   1.481 +        char *dst;
   1.482 +        const char *src;
   1.483 +        size_t siz;
   1.484 +{
   1.485 +        char *d = dst;
   1.486 +        const char *s = src;
   1.487 +        size_t n = siz;
   1.488 +        size_t dlen;
   1.489 +
   1.490 +        /* Find the end of dst and adjust bytes left but don't go past end */
   1.491 +        while (n-- != 0 && *d != '\0')
   1.492 +                d++;
   1.493 +        dlen = d - dst;
   1.494 +        n = siz - dlen;
   1.495 +
   1.496 +        if (n == 0)
   1.497 +                return(dlen + strlen(s));
   1.498 +        while (*s != '\0') {
   1.499 +                if (n != 1) {
   1.500 +                        *d++ = *s;
   1.501 +                        n--;
   1.502 +                }
   1.503 +                s++;
   1.504 +        }
   1.505 +        *d = '\0';
   1.506 +
   1.507 +        return(dlen + (s - src));       /* count does not include NUL */
   1.508 +}
   1.509 +
   1.510 +#endif  /* LINUX or WIN32 */
   1.511 +
   1.512 +#if defined(USE_OWN_INET_NTOP) || defined(WIN32)
   1.513 +#include <errno.h>
   1.514 +#ifdef WIN32
   1.515 +#include <Ws2ipdef.h>
   1.516 +#ifndef EAFNOSUPPORT
   1.517 +#define EAFNOSUPPORT            WSAEAFNOSUPPORT
   1.518 +#endif
   1.519 +#else
   1.520 +#include <sys/socket.h>
   1.521 +#endif
   1.522 +#define INET6
   1.523 +
   1.524 +/* inet_ntop implementation from NetBSD */
   1.525 +
   1.526 +/*
   1.527 + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
   1.528 + * Copyright (c) 1996-1999 by Internet Software Consortium.
   1.529 + *
   1.530 + * Permission to use, copy, modify, and distribute this software for any
   1.531 + * purpose with or without fee is hereby granted, provided that the above
   1.532 + * copyright notice and this permission notice appear in all copies.
   1.533 + *
   1.534 + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
   1.535 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   1.536 + * MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR
   1.537 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   1.538 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   1.539 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
   1.540 + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   1.541 + */
   1.542 +
   1.543 +#if !defined(NS_INADDRSZ)
   1.544 +# define NS_INADDRSZ  4
   1.545 +#endif
   1.546 +#if !defined(NS_IN6ADDRSZ)
   1.547 +# define NS_IN6ADDRSZ  16
   1.548 +#endif
   1.549 +#if !defined(NS_INT16SZ)
   1.550 +# define NS_INT16SZ  2
   1.551 +#endif
   1.552 +
   1.553 +/*
   1.554 + * WARNING: Don't even consider trying to compile this on a system where
   1.555 + * sizeof(int) < 4.  sizeof(int) > 4 is fine; all the world's not a VAX.
   1.556 + */
   1.557 +
   1.558 +static const char *inet_ntop4(const unsigned char *src, char *dst, size_t size);
   1.559 +#ifdef INET6
   1.560 +static const char *inet_ntop6(const unsigned char *src, char *dst, size_t size);
   1.561 +#endif /* INET6 */
   1.562 +
   1.563 +/* char *
   1.564 + * inet_ntop(af, src, dst, size)
   1.565 + *  convert a network format address to presentation format.
   1.566 + * return:
   1.567 + *  pointer to presentation format address (`dst'), or NULL (see errno).
   1.568 + * author:
   1.569 + *  Paul Vixie, 1996.
   1.570 + */
   1.571 +const char *
   1.572 +inet_ntop(int af, const void *src, char *dst, size_t size)
   1.573 +{
   1.574 +
   1.575 +  switch (af) {
   1.576 +  case AF_INET:
   1.577 +    return (inet_ntop4(src, dst, size));
   1.578 +#ifdef INET6
   1.579 +  case AF_INET6:
   1.580 +    return (inet_ntop6(src, dst, size));
   1.581 +#endif /* INET6 */
   1.582 +  default:
   1.583 +    errno = EAFNOSUPPORT;
   1.584 +    return (NULL);
   1.585 +  }
   1.586 +  /* NOTREACHED */
   1.587 +}
   1.588 +
   1.589 +/* const char *
   1.590 + * inet_ntop4(src, dst, size)
   1.591 + *  format an IPv4 address, more or less like inet_ntoa()
   1.592 + * return:
   1.593 + *  `dst' (as a const)
   1.594 + * notes:
   1.595 + *  (1) uses no statics
   1.596 + *  (2) takes a unsigned char* not an in_addr as input
   1.597 + * author:
   1.598 + *  Paul Vixie, 1996.
   1.599 + */
   1.600 +static const char *
   1.601 +inet_ntop4(const unsigned char *src, char *dst, size_t size)
   1.602 +{
   1.603 +  char tmp[sizeof "255.255.255.255"];
   1.604 +  int l;
   1.605 +
   1.606 +  l = snprintf(tmp, sizeof(tmp), "%u.%u.%u.%u",
   1.607 +      src[0], src[1], src[2], src[3]);
   1.608 +  if (l <= 0 || (size_t) l >= size) {
   1.609 +    errno = ENOSPC;
   1.610 +    return (NULL);
   1.611 +  }
   1.612 +  strlcpy(dst, tmp, size);
   1.613 +  return (dst);
   1.614 +}
   1.615 +
   1.616 +#ifdef INET6
   1.617 +/* const char *
   1.618 + * inet_ntop6(src, dst, size)
   1.619 + *  convert IPv6 binary address into presentation (printable) format
   1.620 + * author:
   1.621 + *  Paul Vixie, 1996.
   1.622 + */
   1.623 +static const char *
   1.624 +inet_ntop6(const unsigned char *src, char *dst, size_t size)
   1.625 +{
   1.626 +  /*
   1.627 +   * Note that int32_t and int16_t need only be "at least" large enough
   1.628 +   * to contain a value of the specified size.  On some systems, like
   1.629 +   * Crays, there is no such thing as an integer variable with 16 bits.
   1.630 +   * Keep this in mind if you think this function should have been coded
   1.631 +   * to use pointer overlays.  All the world's not a VAX.
   1.632 +   */
   1.633 +  char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"];
   1.634 +  char *tp, *ep;
   1.635 +  struct { int base, len; } best, cur;
   1.636 +  unsigned int words[NS_IN6ADDRSZ / NS_INT16SZ];
   1.637 +  int i;
   1.638 +  int advance;
   1.639 +
   1.640 +  /*
   1.641 +   * Preprocess:
   1.642 +   *  Copy the input (bytewise) array into a wordwise array.
   1.643 +   *  Find the longest run of 0x00's in src[] for :: shorthanding.
   1.644 +   */
   1.645 +  memset(words, '\0', sizeof words);
   1.646 +  for (i = 0; i < NS_IN6ADDRSZ; i++)
   1.647 +    words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
   1.648 +  best.base = -1;
   1.649 +  cur.base = -1;
   1.650 +  best.len = -1;  /* XXX gcc */
   1.651 +  cur.len = -1;  /* XXX gcc */
   1.652 +  for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
   1.653 +    if (words[i] == 0) {
   1.654 +      if (cur.base == -1)
   1.655 +        cur.base = i, cur.len = 1;
   1.656 +      else
   1.657 +        cur.len++;
   1.658 +    } else {
   1.659 +      if (cur.base != -1) {
   1.660 +        if (best.base == -1 || cur.len > best.len)
   1.661 +          best = cur;
   1.662 +        cur.base = -1;
   1.663 +      }
   1.664 +    }
   1.665 +  }
   1.666 +  if (cur.base != -1) {
   1.667 +    if (best.base == -1 || cur.len > best.len)
   1.668 +      best = cur;
   1.669 +  }
   1.670 +  if (best.base != -1 && best.len < 2)
   1.671 +    best.base = -1;
   1.672 +
   1.673 +  /*
   1.674 +   * Format the result.
   1.675 +   */
   1.676 +  tp = tmp;
   1.677 +  ep = tmp + sizeof(tmp);
   1.678 +  for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
   1.679 +    /* Are we inside the best run of 0x00's? */
   1.680 +    if (best.base != -1 && i >= best.base &&
   1.681 +        i < (best.base + best.len)) {
   1.682 +      if (i == best.base)
   1.683 +        *tp++ = ':';
   1.684 +      continue;
   1.685 +    }
   1.686 +    /* Are we following an initial run of 0x00s or any real hex? */
   1.687 +    if (i != 0) {
   1.688 +      if (tp + 1 >= ep)
   1.689 +        return (NULL);
   1.690 +      *tp++ = ':';
   1.691 +    }
   1.692 +    /* Is this address an encapsulated IPv4? */
   1.693 +    if (i == 6 && best.base == 0 &&
   1.694 +        (best.len == 6 ||
   1.695 +        (best.len == 7 && words[7] != 0x0001) ||
   1.696 +        (best.len == 5 && words[5] == 0xffff))) {
   1.697 +      if (!inet_ntop4(src+12, tp, (size_t)(ep - tp)))
   1.698 +        return (NULL);
   1.699 +      tp += strlen(tp);
   1.700 +      break;
   1.701 +    }
   1.702 +    advance = snprintf(tp, (size_t)(ep - tp), "%x", words[i]);
   1.703 +    if (advance <= 0 || advance >= ep - tp)
   1.704 +      return (NULL);
   1.705 +    tp += advance;
   1.706 +  }
   1.707 +  /* Was it a trailing run of 0x00's? */
   1.708 +  if (best.base != -1 && (best.base + best.len) ==
   1.709 +      (NS_IN6ADDRSZ / NS_INT16SZ)) {
   1.710 +    if (tp + 1 >= ep)
   1.711 +      return (NULL);
   1.712 +    *tp++ = ':';
   1.713 +  }
   1.714 +  if (tp + 1 >= ep)
   1.715 +    return (NULL);
   1.716 +  *tp++ = '\0';
   1.717 +
   1.718 +  /*
   1.719 +   * Check for overflow, copy, and we're done.
   1.720 +   */
   1.721 +  if ((size_t)(tp - tmp) > size) {
   1.722 +    errno = ENOSPC;
   1.723 +    return (NULL);
   1.724 +  }
   1.725 +  strlcpy(dst, tmp, size);
   1.726 +  return (dst);
   1.727 +}
   1.728 +#endif /* INET6 */
   1.729 +
   1.730 +#endif
   1.731 +
   1.732 +#ifdef WIN32
   1.733 +#include <time.h>
   1.734 +/* this is only millisecond-accurate, but that should be OK */
   1.735 +
   1.736 +int gettimeofday(struct timeval *tv, void *tz)
   1.737 +  {
   1.738 +    SYSTEMTIME st;
   1.739 +    FILETIME ft;
   1.740 +    ULARGE_INTEGER u;
   1.741 +
   1.742 +    GetLocalTime (&st);
   1.743 +
   1.744 +    /* strangely, the FILETIME is the number of 100 nanosecond (0.1 us) intervals
   1.745 +     * since the Epoch */
   1.746 +    SystemTimeToFileTime(&st, &ft);
   1.747 +    u.HighPart = ft.dwHighDateTime;
   1.748 +    u.LowPart = ft.dwLowDateTime;
   1.749 +
   1.750 +    tv->tv_sec = (long) (u.QuadPart / 10000000L);
   1.751 +    tv->tv_usec = (long) (st.wMilliseconds * 1000);;
   1.752 +
   1.753 +    return 0;
   1.754 +  }
   1.755 +
   1.756 +int snprintf(char *buffer, size_t n, const char *format, ...)
   1.757 +{
   1.758 +  va_list argp;
   1.759 +  int ret;
   1.760 +  va_start(argp, format);
   1.761 +  ret = _vscprintf(format, argp);
   1.762 +  vsnprintf_s(buffer, n, _TRUNCATE, format, argp);
   1.763 +  va_end(argp);
   1.764 +  return ret;
   1.765 +}
   1.766 +
   1.767 +#endif
   1.768 +

mercurial