]> git.proxmox.com Git - mirror_frr.git/blobdiff - pimd/pim_sock.c
lib: enforce vrf_name_to_id by returning default_vrf when name is null
[mirror_frr.git] / pimd / pim_sock.c
index 07b137bb51c6bab16967267cd460c0c66c865a29..c4538a4ac52e83d4ccbae8d25b88320c981899f4 100644 (file)
@@ -1,22 +1,21 @@
 /*
-  PIM for Quagga
-  Copyright (C) 2008  Everton da Silva Marques
-
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-
-  This program is distributed in the hope that it will be useful, but
-  WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-  General Public License for more details.
-  
-  You should have received a copy of the GNU General Public License
-  along with this program; see the file COPYING; if not, write to the
-  Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
-  MA 02110-1301 USA
-*/
+ * PIM for Quagga
+ * Copyright (C) 2008  Everton da Silva Marques
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
 
 #include <zebra.h>
 
 #include "if.h"
 #include "vrf.h"
 #include "sockopt.h"
+#include "lib_errors.h"
 
 #include "pimd.h"
 #include "pim_mroute.h"
 #include "pim_sock.h"
 #include "pim_str.h"
-#include "pim_igmp_join.h"
 
 /* GLOBAL VARS */
 
-int
-pim_socket_raw (int protocol)
+int pim_socket_raw(int protocol)
 {
-  int fd;
+       int fd;
+
+       frr_elevate_privs(&pimd_privs) {
 
-  if ( pimd_privs.change (ZPRIVS_RAISE) )
-       zlog_err ("pim_sockek_raw: could not raise privs, %s",
-                 safe_strerror (errno) );
+               fd = socket(AF_INET, SOCK_RAW, protocol);
 
-  fd = socket(AF_INET, SOCK_RAW, protocol);
+       }
 
-  if ( pimd_privs.change (ZPRIVS_LOWER) )
-       zlog_err ("pim_socket_raw: could not lower privs, %s",
-                 safe_strerror (errno) );
+       if (fd < 0) {
+               zlog_warn("Could not create raw socket: errno=%d: %s", errno,
+                         safe_strerror(errno));
+               return PIM_SOCK_ERR_SOCKET;
+       }
 
-  if (fd < 0) {
-    zlog_warn("Could not create raw socket: errno=%d: %s",
-             errno, safe_strerror(errno));
-    return PIM_SOCK_ERR_SOCKET;
-  }
-  
-  return fd;
+       return fd;
 }
 
-int
-pim_socket_ip_hdr (int fd)
+void pim_socket_ip_hdr(int fd)
 {
-  const int on = 1;
-  int ret;
-
-  if (pimd_privs.change (ZPRIVS_RAISE))
-    zlog_err ("%s: could not raise privs, %s",
-             __PRETTY_FUNCTION__, safe_strerror (errno));
+       const int on = 1;
 
-  ret = setsockopt (fd, IPPROTO_IP, IP_HDRINCL, &on, sizeof (on));
+       frr_elevate_privs(&pimd_privs) {
 
-  if (pimd_privs.change (ZPRIVS_LOWER))
-    zlog_err ("%s: could not lower privs, %s",
-             __PRETTY_FUNCTION__, safe_strerror (errno));
+               if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &on, sizeof(on)))
+                       zlog_err("%s: Could not turn on IP_HDRINCL option: %s",
+                                __PRETTY_FUNCTION__, safe_strerror(errno));
 
-  return ret;
+       }
 }
 
 /*
  * Given a socket and a interface,
  * Bind that socket to that interface
  */
