diff options
Diffstat (limited to 'usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSUNP.c')
-rw-r--r-- | usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSUNP.c | 560 |
1 files changed, 310 insertions, 250 deletions
diff --git a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSUNP.c b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSUNP.c index fbb4267417..026eaae565 100644 --- a/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSUNP.c +++ b/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSUNP.c @@ -1,7 +1,3 @@ -/* - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ /* -*- Mode: C; tab-width: 4 -*- * * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved. @@ -9,9 +5,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,14 +17,13 @@ #include "mDNSUNP.h" -#include "mDNSDebug.h" - #include <errno.h> #include <assert.h> #include <string.h> #include <stdlib.h> #include <sys/uio.h> #include <sys/ioctl.h> +#include <signal.h> #include <unistd.h> #include <stdio.h> @@ -36,24 +31,24 @@ macro, usually defined in <sys/param.h> or someplace like that, to make sure the CMSG_NXTHDR macro is well-formed. On such platforms, the symbol NEED_ALIGN_MACRO should be set to the name of the header to include to get the ALIGN(P) macro. -*/ + */ #ifdef NEED_ALIGN_MACRO #include NEED_ALIGN_MACRO #endif -/* Solaris defined SIOCGIFCONF etc in <sys/sockio.h> but - other platforms don't even have that include file. So, - if we haven't yet got a definition, let's try to find +/* Solaris defined SIOCGIFCONF etc in <sys/sockio.h> but + other platforms don't even have that include file. So, + if we haven't yet got a definition, let's try to find <sys/sockio.h>. -*/ + */ #ifndef SIOCGIFCONF #include <sys/sockio.h> #endif -/* sockaddr_dl is only referenced if we're using IP_RECVIF, +/* sockaddr_dl is only referenced if we're using IP_RECVIF, so only include the header in that case. -*/ + */ #ifdef IP_RECVIF #include <net/if_dl.h> @@ -64,138 +59,161 @@ #include <net/if_var.h> #else #include <alloca.h> -#endif /* !HAVE_SOLARIS */ +#endif /* !HAVE_SOLARIS */ #include <netinet/in_var.h> -// NOTE: netinet/in_var.h implicitly includes netinet6/in6_var.h for us +// Note: netinet/in_var.h implicitly includes netinet6/in6_var.h for us #endif -#if defined(AF_INET6) && HAVE_IPV6 - -#if HAVE_LINUX +#if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX #include <netdb.h> #include <arpa/inet.h> /* Converts a prefix length to IPv6 network mask */ void plen_to_mask(int plen, char *addr) { - int i; - int colons=7; /* Number of colons in IPv6 address */ - int bits_in_block=16; /* Bits per IPv6 block */ - for(i=0;i<=colons;i++) { - int block, ones=0xffff, ones_in_block; - if(plen>bits_in_block) ones_in_block=bits_in_block; - else ones_in_block=plen; - block = ones & (ones << (bits_in_block-ones_in_block)); - i==0 ? sprintf(addr, "%x", block) : sprintf(addr, "%s:%x", addr, block); - plen -= ones_in_block; - } - } + int i; + int colons=7; /* Number of colons in IPv6 address */ + int bits_in_block=16; /* Bits per IPv6 block */ + for(i=0; i<=colons; i++) { + int block, ones=0xffff, ones_in_block; + if (plen>bits_in_block) ones_in_block=bits_in_block; + else ones_in_block=plen; + block = ones & (ones << (bits_in_block-ones_in_block)); + i==0 ? sprintf(addr, "%x", block) : sprintf(addr, "%s:%x", addr, block); + plen -= ones_in_block; + } +} /* Gets IPv6 interface information from the /proc filesystem in linux*/ struct ifi_info *get_ifi_info_linuxv6(int family, int doaliases) - { - struct ifi_info *ifi, *ifihead, **ifipnext; - FILE *fp; - char addr[8][5]; - int flags, myflags, index, plen, scope; - char ifname[8], lastname[IFNAMSIZ]; - char addr6[32+7+1]; /* don't forget the seven ':' */ - struct addrinfo hints, *res0; - struct sockaddr_in6 *sin6; - struct in6_addr *addrptr; - int err; - - res0=NULL; - ifihead = NULL; - ifipnext = &ifihead; - lastname[0] = 0; - - if ((fp = fopen(PROC_IFINET6_PATH, "r")) != NULL) { - while (fscanf(fp, - "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %8s\n", - addr[0],addr[1],addr[2],addr[3], - addr[4],addr[5],addr[6],addr[7], - &index, &plen, &scope, &flags, ifname) != EOF) { - - myflags = 0; - if (strncmp(lastname, ifname, IFNAMSIZ) == 0) { - if (doaliases == 0) - continue; /* already processed this interface */ - myflags = IFI_ALIAS; - } - memcpy(lastname, ifname, IFNAMSIZ); - ifi = (struct ifi_info*)calloc(1, sizeof(struct ifi_info)); - if (ifi == NULL) { - goto gotError; - } - - *ifipnext = ifi; /* prev points to this new one */ - ifipnext = &ifi->ifi_next; /* pointer to next one goes here */ - - sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s", - addr[0],addr[1],addr[2],addr[3], - addr[4],addr[5],addr[6],addr[7]); - - /* Add address of the interface */ - memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET6; - hints.ai_flags = AI_NUMERICHOST; - err = getaddrinfo(addr6, NULL, &hints, &res0); - if (err) { - goto gotError; - } - ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in6)); - if (ifi->ifi_addr == NULL) { - goto gotError; - } - memcpy(ifi->ifi_addr, res0->ai_addr, sizeof(struct sockaddr_in6)); - - /* Add netmask of the interface */ - char ipv6addr[INET6_ADDRSTRLEN]; - plen_to_mask(plen, ipv6addr); - ifi->ifi_netmask = calloc(1, sizeof(struct sockaddr_in6)); - if (ifi->ifi_addr == NULL) { - goto gotError; - } - sin6=calloc(1, sizeof(struct sockaddr_in6)); - addrptr=calloc(1, sizeof(struct in6_addr)); - inet_pton(family, ipv6addr, addrptr); - sin6->sin6_family=family; - sin6->sin6_addr=*addrptr; - sin6->sin6_scope_id=scope; - memcpy(ifi->ifi_netmask, sin6, sizeof(struct sockaddr_in6)); - free(sin6); - - - /* Add interface name */ - memcpy(ifi->ifi_name, ifname, IFI_NAME); - - /* Add interface index */ - ifi->ifi_index = index; - - /* If interface is in /proc then it is up*/ - ifi->ifi_flags = IFF_UP; - - freeaddrinfo(res0); - res0=NULL; - } - } - goto done; - - gotError: - if (ifihead != NULL) { - free_ifi_info(ifihead); - ifihead = NULL; - } - if (res0 != NULL) { - freeaddrinfo(res0); - res0=NULL; - } - done: - return(ifihead); /* pointer to first structure in linked list */ - } +{ + struct ifi_info *ifi, *ifihead, **ifipnext, *ifipold, **ifiptr; + FILE *fp; + char addr[8][5]; + int flags, myflags, index, plen, scope; + char ifname[9], lastname[IFNAMSIZ]; + char addr6[32+7+1]; /* don't forget the seven ':' */ + struct addrinfo hints, *res0; + struct sockaddr_in6 *sin6; + struct in6_addr *addrptr; + int err; + int sockfd = -1; + struct ifreq ifr; + + res0=NULL; + ifihead = NULL; + ifipnext = &ifihead; + lastname[0] = 0; -#endif /* LINUX */ -#endif /* defined(AF_INET6) && HAVE_IPV6 */ + if ((fp = fopen(PROC_IFINET6_PATH, "r")) != NULL) { + sockfd = socket(AF_INET6, SOCK_DGRAM, 0); + if (sockfd < 0) { + goto gotError; + } + while (fscanf(fp, + "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %8s\n", + addr[0],addr[1],addr[2],addr[3], + addr[4],addr[5],addr[6],addr[7], + &index, &plen, &scope, &flags, ifname) != EOF) { + + myflags = 0; + if (strncmp(lastname, ifname, IFNAMSIZ) == 0) { + if (doaliases == 0) + continue; /* already processed this interface */ + myflags = IFI_ALIAS; + } + memcpy(lastname, ifname, IFNAMSIZ); + ifi = (struct ifi_info*)calloc(1, sizeof(struct ifi_info)); + if (ifi == NULL) { + goto gotError; + } + + ifipold = *ifipnext; /* need this later */ + ifiptr = ifipnext; + *ifipnext = ifi; /* prev points to this new one */ + ifipnext = &ifi->ifi_next; /* pointer to next one goes here */ + + sprintf(addr6, "%s:%s:%s:%s:%s:%s:%s:%s", + addr[0],addr[1],addr[2],addr[3], + addr[4],addr[5],addr[6],addr[7]); + + /* Add address of the interface */ + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + hints.ai_flags = AI_NUMERICHOST; + err = getaddrinfo(addr6, NULL, &hints, &res0); + if (err) { + goto gotError; + } + ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in6)); + if (ifi->ifi_addr == NULL) { + goto gotError; + } + memcpy(ifi->ifi_addr, res0->ai_addr, sizeof(struct sockaddr_in6)); + + /* Add netmask of the interface */ + char ipv6addr[INET6_ADDRSTRLEN]; + plen_to_mask(plen, ipv6addr); + ifi->ifi_netmask = calloc(1, sizeof(struct sockaddr_in6)); + if (ifi->ifi_addr == NULL) { + goto gotError; + } + sin6=calloc(1, sizeof(struct sockaddr_in6)); + addrptr=calloc(1, sizeof(struct in6_addr)); + inet_pton(family, ipv6addr, addrptr); + sin6->sin6_family=family; + sin6->sin6_addr=*addrptr; + sin6->sin6_scope_id=scope; + memcpy(ifi->ifi_netmask, sin6, sizeof(struct sockaddr_in6)); + free(sin6); + + + /* Add interface name */ + memcpy(ifi->ifi_name, ifname, IFI_NAME); + + /* Add interface index */ + ifi->ifi_index = index; + + /* Add interface flags*/ + memcpy(ifr.ifr_name, ifname, IFNAMSIZ); + if (ioctl(sockfd, SIOCGIFFLAGS, &ifr) < 0) { + if (errno == EADDRNOTAVAIL) { + /* + * If the main interface is configured with no IP address but + * an alias interface exists with an IP address, you get + * EADDRNOTAVAIL for the main interface + */ + free(ifi->ifi_addr); + free(ifi); + ifipnext = ifiptr; + *ifipnext = ifipold; + continue; + } else { + goto gotError; + } + } + ifi->ifi_flags = ifr.ifr_flags; + freeaddrinfo(res0); + res0=NULL; + } + } + goto done; + +gotError: + if (ifihead != NULL) { + free_ifi_info(ifihead); + ifihead = NULL; + } + if (res0 != NULL) { + freeaddrinfo(res0); + res0=NULL; + } +done: + if (sockfd != -1) { + assert(close(sockfd) == 0); + } + return(ifihead); /* pointer to first structure in linked list */ +} +#endif // defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX #if HAVE_SOLARIS @@ -230,7 +248,7 @@ select_src_ifi_info_solaris(int sockfd, int numifs, char *chptr; char cmpifname[LIFNAMSIZ]; int i; - uint64_t best_lifrflags; + uint64_t best_lifrflags = 0; uint64_t ifflags; *best_lifr = NULL; @@ -509,23 +527,23 @@ gotError: struct ifi_info *get_ifi_info(int family, int doaliases) { - int junk; - struct ifi_info *ifi, *ifihead, **ifipnext; - int sockfd, sockf6, len, lastlen, flags, myflags; + int junk; + struct ifi_info *ifi, *ifihead, **ifipnext, *ifipold, **ifiptr; + int sockfd, sockf6, len, lastlen, flags, myflags; #ifdef NOT_HAVE_IF_NAMETOINDEX - int index = 200; + int index = 200; #endif char *ptr, *buf, lastname[IFNAMSIZ], *cptr; - struct ifconf ifc; + struct ifconf ifc; struct ifreq *ifr, ifrcopy; struct sockaddr_in *sinptr; - + #if defined(AF_INET6) && HAVE_IPV6 struct sockaddr_in6 *sinptr6; #endif #if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX - if(family == AF_INET6) return get_ifi_info_linuxv6(family, doaliases); + if (family == AF_INET6) return get_ifi_info_linuxv6(family, doaliases); #elif HAVE_SOLARIS return get_ifi_info_solaris(family); #endif @@ -534,7 +552,7 @@ struct ifi_info *get_ifi_info(int family, int doaliases) sockf6 = -1; buf = NULL; ifihead = NULL; - + sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { goto gotError; @@ -577,7 +595,7 @@ struct ifi_info *get_ifi_info(int family, int doaliases) ptr += sizeof(ifr->ifr_name) + GET_SA_LEN(ifr->ifr_addr); // fprintf(stderr, "intf %p name=%s AF=%d\n", index, ifr->ifr_name, ifr->ifr_addr.sa_family); - + if (ifr->ifr_addr.sa_family != family) continue; /* ignore if not desired address family */ @@ -595,7 +613,7 @@ struct ifi_info *get_ifi_info(int family, int doaliases) if (ioctl(sockfd, SIOCGIFFLAGS, &ifrcopy) < 0) { goto gotError; } - + flags = ifrcopy.ifr_flags; if ((flags & IFF_UP) == 0) continue; /* ignore if interface not up */ @@ -604,8 +622,10 @@ struct ifi_info *get_ifi_info(int family, int doaliases) if (ifi == NULL) { goto gotError; } - *ifipnext = ifi; /* prev points to this new one */ - ifipnext = &ifi->ifi_next; /* pointer to next one goes here */ + ifipold = *ifipnext; /* need this later */ + ifiptr = ifipnext; + *ifipnext = ifi; /* prev points to this new one */ + ifipnext = &ifi->ifi_next; /* pointer to next one goes here */ ifi->ifi_flags = flags; /* IFF_xxx values */ ifi->ifi_myflags = myflags; /* IFI_xxx values */ @@ -618,7 +638,7 @@ struct ifi_info *get_ifi_info(int family, int doaliases) ifi->ifi_index = ifrcopy.ifr_index; else #endif - ifi->ifi_index = index++; /* SIOCGIFINDEX is broken on Solaris 2.5ish, so fake it */ + ifi->ifi_index = index++; /* SIOCGIFINDEX is broken on Solaris 2.5ish, so fake it */ #endif memcpy(ifi->ifi_name, ifr->ifr_name, IFI_NAME); ifi->ifi_name[IFI_NAME-1] = '\0'; @@ -635,16 +655,32 @@ struct ifi_info *get_ifi_info(int family, int doaliases) memcpy(ifi->ifi_addr, sinptr, sizeof(struct sockaddr_in)); #ifdef SIOCGIFNETMASK - if (ioctl(sockfd, SIOCGIFNETMASK, &ifrcopy) < 0) goto gotError; - ifi->ifi_netmask = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in)); - if (ifi->ifi_netmask == NULL) goto gotError; - sinptr = (struct sockaddr_in *) &ifrcopy.ifr_addr; - /* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */ + if (ioctl(sockfd, SIOCGIFNETMASK, &ifrcopy) < 0) { + if (errno == EADDRNOTAVAIL) { + /* + * If the main interface is configured with no IP address but + * an alias interface exists with an IP address, you get + * EADDRNOTAVAIL for the main interface + */ + free(ifi->ifi_addr); + free(ifi); + ifipnext = ifiptr; + *ifipnext = ifipold; + continue; + } else { + goto gotError; + } + } + + ifi->ifi_netmask = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in)); + if (ifi->ifi_netmask == NULL) goto gotError; + sinptr = (struct sockaddr_in *) &ifrcopy.ifr_addr; + /* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */ #ifndef NOT_HAVE_SA_LEN - sinptr->sin_len = sizeof(struct sockaddr_in); + sinptr->sin_len = sizeof(struct sockaddr_in); #endif - sinptr->sin_family = AF_INET; - memcpy(ifi->ifi_netmask, sinptr, sizeof(struct sockaddr_in)); + sinptr->sin_family = AF_INET; + memcpy(ifi->ifi_netmask, sinptr, sizeof(struct sockaddr_in)); #endif #ifdef SIOCGIFBRDADDR @@ -653,11 +689,11 @@ struct ifi_info *get_ifi_info(int family, int doaliases) goto gotError; } sinptr = (struct sockaddr_in *) &ifrcopy.ifr_broadaddr; - /* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */ + /* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */ #ifndef NOT_HAVE_SA_LEN - sinptr->sin_len = sizeof( struct sockaddr_in ); + sinptr->sin_len = sizeof( struct sockaddr_in ); #endif - sinptr->sin_family = AF_INET; + sinptr->sin_family = AF_INET; ifi->ifi_brdaddr = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in)); if (ifi->ifi_brdaddr == NULL) { goto gotError; @@ -674,9 +710,9 @@ struct ifi_info *get_ifi_info(int family, int doaliases) sinptr = (struct sockaddr_in *) &ifrcopy.ifr_dstaddr; /* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */ #ifndef NOT_HAVE_SA_LEN - sinptr->sin_len = sizeof( struct sockaddr_in ); + sinptr->sin_len = sizeof( struct sockaddr_in ); #endif - sinptr->sin_family = AF_INET; + sinptr->sin_family = AF_INET; ifi->ifi_dstaddr = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in)); if (ifi->ifi_dstaddr == NULL) { goto gotError; @@ -695,27 +731,42 @@ struct ifi_info *get_ifi_info(int family, int doaliases) if (ifi->ifi_addr == NULL) { goto gotError; } - + /* Some platforms (*BSD) inject the prefix in IPv6LL addresses */ /* We need to strip that out */ if (IN6_IS_ADDR_LINKLOCAL(&sinptr6->sin6_addr)) - sinptr6->sin6_addr.s6_addr[2] = sinptr6->sin6_addr.s6_addr[3] = 0; + sinptr6->sin6_addr.s6_addr[2] = sinptr6->sin6_addr.s6_addr[3] = 0; memcpy(ifi->ifi_addr, sinptr6, sizeof(struct sockaddr_in6)); #ifdef SIOCGIFNETMASK_IN6 - { - struct in6_ifreq ifr6; - if (sockf6 == -1) - sockf6 = socket(AF_INET6, SOCK_DGRAM, 0); - bzero(&ifr6, sizeof(ifr6)); - memcpy(&ifr6.ifr_name, &ifr->ifr_name, sizeof(ifr6.ifr_name )); - memcpy(&ifr6.ifr_ifru.ifru_addr, &ifr->ifr_addr, sizeof(ifr6.ifr_ifru.ifru_addr)); - if (ioctl(sockf6, SIOCGIFNETMASK_IN6, &ifr6) < 0) goto gotError; - ifi->ifi_netmask = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in6)); - if (ifi->ifi_netmask == NULL) goto gotError; - sinptr6 = (struct sockaddr_in6 *) &ifr6.ifr_ifru.ifru_addr; - memcpy(ifi->ifi_netmask, sinptr6, sizeof(struct sockaddr_in6)); - } + { + struct in6_ifreq ifr6; + if (sockf6 == -1) + sockf6 = socket(AF_INET6, SOCK_DGRAM, 0); + memset(&ifr6, 0, sizeof(ifr6)); + memcpy(&ifr6.ifr_name, &ifr->ifr_name, sizeof(ifr6.ifr_name )); + memcpy(&ifr6.ifr_ifru.ifru_addr, &ifr->ifr_addr, sizeof(ifr6.ifr_ifru.ifru_addr)); + if (ioctl(sockf6, SIOCGIFNETMASK_IN6, &ifr6) < 0) { + if (errno == EADDRNOTAVAIL) { + /* + * If the main interface is configured with no IP address but + * an alias interface exists with an IP address, you get + * EADDRNOTAVAIL for the main interface + */ + free(ifi->ifi_addr); + free(ifi); + ifipnext = ifiptr; + *ifipnext = ifipold; + continue; + } else { + goto gotError; + } + } + ifi->ifi_netmask = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in6)); + if (ifi->ifi_netmask == NULL) goto gotError; + sinptr6 = (struct sockaddr_in6 *) &ifr6.ifr_ifru.ifru_addr; + memcpy(ifi->ifi_netmask, sinptr6, sizeof(struct sockaddr_in6)); + } #endif } break; @@ -726,7 +777,7 @@ struct ifi_info *get_ifi_info(int family, int doaliases) } } goto done; - + gotError: if (ifihead != NULL) { free_ifi_info(ifihead); @@ -758,35 +809,35 @@ free_ifi_info(struct ifi_info *ifihead) for (ifi = ifihead; ifi != NULL; ifi = ifinext) { if (ifi->ifi_addr != NULL) free(ifi->ifi_addr); + if (ifi->ifi_netmask != NULL) + free(ifi->ifi_netmask); if (ifi->ifi_brdaddr != NULL) free(ifi->ifi_brdaddr); if (ifi->ifi_dstaddr != NULL) free(ifi->ifi_dstaddr); - if (ifi->ifi_netmask != NULL) - free(ifi->ifi_netmask); ifinext = ifi->ifi_next; /* can't fetch ifi_next after free() */ free(ifi); /* the ifi_info{} itself */ } } /* end free_ifi_info */ -ssize_t +ssize_t recvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp, struct sockaddr *sa, socklen_t *salenptr, struct my_in_pktinfo *pktp, u_char *ttl) { - struct msghdr msg; - struct iovec iov[1]; - ssize_t n; + struct msghdr msg; + struct iovec iov[1]; + ssize_t n; #ifdef CMSG_FIRSTHDR struct cmsghdr *cmptr; union { - struct cmsghdr cm; - char control[1024]; - pad64_t align8; /* ensure structure is 8-byte aligned on sparc */ + struct cmsghdr cm; + char control[1024]; + pad64_t align8; /* ensure structure is 8-byte aligned on sparc */ } control_un; - *ttl = 255; // If kernel fails to provide TTL data then assume the TTL was 255 as it should be + *ttl = 255; // If kernel fails to provide TTL data then assume the TTL was 255 as it should be msg.msg_control = (void *) control_un.control; msg.msg_controllen = sizeof(control_un.control); @@ -808,12 +859,12 @@ recvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp, *salenptr = msg.msg_namelen; /* pass back results */ if (pktp) { /* 0.0.0.0, i/f = -1 */ - /* We set the interface to -1 so that the caller can - tell whether we returned a meaningful value or - just some default. Previously this code just - set the value to 0, but I'm concerned that 0 + /* We set the interface to -1 so that the caller can + tell whether we returned a meaningful value or + just some default. Previously this code just + set the value to 0, but I'm concerned that 0 might be a valid interface value. - */ + */ memset(pktp, 0, sizeof(struct my_in_pktinfo)); pktp->ipi_ifindex = -1; } @@ -821,7 +872,7 @@ recvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp, /* include recvfrom_flags2 */ #ifndef CMSG_FIRSTHDR - #warning CMSG_FIRSTHDR not defined. Will not be able to determine destination address, received interface, etc. + #warning CMSG_FIRSTHDR not defined. Will not be able to determine destination address, received interface, etc. *flagsp = 0; /* pass back results */ return(n); #else @@ -836,18 +887,18 @@ recvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp, #ifdef IP_PKTINFO #if in_pktinfo_definition_is_missing -struct in_pktinfo -{ - int ipi_ifindex; - struct in_addr ipi_spec_dst; - struct in_addr ipi_addr; -}; + struct in_pktinfo + { + int ipi_ifindex; + struct in_addr ipi_spec_dst; + struct in_addr ipi_addr; + }; #endif - if (cmptr->cmsg_level == IPPROTO_IP && + if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO) { struct in_pktinfo *tmp; struct sockaddr_in *sin = (struct sockaddr_in*)&pktp->ipi_addr; - + tmp = (struct in_pktinfo *) CMSG_DATA(cmptr); sin->sin_family = AF_INET; sin->sin_addr = tmp->ipi_addr; @@ -861,7 +912,7 @@ struct in_pktinfo if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR) { struct sockaddr_in *sin = (struct sockaddr_in*)&pktp->ipi_addr; - + sin->sin_family = AF_INET; sin->sin_addr = *(struct in_addr*)CMSG_DATA(cmptr); sin->sin_port = 0; @@ -877,7 +928,16 @@ struct in_pktinfo int nameLen = (sdl->sdl_nlen < IFI_NAME - 1) ? sdl->sdl_nlen : (IFI_NAME - 1); strncpy(pktp->ipi_ifname, sdl->sdl_data, nameLen); #endif - (void) memcpy(&pktp->ipi_ifindex, CMSG_DATA(cmptr), sizeof(uint_t)); + /* + * the is memcpy used for sparc? no idea;) + * pktp->ipi_ifindex = sdl->sdl_index; + */ + (void) memcpy(&pktp->ipi_ifindex, CMSG_DATA(cmptr), sizeof(uint_t)); +#ifdef HAVE_BROKEN_RECVIF_NAME + if (sdl->sdl_index == 0) { + pktp->ipi_ifindex = *(uint_t*)sdl; + } +#endif assert(pktp->ipi_ifname[IFI_NAME - 1] == 0); // null terminated because of memset above continue; @@ -887,22 +947,22 @@ struct in_pktinfo #ifdef IP_RECVTTL if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVTTL) { - *ttl = *(u_char*)CMSG_DATA(cmptr); + *ttl = *(u_char*)CMSG_DATA(cmptr); continue; } else if (cmptr->cmsg_level == IPPROTO_IP && - cmptr->cmsg_type == IP_TTL) { // some implementations seem to send IP_TTL instead of IP_RECVTTL - *ttl = *(int*)CMSG_DATA(cmptr); + cmptr->cmsg_type == IP_TTL) { // some implementations seem to send IP_TTL instead of IP_RECVTTL + *ttl = *(int*)CMSG_DATA(cmptr); continue; } #endif #if defined(IPV6_PKTINFO) && HAVE_IPV6 - if (cmptr->cmsg_level == IPPROTO_IPV6 && - cmptr->cmsg_type == IPV6_PKTINFO) { + if (cmptr->cmsg_level == IPPROTO_IPV6 && + cmptr->cmsg_type == IPV6_PKTINFO) { struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&pktp->ipi_addr; - struct in6_pktinfo *ip6_info = (struct in6_pktinfo*)CMSG_DATA(cmptr); - + struct in6_pktinfo *ip6_info = (struct in6_pktinfo*)CMSG_DATA(cmptr); + sin6->sin6_family = AF_INET6; #ifndef NOT_HAVE_SA_LEN sin6->sin6_len = sizeof(*sin6); @@ -911,15 +971,15 @@ struct in_pktinfo sin6->sin6_flowinfo = 0; sin6->sin6_scope_id = 0; sin6->sin6_port = 0; - pktp->ipi_ifindex = ip6_info->ipi6_ifindex; + pktp->ipi_ifindex = ip6_info->ipi6_ifindex; continue; } #endif #if defined(IPV6_HOPLIMIT) && HAVE_IPV6 - if (cmptr->cmsg_level == IPPROTO_IPV6 && + if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == IPV6_HOPLIMIT) { - *ttl = *(int*)CMSG_DATA(cmptr); + *ttl = *(int*)CMSG_DATA(cmptr); continue; } #endif @@ -937,44 +997,44 @@ struct in_pktinfo #ifdef NOT_HAVE_DAEMON #include <fcntl.h> #include <sys/stat.h> -#include <signal.h> +#include <sys/signal.h> int daemon(int nochdir, int noclose) +{ + switch (fork()) + { + case -1: return (-1); // Fork failed + case 0: break; // Child -- continue + default: _exit(0); // Parent -- exit + } + + if (setsid() == -1) return(-1); + + signal(SIGHUP, SIG_IGN); + + switch (fork()) // Fork again, primarily for reasons of Unix trivia { - switch (fork()) - { - case -1: return (-1); // Fork failed - case 0: break; // Child -- continue - default: _exit(0); // Parent -- exit - } - - if (setsid() == -1) return(-1); - - signal(SIGHUP, SIG_IGN); - - switch (fork()) // Fork again, primarily for reasons of Unix trivia - { - case -1: return (-1); // Fork failed - case 0: break; // Child -- continue - default: _exit(0); // Parent -- exit - } - - if (!nochdir) (void)chdir("/"); - umask(0); - - if (!noclose) - { - int fd = open("/dev/null", O_RDWR, 0); - if (fd != -1) - { - // Avoid unnecessarily duplicating a file descriptor to itself - if (fd != STDIN_FILENO) (void)dup2(fd, STDIN_FILENO); - if (fd != STDOUT_FILENO) (void)dup2(fd, STDOUT_FILENO); - if (fd != STDERR_FILENO) (void)dup2(fd, STDERR_FILENO); - if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO) - (void)close (fd); - } - } - return (0); + case -1: return (-1); // Fork failed + case 0: break; // Child -- continue + default: _exit(0); // Parent -- exit } + + if (!nochdir) (void)chdir("/"); + umask(0); + + if (!noclose) + { + int fd = open("/dev/null", O_RDWR, 0); + if (fd != -1) + { + // Avoid unnecessarily duplicating a file descriptor to itself + if (fd != STDIN_FILENO) (void)dup2(fd, STDIN_FILENO); + if (fd != STDOUT_FILENO) (void)dup2(fd, STDOUT_FILENO); + if (fd != STDERR_FILENO) (void)dup2(fd, STDERR_FILENO); + if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO) + (void)close (fd); + } + } + return (0); +} #endif /* NOT_HAVE_DAEMON */ |