profile
viewpoint
If you are wondering where the data of this site comes from, please visit https://api.github.com/users/eqvinox/events. GitMemory does not store any data, but only uses NGINX to cache data for a period of time. The idea behind GitMemory is simply to give users a better reading experience.
David Lamparter eqvinox OpenSourceRouting @ NetDEF Germany http://opensourcerouting.org/

CESNET/libyang 250

YANG data modeling language library

eqvinox/wifisetup 12

Eduroam EAP-TLS helper for Android 4.0 and up

eqvinox/vpls-linux-kernel 4

VPLS patches

eqvinox/quagga 2

quagga

eqvinox/libopencm3 1

Open Source ARM cortex m microcontroller library

eqvinox/netbox 1

IP address management (IPAM) and data center infrastructure management (DCIM) tool.

eqvinox/vpls-iproute2 1

iproute2 VPLS changes

eqvinox/asa 0

The asa subtitle renderer

eqvinox/flex 0

The Fast Lexical Analyzer - scanner generator for lexing in C and C++

pull request commentFRRouting/frr

OSPF6: Support OSPF6 authentication trailer RFC 7166

btw: sorry for showing up 6 weeks after the PR was created with a whole list of issues, unfortunately I had no time to look at this earlier.

But since this is authentication-related (and thus security relevant), the code really needs to be good quality. I understand the annoyance of tracking a PR for a longer time but I don't think we can fast-track this.

rameshabhinay

comment created time in 11 hours

Pull request review commentFRRouting/frr

OSPF6: Support OSPF6 authentication trailer RFC 7166

 struct ospf6_neighbor {  	/* BFD information */ 	struct bfd_session_params *bfd_session;++	uint32_t seqnum_h;+	uint32_t seqnum_l;

How do those relate to the same name fields in ospf6_auth_cfg? (Please add a comment)

rameshabhinay

comment created time in 11 hours

Pull request review commentFRRouting/frr

OSPF6: Support OSPF6 authentication trailer RFC 7166

 #define OSPF6_MESSAGE_H  #define OSPF6_MESSAGE_BUFSIZ  4096+#define IPPROTO_OSPF 89

This define looks like it may be provided by headers in /usr/include on some systems, please add an #ifndef IPPROTO_OSPF around it. (Also, why do we have it now but didn't need it before?)

rameshabhinay

comment created time in 11 hours

Pull request review commentFRRouting/frr

OSPF6: Support OSPF6 authentication trailer RFC 7166

 #include "qobj.h" #include "hook.h" #include "if.h"+#include "ospf6d.h"  /* Debug option */ extern unsigned char conf_debug_ospf6_interface; #define OSPF6_DEBUG_INTERFACE_ON() (conf_debug_ospf6_interface = 1) #define OSPF6_DEBUG_INTERFACE_OFF() (conf_debug_ospf6_interface = 0) #define IS_OSPF6_DEBUG_INTERFACE (conf_debug_ospf6_interface) +struct ospf6_auth_cfg {+	/* higher order Sequence Number */+	uint32_t seqnum_h;

This seems to be a mixture of config, state and statistics. That's OK but please change the name from ospf6_auth_cfg to something that does not include "cfg" (ospf_auth_data maybe?), and add notes in the comments which is config, which is state, and which is statistics.

rameshabhinay

comment created time in 12 hours

Pull request review commentFRRouting/frr

OSPF6: Support OSPF6 authentication trailer RFC 7166

 static void ospf6_brouter_debug_print(struct ospf6_route *brouter) 	char installed[64], changed[64]; 	struct timeval now, res; 	char id[16], adv_router[16];-	char capa[16], options[16];+	char capa[16], options[32];

Why is the size change 1632 needed here? Should the 32 be replaced with a constant?

rameshabhinay

comment created time in 12 hours

Pull request review commentFRRouting/frr

OSPF6: Support OSPF6 authentication trailer RFC 7166

 static void config_add_line_uniq(struct list *config, const char *line) 	listnode_add_sort(config, XSTRDUP(MTYPE_VTYSH_CONFIG_LINE, line)); } +/* Global variable to keep track of the KEYCHAIN_KEY_NODE for comparing */+static char *key_ptr;

uh... okay... this raises alarm bells for me but I didn't review it yet. Maybe it's OK, did someone else double check it?

rameshabhinay

comment created time in 11 hours

Pull request review commentFRRouting/frr

OSPF6: Support OSPF6 authentication trailer RFC 7166

