summaryrefslogtreecommitdiffstats
path: root/ospf6d/ospf6_message.c
diff options
context:
space:
mode:
Diffstat (limited to 'ospf6d/ospf6_message.c')
-rw-r--r--ospf6d/ospf6_message.c103
1 files changed, 83 insertions, 20 deletions
diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c
index 07da9a5..d13799c 100644
--- a/ospf6d/ospf6_message.c
+++ b/ospf6d/ospf6_message.c
@@ -268,6 +268,18 @@ static struct ospf6_packet *ospf6_packet_new(size_t size)
return new;
}
+static struct ospf6_packet *ospf6_packet_dup(struct ospf6_packet *old)
+{
+ struct ospf6_packet *new;
+
+ new = XCALLOC(MTYPE_OSPF6_PACKET, sizeof(struct ospf6_packet));
+ new->s = stream_dup(old->s);
+ new->dst = old->dst;
+ new->length = old->length;
+
+ return new;
+}
+
static void ospf6_packet_free(struct ospf6_packet *op)
{
if (op->s)
@@ -407,6 +419,25 @@ static void ospf6_hello_recv(struct in6_addr *src, struct in6_addr *dst,
hello = (struct ospf6_hello *)((caddr_t)oh
+ sizeof(struct ospf6_header));
+ if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT
+ || oi->state == OSPF6_INTERFACE_POINTTOMULTIPOINT)
+ && oi->p2xp_only_cfg_neigh) {
+ /* NEVER, never, ever, do this on broadcast (or NBMA)!
+ * DR/BDR election requires everyone to talk to everyone else
+ * only for PtP/PtMP we can be selective in adjacencies!
+ */
+ struct ospf6_if_p2xp_neighcfg *p2xp_cfg;
+
+ p2xp_cfg = ospf6_if_p2xp_find(oi, src);
+ if (!p2xp_cfg) {
+ if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
+ zlog_debug(
+ "ignoring PtP/PtMP hello from %pI6, neighbor not configured",
+ src);
+ return;
+ }
+ }
+
/* HelloInterval check */
if (ntohs(hello->hello_interval) != oi->hello_interval) {
zlog_warn(
@@ -479,7 +510,7 @@ static void ospf6_hello_recv(struct in6_addr *src, struct in6_addr *dst,
on->hello_in++;
/* Always override neighbor's source address */
- memcpy(&on->linklocal_addr, src, sizeof(struct in6_addr));
+ ospf6_neighbor_lladdr_set(on, src);
/* Neighbor ifindex check */
if (on->ifindex != (ifindex_t)ntohl(hello->interface_id)) {
@@ -631,8 +662,8 @@ static void ospf6_dbdesc_recv_master(struct ospf6_header *oh,
"Neighbor state is not ExStart, ignore");
return;
}
- /* else fall through to ExStart */
- /* fallthru */
+ /* else fall through to ExStart */
+ fallthrough;
case OSPF6_NEIGHBOR_EXSTART:
/* if neighbor obeys us as our slave, schedule negotiation_done
and process LSA Headers. Otherwise, ignore this message */
@@ -650,8 +681,8 @@ static void ospf6_dbdesc_recv_master(struct ospf6_header *oh,
on->ospf6_if->interface->vrf->name, on->name);
return;
}
- /* fall through to exchange */
-
+ /* fall through to exchange */
+ fallthrough;
case OSPF6_NEIGHBOR_EXCHANGE:
if (!memcmp(dbdesc, &on->dbdesc_last,
sizeof(struct ospf6_dbdesc))) {
@@ -835,8 +866,8 @@ static void ospf6_dbdesc_recv_slave(struct ospf6_header *oh,
"Neighbor state is not ExStart, ignore");
return;
}
- /* else fall through to ExStart */
- /* fallthru */
+ /* else fall through to ExStart */
+ fallthrough;
case OSPF6_NEIGHBOR_EXSTART:
/* If the neighbor is Master, act as Slave. Schedule
negotiation_done
@@ -2239,8 +2270,6 @@ static void ospf6_write(struct event *thread)
void ospf6_hello_send(struct event *thread)
{
struct ospf6_interface *oi;
- struct ospf6_packet *op;
- uint16_t length = OSPF6_HEADER_SIZE;
oi = (struct ospf6_interface *)EVENT_ARG(thread);
@@ -2266,6 +2295,20 @@ void ospf6_hello_send(struct event *thread)
return;
}
+ event_add_timer(master, ospf6_hello_send, oi, oi->hello_interval,
+ &oi->thread_send_hello);
+
+ ospf6_hello_send_addr(oi, NULL);
+}
+
+/* used to send polls for PtP/PtMP too */
+void ospf6_hello_send_addr(struct ospf6_interface *oi,
+ const struct in6_addr *addr)
+{
+ struct ospf6_packet *op;
+ uint16_t length = OSPF6_HEADER_SIZE;
+ bool anything = false;
+
op = ospf6_packet_new(oi->ifmtu);
ospf6_make_header(OSPF6_MESSAGE_TYPE_HELLO, oi, op->s);
@@ -2284,20 +2327,40 @@ void ospf6_hello_send(struct event *thread)
/* Set packet length. */
op->length = length;
- op->dst = allspfrouters6;
-
- ospf6_fill_hdr_checksum(oi, op);
+ if ((oi->state == OSPF6_INTERFACE_POINTTOPOINT
+ || oi->state == OSPF6_INTERFACE_POINTTOMULTIPOINT)
+ && !addr && oi->p2xp_no_multicast_hello) {
+ struct listnode *node;
+ struct ospf6_neighbor *on;
+ struct ospf6_packet *opdup;
+
+ for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, node, on)) {
+ if (on->state < OSPF6_NEIGHBOR_INIT)
+ /* poll-interval for these */
+ continue;
+
+ opdup = ospf6_packet_dup(op);
+ opdup->dst = on->linklocal_addr;
+ ospf6_fill_hdr_checksum(oi, opdup);
+ ospf6_packet_add_top(oi, opdup);
+ anything = true;
+ }
- /* Add packet to the top of the interface output queue, so that they
- * can't get delayed by things like long queues of LS Update packets
- */
- ospf6_packet_add_top(oi, op);
+ ospf6_packet_free(op);
+ } else {
+ op->dst = addr ? *addr : allspfrouters6;
- /* set next thread */
- event_add_timer(master, ospf6_hello_send, oi, oi->hello_interval,
- &oi->thread_send_hello);
+ /* Add packet to the top of the interface output queue, so that
+ * they can't get delayed by things like long queues of LS
+ * Update packets
+ */
+ ospf6_fill_hdr_checksum(oi, op);
+ ospf6_packet_add_top(oi, op);
+ anything = true;
+ }
- OSPF6_MESSAGE_WRITE_ON(oi);
+ if (anything)
+ OSPF6_MESSAGE_WRITE_ON(oi);
}
static uint16_t ospf6_make_dbdesc(struct ospf6_neighbor *on, struct stream *s)