Skip to content

Commit

Permalink
RDNSS section support more ipv6 aaddrss
Browse files Browse the repository at this point in the history
RFC 6106 recommended that the number of RDNSS addresses thatshould be learned and maintained through the RDNSS RA option should be limited to three.  RFC 8106 removes that recommendation; thus, the number of RDNSS addresses to maintain is determined by an implementer's local policy.The number of RDNSS addresses to maintain is determined by the user's own profile
  • Loading branch information
WenChao1Hou committed Oct 30, 2022
1 parent c8a11fd commit 746ec1e
Show file tree
Hide file tree
Showing 8 changed files with 44 additions and 76 deletions.
4 changes: 1 addition & 3 deletions defaults.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,9 +205,7 @@ struct nd_opt_rdnss_info_local {
uint8_t nd_opt_rdnssi_len;
uint16_t nd_opt_rdnssi_pref_flag_reserved;
uint32_t nd_opt_rdnssi_lifetime;
struct in6_addr nd_opt_rdnssi_addr1;
struct in6_addr nd_opt_rdnssi_addr2;
struct in6_addr nd_opt_rdnssi_addr3;
struct in6_addr nd_opt_rdnssi_addr[];
};
/* pref/flag/reserved field : yyyyx00000000000 (big endian) - 00000000yyyyx000 (little indian); where yyyy = pref, x = flag */
#if BYTE_ORDER == BIG_ENDIAN
Expand Down
26 changes: 9 additions & 17 deletions gram.y
Original file line number Diff line number Diff line change
Expand Up @@ -786,24 +786,15 @@ rdnssaddr : IPV6ADDR
rdnss_init_defaults(rdnss, iface);
}

switch (rdnss->AdvRDNSSNumber) {
case 0:
memcpy(&rdnss->AdvRDNSSAddr1, $1, sizeof(struct in6_addr));
rdnss->AdvRDNSSNumber++;
break;
case 1:
memcpy(&rdnss->AdvRDNSSAddr2, $1, sizeof(struct in6_addr));
rdnss->AdvRDNSSNumber++;
break;
case 2:
memcpy(&rdnss->AdvRDNSSAddr3, $1, sizeof(struct in6_addr));
rdnss->AdvRDNSSNumber++;
break;
default:
flog(LOG_CRIT, "too many addresses in RDNSS section");
ABORT;
rdnss->AdvRDNSSNumber++;
rdnss->AdvRDNSSAddr =
realloc(rdnss->AdvRDNSSAddr,
rdnss->AdvRDNSSNumber * sizeof(struct in6_addr));
if (rdnss->AdvRDNSSAddr == NULL) {
flog(LOG_CRIT, "realloc failed: %s", strerror(errno));
ABORT;
}

memcpy(&rdnss->AdvRDNSSAddr[rdnss->AdvRDNSSNumber - 1], $1, sizeof(struct in6_addr));
}
;

Expand Down Expand Up @@ -1066,6 +1057,7 @@ static void cleanup(void)
}

