summaryrefslogtreecommitdiff
path: root/usr/src/cmd/cmd-inet/usr.lib/mdnsd/mDNSUNP.c
diff options
context:
space:
mode:
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.c560
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 */