-int
-pim_socket_bind (int fd, struct interface *ifp)
+int pim_socket_bind(int fd, struct interface *ifp)
 {
-  int ret = 0;
+       int ret = 0;
 #ifdef SO_BINDTODEVICE
 
-  if (pimd_privs.change (ZPRIVS_RAISE))
-    zlog_err ("%s: could not raise privs, %s",
-             __PRETTY_FUNCTION__, safe_strerror (errno));
+       frr_elevate_privs(&pimd_privs) {
 
-  ret = setsockopt (fd, SOL_SOCKET,
-                   SO_BINDTODEVICE, ifp->name, strlen (ifp->name));
+               ret = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, ifp->name,
+                                strlen(ifp->name));
 
-  if (pimd_privs.change (ZPRIVS_LOWER))
-    zlog_err ("%s: could not lower privs, %s",
-             __PRETTY_FUNCTION__, safe_strerror (errno));
+       }
 
 #endif
-  return ret;
+       return ret;
 }
 
-int pim_socket_mcast(int protocol, struct in_addr ifaddr, struct interface *ifp, u_char loop)
+int pim_socket_mcast(int protocol, struct in_addr ifaddr, struct interface *ifp,
+                    uint8_t loop)
 {
-  int rcvbuf = 1024 * 1024 * 8;
+       int rcvbuf = 1024 * 1024 * 8;
 #ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX
-  struct ip_mreqn mreq;
+       struct ip_mreqn mreq;
 #else
-  struct ip_mreq mreq;
+       struct ip_mreq mreq;
 #endif
-  int fd;
+       int fd;
 
-  fd = pim_socket_raw(protocol);
-  if (fd < 0) {
-    zlog_warn("Could not create multicast socket: errno=%d: %s",
-             errno, safe_strerror(errno));
-    return PIM_SOCK_ERR_SOCKET;
-  }
+       fd = pim_socket_raw(protocol);
+       if (fd < 0) {
+               zlog_warn("Could not create multicast socket: errno=%d: %s",
+                         errno, safe_strerror(errno));
+               return PIM_SOCK_ERR_SOCKET;
+       }
 
 #ifdef SO_BINDTODEVICE
-  if (protocol == IPPROTO_PIM)
-    {
-      int ret;
-
-      ret = pim_socket_bind (fd, ifp);
-      if (ret)
-       {
-          close (fd);
-         zlog_warn("Could not set fd: %d for interface: %s to device",
-                   fd, ifp->name);
-         return PIM_SOCK_ERR_BIND;
+       if (protocol == IPPROTO_PIM) {
+               int ret;
+
+               ret = pim_socket_bind(fd, ifp);
+               if (ret) {
+                       close(fd);
+                       zlog_warn(
+                               "Could not set fd: %d for interface: %s to device",
+                               fd, ifp->name);
+                       return PIM_SOCK_ERR_BIND;
+               }
        }
-    }
 #else
-  /* XXX: use IP_PKTINFO / IP_RECVIF to emulate behaviour?  Or change to
  * only use 1 socket for all interfaces? */
+/* XXX: use IP_PKTINFO / IP_RECVIF to emulate behaviour?  Or change to
+ * only use 1 socket for all interfaces? */
 #endif
 
-  /* Needed to obtain destination address from recvmsg() */
-  {
+       /* Needed to obtain destination address from recvmsg() */
+       {
 #if defined(HAVE_IP_PKTINFO)
-    /* Linux and Solaris IP_PKTINFO */
-    int opt = 1;
-    if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt))) {
-      zlog_warn("Could not set IP_PKTINFO on socket fd=%d: errno=%d: %s",
-               fd, errno, safe_strerror(errno));
-    }
+               /* Linux and Solaris IP_PKTINFO */
+               int opt = 1;
+               if (setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt))) {
+                       zlog_warn(
+                               "Could not set IP_PKTINFO on socket fd=%d: errno=%d: %s",
+                               fd, errno, safe_strerror(errno));
+               }
 #elif defined(HAVE_IP_RECVDSTADDR)
-    /* BSD IP_RECVDSTADDR */
-    int opt = 1;
-    if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt, sizeof(opt))) {
-      zlog_warn("Could not set IP_RECVDSTADDR on socket fd=%d: errno=%d: %s",
-               fd, errno, safe_strerror(errno));
-    }
+               /* BSD IP_RECVDSTADDR */
+               int opt = 1;
+               if (setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR, &opt,
+                              sizeof(opt))) {
+                       zlog_warn(
+                               "Could not set IP_RECVDSTADDR on socket fd=%d: errno=%d: %s",
+                               fd, errno, safe_strerror(errno));
+               }
 #else
