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 +