diff options
author | gdt <gdt> | 2004-12-29 20:06:23 +0000 |
---|---|---|
committer | gdt <gdt> | 2004-12-29 20:06:23 +0000 |
commit | d44debedf53b85c989b72fe7c6924ffc1e7e625b (patch) | |
tree | 4c527145158b49674cffb714fb571fd7d9a92b24 | |
parent | 4660687a38034d60296fbc9e82aae772011c407f (diff) |
2004-12-29 Greg Troxel <gdt@poblano.ir.bbn.com>
* sockopt.c (getsockopt_ipv4_ifindex): Document calling
convention. Beef up comments. Handle the case where the cmsghdr
has a zero controllen, or more specifically when the wanted option
is not present. This is needed for Solaris 8, and in general for
any platform for which configure finds a method and it can fail.
Mark some changes with XXX to be cleaned up post 0.98.
-rw-r--r-- | lib/ChangeLog | 10 | ||||
-rw-r--r-- | lib/sockopt.c | 75 |
2 files changed, 50 insertions, 35 deletions
diff --git a/lib/ChangeLog b/lib/ChangeLog index 6f236372..3af0d0b2 100644 --- a/lib/ChangeLog +++ b/lib/ChangeLog @@ -1,8 +1,12 @@ 2004-12-29 Greg Troxel <gdt@poblano.ir.bbn.com> - * sockopt.c (getsockopt_ipv4_ifindex): Return 0 when passed a NULL - cmsghdr pointer. - + * sockopt.c (getsockopt_ipv4_ifindex): Document calling + convention. Beef up comments. Handle the case where the cmsghdr + has a zero controllen, or more specifically when the wanted option + is not present. This is needed for Solaris 8, and in general for + any platform for which configure finds a method and it can fail. + Mark some changes with XXX to be cleaned up post 0.98. + 2004-12-28 Andrew J. Schorr <ajschorr@alumni.princeton.edu> * sockopt.c: (setsockopt_ipv4_ifindex) Improve error message. diff --git a/lib/sockopt.c b/lib/sockopt.c index 8c518f82..f1366158 100644 --- a/lib/sockopt.c +++ b/lib/sockopt.c @@ -280,63 +280,74 @@ setsockopt_ifindex (int af, int sock, int val) return ret; } +/* + * Requires: msgh is not NULL and points to a valid struct msghdr, which + * may or may not have control data about the incoming interface. + * + * Returns the interface index (small integer >= 1) if it can be + * determined, or else 0. + */ static int getsockopt_ipv4_ifindex (struct msghdr *msgh) { - /* - * XXX: This routine's semantics are ill-defined, in particular how - * the results "can't determine interface due to runtime behavior" - * and "OS has no support for how to determine behavior" are - * encoded. For now, return 0 for either case; caller must handle - * as "don't know". - */ + /* XXX: initialize to zero? (Always overwritten, so just cosmetic.) */ int ifindex = -1; - /* - * If autoconf found a method to get ifindex, but it didn't work for - * this packet, or on this OS, this routine can be entered with a - * NULL cmsghdr pointer. Check msgh before using in each case - * below, rather than here, to avoid having to ifdef twice, once for - * declarations and once for code. - */ - #if defined(IP_PKTINFO) /* Linux pktinfo based ifindex retrieval */ struct in_pktinfo *pktinfo; - if (msgh == NULL) - return 0; - pktinfo = (struct in_pktinfo *)getsockopt_cmsg_data (msgh, IPPROTO_IP, IP_PKTINFO); + /* XXX Can pktinfo be NULL? Clean up post 0.98. */ ifindex = pktinfo->ipi_ifindex; #elif defined(IP_RECVIF) -/* BSD/other IP_RECVIF based ifindex retrieval */ + + /* retrieval based on IP_RECVIF */ + #ifndef SUNOS_5 - /* RECVIF, but not SUNOS, so BSD */ + /* BSD systems use a sockaddr_dl as the control message payload. */ struct sockaddr_dl *sdl; +#else + /* SUNOS_5 uses an integer with the index. */ + int *ifindex_p; #endif /* SUNOS_5 */ - /* SUNOS_5 doesn't need a structure to extract ifindex */ - - if (msgh == NULL) - return 0; #ifndef SUNOS_5 + /* BSD */ sdl = (struct sockaddr_dl *)getsockopt_cmsg_data (msgh, IPPROTO_IP, IP_RECVIF); - ifindex = sdl->sdl_index; -#else /* !SUNOS_5 */ - ifindex = *(uint_t *)getsockopt_cmsg_data (msgh, IPPROTO_IP, IP_RECVIF); + if (sdl != NULL) + ifindex = sdl->sdl_index; + else + ifindex = 0; +#else + /* + * Solaris. On Solaris 8, IP_RECVIF is defined, but the call to + * enable it fails with errno=99, and the struct msghdr has + * controllen 0. + */ + ifindex_p = (uint_t *)getsockopt_cmsg_data (msgh, IPPROTO_IP, IP_RECVIF); + if (ifindex_p != NULL) + ifindex = *ifindex_p; + else + ifindex = 0; #endif /* SUNOS_5 */ -#else /* neither IP_PKTINFO nor IP_RECVIF, broken */ - -#warning "getsockopt_ipv4_pktinfo_ifindex: dont have PKTINFO or RECVIF" -#warning "things probably will be broken on this platform!" - /* XXX why not -1 - this is a failure condition. */ +#else + /* + * Neither IP_PKTINFO nor IP_RECVIF defined - warn at compile time. + * XXX Decide if this is a core service, or if daemons have to cope. + * Since Solaris 8 and OpenBSD seem not to provide it, it seems that + * daemons have to cope. + */ +#warning "getsockopt_ipv4_ifindex: Neither IP_PKTINFO nor IP_RECVIF defined." +#warning "Some daemons may fail to operate correctly!" ifindex = 0; + #endif /* IP_PKTINFO */ + return ifindex; } |