1 /* -*- Mode: C; tab-width: 4 -*- 2 * 3 * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 #include "mDNSUNP.h" 19 20 #include <errno.h> 21 #include <assert.h> 22 #include <string.h> 23 #include <stdlib.h> 24 #include <sys/uio.h> 25 #include <sys/ioctl.h> 26 #include <signal.h> 27 #include <unistd.h> 28 #include <stdio.h> 29 30 /* Some weird platforms derived from 4.4BSD Lite (e.g. EFI) need the ALIGN(P) 31 macro, usually defined in <sys/param.h> or someplace like that, to make sure the 32 CMSG_NXTHDR macro is well-formed. On such platforms, the symbol NEED_ALIGN_MACRO 33 should be set to the name of the header to include to get the ALIGN(P) macro. 34 */ 35 #ifdef NEED_ALIGN_MACRO 36 #include NEED_ALIGN_MACRO 37 #endif 38 39 /* Solaris defined SIOCGIFCONF etc in <sys/sockio.h> but 40 other platforms don't even have that include file. So, 41 if we haven't yet got a definition, let's try to find 42 <sys/sockio.h>. 43 */ 44 45 #ifndef SIOCGIFCONF 46 #include <sys/sockio.h> 47 #endif 48 49 /* sockaddr_dl is only referenced if we're using IP_RECVIF, 50 so only include the header in that case. 51 */ 52 53 #ifdef IP_RECVIF 54 #include <net/if_dl.h> 55 #endif 56 57 #if defined(AF_INET6) && HAVE_IPV6 && !HAVE_LINUX 58 #include <net/if_var.h> 59 #include <netinet/in_var.h> 60 // Note: netinet/in_var.h implicitly includes netinet6/in6_var.h for us 61 #endif 62 63 #if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX 64 #include <netdb.h> 65 #include <arpa/inet.h> 66 67 /* Converts a prefix length to IPv6 network mask */ 68 void plen_to_mask(int plen, char *addr) { 69 int i; 70 int colons=7; /* Number of colons in IPv6 address */ 71 int bits_in_block=16; /* Bits per IPv6 block */ 72 for(i=0;i<=colons;i++) { 73 int block, ones=0xffff, ones_in_block; 74 if (plen>bits_in_block) ones_in_block=bits_in_block; 75 else ones_in_block=plen; 76 block = ones & (ones << (bits_in_block-ones_in_block)); 77 i==0 ? sprintf(addr, "%x", block) : sprintf(addr, "%s:%x", addr, block); 78 plen -= ones_in_block; 79 } 80 } 81 82 /* Gets IPv6 interface information from the /proc filesystem in linux*/ 83 struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases) 84 { 85 struct ifi_info *ifi, *ifihead, **ifipnext, *ifipold, **ifiptr; 86 FILE *fp = NULL; 87 char addr[8][5]; 88 int flags, myflags, index, plen, scope; 89 char ifname[9], lastname[IFNAMSIZ]; 90 char addr6[32+7+1]; /* don't forget the seven ':' */ 91 struct addrinfo hints, *res0; 92 struct sockaddr_in6 *sin6; 93 struct in6_addr *addrptr; 94 int err; 95 int sockfd = -1; 96 struct ifreq ifr; 97 98 res0=NULL; 99 ifihead = NULL; 100 ifipnext = &ifihead; 101 lastname[0] = 0; 102 103 if ((fp = fopen(PROC_IFINET6_PATH, "r")) != NULL) { 104 sockfd = socket(AF_INET6, SOCK_DGRAM, 0); 105 if (sockfd < 0) { 106 goto gotError; 107 } 108 while (fscanf(fp, 109 "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %8s\n", 110 addr[0],addr[1],addr[2],addr[3], 111 addr[4],addr[5],addr[6],addr[7], 112 &index, &plen, &scope, &flags, ifname) != EOF) { 113 114 myflags = 0; 115 if (strncmp(lastname, ifname, IFNAMSIZ) == 0) { 116 if (doaliases == 0) 117 continue; /* already processed this interface */ 118 myflags = IFI_ALIAS; 119 } 120 strncpy(lastname, ifname, IFNAMSIZ); 121 ifi = (struct ifi_info*)calloc(1, sizeof(struct ifi_info)); 122 if (ifi == NULL) { 123 goto gotError; 124 } 125 126 ifipold = *ifipnext; /* need this later */ 127 ifiptr = ifipnext; 128 *ifipnext = ifi; /* prev points to this new one */ 129 ifipnext = &ifi->ifi_next; /* pointer to next one goes here */ 130 131 sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s", 132 addr[0],addr[1],addr[2],addr[3], 133 addr[4],addr[5],addr[6],addr[7]); 134 135 /* Add address of the interface */ 136 memset(&hints, 0, sizeof(hints)); 137 hints.ai_family = AF_INET6; 138 hints.ai_flags = AI_NUMERICHOST; 139 err = getaddrinfo(addr6, NULL, &hints, &res0); 140 if (err) { 141 goto gotError; 142 } 143 ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in6)); 144 if (ifi->ifi_addr == NULL) { 145 goto gotError; 146 } 147 memcpy(ifi->ifi_addr, res0->ai_addr, sizeof(struct sockaddr_in6)); 148 149 /* Add netmask of the interface */ 150 char ipv6addr[INET6_ADDRSTRLEN]; 151 plen_to_mask(plen, ipv6addr); 152 ifi->ifi_netmask = calloc(1, sizeof(struct sockaddr_in6)); 153 if (ifi->ifi_addr == NULL) { 154 goto gotError; 155 } 156 sin6=calloc(1, sizeof(struct sockaddr_in6)); 157 addrptr=calloc(1, sizeof(struct in6_addr)); 158 inet_pton(family, ipv6addr, addrptr); 159 sin6->sin6_family=family; 160 sin6->sin6_addr=*addrptr; 161 sin6->sin6_scope_id=scope; 162 memcpy(ifi->ifi_netmask, sin6, sizeof(struct sockaddr_in6)); 163 free(sin6); 164 165 166 /* Add interface name */ 167 strncpy(ifi->ifi_name, ifname, IFI_NAME); 168 169 /* Add interface index */ 170 ifi->ifi_index = index; 171 172 /* Add interface flags*/ 173 strncpy(ifr.ifr_name, ifname, IFNAMSIZ); 174 if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) { 175 if (errno == EADDRNOTAVAIL) { 176 /* 177 * If the main interface is configured with no IP address but 178 * an alias interface exists with an IP address, you get 179 * EADDRNOTAVAIL for the main interface 180 */ 181 free(ifi->ifi_addr); 182 free(ifi); 183 ifipnext = ifiptr; 184 *ifipnext = ifipold; 185 continue; 186 } else { 187 goto gotError; 188 } 189 } 190 ifi->ifi_flags = ifr.ifr_flags; 191 freeaddrinfo(res0); 192 res0=NULL; 193 } 194 } 195 goto done; 196 197 gotError: 198 if (ifihead != NULL) { 199 free_ifi_info(ifihead); 200 ifihead = NULL; 201 } 202 if (res0 != NULL) { 203 freeaddrinfo(res0); 204 res0=NULL; 205 } 206 done: 207 if (sockfd != -1) { 208 // __ANDROID__ : replaced assert(close(..)) 209 int sockfd_closed = close(sockfd); 210 assert(sockfd_closed == 0); 211 } 212 // __ANDROID__ : if fp was opened, it needs to be closed 213 if (fp != NULL) { 214 int fd_closed = fclose(fp); 215 assert(fd_closed == 0); 216 } 217 return(ifihead); /* pointer to first structure in linked list */ 218 } 219 #endif // defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX 220 221 struct ifi_info *get_ifi_info(int family, int doaliases) 222 { 223 int junk; 224 struct ifi_info *ifi, *ifihead, **ifipnext, *ifipold, **ifiptr; 225 int sockfd, sockf6, len, lastlen, flags, myflags; 226 #ifdef NOT_HAVE_IF_NAMETOINDEX 227 int index = 200; 228 #endif 229 char *ptr, *buf, lastname[IFNAMSIZ], *cptr; 230 struct ifconf ifc; 231 struct ifreq *ifr, ifrcopy; 232 struct sockaddr_in *sinptr; 233 234 #if defined(AF_INET6) && HAVE_IPV6 235 struct sockaddr_in6 *sinptr6; 236 #endif 237 238 #if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX 239 if (family == AF_INET6) return get_ifi_info_linuxv6(family, doaliases); 240 #endif 241 242 sockfd = -1; 243 sockf6 = -1; 244 buf = NULL; 245 ifihead = NULL; 246 247 sockfd = socket(AF_INET, SOCK_DGRAM, 0); 248 if (sockfd < 0) { 249 goto gotError; 250 } 251 252 lastlen = 0; 253 len = 100 * sizeof(struct ifreq); /* initial buffer size guess */ 254 for ( ; ; ) { 255 buf = (char*)malloc(len); 256 if (buf == NULL) { 257 goto gotError; 258 } 259 ifc.ifc_len = len; 260 ifc.ifc_buf = buf; 261 if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) { 262 if (errno != EINVAL || lastlen != 0) { 263 goto gotError; 264 } 265 } else { 266 if (ifc.ifc_len == lastlen) 267 break; /* success, len has not changed */ 268 lastlen = ifc.ifc_len; 269 } 270 len += 10 * sizeof(struct ifreq); /* increment */ 271 free(buf); 272 } 273 ifihead = NULL; 274 ifipnext = &ifihead; 275 lastname[0] = 0; 276 /* end get_ifi_info1 */ 277 278 /* include get_ifi_info2 */ 279 for (ptr = buf; ptr < buf + ifc.ifc_len; ) { 280 ifr = (struct ifreq *) ptr; 281 282 /* Advance to next one in buffer */ 283 if (sizeof(struct ifreq) > sizeof(ifr->ifr_name) + GET_SA_LEN(ifr->ifr_addr)) 284 ptr += sizeof(struct ifreq); 285 else 286 ptr += sizeof(ifr->ifr_name) + GET_SA_LEN(ifr->ifr_addr); 287 288 // fprintf(stderr, "intf %p name=%s AF=%d\n", index, ifr->ifr_name, ifr->ifr_addr.sa_family); 289 290 if (ifr->ifr_addr.sa_family != family) 291 continue; /* ignore if not desired address family */ 292 293 myflags = 0; 294 if ( (cptr = strchr(ifr->ifr_name, ':')) != NULL) 295 *cptr = 0; /* replace colon will null */ 296 if (strncmp(lastname, ifr->ifr_name, IFNAMSIZ) == 0) { 297 if (doaliases == 0) 298 continue; /* already processed this interface */ 299 myflags = IFI_ALIAS; 300 } 301 memcpy(lastname, ifr->ifr_name, IFNAMSIZ); 302 303 ifrcopy = *ifr; 304 if (ioctl(sockfd, SIOCGIFFLAGS, &ifrcopy) < 0) { 305 goto gotError; 306 } 307 308 flags = ifrcopy.ifr_flags; 309 if ((flags & IFF_UP) == 0) 310 continue; /* ignore if interface not up */ 311 312 ifi = (struct ifi_info*)calloc(1, sizeof(struct ifi_info)); 313 if (ifi == NULL) { 314 goto gotError; 315 } 316 ifipold = *ifipnext; /* need this later */ 317 ifiptr = ifipnext; 318 *ifipnext = ifi; /* prev points to this new one */ 319 ifipnext = &ifi->ifi_next; /* pointer to next one goes here */ 320 321 ifi->ifi_flags = flags; /* IFF_xxx values */ 322 ifi->ifi_myflags = myflags; /* IFI_xxx values */ 323 #ifndef NOT_HAVE_IF_NAMETOINDEX 324 ifi->ifi_index = if_nametoindex(ifr->ifr_name); 325 #else 326 ifrcopy = *ifr; 327 #ifdef SIOCGIFINDEX 328 if ( 0 >= ioctl(sockfd, SIOCGIFINDEX, &ifrcopy)) 329 ifi->ifi_index = ifrcopy.ifr_index; 330 else 331 #endif 332 ifi->ifi_index = index++; /* SIOCGIFINDEX is broken on Solaris 2.5ish, so fake it */ 333 #endif 334 memcpy(ifi->ifi_name, ifr->ifr_name, IFI_NAME); 335 ifi->ifi_name[IFI_NAME-1] = '\0'; 336 /* end get_ifi_info2 */ 337 /* include get_ifi_info3 */ 338 switch (ifr->ifr_addr.sa_family) { 339 case AF_INET: 340 sinptr = (struct sockaddr_in *) &ifr->ifr_addr; 341 if (ifi->ifi_addr == NULL) { 342 ifi->ifi_addr = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in)); 343 if (ifi->ifi_addr == NULL) { 344 goto gotError; 345 } 346 memcpy(ifi->ifi_addr, sinptr, sizeof(struct sockaddr_in)); 347 348 #ifdef SIOCGIFNETMASK 349 if (ioctl(sockfd, SIOCGIFNETMASK, &ifrcopy) < 0) { 350 if (errno == EADDRNOTAVAIL) { 351 /* 352 * If the main interface is configured with no IP address but 353 * an alias interface exists with an IP address, you get 354 * EADDRNOTAVAIL for the main interface 355 */ 356 free(ifi->ifi_addr); 357 free(ifi); 358 ifipnext = ifiptr; 359 *ifipnext = ifipold; 360 continue; 361 } else { 362 goto gotError; 363 } 364 } 365 366 ifi->ifi_netmask = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in)); 367 if (ifi->ifi_netmask == NULL) goto gotError; 368 sinptr = (struct sockaddr_in *) &ifrcopy.ifr_addr; 369 /* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */ 370 #ifndef NOT_HAVE_SA_LEN 371 sinptr->sin_len = sizeof(struct sockaddr_in); 372 #endif 373 sinptr->sin_family = AF_INET; 374 memcpy(ifi->ifi_netmask, sinptr, sizeof(struct sockaddr_in)); 375 #endif 376 377 #ifdef SIOCGIFBRDADDR 378 if (flags & IFF_BROADCAST) { 379 if (ioctl(sockfd, SIOCGIFBRDADDR, &ifrcopy) < 0) { 380 goto gotError; 381 } 382 sinptr = (struct sockaddr_in *) &ifrcopy.ifr_broadaddr; 383 /* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */ 384 #ifndef NOT_HAVE_SA_LEN 385 sinptr->sin_len = sizeof( struct sockaddr_in ); 386 #endif 387 sinptr->sin_family = AF_INET; 388 ifi->ifi_brdaddr = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in)); 389 if (ifi->ifi_brdaddr == NULL) { 390 goto gotError; 391 } 392 memcpy(ifi->ifi_brdaddr, sinptr, sizeof(struct sockaddr_in)); 393 } 394 #endif 395 396 #ifdef SIOCGIFDSTADDR 397 if (flags & IFF_POINTOPOINT) { 398 if (ioctl(sockfd, SIOCGIFDSTADDR, &ifrcopy) < 0) { 399 goto gotError; 400 } 401 sinptr = (struct sockaddr_in *) &ifrcopy.ifr_dstaddr; 402 /* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */ 403 #ifndef NOT_HAVE_SA_LEN 404 sinptr->sin_len = sizeof( struct sockaddr_in ); 405 #endif 406 sinptr->sin_family = AF_INET; 407 ifi->ifi_dstaddr = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in)); 408 if (ifi->ifi_dstaddr == NULL) { 409 goto gotError; 410 } 411 memcpy(ifi->ifi_dstaddr, sinptr, sizeof(struct sockaddr_in)); 412 } 413 #endif 414 } 415 break; 416 417 #if defined(AF_INET6) && HAVE_IPV6 418 case AF_INET6: 419 sinptr6 = (struct sockaddr_in6 *) &ifr->ifr_addr; 420 if (ifi->ifi_addr == NULL) { 421 ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in6)); 422 if (ifi->ifi_addr == NULL) { 423 goto gotError; 424 } 425 426 /* Some platforms (*BSD) inject the prefix in IPv6LL addresses */ 427 /* We need to strip that out */ 428 if (IN6_IS_ADDR_LINKLOCAL(&sinptr6->sin6_addr)) 429 sinptr6->sin6_addr.s6_addr[2] = sinptr6->sin6_addr.s6_addr[3] = 0; 430 memcpy(ifi->ifi_addr, sinptr6, sizeof(struct sockaddr_in6)); 431 432 #ifdef SIOCGIFNETMASK_IN6 433 { 434 struct in6_ifreq ifr6; 435 if (sockf6 == -1) 436 sockf6 = socket(AF_INET6, SOCK_DGRAM, 0); 437 memset(&ifr6, 0, sizeof(ifr6)); 438 memcpy(&ifr6.ifr_name, &ifr->ifr_name, sizeof(ifr6.ifr_name )); 439 memcpy(&ifr6.ifr_ifru.ifru_addr, &ifr->ifr_addr, sizeof(ifr6.ifr_ifru.ifru_addr)); 440 if (ioctl(sockf6, SIOCGIFNETMASK_IN6, &ifr6) < 0) { 441 if (errno == EADDRNOTAVAIL) { 442 /* 443 * If the main interface is configured with no IP address but 444 * an alias interface exists with an IP address, you get 445 * EADDRNOTAVAIL for the main interface 446 */ 447 free(ifi->ifi_addr); 448 free(ifi); 449 ifipnext = ifiptr; 450 *ifipnext = ifipold; 451 continue; 452 } else { 453 goto gotError; 454 } 455 } 456 ifi->ifi_netmask = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in6)); 457 if (ifi->ifi_netmask == NULL) goto gotError; 458 sinptr6 = (struct sockaddr_in6 *) &ifr6.ifr_ifru.ifru_addr; 459 memcpy(ifi->ifi_netmask, sinptr6, sizeof(struct sockaddr_in6)); 460 } 461 #endif 462 } 463 break; 464 #endif 465 466 default: 467 break; 468 } 469 } 470 goto done; 471 472 gotError: 473 if (ifihead != NULL) { 474 free_ifi_info(ifihead); 475 ifihead = NULL; 476 } 477 478 done: 479 if (buf != NULL) { 480 free(buf); 481 } 482 if (sockfd != -1) { 483 junk = close(sockfd); 484 assert(junk == 0); 485 } 486 if (sockf6 != -1) { 487 junk = close(sockf6); 488 assert(junk == 0); 489 } 490 return(ifihead); /* pointer to first structure in linked list */ 491 } 492 /* end get_ifi_info3 */ 493 494 /* include free_ifi_info */ 495 void 496 free_ifi_info(struct ifi_info *ifihead) 497 { 498 struct ifi_info *ifi, *ifinext; 499 500 for (ifi = ifihead; ifi != NULL; ifi = ifinext) { 501 if (ifi->ifi_addr != NULL) 502 free(ifi->ifi_addr); 503 if (ifi->ifi_netmask != NULL) 504 free(ifi->ifi_netmask); 505 if (ifi->ifi_brdaddr != NULL) 506 free(ifi->ifi_brdaddr); 507 if (ifi->ifi_dstaddr != NULL) 508 free(ifi->ifi_dstaddr); 509 ifinext = ifi->ifi_next; /* can't fetch ifi_next after free() */ 510 free(ifi); /* the ifi_info{} itself */ 511 } 512 } 513 /* end free_ifi_info */ 514 515 ssize_t 516 recvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp, 517 struct sockaddr *sa, socklen_t *salenptr, struct my_in_pktinfo *pktp, u_char *ttl) 518 { 519 struct msghdr msg; 520 struct iovec iov[1]; 521 ssize_t n; 522 523 #ifdef CMSG_FIRSTHDR 524 struct cmsghdr *cmptr; 525 union { 526 struct cmsghdr cm; 527 char control[1024]; 528 } control_un; 529 530 *ttl = 255; // If kernel fails to provide TTL data then assume the TTL was 255 as it should be 531 532 msg.msg_control = control_un.control; 533 msg.msg_controllen = sizeof(control_un.control); 534 msg.msg_flags = 0; 535 #else 536 memset(&msg, 0, sizeof(msg)); /* make certain msg_accrightslen = 0 */ 537 #endif /* CMSG_FIRSTHDR */ 538 539 msg.msg_name = (char *) sa; 540 msg.msg_namelen = *salenptr; 541 iov[0].iov_base = (char *)ptr; 542 iov[0].iov_len = nbytes; 543 msg.msg_iov = iov; 544 msg.msg_iovlen = 1; 545 546 if ( (n = recvmsg(fd, &msg, *flagsp)) < 0) 547 return(n); 548 549 *salenptr = msg.msg_namelen; /* pass back results */ 550 if (pktp) { 551 /* 0.0.0.0, i/f = -1 */ 552 /* We set the interface to -1 so that the caller can 553 tell whether we returned a meaningful value or 554 just some default. Previously this code just 555 set the value to 0, but I'm concerned that 0 556 might be a valid interface value. 557 */ 558 memset(pktp, 0, sizeof(struct my_in_pktinfo)); 559 pktp->ipi_ifindex = -1; 560 } 561 /* end recvfrom_flags1 */ 562 563 /* include recvfrom_flags2 */ 564 #ifndef CMSG_FIRSTHDR 565 #warning CMSG_FIRSTHDR not defined. Will not be able to determine destination address, received interface, etc. 566 *flagsp = 0; /* pass back results */ 567 return(n); 568 #else 569 570 *flagsp = msg.msg_flags; /* pass back results */ 571 if (msg.msg_controllen < (socklen_t)sizeof(struct cmsghdr) || 572 (msg.msg_flags & MSG_CTRUNC) || pktp == NULL) 573 return(n); 574 575 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr != NULL; 576 cmptr = CMSG_NXTHDR(&msg, cmptr)) { 577 578 #ifdef IP_PKTINFO 579 #if in_pktinfo_definition_is_missing 580 struct in_pktinfo 581 { 582 int ipi_ifindex; 583 struct in_addr ipi_spec_dst; 584 struct in_addr ipi_addr; 585 }; 586 #endif 587 if (cmptr->cmsg_level == IPPROTO_IP && 588 cmptr->cmsg_type == IP_PKTINFO) { 589 struct in_pktinfo *tmp; 590 struct sockaddr_in *sin = (struct sockaddr_in*)&pktp->ipi_addr; 591 592 tmp = (struct in_pktinfo *) CMSG_DATA(cmptr); 593 sin->sin_family = AF_INET; 594 sin->sin_addr = tmp->ipi_addr; 595 sin->sin_port = 0; 596 pktp->ipi_ifindex = tmp->ipi_ifindex; 597 continue; 598 } 599 #endif 600 601 #ifdef IP_RECVDSTADDR 602 if (cmptr->cmsg_level == IPPROTO_IP && 603 cmptr->cmsg_type == IP_RECVDSTADDR) { 604 struct sockaddr_in *sin = (struct sockaddr_in*)&pktp->ipi_addr; 605 606 sin->sin_family = AF_INET; 607 sin->sin_addr = *(struct in_addr*)CMSG_DATA(cmptr); 608 sin->sin_port = 0; 609 continue; 610 } 611 #endif 612 613 #ifdef IP_RECVIF 614 if (cmptr->cmsg_level == IPPROTO_IP && 615 cmptr->cmsg_type == IP_RECVIF) { 616 struct sockaddr_dl *sdl = (struct sockaddr_dl *) CMSG_DATA(cmptr); 617 #ifndef HAVE_BROKEN_RECVIF_NAME 618 int nameLen = (sdl->sdl_nlen < IFI_NAME - 1) ? sdl->sdl_nlen : (IFI_NAME - 1); 619 strncpy(pktp->ipi_ifname, sdl->sdl_data, nameLen); 620 #endif 621 pktp->ipi_ifindex = sdl->sdl_index; 622 #ifdef HAVE_BROKEN_RECVIF_NAME 623 if (sdl->sdl_index == 0) { 624 pktp->ipi_ifindex = *(uint_t*)sdl; 625 } 626 #endif 627 assert(pktp->ipi_ifname[IFI_NAME - 1] == 0); 628 // null terminated because of memset above 629 continue; 630 } 631 #endif 632 633 #ifdef IP_RECVTTL 634 if (cmptr->cmsg_level == IPPROTO_IP && 635 cmptr->cmsg_type == IP_RECVTTL) { 636 *ttl = *(u_char*)CMSG_DATA(cmptr); 637 continue; 638 } 639 else if (cmptr->cmsg_level == IPPROTO_IP && 640 cmptr->cmsg_type == IP_TTL) { // some implementations seem to send IP_TTL instead of IP_RECVTTL 641 *ttl = *(int*)CMSG_DATA(cmptr); 642 continue; 643 } 644 #endif 645 646 #if defined(IPV6_PKTINFO) && HAVE_IPV6 647 if (cmptr->cmsg_level == IPPROTO_IPV6 && 648 cmptr->cmsg_type == IPV6_2292_PKTINFO) { 649 struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&pktp->ipi_addr; 650 struct in6_pktinfo *ip6_info = (struct in6_pktinfo*)CMSG_DATA(cmptr); 651 652 sin6->sin6_family = AF_INET6; 653 #ifndef NOT_HAVE_SA_LEN 654 sin6->sin6_len = sizeof(*sin6); 655 #endif 656 sin6->sin6_addr = ip6_info->ipi6_addr; 657 sin6->sin6_flowinfo = 0; 658 sin6->sin6_scope_id = 0; 659 sin6->sin6_port = 0; 660 pktp->ipi_ifindex = ip6_info->ipi6_ifindex; 661 continue; 662 } 663 #endif 664 665 #if defined(IPV6_HOPLIMIT) && HAVE_IPV6 666 if (cmptr->cmsg_level == IPPROTO_IPV6 && 667 cmptr->cmsg_type == IPV6_2292_HOPLIMIT) { 668 *ttl = *(int*)CMSG_DATA(cmptr); 669 continue; 670 } 671 #endif 672 assert(0); // unknown ancillary data 673 } 674 return(n); 675 #endif /* CMSG_FIRSTHDR */ 676 } 677 678 // ********************************************************************************************** 679 680 // daemonize the process. Adapted from "Unix Network Programming" vol 1 by Stevens, section 12.4. 681 // Returns 0 on success, -1 on failure. 682 683 #ifdef NOT_HAVE_DAEMON 684 #include <fcntl.h> 685 #include <sys/stat.h> 686 #include <sys/signal.h> 687 688 int daemon(int nochdir, int noclose) 689 { 690 switch (fork()) 691 { 692 case -1: return (-1); // Fork failed 693 case 0: break; // Child -- continue 694 default: _exit(0); // Parent -- exit 695 } 696 697 if (setsid() == -1) return(-1); 698 699 signal(SIGHUP, SIG_IGN); 700 701 switch (fork()) // Fork again, primarily for reasons of Unix trivia 702 { 703 case -1: return (-1); // Fork failed 704 case 0: break; // Child -- continue 705 default: _exit(0); // Parent -- exit 706 } 707 708 if (!nochdir) (void)chdir("/"); 709 umask(0); 710 711 if (!noclose) 712 { 713 int fd = open("/dev/null", O_RDWR, 0); 714 if (fd != -1) 715 { 716 // Avoid unnecessarily duplicating a file descriptor to itself 717 if (fd != STDIN_FILENO) (void)dup2(fd, STDIN_FILENO); 718 if (fd != STDOUT_FILENO) (void)dup2(fd, STDOUT_FILENO); 719 if (fd != STDERR_FILENO) (void)dup2(fd, STDERR_FILENO); 720 if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO) 721 (void)close (fd); 722 } 723 } 724 return (0); 725 } 726 #endif /* NOT_HAVE_DAEMON */ 727