[dhcp6relay] Fix option parsing and add dhcpv6 client messages (#10819)
This commit is contained in:
parent
915f2834b0
commit
2ead3aaefc
@ -18,21 +18,23 @@ except KeyError:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
expected_counts = """\
|
expected_counts = """\
|
||||||
Message Type Vlan1000
|
Message Type Vlan1000
|
||||||
-------------- -----------
|
------------------- -----------
|
||||||
Unknown
|
Unknown
|
||||||
Solicit
|
Solicit
|
||||||
Advertise
|
Advertise
|
||||||
Request
|
Request
|
||||||
Confirm
|
Confirm
|
||||||
Renew
|
Renew
|
||||||
Rebind
|
Rebind
|
||||||
Reply
|
Reply
|
||||||
Release
|
Release
|
||||||
Decline
|
Decline
|
||||||
Relay-Forward
|
Reconfigure
|
||||||
Relay-Reply
|
Information-Request
|
||||||
Malformed
|
Relay-Forward
|
||||||
|
Relay-Reply
|
||||||
|
Malformed
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ from swsscommon.swsscommon import SonicV2Connector
|
|||||||
DHCPv6_COUNTER_TABLE = 'DHCPv6_COUNTER_TABLE'
|
DHCPv6_COUNTER_TABLE = 'DHCPv6_COUNTER_TABLE'
|
||||||
|
|
||||||
# DHCPv6 Counter Messages
|
# DHCPv6 Counter Messages
|
||||||
messages = ["Unknown", "Solicit", "Advertise", "Request", "Confirm", "Renew", "Rebind", "Reply", "Release", "Decline", "Relay-Forward", "Relay-Reply", "Malformed"]
|
messages = ["Unknown", "Solicit", "Advertise", "Request", "Confirm", "Renew", "Rebind", "Reply", "Release", "Decline", "Reconfigure", "Information-Request", "Relay-Forward", "Relay-Reply", "Malformed"]
|
||||||
|
|
||||||
# DHCP_RELAY Config Table
|
# DHCP_RELAY Config Table
|
||||||
DHCP_RELAY = 'DHCP_RELAY'
|
DHCP_RELAY = 'DHCP_RELAY'
|
||||||
|
@ -59,6 +59,8 @@ std::map<int, std::string> counterMap = {{DHCPv6_MESSAGE_TYPE_UNKNOWN, "Unknown"
|
|||||||
{DHCPv6_MESSAGE_TYPE_REPLY, "Reply"},
|
{DHCPv6_MESSAGE_TYPE_REPLY, "Reply"},
|
||||||
{DHCPv6_MESSAGE_TYPE_RELEASE, "Release"},
|
{DHCPv6_MESSAGE_TYPE_RELEASE, "Release"},
|
||||||
{DHCPv6_MESSAGE_TYPE_DECLINE, "Decline"},
|
{DHCPv6_MESSAGE_TYPE_DECLINE, "Decline"},
|
||||||
|
{DHCPv6_MESSAGE_TYPE_RECONFIGURE, "Reconfigure"},
|
||||||
|
{DHCPv6_MESSAGE_TYPE_INFORMATION_REQUEST, "Information-Request"},
|
||||||
{DHCPv6_MESSAGE_TYPE_RELAY_FORW, "Relay-Forward"},
|
{DHCPv6_MESSAGE_TYPE_RELAY_FORW, "Relay-Forward"},
|
||||||
{DHCPv6_MESSAGE_TYPE_RELAY_REPL, "Relay-Reply"},
|
{DHCPv6_MESSAGE_TYPE_RELAY_REPL, "Relay-Reply"},
|
||||||
{DHCPv6_MESSAGE_TYPE_MALFORMED, "Malformed"}};
|
{DHCPv6_MESSAGE_TYPE_MALFORMED, "Malformed"}};
|
||||||
@ -84,6 +86,8 @@ void initialize_counter(swss::DBConnector *db, std::string counterVlan) {
|
|||||||
db->hset(counterVlan, "Reply", toString(counters[DHCPv6_MESSAGE_TYPE_REPLY]));
|
db->hset(counterVlan, "Reply", toString(counters[DHCPv6_MESSAGE_TYPE_REPLY]));
|
||||||
db->hset(counterVlan, "Release", toString(counters[DHCPv6_MESSAGE_TYPE_RELEASE]));
|
db->hset(counterVlan, "Release", toString(counters[DHCPv6_MESSAGE_TYPE_RELEASE]));
|
||||||
db->hset(counterVlan, "Decline", toString(counters[DHCPv6_MESSAGE_TYPE_DECLINE]));
|
db->hset(counterVlan, "Decline", toString(counters[DHCPv6_MESSAGE_TYPE_DECLINE]));
|
||||||
|
db->hset(counterVlan, "Reconfigure", toString(counters[DHCPv6_MESSAGE_TYPE_RECONFIGURE]));
|
||||||
|
db->hset(counterVlan, "Information-Request", toString(counters[DHCPv6_MESSAGE_TYPE_INFORMATION_REQUEST]));
|
||||||
db->hset(counterVlan, "Relay-Forward", toString(counters[DHCPv6_MESSAGE_TYPE_RELAY_FORW]));
|
db->hset(counterVlan, "Relay-Forward", toString(counters[DHCPv6_MESSAGE_TYPE_RELAY_FORW]));
|
||||||
db->hset(counterVlan, "Relay-Reply", toString(counters[DHCPv6_MESSAGE_TYPE_RELAY_REPL]));
|
db->hset(counterVlan, "Relay-Reply", toString(counters[DHCPv6_MESSAGE_TYPE_RELAY_REPL]));
|
||||||
db->hset(counterVlan, "Malformed", toString(counters[DHCPv6_MESSAGE_TYPE_MALFORMED]));
|
db->hset(counterVlan, "Malformed", toString(counters[DHCPv6_MESSAGE_TYPE_MALFORMED]));
|
||||||
@ -204,11 +208,12 @@ const struct dhcpv6_relay_msg *parse_dhcpv6_relay(const uint8_t *buffer) {
|
|||||||
* @return dhcpv6_option end of dhcpv6 message option
|
* @return dhcpv6_option end of dhcpv6 message option
|
||||||
*/
|
*/
|
||||||
const struct dhcpv6_option *parse_dhcpv6_opt(const uint8_t *buffer, const uint8_t **out_end) {
|
const struct dhcpv6_option *parse_dhcpv6_opt(const uint8_t *buffer, const uint8_t **out_end) {
|
||||||
uint32_t size = 4; // option-code + option-len
|
auto option = (const struct dhcpv6_option *)buffer;
|
||||||
size += ntohs(*(uint16_t *)(buffer + 2));
|
uint8_t size = 4; // option-code + option-len
|
||||||
(*out_end) = buffer + size;
|
size += *(uint16_t *)(buffer);
|
||||||
|
(*out_end) = buffer + size + ntohs(option->option_length);
|
||||||
|
|
||||||
return (const struct dhcpv6_option *)buffer;
|
return option;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -589,6 +594,7 @@ void relay_relay_forw(int sock, const uint8_t *msg, int32_t len, const ip6_hdr *
|
|||||||
void callback(evutil_socket_t fd, short event, void *arg) {
|
void callback(evutil_socket_t fd, short event, void *arg) {
|
||||||
struct relay_config *config = (struct relay_config *)arg;
|
struct relay_config *config = (struct relay_config *)arg;
|
||||||
static uint8_t message_buffer[4096];
|
static uint8_t message_buffer[4096];
|
||||||
|
std::string counterVlan = counter_table;
|
||||||
int32_t len = recv(config->filter, message_buffer, 4096, 0);
|
int32_t len = recv(config->filter, message_buffer, 4096, 0);
|
||||||
if (len <= 0) {
|
if (len <= 0) {
|
||||||
syslog(LOG_WARNING, "recv: Failed to receive data at filter socket: %s\n", strerror(errno));
|
syslog(LOG_WARNING, "recv: Failed to receive data at filter socket: %s\n", strerror(errno));
|
||||||
@ -626,10 +632,6 @@ void callback(evutil_socket_t fd, short event, void *arg) {
|
|||||||
auto msg = parse_dhcpv6_hdr(current_position);
|
auto msg = parse_dhcpv6_hdr(current_position);
|
||||||
auto option_position = current_position + sizeof(struct dhcpv6_msg);
|
auto option_position = current_position + sizeof(struct dhcpv6_msg);
|
||||||
|
|
||||||
counters[msg->msg_type]++;
|
|
||||||
std::string counterVlan = counter_table;
|
|
||||||
update_counter(config->db, counterVlan.append(config->interface), msg->msg_type);
|
|
||||||
|
|
||||||
switch (msg->msg_type) {
|
switch (msg->msg_type) {
|
||||||
case DHCPv6_MESSAGE_TYPE_RELAY_FORW:
|
case DHCPv6_MESSAGE_TYPE_RELAY_FORW:
|
||||||
{
|
{
|
||||||
@ -638,21 +640,25 @@ void callback(evutil_socket_t fd, short event, void *arg) {
|
|||||||
}
|
}
|
||||||
case DHCPv6_MESSAGE_TYPE_SOLICIT:
|
case DHCPv6_MESSAGE_TYPE_SOLICIT:
|
||||||
case DHCPv6_MESSAGE_TYPE_REQUEST:
|
case DHCPv6_MESSAGE_TYPE_REQUEST:
|
||||||
|
case DHCPv6_MESSAGE_TYPE_CONFIRM:
|
||||||
case DHCPv6_MESSAGE_TYPE_RENEW:
|
case DHCPv6_MESSAGE_TYPE_RENEW:
|
||||||
case DHCPv6_MESSAGE_TYPE_REBIND:
|
case DHCPv6_MESSAGE_TYPE_REBIND:
|
||||||
case DHCPv6_MESSAGE_TYPE_RELEASE:
|
case DHCPv6_MESSAGE_TYPE_RELEASE:
|
||||||
case DHCPv6_MESSAGE_TYPE_DECLINE:
|
case DHCPv6_MESSAGE_TYPE_DECLINE:
|
||||||
|
case DHCPv6_MESSAGE_TYPE_INFORMATION_REQUEST:
|
||||||
{
|
{
|
||||||
while (option_position - message_buffer < len) {
|
while (option_position - message_buffer < len) {
|
||||||
auto option = parse_dhcpv6_opt(option_position, &tmp);
|
auto option = parse_dhcpv6_opt(option_position, &tmp);
|
||||||
option_position = tmp;
|
option_position = tmp;
|
||||||
if(ntohs(option->option_code) > DHCPv6_OPTION_LIMIT) {
|
if (ntohs(option->option_code) > DHCPv6_OPTION_LIMIT) {
|
||||||
counters[DHCPv6_MESSAGE_TYPE_MALFORMED]++;
|
counters[DHCPv6_MESSAGE_TYPE_MALFORMED]++;
|
||||||
update_counter(config->db, counterVlan.append(config->interface), DHCPv6_MESSAGE_TYPE_MALFORMED);
|
update_counter(config->db, counterVlan.append(config->interface), DHCPv6_MESSAGE_TYPE_MALFORMED);
|
||||||
syslog(LOG_WARNING, "DHCPv6 option is invalid or contains malformed payload\n");
|
syslog(LOG_WARNING, "DHCPv6 option is invalid or contains malformed payload\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
counters[msg->msg_type]++;
|
||||||
|
update_counter(config->db, counterVlan.append(config->interface), msg->msg_type);
|
||||||
relay_client(config->local_sock, current_position, ntohs(udp_header->len) - sizeof(udphdr), ip_header, ether_header, config);
|
relay_client(config->local_sock, current_position, ntohs(udp_header->len) - sizeof(udphdr), ip_header, ether_header, config);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,8 @@ typedef enum
|
|||||||
DHCPv6_MESSAGE_TYPE_REPLY = 7,
|
DHCPv6_MESSAGE_TYPE_REPLY = 7,
|
||||||
DHCPv6_MESSAGE_TYPE_RELEASE = 8,
|
DHCPv6_MESSAGE_TYPE_RELEASE = 8,
|
||||||
DHCPv6_MESSAGE_TYPE_DECLINE = 9,
|
DHCPv6_MESSAGE_TYPE_DECLINE = 9,
|
||||||
|
DHCPv6_MESSAGE_TYPE_RECONFIGURE = 10,
|
||||||
|
DHCPv6_MESSAGE_TYPE_INFORMATION_REQUEST = 11,
|
||||||
DHCPv6_MESSAGE_TYPE_RELAY_FORW = 12,
|
DHCPv6_MESSAGE_TYPE_RELAY_FORW = 12,
|
||||||
DHCPv6_MESSAGE_TYPE_RELAY_REPL = 13,
|
DHCPv6_MESSAGE_TYPE_RELAY_REPL = 13,
|
||||||
DHCPv6_MESSAGE_TYPE_MALFORMED = 14,
|
DHCPv6_MESSAGE_TYPE_MALFORMED = 14,
|
||||||
@ -60,6 +62,7 @@ struct relay_config {
|
|||||||
|
|
||||||
struct dhcpv6_msg {
|
struct dhcpv6_msg {
|
||||||
uint8_t msg_type;
|
uint8_t msg_type;
|
||||||
|
uint8_t xid[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PACKED dhcpv6_relay_msg {
|
struct PACKED dhcpv6_relay_msg {
|
||||||
|
Loading…
Reference in New Issue
Block a user