mirror of
https://github.com/rtbrick/bngblaster.git
synced 2024-05-06 15:54:57 +00:00
A10NSP DHCPv6 and LDRA
This commit adds support for DHCPv6 on A10NSP interfaces (#87). It also adds general support for DHCPv6 LDRA (#96 and #157).
This commit is contained in:
@@ -459,6 +459,122 @@ bbl_a10nsp_dhcp_handler(bbl_a10nsp_interface_s *interface,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bbl_a10nsp_dhcpv6_handler(bbl_a10nsp_interface_s *interface,
|
||||
bbl_session_s *session,
|
||||
bbl_ethernet_header_s *eth)
|
||||
{
|
||||
bbl_a10nsp_session_s *a10nsp_session = session->a10nsp_session;
|
||||
bbl_ipv6_s *ipv6 = (bbl_ipv6_s*)eth->next;
|
||||
bbl_udp_s *udp = (bbl_udp_s*)ipv6->next;
|
||||
|
||||
bbl_dhcpv6_s *dhcpv6 = (bbl_dhcpv6_s*)udp->next;
|
||||
bbl_dhcpv6_s *dhcpv6_outer = dhcpv6;
|
||||
|
||||
if(dhcpv6->type == DHCPV6_MESSAGE_RELAY_FORW) {
|
||||
if(!dhcpv6->relay_message) {
|
||||
/* Invalid request. */
|
||||
return;
|
||||
}
|
||||
dhcpv6 = dhcpv6->relay_message;
|
||||
dhcpv6_outer->type = DHCPV6_MESSAGE_RELAY_REPL;
|
||||
}
|
||||
|
||||
switch(dhcpv6->type) {
|
||||
case DHCPV6_MESSAGE_SOLICIT:
|
||||
if(dhcpv6->rapid) {
|
||||
dhcpv6->type = DHCPV6_MESSAGE_REPLY;
|
||||
} else {
|
||||
dhcpv6->type = DHCPV6_MESSAGE_ADVERTISE;
|
||||
}
|
||||
break;
|
||||
case DHCPV6_MESSAGE_REQUEST:
|
||||
dhcpv6->type = DHCPV6_MESSAGE_REPLY;
|
||||
break;
|
||||
case DHCPV6_MESSAGE_RELEASE:
|
||||
dhcpv6->type = DHCPV6_MESSAGE_REPLY;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if(dhcpv6_outer->access_line) {
|
||||
if(dhcpv6_outer->access_line->aci) {
|
||||
if(a10nsp_session->dhcpv6_aci) {
|
||||
free(a10nsp_session->dhcpv6_aci);
|
||||
}
|
||||
a10nsp_session->dhcp_aci = strdup(dhcpv6_outer->access_line->aci);
|
||||
}
|
||||
if(dhcpv6_outer->access_line->ari) {
|
||||
if(a10nsp_session->dhcpv6_ari) {
|
||||
free(a10nsp_session->dhcpv6_ari);
|
||||
}
|
||||
a10nsp_session->dhcpv6_ari = strdup(dhcpv6_outer->access_line->ari);
|
||||
}
|
||||
dhcpv6_outer->access_line = NULL;
|
||||
}
|
||||
|
||||
ipv6->dst = ipv6->src;
|
||||
ipv6->src = (void*)ipv6_link_local_address;
|
||||
ipv6->ttl = 255;
|
||||
udp->src = DHCPV6_UDP_SERVER;
|
||||
udp->dst = DHCPV6_UDP_CLIENT;
|
||||
|
||||
dhcpv6->server_duid = (void*)mock_dhcpv6_server_duid;
|
||||
dhcpv6->server_duid_len = sizeof(mock_dhcpv6_server_duid);
|
||||
dhcpv6->rapid = false;
|
||||
dhcpv6->oro = false;
|
||||
dhcpv6->dns1 = NULL;
|
||||
dhcpv6->dns2 = NULL;
|
||||
if(dhcpv6->ia_na_iaid) {
|
||||
dhcpv6->ia_na_option_len = 0;
|
||||
dhcpv6->ia_na_address = (void*)&mock_ipv6_ia_na;
|
||||
dhcpv6->ia_na_t1 = 300;
|
||||
dhcpv6->ia_na_t2 = 600;
|
||||
dhcpv6->ia_na_preferred_lifetime = 900;
|
||||
dhcpv6->ia_na_valid_lifetime = 1800;
|
||||
}
|
||||
if(dhcpv6->ia_pd_iaid) {
|
||||
dhcpv6->ia_pd_option_len = 0;
|
||||
dhcpv6->ia_pd_prefix = (void*)&mock_ipv6_ia_pd;
|
||||
dhcpv6->ia_pd_t1 = 300;
|
||||
dhcpv6->ia_pd_t2 = 600;
|
||||
dhcpv6->ia_pd_preferred_lifetime = 900;
|
||||
dhcpv6->ia_pd_valid_lifetime = 1800;
|
||||
}
|
||||
|
||||
if(bbl_txq_to_buffer(interface->txq, eth) == BBL_TXQ_OK) {
|
||||
a10nsp_session->stats.packets_tx++;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bbl_a10nsp_icmpv6_handler(bbl_a10nsp_interface_s *interface,
|
||||
bbl_session_s *session,
|
||||
bbl_ethernet_header_s *eth)
|
||||
{
|
||||
bbl_a10nsp_session_s *a10nsp_session = session->a10nsp_session;
|
||||
bbl_ipv6_s *ipv6 = (bbl_ipv6_s*)eth->next;
|
||||
bbl_icmpv6_s *icmpv6 = (bbl_icmpv6_s*)ipv6->next;
|
||||
|
||||
switch(icmpv6->type) {
|
||||
case IPV6_ICMPV6_ROUTER_SOLICITATION:
|
||||
icmpv6->type = IPV6_ICMPV6_ROUTER_ADVERTISEMENT;
|
||||
icmpv6->mac = interface->mac;
|
||||
icmpv6->data_len = 0;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
ipv6->src = (void*)ipv6_link_local_address;
|
||||
ipv6->dst = (void*)ipv6_multicast_all_nodes;
|
||||
ipv6->ttl = 255;
|
||||
if(bbl_txq_to_buffer(interface->txq, eth) == BBL_TXQ_OK) {
|
||||
a10nsp_session->stats.packets_tx++;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bbl_a10nsp_ipv4_handler(bbl_a10nsp_interface_s *interface,
|
||||
bbl_session_s *session,
|
||||
@@ -479,6 +595,29 @@ bbl_a10nsp_ipv4_handler(bbl_a10nsp_interface_s *interface,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
bbl_a10nsp_ipv6_handler(bbl_a10nsp_interface_s *interface,
|
||||
bbl_session_s *session,
|
||||
bbl_ethernet_header_s *eth)
|
||||
{
|
||||
bbl_ipv6_s *ipv6 = (bbl_ipv6_s*)eth->next;
|
||||
bbl_udp_s *udp;
|
||||
|
||||
switch(ipv6->protocol) {
|
||||
case IPV6_NEXT_HEADER_UDP:
|
||||
udp = (bbl_udp_s*)ipv6->next;
|
||||
if(udp->protocol == UDP_PROTOCOL_DHCPV6) {
|
||||
bbl_a10nsp_dhcpv6_handler(interface, session, eth);
|
||||
}
|
||||
break;
|
||||
case IPV6_NEXT_HEADER_ICMPV6:
|
||||
bbl_a10nsp_icmpv6_handler(interface, session, eth);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* bbl_a10nsp_rx
|
||||
*
|
||||
@@ -525,6 +664,9 @@ bbl_a10nsp_rx(bbl_a10nsp_interface_s *interface,
|
||||
case ETH_TYPE_IPV4:
|
||||
bbl_a10nsp_ipv4_handler(interface, session, eth);
|
||||
break;
|
||||
case ETH_TYPE_IPV6:
|
||||
bbl_a10nsp_ipv6_handler(interface, session, eth);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -506,12 +506,6 @@ bbl_access_rx_icmpv6(bbl_access_interface_s *interface,
|
||||
|
||||
session->stats.icmpv6_rx++;
|
||||
|
||||
if(session->a10nsp_session) {
|
||||
/* There is currently no IPv6 support
|
||||
* for A10NSP terminated sessions today. */
|
||||
return;
|
||||
}
|
||||
|
||||
if(session->access_type == ACCESS_TYPE_PPPOE &&
|
||||
session->ip6cp_state != BBL_PPP_OPENED) {
|
||||
return;
|
||||
|
||||
@@ -982,6 +982,12 @@ json_parse_access_interface(json_t *access_interface, bbl_access_config_s *acces
|
||||
} else {
|
||||
access_config->dhcpv6_enable = g_ctx->config.dhcpv6_enable;
|
||||
}
|
||||
value = json_object_get(access_interface, "dhcpv6-ldra");
|
||||
if(json_is_boolean(value)) {
|
||||
access_config->dhcpv6_ldra = json_boolean_value(value);
|
||||
} else {
|
||||
access_config->dhcpv6_ldra = g_ctx->config.dhcpv6_ldra;
|
||||
}
|
||||
value = json_object_get(access_interface, "ipv6");
|
||||
if(json_is_boolean(value)) {
|
||||
access_config->ipv6_enable = json_boolean_value(value);
|
||||
@@ -2252,6 +2258,10 @@ json_parse_config(json_t *root)
|
||||
if(json_is_boolean(value)) {
|
||||
g_ctx->config.dhcpv6_enable = json_boolean_value(value);
|
||||
}
|
||||
value = json_object_get(section, "ldra");
|
||||
if(json_is_boolean(value)) {
|
||||
g_ctx->config.dhcpv6_ldra = json_boolean_value(value);
|
||||
}
|
||||
value = json_object_get(section, "ia-na");
|
||||
if(json_is_boolean(value)) {
|
||||
g_ctx->config.dhcpv6_ia_na = json_boolean_value(value);
|
||||
|
||||
@@ -65,6 +65,7 @@ typedef struct bbl_access_config_
|
||||
bool ipv6_enable;
|
||||
bool dhcp_enable;
|
||||
bool dhcpv6_enable;
|
||||
bool dhcpv6_ldra;
|
||||
bool igmp_autostart;
|
||||
uint8_t igmp_version;
|
||||
bool session_traffic_autostart;
|
||||
|
||||
@@ -288,6 +288,7 @@ typedef struct bbl_ctx_
|
||||
|
||||
/* DHCPv6 */
|
||||
bool dhcpv6_enable;
|
||||
bool dhcpv6_ldra;
|
||||
bool dhcpv6_ia_na;
|
||||
bool dhcpv6_ia_pd;
|
||||
bool dhcpv6_rapid_commit;
|
||||
|
||||
@@ -62,6 +62,14 @@
|
||||
#define MOCK_DNS1 134744072 /* 8.8.8.8 */
|
||||
#define MOCK_DNS2 16843009 /* 1.1.1.1 */
|
||||
|
||||
static const uint8_t mock_dhcpv6_server_duid[] = {0x00, 0x02, 0x00, 0x00, 0x8A, 0xC3, 0x01, 0x01};
|
||||
static const ipv6addr_t mock_ipv6_local = {0xFC, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
|
||||
static const ipv6addr_t mock_ipv6_ia_na = {0xFC, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02};
|
||||
static const ipv6_prefix mock_ipv6_ia_pd = {
|
||||
.len = 56,
|
||||
.address = {0xFC, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
};
|
||||
|
||||
/* Interface Send Mask */
|
||||
#define BBL_SEND_LACP 0x00000001
|
||||
|
||||
|
||||
@@ -205,6 +205,14 @@ bbl_dhcpv6_rx(bbl_session_s *session, bbl_ethernet_header_s *eth, bbl_dhcpv6_s *
|
||||
return;
|
||||
}
|
||||
|
||||
if(dhcpv6->type == DHCPV6_MESSAGE_RELAY_REPL) {
|
||||
if(!dhcpv6->relay_message) {
|
||||
/* Invalid packet received */
|
||||
return;
|
||||
}
|
||||
dhcpv6 = dhcpv6->relay_message;
|
||||
}
|
||||
|
||||
/* Ignore packets with wrong transaction identifier */
|
||||
if(dhcpv6->xid != session->dhcpv6_xid) {
|
||||
return;
|
||||
|
||||
@@ -230,17 +230,53 @@ encode_dhcpv6(uint8_t *buf, uint16_t *len,
|
||||
{
|
||||
uint16_t value_len;
|
||||
|
||||
/* Transaction ID */
|
||||
*(uint32_t*)buf = htobe32(dhcpv6->xid);
|
||||
*buf = dhcpv6->type;
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint32_t));
|
||||
/* Elapsed Time */
|
||||
*(uint16_t*)buf = htobe16(DHCPV6_OPTION_ELAPSED_TIME);
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
|
||||
*(uint16_t*)buf = htobe16(sizeof(uint16_t));
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
|
||||
*(uint16_t*)buf = 0;
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
|
||||
if(dhcpv6->type == DHCPV6_MESSAGE_RELAY_FORW ||
|
||||
dhcpv6->type == DHCPV6_MESSAGE_RELAY_REPL) {
|
||||
/* Type */
|
||||
*buf = dhcpv6->type;
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t));
|
||||
/* Hops */
|
||||
*buf = dhcpv6->hops;
|
||||
/* Link Address */
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t));
|
||||
if(dhcpv6->link_address) {
|
||||
memcpy(buf, dhcpv6->link_address, sizeof(ipv6addr_t));
|
||||
} else {
|
||||
memset(buf, 0x0, sizeof(ipv6addr_t));
|
||||
}
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(ipv6addr_t));
|
||||
/* Peer Address */
|
||||
if(dhcpv6->peer_address) {
|
||||
memcpy(buf, dhcpv6->peer_address, sizeof(ipv6addr_t));
|
||||
} else {
|
||||
memset(buf, 0x0, sizeof(ipv6addr_t));
|
||||
}
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(ipv6addr_t));
|
||||
} else {
|
||||
/* Type/Transaction ID */
|
||||
*(uint32_t*)buf = htobe32(dhcpv6->xid);
|
||||
*buf = dhcpv6->type;
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint32_t));
|
||||
/* Elapsed Time */
|
||||
*(uint16_t*)buf = htobe16(DHCPV6_OPTION_ELAPSED_TIME);
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
|
||||
*(uint16_t*)buf = htobe16(sizeof(uint16_t));
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
|
||||
*(uint16_t*)buf = 0;
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
|
||||
}
|
||||
|
||||
/* Relay Message */
|
||||
if(dhcpv6->relay_message) {
|
||||
*(uint16_t*)buf = htobe16(DHCPV6_OPTION_RELAY_MSG);
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
|
||||
value_len = 0;
|
||||
if(encode_dhcpv6(buf+2, &value_len, dhcpv6->relay_message) != PROTOCOL_SUCCESS) {
|
||||
return ENCODE_ERROR;
|
||||
}
|
||||
*(uint16_t*)buf = htobe16(value_len);
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t)+value_len);
|
||||
}
|
||||
/* Client Identifier */
|
||||
if(dhcpv6->client_duid_len) {
|
||||
*(uint16_t*)buf = htobe16(DHCPV6_OPTION_CLIENTID);
|
||||
@@ -277,14 +313,31 @@ encode_dhcpv6(uint8_t *buf, uint16_t *len,
|
||||
} else if(dhcpv6->ia_na_iaid) {
|
||||
*(uint16_t*)buf = htobe16(DHCPV6_OPTION_IA_NA);
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
|
||||
*(uint16_t*)buf = htobe16(12);
|
||||
if(dhcpv6->ia_na_address) {
|
||||
*(uint16_t*)buf = htobe16(40); /* length */
|
||||
} else {
|
||||
*(uint16_t*)buf = htobe16(12); /* length */
|
||||
}
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
|
||||
*(uint32_t*)buf = dhcpv6->ia_na_iaid;
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint32_t));
|
||||
*(uint32_t*)buf = 0; /* T1 */
|
||||
*(uint32_t*)buf = dhcpv6->ia_na_t1; /* T1 */
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint32_t));
|
||||
*(uint32_t*)buf = 0; /* T2 */
|
||||
*(uint32_t*)buf = dhcpv6->ia_na_t2; /* T2 */
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint32_t));
|
||||
if(dhcpv6->ia_na_address) {
|
||||
*(uint16_t*)buf = htobe16(DHCPV6_OPTION_IAADDR);
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
|
||||
*(uint16_t*)buf = htobe16(24); /* length */
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
|
||||
memcpy(buf, dhcpv6->ia_na_address, sizeof(ipv6addr_t));
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(ipv6addr_t));
|
||||
*(uint32_t*)buf = dhcpv6->ia_na_preferred_lifetime;
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint32_t));
|
||||
*(uint32_t*)buf = dhcpv6->ia_na_valid_lifetime;
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
}
|
||||
/* IA_PD */
|
||||
if(dhcpv6->ia_pd_option_len) {
|
||||
@@ -297,23 +350,27 @@ encode_dhcpv6(uint8_t *buf, uint16_t *len,
|
||||
} else if(dhcpv6->ia_pd_iaid) {
|
||||
*(uint16_t*)buf = htobe16(DHCPV6_OPTION_IA_PD);
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
|
||||
*(uint16_t*)buf = htobe16(41);
|
||||
*(uint16_t*)buf = htobe16(41); /* length */
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
|
||||
*(uint32_t*)buf = dhcpv6->ia_pd_iaid;
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint32_t));
|
||||
*(uint32_t*)buf = 0; /* T1 */
|
||||
*(uint32_t*)buf = dhcpv6->ia_pd_t1; /* T1 */
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint32_t));
|
||||
*(uint32_t*)buf = 0; /* T2 */
|
||||
*(uint32_t*)buf = dhcpv6->ia_pd_t2; /* T2 */
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint32_t));
|
||||
*(uint16_t*)buf = htobe16(DHCPV6_OPTION_IAPREFIX);
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
|
||||
*(uint16_t*)buf = htobe16(25); /* length */
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
|
||||
*(uint32_t*)buf = 0; /* preferred lifetime */
|
||||
*(uint32_t*)buf = dhcpv6->ia_pd_preferred_lifetime;
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint32_t));
|
||||
*(uint32_t*)buf = 0; /* valid lifetime */
|
||||
*(uint32_t*)buf = dhcpv6->ia_pd_valid_lifetime;
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint32_t));
|
||||
memset(buf, 0x0, sizeof(ipv6_prefix));
|
||||
if(dhcpv6->ia_pd_prefix) {
|
||||
memcpy(buf, dhcpv6->ia_pd_prefix, sizeof(ipv6_prefix));
|
||||
} else {
|
||||
memset(buf, 0x0, sizeof(ipv6_prefix));
|
||||
}
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(ipv6_prefix));
|
||||
}
|
||||
/* Option Request Option */
|
||||
@@ -351,6 +408,7 @@ encode_dhcpv6(uint8_t *buf, uint16_t *len,
|
||||
value_len = strnlen(dhcpv6->access_line->ari, UINT16_MAX);
|
||||
*(uint16_t*)buf = htobe16(value_len+4);
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
|
||||
/* See TR-177 chapter 5.6.1, R-11! */
|
||||
*(uint32_t*)buf = htobe32(BROADBAND_FORUM);
|
||||
BUMP_WRITE_BUFFER(buf, len, sizeof(uint32_t));
|
||||
memcpy(buf, dhcpv6->access_line->ari, value_len);
|
||||
@@ -2506,7 +2564,8 @@ decode_dhcpv6_ia_pd(uint8_t *buf, uint16_t len, bbl_dhcpv6_s *dhcpv6)
|
||||
static protocol_error_t
|
||||
decode_dhcpv6(uint8_t *buf, uint16_t len,
|
||||
uint8_t *sp, uint16_t sp_len,
|
||||
bbl_dhcpv6_s **_dhcpv6)
|
||||
bbl_dhcpv6_s **_dhcpv6,
|
||||
bool relay)
|
||||
{
|
||||
protocol_error_t ret_val = PROTOCOL_SUCCESS;
|
||||
|
||||
@@ -2522,10 +2581,23 @@ decode_dhcpv6(uint8_t *buf, uint16_t len,
|
||||
dhcpv6 = (bbl_dhcpv6_s*)sp; BUMP_BUFFER(sp, sp_len, sizeof(bbl_dhcpv6_s));
|
||||
memset(dhcpv6, 0x0, sizeof(bbl_dhcpv6_s));
|
||||
|
||||
dhcpv6->xid = be32toh(*(uint32_t*)buf);
|
||||
dhcpv6->type = dhcpv6->xid >> 24;
|
||||
dhcpv6->xid &= DHCPV6_TYPE_MASK;
|
||||
BUMP_BUFFER(buf, len, sizeof(uint32_t));
|
||||
dhcpv6->type = *buf;
|
||||
if(dhcpv6->type == DHCPV6_MESSAGE_RELAY_FORW ||
|
||||
dhcpv6->type == DHCPV6_MESSAGE_RELAY_REPL) {
|
||||
if(relay || len < 34) {
|
||||
return DECODE_ERROR;
|
||||
}
|
||||
BUMP_BUFFER(buf, len, sizeof(uint8_t));
|
||||
dhcpv6->hops = *buf;
|
||||
BUMP_BUFFER(buf, len, sizeof(uint8_t));
|
||||
dhcpv6->link_address = (ipv6addr_t*)(buf);
|
||||
BUMP_BUFFER(buf, len, sizeof(ipv6addr_t));
|
||||
dhcpv6->peer_address = (ipv6addr_t*)(buf);
|
||||
BUMP_BUFFER(buf, len, sizeof(ipv6addr_t));
|
||||
} else {
|
||||
dhcpv6->xid = be32toh(*(uint32_t*)buf) & DHCPV6_TYPE_MASK;
|
||||
BUMP_BUFFER(buf, len, sizeof(uint32_t));
|
||||
}
|
||||
|
||||
while(len >= 4) {
|
||||
option = be16toh(*(uint16_t*)buf);
|
||||
@@ -2564,6 +2636,17 @@ decode_dhcpv6(uint8_t *buf, uint16_t len,
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DHCPV6_OPTION_INTERFACE_ID:
|
||||
dhcpv6->interface_id = buf;
|
||||
dhcpv6->interface_id_len = option_len;
|
||||
break;
|
||||
case DHCPV6_OPTION_RELAY_MSG:
|
||||
if(!(dhcpv6->type == DHCPV6_MESSAGE_RELAY_FORW || dhcpv6->type == DHCPV6_MESSAGE_RELAY_REPL)) {
|
||||
return DECODE_ERROR;
|
||||
}
|
||||
if(decode_dhcpv6(buf, option_len, sp, sp_len, (bbl_dhcpv6_s**)&dhcpv6->relay_message, true) != PROTOCOL_SUCCESS) {
|
||||
return DECODE_ERROR;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -2975,7 +3058,7 @@ decode_udp(uint8_t *buf, uint16_t len,
|
||||
case DHCPV6_UDP_CLIENT:
|
||||
case DHCPV6_UDP_SERVER:
|
||||
udp->protocol = UDP_PROTOCOL_DHCPV6;
|
||||
ret_val = decode_dhcpv6(buf, len, sp, sp_len, (bbl_dhcpv6_s**)&udp->next);
|
||||
ret_val = decode_dhcpv6(buf, len, sp, sp_len, (bbl_dhcpv6_s**)&udp->next, false);
|
||||
break;
|
||||
case BBL_UDP_PORT:
|
||||
udp->protocol = UDP_PROTOCOL_BBL;
|
||||
|
||||
@@ -830,7 +830,10 @@ typedef struct bbl_icmpv6_ {
|
||||
|
||||
typedef struct bbl_dhcpv6_ {
|
||||
uint8_t type;
|
||||
uint8_t hops;
|
||||
uint32_t xid;
|
||||
uint8_t *interface_id;
|
||||
uint8_t interface_id_len;
|
||||
uint8_t *client_duid;
|
||||
uint8_t client_duid_len;
|
||||
uint8_t *server_duid;
|
||||
@@ -858,6 +861,12 @@ typedef struct bbl_dhcpv6_ {
|
||||
uint32_t ia_pd_preferred_lifetime;
|
||||
uint32_t ia_pd_valid_lifetime;
|
||||
access_line_s *access_line;
|
||||
|
||||
/* DHCPv6 Relay Attributes */
|
||||
|
||||
ipv6addr_t *link_address;
|
||||
ipv6addr_t *peer_address;
|
||||
struct bbl_dhcpv6_ *relay_message;
|
||||
} bbl_dhcpv6_s;
|
||||
|
||||
struct dhcp_header {
|
||||
|
||||
@@ -438,6 +438,7 @@ bbl_tx_encode_packet_dhcpv6_request(bbl_session_s *session)
|
||||
bbl_ipv6_s ipv6 = {0};
|
||||
bbl_udp_s udp = {0};
|
||||
bbl_dhcpv6_s dhcpv6 = {0};
|
||||
bbl_dhcpv6_s dhcpv6_relay = {0};
|
||||
access_line_s access_line = {0};
|
||||
uint8_t mac[ETH_ADDR_LEN];
|
||||
|
||||
@@ -446,15 +447,28 @@ bbl_tx_encode_packet_dhcpv6_request(bbl_session_s *session)
|
||||
return IGNORED;
|
||||
}
|
||||
|
||||
if(g_ctx->config.dhcpv6_access_line &&
|
||||
(session->agent_circuit_id || session->agent_remote_id) &&
|
||||
session->dhcpv6_state != BBL_DHCP_RELEASE) {
|
||||
access_line.aci = session->agent_circuit_id;
|
||||
access_line.ari = session->agent_remote_id;
|
||||
access_line.up = session->rate_up;
|
||||
access_line.down = session->rate_down;
|
||||
access_line.dsl_type = session->dsl_type;
|
||||
dhcpv6.access_line = &access_line;
|
||||
if(g_ctx->config.dhcpv6_ldra) {
|
||||
dhcpv6_relay.type = DHCPV6_MESSAGE_RELAY_FORW;
|
||||
dhcpv6_relay.peer_address = (void*)session->link_local_ipv6_address;
|
||||
dhcpv6_relay.relay_message = &dhcpv6;
|
||||
if(g_ctx->config.dhcpv6_access_line &&
|
||||
(session->agent_circuit_id || session->agent_remote_id)) {
|
||||
access_line.aci = session->agent_circuit_id;
|
||||
access_line.ari = session->agent_remote_id;
|
||||
access_line.up = session->rate_up;
|
||||
access_line.down = session->rate_down;
|
||||
access_line.dsl_type = session->dsl_type;
|
||||
|
||||
}
|
||||
if(!access_line.aci) {
|
||||
/* The ACI is mapped to the Interface-Id option,
|
||||
* which is mandatory for relay forward messages. */
|
||||
access_line.aci = format_mac_address(session->client_mac);
|
||||
}
|
||||
dhcpv6_relay.access_line = &access_line;
|
||||
udp.next = &dhcpv6_relay;
|
||||
} else {
|
||||
udp.next = &dhcpv6;
|
||||
}
|
||||
|
||||
eth.src = session->client_mac;
|
||||
@@ -491,7 +505,6 @@ bbl_tx_encode_packet_dhcpv6_request(bbl_session_s *session)
|
||||
udp.dst = DHCPV6_UDP_SERVER;
|
||||
udp.src = DHCPV6_UDP_CLIENT;
|
||||
udp.protocol = UDP_PROTOCOL_DHCPV6;
|
||||
udp.next = &dhcpv6;
|
||||
dhcpv6.xid = session->dhcpv6_xid;
|
||||
dhcpv6.client_duid = session->dhcpv6_duid;
|
||||
dhcpv6.client_duid_len = DUID_LEN;
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
* - `enable`
|
||||
- This option allows to enable or disable DHCPv6
|
||||
- true
|
||||
* - `ldra`
|
||||
- This option allows to enable or disable LDRA
|
||||
- false
|
||||
* - `ia-na`
|
||||
- This option allows to enable or disable DHCPv6 IA_NA
|
||||
- true
|
||||
@@ -30,4 +33,9 @@
|
||||
- 10
|
||||
* - `access-line`
|
||||
- Add access-line attributes like Agent-Remote/Circuit-Id
|
||||
- true
|
||||
- true
|
||||
|
||||
DHCPv6 LDRA (Lightweight DHCPv6 Relay Agent) is defined in
|
||||
[RFC6221](https://datatracker.ietf.org/doc/html/rfc6221). Adding
|
||||
access-line information like Agent-Remote-Id or Agent-Circuit-Id
|
||||
is allowed with LDRA enabled only.
|
||||
|
||||
@@ -109,6 +109,9 @@
|
||||
* - `dhcpv6`
|
||||
- De-/activate DHCPv6
|
||||
-
|
||||
* - `dhcpv6-ldra`
|
||||
- De-/activate DHCPv6 LDRA
|
||||
-
|
||||
* - `igmp-autostart`
|
||||
- Overwrite IGMP autostart
|
||||
-
|
||||
|
||||
Reference in New Issue
Block a user