]> git.puffer.fish Git - matthieu/frr.git/commitdiff
2004-07-23 Paul Jakma <paul@dishone.st>
authorpaul <paul>
Fri, 23 Jul 2004 15:11:07 +0000 (15:11 +0000)
committerpaul <paul>
Fri, 23 Jul 2004 15:11:07 +0000 (15:11 +0000)
        * sockopt.h: Add SOPT_SIZE_CMSG_PKTINFO{_IPV{4,6}} define, for
          sizeof pktinfo as appropriate, to be used when allocating msg
          buffers. export setsockopt_pktinfo() and
          getsockopt_pktinfo_ifindex()
        * sockopt.c: (setsockopt_pktinfo_ifindex) new function to portably
          set received ifindex sock option.
          (getsockopt_pktinfo_ifindex) portably retrieve ifindex.
          (getsockopt_cmsg_data) retrieve indicated control info from
          message header.
          (getsockopt_ipv6_pktinfo_ifindex) ipv6 version of above.
          (setsockopt_ipv4_pktinfo) v4 version
          (setsockopt_pktinfo) the exported version
          (getsockopt_ipv4_pktinfo_ifindex) v4 specific version
          (getsockopt_pktinfo_ifindex) the exported version

lib/ChangeLog
lib/sockopt.c
lib/sockopt.h

index b3d452e0f1c0b9fc1e56754069dd45ca002612da..ff813bba0fed2d0f5c18c2c12c75ba0bef9ea52d 100644 (file)
@@ -1,3 +1,20 @@
+2004-07-23 Paul Jakma <paul@dishone.st>
+
+       * sockopt.h: Add SOPT_SIZE_CMSG_PKTINFO{_IPV{4,6}} define, for
+         sizeof pktinfo as appropriate, to be used when allocating msg
+         buffers. export setsockopt_pktinfo() and
+         getsockopt_pktinfo_ifindex()
+       * sockopt.c: (setsockopt_pktinfo_ifindex) new function to portably
+         set received ifindex sock option.
+         (getsockopt_pktinfo_ifindex) portably retrieve ifindex.
+         (getsockopt_cmsg_data) retrieve indicated control info from 
+         message header.
+         (getsockopt_ipv6_pktinfo_ifindex) ipv6 version of above.
+         (setsockopt_ipv4_pktinfo) v4 version
+         (setsockopt_pktinfo) the exported version
+         (getsockopt_ipv4_pktinfo_ifindex) v4 specific version
+         (getsockopt_pktinfo_ifindex) the exported version
+
 2004-07-14 Paul Jakma <paul@dishone.st>
 
        * sigevent.c: (quagga_signal_handler) add a global caught flag, set
index e2beca9f9ca019a69ed1acbaaf8a263562d09c8f..ee10ac302f3a3c70abc857875f7d5052c78588f8 100644 (file)
 #include <zebra.h>
 #include "log.h"
 
+static void *
+getsockopt_cmsg_data (struct msghdr *msgh, int level, int type)
+{
+  struct cmsghdr *cmsg;
+  void *ptr = NULL;
+  
+  for (cmsg = CMSG_FIRSTHDR(msgh); 
+       cmsg != NULL;
+       cmsg = CMSG_NXTHDR(msgh, cmsg))
+    if (cmsg->cmsg_level == level && cmsg->cmsg_type)
+      return (ptr = CMSG_DATA(cmsg));
+}
+
 #ifdef HAVE_IPV6
 /* Set IPv6 packet info to the socket. */
 int
@@ -111,6 +124,15 @@ setsockopt_ipv6_multicast_loop (int sock, int val)
   return ret;
 }
 
+static int
+getsockopt_ipv6_pktinfo_ifindex (struct msghdr *msgh)
+{
+  struct in6_pktinfo *pktinfo;
+  
+  pktinfo = getsockopt_cmsg_data (msgh, IPPROTO_IPV6, IPV6_PKTINFO);
+  
+  return pktinfo->ipi6_ifindex;
+}
 #endif /* HAVE_IPV6 */
 
 
@@ -197,3 +219,105 @@ setsockopt_multicast_ipv4(int sock,
 #endif /* #if OS_TYPE */
 
 }
