#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"
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));
}
}
}
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;
/* 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 = NULL;
- thread_add_read(master, pim_msdp_sock_accept, listener, accept_sock,
- &listener->thread);
+ 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",
- sockunion2str(&su, buf, SU_ADDRSTRLEN));
+ flog_err(EC_PIM_MSDP_PACKET,
+ "msdp peer connection refused from %s",
+ sockunion2str(&su, buf, SU_ADDRSTRLEN));
}
close(msdp_sock);
return -1;
* 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));
}
}
/* 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;
}
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;
}
listener->fd = sock;
memcpy(&listener->su, &sin, socklen);
listener->thread = NULL;
- thread_add_read(msdp->master, pim_msdp_sock_accept, listener, sock,
+ 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;
}
* 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);
}
/* 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 */
/* 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;