1/* 2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23/* 24 * utils.c - various utility functions used in pppd. 25 * 26 * Copyright (c) 1999-2002 Paul Mackerras. All rights reserved. 27 * 28 * Redistribution and use in source and binary forms, with or without 29 * modification, are permitted provided that the following conditions 30 * are met: 31 * 32 * 1. Redistributions of source code must retain the above copyright 33 * notice, this list of conditions and the following disclaimer. 34 * 35 * 2. Redistributions in binary form must reproduce the above copyright 36 * notice, this list of conditions and the following disclaimer in 37 * the documentation and/or other materials provided with the 38 * distribution. 39 * 40 * 3. The name(s) of the authors of this software must not be used to 41 * endorse or promote products derived from this software without 42 * prior written permission. 43 * 44 * 4. Redistributions of any form whatsoever must retain the following 45 * acknowledgment: 46 * "This product includes software developed by Paul Mackerras 47 * <paulus@samba.org>". 48 * 49 * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO 50 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 51 * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY 52 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 53 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 54 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 55 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 56 */ 57 58#define RCSID "$Id: utils.c,v 1.8 2005/12/13 06:30:15 lindak Exp $" 59 60#include <stdio.h> 61#include <ctype.h> 62#include <stdlib.h> 63#include <string.h> 64#include <unistd.h> 65#include <signal.h> 66#include <errno.h> 67#include <fcntl.h> 68#include <syslog.h> 69#include <netdb.h> 70#include <time.h> 71#include <pwd.h> 72#include <sys/param.h> 73#include <sys/types.h> 74#include <sys/wait.h> 75#include <sys/time.h> 76#include <sys/resource.h> 77#include <sys/stat.h> 78#include <sys/socket.h> 79#include <netinet/in.h> 80#ifdef SVR4 81#include <sys/mkdev.h> 82#endif 83#include <arpa/inet.h> 84#include <net/if.h> 85#include <net/if_media.h> 86#include <netinet/in_var.h> 87#include <sys/kern_event.h> 88#include <SystemConfiguration/SystemConfiguration.h> 89#include <SystemConfiguration/SCValidation.h> 90#include <CoreFoundation/CFBundle.h> 91 92#include "pppd.h" 93#include "fsm.h" 94#include "lcp.h" 95 96#ifndef lint 97static const char rcsid[] = RCSID; 98#endif 99 100#if defined(SUNOS4) 101extern char *strerror(); 102#endif 103 104static void logit __P((int, char *, va_list)); 105static void log_write __P((int, char *)); 106static void vslp_printer __P((void *, char *, ...)); 107static void format_packet __P((u_char *, int, void (*) (void *, char *, ...), 108 void *)); 109 110struct buffer_info { 111 char *ptr; 112 int len; 113}; 114 115#ifdef NO_SRTLXXX 116 117/* 118 * strlcpy - like strcpy/strncpy, doesn't overflow destination buffer, 119 * always leaves destination null-terminated (for len > 0). 120 */ 121size_t 122strlcpy(dest, src, len) 123 char *dest; 124 const char *src; 125 size_t len; 126{ 127 size_t ret = strlen(src); 128 129 if (len != 0) { 130 if (ret < len) 131 strcpy(dest, src); 132 else { 133 strncpy(dest, src, len - 1); 134 dest[len-1] = 0; 135 } 136 } 137 return ret; 138} 139 140/* 141 * strlcat - like strcat/strncat, doesn't overflow destination buffer, 142 * always leaves destination null-terminated (for len > 0). 143 */ 144size_t 145strlcat(dest, src, len) 146 char *dest; 147 const char *src; 148 size_t len; 149{ 150 size_t dlen = strlen(dest); 151 152 return dlen + strlcpy(dest + dlen, src, (len > dlen? len - dlen: 0)); 153} 154 155#endif /* NO_SRTLXXX */ 156 157/* 158 * slprintf - format a message into a buffer. Like sprintf except we 159 * also specify the length of the output buffer, and we handle 160 * %m (error message), %v (visible string), 161 * %q (quoted string), %t (current time) and %I (IP address) formats. 162 * Doesn't do floating-point formats. 163 * Returns the number of chars put into buf. 164 */ 165int 166slprintf __V((char *buf, int buflen, char *fmt, ...)) 167{ 168 va_list args; 169 int n; 170 171#if defined(__STDC__) 172 va_start(args, fmt); 173#else 174 char *buf; 175 int buflen; 176 char *fmt; 177 va_start(args); 178 buf = va_arg(args, char *); 179 buflen = va_arg(args, int); 180 fmt = va_arg(args, char *); 181#endif 182 n = vslprintf(buf, buflen, fmt, args); 183 va_end(args); 184 return n; 185} 186 187/* 188 * vslprintf - like slprintf, takes a va_list instead of a list of args. 189 */ 190#define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0) 191 192int 193vslprintf(buf, buflen, fmt, args) 194 char *buf; 195 int buflen; 196 char *fmt; 197 va_list args; 198{ 199 int c, i, n; 200 int width, prec, fillch; 201 int base, len, neg, quoted; 202 unsigned long val = 0; 203 char *str, *f, *buf0; 204 unsigned char *p; 205 char num[32]; 206 time_t t; 207 u_int32_t ip; 208 static char hexchars[] = "0123456789abcdef"; 209 struct buffer_info bufinfo; 210 211 buf0 = buf; 212 --buflen; 213 while (buflen > 0) { 214 for (f = fmt; *f != '%' && *f != 0; ++f) 215 ; 216 if (f > fmt) { 217 len = f - fmt; 218 if (len > buflen) 219 len = buflen; 220 memcpy(buf, fmt, len); 221 buf += len; 222 buflen -= len; 223 fmt = f; 224 } 225 if (*fmt == 0) 226 break; 227 c = *++fmt; 228 width = 0; 229 prec = -1; 230 fillch = ' '; 231 if (c == '0') { 232 fillch = '0'; 233 c = *++fmt; 234 } 235 if (c == '*') { 236 width = va_arg(args, int); 237 c = *++fmt; 238 } else { 239 while (isdigit(c)) { 240 width = width * 10 + c - '0'; 241 c = *++fmt; 242 } 243 } 244 if (c == '.') { 245 c = *++fmt; 246 if (c == '*') { 247 prec = va_arg(args, int); 248 c = *++fmt; 249 } else { 250 prec = 0; 251 while (isdigit(c)) { 252 prec = prec * 10 + c - '0'; 253 c = *++fmt; 254 } 255 } 256 } 257 str = 0; 258 base = 0; 259 neg = 0; 260 ++fmt; 261 switch (c) { 262 case 'l': 263 c = *fmt++; 264 switch (c) { 265 case 'd': 266 val = va_arg(args, long); 267 if ((long)val < 0) { 268 neg = 1; 269 val = -val; 270 } 271 base = 10; 272 break; 273 case 'u': 274 val = va_arg(args, unsigned long); 275 base = 10; 276 break; 277 default: 278 *buf++ = '%'; --buflen; 279 *buf++ = 'l'; --buflen; 280 --fmt; /* so %lz outputs %lz etc. */ 281 continue; 282 } 283 break; 284 case 'd': 285 i = va_arg(args, int); 286 if (i < 0) { 287 neg = 1; 288 val = -i; 289 } else 290 val = i; 291 base = 10; 292 break; 293 case 'u': 294 val = va_arg(args, unsigned int); 295 base = 10; 296 break; 297 case 'o': 298 val = va_arg(args, unsigned int); 299 base = 8; 300 break; 301 case 'x': 302 case 'X': 303 val = va_arg(args, unsigned int); 304 base = 16; 305 break; 306 case 'p': 307 val = (unsigned long) va_arg(args, void *); 308 base = 16; 309 neg = 2; 310 break; 311 case 's': 312 str = va_arg(args, char *); 313 break; 314 case 'c': 315 num[0] = va_arg(args, int); 316 num[1] = 0; 317 str = num; 318 break; 319 case 'm': 320 str = strerror(errno); 321 break; 322 case 'I': 323 ip = va_arg(args, u_int32_t); 324 ip = ntohl(ip); 325 slprintf(num, sizeof(num), "%d.%d.%d.%d", (ip >> 24) & 0xff, 326 (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff); 327 str = num; 328 break; 329#if 0 /* not used, and breaks on S/390, apparently */ 330 case 'r': 331 f = va_arg(args, char *); 332#ifndef __powerpc__ 333 n = vslprintf(buf, buflen + 1, f, va_arg(args, va_list)); 334#else 335 /* On the powerpc, a va_list is an array of 1 structure */ 336 n = vslprintf(buf, buflen + 1, f, va_arg(args, void *)); 337#endif 338 buf += n; 339 buflen -= n; 340 continue; 341#endif 342 case 't': 343 time(&t); 344 str = ctime(&t); 345 str += 4; /* chop off the day name */ 346 str[15] = 0; /* chop off year and newline */ 347 break; 348 case 'v': /* "visible" string */ 349 case 'q': /* quoted string */ 350 quoted = c == 'q'; 351 p = va_arg(args, unsigned char *); 352 if (fillch == '0' && prec >= 0) { 353 n = prec; 354 } else { 355 n = strlen((char *)p); 356 if (prec >= 0 && n > prec) 357 n = prec; 358 } 359 while (n > 0 && buflen > 0) { 360 c = *p++; 361 --n; 362 if (!quoted && c >= 0x80) { 363 OUTCHAR('M'); 364 OUTCHAR('-'); 365 c -= 0x80; 366 } 367 if (quoted && (c == '"' || c == '\\')) 368 OUTCHAR('\\'); 369 if (c < 0x20 || (0x7f <= c && c < 0xa0)) { 370 if (quoted) { 371 OUTCHAR('\\'); 372 switch (c) { 373 case '\t': OUTCHAR('t'); break; 374 case '\n': OUTCHAR('n'); break; 375 case '\b': OUTCHAR('b'); break; 376 case '\f': OUTCHAR('f'); break; 377 default: 378 OUTCHAR('x'); 379 OUTCHAR(hexchars[c >> 4]); 380 OUTCHAR(hexchars[c & 0xf]); 381 } 382 } else { 383 if (c == '\t') 384 OUTCHAR(c); 385 else { 386 OUTCHAR('^'); 387 OUTCHAR(c ^ 0x40); 388 } 389 } 390 } else 391 OUTCHAR(c); 392 } 393 continue; 394 case 'P': /* print PPP packet */ 395 bufinfo.ptr = buf; 396 bufinfo.len = buflen + 1; 397 p = va_arg(args, unsigned char *); 398 n = va_arg(args, int); 399 format_packet(p, n, vslp_printer, &bufinfo); 400 buf = bufinfo.ptr; 401 buflen = bufinfo.len - 1; 402 continue; 403 case 'B': 404 p = va_arg(args, unsigned char *); 405 for (n = prec; n > 0; --n) { 406 c = *p++; 407 if (fillch == ' ') 408 OUTCHAR(' '); 409 OUTCHAR(hexchars[(c >> 4) & 0xf]); 410 OUTCHAR(hexchars[c & 0xf]); 411 } 412 continue; 413 default: 414 *buf++ = '%'; 415 if (c != '%') 416 --fmt; /* so %z outputs %z etc. */ 417 --buflen; 418 continue; 419 } 420 if (base != 0) { 421 str = num + sizeof(num); 422 *--str = 0; 423 while (str > num + neg) { 424 *--str = hexchars[val % base]; 425 val = val / base; 426 if (--prec <= 0 && val == 0) 427 break; 428 } 429 switch (neg) { 430 case 1: 431 *--str = '-'; 432 break; 433 case 2: 434 *--str = 'x'; 435 *--str = '0'; 436 break; 437 } 438 len = num + sizeof(num) - 1 - str; 439 } else { 440 len = strlen(str); 441 if (prec >= 0 && len > prec) 442 len = prec; 443 } 444 if (width > 0) { 445 if (width > buflen) 446 width = buflen; 447 if ((n = width - len) > 0) { 448 buflen -= n; 449 for (; n > 0; --n) 450 *buf++ = fillch; 451 } 452 } 453 if (len > buflen) 454 len = buflen; 455 memcpy(buf, str, len); 456 buf += len; 457 buflen -= len; 458 } 459 *buf = 0; 460 return buf - buf0; 461} 462 463/* 464 * vslp_printer - used in processing a %P format 465 */ 466static void 467vslp_printer __V((void *arg, char *fmt, ...)) 468{ 469 int n; 470 va_list pvar; 471 struct buffer_info *bi; 472 473#if defined(__STDC__) 474 va_start(pvar, fmt); 475#else 476 void *arg; 477 char *fmt; 478 va_start(pvar); 479 arg = va_arg(pvar, void *); 480 fmt = va_arg(pvar, char *); 481#endif 482 483 bi = (struct buffer_info *) arg; 484 n = vslprintf(bi->ptr, bi->len, fmt, pvar); 485 va_end(pvar); 486 487 bi->ptr += n; 488 bi->len -= n; 489} 490 491#ifdef unused 492/* 493 * log_packet - format a packet and log it. 494 */ 495 496void 497log_packet(p, len, prefix, level) 498 u_char *p; 499 int len; 500 char *prefix; 501 int level; 502{ 503 init_pr_log(prefix, level); 504 format_packet(p, len, pr_log, &level); 505 end_pr_log(); 506} 507#endif /* unused */ 508 509/* 510 * format_packet - make a readable representation of a packet, 511 * calling `printer(arg, format, ...)' to output it. 512 */ 513static void 514format_packet(p, len, printer, arg) 515 u_char *p; 516 int len; 517 void (*printer) __P((void *, char *, ...)); 518 void *arg; 519{ 520 int i, n; 521 u_short proto; 522 struct protent *protp; 523 524 if (len >= PPP_HDRLEN && p[0] == PPP_ALLSTATIONS && p[1] == PPP_UI) { 525 p += 2; 526 GETSHORT(proto, p); 527 len -= PPP_HDRLEN; 528 for (i = 0; (protp = protocols[i]) != NULL; ++i) 529 if (proto == protp->protocol) 530 break; 531 if (protp != NULL) { 532 printer(arg, "[%s", protp->name); 533 n = (*protp->printpkt)(p, len, printer, arg); 534 printer(arg, "]"); 535 p += n; 536 len -= n; 537 } else { 538 for (i = 0; (protp = protocols[i]) != NULL; ++i) 539 if (proto == (protp->protocol & ~0x8000)) 540 break; 541 if (protp != 0 && protp->data_name != 0) { 542#ifdef __APPLE__ 543 printer(arg, "[%s data", protp->data_name); 544 if (protp->printdatapkt) { 545 n = (*protp->printdatapkt)(p, len, printer, arg); 546 p += n; 547 len -= n; 548 } 549 printer(arg, "]\n"); 550 551 while (len > 0) { 552 int lcount = (len > 16) ? 16 : len; 553 554 /* output line (hex 1st, then ascii) */ 555 printer(arg, " "); 556 for(i = 0; i < lcount; i++) { 557 if (i == 8) printer(arg, " "); 558 printer(arg, "%.1B", &p[i]); 559 } 560 for( ; i < 16; i++) { 561 if (i == 8) printer(arg, " "); 562 printer(arg, " "); 563 } 564 printer(arg, " '"); 565 for(i = 0; i < lcount; i++) 566 printer(arg, "%c",(p[i]>=040 && p[i]<=0176)?p[i]:'.'); 567 printer(arg, "'\n"); 568 569 len -= 16; 570 p += 16; 571 } 572#else 573 printer(arg, "[%s data]\n", protp->data_name); 574 if (len > 8) 575 printer(arg, "%.8B ...", p); 576 else 577 printer(arg, "%.*B", len, p); 578#endif 579 len = 0; 580 } else 581 printer(arg, "[proto=0x%x]", proto); 582 } 583 } 584 585 if (len > 32) 586 printer(arg, "%.32B ...", p); 587 else 588 printer(arg, "%.*B", len, p); 589} 590 591/* 592 * init_pr_log, end_pr_log - initialize and finish use of pr_log. 593 */ 594 595static char line[256]; /* line to be logged accumulated here */ 596static char *linep; /* current pointer within line */ 597static int llevel; /* level for logging */ 598 599void 600init_pr_log(prefix, level) 601 char *prefix; 602 int level; 603{ 604 linep = line; 605 if (prefix != NULL) { 606 strlcpy(line, prefix, sizeof(line)); 607 linep = line + strlen(line); 608 } 609 llevel = level; 610} 611 612void 613end_pr_log() 614{ 615 if (linep != line) { 616 *linep = 0; 617 log_write(llevel, line); 618 } 619} 620 621/* 622 * pr_log - printer routine for outputting to syslog 623 */ 624void 625pr_log __V((void *arg, char *fmt, ...)) 626{ 627 int l, n; 628 va_list pvar; 629 char *p, *eol; 630 char buf[256]; 631 632#if defined(__STDC__) 633 va_start(pvar, fmt); 634#else 635 void *arg; 636 char *fmt; 637 va_start(pvar); 638 arg = va_arg(pvar, void *); 639 fmt = va_arg(pvar, char *); 640#endif 641 642 n = vslprintf(buf, sizeof(buf), fmt, pvar); 643 va_end(pvar); 644 645 p = buf; 646 eol = strchr(buf, '\n'); 647 if (linep != line) { 648 l = (eol == NULL)? n: eol - buf; 649 if (linep + l < line + sizeof(line)) { 650 if (l > 0) { 651 memcpy(linep, buf, l); 652 linep += l; 653 } 654 if (eol == NULL) 655 return; 656 p = eol + 1; 657 eol = strchr(p, '\n'); 658 } 659 *linep = 0; 660 log_write(llevel, line); 661 linep = line; 662 } 663 664 while (eol != NULL) { 665 *eol = 0; 666 log_write(llevel, p); 667 p = eol + 1; 668 eol = strchr(p, '\n'); 669 } 670 671 /* assumes sizeof(buf) <= sizeof(line) */ 672 l = buf + n - p; 673 if (l > 0) { 674 memcpy(line, p, n); 675 linep = line + l; 676 } 677} 678 679/* 680 * print_string - print a readable representation of a string using 681 * printer. 682 */ 683void 684print_string(p, len, printer, arg) 685 char *p; 686 int len; 687 void (*printer) __P((void *, char *, ...)); 688 void *arg; 689{ 690 int c; 691 692 printer(arg, "\""); 693 for (; len > 0; --len) { 694 c = *p++; 695 if (' ' <= c && c <= '~') { 696 if (c == '\\' || c == '"') 697 printer(arg, "\\"); 698 printer(arg, "%c", c); 699 } else { 700 switch (c) { 701 case '\n': 702 printer(arg, "\\n"); 703 break; 704 case '\r': 705 printer(arg, "\\r"); 706 break; 707 case '\t': 708 printer(arg, "\\t"); 709 break; 710 default: 711 printer(arg, "\\%.3o", c); 712 } 713 } 714 } 715 printer(arg, "\""); 716} 717 718/* 719 * logit - does the hard work for fatal et al. 720 */ 721static void 722logit(level, fmt, args) 723 int level; 724 char *fmt; 725 va_list args; 726{ 727 int n; 728#ifdef __APPLE__ 729 char buf[4096]; 730#else 731 char buf[1024]; 732#endif 733 734 n = vslprintf(buf, sizeof(buf), fmt, args); 735 log_write(level, buf); 736} 737 738static void 739log_write(level, buf) 740 int level; 741 char *buf; 742{ 743#ifdef __APPLE__ 744 time_t t; 745 int ns; 746 char s[64]; 747#endif 748 749 sys_log(level, "%s", buf); 750 if (log_to_fd >= 0 && (level != LOG_DEBUG || debug)) { 751 int n = strlen(buf); 752 753#ifdef __APPLE__ 754 time(&t); 755 ns = strftime(s, sizeof(s), "%c : ", localtime(&t)); 756 if (write(log_to_fd, s, ns) != ns) 757 log_to_fd = -1; 758#endif 759 760 if (n > 0 && buf[n-1] == '\n') 761 --n; 762 if (write(log_to_fd, buf, n) != n 763 || write(log_to_fd, "\n", 1) != 1) 764 log_to_fd = -1; 765 } 766} 767 768/* 769 * fatal - log an error message and die horribly. 770 */ 771void 772fatal __V((char *fmt, ...)) 773{ 774 va_list pvar; 775 776#if defined(__STDC__) 777 va_start(pvar, fmt); 778#else 779 char *fmt; 780 va_start(pvar); 781 fmt = va_arg(pvar, char *); 782#endif 783 784 logit(LOG_ERR, fmt, pvar); 785 va_end(pvar); 786 787 die(1); /* as promised */ 788} 789 790/* 791 * error - log an error message. 792 */ 793void 794error __V((char *fmt, ...)) 795{ 796 va_list pvar; 797 798#if defined(__STDC__) 799 va_start(pvar, fmt); 800#else 801 char *fmt; 802 va_start(pvar); 803 fmt = va_arg(pvar, char *); 804#endif 805 806 logit(LOG_ERR, fmt, pvar); 807 va_end(pvar); 808 ++error_count; 809} 810 811/* 812 * warn - log a warning message. 813 */ 814void 815#ifdef __APPLE__ 816warning 817#else 818warn 819#endif 820 __V((char *fmt, ...)) 821{ 822 va_list pvar; 823 824#if defined(__STDC__) 825 va_start(pvar, fmt); 826#else 827 char *fmt; 828 va_start(pvar); 829 fmt = va_arg(pvar, char *); 830#endif 831 832 logit(LOG_WARNING, fmt, pvar); 833 va_end(pvar); 834} 835 836/* 837 * notice - log a notice-level message. 838 */ 839void 840notice __V((char *fmt, ...)) 841{ 842 va_list pvar; 843 844#if defined(__STDC__) 845 va_start(pvar, fmt); 846#else 847 char *fmt; 848 va_start(pvar); 849 fmt = va_arg(pvar, char *); 850#endif 851 852 logit(LOG_NOTICE, fmt, pvar); 853 va_end(pvar); 854} 855 856/* 857 * info - log an informational message. 858 */ 859void 860info __V((char *fmt, ...)) 861{ 862 va_list pvar; 863 864#if defined(__STDC__) 865 va_start(pvar, fmt); 866#else 867 char *fmt; 868 va_start(pvar); 869 fmt = va_arg(pvar, char *); 870#endif 871 872 logit(LOG_INFO, fmt, pvar); 873 va_end(pvar); 874} 875 876/* 877 * dbglog - log a debug message. 878 */ 879void 880dbglog __V((char *fmt, ...)) 881{ 882 va_list pvar; 883 884#if defined(__STDC__) 885 va_start(pvar, fmt); 886#else 887 char *fmt; 888 va_start(pvar); 889 fmt = va_arg(pvar, char *); 890#endif 891 892 logit(LOG_DEBUG, fmt, pvar); 893 va_end(pvar); 894} 895 896/* 897 * dump_packet - print out a packet in readable form if it is interesting. 898 * Assumes len >= PPP_HDRLEN. 899 */ 900void 901dump_packet(const char *tag, unsigned char *p, int len) 902{ 903 int proto; 904 905 if (!debug) 906 return; 907 908 /* 909 * don't print LCP echo request/reply packets if debug <= 1 910 * and the link is up. 911 */ 912 proto = (p[2] << 8) + p[3]; 913 if (debug <= 1 && unsuccess == 0 && proto == PPP_LCP 914 && len >= PPP_HDRLEN + HEADERLEN) { 915 unsigned char *lcp = p + PPP_HDRLEN; 916 int l = (lcp[2] << 8) + lcp[3]; 917 if ((lcp[0] == ECHOREQ || lcp[0] == ECHOREP 918#ifdef __APPLE__ 919 || lcp[0] == TIMEREMAINING 920#endif 921 ) 922 && l >= HEADERLEN && l <= len - PPP_HDRLEN) 923 return; 924 } 925 926 dbglog("%s %P", tag, p, len); 927} 928 929/* 930 * complete_read - read a full `count' bytes from fd, 931 * unless end-of-file or an error other than EINTR is encountered. 932 */ 933ssize_t 934complete_read(int fd, void *buf, size_t count) 935{ 936 size_t done; 937 ssize_t nb; 938 char *ptr = buf; 939 940 for (done = 0; done < count; ) { 941 nb = read(fd, ptr, count - done); 942 if (nb < 0) { 943 if (errno == EINTR) 944 continue; 945 return -1; 946 } 947 if (nb == 0) 948 break; 949 done += nb; 950 ptr += nb; 951 } 952 return done; 953} 954 955/* Procedures for locking the serial device using a lock file. */ 956#ifndef LOCK_DIR 957#ifdef __linux__ 958#define LOCK_DIR "/var/lock" 959#else 960#ifdef SVR4 961#define LOCK_DIR "/var/spool/locks" 962#else 963#define LOCK_DIR "/var/spool/lock" 964#endif 965#endif 966#endif /* LOCK_DIR */ 967 968static char lock_file[MAXPATHLEN]; 969 970/* 971 * lock - create a lock file for the named device 972 */ 973int 974lock(dev) 975 char *dev; 976{ 977#ifdef LOCKLIB 978 int result; 979 980 result = mklock (dev, (void *) 0); 981 if (result == 0) { 982 strlcpy(lock_file, dev, sizeof(lock_file)); 983 return 0; 984 } 985 986 if (result > 0) 987 notice("Device %s is locked by pid %d", dev, result); 988 else 989 error("Can't create lock file %s", lock_file); 990 return -1; 991 992#else /* LOCKLIB */ 993 994 char lock_buffer[12]; 995 int fd, pid, n; 996 997#ifdef SVR4 998 struct stat sbuf; 999 1000 if (stat(dev, &sbuf) < 0) { 1001 error("Can't get device number for %s: %m", dev); 1002 return -1; 1003 } 1004 if ((sbuf.st_mode & S_IFMT) != S_IFCHR) { 1005 error("Can't lock %s: not a character device", dev); 1006 return -1; 1007 } 1008 slprintf(lock_file, sizeof(lock_file), "%s/LK.%03d.%03d.%03d", 1009 LOCK_DIR, major(sbuf.st_dev), 1010 major(sbuf.st_rdev), minor(sbuf.st_rdev)); 1011#else 1012 char *p; 1013 char lockdev[MAXPATHLEN]; 1014 1015 if ((p = strstr(dev, "dev/")) != NULL) { 1016 dev = p + 4; 1017 strncpy(lockdev, dev, MAXPATHLEN-1); 1018 lockdev[MAXPATHLEN-1] = 0; 1019 while ((p = strrchr(lockdev, '/')) != NULL) { 1020 *p = '_'; 1021 } 1022 dev = lockdev; 1023 } else 1024 if ((p = strrchr(dev, '/')) != NULL) 1025 dev = p + 1; 1026 1027 slprintf(lock_file, sizeof(lock_file), "%s/LCK..%s", LOCK_DIR, dev); 1028#endif 1029 1030 while ((fd = open(lock_file, O_EXCL | O_CREAT | O_RDWR, 0644)) < 0) { 1031 if (errno != EEXIST) { 1032 error("Can't create lock file %s: %m", lock_file); 1033 break; 1034 } 1035 1036 /* Read the lock file to find out who has the device locked. */ 1037 fd = open(lock_file, O_RDONLY, 0); 1038 if (fd < 0) { 1039 if (errno == ENOENT) /* This is just a timing problem. */ 1040 continue; 1041 error("Can't open existing lock file %s: %m", lock_file); 1042 break; 1043 } 1044#ifndef LOCK_BINARY 1045 n = read(fd, lock_buffer, 11); 1046#else 1047 n = read(fd, &pid, sizeof(pid)); 1048#endif /* LOCK_BINARY */ 1049 close(fd); 1050 fd = -1; 1051 if (n <= 0) { 1052 error("Can't read pid from lock file %s", lock_file); 1053 break; 1054 } 1055 1056 /* See if the process still exists. */ 1057#ifndef LOCK_BINARY 1058 lock_buffer[n] = 0; 1059 pid = atoi(lock_buffer); 1060#endif /* LOCK_BINARY */ 1061 if (pid == getpid()) 1062 return 1; /* somebody else locked it for us */ 1063 if (pid == 0 1064 || (kill(pid, 0) == -1 && errno == ESRCH)) { 1065 if (unlink (lock_file) == 0) { 1066 notice("Removed stale lock on %s (pid %d)", dev, pid); 1067 continue; 1068 } 1069 warning("Couldn't remove stale lock on %s", dev); 1070 } else 1071 notice("Device %s is locked by pid %d", dev, pid); 1072 break; 1073 } 1074 1075 if (fd < 0) { 1076 lock_file[0] = 0; 1077 return -1; 1078 } 1079 1080 pid = getpid(); 1081#ifndef LOCK_BINARY 1082 slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid); 1083 write (fd, lock_buffer, 11); 1084#else 1085 write(fd, &pid, sizeof (pid)); 1086#endif 1087 close(fd); 1088 return 0; 1089 1090#endif 1091} 1092 1093/* 1094 * relock - called to update our lockfile when we are about to detach, 1095 * thus changing our pid (we fork, the child carries on, and the parent dies). 1096 * Note that this is called by the parent, with pid equal to the pid 1097 * of the child. This avoids a potential race which would exist if 1098 * we had the child rewrite the lockfile (the parent might die first, 1099 * and another process could think the lock was stale if it checked 1100 * between when the parent died and the child rewrote the lockfile). 1101 */ 1102int 1103relock(pid) 1104 int pid; 1105{ 1106#ifdef LOCKLIB 1107 /* XXX is there a way to do this? */ 1108 return -1; 1109#else /* LOCKLIB */ 1110 1111 int fd; 1112 char lock_buffer[12]; 1113 1114 if (lock_file[0] == 0) 1115 return -1; 1116 fd = open(lock_file, O_WRONLY, 0); 1117 if (fd < 0) { 1118 error("Couldn't reopen lock file %s: %m", lock_file); 1119 lock_file[0] = 0; 1120 return -1; 1121 } 1122 1123#ifndef LOCK_BINARY 1124 slprintf(lock_buffer, sizeof(lock_buffer), "%10d\n", pid); 1125 write (fd, lock_buffer, 11); 1126#else 1127 write(fd, &pid, sizeof(pid)); 1128#endif /* LOCK_BINARY */ 1129 close(fd); 1130 return 0; 1131 1132#endif /* LOCKLIB */ 1133} 1134 1135/* 1136 * unlock - remove our lockfile 1137 */ 1138void 1139unlock() 1140{ 1141 if (lock_file[0]) { 1142#ifdef LOCKLIB 1143 (void) rmlock(lock_file, (void *) 0); 1144#else 1145 unlink(lock_file); 1146#endif 1147 lock_file[0] = 0; 1148 } 1149} 1150 1151static char unknown_if_family_str[16]; 1152static char * 1153if_family2ascii (u_int32_t if_family) 1154{ 1155 switch (if_family) { 1156 case APPLE_IF_FAM_LOOPBACK: 1157 return("Loopback"); 1158 case APPLE_IF_FAM_ETHERNET: 1159 return("Ether"); 1160 case APPLE_IF_FAM_SLIP: 1161 return("SLIP"); 1162 case APPLE_IF_FAM_TUN: 1163 return("TUN"); 1164 case APPLE_IF_FAM_VLAN: 1165 return("VLAN"); 1166 case APPLE_IF_FAM_PPP: 1167 return("PPP"); 1168 case APPLE_IF_FAM_PVC: 1169 return("PVC"); 1170 case APPLE_IF_FAM_DISC: 1171 return("DISC"); 1172 case APPLE_IF_FAM_MDECAP: 1173 return("MDECAP"); 1174 case APPLE_IF_FAM_GIF: 1175 return("GIF"); 1176 case APPLE_IF_FAM_FAITH: 1177 return("FAITH"); 1178 case APPLE_IF_FAM_STF: 1179 return("STF"); 1180 case APPLE_IF_FAM_FIREWIRE: 1181 return("FireWire"); 1182 case APPLE_IF_FAM_BOND: 1183 return("Bond"); 1184 default: 1185 snprintf(unknown_if_family_str, sizeof(unknown_if_family_str), "%d", if_family); 1186 return(unknown_if_family_str); 1187 } 1188} 1189 1190void 1191log_vpn_interface_address_event (const char *location, 1192 struct kern_event_msg *ev_msg, 1193 int wait_interface_timeout, 1194 u_char *interface, 1195 struct in_addr *our_address) 1196{ 1197 struct in_addr mask; 1198 char our_addr_str[INET_ADDRSTRLEN]; 1199 1200 if (!ev_msg) { 1201 notice("%s: %d secs TIMEOUT waiting for interface to be reconfigured. previous setting (name: %s, address: %s).", 1202 location, 1203 wait_interface_timeout, 1204 interface, 1205 addr2ascii(AF_INET, our_address, sizeof(*our_address), our_addr_str)); 1206 return; 1207 } else { 1208 struct kev_in_data *inetdata = (struct kev_in_data *) &ev_msg->event_data[0]; 1209 struct kev_in_collision *inetdata_coll = (struct kev_in_collision *) &ev_msg->event_data[0]; 1210 char new_addr_str[INET_ADDRSTRLEN]; 1211 char new_mask_str[INET_ADDRSTRLEN]; 1212 char dst_addr_str[INET_ADDRSTRLEN]; 1213 1214 mask.s_addr = ntohl(inetdata->ia_subnetmask); 1215 1216 switch (ev_msg->event_code) { 1217 case KEV_INET_NEW_ADDR: 1218 notice("%s: Address added. previous interface setting (name: %s, address: %s), current interface setting (name: %s%d, family: %s, address: %s, subnet: %s, destination: %s).", 1219 location, 1220 interface, 1221 addr2ascii(AF_INET, our_address, sizeof(*our_address), our_addr_str), 1222 inetdata->link_data.if_name, inetdata->link_data.if_unit, 1223 if_family2ascii(inetdata->link_data.if_family), 1224 addr2ascii(AF_INET, &inetdata->ia_addr, sizeof(inetdata->ia_addr), new_addr_str), 1225 addr2ascii(AF_INET, &mask, sizeof(mask), new_mask_str), 1226 addr2ascii(AF_INET, &inetdata->ia_dstaddr, sizeof(inetdata->ia_dstaddr), dst_addr_str)); 1227 break; 1228 case KEV_INET_CHANGED_ADDR: 1229 notice("%s: Address changed. previous interface setting (name: %s, address: %s), current interface setting (name: %s%d, family: %s, address: %s, subnet: %s, destination: %s).", 1230 location, 1231 interface, 1232 addr2ascii(AF_INET, our_address, sizeof(*our_address), our_addr_str), 1233 inetdata->link_data.if_name, inetdata->link_data.if_unit, 1234 if_family2ascii(inetdata->link_data.if_family), 1235 addr2ascii(AF_INET, &inetdata->ia_addr, sizeof(inetdata->ia_addr), new_addr_str), 1236 addr2ascii(AF_INET, &mask, sizeof(mask), new_mask_str), 1237 addr2ascii(AF_INET, &inetdata->ia_dstaddr, sizeof(inetdata->ia_dstaddr), dst_addr_str)); 1238 break; 1239 case KEV_INET_ADDR_DELETED: 1240 notice("%s: Address deleted. previous interface setting (name: %s, address: %s), deleted interface setting (name: %s%d, family: %s, address: %s, subnet: %s, destination: %s).", 1241 location, 1242 interface, 1243 addr2ascii(AF_INET, our_address, sizeof(*our_address), our_addr_str), 1244 inetdata->link_data.if_name, inetdata->link_data.if_unit, 1245 if_family2ascii(inetdata->link_data.if_family), 1246 addr2ascii(AF_INET, &inetdata->ia_addr, sizeof(inetdata->ia_addr), new_addr_str), 1247 addr2ascii(AF_INET, &mask, sizeof(mask), new_mask_str), 1248 addr2ascii(AF_INET, &inetdata->ia_dstaddr, sizeof(inetdata->ia_dstaddr), dst_addr_str)); 1249 break; 1250 case KEV_INET_ARPCOLLISION: 1251 notice("%s: ARP collided. previous interface setting (name: %s, address: %s), conflicting interface setting (name: %s%d, family: %s, address: %s, mac: %x:%x:%x:%x:%x:%x).", 1252 location, 1253 interface, 1254 addr2ascii(AF_INET, our_address, sizeof(*our_address), our_addr_str), 1255 inetdata_coll->link_data.if_name, 1256 inetdata_coll->link_data.if_unit, 1257 if_family2ascii(inetdata_coll->link_data.if_family), 1258 addr2ascii(AF_INET, &inetdata_coll->ia_ipaddr, sizeof(inetdata_coll->ia_ipaddr), new_addr_str), 1259 inetdata_coll->hw_addr[5],inetdata_coll->hw_addr[4],inetdata_coll->hw_addr[3],inetdata_coll->hw_addr[2],inetdata_coll->hw_addr[1],inetdata_coll->hw_addr[0]); 1260 break; 1261 default: 1262 notice("%s: Other Address event (%d). previous interface setting (name: %s, address: %s), other interface setting (name: %s%d, family: %s, address: %s, subnet: %s, destination: %s).", 1263 location, 1264 ev_msg->event_code, 1265 interface, 1266 addr2ascii(AF_INET, our_address, sizeof(*our_address), our_addr_str), 1267 inetdata->link_data.if_name, inetdata->link_data.if_unit, 1268 if_family2ascii(inetdata->link_data.if_family), 1269 addr2ascii(AF_INET, &inetdata->ia_addr, sizeof(inetdata->ia_addr), new_addr_str), 1270 addr2ascii(AF_INET, &mask, sizeof(mask), new_mask_str), 1271 addr2ascii(AF_INET, &inetdata->ia_dstaddr, sizeof(inetdata->ia_dstaddr), dst_addr_str)); 1272 break; 1273 } 1274 } 1275} 1276 1277int 1278check_vpn_interface_or_service_unrecoverable (SCDynamicStoreRef dynamicStoreRef, 1279 const char *location, 1280 struct kern_event_msg *ev_msg, 1281 char *interface_buf) 1282{ 1283 //SCDynamicStoreRef dynamicStoreRef = (SCDynamicStoreRef)dynamicStore; 1284 1285 // return 1, if this is a delete event, and; 1286 // TODO: add support for IPv6 <rdar://problem/5920237> 1287 // walk Setup:/Network/Service/* and check if there are service entries referencing this interface. e.g. Setup:/Network/Service/44DB8790-0177-4F17-8D4E-37F9413D1D87/Interface:DeviceName == interface, other_serv_found = 1 1288 // Setup:/Network/Interface/"interface"/AirPort:'PowerEnable' == 0 || Setup:/Network/Interface/"interface"/IPv4 is missing, interf_down = 1 1289 if (!dynamicStoreRef) 1290 dbglog("%s: invalid SCDynamicStore reference", location); 1291 1292 if (dynamicStoreRef && 1293 (ev_msg->event_code == KEV_INET_ADDR_DELETED || ev_msg->event_code == KEV_INET_CHANGED_ADDR)) { 1294 CFStringRef interf_key; 1295 CFMutableArrayRef interf_keys; 1296 CFStringRef pattern; 1297 CFMutableArrayRef patterns; 1298 CFDictionaryRef dict = NULL; 1299 CFIndex i; 1300 const void * keys_q[128]; 1301 const void ** keys = keys_q; 1302 const void * values_q[128]; 1303 const void ** values = values_q; 1304 CFIndex n; 1305 CFStringRef vpn_if; 1306 int other_serv_found = 0, interf_down = 0; 1307 1308 vpn_if = CFStringCreateWithCStringNoCopy(NULL, 1309 interface_buf, 1310 kCFStringEncodingASCII, 1311 kCFAllocatorNull); 1312 if (!vpn_if) { 1313 // if we could not initialize interface CFString 1314 notice("%s: failed to initialize interface CFString", location); 1315 goto done; 1316 } 1317 1318 interf_keys = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 1319 patterns = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); 1320 // get Setup:/Network/Interface/<vpn_if>/Airport 1321 interf_key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, 1322 kSCDynamicStoreDomainSetup, 1323 vpn_if, 1324 kSCEntNetAirPort); 1325 CFArrayAppendValue(interf_keys, interf_key); 1326 CFRelease(interf_key); 1327 // get State:/Network/Interface/<vpn_if>/Airport 1328 interf_key = SCDynamicStoreKeyCreateNetworkInterfaceEntity(NULL, 1329 kSCDynamicStoreDomainState, 1330 vpn_if, 1331 kSCEntNetAirPort); 1332 CFArrayAppendValue(interf_keys, interf_key); 1333 CFRelease(interf_key); 1334 // get Setup:/Network/Service/*/Interface 1335 pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, 1336 kSCDynamicStoreDomainSetup, 1337 kSCCompAnyRegex, 1338 kSCEntNetInterface); 1339 CFArrayAppendValue(patterns, pattern); 1340 CFRelease(pattern); 1341 // get Setup:/Network/Service/*/IPv4 1342 pattern = SCDynamicStoreKeyCreateNetworkServiceEntity(NULL, 1343 kSCDynamicStoreDomainSetup, 1344 kSCCompAnyRegex, 1345 kSCEntNetIPv4); 1346 CFArrayAppendValue(patterns, pattern); 1347 CFRelease(pattern); 1348 dict = SCDynamicStoreCopyMultiple(dynamicStoreRef, interf_keys, patterns); 1349 CFRelease(interf_keys); 1350 CFRelease(patterns); 1351 1352 if (!dict) { 1353 // if we could not access the SCDynamicStore 1354 notice("%s: failed to initialize SCDynamicStore dictionary", location); 1355 CFRelease(vpn_if); 1356 goto done; 1357 } 1358 // look for the service which matches the provided prefixes 1359 n = CFDictionaryGetCount(dict); 1360 if (n <= 0) { 1361 notice("%s: empty SCDynamicStore dictionary", location); 1362 CFRelease(vpn_if); 1363 goto done; 1364 } 1365 if (n > (CFIndex)(sizeof(keys_q) / sizeof(CFTypeRef))) { 1366 keys = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0); 1367 values = CFAllocatorAllocate(NULL, n * sizeof(CFTypeRef), 0); 1368 } 1369 CFDictionaryGetKeysAndValues(dict, keys, values); 1370 for (i=0; i < n; i++) { 1371 CFStringRef s_key = (CFStringRef)keys[i]; 1372 CFDictionaryRef s_dict = (CFDictionaryRef)values[i]; 1373 CFStringRef s_if; 1374 1375 if (!isA_CFString(s_key) || !isA_CFDictionary(s_dict)) { 1376 continue; 1377 } 1378 1379 if (CFStringHasSuffix(s_key, kSCEntNetInterface)) { 1380 // is a Service Interface entity 1381 s_if = CFDictionaryGetValue(s_dict, kSCPropNetInterfaceDeviceName); 1382 if (isA_CFString(s_if) && CFEqual(vpn_if, s_if)) { 1383 CFArrayRef components; 1384 CFStringRef serviceIDRef = NULL, serviceKey = NULL; 1385 CFPropertyListRef serviceRef = NULL; 1386 1387 other_serv_found = 1; 1388 // extract service ID 1389 components = CFStringCreateArrayBySeparatingStrings(NULL, s_key, CFSTR("/")); 1390 if (CFArrayGetCount(components) > 3) { 1391 serviceIDRef = CFArrayGetValueAtIndex(components, 3); 1392 //if (new key) Setup:/Network/Service/service_id/IPv4 is missing, then interf_down = 1 1393 serviceKey = SCDynamicStoreKeyCreateNetworkServiceEntity(0, kSCDynamicStoreDomainSetup, serviceIDRef, kSCEntNetIPv4); 1394 if (!serviceKey || 1395 !(serviceRef = CFDictionaryGetValue(dict, serviceKey))) { 1396 notice("%s: detected disabled IPv4 Config", location); 1397 interf_down = 1; 1398 } 1399 if (serviceKey) CFRelease(serviceKey); 1400 } 1401 if (components) CFRelease(components); 1402 if (interf_down) break; 1403 } 1404 continue; 1405 } else if (CFStringHasSuffix(s_key, kSCEntNetAirPort)) { 1406 // Interface/<vpn_if>/Airport entity 1407 if (CFStringHasPrefix(s_key, kSCDynamicStoreDomainSetup)) { 1408 CFBooleanRef powerEnable = CFDictionaryGetValue(s_dict, SC_AIRPORT_POWERENABLED_KEY); 1409 if (isA_CFBoolean(powerEnable) && 1410 CFEqual(powerEnable, kCFBooleanFalse)) { 1411 notice("%s: detected AirPort, PowerEnable == FALSE", location); 1412 interf_down = 1; 1413 break; 1414 } 1415 } else if (CFStringHasPrefix(s_key, kSCDynamicStoreDomainState)) { 1416 UInt16 temp; 1417 CFNumberRef airStatus = CFDictionaryGetValue(s_dict, SC_AIRPORT_POWERSTATUS_KEY); 1418 if (isA_CFNumber(airStatus) && 1419 CFNumberGetValue(airStatus, kCFNumberShortType, &temp)) { 1420 if (temp ==0) { 1421 notice("%s: detected AirPort, PowerStatus == 0", location); 1422 } 1423 } 1424 } 1425 continue; 1426 } 1427 } 1428 if (vpn_if) CFRelease(vpn_if); 1429 if (keys != keys_q) { 1430 CFAllocatorDeallocate(NULL, keys); 1431 CFAllocatorDeallocate(NULL, values); 1432 } 1433done : 1434 if (dict) CFRelease(dict); 1435 1436 return (other_serv_found == 0 || interf_down == 1); 1437 } 1438 return 0; 1439} 1440 1441int 1442check_vpn_interface_address_change (int transport_down, 1443 struct kern_event_msg *ev_msg, 1444 char *interface_buf, 1445 int interface_media, 1446 struct in_addr *our_address) 1447{ 1448 struct kev_in_data *inetdata; 1449 1450 /* if transport is still down: ignore deletes, and check if the underlying interface's address has changed (ignore link-local addresses) */ 1451 if (transport_down && 1452 (ev_msg->event_code == KEV_INET_NEW_ADDR || ev_msg->event_code == KEV_INET_CHANGED_ADDR)) { 1453 inetdata = (struct kev_in_data *) &ev_msg->event_data[0]; 1454#if 0 1455 notice("%s: checking for interface address change. underlying %s, old-addr %x, new-addr %x\n", 1456 __FUNCTION__, interface_buf, our_address->s_addr, inetdata->ia_addr.s_addr); 1457#endif 1458 /* check if address changed */ 1459 if (our_address->s_addr != inetdata->ia_addr.s_addr && 1460 !IN_LINKLOCAL(ntohl(inetdata->ia_addr.s_addr))) { 1461 return 1; 1462 } 1463 } 1464 1465 return 0; 1466} 1467 1468int 1469check_vpn_interface_alternate (int transport_down, 1470 struct kern_event_msg *ev_msg, 1471 char *interface_buf) 1472{ 1473 struct kev_in_data *inetdata; 1474 1475 /* if transport is still down: ignore deletes, and check if an alternative interface has a valid address (ignore link-local) */ 1476 if (transport_down && 1477 (ev_msg->event_code == KEV_INET_NEW_ADDR || ev_msg->event_code == KEV_INET_CHANGED_ADDR)) { 1478 inetdata = (struct kev_in_data *) &ev_msg->event_data[0]; 1479#if 0 1480 notice("%s: checking for alternate interface. underlying %s, new-addr %x\n", 1481 __FUNCTION__, interface_buf, inetdata->ia_addr.s_addr); 1482#endif 1483 if (!IN_LINKLOCAL(ntohl(inetdata->ia_addr.s_addr))) { 1484 return 1; 1485 } 1486 } 1487 1488 return 0; 1489} 1490 1491#if 0 1492/* 1493 * print_hex - hexdump (in out buffer) of binary data (in buffer), for count bytes 1494 */ 1495static void 1496print_hex (unsigned char *out, unsigned char *in, int count) 1497{ 1498 register unsigned char next_ch; 1499 static char hex[] = "0123456789abcdef"; 1500 1501 while (count-- > 0) { 1502 next_ch = *in++; 1503 *out++ = hex[(next_ch >> 4) & 0x0F]; 1504 *out++ = hex[next_ch & 0x0F]; 1505 } 1506 1507 *out = '\0'; 1508} 1509 1510/* 1511 * dump_mppe_keys - print out mppe send/recv keys 1512 */ 1513void 1514dump_buffer(char *caller, unsigned char* binbuf, int size) 1515{ 1516 if(binbuf) 1517 { 1518 static unsigned char buf[65]; 1519 1520 print_hex(buf, binbuf, size); 1521 error("%s: data (%d bits) = %s",caller, size<<3, buf); 1522 } 1523} 1524#endif 1525