-    zlog_err("%s %s: Missing IP_PKTINFO and IP_RECVDSTADDR: unable to get dst addr from recvmsg()",
-            __FILE__, __PRETTY_FUNCTION__);
-    close(fd);
-    return PIM_SOCK_ERR_DSTADDR;
+               flog_err(
+                       EC_LIB_DEVELOPMENT,
+                       "%s %s: Missing IP_PKTINFO and IP_RECVDSTADDR: unable to get dst addr from recvmsg()",
+                       __FILE__, __PRETTY_FUNCTION__);
+               close(fd);
+               return PIM_SOCK_ERR_DSTADDR;
 #endif
-  }
-
-  
-  /* Set router alert (RFC 2113) for all IGMP messages (RFC 3376 4. Message Formats)*/
-  if (protocol == IPPROTO_IGMP) {
-    uint8_t ra[4];
-    ra[0] = 148;
-    ra[1] = 4;
-    ra[2] = 0;
-    ra[3] = 0;
-    if (setsockopt(fd, IPPROTO_IP, IP_OPTIONS, ra, 4)) {
-      zlog_warn("Could not set Router Alert Option on socket fd=%d: errno=%d: %s",
-               fd, errno, safe_strerror(errno));
-      close(fd);
-      return PIM_SOCK_ERR_RA;
-    }
-  }
-
-  {
-    int reuse = 1;
-    if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
-                  (void *) &reuse, sizeof(reuse))) {
-      zlog_warn("Could not set Reuse Address Option on socket fd=%d: errno=%d: %s",
-               fd, errno, safe_strerror(errno));
-      close(fd);
-      return PIM_SOCK_ERR_REUSE;
-    }
-  }
-
-  {
-    const int MTTL = 1;
-    int ttl = MTTL;
-    if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL,
-                  (void *) &ttl, sizeof(ttl))) {
-      zlog_warn("Could not set multicast TTL=%d on socket fd=%d: errno=%d: %s",
-               MTTL, fd, errno, safe_strerror(errno));
-      close(fd);
-      return PIM_SOCK_ERR_TTL;
-    }
-  }
-
-  if (setsockopt_ipv4_multicast_loop (fd, loop)) {
-    zlog_warn("Could not %s Multicast Loopback Option on socket fd=%d: errno=%d: %s",
-             loop ? "enable" : "disable",
-             fd, errno, safe_strerror(errno));
-    close(fd);
-    return PIM_SOCK_ERR_LOOP;
-  }
-
-  memset (&mreq, 0, sizeof (mreq));
+       }
+
+
+       /* Set router alert (RFC 2113) for all IGMP messages (RFC 3376 4.
+        * Message Formats)*/
+       if (protocol == IPPROTO_IGMP) {
+               uint8_t ra[4];
+               ra[0] = 148;
+               ra[1] = 4;
+               ra[2] = 0;
+               ra[3] = 0;
+               if (setsockopt(fd, IPPROTO_IP, IP_OPTIONS, ra, 4)) {
+                       zlog_warn(
+                               "Could not set Router Alert Option on socket fd=%d: errno=%d: %s",
+                               fd, errno, safe_strerror(errno));
+                       close(fd);
+                       return PIM_SOCK_ERR_RA;
+               }
+       }
+
+       {
+               int reuse = 1;
+               if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse,
+                              sizeof(reuse))) {
+                       zlog_warn(
+                               "Could not set Reuse Address Option on socket fd=%d: errno=%d: %s",
+                               fd, errno, safe_strerror(errno));
+                       close(fd);
+                       return PIM_SOCK_ERR_REUSE;
+               }
+       }
+
+       {
+               const int MTTL = 1;
+               int ttl = MTTL;
+               if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&ttl,
+                              sizeof(ttl))) {
+                       zlog_warn(
+                               "Could not set multicast TTL=%d on socket fd=%d: errno=%d: %s",
+                               MTTL, fd, errno, safe_strerror(errno));
+                       close(fd);
+                       return PIM_SOCK_ERR_TTL;
+               }
+       }
+
+       if (setsockopt_ipv4_multicast_loop(fd, loop)) {
+               zlog_warn(
+                       "Could not %s Multicast Loopback Option on socket fd=%d: errno=%d: %s",
+                       loop ? "enable" : "disable", fd, errno,
+                       safe_strerror(errno));
+               close(fd);
+               return PIM_SOCK_ERR_LOOP;
+       }
+
+       memset(&mreq, 0, sizeof(mreq));
 #ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX
-  mreq.imr_ifindex = ifp->ifindex;
+       mreq.imr_ifindex = ifp->ifindex;
 #else
-  /*
  * I am not sure what to do here yet for *BSD
  */
-  //mreq.imr_interface = ifindex;
+/*
+ * I am not sure what to do here yet for *BSD
+ */
+// mreq.imr_interface = ifindex;
 #endif
 
-  if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF,
-                (void *) &mreq, sizeof(mreq))) {
-    zlog_warn("Could not set Outgoing Interface Option on socket fd=%d: errno=%d: %s",
-             fd, errno, safe_strerror(errno));
-    close(fd);
-    return PIM_SOCK_ERR_IFACE;
-  }
-
-  if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)))
-      zlog_warn("%s: Failure to set buffer size to %d",
-               __PRETTY_FUNCTION__, rcvbuf);
-
-  {
-    long flags;
-
-    flags = fcntl(fd, F_GETFL, 0);
-    if (flags < 0) {
-      zlog_warn("Could not get fcntl(F_GETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s",
-               fd, errno, safe_strerror(errno));
-      close(fd);
-      return PIM_SOCK_ERR_NONBLOCK_GETFL;
-    }
-
-    if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) {
-      zlog_warn("Could not set fcntl(F_SETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s",
-               fd, errno, safe_strerror(errno));
-      close(fd);
-      return PIM_SOCK_ERR_NONBLOCK_SETFL;
-    }
-  }
-
-  return fd;
+       if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, (void *)&mreq,
+                      sizeof(mreq))) {
+               zlog_warn(
+                       "Could not set Outgoing Interface Option on socket fd=%d: errno=%d: %s",
+                       fd, errno, safe_strerror(errno));
+               close(fd);
+               return PIM_SOCK_ERR_IFACE;
+       }
+
+       if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)))
+               zlog_warn("%s: Failure to set buffer size to %d",
+                         __PRETTY_FUNCTION__, rcvbuf);
+
+       {
+               long flags;
+
+               flags = fcntl(fd, F_GETFL, 0);
+               if (flags < 0) {
+                       zlog_warn(
+                               "Could not get fcntl(F_GETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s",
+                               fd, errno, safe_strerror(errno));
+                       close(fd);
+                       return PIM_SOCK_ERR_NONBLOCK_GETFL;
+               }
+
+               if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) {
+                       zlog_warn(
+                               "Could not set fcntl(F_SETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s",
+                               fd, errno, safe_strerror(errno));
+                       close(fd);
+                       return PIM_SOCK_ERR_NONBLOCK_SETFL;
+               }
+       }
+
+       return fd;
 }
 
-int pim_socket_join(int fd, struct in_addr group,
-                   struct in_addr ifaddr, ifindex_t ifindex)
+int pim_socket_join(int fd, struct in_addr group, struct in_addr ifaddr,
+                   ifindex_t ifindex)
 {
-  int ret;
+       int ret;
 
 #ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX
-  struct ip_mreqn opt;
+       struct ip_mreqn opt;
 #else
-  struct ip_mreq opt;
+       struct ip_mreq opt;
 #endif
 
-  opt.imr_multiaddr = group;
+       opt.imr_multiaddr = group;
 
 #ifdef HAVE_STRUCT_IP_MREQN_IMR_IFINDEX
-  opt.imr_address   = ifaddr;
-  opt.imr_ifindex   = ifindex;
+       opt.imr_address = ifaddr;
+       opt.imr_ifindex = ifindex;
 #else
-  opt.imr_interface = ifaddr;
+       opt.imr_interface = ifaddr;
 #endif
 
-  ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &opt, sizeof(opt));
-  if (ret) {
-    char group_str[INET_ADDRSTRLEN];
-    char ifaddr_str[INET_ADDRSTRLEN];
-    if (!inet_ntop(AF_INET, &group, group_str , sizeof(group_str)))
-      sprintf(group_str, "<group?>");
-    if (!inet_ntop(AF_INET, &ifaddr, ifaddr_str , sizeof(ifaddr_str)))
-      sprintf(ifaddr_str, "<ifaddr?>");
-
-    zlog_err("Failure socket joining fd=%d group %s on interface address %s: errno=%d: %s",
-            fd, group_str, ifaddr_str, errno, safe_strerror(errno));
-    return ret;
-  }
-
-  if (PIM_DEBUG_TRACE) {
-    char group_str[INET_ADDRSTRLEN];
-    char ifaddr_str[INET_ADDRSTRLEN];
-    if (!inet_ntop(AF_INET, &group, group_str , sizeof(group_str)))
-      sprintf(group_str, "<group?>");
-    if (!inet_ntop(AF_INET, &ifaddr, ifaddr_str , sizeof(ifaddr_str)))
-      sprintf(ifaddr_str, "<ifaddr?>");
-
-    zlog_debug("Socket fd=%d joined group %s on interface address %s",
-              fd, group_str, ifaddr_str);
-  }
-
-  return ret;
-}
+       ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &opt, sizeof(opt));
+       if (ret) {
+               char group_str[INET_ADDRSTRLEN];
+               char ifaddr_str[INET_ADDRSTRLEN];
+               if (!inet_ntop(AF_INET, &group, group_str, sizeof(group_str)))
+                       sprintf(group_str, "<group?>");
+               if (!inet_ntop(AF_INET, &ifaddr, ifaddr_str,
+                              sizeof(ifaddr_str)))
+                       sprintf(ifaddr_str, "<ifaddr?>");
+
+               flog_err(
+                       EC_LIB_SOCKET,
+                       "Failure socket joining fd=%d group %s on interface address %s: errno=%d: %s",
+                       fd, group_str, ifaddr_str, errno, safe_strerror(errno));
+               return ret;
+       }
 
-int pim_socket_join_source(int fd, ifindex_t ifindex,
-                          struct in_addr group_addr,
-                          struct in_addr source_addr,
-                          const char *ifname)
-{
-  if (pim_igmp_join_source(fd, ifindex, group_addr, source_addr)) {
-    char group_str[INET_ADDRSTRLEN];
-    char source_str[INET_ADDRSTRLEN];
-    pim_inet4_dump("<grp?>", group_addr, group_str, sizeof(group_str));
-    pim_inet4_dump("<src?>", source_addr, source_str, sizeof(source_str));
-    zlog_warn("%s: setsockopt(fd=%d) failure for IGMP group %s source %s ifindex %d on interface %s: errno=%d: %s",
-             __PRETTY_FUNCTION__,
-             fd, group_str, source_str, ifindex, ifname,
-             errno, safe_strerror(errno));
-    return -1;
-  }
-
-  return 0;
+       if (PIM_DEBUG_TRACE) {
+               char group_str[INET_ADDRSTRLEN];
+               char ifaddr_str[INET_ADDRSTRLEN];
+               if (!inet_ntop(AF_INET, &group, group_str, sizeof(group_str)))
+                       sprintf(group_str, "<group?>");
+               if (!inet_ntop(AF_INET, &ifaddr, ifaddr_str,
+                              sizeof(ifaddr_str)))
+                       sprintf(ifaddr_str, "<ifaddr?>");
+
+               zlog_debug(
+                       "Socket fd=%d joined group %s on interface address %s",
+                       fd, group_str, ifaddr_str);
+       }
+
+       return ret;
 }
 
 int pim_socket_recvfromto(int fd, uint8_t *buf, size_t len,
@@ -336,117 +317,121 @@ int pim_socket_recvfromto(int fd, uint8_t *buf, size_t len,
                          struct sockaddr_in *to, socklen_t *tolen,
                          ifindex_t *ifindex)
 {
-  struct msghdr msgh;
-  struct cmsghdr *cmsg;
-  struct iovec iov;
-  char cbuf[1000];
-  int err;
-
-  /*
-   * IP_PKTINFO / IP_RECVDSTADDR don't yield sin_port.
-   * Use getsockname() to get sin_port.
-   */
-  if (to) {
-    struct sockaddr_in si;
-    socklen_t si_len = sizeof(si);
-
-    memset (&si, 0, sizeof (si));
-    to->sin_family = AF_INET;
-
-    pim_socket_getsockname(fd, (struct sockaddr *) &si, &si_len);
-
-    to->sin_port = si.sin_port;
-    to->sin_addr = si.sin_addr;
-
-    if (tolen) 
-      *tolen = sizeof(si);
-  }
-
-  memset(&msgh, 0, sizeof(struct msghdr));
-  iov.iov_base = buf;
-  iov.iov_len  = len;
-  msgh.msg_control = cbuf;
-  msgh.msg_controllen = sizeof(cbuf);
-  msgh.msg_name = from;
-  msgh.msg_namelen = fromlen ? *fromlen : 0;
-  msgh.msg_iov  = &iov;
-  msgh.msg_iovlen = 1;
-  msgh.msg_flags = 0;
-
-  err = recvmsg(fd, &msgh, 0);
-  if (err < 0)
-    return err;
-
-  if (fromlen)
-    *fromlen = msgh.msg_namelen;
-
-  for (cmsg = CMSG_FIRSTHDR(&msgh);
-       cmsg != NULL;
-       cmsg = CMSG_NXTHDR(&msgh,cmsg)) {
+       struct msghdr msgh;
+       struct cmsghdr *cmsg;
+       struct iovec iov;
+       char cbuf[1000];
+       int err;
+
+       /*
+        * IP_PKTINFO / IP_RECVDSTADDR don't yield sin_port.
+        * Use getsockname() to get sin_port.
+        */
+       if (to) {
+               struct sockaddr_in si;
+               socklen_t si_len = sizeof(si);
+
+               memset(&si, 0, sizeof(si));
+               to->sin_family = AF_INET;
+
+               pim_socket_getsockname(fd, (struct sockaddr *)&si, &si_len);
+
+               to->sin_port = si.sin_port;
+               to->sin_addr = si.sin_addr;
+
+               if (tolen)
+                       *tolen = sizeof(si);
+       }
+
+       memset(&msgh, 0, sizeof(struct msghdr));
+       iov.iov_base = buf;
+       iov.iov_len = len;
+       msgh.msg_control = cbuf;
+       msgh.msg_controllen = sizeof(cbuf);
+       msgh.msg_name = from;
+       msgh.msg_namelen = fromlen ? *fromlen : 0;
+       msgh.msg_iov = &iov;
+       msgh.msg_iovlen = 1;
+       msgh.msg_flags = 0;
+
+       err = recvmsg(fd, &msgh, 0);
+       if (err < 0)
+               return err;
+
+       if (fromlen)
+               *fromlen = msgh.msg_namelen;
+
+       for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL;
+            cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
 
 #ifdef HAVE_IP_PKTINFO
-    if ((cmsg->cmsg_level == IPPROTO_IP) && (cmsg->cmsg_type == IP_PKTINFO)) {
-      struct in_pktinfo *i = (struct in_pktinfo *) CMSG_DATA(cmsg);
-      if (to)
-       ((struct sockaddr_in *) to)->sin_addr = i->ipi_addr;
-      if (tolen)
-       *tolen = sizeof(struct sockaddr_in);
-      if (ifindex)
-       *ifindex = i->ipi_ifindex;
-
-      break;
-    }
+               if ((cmsg->cmsg_level == IPPROTO_IP)
+                   && (cmsg->cmsg_type == IP_PKTINFO)) {
+                       struct in_pktinfo *i =
+                               (struct in_pktinfo *)CMSG_DATA(cmsg);
+                       if (to)
+                               ((struct sockaddr_in *)to)->sin_addr =
+                                       i->ipi_addr;
+                       if (tolen)
+                               *tolen = sizeof(struct sockaddr_in);
+                       if (ifindex)
+                               *ifindex = i->ipi_ifindex;
+
+                       break;
+               }
 #endif
 
 #ifdef HAVE_IP_RECVDSTADDR
-    if ((cmsg->cmsg_level == IPPROTO_IP) && (cmsg->cmsg_type == IP_RECVDSTADDR)) {
-      struct in_addr *i = (struct in_addr *) CMSG_DATA(cmsg);
-      if (to)
-       ((struct sockaddr_in *) to)->sin_addr = *i;
-      if (tolen)
-       *tolen = sizeof(struct sockaddr_in);
-
-      break;
-    }
+               if ((cmsg->cmsg_level == IPPROTO_IP)
+                   && (cmsg->cmsg_type == IP_RECVDSTADDR)) {
+                       struct in_addr *i = (struct in_addr *)CMSG_DATA(cmsg);
+                       if (to)
+                               ((struct sockaddr_in *)to)->sin_addr = *i;
+                       if (tolen)
+                               *tolen = sizeof(struct sockaddr_in);
+
+                       break;
+               }
 #endif
 
 #if defined(HAVE_IP_RECVIF) && defined(CMSG_IFINDEX)
-      if (cmsg->cmsg_type == IP_RECVIF)
-       if (ifindex)
-         *ifindex = CMSG_IFINDEX(cmsg);
+               if (cmsg->cmsg_type == IP_RECVIF)
+                       if (ifindex)
+                               *ifindex = CMSG_IFINDEX(cmsg);
 #endif
 
-  } /* for (cmsg) */
+       } /* for (cmsg) */
 
-  return err; /* len */
+       return err; /* len */
 }
 
 int pim_socket_mcastloop_get(int fd)
 {
-  int loop;
-  socklen_t loop_len = sizeof(loop);
-  
-  if (getsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP,
-                &loop, &loop_len)) {
-    int e = errno;
-    zlog_warn("Could not get Multicast Loopback Option on socket fd=%d: errno=%d: %s",
-             fd, errno, safe_strerror(errno));
-    errno = e;
-    return PIM_SOCK_ERR_LOOP;
-  }
-  
-  return loop;
+       int loop;
+       socklen_t loop_len = sizeof(loop);
+
+       if (getsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, &loop_len)) {
+               int e = errno;
+               zlog_warn(
+                       "Could not get Multicast Loopback Option on socket fd=%d: errno=%d: %s",
+                       fd, errno, safe_strerror(errno));
+               errno = e;
+               return PIM_SOCK_ERR_LOOP;
+       }
+
+       return loop;
 }
 
 int pim_socket_getsockname(int fd, struct sockaddr *name, socklen_t *namelen)
 {
-  if (getsockname(fd, name, namelen)) {
-    int e = errno;
-    zlog_warn("Could not get Socket Name for socket fd=%d: errno=%d: %s",
-             fd, errno, safe_strerror(errno));
-    errno = e;
-    return PIM_SOCK_ERR_NAME;
-  }
-
-  return PIM_SOCK_ERR_NONE;
+       if (getsockname(fd, name, namelen)) {
+               int e = errno;
+               zlog_warn(
+                       "Could not get Socket Name for socket fd=%d: errno=%d: %s",
+                       fd, errno, safe_strerror(errno));
+               errno = e;
+               return PIM_SOCK_ERR_NAME;
+       }
+
+       return PIM_SOCK_ERR_NONE;
 }