]> git.proxmox.com Git - mirror_frr.git/blobdiff - pimd/pim_mroute.c
Merge pull request #3502 from donaldsharp/socket_to_me_baby
[mirror_frr.git] / pimd / pim_mroute.c
index 8462a4fdf8d6a20ea311d007dd9238017677ef59..dc4c4402a1cc50c9fe92ef146af815a3bcc01db8 100644 (file)
@@ -25,6 +25,7 @@
 #include "vty.h"
 #include "plist.h"
 #include "sockopt.h"
+#include "lib_errors.h"
 
 #include "pimd.h"
 #include "pim_rpf.h"
@@ -47,54 +48,58 @@ static void mroute_read_on(struct pim_instance *pim);
 static int pim_mroute_set(struct pim_instance *pim, int enable)
 {
        int err;
-       int opt;
-       socklen_t opt_len = sizeof(opt);
+       int opt, data;
+       socklen_t data_len = sizeof(data);
        long flags;
 
        /*
         * We need to create the VRF table for the pim mroute_socket
         */
        if (pim->vrf_id != VRF_DEFAULT) {
-               if (pimd_privs.change(ZPRIVS_RAISE))
-                       zlog_err(
-                               "pim_mroute_socket_enable: could not raise privs, %s",
-                               safe_strerror(errno));
+               frr_elevate_privs(&pimd_privs) {
+
+                       data = pim->vrf->data.l.table_id;
+                       err = setsockopt(pim->mroute_socket, IPPROTO_IP,
+                                        MRT_TABLE,
+                                        &data, data_len);
+                       if (err) {
+                               zlog_warn(
+                                         "%s %s: failure: setsockopt(fd=%d,IPPROTO_IP, MRT_TABLE=%d): errno=%d: %s",
+                                         __FILE__, __PRETTY_FUNCTION__,
+                                         pim->mroute_socket, data, errno,
+                                         safe_strerror(errno));
+                               return -1;
+                       }
 
-               opt = pim->vrf->data.l.table_id;
-               err = setsockopt(pim->mroute_socket, IPPROTO_IP, MRT_TABLE,
-                                &opt, opt_len);
+               }
+       }
+
+       frr_elevate_privs(&pimd_privs) {
+               opt = enable ? MRT_INIT : MRT_DONE;
+               /*
+                * *BSD *cares* about what value we pass down
+                * here
+                */
+               data = 1;
+               err = setsockopt(pim->mroute_socket, IPPROTO_IP,
+                                opt, &data, data_len);
                if (err) {
                        zlog_warn(
-                               "%s %s: failure: setsockopt(fd=%d,IPPROTO_IP, MRT_TABLE=%d): errno=%d: %s",
-                               __FILE__, __PRETTY_FUNCTION__,
-                               pim->mroute_socket, opt, errno,
-                               safe_strerror(errno));
+                                 "%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,%s=%d): errno=%d: %s",
+                                 __FILE__, __PRETTY_FUNCTION__,
+                                 pim->mroute_socket,
+                                 enable ? "MRT_INIT" : "MRT_DONE", data, errno,
+                                 safe_strerror(errno));
                        return -1;
                }
-
-               if (pimd_privs.change(ZPRIVS_LOWER))
-                       zlog_err(
-                               "pim_mroute_socket_enable: could not lower privs, %s",
-                               safe_strerror(errno));
-       }
-
-       opt = enable ? MRT_INIT : MRT_DONE;
-       err = setsockopt(pim->mroute_socket, IPPROTO_IP, opt, &opt, opt_len);
-       if (err) {
-               zlog_warn(
-                       "%s %s: failure: setsockopt(fd=%d,IPPROTO_IP,%s=%d): errno=%d: %s",
-                       __FILE__, __PRETTY_FUNCTION__, pim->mroute_socket,
-                       enable ? "MRT_INIT" : "MRT_DONE", opt, errno,
-                       safe_strerror(errno));
-               return -1;
        }
 
 #if defined(HAVE_IP_PKTINFO)
        if (enable) {
                /* Linux and Solaris IP_PKTINFO */
-               opt = 1;
-               if (setsockopt(pim->mroute_socket, IPPROTO_IP, IP_PKTINFO, &opt,
-                              sizeof(opt))) {
+               data = 1;
+               if (setsockopt(pim->mroute_socket, IPPROTO_IP, IP_PKTINFO,
+                              &data, data_len)) {
                        zlog_warn(
                                "Could not set IP_PKTINFO on socket fd=%d: errno=%d: %s",
                                pim->mroute_socket, errno,
@@ -152,18 +157,18 @@ static int pim_mroute_msg_nocache(int fd, struct interface *ifp,
        struct pim_rpf *rpg;
        struct prefix_sg sg;
 
-       rpg = RP(pim_ifp->pim, msg->im_dst);
+       rpg = pim_ifp ? RP(pim_ifp->pim, msg->im_dst) : NULL;
        /*
         * If the incoming interface is unknown OR
         * the Interface type is SSM we don't need to
         * do anything here
         */
-       if ((pim_rpf_addr_is_inaddr_none(rpg)) || (!pim_ifp)
-           || (!(PIM_I_am_DR(pim_ifp)))) {
+       if (!rpg || pim_rpf_addr_is_inaddr_none(rpg)) {
                if (PIM_DEBUG_MROUTE_DETAIL)
                        zlog_debug(
-                               "%s: Interface is not configured correctly to handle incoming packet: Could be !DR, !pim_ifp, !SM, !RP",
+                               "%s: Interface is not configured correctly to handle incoming packet: Could be !pim_ifp, !SM, !RP",
                                __PRETTY_FUNCTION__);
+
                return 0;
        }
 
@@ -183,6 +188,26 @@ static int pim_mroute_msg_nocache(int fd, struct interface *ifp,
        sg.src = msg->im_src;
        sg.grp = msg->im_dst;
 
+       if (!(PIM_I_am_DR(pim_ifp))) {
+               struct channel_oil *c_oil;
+
+               if (PIM_DEBUG_MROUTE_DETAIL)
+                       zlog_debug("%s: Interface is not the DR blackholing incoming traffic for %s",
+                                  __PRETTY_FUNCTION__, pim_str_sg_dump(&sg));
+
+               /*
+                * We are not the DR, but we are still receiving packets
+                * Let's blackhole those packets for the moment
+                * As that they will be coming up to the cpu
+                * and causing us to consider them.
+                */
+               c_oil = pim_channel_oil_add(pim_ifp->pim, &sg,
+                                           pim_ifp->mroute_vif_index);
+               pim_mroute_add(c_oil, __PRETTY_FUNCTION__);
+
+               return 0;
+       }
+
        up = pim_upstream_find_or_add(&sg, ifp, PIM_UPSTREAM_FLAG_MASK_FHR,
                                      __PRETTY_FUNCTION__);
        if (!up) {
@@ -278,7 +303,7 @@ static int pim_mroute_msg_wholepkt(int fd, struct interface *ifp,
 
        pim_ifp = up->rpf.source_nexthop.interface->info;
 
-       rpg = RP(pim_ifp->pim, sg.grp);
+       rpg = pim_ifp ? RP(pim_ifp->pim, sg.grp) : NULL;
 
        if ((pim_rpf_addr_is_inaddr_none(rpg)) || (!pim_ifp)
            || (!(PIM_I_am_DR(pim_ifp)))) {
@@ -708,32 +733,29 @@ int pim_mroute_socket_enable(struct pim_instance *pim)
 {
        int fd;
 
-       if (pimd_privs.change(ZPRIVS_RAISE))
-               zlog_err("pim_mroute_socket_enable: could not raise privs, %s",
-                        safe_strerror(errno));
+       frr_elevate_privs(&pimd_privs) {
 
-       fd = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP);
+               fd = socket(AF_INET, SOCK_RAW, IPPROTO_IGMP);
 
-       if (fd < 0) {
-               zlog_warn("Could not create mroute socket: errno=%d: %s", errno,
-                         safe_strerror(errno));
-               return -2;
-       }
+               if (fd < 0) {
+                       zlog_warn("Could not create mroute socket: errno=%d: %s",
+                                 errno,
+                                 safe_strerror(errno));
+                       return -2;
+               }
 
 #ifdef SO_BINDTODEVICE
-       if (pim->vrf->vrf_id != VRF_DEFAULT
-           && setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, pim->vrf->name,
-                         strlen(pim->vrf->name))) {
-               zlog_warn("Could not setsockopt SO_BINDTODEVICE: %s",
-                         safe_strerror(errno));
-               close(fd);
-               return -3;
-       }
+               if (pim->vrf->vrf_id != VRF_DEFAULT
+                   && setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE,
+                                 pim->vrf->name, strlen(pim->vrf->name))) {
+                       zlog_warn("Could not setsockopt SO_BINDTODEVICE: %s",
+                                 safe_strerror(errno));
+                       close(fd);
+                       return -3;
+               }
 #endif
 
-       if (pimd_privs.change(ZPRIVS_LOWER))
-               zlog_err("pim_mroute_socket_enable: could not lower privs, %s",
-                        safe_strerror(errno));
+       }
 
        pim->mroute_socket = fd;
        if (pim_mroute_set(pim, 1)) {