+/*+ * Copyright (C) 2021 Abhinay Ramesh+ *+ * This file is part of GNU Zebra.+ *+ * GNU Zebra is free software; you can redistribute it and/or modify it+ * under the terms of the GNU General Public License as published by the+ * Free Software Foundation; either version 2, or (at your option) any+ * later version.+ *+ * GNU Zebra is distributed in the hope that it will be useful, but+ * WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU+ * General Public License for more details.+ *+ * You should have received a copy of the GNU General Public License along+ * with this program; see the file COPYING; if not, write to the Free Software+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA+ */++#include "memory.h"+#include "zebra.h"+#include "ospf6d.h"+#include "vty.h"+#include "command.h"+#include "md5.h"+#include "sha256.h"+#include "lib/zlog.h"+#include "ospf6_message.h"+#include "ospf6_interface.h"+#include "ospf6_neighbor.h"+#include "ospf6_proto.h"+#include "ospf6_auth_trailer.h"+#include "ospf6_route.h"+#include "ospf6_zebra.h"+#include "lib/keychain.h"++unsigned char conf_debug_ospf6_auth[2];+DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_AUTH_PKT, "OSPF6 auth packet");+DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_AUTH_HASH, "OSPF6 auth hash");+DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_AUTH_HASH_XOR, "OSPF6 auth hash xor");+DECLARE_MTYPE(OSPF6_AUTH_MANUAL_KEY);++/*Apad is the hexadecimal value 0x878FE1F3. */+const uint8_t ospf6_hash_apad_max[KEYCHAIN_MAX_HASH_SIZE] = {+	0x87, 0x8f, 0xe1, 0xf3, 0x87, 0x8f, 0xe1, 0xf3, 0x87, 0x8f, 0xe1,+	0xf3, 0x87, 0x8f, 0xe1, 0xf3, 0x87, 0x8f, 0xe1, 0xf3, 0x87, 0x8f,+	0xe1, 0xf3, 0x87, 0x8f, 0xe1, 0xf3, 0x87, 0x8f, 0xe1, 0xf3, 0x87,+	0x8f, 0xe1, 0xf3, 0x87, 0x8f, 0xe1, 0xf3, 0x87, 0x8f, 0xe1, 0xf3,+	0x87, 0x8f, 0xe1, 0xf3, 0x87, 0x8f, 0xe1, 0xf3, 0x87, 0x8f, 0xe1,+	0xf3, 0x87, 0x8f, 0xe1, 0xf3, 0x87, 0x8f, 0xe1, 0xf3,+};++const uint8_t ospf6_hash_ipad_max[KEYCHAIN_ALGO_MAX_INTERNAL_BLK_SIZE] = {+	0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,+	0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,+	0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,+	0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,+	0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,+	0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,+	0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,+	0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,+	0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,+	0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,+	0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,+};++const uint8_t ospf6_hash_opad_max[KEYCHAIN_ALGO_MAX_INTERNAL_BLK_SIZE] = {+	0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,+	0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,+	0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,+	0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,+	0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,+	0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,+	0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,+	0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,+	0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,+	0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,+	0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,+};++void ospf6_auth_hdr_dump_send(struct ospf6_header *ospfh, uint16_t length)+{+	struct ospf6_auth_hdr *ospf6_at_hdr;+	int at_len, oh_len, at_hdr_len, hash_len;+	unsigned char temp[KEYCHAIN_MAX_HASH_SIZE+1];++	oh_len = htons(ospfh->length);+	at_len = length - oh_len;+	if (at_len > 0) {+		ospf6_at_hdr = (struct ospf6_auth_hdr *)+					((uint8_t *)ospfh + oh_len);+		at_hdr_len = htons(ospf6_at_hdr->length);+		hash_len = at_hdr_len - OSPF6_AUTH_HDR_MIN_SIZE;+		memcpy(temp, ospf6_at_hdr->data, hash_len);+		temp[hash_len] = '\0';+		zlog_debug("OSPF6 Authentication Trailer");+		zlog_debug("  Type %d", htons(ospf6_at_hdr->type));+		zlog_debug("  Length %d", at_hdr_len);+		zlog_debug("  Reserved %d", ospf6_at_hdr->reserved);+		zlog_debug("  SA ID %d", htons(ospf6_at_hdr->id));+		zlog_debug("  seqnum high 0x%08x",+			   htonl(ospf6_at_hdr->seqnum_h));+		zlog_debug("  seqnum high 0x%08x",+			   htonl(ospf6_at_hdr->seqnum_l));+		zlog_debug("  Data %s", temp);+	}+}++void ospf6_auth_hdr_dump_recv(struct ospf6_header *ospfh, uint16_t length)+{+	struct ospf6_auth_hdr *ospf6_at_hdr;+	int at_len, oh_len, at_hdr_len, hash_len;+	unsigned char temp[KEYCHAIN_MAX_HASH_SIZE+1];++	oh_len = ntohs(ospfh->length);+	at_len = length - oh_len;+	if (at_len > 0) {+		ospf6_at_hdr = (struct ospf6_auth_hdr *)+					((uint8_t *)ospfh + oh_len);+		at_hdr_len = ntohs(ospf6_at_hdr->length);+		hash_len = at_hdr_len - OSPF6_AUTH_HDR_MIN_SIZE;+		memcpy(temp, ospf6_at_hdr->data, hash_len);+		temp[hash_len] = '\0';+		zlog_debug("OSPF6 Authentication Trailer");+		zlog_debug("  Type %d", ntohs(ospf6_at_hdr->type));+		zlog_debug("  Length %d", at_hdr_len);+		zlog_debug("  Reserved %d", ospf6_at_hdr->reserved);+		zlog_debug("  SA ID %d", ntohs(ospf6_at_hdr->id));+		zlog_debug("  seqnum high 0x%08x",+			   ntohl(ospf6_at_hdr->seqnum_h));+		zlog_debug("  seqnum high 0x%08x",+			   ntohl(ospf6_at_hdr->seqnum_l));+		zlog_debug("  Data %s", temp);+	}+}++unsigned char *ospf6_hash_message_xor(unsigned char *mes1,+				      unsigned char *mes2,+				      uint32_t len)+{+	unsigned char *result;+	uint32_t i;++	result = XCALLOC(MTYPE_OSPF6_AUTH_HASH_XOR, len + 1);+	if (!result)+		return NULL;++	for (i = 0; i < len; i++)+		result[i] = mes1[i] ^ mes2[i];++	result[len] = '\0';+	return result;+}++static void md5_digest(unsigned char *mes, uint32_t len,+		       unsigned char *digest)+{+#ifdef CRYPTO_OPENSSL+	unsigned int size = KEYCHAIN_MD5_HASH_SIZE;+	EVP_MD_CTX *ctx;+#elif CRYPTO_INTERNAL+	MD5_CTX ctx;+#endif++#ifdef CRYPTO_OPENSSL+	ctx = EVP_MD_CTX_new();+	EVP_DigestInit(ctx, EVP_md5());+	EVP_DigestUpdate(ctx, mes, len);+	EVP_DigestFinal(ctx, digest, &size);+	EVP_MD_CTX_free(ctx);+#elif CRYPTO_INTERNAL+	memset(&ctx, 0, sizeof(ctx));+	MD5Init(&ctx);+	MD5Update(&ctx, mes, len);+	MD5Final(digest, &ctx);+#endif+}++static void sha256_digest(unsigned char *mes, uint32_t len,+			  unsigned char *digest)+{+#ifdef CRYPTO_OPENSSL+	unsigned int size = KEYCHAIN_HMAC_SHA256_HASH_SIZE;+	EVP_MD_CTX *ctx;+#elif CRYPTO_INTERNAL+	SHA256_CTX ctx;+#endif++#ifdef CRYPTO_OPENSSL+	ctx = EVP_MD_CTX_new();+	EVP_DigestInit(ctx, EVP_sha256());+	EVP_DigestUpdate(ctx, mes, len);+	EVP_DigestFinal(ctx, digest, &size);+	EVP_MD_CTX_free(ctx);+#elif CRYPTO_INTERNAL+	memset(&ctx, 0, sizeof(ctx));+	SHA256_Init(&ctx);+	SHA256_Update(&ctx, mes, len);+	SHA256_Final(digest, &ctx);+#endif+}++#ifdef CRYPTO_OPENSSL+static void sha1_digest(unsigned char *mes, uint32_t len,+			unsigned char *digest)+{+	EVP_MD_CTX *ctx;+	unsigned int size = KEYCHAIN_HMAC_SHA1_HASH_SIZE;++	ctx = EVP_MD_CTX_new();+	EVP_DigestInit(ctx, EVP_sha1());+	EVP_DigestUpdate(ctx, mes, len);+	EVP_DigestFinal(ctx, digest, &size);+	EVP_MD_CTX_free(ctx);+}++static void sha384_digest(unsigned char *mes, uint32_t len,+			  unsigned char *digest)+{+	EVP_MD_CTX *ctx;+	unsigned int size = KEYCHAIN_HMAC_SHA384_HASH_SIZE;++	ctx = EVP_MD_CTX_new();+	EVP_DigestInit(ctx, EVP_sha384());+	EVP_DigestUpdate(ctx, mes, len);+	EVP_DigestFinal(ctx, digest, &size);+	EVP_MD_CTX_free(ctx);+}++static void sha512_digest(unsigned char *mes, uint32_t len,+			  unsigned char *digest)+{+	EVP_MD_CTX *ctx;+	unsigned int size = KEYCHAIN_HMAC_SHA512_HASH_SIZE;++	ctx = EVP_MD_CTX_new();+	EVP_DigestInit(ctx, EVP_sha512());+	EVP_DigestUpdate(ctx, mes, len);+	EVP_DigestFinal(ctx, digest, &size);+	EVP_MD_CTX_free(ctx);+}+#endif /* CRYPTO_OPENSSL */++static void ospf6_hash_hmac_sha_digest(enum keychain_hash_algo key,+				       unsigned char *mes, uint32_t len,+				       unsigned char *digest)+{+	if ((key <= KEYCHAIN_ALGO_NULL) || (key >= KEYCHAIN_ALGO_MAX))+		return;++	switch (key) {+	case KEYCHAIN_ALGO_MD5:+		md5_digest(mes, len, digest);+		break;+	case KEYCHAIN_ALGO_HMAC_SHA1:+#ifdef CRYPTO_OPENSSL+		sha1_digest(mes, len, digest);+#endif+		break;+	case KEYCHAIN_ALGO_HMAC_SHA256:+		sha256_digest(mes, len, digest);+		break;+	case KEYCHAIN_ALGO_HMAC_SHA384:+#ifdef CRYPTO_OPENSSL+		sha384_digest(mes, len, digest);+#endif+		break;+	case KEYCHAIN_ALGO_HMAC_SHA512:+#ifdef CRYPTO_OPENSSL+		sha512_digest(mes, len, digest);+#endif+		break;+	case KEYCHAIN_ALGO_NULL:+	case KEYCHAIN_ALGO_MAX:+	default:+		/* no action */+		break;+	}+}++unsigned int ospf6_auth_len_get(struct ospf6_interface *oi)+{+	unsigned int at_len = 0;+	char *keychain_name = NULL;+	struct keychain *keychain = NULL;+	struct key *key = NULL;++	if (CHECK_FLAG(oi->at_cfg.flags, OSPF6_AUTH_TRAILER_KEYCHAIN)) {+		if (CHECK_FLAG(oi->at_cfg.flags,+			       OSPF6_AUTH_TRAILER_KEYCHAIN_VALID)) {+			at_len = OSPF6_AUTH_HDR_MIN_SIZE+				 + keychain_get_hash_len(oi->at_cfg.hash_algo);+		} else {+			keychain_name = oi->at_cfg.keychain;+			keychain = keychain_lookup(keychain_name);+			if (keychain) {+				key = key_lookup_for_send(keychain);+				if (key && key->string+				    && key->hash_algo != KEYCHAIN_ALGO_NULL) {+					at_len = OSPF6_AUTH_HDR_MIN_SIZE+						 + keychain_get_hash_len(+							   key->hash_algo);+				}+			}+		}+	} else if (CHECK_FLAG(oi->at_cfg.flags,+			      OSPF6_AUTH_TRAILER_MANUAL_KEY)) {+		at_len = OSPF6_AUTH_HDR_MIN_SIZE+			 + keychain_get_hash_len(oi->at_cfg.hash_algo);+	}++	return at_len;+}++int ospf6_auth_validate_pkt(struct ospf6_interface *oi, unsigned int *pkt_len,+			    struct ospf6_header *oh, unsigned int *at_len)+{+	struct ospf6_hello *hello = NULL;+	struct ospf6_dbdesc *dbdesc = NULL;+	struct ospf6_neighbor *on = NULL;+	struct ospf6_auth_hdr ospf6_auth_info;+	uint16_t hdr_len = 0;+	uint32_t oh_seqnum_h = 0;+	uint32_t oh_seqnum_l = 0;++	on = ospf6_neighbor_lookup(oh->router_id, oi);+	hdr_len = ntohs(oh->length);+	if (*pkt_len < hdr_len) {+		if (IS_OSPF6_DEBUG_AUTH_RX)+			zlog_warn("RECV[%s] Wrong %s packet auth length",+				  oi->interface->name,+				  lookup_msg(ospf6_message_type_str, oh->type,+					     NULL));+		oi->at_cfg.rx_drop++;+		return -1;+	} else if (*pkt_len == hdr_len) {+		/* no auth data in packet+		 */+		return -1;+	}++	switch (oh->type) {+	case OSPF6_MESSAGE_TYPE_HELLO:+		hello = (struct ospf6_hello *)((uint8_t *)oh+					       + sizeof(struct ospf6_header));+		if (OSPF6_OPT_ISSET_EXT(hello->options, OSPF6_OPT_AT)) {+			if (on)+				on->auth_present = true;+		} else {+			if (on)+				on->auth_present = false;++			if (oi->at_cfg.flags != 0) {+				if (IS_OSPF6_DEBUG_AUTH_RX)+					zlog_warn("RECV[%s] : Auth option miss-match in hello pkt",+						  oi->interface->name);+				oi->at_cfg.rx_drop++;+			}++			return -1;+		}+		break;+	case OSPF6_MESSAGE_TYPE_DBDESC:+		dbdesc = (struct ospf6_dbdesc *)((uint8_t *)oh+						 + sizeof(struct ospf6_header));++		if (OSPF6_OPT_ISSET_EXT(dbdesc->options, OSPF6_OPT_AT)) {+			if (on)+				on->auth_present = true;+		} else {+			if (on)+				on->auth_present = false;++			if (oi->at_cfg.flags != 0) {+				if (IS_OSPF6_DEBUG_AUTH_RX)+					zlog_warn("RECV[%s] : Auth option miss-match in DB desc pkt",+						  oi->interface->name);+				oi->at_cfg.rx_drop++;+			}++			return -1;+		}+		break;+	case OSPF6_MESSAGE_TYPE_LSREQ:+	case OSPF6_MESSAGE_TYPE_LSUPDATE:+	case OSPF6_MESSAGE_TYPE_LSACK:+		if ((on && on->auth_present == false)+		    && (oi->at_cfg.flags != 0)) {+			if (IS_OSPF6_DEBUG_AUTH_RX)+				zlog_warn("RECV[%s] : Auth config miss-match in %s",+					  oi->interface->name,+					  lookup_msg(ospf6_message_type_str,+						     oh->type, NULL));+			oi->at_cfg.rx_drop++;+			return -1;+		}+		break;+	default:+		if (IS_OSPF6_DEBUG_AUTH_RX)+			zlog_warn("RECV[%s] : Wrong packet type %d",+				  oi->interface->name, oh->type);+		return -1;+	}++	memset(&ospf6_auth_info, 0, sizeof(struct ospf6_auth_hdr));+	memcpy(&ospf6_auth_info, (uint8_t *)oh + hdr_len, *pkt_len - hdr_len);+	if (ntohs(ospf6_auth_info.length) > OSPF6_AUTH_HDR_FULL) {+		if (IS_OSPF6_DEBUG_AUTH_RX)+			zlog_warn("RECV[%s] : Auth config miss-match in %s",+				  oi->interface->name,+				  lookup_msg(ospf6_message_type_str, oh->type,+					     NULL));+		oi->at_cfg.rx_drop++;+		return -1;+	}++	/* after authentication header validation is done+	 * reduce the auth hdr size from the packet length+	 */+	*at_len = ntohs(ospf6_auth_info.length);+	*pkt_len = *pkt_len - *at_len;++	if (on) {+		oh_seqnum_h = ntohl(ospf6_auth_info.seqnum_h);+		oh_seqnum_l = ntohl(ospf6_auth_info.seqnum_l);+		if ((oh_seqnum_h >= on->seqnum_h) &&+		     (oh_seqnum_l > on->seqnum_l)) {+			/* valid sequence number received */+			on->seqnum_h = oh_seqnum_h;+			on->seqnum_l = oh_seqnum_l;+		} else {+			if (IS_OSPF6_DEBUG_AUTH_RX) {+				zlog_warn("RECV[%s] : Nbr(%s) Auth Sequence number mismatch",+					  oi->interface->name, on->name);+				zlog_warn("nbr_seq_l %u, nbr_seq_h %u, hdr_seq_l %u, hdr_seq_h %u",+					  on->seqnum_l, on->seqnum_h,+					  oh_seqnum_l, oh_seqnum_h);+			}++			oi->at_cfg.rx_drop++;+			return -1;+		}+	}++	return 0;+}++/* Starting point of packet process function. */+int ospf6_auth_check_digest(struct ospf6_header *oh, struct ospf6_interface *oi,+			    struct in6_addr *src)+{+	uint32_t hash_len = KEYCHAIN_MAX_HASH_SIZE;+	unsigned char apad[hash_len];+	unsigned char temp_hash[hash_len];+	struct ospf6_auth_hdr *ospf6_auth;+	uint32_t ipv6_addr_size = sizeof(struct in6_addr);+	struct keychain *keychain = NULL;+	struct key *key = NULL;+	char *auth_str = NULL;+	uint16_t auth_len = 0;+	uint8_t hash_algo = 0;+	uint16_t oh_len = ntohs(oh->length);++	if (oi->at_cfg.flags == 0)+		return -2;++	ospf6_auth = (struct ospf6_auth_hdr *)((uint8_t *)oh + oh_len);+	if (CHECK_FLAG(oi->at_cfg.flags, OSPF6_AUTH_TRAILER_KEYCHAIN)) {+		keychain = keychain_lookup(oi->at_cfg.keychain);+		if (!keychain) {+			if (IS_OSPF6_DEBUG_AUTH_RX)+				zlog_warn("RECV[%s]: Keychain does't exist for %s",+					  oi->interface->name,+					  lookup_msg(ospf6_message_type_str,+						     oh->type, NULL));+			oi->at_cfg.rx_drop++;+			return -1;+		}++		key = key_lookup_for_accept(keychain, ntohs(ospf6_auth->id));+		if (!key) {+			if (IS_OSPF6_DEBUG_AUTH_RX)+				zlog_warn("RECV[%s]: Auth, Invalid SA for %s",+					  oi->interface->name,+					  lookup_msg(ospf6_message_type_str,+						     oh->type, NULL));+			oi->at_cfg.rx_drop++;+			return -1;+		}++		if (key && key->string+		    && key->hash_algo != KEYCHAIN_ALGO_NULL) {+			auth_str = key->string;+			hash_algo = key->hash_algo;+		} else {+			if (IS_OSPF6_DEBUG_AUTH_RX)+				zlog_warn("RECV[%s]: Incomplete keychain config for %s",+					  oi->interface->name,+					  lookup_msg(ospf6_message_type_str,+						     oh->type, NULL));+			oi->at_cfg.rx_drop++;+			return -1;+		}+	} else if (CHECK_FLAG(oi->at_cfg.flags,+			      OSPF6_AUTH_TRAILER_MANUAL_KEY)) {+		auth_str = oi->at_cfg.auth_key;+		hash_algo = oi->at_cfg.hash_algo;+	}++	hash_len = keychain_get_hash_len(hash_algo);+	memset(apad, 0, sizeof(hash_len));+	memset(temp_hash, 0, sizeof(hash_len));++	/* start digest verification */+	memcpy(apad, src, ipv6_addr_size);+	memcpy(apad + ipv6_addr_size, ospf6_hash_apad_max,+	       (hash_len - ipv6_addr_size));++	auth_len = ntohs(ospf6_auth->length);++	memcpy(temp_hash, ospf6_auth->data, hash_len);+	memcpy(ospf6_auth->data, apad, hash_len);++	ospf6_auth_update_digest(oi, oh, ospf6_auth, auth_str, auth_len,+				 (oh_len + auth_len), hash_algo);++	return !(memcmp(temp_hash, ospf6_auth->data, hash_len));+}++void ospf6_auth_digest_send(struct in6_addr *src, struct ospf6_interface *oi,+			    struct ospf6_header *oh, uint16_t auth_len,+			    uint32_t pkt_len)+{+	struct ospf6_auth_hdr *ospf6_auth;+	char *keychain_name = NULL;+	struct keychain *keychain = NULL;+	struct key *key = NULL;+	char *auth_str = NULL;+	uint16_t key_id = 0;+	enum keychain_hash_algo hash_algo = KEYCHAIN_ALGO_NULL;+	uint32_t hash_len = KEYCHAIN_MAX_HASH_SIZE;+	unsigned char apad[hash_len];+	int ipv6_addr_size = sizeof(struct in6_addr);++	if (CHECK_FLAG(oi->at_cfg.flags, OSPF6_AUTH_TRAILER_KEYCHAIN)) {+		if (CHECK_FLAG(oi->at_cfg.flags,+			       OSPF6_AUTH_TRAILER_KEYCHAIN_VALID)) {+			auth_str = oi->at_cfg.auth_key;+			hash_algo = oi->at_cfg.hash_algo;+			key_id = oi->at_cfg.key_id;+		} else {+			keychain_name = oi->at_cfg.keychain;+			keychain = keychain_lookup(keychain_name);+			if (keychain) {+				key = key_lookup_for_send(keychain);+				if (key && key->string+				    && key->hash_algo != KEYCHAIN_ALGO_NULL) {+					auth_str = key->string;+					hash_algo = key->hash_algo;+					key_id = key->index;+				}+			}+		}+	} else if (CHECK_FLAG(oi->at_cfg.flags,+			      OSPF6_AUTH_TRAILER_MANUAL_KEY)) {+		auth_str = oi->at_cfg.auth_key;+		hash_algo = oi->at_cfg.hash_algo;+		key_id = oi->at_cfg.key_id;+	} else {+		if (IS_OSPF6_DEBUG_AUTH_TX)+			zlog_warn("SEND[%s]: Authentication not configured for %s",+				  oi->interface->name,+				  lookup_msg(ospf6_message_type_str,+					     oh->type, NULL));+		return;+	}++	hash_len = keychain_get_hash_len(hash_algo);+	oi->at_cfg.seqnum_l++;++	if (oi->at_cfg.seqnum_l == 0xFFFFFFFF) {+		oi->at_cfg.seqnum_h++;+		oi->at_cfg.seqnum_l = 0;+	}++	/* Key must be reset. which is not handled as of now. */+	if ((oi->at_cfg.seqnum_l == 0xFFFFFFFF)+	    && (oi->at_cfg.seqnum_h == 0xFFFFFFFF)) {+		oi->at_cfg.seqnum_l = 0;+		oi->at_cfg.seqnum_h = 0;+	}++	memset(apad, 0, hash_len);++	if (src)+		memcpy(apad, src, ipv6_addr_size);++	memcpy(apad + ipv6_addr_size, ospf6_hash_apad_max,+	       (hash_len - ipv6_addr_size));++	ospf6_auth =+		(struct ospf6_auth_hdr *)((uint8_t *)oh + ntohs(oh->length));+	ospf6_auth->type = htons(OSPF6_AUTHENTICATION_CRYPTOGRAPHIC);+	ospf6_auth->length = htons(auth_len);+	ospf6_auth->reserved = 0;+	ospf6_auth->id = htons(key_id);+	ospf6_auth->seqnum_h = htonl(oi->at_cfg.seqnum_h);+	ospf6_auth->seqnum_l = htonl(oi->at_cfg.seqnum_l);+	memcpy(ospf6_auth->data, apad, hash_len);++	ospf6_auth_update_digest(oi, oh, ospf6_auth, auth_str, auth_len,+				 pkt_len, hash_algo);++	if (CHECK_FLAG(oi->at_cfg.flags, OSPF6_AUTH_TRAILER_KEYCHAIN_VALID)) {+		oi->at_cfg.hash_algo = KEYCHAIN_ALGO_NULL;+		if (oi->at_cfg.auth_key) {+			XFREE(MTYPE_OSPF6_AUTH_MANUAL_KEY, oi->at_cfg.auth_key);+			oi->at_cfg.auth_key = NULL;+		}++		oi->at_cfg.key_id = 0;+		UNSET_FLAG(oi->at_cfg.flags, OSPF6_AUTH_TRAILER_KEYCHAIN_VALID);+	}+}++void ospf6_auth_update_digest(struct ospf6_interface *oi,+			      struct ospf6_header *oh,+			      struct ospf6_auth_hdr *ospf6_auth, char *auth_str,+			      uint16_t auth_len, uint32_t pkt_len,+			      enum keychain_hash_algo algo)+{+	uint32_t hash_len = keychain_get_hash_len(algo);+	uint32_t block_s = keychain_get_block_size(algo);+	uint32_t k_len = strlen(auth_str);+	uint32_t ks_len = strlen(auth_str) + sizeof(CPID);+	unsigned char ipad[block_s];+	unsigned char opad[block_s];+	unsigned char ko[block_s], ks[ks_len], tmp[hash_len];+	unsigned char *first = NULL;+	unsigned char *second = NULL;+	unsigned char *first_mes, *second_mes;+	unsigned char *first_hash, *second_hash;++	memset(ko, 0, block_s);+	memcpy(ks, auth_str, k_len);+	memcpy(ks + k_len, &CPID, sizeof(CPID));+	if (ks_len > hash_len) {+		ospf6_hash_hmac_sha_digest(algo, ks, ks_len, tmp);+		memcpy(ko, tmp, hash_len);+	} else+		memcpy(ko, ks, ks_len);++	memcpy(ipad, ospf6_hash_ipad_max, block_s);+	memcpy(opad, ospf6_hash_opad_max, block_s);++	first = ospf6_hash_message_xor((unsigned char *)&ipad, ko, block_s);+	second = ospf6_hash_message_xor((unsigned char *)&opad, ko, block_s);++	first_mes = XMALLOC(MTYPE_OSPF6_AUTH_PKT, (block_s + pkt_len));+	if (first_mes == NULL) {+		XFREE(MTYPE_OSPF6_AUTH_HASH_XOR, first);+		XFREE(MTYPE_OSPF6_AUTH_HASH_XOR, second);+		zlog_err("Memory allocation for first message failed.");+		return;+	}++	memcpy(first_mes, first, block_s);+	memcpy(first_mes + block_s, oh, pkt_len);++	first_hash = XMALLOC(MTYPE_OSPF6_AUTH_HASH, hash_len);+	if (first_hash == NULL) {+		XFREE(MTYPE_OSPF6_AUTH_HASH_XOR, first);+		XFREE(MTYPE_OSPF6_AUTH_HASH_XOR, second);+		XFREE(MTYPE_OSPF6_AUTH_PKT, first_mes);+		zlog_err("Memory allocation for first hash failed.");+		return;+	}++	ospf6_hash_hmac_sha_digest(algo, first_mes, (block_s + pkt_len),+				   first_hash);++	second_mes = XMALLOC(MTYPE_OSPF6_AUTH_PKT, (block_s + hash_len));+	if (second_mes == NULL) {+		XFREE(MTYPE_OSPF6_AUTH_HASH_XOR, first);+		XFREE(MTYPE_OSPF6_AUTH_HASH_XOR, second);+		XFREE(MTYPE_OSPF6_AUTH_PKT, first_mes);+		XFREE(MTYPE_OSPF6_AUTH_HASH, first_hash);+		zlog_err("Memory allocation for second message failed.");

