#include "privs.h"
#include "vrf.h"
#include "ns.h"
+#include "lib_errors.h"
#include "zebra/interface.h"
#include "zebra/rtadv.h"
#include "zebra/zapi_msg.h"
#include "zebra/zebra_ns.h"
#include "zebra/zebra_vrf.h"
+#include "zebra/zebra_errors.h"
+#include "zebra/zebra_router.h"
extern struct zebra_privs_t zserv_privs;
if (ret < 0)
return ret;
- for (cmsgptr = ZCMSG_FIRSTHDR(&msg); cmsgptr != NULL;
+ for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL;
cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
/* I want interface index which this packet comes from. */
if (cmsgptr->cmsg_level == IPPROTO_IPV6
adata = calloc(1, CMSG_SPACE(sizeof(struct in6_pktinfo)));
if (adata == NULL) {
- zlog_err(
+ zlog_debug(
"rtadv_send_packet: can't malloc control data");
exit(-1);
}
iov.iov_base = buf;
iov.iov_len = len;
- cmsgptr = ZCMSG_FIRSTHDR(&msg);
+ cmsgptr = CMSG_FIRSTHDR(&msg);
cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
cmsgptr->cmsg_level = IPPROTO_IPV6;
cmsgptr->cmsg_type = IPV6_PKTINFO;
ret = sendmsg(sock, &msg, 0);
if (ret < 0) {
- zlog_err("%s(%u): Tx RA failed, socket %u error %d (%s)",
- ifp->name, ifp->ifindex, sock, errno,
- safe_strerror(errno));
+ flog_err_sys(EC_LIB_SOCKET,
+ "%s(%u): Tx RA failed, socket %u error %d (%s)",
+ ifp->name, ifp->ifindex, sock, errno,
+ safe_strerror(errno));
} else
zif->ra_sent++;
}
struct zebra_if *zif;
int period;
- zns->rtadv.ra_timer = NULL;
- if (zns->rtadv.adv_msec_if_count == 0) {
+ zrouter.rtadv.ra_timer = NULL;
+ if (zrouter.rtadv.adv_msec_if_count == 0) {
period = 1000; /* 1 s */
rtadv_event(zns, RTADV_TIMER, 1 /* 1 s */);
} else {
"Fast RA Rexmit on interface %s",
ifp->name);
- rtadv_send_packet(zns->rtadv.sock, ifp);
+ rtadv_send_packet(zrouter.rtadv.sock,
+ ifp);
} else {
zif->rtadv.AdvIntervalTimer -= period;
if (zif->rtadv.AdvIntervalTimer <= 0) {
zif->rtadv
.MaxRtrAdvInterval;
rtadv_send_packet(
- zns->rtadv.sock, ifp);
+ zrouter.rtadv.sock,
+ ifp);
}
}
}
struct zebra_ns *zns = zvrf->zns;
assert(zns);
- rtadv_send_packet(zns->rtadv.sock, ifp);
+ rtadv_send_packet(zrouter.rtadv.sock, ifp);
+}
+
+/*
+ * This function processes optional attributes off of
+ * end of a RA packet received. At this point in
+ * time we only care about this in one situation
+ * which is when a interface does not have a LL
+ * v6 address. We still need to be able to install
+ * the mac address for v4 to v6 resolution
+ */
+static void rtadv_process_optional(uint8_t *optional, unsigned int len,
+ struct interface *ifp,
+ struct sockaddr_in6 *addr)
+{
+ char *mac;
+
+ while (len > 0) {
+ struct nd_opt_hdr *opt_hdr = (struct nd_opt_hdr *)optional;
+
+ switch(opt_hdr->nd_opt_type) {
+ case ND_OPT_SOURCE_LINKADDR:
+ mac = (char *)(optional+2);
+ if_nbr_mac_to_ipv4ll_neigh_update(ifp, mac,
+ &addr->sin6_addr, 1);
+ break;
+ default:
+ break;
+ }
+
+ len -= 8 * opt_hdr->nd_opt_len;
+ optional += 8 * opt_hdr->nd_opt_len;
+ }
}
static void rtadv_process_advert(uint8_t *msg, unsigned int len,
inet_ntop(AF_INET6, &addr->sin6_addr, addr_str, INET6_ADDRSTRLEN);
if (len < sizeof(struct nd_router_advert)) {
- zlog_warn("%s(%u): Rx RA with invalid length %d from %s",
- ifp->name, ifp->ifindex, len, addr_str);
+ if (IS_ZEBRA_DEBUG_PACKET)
+ zlog_debug("%s(%u): Rx RA with invalid length %d from %s",
+ ifp->name, ifp->ifindex, len, addr_str);
return;
}
+
if (!IN6_IS_ADDR_LINKLOCAL(&addr->sin6_addr)) {
- zlog_warn(
- "%s(%u): Rx RA with non-linklocal source address from %s",
- ifp->name, ifp->ifindex, addr_str);
+ rtadv_process_optional(msg + sizeof(struct nd_router_advert),
+ len - sizeof(struct nd_router_advert),
+ ifp, addr);
+ if (IS_ZEBRA_DEBUG_PACKET)
+ zlog_debug("%s(%u): Rx RA with non-linklocal source address from %s",
+ ifp->name, ifp->ifindex, addr_str);
return;
}
if ((radvert->nd_ra_curhoplimit && zif->rtadv.AdvCurHopLimit)
&& (radvert->nd_ra_curhoplimit != zif->rtadv.AdvCurHopLimit)) {
- zlog_warn(
+ flog_warn(
+ EC_ZEBRA_RA_PARAM_MISMATCH,
"%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s",
ifp->name, ifp->ifindex, addr_str);
}
if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_MANAGED)
&& !zif->rtadv.AdvManagedFlag) {
- zlog_warn(
+ flog_warn(
+ EC_ZEBRA_RA_PARAM_MISMATCH,
"%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s",
ifp->name, ifp->ifindex, addr_str);
}
if ((radvert->nd_ra_flags_reserved & ND_RA_FLAG_OTHER)
&& !zif->rtadv.AdvOtherConfigFlag) {
- zlog_warn(
+ flog_warn(
+ EC_ZEBRA_RA_PARAM_MISMATCH,
"%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s",
ifp->name, ifp->ifindex, addr_str);
}
if ((radvert->nd_ra_reachable && zif->rtadv.AdvReachableTime)
&& (ntohl(radvert->nd_ra_reachable)
!= zif->rtadv.AdvReachableTime)) {
- zlog_warn(
+ flog_warn(
+ EC_ZEBRA_RA_PARAM_MISMATCH,
"%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s",
ifp->name, ifp->ifindex, addr_str);
}
if ((radvert->nd_ra_retransmit && zif->rtadv.AdvRetransTimer)
&& (ntohl(radvert->nd_ra_retransmit)
!= (unsigned int)zif->rtadv.AdvRetransTimer)) {
- zlog_warn(
+ flog_warn(
+ EC_ZEBRA_RA_PARAM_MISMATCH,
"%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s",
ifp->name, ifp->ifindex, addr_str);
}
/* Create entry for neighbor if not known. */
p.family = AF_INET6;
- IPV6_ADDR_COPY(&p.u.prefix, &addr->sin6_addr);
+ IPV6_ADDR_COPY(&p.u.prefix6, &addr->sin6_addr);
p.prefixlen = IPV6_MAX_PREFIXLEN;
if (!nbr_connected_check(ifp, &p))
/* Interface search. */
ifp = if_lookup_by_index_per_ns(zns, ifindex);
if (ifp == NULL) {
- zlog_warn("RA/RS received on unknown IF %u from %s", ifindex,
+ flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE,
+ "RA/RS received on unknown IF %u from %s", ifindex,
addr_str);
return;
}
/* ICMP message length check. */
if (len < sizeof(struct icmp6_hdr)) {
- zlog_warn("%s(%u): Rx RA with Invalid ICMPV6 packet length %d",
- ifp->name, ifp->ifindex, len);
+ zlog_debug("%s(%u): Rx RA with Invalid ICMPV6 packet length %d",
+ ifp->name, ifp->ifindex, len);
return;
}
/* ICMP message type check. */
if (icmph->icmp6_type != ND_ROUTER_SOLICIT
&& icmph->icmp6_type != ND_ROUTER_ADVERT) {
- zlog_warn("%s(%u): Rx RA - Unwanted ICMPV6 message type %d",
- ifp->name, ifp->ifindex, icmph->icmp6_type);
+ zlog_debug("%s(%u): Rx RA - Unwanted ICMPV6 message type %d",
+ ifp->name, ifp->ifindex, icmph->icmp6_type);
return;
}
/* Hoplimit check. */
if (hoplimit >= 0 && hoplimit != 255) {
- zlog_warn("%s(%u): Rx RA - Invalid hoplimit %d", ifp->name,
- ifp->ifindex, hoplimit);
+ zlog_debug("%s(%u): Rx RA - Invalid hoplimit %d", ifp->name,
+ ifp->ifindex, hoplimit);
return;
}
struct zebra_ns *zns = THREAD_ARG(thread);
sock = THREAD_FD(thread);
- zns->rtadv.ra_read = NULL;
+ zrouter.rtadv.ra_read = NULL;
/* Register myself. */
rtadv_event(zns, RTADV_READ, sock);
&hoplimit);
if (len < 0) {
- zlog_warn("RA/RS recv failed, socket %u error %s", sock,
- safe_strerror(errno));
+ flog_err_sys(EC_LIB_SOCKET,
+ "RA/RS recv failed, socket %u error %s", sock,
+ safe_strerror(errno));
return len;
}
static int rtadv_make_socket(ns_id_t ns_id)
{
- int sock;
+ int sock = -1;
int ret = 0;
struct icmp6_filter filter;
- if (zserv_privs.change(ZPRIVS_RAISE))
- zlog_err("rtadv_make_socket: could not raise privs, %s",
- safe_strerror(errno));
+ frr_elevate_privs(&zserv_privs) {
- sock = ns_socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6, ns_id);
+ sock = ns_socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6, ns_id);
- if (zserv_privs.change(ZPRIVS_LOWER))
- zlog_err("rtadv_make_socket: could not lower privs, %s",
- safe_strerror(errno));
+ }
if (sock < 0) {
return -1;
if (zif->rtadv.AdvSendAdvertisements) {
zif->rtadv.AdvSendAdvertisements = 0;
zif->rtadv.AdvIntervalTimer = 0;
- zns->rtadv.adv_if_count--;
+ zrouter.rtadv.adv_if_count--;
- if_leave_all_router(zns->rtadv.sock, ifp);
+ if_leave_all_router(zrouter.rtadv.sock, ifp);
- if (zns->rtadv.adv_if_count == 0)
+ if (zrouter.rtadv.adv_if_count == 0)
rtadv_event(zns, RTADV_STOP, 0);
}
} else {
if (!zif->rtadv.AdvSendAdvertisements) {
zif->rtadv.AdvSendAdvertisements = 1;
zif->rtadv.AdvIntervalTimer = 0;
- zns->rtadv.adv_if_count++;
+ zrouter.rtadv.adv_if_count++;
if (zif->rtadv.MaxRtrAdvInterval >= 1000) {
/* Enable Fast RA only when RA interval is in
RTADV_NUM_FAST_REXMITS;
}
- if_join_all_router(zns->rtadv.sock, ifp);
+ if_join_all_router(zrouter.rtadv.sock, ifp);
- if (zns->rtadv.adv_if_count == 1)
- rtadv_event(zns, RTADV_START, zns->rtadv.sock);
+ if (zrouter.rtadv.adv_if_count == 1)
+ rtadv_event(zns, RTADV_START,
+ zrouter.rtadv.sock);
}
}
}
/* Locate interface and check VRF match. */
ifp = if_lookup_by_index_per_ns(zebra_ns_lookup(NS_DEFAULT), ifindex);
if (!ifp) {
- zlog_warn("%u: IF %u RA %s client %s - interface unknown",
+ flog_warn(EC_ZEBRA_UNKNOWN_INTERFACE,
+ "%u: IF %u RA %s client %s - interface unknown",
zvrf_id(zvrf), ifindex, enable ? "enable" : "disable",
zebra_route_string(client->proto));
return;
}
if (ifp->vrf_id != zvrf_id(zvrf)) {
- zlog_warn("%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
- zvrf_id(zvrf), ifindex, enable ? "enable" : "disable",
- zebra_route_string(client->proto), ifp->vrf_id);
+ zlog_debug(
+ "%u: IF %u RA %s client %s - VRF mismatch, IF VRF %u",
+ zvrf_id(zvrf), ifindex, enable ? "enable" : "disable",
+ zebra_route_string(client->proto), ifp->vrf_id);
return;
}
VTY_DECLVAR_CONTEXT(interface, ifp);
unsigned interval;
struct zebra_if *zif = ifp->info;
- struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
- struct zebra_ns *zns;
- zns = zvrf->zns;
interval = strtoul(argv[idx_number]->arg, NULL, 10);
if ((zif->rtadv.AdvDefaultLifetime != -1
&& interval > (unsigned)zif->rtadv.AdvDefaultLifetime * 1000)) {
}
if (zif->rtadv.MaxRtrAdvInterval % 1000)
- zns->rtadv.adv_msec_if_count--;
+ zrouter.rtadv.adv_msec_if_count--;
if (interval % 1000)
- zns->rtadv.adv_msec_if_count++;
+ zrouter.rtadv.adv_msec_if_count++;
SET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
zif->rtadv.MaxRtrAdvInterval = interval;
VTY_DECLVAR_CONTEXT(interface, ifp);
unsigned interval;
struct zebra_if *zif = ifp->info;
- struct zebra_vrf *zvrf = vrf_info_lookup(ifp->vrf_id);
- struct zebra_ns *zns;
- zns = zvrf->zns;
interval = strtoul(argv[idx_number]->arg, NULL, 10);
if ((zif->rtadv.AdvDefaultLifetime != -1
&& interval > (unsigned)zif->rtadv.AdvDefaultLifetime)) {
}
if (zif->rtadv.MaxRtrAdvInterval % 1000)
- zns->rtadv.adv_msec_if_count--;
+ zrouter.rtadv.adv_msec_if_count--;
/* convert to milliseconds */
interval = interval * 1000;
{
VTY_DECLVAR_CONTEXT(interface, ifp);
struct zebra_if *zif = ifp->info;
- struct zebra_vrf *zvrf;
- struct zebra_ns *zns;
-
- zvrf = vrf_info_lookup(ifp->vrf_id);
- zns = zvrf->zns;
if (zif->rtadv.MaxRtrAdvInterval % 1000)
- zns->rtadv.adv_msec_if_count--;
+ zrouter.rtadv.adv_msec_if_count--;
UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
static void rtadv_event(struct zebra_ns *zns, enum rtadv_event event, int val)
{
- struct rtadv *rtadv = &zns->rtadv;
+ struct rtadv *rtadv = &zrouter.rtadv;
switch (event) {
case RTADV_START:
void rtadv_init(struct zebra_ns *zns)
{
- zns->rtadv.sock = rtadv_make_socket(zns->ns_id);
+ zrouter.rtadv.sock = rtadv_make_socket(zns->ns_id);
}
void rtadv_terminate(struct zebra_ns *zns)
{
rtadv_event(zns, RTADV_STOP, 0);
- if (zns->rtadv.sock >= 0) {
- close(zns->rtadv.sock);
- zns->rtadv.sock = -1;
+ if (zrouter.rtadv.sock >= 0) {
+ close(zrouter.rtadv.sock);
+ zrouter.rtadv.sock = -1;
}
- zns->rtadv.adv_if_count = 0;
- zns->rtadv.adv_msec_if_count = 0;
+ zrouter.rtadv.adv_if_count = 0;
+ zrouter.rtadv.adv_msec_if_count = 0;
}
void rtadv_cmd_init(void)
ret = setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP, (char *)&mreq,
sizeof mreq);
if (ret < 0)
- zlog_warn("%s(%u): Failed to join group, socket %u error %s",
- ifp->name, ifp->ifindex, sock, safe_strerror(errno));
+ flog_err_sys(EC_LIB_SOCKET,
+ "%s(%u): Failed to join group, socket %u error %s",
+ ifp->name, ifp->ifindex, sock,
+ safe_strerror(errno));
if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug(
ret = setsockopt(sock, IPPROTO_IPV6, IPV6_LEAVE_GROUP, (char *)&mreq,
sizeof mreq);
if (ret < 0)
- zlog_warn("%s(%u): Failed to leave group, socket %u error %s",
- ifp->name, ifp->ifindex, sock, safe_strerror(errno));
+ flog_err_sys(
+ EC_LIB_SOCKET,
+ "%s(%u): Failed to leave group, socket %u error %s",
+ ifp->name, ifp->ifindex, sock, safe_strerror(errno));
if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug(