4b22b9337f359bfd063322244f5336cc7c6ffcfars/* -*- Mode: C; tab-width: 4 -*-
4b22b9337f359bfd063322244f5336cc7c6ffcfars * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
4b22b9337f359bfd063322244f5336cc7c6ffcfars * Licensed under the Apache License, Version 2.0 (the "License");
4b22b9337f359bfd063322244f5336cc7c6ffcfars * you may not use this file except in compliance with the License.
4b22b9337f359bfd063322244f5336cc7c6ffcfars * You may obtain a copy of the License at
4b22b9337f359bfd063322244f5336cc7c6ffcfars * Unless required by applicable law or agreed to in writing, software
4b22b9337f359bfd063322244f5336cc7c6ffcfars * distributed under the License is distributed on an "AS IS" BASIS,
4b22b9337f359bfd063322244f5336cc7c6ffcfars * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
4b22b9337f359bfd063322244f5336cc7c6ffcfars * See the License for the specific language governing permissions and
4b22b9337f359bfd063322244f5336cc7c6ffcfars * limitations under the License.
4b22b9337f359bfd063322244f5336cc7c6ffcfars/* Some weird platforms derived from 4.4BSD Lite (e.g. EFI) need the ALIGN(P)
4b22b9337f359bfd063322244f5336cc7c6ffcfars macro, usually defined in <sys/param.h> or someplace like that, to make sure the
4b22b9337f359bfd063322244f5336cc7c6ffcfars CMSG_NXTHDR macro is well-formed. On such platforms, the symbol NEED_ALIGN_MACRO
4b22b9337f359bfd063322244f5336cc7c6ffcfars should be set to the name of the header to include to get the ALIGN(P) macro.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome/* Solaris defined SIOCGIFCONF etc in <sys/sockio.h> but
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome other platforms don't even have that include file. So,
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if we haven't yet got a definition, let's try to find
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome/* sockaddr_dl is only referenced if we're using IP_RECVIF,
4b22b9337f359bfd063322244f5336cc7c6ffcfars so only include the header in that case.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome#endif /* !HAVE_SOLARIS */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome// Note: netinet/in_var.h implicitly includes netinet6/in6_var.h for us
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome#if defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
4b22b9337f359bfd063322244f5336cc7c6ffcfars/* Converts a prefix length to IPv6 network mask */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome int colons=7; /* Number of colons in IPv6 address */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome int bits_in_block=16; /* Bits per IPv6 block */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome for(i=0; i<=colons; i++) {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (plen>bits_in_block) ones_in_block=bits_in_block;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome block = ones & (ones << (bits_in_block-ones_in_block));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome i==0 ? sprintf(addr, "%x", block) : sprintf(addr, "%s:%x", addr, block);
4b22b9337f359bfd063322244f5336cc7c6ffcfars/* Gets IPv6 interface information from the /proc filesystem in linux*/
4b22b9337f359bfd063322244f5336cc7c6ffcfarsstruct ifi_info *get_ifi_info_linuxv6(int family, int doaliases)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome struct ifi_info *ifi, *ifihead, **ifipnext, *ifipold, **ifiptr;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome char addr6[32+7+1]; /* don't forget the seven ':' */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if ((fp = fopen(PROC_IFINET6_PATH, "r")) != NULL) {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome "%4s%4s%4s%4s%4s%4s%4s%4s %02x %02x %02x %02x %8s\n",
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome &index, &plen, &scope, &flags, ifname) != EOF) {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (strncmp(lastname, ifname, IFNAMSIZ) == 0) {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome continue; /* already processed this interface */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ifi = (struct ifi_info*)calloc(1, sizeof(struct ifi_info));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome *ifipnext = ifi; /* prev points to this new one */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ifipnext = &ifi->ifi_next; /* pointer to next one goes here */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome /* Add address of the interface */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ifi->ifi_addr = calloc(1, sizeof(struct sockaddr_in6));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome memcpy(ifi->ifi_addr, res0->ai_addr, sizeof(struct sockaddr_in6));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome /* Add netmask of the interface */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ifi->ifi_netmask = calloc(1, sizeof(struct sockaddr_in6));
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome ((struct sockaddr_in6 *)ifi->ifi_netmask)->sin6_family=family;
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome ((struct sockaddr_in6 *)ifi->ifi_netmask)->sin6_scope_id=scope;
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome inet_pton(family, ipv6addr, &((struct sockaddr_in6 *)ifi->ifi_netmask)->sin6_addr);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome /* Add interface name */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome /* Add interface index */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome /* Add interface flags*/
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * If the main interface is configured with no IP address but
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * an alias interface exists with an IP address, you get
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * EADDRNOTAVAIL for the main interface
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome return(ifihead); /* pointer to first structure in linked list */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome#endif // defined(AF_INET6) && HAVE_IPV6 && HAVE_LINUX
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome * Converts prefix length to network mask. Assumes
4b22b9337f359bfd063322244f5336cc7c6ffcfars * addr points to a zeroed out buffer and prefix <= sizeof(addr)
4b22b9337f359bfd063322244f5336cc7c6ffcfars * Unlike plen_to_mask returns netmask in binary form and not
4b22b9337f359bfd063322244f5336cc7c6ffcfars * in text form.
4b22b9337f359bfd063322244f5336cc7c6ffcfarsstatic void plen_to_netmask(int prefix, unsigned char *addr) {
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome * This function goes through all the IP interfaces associated with a
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome * physical interface and finds the best matched one for use by mDNS.
4b22b9337f359bfd063322244f5336cc7c6ffcfars * Returns NULL when none of the IP interfaces associated with a physical
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome * interface are usable. Otherwise returns the best matched interface
4b22b9337f359bfd063322244f5336cc7c6ffcfars * information and a pointer to the best matched lifreq.
4b22b9337f359bfd063322244f5336cc7c6ffcfars * Check all logical interfaces associated with the physical
4b22b9337f359bfd063322244f5336cc7c6ffcfars * interface and figure out which one works best for us.
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (strlcpy(cmpifname, lifr->lifr_name, sizeof(cmpifname)) >= sizeof(cmpifname))
4b22b9337f359bfd063322244f5336cc7c6ffcfars continue; /* skip interface */
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* Strip logical interface number before checking ifname */
4b22b9337f359bfd063322244f5336cc7c6ffcfars * Check ifname to see if the logical interface is associated
4b22b9337f359bfd063322244f5336cc7c6ffcfars * with the physical interface we are interested in.
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* interface removed */
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* ignore address if not up */
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome * Avoid address if any of the following flags are set:
4b22b9337f359bfd063322244f5336cc7c6ffcfars * IFF_NOXMIT: no packets transmitted over interface
4b22b9337f359bfd063322244f5336cc7c6ffcfars * IFF_NOLOCAL: no address
4b22b9337f359bfd063322244f5336cc7c6ffcfars * IFF_PRIVATE: is not advertised
e11c3f44f531fdff80941ce57c065d2ae861cefcmeem if (ifflags & (IFF_NOXMIT | IFF_NOLOCAL | IFF_PRIVATE))
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome /* A DHCP client will have IFF_UP set yet the address is zero. Ignore */
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome sinptr = (struct sockaddr_in *) &lifr->lifr_addr;
4b22b9337f359bfd063322244f5336cc7c6ffcfars * Check if we found a better interface by checking
4b22b9337f359bfd063322244f5336cc7c6ffcfars * the flags. If flags are identical we prefer
4b22b9337f359bfd063322244f5336cc7c6ffcfars * the new found interface.
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* If interface has a different set of flags */
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (diff_flags != 0) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* Check flags in increasing order of ones we prefer */
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* Address temporary? */
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* Deprecated address? */
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* Last best-matched interface address has preferred? */
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* Set best match interface & flags */
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* Found a match: return the interface information */
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifi->ifi_index = if_nametoindex((*best_lifr)->lifr_name);
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (strlcpy(ifi->ifi_name, (*best_lifr)->lifr_name, sizeof(ifi->ifi_name)) >= sizeof(ifi->ifi_name)) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars * Returns a list of IP interface information on Solaris. The function
4b22b9337f359bfd063322244f5336cc7c6ffcfars * returns all IP interfaces on the system with IPv4 address assigned
4b22b9337f359bfd063322244f5336cc7c6ffcfars * when passed AF_INET and returns IP interfaces with IPv6 address assigned
4b22b9337f359bfd063322244f5336cc7c6ffcfars * when AF_INET6 is passed.
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome * Pad interface count to detect & retrieve any
4b22b9337f359bfd063322244f5336cc7c6ffcfars * additional interfaces between IFNUM & IFCONF calls.
4b22b9337f359bfd063322244f5336cc7c6ffcfars * See if we have already processed the interface
4b22b9337f359bfd063322244f5336cc7c6ffcfars * by checking the interface names.
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (strlcpy(ifname, lifrp->lifr_name, sizeof(ifname)) >= sizeof(ifname))
4b22b9337f359bfd063322244f5336cc7c6ffcfars * If any of the interfaces found so far share the physical
4b22b9337f359bfd063322244f5336cc7c6ffcfars * interface name then we have already processed the interface.
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* Retrieve physical interface name */
4b22b9337f359bfd063322244f5336cc7c6ffcfars (void) strlcpy(cmpifname, ifi->ifi_name, sizeof(cmpifname));
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* Strip logical interface number before checking ifname */
4b22b9337f359bfd063322244f5336cc7c6ffcfars continue; /* already processed */
4b22b9337f359bfd063322244f5336cc7c6ffcfars * New interface, find the one with the preferred source
4b22b9337f359bfd063322244f5336cc7c6ffcfars * address for our use in Multicast DNS.
4b22b9337f359bfd063322244f5336cc7c6ffcfars memcpy(ifi->ifi_addr, sinptr6, sizeof(struct sockaddr_in6));
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifi->ifi_netmask = calloc(1, sizeof(struct sockaddr_in6));
4b22b9337f359bfd063322244f5336cc7c6ffcfars memcpy(ifi->ifi_addr, sinptr, sizeof(struct sockaddr_in));
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* interface removed */
4b22b9337f359bfd063322244f5336cc7c6ffcfars memcpy(ifi->ifi_netmask, sinptr, sizeof(struct sockaddr_in));
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* never reached */
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifipnext = &ifi->ifi_next; /* pointer to next one goes here */
4b22b9337f359bfd063322244f5336cc7c6ffcfars return(ifihead); /* pointer to first structure in linked list */
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif /* HAVE_SOLARIS */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome struct ifi_info *ifi, *ifihead, **ifipnext, *ifipold, **ifiptr;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome int sockfd, sockf6, len, lastlen, flags, myflags;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (family == AF_INET6) return get_ifi_info_linuxv6(family, doaliases);
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (sockfd < 0) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars len = 100 * sizeof(struct ifreq); /* initial buffer size guess */
4b22b9337f359bfd063322244f5336cc7c6ffcfars for ( ; ; ) {
4b22b9337f359bfd063322244f5336cc7c6ffcfars break; /* success, len has not changed */
4b22b9337f359bfd063322244f5336cc7c6ffcfars/* end get_ifi_info1 */
4b22b9337f359bfd063322244f5336cc7c6ffcfars/* include get_ifi_info2 */
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* Advance to next one in buffer */
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (sizeof(struct ifreq) > sizeof(ifr->ifr_name) + GET_SA_LEN(ifr->ifr_addr))
4b22b9337f359bfd063322244f5336cc7c6ffcfars ptr += sizeof(ifr->ifr_name) + GET_SA_LEN(ifr->ifr_addr);
4b22b9337f359bfd063322244f5336cc7c6ffcfars// fprintf(stderr, "intf %p name=%s AF=%d\n", index, ifr->ifr_name, ifr->ifr_addr.sa_family);
4b22b9337f359bfd063322244f5336cc7c6ffcfars continue; /* ignore if not desired address family */
4b22b9337f359bfd063322244f5336cc7c6ffcfars continue; /* already processed this interface */
4b22b9337f359bfd063322244f5336cc7c6ffcfars continue; /* ignore if interface not up */
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifi = (struct ifi_info*)calloc(1, sizeof(struct ifi_info));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome *ifipnext = ifi; /* prev points to this new one */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ifipnext = &ifi->ifi_next; /* pointer to next one goes here */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ifi->ifi_index = index++; /* SIOCGIFINDEX is broken on Solaris 2.5ish, so fake it */
4b22b9337f359bfd063322244f5336cc7c6ffcfars/* end get_ifi_info2 */
4b22b9337f359bfd063322244f5336cc7c6ffcfars/* include get_ifi_info3 */
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifi->ifi_addr = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
4b22b9337f359bfd063322244f5336cc7c6ffcfars memcpy(ifi->ifi_addr, sinptr, sizeof(struct sockaddr_in));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (ioctl(sockfd, SIOCGIFNETMASK, &ifrcopy) < 0) {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * If the main interface is configured with no IP address but
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * an alias interface exists with an IP address, you get
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * EADDRNOTAVAIL for the main interface
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ifi->ifi_netmask = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome sinptr = (struct sockaddr_in *) &ifrcopy.ifr_addr;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome /* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome memcpy(ifi->ifi_netmask, sinptr, sizeof(struct sockaddr_in));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome /* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome sinptr->sin_len = sizeof( struct sockaddr_in );
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifi->ifi_brdaddr = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
4b22b9337f359bfd063322244f5336cc7c6ffcfars memcpy(ifi->ifi_brdaddr, sinptr, sizeof(struct sockaddr_in));
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* The BSD ioctls (including Mac OS X) stick some weird values in for sin_len and sin_family */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome sinptr->sin_len = sizeof( struct sockaddr_in );
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifi->ifi_dstaddr = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in));
4b22b9337f359bfd063322244f5336cc7c6ffcfars memcpy(ifi->ifi_dstaddr, sinptr, sizeof(struct sockaddr_in));
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* Some platforms (*BSD) inject the prefix in IPv6LL addresses */
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* We need to strip that out */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome sinptr6->sin6_addr.s6_addr[2] = sinptr6->sin6_addr.s6_addr[3] = 0;
4b22b9337f359bfd063322244f5336cc7c6ffcfars memcpy(ifi->ifi_addr, sinptr6, sizeof(struct sockaddr_in6));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome memcpy(&ifr6.ifr_name, &ifr->ifr_name, sizeof(ifr6.ifr_name ));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome memcpy(&ifr6.ifr_ifru.ifru_addr, &ifr->ifr_addr, sizeof(ifr6.ifr_ifru.ifru_addr));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (ioctl(sockf6, SIOCGIFNETMASK_IN6, &ifr6) < 0) {
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * If the main interface is configured with no IP address but
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * an alias interface exists with an IP address, you get
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome * EADDRNOTAVAIL for the main interface
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome ifi->ifi_netmask = (struct sockaddr*)calloc(1, sizeof(struct sockaddr_in6));
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome sinptr6 = (struct sockaddr_in6 *) &ifr6.ifr_ifru.ifru_addr;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome memcpy(ifi->ifi_netmask, sinptr6, sizeof(struct sockaddr_in6));
4b22b9337f359bfd063322244f5336cc7c6ffcfars return(ifihead); /* pointer to first structure in linked list */
4b22b9337f359bfd063322244f5336cc7c6ffcfars/* end get_ifi_info3 */
4b22b9337f359bfd063322244f5336cc7c6ffcfars/* include free_ifi_info */
4b22b9337f359bfd063322244f5336cc7c6ffcfars ifinext = ifi->ifi_next; /* can't fetch ifi_next after free() */
4b22b9337f359bfd063322244f5336cc7c6ffcfars/* end free_ifi_info */
4b22b9337f359bfd063322244f5336cc7c6ffcfarsrecvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp,
4b22b9337f359bfd063322244f5336cc7c6ffcfars struct sockaddr *sa, socklen_t *salenptr, struct my_in_pktinfo *pktp, u_char *ttl)
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome pad64_t align8; /* ensure structure is 8-byte aligned on sparc */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome *ttl = 255; // If kernel fails to provide TTL data then assume the TTL was 255 as it should be
4b22b9337f359bfd063322244f5336cc7c6ffcfars memset(&msg, 0, sizeof(msg)); /* make certain msg_accrightslen = 0 */
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif /* CMSG_FIRSTHDR */
4b22b9337f359bfd063322244f5336cc7c6ffcfars return(n);
4b22b9337f359bfd063322244f5336cc7c6ffcfars /* 0.0.0.0, i/f = -1 */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome /* We set the interface to -1 so that the caller can
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome tell whether we returned a meaningful value or
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome just some default. Previously this code just
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome set the value to 0, but I'm concerned that 0
4b22b9337f359bfd063322244f5336cc7c6ffcfars might be a valid interface value.
4b22b9337f359bfd063322244f5336cc7c6ffcfars/* end recvfrom_flags1 */
4b22b9337f359bfd063322244f5336cc7c6ffcfars/* include recvfrom_flags2 */
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome #warning CMSG_FIRSTHDR not defined. Will not be able to determine destination address, received interface, etc.
4b22b9337f359bfd063322244f5336cc7c6ffcfars return(n);
4b22b9337f359bfd063322244f5336cc7c6ffcfars if (msg.msg_controllen < (socklen_t)sizeof(struct cmsghdr) ||
4b22b9337f359bfd063322244f5336cc7c6ffcfars return(n);
4b22b9337f359bfd063322244f5336cc7c6ffcfars struct sockaddr_in *sin = (struct sockaddr_in*)&pktp->ipi_addr;
4b22b9337f359bfd063322244f5336cc7c6ffcfars struct sockaddr_in *sin = (struct sockaddr_in*)&pktp->ipi_addr;
4b22b9337f359bfd063322244f5336cc7c6ffcfars struct sockaddr_dl *sdl = (struct sockaddr_dl *) CMSG_DATA(cmptr);
4b22b9337f359bfd063322244f5336cc7c6ffcfars int nameLen = (sdl->sdl_nlen < IFI_NAME - 1) ? sdl->sdl_nlen : (IFI_NAME - 1);
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome * the is memcpy used for sparc? no idea;)
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome * pktp->ipi_ifindex = sdl->sdl_index;
cda73f64f20b8a0afc4909f5ea1f055ec7913856Toomas Soome (void) memcpy(&pktp->ipi_ifindex, CMSG_DATA(cmptr), sizeof(uint_t));
4b22b9337f359bfd063322244f5336cc7c6ffcfars // null terminated because of memset above
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome cmptr->cmsg_type == IP_TTL) { // some implementations seem to send IP_TTL instead of IP_RECVTTL
4b22b9337f359bfd063322244f5336cc7c6ffcfars struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&pktp->ipi_addr;
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome struct in6_pktinfo *ip6_info = (struct in6_pktinfo*)CMSG_DATA(cmptr);
4b22b9337f359bfd063322244f5336cc7c6ffcfars return(n);
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif /* CMSG_FIRSTHDR */
4b22b9337f359bfd063322244f5336cc7c6ffcfars// **********************************************************************************************
4b22b9337f359bfd063322244f5336cc7c6ffcfars// daemonize the process. Adapted from "Unix Network Programming" vol 1 by Stevens, section 12.4.
4b22b9337f359bfd063322244f5336cc7c6ffcfars// Returns 0 on success, -1 on failure.
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome case 0: break; // Child -- continue
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome switch (fork()) // Fork again, primarily for reasons of Unix trivia
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome case 0: break; // Child -- continue
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome // Avoid unnecessarily duplicating a file descriptor to itself
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (fd != STDIN_FILENO) (void)dup2(fd, STDIN_FILENO);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (fd != STDOUT_FILENO) (void)dup2(fd, STDOUT_FILENO);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (fd != STDERR_FILENO) (void)dup2(fd, STDERR_FILENO);
5ffb0c9b03b5149ff4f5821a62be4a52408ada2aToomas Soome if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO)
4b22b9337f359bfd063322244f5336cc7c6ffcfars#endif /* NOT_HAVE_DAEMON */