XMALLOC cannot fail by definition and will never return NULL

(affects all uses in multiple locations)

rameshabhinay

comment created time in 12 hours

Pull request review commentFRRouting/frr

OSPF6: Support OSPF6 authentication trailer RFC 7166

 void install_element_ospf6_debug_interface(void) 	install_element(CONFIG_NODE, &debug_ospf6_interface_cmd); 	install_element(CONFIG_NODE, &no_debug_ospf6_interface_cmd); }++void ospf6_auth_write_config(struct vty *vty, struct ospf6_auth_cfg *at_cfg)+{+	if (CHECK_FLAG(at_cfg->flags, OSPF6_AUTH_TRAILER_KEYCHAIN))+		vty_out(vty, " ipv6 ospf6 authentication keychain %s\n",+			at_cfg->keychain);+	else if (CHECK_FLAG(at_cfg->flags, OSPF6_AUTH_TRAILER_MANUAL_KEY))+		vty_out(vty,+			" ipv6 ospf6 authentication key-id %d hash-algo %s key %s\n",+			at_cfg->key_id,+			keychain_get_algo_name_by_id(at_cfg->hash_algo),+			at_cfg->auth_key);+}++DEFUN(ipv6_ospf6_intf_auth_trailer_keychain,+      ipv6_ospf6_intf_auth_trailer_keychain_cmd,+      "ipv6 ospf6 authentication keychain KEYCHAIN_NAME",+      IP6_STR OSPF6_STR+      "Enable authentication on this interface\n"+      "Keychain\n"+      "Keychain name\n")+{+	VTY_DECLVAR_CONTEXT(interface, ifp);+	int keychain_idx = 4;+	struct ospf6_interface *oi;++	assert(ifp);+	oi = (struct ospf6_interface *)ifp->info;+	if (oi == NULL)+		oi = ospf6_interface_create(ifp);++	assert(oi);+	if (CHECK_FLAG(oi->at_cfg.flags, OSPF6_AUTH_TRAILER_MANUAL_KEY)) {+		vty_out(vty,+			"Manual key configured, unconfigure it before configuring key chain\n");+		return CMD_WARNING_CONFIG_FAILED;+	}++	SET_FLAG(oi->at_cfg.flags, OSPF6_AUTH_TRAILER_KEYCHAIN);+	if (oi->at_cfg.keychain)+		XFREE(MTYPE_OSPF6_AUTH_KEYCHAIN, oi->at_cfg.keychain);++	oi->at_cfg.keychain =+		XSTRDUP(MTYPE_OSPF6_AUTH_KEYCHAIN, argv[keychain_idx]->arg);++	return CMD_SUCCESS;+}++DEFUN(no_ipv6_ospf6_intf_auth_trailer_keychain,+      no_ipv6_ospf6_intf_auth_trailer_keychain_cmd,+      "no ipv6 ospf6 authentication keychain [KEYCHAIN_NAME]",+      NO_STR IP6_STR OSPF6_STR+      "Enable authentication on this interface\n"+      "Keychain\n"+      "Keychain name\n")+{+	VTY_DECLVAR_CONTEXT(interface, ifp);+	struct ospf6_interface *oi;++	assert(ifp);+	oi = (struct ospf6_interface *)ifp->info;+	if (oi == NULL)+		oi = ospf6_interface_create(ifp);++	assert(oi);+	if (!CHECK_FLAG(oi->at_cfg.flags, OSPF6_AUTH_TRAILER_KEYCHAIN))+		return CMD_SUCCESS;++	if (oi->at_cfg.keychain) {+		oi->at_cfg.flags = 0;+		XFREE(MTYPE_OSPF6_AUTH_KEYCHAIN, oi->at_cfg.keychain);+		oi->at_cfg.keychain = NULL;+	}++	return CMD_SUCCESS;+}++DEFUN(ipv6_ospf6_intf_auth_trailer_key, ipv6_ospf6_intf_auth_trailer_key_cmd,+      "ipv6 ospf6 authentication key-id (1-65535) hash-algo "+#ifdef CRYPTO_INTERNAL+      "<md5|hmac-sha-256> "+#endif /* CRYPTO_INTERNAL */+#ifdef CRYPTO_OPENSSL+      "<md5|hmac-sha-256|hmac-sha-1|hmac-sha-384|hmac-sha-512> "+#endif /* CRYPTO_OPENSSL */+      "key WORD",+      IP6_STR OSPF6_STR+      "Authentication\n"+      "Key ID\n"+      "Key ID value\n"+      "Cryptographic-algorithm\n"+#ifdef CRYPTO_INTERNAL+      "Use MD5 algorithm\n"+      "Use HMAC-SHA-256 algorithm\n"+#endif /* CRYPTO_INTERNAL */+#ifdef CRYPTO_OPENSSL+      "Use MD5 algorithm\n"+      "Use HMAC-SHA-1 algorithm\n"+      "Use HMAC-SHA-256 algorithm\n"+      "Use HMAC-SHA-384 algorithm\n"+      "Use HMAC-SHA-512 algorithm\n"+#endif /* CRYPTO_OPENSSL */

#ifdef in the middle of DEFUN is very tricky and would break e.g. clippy (which you're not using here, but probably should too.)

Also, I think it would be better to always accept all types but print errors when they cannot be used. Otherwise the error for "algorithm not supported" is just "command not found" which is very confusing for an user because they cannot know if they just mistyped the command or FRR was compiled w/o the algo.

(... which makes the #ifdef go away too.)

rameshabhinay

comment created time in 12 hours

Pull request review commentFRRouting/frr

OSPF6: Support OSPF6 authentication trailer RFC 7166

 import ipaddr import ipaddress import sys+import pdb

leftover import from debugging?

rameshabhinay

comment created time in 11 hours

Pull request review commentFRRouting/frr

OSPF6: Support OSPF6 authentication trailer RFC 7166

 #include "ospf6d.h"  #include <netinet/ip6.h>+#include "lib/keychain.h"+#include "ospf6_auth_trailer.h"  DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_MESSAGE, "OSPF6 message"); DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_PACKET, "OSPF6 packet"); DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_FIFO, "OSPF6  FIFO queue");-+DECLARE_MTYPE(OSPF6_AUTH_MANUAL_KEY);

again DECLARE_MTYPE should be in .h file

rameshabhinay

comment created time in 12 hours

Pull request review commentFRRouting/frr

OSPF6: Support OSPF6 authentication trailer RFC 7166

 #ifndef OSPF6D_H #define OSPF6D_H +#include "config.h"

#include "config.h" does not belong in .h files, instead the first include in all .c files must be either config.h or zebra.h.

rameshabhinay

comment created time in 11 hours

Pull request review commentFRRouting/frr

OSPF6: Support OSPF6 authentication trailer RFC 7166

 #include "ospf6d.h"  #include <netinet/ip6.h>+#include "lib/keychain.h"+#include "ospf6_auth_trailer.h"  DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_MESSAGE, "OSPF6 message"); DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_PACKET, "OSPF6 packet"); DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_FIFO, "OSPF6  FIFO queue");-+DECLARE_MTYPE(OSPF6_AUTH_MANUAL_KEY); unsigned char conf_debug_ospf6_message[6] = {0x03, 0, 0, 0, 0, 0};-static const struct message ospf6_message_type_str[] = {+const struct message ospf6_message_type_str[] = {

When using this array from another .c file, the size is not known ([]) and therefore it can't be checked against access past the end of the array. Please create a const char *ospf6_message_type(uint8_t message); function with a built-in range check instead. (Or a %iOMT printfrr specifier.)

rameshabhinay

comment created time in 11 hours

PullRequestReviewEvent

Pull request review commentFRRouting/frr

OSPF6: Support OSPF6 authentication trailer RFC 7166

+/*+ * Copyright (C) 2021 Abhinay Ramesh+ *+ * This file is part of GNU Zebra.+ *+ * GNU Zebra is free software; you can redistribute it and/or modify it+ * under the terms of the GNU General Public License as published by the+ * Free Software Foundation; either version 2, or (at your option) any+ * later version.+ *+ * GNU Zebra is distributed in the hope that it will be useful, but+ * WITHOUT ANY WARRANTY; without even the implied warranty of+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU+ * General Public License for more details.+ *+ * You should have received a copy of the GNU General Public License along+ * with this program; see the file COPYING; if not, write to the Free Software+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA+ */++#include "memory.h"+#include "zebra.h"+#include "ospf6d.h"+#include "vty.h"+#include "command.h"+#include "md5.h"+#include "sha256.h"+#include "lib/zlog.h"+#include "ospf6_message.h"+#include "ospf6_interface.h"+#include "ospf6_neighbor.h"+#include "ospf6_proto.h"+#include "ospf6_auth_trailer.h"+#include "ospf6_route.h"+#include "ospf6_zebra.h"+#include "lib/keychain.h"++unsigned char conf_debug_ospf6_auth[2];+DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_AUTH_PKT, "OSPF6 auth packet");+DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_AUTH_HASH, "OSPF6 auth hash");+DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_AUTH_HASH_XOR, "OSPF6 auth hash xor");+DECLARE_MTYPE(OSPF6_AUTH_MANUAL_KEY);

DECLARE_MTYPE should not ever go into a .c file, it should be in a .h file with DEFINE_MTYPE in the .c file

rameshabhinay

comment created time in 12 hours

PullRequestReviewEvent

pull request commentFRRouting/frr

ospf6d: virtual link support

This is a DRAFT. I'm aware it fails things, has conflicts and formatting issues. It's posted publicly for visiblity and to avoid duplicate work.

eqvinox

comment created time in a day

pull request commentFRRouting/frr

ospf6d: add PtMP interface mode & related bits

(I'm aware this needs to be rebased. It's a DRAFT. I pushed it out for visibility and to avoid duplicate work. Due to priorities/resource allocations, this is probably going to sit here for a bit.)

eqvinox

comment created time in a day

Pull request review commentFRRouting/frr

ospf6d: add PtMP interface mode & related bits

 void ospf6_interface_connected_route_update(struct interface *ifp) 			} 		} +		if (oi->state == OSPF6_INTERFACE_LOOPBACK

I looked at that before working on this & it looked like it was inactive (and it's autoclose now.) Either way the changes in this PR include a superset of #8061 (since the LA bit has additional rules for PtMP support.)

eqvinox

comment created time in a day

PullRequestReviewEvent
PullRequestReviewEvent

Pull request review commentFRRouting/frr

ospf6d: add PtMP interface mode & related bits

 OSPF6 interface     Sets interface's Inf-Trans-Delay. Default value is 1. -.. clicmd:: ipv6 ospf6 network (broadcast|point-to-point)+.. clicmd:: ipv6 ospf6 network (broadcast|point-to-point|point-to-multipoint)     Set explicitly network type for specified interface. +   The only functional difference between ``point-to-point`` (PtP) and+   ``point-to-multipoint`` (PtMP) mode is the packet addressing for database+   flooding and updates.  PtP will use multicast packets while PtMP will+   unicast them.  Apart from this,+   :clicmd:`ipv6 ospf6 p2p-p2mp connected-prefixes <include|exclude>` has a+   different default for PtP and PtMP.  There are no other differences, in+   particular FRR does not impose a limit of one neighbor in PtP mode.++   FRR does not support NBMA mode for IPv6 and likely never will, as NBMA is+   considered deprecated for IPv6.  Refer to `this IETF OSPF working group+   discussion+   <https://mailarchive.ietf.org/arch/msg/ospf/8GAbr4qSMMt5J7SvAcZQ1H7ARhk/>`_+   for context.++OSPF6 point-to-point and point-to-multipoint operation+======================================================++OSPFv3, by default, operates in broadcast mode where it elects a DR and BDR+for each network segment.  This can be changed to point-to-point (PtP) /+point-to-multipoint (PtMP) mode by configuration.  The actual physical+interface characteristics do not matter for this setting, all interfaces can+be configured for all modes.  However, routers must be configured for the same+mode to form adjacencies.++The main advantages of PtP/PtMP mode are:++- no DR/BDR election+- adjacencies can be suppressed in a pairwise manner for any two routers, e.g.+  to represent the underlying topology if it isn't a true full mesh+- distinct costs can be set for each pair of routers and direction++The main downside is less efficient flooding on networks with a large number+of OSPFv3 routers.

That's kinda listed as an advantage because the very same thing allows you to control metrics in a n×m manner :smile: … but yeah that's another reason why I put the "advanced options, make sure you know what you're doing" above.

eqvinox

comment created time in a day

Pull request review commentFRRouting/frr

ospf6d: add PtMP interface mode & related bits

 struct ospf6_interface { DECLARE_QOBJ_TYPE(ospf6_interface);  /* interface state */-#define OSPF6_INTERFACE_NONE             0-#define OSPF6_INTERFACE_DOWN             1-#define OSPF6_INTERFACE_LOOPBACK         2-#define OSPF6_INTERFACE_WAITING          3-#define OSPF6_INTERFACE_POINTTOPOINT     4-#define OSPF6_INTERFACE_DROTHER          5-#define OSPF6_INTERFACE_BDR              6-#define OSPF6_INTERFACE_DR               7-#define OSPF6_INTERFACE_MAX              8+#define OSPF6_INTERFACE_NONE               0

POINTTOMULTIPOINT is longer than the other names… without the whitespace change it's this:

#define OSPF6_INTERFACE_WAITING          3
#define OSPF6_INTERFACE_POINTTOPOINT     4
#define OSPF6_INTERFACE_POINTTOMULTIPOINT 5
#define OSPF6_INTERFACE_DROTHER          6
#define OSPF6_INTERFACE_BDR              7

⇒ I'd say the whitespace change is appropriate.

eqvinox

comment created time in a day

PullRequestReviewEvent

PR opened FRRouting/frr

ospf6d: virtual link support

WORK IN PROGRESS

Posting this as a draft PR so people are aware of it & we don't waste time if anyone else works on OSPFv3 virtual links.

This passes preliminary testing, but still has a bunch of rough edges. Also, no docs and tests yet. It'll be a bit until those come due to priorities being this way :(

NB: this is based on top of the PtMP draft (#9198) since some of the changes are related.

+2096 -307

0 comment

24 changed files

pr created time in a day

push eventopensourcerouting/frr

David Lamparter

commit sha 01cc857375ad1517fbbda5094733252bf06926e2

ospf6d: connected prefix toggle for PtP/PtMP To announce connected prefixes, or not to announce connected prefixes, that is the question... Signed-off-by: David Lamparter <equinox@opensourcerouting.org>

view details

David Lamparter

commit sha 801f69fd02b8dd7b72f7ed0cb894fad1b2463abe

doc: update user docs for OSPFv3 PtMP changes Update & add docs for all the stuff in the previous 10-ish commits. Signed-off-by: David Lamparter <equinox@opensourcerouting.org>

view details

David Lamparter

commit sha 41be9358ebb2db0abf983fea24f8984fcca4ae9a

lib: don't delete item that wasn't added The RB-tree of interfaces only contains interfaces that have a non-empty name. Don't try to remove an interface whose name is empty and which was therefore never added to the tree. Signed-off-by: David Lamparter <equinox@opensourcerouting.org>

view details

David Lamparter

commit sha 48f21d9ef63de94fd07427d81f7fce7a459231f5

ospf6d: allow creating interface w/o LSDBs To support virtual links, it makes sense to put a dummy interface into the backbone area, which virtual links are neighbors on. That interface shouldn't ever have its various LSDBs used for anything, so the "basic" create/delete added here doesn't create them.

view details

David Lamparter

commit sha 39d0f1741f8d337f9fe26c7d0dd0b3f37cf8782f

ospf6d: factor out interface name printing The dummy interface for virtual link support has an empty interface name ("", not null pointer), which can be confusing when printed. Create an `ospf6_ifname()` helper for JSON output and a `%pOI` printfrr modifier for logging/CLI. (Latter also shortens some code a bit.)

view details

David Lamparter

commit sha be550dc1a2517cabd570f4240bf02ed4f98eff4e

ospf6d: factor out interface address filter Need to access this to find a LA for virtual links if there is none otherwise, so split the filtering into its own function. Also gets rid of a bunch of weird one-use macros while at it.

view details

David Lamparter

commit sha 58e5044c992d334cf1b8df16a6b781651edbdda8

ospf6d: /128 addresses are always local A connected prefix with a /128 prefix length is... *drumroll* ... a local address. Flag it as such so it can be used for virtual links.

view details

David Lamparter

commit sha c5aac5f0e39911ad0ee80bceef0a7b55a1880394

ospf6d: chop RX function in two Need to insert virtual link handling inbetween this, so make the second half its own independent function.

view details

David Lamparter

commit sha e07d8972ab239f21e3eb4a26e92133b049200cc9

ospf6d: virtual link support Passed preliminary testing, but still somewhat experimental.

view details

push time in a day

pull request commentFRRouting/frr

workflow: document release scheduling discussed

Whoops, changed the dates in the table but forgot them in the text above…

eqvinox

comment created time in 2 days

push eventopensourcerouting/frr

David Lamparter

commit sha 247a95c872e728353743d2ee82a9f786db6eaf33

workflow: document release scheduling discussed As discussed in the weekly meeting today, this is what we're trying to work with for the time being. (Date calculator included as a bonus goodie ;) Signed-off-by: David Lamparter <equinox@opensourcerouting.org>

view details

push time in 2 days

PR opened FRRouting/frr

workflow: document release scheduling discussed

As discussed in the weekly meeting today, this is what we're trying to work with for the time being.

(Date calculator included as a bonus goodie ;)

+91 -16

0 comment

2 changed files

pr created time in 2 days

create barnchopensourcerouting/frr

branch : workflow-release-sched

created branch time in 2 days

pull request commentFRRouting/frr

pimd: Candidate RP support

The refactoring/restructuring should all be contained in this commit: 00e0778 (#9180)

I don't think I can split it off further, it doesn't really divide into a cleanup and a changes step, particularly since the previous code was wrong in some corner cases.

eqvinox

comment created time in 2 days