static void pim_msdp_sa_peer_ip_set(struct pim_msdp_sa *sa, struct pim_msdp_peer *mp, struct in_addr rp) { struct pim_msdp_peer *old_mp; /* optimize the "no change" case as it will happen * frequently/periodically */ if (mp && (sa->peer.s_addr == mp->peer.s_addr)) { return; } /* any time the peer ip changes also update the rp address */ if (PIM_INADDR_ISNOT_ANY(sa->peer)) { old_mp = pim_msdp_peer_find(sa->pim, sa->peer); if (old_mp && old_mp->sa_cnt) { --old_mp->sa_cnt; } } if (mp) { ++mp->sa_cnt; sa->peer = mp->peer; } else { sa->peer.s_addr = PIM_NET_INADDR_ANY; } sa->rp = rp; }
/* add peer configuration if it doesn't already exist */ enum pim_msdp_err pim_msdp_peer_add(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; if (mp_p) { *mp_p = NULL; } if (peer_addr.s_addr == local_addr.s_addr) { /* skip session setup if config is invalid */ if (PIM_DEBUG_MSDP_EVENTS) { char peer_str[INET_ADDRSTRLEN]; pim_inet4_dump("<peer?>", peer_addr, peer_str, sizeof(peer_str)); zlog_debug("%s add skipped as DIP=SIP", peer_str); } return PIM_MSDP_ERR_SIP_EQ_DIP; } mp = pim_msdp_peer_find(pim, peer_addr); if (mp) { if (mp_p) { *mp_p = mp; } return PIM_MSDP_ERR_PEER_EXISTS; } return pim_msdp_peer_new(pim, peer_addr, local_addr, mesh_group_name, mp_p); }
enum pim_msdp_err pim_msdp_peer_del(struct pim_instance *pim, struct in_addr peer_addr) { struct pim_msdp_peer *mp; mp = pim_msdp_peer_find(pim, peer_addr); if (!mp) { return PIM_MSDP_ERR_NO_PEER; } return pim_msdp_peer_do_del(mp); }
/* 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; }