if (rdnss) {
free(rdnss->AdvRDNSSAddr);
free(rdnss);
rdnss = 0;
}
Expand Down
1 change: 1 addition & 0 deletions interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,7 @@ static void free_iface_list(struct Interface *iface)
while (rdnss) {
struct AdvRDNSS *next_rdnss = rdnss->next;

free(rdnss->AdvRDNSSAddr);
free(rdnss);
rdnss = next_rdnss;
}
Expand Down
45 changes: 11 additions & 34 deletions process.c
Original file line number Diff line number Diff line change
Expand Up @@ -322,44 +322,21 @@ static void process_ra(struct Interface *iface, unsigned char *msg, int len, str
break;
case ND_OPT_RDNSS_INFORMATION: {
char rdnss_str[INET6_ADDRSTRLEN];
struct AdvRDNSS *rdnss = 0;
struct nd_opt_rdnss_info_local *rdnssinfo = (struct nd_opt_rdnss_info_local *)opt_str;
if (len < sizeof(*rdnssinfo))
return;
int count = rdnssinfo->nd_opt_rdnssi_len;

/* Check the RNDSS addresses received */
switch (count) {
case 7:
rdnss = iface->AdvRDNSSList;
if (!check_rdnss_presence(rdnss, &rdnssinfo->nd_opt_rdnssi_addr3)) {
/* no match found in iface->AdvRDNSSList */
addrtostr(&rdnssinfo->nd_opt_rdnssi_addr3, rdnss_str, sizeof(rdnss_str));
flog(LOG_WARNING, "RDNSS address %s received on %s from %s is not advertised by us",
rdnss_str, iface->props.name, addr_str);
}
/* FALLTHROUGH */
case 5:
rdnss = iface->AdvRDNSSList;
if (!check_rdnss_presence(rdnss, &rdnssinfo->nd_opt_rdnssi_addr2)) {
/* no match found in iface->AdvRDNSSList */
addrtostr(&rdnssinfo->nd_opt_rdnssi_addr2, rdnss_str, sizeof(rdnss_str));
flog(LOG_WARNING, "RDNSS address %s received on %s from %s is not advertised by us",
rdnss_str, iface->props.name, addr_str);
}
/* FALLTHROUGH */
case 3:
rdnss = iface->AdvRDNSSList;
if (!check_rdnss_presence(rdnss, &rdnssinfo->nd_opt_rdnssi_addr1)) {
/* no match found in iface->AdvRDNSSList */
addrtostr(&rdnssinfo->nd_opt_rdnssi_addr1, rdnss_str, sizeof(rdnss_str));
flog(LOG_WARNING, "RDNSS address %s received on %s from %s is not advertised by us",
rdnss_str, iface->props.name, addr_str);
}

break;
default:
flog(LOG_ERR, "invalid len %i in RDNSS option on %s from %s", count, iface->props.name, addr_str);
if (rdnssinfo->nd_opt_rdnssi_len > 2) {
for (int i = 0; i < (rdnssinfo->nd_opt_rdnssi_len - 1) / 2; i++) {
if (!check_rdnss_presence(iface->AdvRDNSSList, &rdnssinfo->nd_opt_rdnssi_addr[i])) {
addrtostr(&rdnssinfo->nd_opt_rdnssi_addr[i], rdnss_str, sizeof(rdnss_str));
flog(LOG_WARNING, "RDNSS address %s received on %s from %s is not advertised by us",
rdnss_str, iface->props.name, addr_str);
}
}
} else {
flog(LOG_ERR, "invalid len %i in RDNSS option on %s from %s",
rdnssinfo->nd_opt_rdnssi_len, iface->props.name, addr_str);
}

break;
Expand Down
4 changes: 1 addition & 3 deletions radvd.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,9 +198,7 @@ struct AdvRDNSS {
int AdvRDNSSNumber;
uint32_t AdvRDNSSLifetime;
int FlushRDNSSFlag;
struct in6_addr AdvRDNSSAddr1;
struct in6_addr AdvRDNSSAddr2;
struct in6_addr AdvRDNSSAddr3;
struct in6_addr *AdvRDNSSAddr;

struct AdvRDNSS *next;
};
Expand Down
11 changes: 2 additions & 9 deletions radvdump.c
Original file line number Diff line number Diff line change
Expand Up @@ -402,15 +402,8 @@ static void print_ff(unsigned char *msg, int len, struct sockaddr_in6 *addr, int

printf("\n\tRDNSS");

addrtostr(&rdnss_info->nd_opt_rdnssi_addr1, prefix_str, sizeof(prefix_str));
printf(" %s", prefix_str);

if (rdnss_info->nd_opt_rdnssi_len >= 5) {
addrtostr(&rdnss_info->nd_opt_rdnssi_addr2, prefix_str, sizeof(prefix_str));
printf(" %s", prefix_str);
}
if (rdnss_info->nd_opt_rdnssi_len >= 7) {
addrtostr(&rdnss_info->nd_opt_rdnssi_addr3, prefix_str, sizeof(prefix_str));
for (int i = 0; i < (rdnss_info->nd_opt_rdnssi_len - 1) / 2; i++) {
addrtostr(&rdnss_info->nd_opt_rdnssi_addr[i], prefix_str, sizeof(prefix_str));
printf(" %s", prefix_str);
}

Expand Down
21 changes: 15 additions & 6 deletions send.c
Original file line number Diff line number Diff line change
Expand Up @@ -584,8 +584,10 @@ static struct safe_buffer_list *add_ra_options_route(struct safe_buffer_list *sb
static struct safe_buffer_list *add_ra_options_rdnss(struct safe_buffer_list *sbl, struct Interface const *iface,
struct AdvRDNSS const *rdnss, int cease_adv, struct in6_addr const *dest)
{
struct safe_buffer *rdnss_addr = new_safe_buffer();
while (rdnss) {
struct nd_opt_rdnss_info_local rdnssinfo;
rdnss_addr->used = 0;

if (!cease_adv && !schedule_option_rdnss(dest, iface, rdnss)) {
rdnss = rdnss->next;
Expand All @@ -594,6 +596,12 @@ static struct safe_buffer_list *add_ra_options_rdnss(struct safe_buffer_list *sb

memset(&rdnssinfo, 0, sizeof(rdnssinfo));

size_t const bytes = sizeof(rdnssinfo) + sizeof(struct in6_addr) * rdnss->AdvRDNSSNumber;
if (bytes > (256 * 8)) {
flog(LOG_ERR, "RDNSS too long for RA option, must be < 2048 bytes. Exiting.");
exit(1);
}

rdnssinfo.nd_opt_rdnssi_type = ND_OPT_RDNSS_INFORMATION;
rdnssinfo.nd_opt_rdnssi_len = 1 + 2 * rdnss->AdvRDNSSNumber;
rdnssinfo.nd_opt_rdnssi_pref_flag_reserved = 0;
Expand All @@ -604,16 +612,17 @@ static struct safe_buffer_list *add_ra_options_rdnss(struct safe_buffer_list *sb
rdnssinfo.nd_opt_rdnssi_lifetime = htonl(rdnss->AdvRDNSSLifetime);
}

memcpy(&rdnssinfo.nd_opt_rdnssi_addr1, &rdnss->AdvRDNSSAddr1, sizeof(struct in6_addr));
memcpy(&rdnssinfo.nd_opt_rdnssi_addr2, &rdnss->AdvRDNSSAddr2, sizeof(struct in6_addr));
memcpy(&rdnssinfo.nd_opt_rdnssi_addr3, &rdnss->AdvRDNSSAddr3, sizeof(struct in6_addr));

sbl = safe_buffer_list_append(sbl);
safe_buffer_append(sbl->sb, &rdnssinfo,
sizeof(rdnssinfo) - (3 - rdnss->AdvRDNSSNumber) * sizeof(struct in6_addr));
safe_buffer_append(sbl->sb, &rdnssinfo, sizeof(rdnssinfo));
for (int i = 0; i < rdnss->AdvRDNSSNumber; i++) {
safe_buffer_append(rdnss_addr, &rdnss->AdvRDNSSAddr[i], sizeof(struct in6_addr));
}
safe_buffer_append(sbl->sb, rdnssbuf->buffer, rdnssbuf->used);
safe_buffer_free(rdnssbuf);

rdnss = rdnss->next;
}
safe_buffer_free(rdnss_addr);

return sbl;
}
Expand Down
8 changes: 4 additions & 4 deletions util.c
Original file line number Diff line number Diff line change
Expand Up @@ -187,10 +187,10 @@ void addrtostr(struct in6_addr const *addr, char *str, size_t str_size)
int check_rdnss_presence(struct AdvRDNSS *rdnss, struct in6_addr *addr)
{
while (rdnss) {
if (!memcmp(&rdnss->AdvRDNSSAddr1, addr, sizeof(struct in6_addr)) ||
!memcmp(&rdnss->AdvRDNSSAddr2, addr, sizeof(struct in6_addr)) ||
!memcmp(&rdnss->AdvRDNSSAddr3, addr, sizeof(struct in6_addr)))
return 1; /* rdnss address found in the list */
for (int i = 0; i < rdnss->AdvRDNSSNumber; i++) {
if (!memcmp(&rdnss->AdvRDNSSAddr[i], addr, sizeof(struct in6_addr)))
return 1; /* rdnss address found in the list */
}
rdnss = rdnss->next;
}
return 0;
Expand Down

0 comments on commit 746ec1e

Please sign in to comment.