summaryrefslogtreecommitdiff
path: root/ospfd/ospf_packet.c
diff options
context:
space:
mode:
Diffstat (limited to 'ospfd/ospf_packet.c')
-rw-r--r--ospfd/ospf_packet.c88
1 files changed, 60 insertions, 28 deletions
diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c
index 36f9a6757a..47f5ee76d2 100644
--- a/ospfd/ospf_packet.c
+++ b/ospfd/ospf_packet.c
@@ -519,7 +519,7 @@ int ospf_ls_upd_timer(struct thread *thread)
if (listcount(update) > 0)
ospf_ls_upd_send(nbr, update, OSPF_SEND_PACKET_DIRECT);
- list_delete(update);
+ list_delete_and_null(&update);
}
/* Set LS Update retransmission timer. */
@@ -649,6 +649,12 @@ static int ospf_write(struct thread *thread)
#define OSPF_WRITE_IPHL_SHIFT 2
int pkt_count = 0;
+#ifdef GNU_LINUX
+ unsigned char cmsgbuf[64] = {};
+ struct cmsghdr *cm = (struct cmsghdr *)cmsgbuf;
+ struct in_pktinfo *pi;
+#endif
+
ospf->t_write = NULL;
node = listhead(ospf->oi_write_q);
@@ -753,14 +759,28 @@ static int ospf_write(struct thread *thread)
msg.msg_namelen = sizeof(sa_dst);
msg.msg_iov = iov;
msg.msg_iovlen = 2;
+
iov[0].iov_base = (char *)&iph;
iov[0].iov_len = iph.ip_hl << OSPF_WRITE_IPHL_SHIFT;
iov[1].iov_base = STREAM_PNT(op->s);
iov[1].iov_len = op->length;
-/* Sadly we can not rely on kernels to fragment packets because of either
- * IP_HDRINCL and/or multicast destination being set.
- */
+#ifdef GNU_LINUX
+ msg.msg_control = (caddr_t)cm;
+ cm->cmsg_level = SOL_IP;
+ cm->cmsg_type = IP_PKTINFO;
+ cm->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
+ pi = (struct in_pktinfo *)CMSG_DATA(cm);
+ pi->ipi_ifindex = oi->ifp->ifindex;
+
+ msg.msg_controllen = cm->cmsg_len;
+#endif
+
+ /* Sadly we can not rely on kernels to fragment packets
+ * because of either IP_HDRINCL and/or multicast
+ * destination being set.
+ */
+
#ifdef WANT_OSPF_WRITE_FRAGMENT
if (op->length > maxdatasize)
ospf_write_frags(ospf->fd, op, &iph, &msg, maxdatasize,
@@ -907,9 +927,10 @@ static void ospf_hello(struct ip *iph, struct ospf_header *ospfh,
}
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("Packet %s [Hello:RECV]: Options %s",
+ zlog_debug("Packet %s [Hello:RECV]: Options %s vrf %s",
inet_ntoa(ospfh->router_id),
- ospf_options_dump(hello->options));
+ ospf_options_dump(hello->options),
+ ospf_vrf_id_to_name(oi->ospf->vrf_id));
/* Compare options. */
#define REJECT_IF_TBIT_ON 1 /* XXX */
@@ -1551,15 +1572,16 @@ static void ospf_ls_req(struct ip *iph, struct ospf_header *ospfh,
/* Verify LSA type. */
if (ls_type < OSPF_MIN_LSA || ls_type >= OSPF_MAX_LSA) {
OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_BadLSReq);
- list_delete(ls_upd);
+ list_delete_and_null(&ls_upd);
return;
}
/* Search proper LSA in LSDB. */
- find = ospf_lsa_lookup(oi->area, ls_type, ls_id, adv_router);
+ find = ospf_lsa_lookup(oi->ospf, oi->area, ls_type, ls_id,
+ adv_router);
if (find == NULL) {
OSPF_NSM_EVENT_SCHEDULE(nbr, NSM_BadLSReq);
- list_delete(ls_upd);
+ list_delete_and_null(&ls_upd);
return;
}
@@ -1593,9 +1615,9 @@ static void ospf_ls_req(struct ip *iph, struct ospf_header *ospfh,
ospf_ls_upd_send(nbr, ls_upd,
OSPF_SEND_PACKET_INDIRECT);
- list_delete(ls_upd);
+ list_delete_and_null(&ls_upd);
} else
- list_free(ls_upd);
+ list_delete_and_null(&ls_upd);
}
/* Get the list of LSAs from Link State Update packet.
@@ -1696,6 +1718,7 @@ static struct list *ospf_ls_upd_list_lsa(struct ospf_neighbor *nbr,
/* Create OSPF LSA instance. */
lsa = ospf_lsa_new();
+ lsa->vrf_id = oi->ospf->vrf_id;
/* We may wish to put some error checking if type NSSA comes in
and area not in NSSA mode */
switch (lsah->type) {
@@ -1735,7 +1758,7 @@ static void ospf_upd_list_clean(struct list *lsas)
for (ALL_LIST_ELEMENTS(lsas, node, nnode, lsa))
ospf_lsa_discard(lsa);
- list_delete(lsas);
+ list_delete_and_null(&lsas);
}
/* OSPF Link State Update message read -- RFC2328 Section 13. */
@@ -1784,6 +1807,8 @@ static void ospf_ls_upd(struct ospf *ospf, struct ip *iph,
*/
lsas = ospf_ls_upd_list_lsa(nbr, s, oi, size);
+ if (lsas == NULL)
+ return;
#define DISCARD_LSA(L, N) \
{ \
if (IS_DEBUG_OSPF_EVENT) \
@@ -2134,7 +2159,7 @@ static void ospf_ls_upd(struct ospf *ospf, struct ip *iph,
#undef DISCARD_LSA
assert(listcount(lsas) == 0);
- list_delete(lsas);
+ list_delete_and_null(&lsas);
}
/* OSPF Link State Acknowledgment message read -- RFC2328 Section 13.7. */
@@ -2173,6 +2198,7 @@ static void ospf_ls_ack(struct ip *iph, struct ospf_header *ospfh,
lsa = ospf_lsa_new();
lsa->data = (struct lsa_header *)STREAM_PNT(s);
+ lsa->vrf_id = oi->ospf->vrf_id;
/* lsah = (struct lsa_header *) STREAM_PNT (s); */
size -= OSPF_LSA_HEADER_SIZE;
@@ -2197,7 +2223,8 @@ static void ospf_ls_ack(struct ip *iph, struct ospf_header *ospfh,
return;
}
-static struct stream *ospf_recv_packet(int fd, struct interface **ifp,
+static struct stream *ospf_recv_packet(struct ospf *ospf, int fd,
+ struct interface **ifp,
struct stream *ibuf)
{
int ret;
@@ -2265,7 +2292,7 @@ static struct stream *ospf_recv_packet(int fd, struct interface **ifp,
ifindex = getsockopt_ifindex(AF_INET, &msgh);
- *ifp = if_lookup_by_index(ifindex, VRF_DEFAULT);
+ *ifp = if_lookup_by_index(ifindex, ospf->vrf_id);
if (ret != ip_len) {
zlog_warn(
@@ -2833,7 +2860,7 @@ int ospf_read(struct thread *thread)
struct ip *iph;
struct ospf_header *ospfh;
u_int16_t length;
- struct interface *ifp;
+ struct interface *ifp = NULL;
struct connected *c;
/* first of all get interface pointer. */
@@ -2844,7 +2871,8 @@ int ospf_read(struct thread *thread)
thread_add_read(master, ospf_read, ospf, ospf->fd, &ospf->t_read);
stream_reset(ospf->ibuf);
- if (!(ibuf = ospf_recv_packet(ospf->fd, &ifp, ospf->ibuf)))
+ ibuf = ospf_recv_packet(ospf, ospf->fd, &ifp, ospf->ibuf);
+ if (ibuf == NULL)
return -1;
/* This raw packet is known to be at least as big as its IP header. */
@@ -2861,7 +2889,7 @@ int ospf_read(struct thread *thread)
ifindex
retrieval but do not. */
c = if_lookup_address((void *)&iph->ip_src, AF_INET,
- VRF_DEFAULT);
+ ospf->vrf_id);
if (c)
ifp = c->ifp;
if (ifp == NULL)
@@ -3487,6 +3515,13 @@ static void ospf_hello_send_sub(struct ospf_interface *oi, in_addr_t addr)
op->dst.s_addr = addr;
+ if (IS_DEBUG_OSPF_EVENT) {
+ if (oi->ospf->vrf_id)
+ zlog_debug("%s: Hello Tx interface %s ospf vrf %s id %u",
+ __PRETTY_FUNCTION__, oi->ifp->name,
+ ospf_vrf_id_to_name(oi->ospf->vrf_id),
+ oi->ospf->vrf_id);
+ }
/* 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
*/
@@ -3739,7 +3774,7 @@ void ospf_ls_upd_send_lsa(struct ospf_neighbor *nbr, struct ospf_lsa *lsa,
listnode_add(update, lsa);
ospf_ls_upd_send(nbr, update, flag);
- list_delete(update);
+ list_delete_and_null(&update);
}
/* Determine size for packet. Must be at least big enough to accomodate next
@@ -3883,8 +3918,7 @@ static int ospf_ls_upd_send_queue_event(struct thread *thread)
/* list might not be empty. */
if (listcount(update) == 0) {
- list_delete(rn->info);
- rn->info = NULL;
+ list_delete_and_null((struct list **)&rn->info);
route_unlock_node(rn);
} else
again = 1;
@@ -4065,21 +4099,19 @@ void ospf_ls_ack_send_delayed(struct ospf_interface *oi)
* punt-to-CPU set on them. This may overload the CPU control path that
* can be avoided if the MAC was known apriori.
*/
-#define OSPF_PING_NBR_STR_MAX (8 + 40 + 20)
+#define OSPF_PING_NBR_STR_MAX (BUFSIZ)
void ospf_proactively_arp(struct ospf_neighbor *nbr)
{
char ping_nbr[OSPF_PING_NBR_STR_MAX];
- char *str_ptr;
int ret;
if (!nbr || !nbr->oi || !nbr->oi->ifp)
return;
- str_ptr = strcpy(ping_nbr, "ping -c 1 -I ");
- str_ptr = strcat(str_ptr, nbr->oi->ifp->name);
- str_ptr = strcat(str_ptr, " ");
- str_ptr = strcat(str_ptr, inet_ntoa(nbr->address.u.prefix4));
- str_ptr = strcat(str_ptr, " > /dev/null 2>&1 &");
+ snprintf(ping_nbr, sizeof(ping_nbr),
+ "ping -c 1 -I %s %s > /dev/null 2>&1 &",
+ nbr->oi->ifp->name, inet_ntoa(nbr->address.u.prefix4));
+
ret = system(ping_nbr);
if (IS_DEBUG_OSPF_EVENT)
zlog_debug("Executed %s %s", ping_nbr,