summaryrefslogtreecommitdiff
path: root/ripd/ripd.c
diff options
context:
space:
mode:
Diffstat (limited to 'ripd/ripd.c')
-rw-r--r--ripd/ripd.c71
1 files changed, 68 insertions, 3 deletions
diff --git a/ripd/ripd.c b/ripd/ripd.c
index e0ff0430f8..cd2ddb1eba 100644
--- a/ripd/ripd.c
+++ b/ripd/ripd.c
@@ -37,7 +37,9 @@
#include "if_rmap.h"
#include "plist.h"
#include "distribute.h"
+#ifdef CRYPTO_INTERNAL
#include "md5.h"
+#endif
#include "keychain.h"
#include "privs.h"
#include "lib_errors.h"
@@ -870,7 +872,11 @@ static int rip_auth_md5(struct rip_packet *packet, struct sockaddr_in *from,
struct rip_md5_data *md5data;
struct keychain *keychain;
struct key *key;
+#ifdef CRYPTO_OPENSSL
+ EVP_MD_CTX *ctx;
+#elif CRYPTO_INTERNAL
MD5_CTX ctx;
+#endif
uint8_t digest[RIP_AUTH_MD5_SIZE];
uint16_t packet_len;
char auth_str[RIP_AUTH_MD5_SIZE] = {};
@@ -934,11 +940,21 @@ static int rip_auth_md5(struct rip_packet *packet, struct sockaddr_in *from,
return 0;
/* MD5 digest authentication. */
+#ifdef CRYPTO_OPENSSL
+ unsigned int md5_size = RIP_AUTH_MD5_SIZE;
+ ctx = EVP_MD_CTX_new();
+ EVP_DigestInit(ctx, EVP_md5());
+ EVP_DigestUpdate(ctx, packet, packet_len + RIP_HEADER_SIZE);
+ EVP_DigestUpdate(ctx, auth_str, RIP_AUTH_MD5_SIZE);
+ EVP_DigestFinal(ctx, digest, &md5_size);
+ EVP_MD_CTX_free(ctx);
+#elif CRYPTO_INTERNAL
memset(&ctx, 0, sizeof(ctx));
MD5Init(&ctx);
MD5Update(&ctx, packet, packet_len + RIP_HEADER_SIZE);
MD5Update(&ctx, auth_str, RIP_AUTH_MD5_SIZE);
MD5Final(digest, &ctx);
+#endif
if (memcmp(md5data->digest, digest, RIP_AUTH_MD5_SIZE) == 0)
return packet_len;
@@ -1063,7 +1079,11 @@ static void rip_auth_md5_set(struct stream *s, struct rip_interface *ri,
size_t doff, char *auth_str, int authlen)
{
unsigned long len;
+#ifdef CRYPTO_OPENSSL
+ EVP_MD_CTX *ctx;
+#elif CRYPTO_INTERNAL
MD5_CTX ctx;
+#endif
unsigned char digest[RIP_AUTH_MD5_SIZE];
/* Make it sure this interface is configured as MD5
@@ -1092,11 +1112,21 @@ static void rip_auth_md5_set(struct stream *s, struct rip_interface *ri,
stream_putw(s, RIP_AUTH_DATA);
/* Generate a digest for the RIP packet. */
+#ifdef CRYPTO_OPENSSL
+ unsigned int md5_size = RIP_AUTH_MD5_SIZE;
+ ctx = EVP_MD_CTX_new();
+ EVP_DigestInit(ctx, EVP_md5());
+ EVP_DigestUpdate(ctx, STREAM_DATA(s), stream_get_endp(s));
+ EVP_DigestUpdate(ctx, auth_str, RIP_AUTH_MD5_SIZE);
+ EVP_DigestFinal(ctx, digest, &md5_size);
+ EVP_MD_CTX_free(ctx);
+#elif CRYPTO_INTERNAL
memset(&ctx, 0, sizeof(ctx));
MD5Init(&ctx);
MD5Update(&ctx, STREAM_DATA(s), stream_get_endp(s));
MD5Update(&ctx, auth_str, RIP_AUTH_MD5_SIZE);
MD5Final(digest, &ctx);
+#endif
/* Copy the digest to the packet. */
stream_write(s, digest, RIP_AUTH_MD5_SIZE);
@@ -1365,7 +1395,7 @@ int rip_create_socket(struct vrf *vrf)
/* Make datagram socket. */
if (vrf->vrf_id != VRF_DEFAULT)
vrf_dev = vrf->name;
- frr_elevate_privs(&ripd_privs) {
+ frr_with_privs(&ripd_privs) {
sock = vrf_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, vrf->vrf_id,
vrf_dev);
if (sock < 0) {
@@ -1385,7 +1415,7 @@ int rip_create_socket(struct vrf *vrf)
#endif
setsockopt_so_recvbuf(sock, RIP_UDP_RCV_BUF);
- frr_elevate_privs(&ripd_privs) {
+ frr_with_privs(&ripd_privs) {
if ((ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr)))
< 0) {
zlog_err("%s: Can't bind socket %d to %s port %d: %s",
@@ -3611,6 +3641,41 @@ static int rip_vrf_enable(struct vrf *vrf)
int socket;
rip = rip_lookup_by_vrf_name(vrf->name);
+ if (!rip) {
+ char *old_vrf_name = NULL;
+
+ rip = (struct rip *)vrf->info;
+ if (!rip)
+ return 0;
+ /* update vrf name */
+ if (rip->vrf_name)
+ old_vrf_name = rip->vrf_name;
+ rip->vrf_name = XSTRDUP(MTYPE_RIP_VRF_NAME, vrf->name);
+ /*
+ * HACK: Change the RIP VRF in the running configuration directly,
+ * bypassing the northbound layer. This is necessary to avoid deleting
+ * the RIP and readding it in the new VRF, which would have
+ * several implications.
+ */
+ if (yang_module_find("frr-ripd") && old_vrf_name) {
+ struct lyd_node *rip_dnode;
+
+ pthread_rwlock_wrlock(&running_config->lock);
+ {
+ rip_dnode = yang_dnode_get(
+ running_config->dnode,
+ "/frr-ripd:ripd/instance[vrf='%s']/vrf",
+ old_vrf_name);
+ if (rip_dnode) {
+ yang_dnode_change_leaf(rip_dnode, vrf->name);
+ running_config->version++;
+ }
+ }
+ pthread_rwlock_unlock(&running_config->lock);
+ }
+ if (old_vrf_name)
+ XFREE(MTYPE_RIP_VRF_NAME, old_vrf_name);
+ }
if (!rip || rip->enabled)
return 0;
@@ -3652,7 +3717,7 @@ static int rip_vrf_disable(struct vrf *vrf)
void rip_vrf_init(void)
{
vrf_init(rip_vrf_new, rip_vrf_enable, rip_vrf_disable, rip_vrf_delete,
- NULL);
+ rip_vrf_enable);
}
void rip_vrf_terminate(void)