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

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

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

mercurial