vrrp_send_adv() 發送 vrrp 通告:
1、構造 vrrp 通告消息,存儲在 vrrp->send_buffer;
2、使用 sendmsg,向 單播地址、IPV4 組播地址:224.0.0.18 或 IPV6 組播地址:ff02::12 發送 vrrp 通告。
/* send VRRP advertisement */
void
vrrp_send_adv(vrrp_t * vrrp, uint8_t prio)
{
unicast_peer_t *peer;
element e;
#ifdef _HAVE_VRRP_IPVLAN_
if (__test_bit(VRRP_IPVLAN_BIT, &vrrp->vmac_flags) &&
vrrp->saddr.ss_family == AF_UNSPEC &&
vrrp->family == AF_INET6) {
if (!vrrp->ifp->sin6_addr.s6_addr32[0] &&
!vrrp->ifp->sin6_addr.s6_addr32[1] &&
!vrrp->ifp->sin6_addr.s6_addr32[2] &&
!vrrp->ifp->sin6_addr.s6_addr32[3]) {
log_message(LOG_INFO, "No address yet for %s", vrrp->ifp->ifname);
return;
}
inet_ip6tosockaddr(&vrrp->ifp->sin6_addr, &vrrp->saddr);
}
#endif
/* 構造包,包數據存儲:vrrp->send_buffer */
vrrp_update_pkt(vrrp, prio, NULL);
/* Send the packet, but don't log an error if it is a prio 0 message
* and the interface is down. */
if (LIST_ISEMPTY(vrrp->unicast_peer)) {
/* 向 ipv4/ipv6 組播 地址發送 vrrp 通告 */
if (vrrp_send_pkt(vrrp, NULL) == -1 &&
(prio != VRRP_PRIO_STOP || errno != ENETUNREACH || IF_FLAGS_UP(vrrp->ifp)))
log_message(LOG_INFO, "(%s): send advert error %d (%m)", vrrp->iname, errno);
}
else {
LIST_FOREACH(vrrp->unicast_peer, peer, e) {
/* 向各點播地址發送 vrrp 通告 */
if (vrrp->family == AF_INET)
vrrp_update_pkt(vrrp, prio, &peer->address);
if (vrrp_send_pkt(vrrp, peer) == -1 &&
(prio != VRRP_PRIO_STOP || errno != ENETUNREACH || IF_FLAGS_UP(vrrp->ifp)))
log_message(LOG_INFO, "(%s) Cant send advert to %s (%m)"
, vrrp->iname, inet_sockaddrtos(&peer->address));
}
}
++vrrp->stats->advert_sent;
}
static ssize_t
vrrp_send_pkt(vrrp_t * vrrp, unicast_peer_t *peer)
{
struct sockaddr_storage *src = &vrrp->saddr;
struct msghdr msg;
struct iovec iov;
char cbuf[256];
/* Build the message data */
memset(&msg, 0, sizeof(msg));
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
iov.iov_base = vrrp->send_buffer; /* 消息的內容 */
iov.iov_len = vrrp->send_buffer_size; /* 消息的長度 */
/* Unicast sending path */
if (peer && peer->address.ss_family == AF_INET) {
msg.msg_name = &peer->address; /* 數據包的目的地址:單播地址 */
msg.msg_namelen = sizeof(struct sockaddr_in); /* 目的地址的長度 */
} else if (peer && peer->address.ss_family == AF_INET6) {
msg.msg_name = &peer->address;
msg.msg_namelen = sizeof(struct sockaddr_in6);
vrrp_build_ancillary_data(&msg, cbuf, src, vrrp);
} else if (vrrp->family == AF_INET) { /* Multicast sending path */
msg.msg_name = &global_data->vrrp_mcast_group4; /* IPV4 組播地址:224.0.0.18 */
msg.msg_namelen = sizeof(struct sockaddr_in);
} else if (vrrp->family == AF_INET6) {
msg.msg_name = &global_data->vrrp_mcast_group6; /* IPV6 組播地址:ff02::12 */
msg.msg_namelen = sizeof(struct sockaddr_in6);
vrrp_build_ancillary_data(&msg, cbuf, src, vrrp);
}
#ifdef _CHECKSUM_DEBUG_
if (vrrp->family == AF_INET && do_checksum_debug)
check_tx_checksum(vrrp, peer);
#endif
/* Send the packet */
return sendmsg(vrrp->sockets->fd_out, &msg, (peer) ? 0 : MSG_DONTROUTE);
}