]> git.proxmox.com Git - mirror_frr.git/blobdiff - pimd/pim_msdp_socket.c
zebra: Allow ns delete to happen after under/over flow checks
[mirror_frr.git] / pimd / pim_msdp_socket.c
index 0ff2016ba7f879dcb6b76b0fddf841196b591765..7997d3138adf0380dd4895b1e97e5a31c4a3114a 100644 (file)
  * 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
+ * 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 <lib/sockunion.h>
 #include <lib/thread.h>
 #include <lib/vty.h>
+#include <lib/if.h>
+#include <lib/vrf.h>
+#include <lib/lib_errors.h>
 
 #include "pimd.h"
+#include "pim_sock.h"
+#include "pim_errors.h"
 
 #include "pim_msdp.h"
 #include "pim_msdp_socket.h"
@@ -39,16 +43,18 @@ static void pim_msdp_update_sock_send_buffer_size(int fd)
        socklen_t optlen = sizeof(optval);
 
        if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &optval, &optlen) < 0) {
-               zlog_err("getsockopt of SO_SNDBUF failed %s\n",
-                        safe_strerror(errno));
+               flog_err_sys(EC_LIB_SOCKET,
+                            "getsockopt of SO_SNDBUF failed %s\n",
+                            safe_strerror(errno));
                return;
        }
 
        if (optval < size) {
                if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size))
                    < 0) {
-                       zlog_err("Couldn't increase send buffer: %s\n",
-                                safe_strerror(errno));
+                       flog_err_sys(EC_LIB_SOCKET,
+                                    "Couldn't increase send buffer: %s\n",
+                                    safe_strerror(errno));
                }
        }
 }
