#include "command.h"
#include "privs.h"
#include "vrf.h"
+#include "ns.h"
#include "zebra/interface.h"
#include "zebra/rtadv.h"
*/
if (adata == NULL) {
/* XXX Free on shutdown. */
- adata = malloc(CMSG_SPACE(sizeof(struct in6_pktinfo)));
+ adata = calloc(1, CMSG_SPACE(sizeof(struct in6_pktinfo)));
- if (adata == NULL)
+ if (adata == NULL) {
zlog_err(
"rtadv_send_packet: can't malloc control data");
+ exit(-1);
+ }
}
/* Logging of packet. */
{
struct zebra_ns *zns = THREAD_ARG(thread);
struct vrf *vrf;
- struct listnode *node, *nnode;
struct interface *ifp;
struct zebra_if *zif;
int period;
rtadv_event(zns, RTADV_TIMER_MSEC, 10 /* 10 ms */);
}
- RB_FOREACH(vrf, vrf_id_head, &vrfs_by_id)
- for (ALL_LIST_ELEMENTS(vrf->iflist, node, nnode, ifp)) {
- if (if_is_loopback(ifp)
- || CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK)
- || !if_is_operative(ifp))
- continue;
-
- zif = ifp->info;
+ RB_FOREACH (vrf, vrf_id_head, &vrfs_by_id)
+ FOR_ALL_INTERFACES (vrf, ifp) {
+ if (if_is_loopback(ifp)
+ || CHECK_FLAG(ifp->status,
+ ZEBRA_INTERFACE_VRF_LOOPBACK)
+ || !if_is_operative(ifp))
+ continue;
+
+ zif = ifp->info;
+
+ if (zif->rtadv.AdvSendAdvertisements) {
+ if (zif->rtadv.inFastRexmit) {
+ /* We assume we fast rexmit every sec so
+ * no
+ * additional vars */
+ if (--zif->rtadv.NumFastReXmitsRemain
+ <= 0)
+ zif->rtadv.inFastRexmit = 0;
+
+ if (IS_ZEBRA_DEBUG_SEND)
+ zlog_debug(
+ "Fast RA Rexmit on interface %s",
+ ifp->name);
- if (zif->rtadv.AdvSendAdvertisements) {
- if (zif->rtadv.inFastRexmit) {
- /* We assume we fast rexmit every sec so no
- * additional vars */
- if (--zif->rtadv.NumFastReXmitsRemain <= 0)
- zif->rtadv.inFastRexmit = 0;
-
- if (IS_ZEBRA_DEBUG_SEND)
- zlog_debug(
- "Fast RA Rexmit on interface %s",
- ifp->name);
-
- rtadv_send_packet(zns->rtadv.sock, ifp);
- } else {
- zif->rtadv.AdvIntervalTimer -= period;
- if (zif->rtadv.AdvIntervalTimer <= 0) {
- /* FIXME: using MaxRtrAdvInterval each
- time isn't what section
- 6.2.4 of RFC4861 tells to do. */
- zif->rtadv.AdvIntervalTimer =
- zif->rtadv.MaxRtrAdvInterval;
rtadv_send_packet(zns->rtadv.sock, ifp);
+ } else {
+ zif->rtadv.AdvIntervalTimer -= period;
+ if (zif->rtadv.AdvIntervalTimer <= 0) {
+ /* FIXME: using
+ MaxRtrAdvInterval each
+ time isn't what section
+ 6.2.4 of RFC4861 tells to do.
+ */
+ zif->rtadv.AdvIntervalTimer =
+ zif->rtadv
+ .MaxRtrAdvInterval;
+ rtadv_send_packet(
+ zns->rtadv.sock, ifp);
+ }
}
}
}
- }
return 0;
}
return 0;
}
-static int rtadv_make_socket(void)
+static int rtadv_make_socket(ns_id_t ns_id)
{
int sock;
int ret = 0;
zlog_err("rtadv_make_socket: could not raise privs, %s",
safe_strerror(errno));
- sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
+ 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",
sizeof(struct icmp6_filter));
if (ret < 0) {
zlog_info("ICMP6_FILTER set fail: %s", safe_strerror(errno));
+ close(sock);
return ret;
}
* if the operator has explicitly enabled RA. The enable request can also
* specify a RA interval (in seconds).
*/
-void zebra_interface_radv_set(struct zserv *client, int sock, u_short length,
+void zebra_interface_radv_set(struct zserv *client, u_short length,
struct zebra_vrf *zvrf, int enable)
{
struct stream *s;
- unsigned int ifindex;
+ ifindex_t ifindex;
struct interface *ifp;
struct zebra_if *zif;
int ra_interval;
s = client->ibuf;
/* Get interface index and RA interval. */
- ifindex = stream_getl(s);
- ra_interval = stream_getl(s);
+ STREAM_GETL(s, ifindex);
+ STREAM_GETL(s, ra_interval);
if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug("%u: IF %u RA %s from client %s, interval %ds",
zif = ifp->info;
if (enable) {
+ SET_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED);
ipv6_nd_suppress_ra_set(ifp, RA_ENABLE);
if (ra_interval
- && (ra_interval * 1000) < zif->rtadv.MaxRtrAdvInterval)
+ && (ra_interval * 1000) < zif->rtadv.MaxRtrAdvInterval
+ && !CHECK_FLAG(zif->rtadv.ra_configured,
+ VTY_RA_INTERVAL_CONFIGURED))
zif->rtadv.MaxRtrAdvInterval = ra_interval * 1000;
} else {
- if (!zif->rtadv.configured) {
+ UNSET_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED);
+ if (!CHECK_FLAG(zif->rtadv.ra_configured,
+ VTY_RA_INTERVAL_CONFIGURED))
zif->rtadv.MaxRtrAdvInterval =
RTADV_MAX_RTR_ADV_INTERVAL;
+ if (!CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED))
ipv6_nd_suppress_ra_set(ifp, RA_SUPPRESS);
- }
}
+stream_failure:
+ return;
}
DEFUN (ipv6_nd_suppress_ra,
return CMD_WARNING_CONFIG_FAILED;
}
- ipv6_nd_suppress_ra_set(ifp, RA_SUPPRESS);
- zif->rtadv.configured = 0;
+ if (!CHECK_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED))
+ ipv6_nd_suppress_ra_set(ifp, RA_SUPPRESS);
+
+ UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED);
return CMD_SUCCESS;
}
}
ipv6_nd_suppress_ra_set(ifp, RA_ENABLE);
- zif->rtadv.configured = 1;
+ SET_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED);
return CMD_SUCCESS;
}
if (interval % 1000)
zns->rtadv.adv_msec_if_count++;
+ SET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
zif->rtadv.MaxRtrAdvInterval = interval;
zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
zif->rtadv.AdvIntervalTimer = 0;
/* convert to milliseconds */
interval = interval * 1000;
+ SET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
zif->rtadv.MaxRtrAdvInterval = interval;
zif->rtadv.MinRtrAdvInterval = 0.33 * interval;
zif->rtadv.AdvIntervalTimer = 0;
if (zif->rtadv.MaxRtrAdvInterval % 1000)
zns->rtadv.adv_msec_if_count--;
- zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
- zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
+ UNSET_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED);
+
+ if (CHECK_FLAG(zif->rtadv.ra_configured, BGP_RA_CONFIGURED))
+ zif->rtadv.MaxRtrAdvInterval = 10000;
+ else
+ zif->rtadv.MaxRtrAdvInterval = RTADV_MAX_RTR_ADV_INTERVAL;
+
zif->rtadv.AdvIntervalTimer = zif->rtadv.MaxRtrAdvInterval;
+ zif->rtadv.MinRtrAdvInterval = RTADV_MIN_RTR_ADV_INTERVAL;
return CMD_SUCCESS;
}
if (!(if_is_loopback(ifp)
|| CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_VRF_LOOPBACK))) {
- if (zif->rtadv.AdvSendAdvertisements)
+ if (zif->rtadv.AdvSendAdvertisements
+ && CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_CONFIGURED))
vty_out(vty, " no ipv6 nd suppress-ra\n");
}
interval = zif->rtadv.MaxRtrAdvInterval;
- if (interval % 1000)
- vty_out(vty, " ipv6 nd ra-interval msec %d\n", interval);
- else if (interval != RTADV_MAX_RTR_ADV_INTERVAL)
- vty_out(vty, " ipv6 nd ra-interval %d\n", interval / 1000);
+ if (CHECK_FLAG(zif->rtadv.ra_configured, VTY_RA_INTERVAL_CONFIGURED)) {
+ if (interval % 1000)
+ vty_out(vty, " ipv6 nd ra-interval msec %d\n",
+ interval);
+ else if (interval != RTADV_MAX_RTR_ADV_INTERVAL)
+ vty_out(vty, " ipv6 nd ra-interval %d\n",
+ interval / 1000);
+ }
if (zif->rtadv.AdvIntervalOption)
vty_out(vty, " ipv6 nd adv-interval-option\n");
void rtadv_init(struct zebra_ns *zns)
{
- zns->rtadv.sock = rtadv_make_socket();
+ zns->rtadv.sock = rtadv_make_socket(zns->ns_id);
}
void rtadv_terminate(struct zebra_ns *zns)