mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-08-06 10:54:47 +00:00
vrrpd: fix packet encode
* Properly encode VRRP packets * Calculate checksum appropriately * Update signature to provide caller both packet and result length Signed-off-by: Quentin Young <qlyoung@cumulusnetworks.com>
This commit is contained in:
parent
ef4cc1ebff
commit
3eca38577a
@ -19,32 +19,48 @@
|
|||||||
*/
|
*/
|
||||||
#include <zebra.h>
|
#include <zebra.h>
|
||||||
|
|
||||||
#include "memory.h"
|
#include "lib/memory.h"
|
||||||
#include "ipaddr.h"
|
#include "lib/ipaddr.h"
|
||||||
|
#include "lib/checksum.h"
|
||||||
|
|
||||||
#include "vrrp_packet.h"
|
#include "vrrp_packet.h"
|
||||||
|
|
||||||
/*
|
ssize_t vrrp_pkt_build(struct vrrp_pkt **pkt, uint8_t vrid, uint8_t prio,
|
||||||
* Builds a VRRP packet.
|
|
||||||
*/
|
|
||||||
struct vrrp_pkt *vrrp_pkt_build(uint8_t vrid, uint8_t prio,
|
|
||||||
uint16_t max_adver_int, bool v6, uint8_t numip,
|
uint16_t max_adver_int, bool v6, uint8_t numip,
|
||||||
void **ips)
|
void **ips)
|
||||||
{
|
{
|
||||||
|
/* Used for pointer math when filling IPvX field */
|
||||||
|
struct in6_addr *v6ptr;
|
||||||
|
struct in_addr *v4ptr;
|
||||||
|
|
||||||
size_t addrsz = v6 ? sizeof(struct in6_addr) : sizeof(struct in_addr);
|
size_t addrsz = v6 ? sizeof(struct in6_addr) : sizeof(struct in_addr);
|
||||||
struct vrrp_pkt *pkt =
|
size_t pktsize = sizeof(struct vrrp_hdr) + addrsz * numip;
|
||||||
XCALLOC(MTYPE_TMP, sizeof(struct vrrp_pkt) + addrsz * numip);
|
*pkt = XCALLOC(MTYPE_TMP, pktsize);
|
||||||
|
|
||||||
pkt->hdr.version = VRRP_VERSION;
|
v6ptr = (struct in6_addr *) (*pkt)->addrs;
|
||||||
pkt->hdr.type = VRRP_TYPE_ADVERTISEMENT;
|
v4ptr = (struct in_addr *) (*pkt)->addrs;
|
||||||
pkt->hdr.vrid = vrid;
|
|
||||||
pkt->hdr.priority = prio;
|
|
||||||
pkt->hdr.v3.rsvd = 0;
|
|
||||||
pkt->hdr.v3.adver_int = max_adver_int;
|
|
||||||
for (uint8_t i = 0; i < numip; i++)
|
|
||||||
memcpy(&pkt->addrs[i].v4, ips[i], addrsz);
|
|
||||||
/* FIXME */
|
|
||||||
pkt->hdr.chksum = 0;
|
|
||||||
|
|
||||||
return pkt;
|
(*pkt)->hdr.vertype |= VRRP_VERSION << 4;
|
||||||
|
(*pkt)->hdr.vertype |= VRRP_TYPE_ADVERTISEMENT;
|
||||||
|
(*pkt)->hdr.vrid = vrid;
|
||||||
|
(*pkt)->hdr.priority = prio;
|
||||||
|
(*pkt)->hdr.naddr = numip;
|
||||||
|
(*pkt)->hdr.v3.adver_int = htons(max_adver_int);
|
||||||
|
|
||||||
|
char buf[INET_ADDRSTRLEN];
|
||||||
|
for (int i = 0; i < numip; i++) {
|
||||||
|
/* If v4, treat as array of v4 addresses */
|
||||||
|
inet_ntop(AF_INET, ips[i], buf, sizeof(buf));
|
||||||
|
if (!v6)
|
||||||
|
memcpy(&v4ptr[i], ips[i], addrsz);
|
||||||
|
else
|
||||||
|
memcpy(&v6ptr[i], ips[i], addrsz);
|
||||||
|
inet_ntop(AF_INET, &v4ptr[i], buf, sizeof(buf));
|
||||||
|
}
|
||||||
|
(*pkt)->hdr.chksum = 0;
|
||||||
|
|
||||||
|
uint16_t chksum = in_cksum(*pkt, pktsize);
|
||||||
|
(*pkt)->hdr.chksum = htons(chksum);
|
||||||
|
|
||||||
|
return pktsize;
|
||||||
}
|
}
|
||||||
|
@ -30,8 +30,12 @@
|
|||||||
* Shared header for VRRPv2/v3 packets.
|
* Shared header for VRRPv2/v3 packets.
|
||||||
*/
|
*/
|
||||||
struct vrrp_hdr {
|
struct vrrp_hdr {
|
||||||
uint8_t version : 4;
|
/*
|
||||||
uint8_t type : 4;
|
* H L H L
|
||||||
|
* 0000 0000
|
||||||
|
* ver type
|
||||||
|
*/
|
||||||
|
uint8_t vertype;
|
||||||
uint8_t vrid;
|
uint8_t vrid;
|
||||||
uint8_t priority;
|
uint8_t priority;
|
||||||
uint8_t naddr;
|
uint8_t naddr;
|
||||||
@ -42,9 +46,13 @@ struct vrrp_hdr {
|
|||||||
uint8_t adver_int;
|
uint8_t adver_int;
|
||||||
} v2;
|
} v2;
|
||||||
struct {
|
struct {
|
||||||
/* advertisement interval (in centiseconds) */
|
/*
|
||||||
uint16_t rsvd : 4;
|
* advertisement interval (in centiseconds)
|
||||||
uint16_t adver_int : 12;
|
* H L H L
|
||||||
|
* 0000 000000000000
|
||||||
|
* rsvd adver_int
|
||||||
|
*/
|
||||||
|
uint16_t adver_int;
|
||||||
} v3;
|
} v3;
|
||||||
};
|
};
|
||||||
uint16_t chksum;
|
uint16_t chksum;
|
||||||
@ -60,7 +68,29 @@ struct vrrp_pkt {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Builds a VRRP packet.
|
* Builds a VRRP packet.
|
||||||
|
*
|
||||||
|
* pkt
|
||||||
|
* Pointer to store pointer to result buffer in
|
||||||
|
*
|
||||||
|
* vrid
|
||||||
|
* Virtual Router Identifier
|
||||||
|
*
|
||||||
|
* prio
|
||||||
|
* Virtual Router Priority
|
||||||
|
*
|
||||||
|
* max_adver_int
|
||||||
|
* time between ADVERTISEMENTs
|
||||||
|
*
|
||||||
|
* v6
|
||||||
|
* whether 'ips' is an array of v4 or v6 addresses
|
||||||
|
*
|
||||||
|
* numip
|
||||||
|
* number of IPvX addresses in 'ips'
|
||||||
|
*
|
||||||
|
* ips
|
||||||
|
* array of pointer to either struct in_addr (v6 = false) or struct in6_addr
|
||||||
|
* (v6 = true)
|
||||||
*/
|
*/
|
||||||
struct vrrp_pkt *vrrp_pkt_build(uint8_t vrid, uint8_t prio,
|
ssize_t vrrp_pkt_build(struct vrrp_pkt **pkt, uint8_t vrid, uint8_t prio,
|
||||||
uint16_t max_adver_int, bool v6, uint8_t numip,
|
uint16_t max_adver_int, bool v6, uint8_t numip,
|
||||||
void **ips);
|
void **ips);
|
||||||
|
Loading…
Reference in New Issue
Block a user