@@ -57,7 +63,7 @@ static void pim_msdp_update_sock_send_buffer_size(int fd)
 static int pim_msdp_sock_accept(struct thread *thread)
 {
        union sockunion su;
-       struct pim_msdp_listener *listener = THREAD_ARG(thread);
+       struct pim_instance *pim = THREAD_ARG(thread);
        int accept_sock;
        int msdp_sock;
        struct pim_msdp_peer *mp;
@@ -68,26 +74,29 @@ static int pim_msdp_sock_accept(struct thread *thread)
        /* re-register accept thread */
        accept_sock = THREAD_FD(thread);
        if (accept_sock < 0) {
-               zlog_err("accept_sock is negative value %d", accept_sock);
+               flog_err(EC_LIB_DEVELOPMENT, "accept_sock is negative value %d",
+                        accept_sock);
                return -1;
        }
-       listener->thread = thread_add_read(master, pim_msdp_sock_accept,
-                                          listener, accept_sock);
+       pim->msdp.listener.thread = NULL;
+       thread_add_read(master, pim_msdp_sock_accept, pim, accept_sock,
+                       &pim->msdp.listener.thread);
 
        /* accept client connection. */
        msdp_sock = sockunion_accept(accept_sock, &su);
        if (msdp_sock < 0) {
-               zlog_err("pim_msdp_sock_accept failed (%s)",
-                        safe_strerror(errno));
+               flog_err_sys(EC_LIB_SOCKET, "pim_msdp_sock_accept failed (%s)",
+                            safe_strerror(errno));
                return -1;
        }
 
        /* see if have peer config for this */
-       mp = pim_msdp_peer_find(su.sin.sin_addr);
+       mp = pim_msdp_peer_find(pim, su.sin.sin_addr);
        if (!mp || !PIM_MSDP_PEER_IS_LISTENER(mp)) {
-               ++msdp->rejected_accepts;
+               ++pim->msdp.rejected_accepts;
                if (PIM_DEBUG_MSDP_EVENTS) {
-                       zlog_err("msdp peer connection refused from %s",
+                       flog_err(EC_PIM_MSDP_PACKET,
+                                "msdp peer connection refused from %s",
                                 sockunion2str(&su, buf, SU_ADDRSTRLEN));
                }
                close(msdp_sock);
@@ -103,7 +112,7 @@ static int pim_msdp_sock_accept(struct thread *thread)
         * with this one */
        if (mp->fd >= 0) {
                if (PIM_DEBUG_MSDP_EVENTS) {
-                       zlog_err(
+                       zlog_notice(
                                "msdp peer new connection from %s stop old connection",
                                sockunion2str(&su, buf, SU_ADDRSTRLEN));
                }
@@ -117,22 +126,22 @@ static int pim_msdp_sock_accept(struct thread *thread)
 }
 
 /* global listener for the MSDP well know TCP port */
-int pim_msdp_sock_listen(void)
+int pim_msdp_sock_listen(struct pim_instance *pim)
 {
        int sock;
        int socklen;
        struct sockaddr_in sin;
        int rc;
-       struct pim_msdp_listener *listener = &msdp->listener;
+       struct pim_msdp_listener *listener = &pim->msdp.listener;
 
-       if (msdp->flags & PIM_MSDPF_LISTENER) {
+       if (pim->msdp.flags & PIM_MSDPF_LISTENER) {
                /* listener already setup */
                return 0;
        }
 
        sock = socket(AF_INET, SOCK_STREAM, 0);
        if (sock < 0) {
-               zlog_err("socket: %s", safe_strerror(errno));
+               flog_err_sys(EC_LIB_SOCKET, "socket: %s", safe_strerror(errno));
                return sock;
        }
 
@@ -147,29 +156,42 @@ int pim_msdp_sock_listen(void)
        sockopt_reuseaddr(sock);
        sockopt_reuseport(sock);
 
-       if (pimd_privs.change(ZPRIVS_RAISE)) {
-               zlog_err("pim_msdp_socket: could not raise privs, %s",
-                        safe_strerror(errno));
+       if (pim->vrf_id != VRF_DEFAULT) {
+               struct interface *ifp =
+                       if_lookup_by_name(pim->vrf->name, pim->vrf_id);
+               if (!ifp) {
+                       flog_err(EC_LIB_INTERFACE,
+                                "%s: Unable to lookup vrf interface: %s",
+                                __PRETTY_FUNCTION__, pim->vrf->name);
+                       close(sock);
+                       return -1;
+               }
+               if (pim_socket_bind(sock, ifp)) {
+                       flog_err_sys(EC_LIB_SOCKET,
+                                    "%s: Unable to bind to socket: %s",
+                                    __PRETTY_FUNCTION__, safe_strerror(errno));
+                       close(sock);
+                       return -1;
+               }
        }
 
-       /* bind to well known TCP port */
-       rc = bind(sock, (struct sockaddr *)&sin, socklen);
-
-       if (pimd_privs.change(ZPRIVS_LOWER)) {
-               zlog_err("pim_msdp_socket: could not lower privs, %s",
-                        safe_strerror(errno));
+       frr_elevate_privs(&pimd_privs) {
+               /* bind to well known TCP port */
+               rc = bind(sock, (struct sockaddr *)&sin, socklen);
        }
 
        if (rc < 0) {
-               zlog_err("pim_msdp_socket bind to port %d: %s",
-                        ntohs(sin.sin_port), safe_strerror(errno));
+               flog_err_sys(EC_LIB_SOCKET,
+                            "pim_msdp_socket bind to port %d: %s",
+                            ntohs(sin.sin_port), safe_strerror(errno));
                close(sock);
                return rc;
        }
 
        rc = listen(sock, 3 /* backlog */);
        if (rc < 0) {
-               zlog_err("pim_msdp_socket listen: %s", safe_strerror(errno));
+               flog_err_sys(EC_LIB_SOCKET, "pim_msdp_socket listen: %s",
+                            safe_strerror(errno));
                close(sock);
                return rc;
        }
@@ -177,10 +199,11 @@ int pim_msdp_sock_listen(void)
        /* add accept thread */
        listener->fd = sock;
        memcpy(&listener->su, &sin, socklen);
-       listener->thread = thread_add_read(msdp->master, pim_msdp_sock_accept,
-                                          listener, sock);
+       listener->thread = NULL;
+       thread_add_read(pim->msdp.master, pim_msdp_sock_accept, pim, sock,
+                       &listener->thread);
 
-       msdp->flags |= PIM_MSDPF_LISTENER;
+       pim->msdp.flags |= PIM_MSDPF_LISTENER;
        return 0;
 }
 
@@ -198,7 +221,7 @@ int pim_msdp_sock_connect(struct pim_msdp_peer *mp)
         * with this one */
        if (mp->fd >= 0) {
                if (PIM_DEBUG_MSDP_EVENTS) {
-                       zlog_err(
+                       zlog_notice(
                                "msdp duplicate connect to %s nuke old connection",
                                mp->key_str);
                }
@@ -208,11 +231,31 @@ int pim_msdp_sock_connect(struct pim_msdp_peer *mp)
        /* Make socket for the peer. */
        mp->fd = sockunion_socket(&mp->su_peer);
        if (mp->fd < 0) {
-               zlog_err("pim_msdp_socket socket failure: %s",
-                        safe_strerror(errno));
+               flog_err_sys(EC_LIB_SOCKET,
+                            "pim_msdp_socket socket failure: %s",
+                            safe_strerror(errno));
                return -1;
        }
 
+       if (mp->pim->vrf_id != VRF_DEFAULT) {
+               struct interface *ifp =
+                       if_lookup_by_name(mp->pim->vrf->name, mp->pim->vrf_id);
+               if (!ifp) {
+                       flog_err(EC_LIB_INTERFACE,
+                                "%s: Unable to lookup vrf interface: %s",
+                                __PRETTY_FUNCTION__, mp->pim->vrf->name);
+                       return -1;
+               }
+               if (pim_socket_bind(mp->fd, ifp)) {
+                       flog_err_sys(EC_LIB_SOCKET,
+                                    "%s: Unable to bind to socket: %s",
+                                    __PRETTY_FUNCTION__, safe_strerror(errno));
+                       close(mp->fd);
+                       mp->fd = -1;
+                       return -1;
+               }
+       }
+
        set_nonblocking(mp->fd);
 
        /* Set socket send buffer size */
@@ -223,8 +266,9 @@ int pim_msdp_sock_connect(struct pim_msdp_peer *mp)
        /* source bind */
        rc = sockunion_bind(mp->fd, &mp->su_local, 0, &mp->su_local);
        if (rc < 0) {
-               zlog_err("pim_msdp_socket connect bind failure: %s",
-                        safe_strerror(errno));
+               flog_err_sys(EC_LIB_SOCKET,
+                            "pim_msdp_socket connect bind failure: %s",
+                            safe_strerror(errno));
                close(mp->fd);
                mp->fd = -1;
                return rc;