Example #1
0
/* 11.2.A1: create a new peer and transition state to listen or connecting */
static enum pim_msdp_err pim_msdp_peer_new(struct pim_instance *pim,
					   struct in_addr peer_addr,
					   struct in_addr local_addr,
					   const char *mesh_group_name,
					   struct pim_msdp_peer **mp_p)
{
	struct pim_msdp_peer *mp;

	pim_msdp_enable(pim);

	mp = XCALLOC(MTYPE_PIM_MSDP_PEER, sizeof(*mp));

	mp->pim = pim;
	mp->peer = peer_addr;
	pim_inet4_dump("<peer?>", mp->peer, mp->key_str, sizeof(mp->key_str));
	pim_msdp_addr2su(&mp->su_peer, mp->peer);
	mp->local = local_addr;
	/* XXX: originator_id setting needs to move to the mesh group */
	pim->msdp.originator_id = local_addr;
	pim_msdp_addr2su(&mp->su_local, mp->local);
	mp->mesh_group_name = XSTRDUP(MTYPE_PIM_MSDP_MG_NAME, mesh_group_name);
	mp->state = PIM_MSDP_INACTIVE;
	mp->fd = -1;
	strlcpy(mp->last_reset, "-", sizeof(mp->last_reset));
	/* higher IP address is listener */
	if (ntohl(mp->local.s_addr) > ntohl(mp->peer.s_addr)) {
		mp->flags |= PIM_MSDP_PEERF_LISTENER;
	}

	/* setup packet buffers */
	mp->ibuf = stream_new(PIM_MSDP_MAX_PACKET_SIZE);
	mp->obuf = stream_fifo_new();

	/* insert into misc tables for easy access */
	mp = hash_get(pim->msdp.peer_hash, mp, hash_alloc_intern);
	listnode_add_sort(pim->msdp.peer_list, mp);

	if (PIM_DEBUG_MSDP_EVENTS) {
		zlog_debug("MSDP peer %s created", mp->key_str);

		pim_msdp_peer_state_chg_log(mp);
	}

	/* fireup the connect state machine */
	if (PIM_MSDP_PEER_IS_LISTENER(mp)) {
		pim_msdp_peer_listen(mp);
	} else {
		pim_msdp_peer_connect(mp);
	}
	if (mp_p) {
		*mp_p = mp;
	}
	return PIM_MSDP_ERR_NONE;
}
Example #2
0
/* RFC-3618:Sec-5.6 - stop the peer tcp connection and startover */
void pim_msdp_peer_reset_tcp_conn(struct pim_msdp_peer *mp, const char *rc_str)
{
	if (PIM_DEBUG_EVENTS) {
		zlog_debug("MSDP peer %s tcp reset %s", mp->key_str, rc_str);
		snprintf(mp->last_reset, sizeof(mp->last_reset), "%s", rc_str);
	}

	/* close the connection and transition to listening or connecting */
	pim_msdp_peer_stop_tcp_conn(mp, true /* chg_state */);
	if (PIM_MSDP_PEER_IS_LISTENER(mp)) {
		pim_msdp_peer_listen(mp);
	} else {
		pim_msdp_peer_connect(mp);
	}
}
Example #3
0
/* RFC-3618:Sec-5.6 - connection retry on active peer */
static int pim_msdp_peer_cr_timer_cb(struct thread *t)
{
	struct pim_msdp_peer *mp;

	mp = THREAD_ARG(t);

	if (PIM_DEBUG_MSDP_EVENTS) {
		pim_msdp_peer_timer_expiry_log(mp, "connect-retry");
	}

	if (mp->state != PIM_MSDP_CONNECTING || PIM_MSDP_PEER_IS_LISTENER(mp)) {
		return 0;
	}

	pim_msdp_peer_active_connect(mp);
	return 0;
}
Example #4
0
/* passive peer socket accept */
static int pim_msdp_sock_accept(struct thread *thread)
{
	union sockunion su;
	struct pim_instance *pim = THREAD_ARG(thread);
	int accept_sock;
	int msdp_sock;
	struct pim_msdp_peer *mp;
	char buf[SU_ADDRSTRLEN];

	sockunion_init(&su);

	/* re-register accept thread */
	accept_sock = THREAD_FD(thread);
	if (accept_sock < 0) {
		flog_err(LIB_ERR_DEVELOPMENT,
			  "accept_sock is negative value %d", accept_sock);
		return -1;
	}
	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) {
		flog_err_sys(LIB_ERR_SOCKET, "pim_msdp_sock_accept failed (%s)",
			     safe_strerror(errno));
		return -1;
	}

	/* see if have peer config for this */
	mp = pim_msdp_peer_find(pim, su.sin.sin_addr);
	if (!mp || !PIM_MSDP_PEER_IS_LISTENER(mp)) {
		++pim->msdp.rejected_accepts;
		if (PIM_DEBUG_MSDP_EVENTS) {
			flog_err(PIM_ERR_MSDP_PACKET,
				  "msdp peer connection refused from %s",
				  sockunion2str(&su, buf, SU_ADDRSTRLEN));
		}
		close(msdp_sock);
		return -1;
	}

	if (PIM_DEBUG_MSDP_INTERNAL) {
		zlog_debug("MSDP peer %s accept success%s", mp->key_str,
			   mp->fd >= 0 ? "(dup)" : "");
	}

	/* if we have an existing connection we need to kill that one
	 * with this one */
	if (mp->fd >= 0) {
		if (PIM_DEBUG_MSDP_EVENTS) {
			zlog_notice(
				"msdp peer new connection from %s stop old connection",
				sockunion2str(&su, buf, SU_ADDRSTRLEN));
		}
		pim_msdp_peer_stop_tcp_conn(mp, true /* chg_state */);
	}
	mp->fd = msdp_sock;
	set_nonblocking(mp->fd);
	pim_msdp_update_sock_send_buffer_size(mp->fd);
	pim_msdp_peer_established(mp);
	return 0;
}