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:
Christian Giese
2023-03-30 19:26:32 +00:00
parent 96e7218bc8
commit 3d5d5732c2
12 changed files with 323 additions and 43 deletions
+142
View File
@@ -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;
}
-6
View File
@@ -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;
+10
View File
@@ -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);
+1
View File
@@ -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;
+1
View File
@@ -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;
+8
View File
@@ -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
+8
View File
@@ -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;
+109 -26
View File
@@ -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;
+9
View File
@@ -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 {
+23 -10
View File
@@ -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;
+9 -1
View File
@@ -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
-