+
+static int
+setsockopt_ipv4_pktinfo (int sock, int val)
+{
+  int ret;
+
+#if defined (IP_PKTINFO)
+  ret = setsockopt (sock, IPPROTO_IP, IP_PKTINFO, &val, sizeof (val));
+#elif defined (IP_RECVIF)
+  ret = setsockopt (sock, IPPROTO_IP, IP_RECVIF, &val, sizeof (val));
+#else
+#warning "Neither IP_PKTINFO nor IP_RECVIF is available."
+#warning "Will not be able to receive link info."
+#warning "Things might be seriously broken.."
+#endif
+
+  if (ret < 0)
+    zlog_warn ("Can't set IP_PKTINFO option");
+  return ret;
+}
+
+/* set appropriate pktinfo socket option 
+ * on systems without PKTINFO, sets RECVIF, which only retrieves
+ * interface index.
+ */
+int 
+setsockopt_pktinfo (int af, int sock, int val)
+{
+  int ret = -1;
+  
+  switch (af)
+    {
+      case AF_INET:
+        ret = setsockopt_ipv4_pktinfo (sock, val);
+        break;
+#ifdef HAVE_IPV6
+      case AF_INET6:
+        ret = setsockopt_ipv6_pktinfo (sock, val);
+        break;
+#endif
+      default:
+        zlog_warn ("setsockopt_pktinfo: unknown address family %d");
+    }
+  return ret;
+}
+
+
+static int
+getsockopt_ipv4_pktinfo_ifindex (struct msghdr *msgh)
+{
+  int ifindex = 0;
+#if defined (IP_PKTINFO)
+  struct in_pktinfo *pktinfo;
+#elif defined (IP_REVCIF)
+#ifndef SUNOS_5
+  struct sockaddr_dl *sdl;
+#endif /* SUNOS_5 */
+#else /* IP_RECVIF */
+  char *pktinfo;
+#endif /* IP_PKTINFO */
+  
+#ifdef IP_PKTINFO
+  pktinfo = 
+    (struct in_pktinfo *)getsockopt_cmsg_data (msgh, IPPROTO_IP, IP_PKTINFO);
+#elif defined (IP_RECVIF)
+#ifdef SUNOS_5
+  ifindex = *(uint_t *)getsockopt_cmsg_data (msgh, IPPROTO_IP, IP_RECVIF);
+#else
+  pktinfo = 
+    (struct sockaddr_dl *)getsockopt_cmsg_data (msgh, IPPROTO_IP, IP_RECVIF);
+  ifindex = pktinfo->sdl_index;
+#endif /* SUNOS_5 */
+#else
+#warning "getsockopt_ipv4_pktinfo_ifindex: dont have PKTINFO or RECVIF"
+        ifindex = 0;
+#endif /* IP_PKTINFO */
+  return ifindex;
+}
+
+/* return ifindex, 0 if none found */
+int
+getsockopt_pktinfo_ifindex (int af, struct msghdr *msgh)
+{
+  int ifindex = 0;
+  
+  switch (af)
+    {
+      case AF_INET:
+        return (getsockopt_ipv4_pktinfo_ifindex (msgh));
+        break;
+#ifdef HAVE_IPV6
+      case AF_INET6:
+        return (getsockopt_ipv6_pktinfo_ifindex (msgh));
+        break;
+#endif
+      default:
+        zlog_warn ("getsockopt_pktinfo_ifindex: unknown address family %d");
+        return (ifindex = 0);
+    }
+}
+
index 7fb31c186a9be2c0134345075c4096d7962d52dc..c5d171c25d3f82145352161c0837a8136246f651 100644 (file)
@@ -31,11 +31,27 @@ int setsockopt_ipv6_hoplimit (int, int);
 int setsockopt_ipv6_multicast_loop (int, int);
 #endif /* HAVE_IPV6 */
 
+#if defined (IP_PKTINFO)
+#define SOPT_SIZE_CMSG_PKTINFO_IPV4()  (sizeof (struct in_pktinfo))
+#elif defined (IP_RECVIF)
+#if defined (SUNOS_5)
+#define SOPT_SIZE_CMSG_PKTINFO_IPV4()  (sizeof (uint_t))
+#else
+#define SOPT_SIZE_CMSG_PKTINFO_IPV4()  (sizeof (struct sockaddr_dl))
+#endif /* SUNOS_5 */
+#endif
+
+#define SOPT_SIZE_CMSG_PKTINFO_IPV6() (sizeof (struct in6_pktinfo));
+
+#define SOPT_SIZE_CMSG_PKTINFO(af) \
+  ((af == AF_INET) ? SOPT_SIZE_CMSG_PKTINFO_IPV4() \
+                   : SOPT_SIZE_CMSG_PKTINFO_IPV6()
+
 int setsockopt_multicast_ipv4(int sock, 
                             int optname, 
                             struct in_addr if_addr,
                             unsigned int mcast_addr,
                             unsigned int ifindex);
-
-
+int setsockopt_pktinfo (int, int, int);
+int getsockopt_pktinfo_ifindex (int, struct msghdr *);
 #endif /*_ZEBRA_SOCKOPT_H */