Skip to content

Add DHCPv6 Relay Agent #8251

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Aug 20, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions src/dhcp6relay/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@

int main(int argc, char *argv[]) {
try {
auto parser = ArgumentParser();
parser.parse_args(argc, argv);
auto context = parser.get_arg();
arg_config context;
initialize_swss(&context);
loop_relay(&context);
}
Expand Down
65 changes: 9 additions & 56 deletions src/dhcp6relay/src/relay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,52 +22,6 @@ struct event *ev_sigterm;
bool serverListener = true;
std::shared_ptr<boost::thread> serverPtr;

/**
* @code parse_args(int argc, char *argv[]);
*
* @brief parse through argument and define the interface to bind to and to turn off option 79.
* read from config database and set the ipv6 helper addresses.
*
* @return none
*/
void ArgumentParser::parse_args(int argc, char *argv[]) {
int opt;
std::string option;
bool is_interface_set = false;
m_config.is_option_79 = false;

while ((opt = getopt(argc, argv, "i:o:")) != -1) {
switch (opt) {
case 'i':
if (is_interface_set) {
throw ArgumentException("Interface is already set to : " + this->m_config.interface);
}
else {
is_interface_set = true;
this->m_config.interface = std::string(optarg);
config_interface = this->m_config.interface;
}
break;
case 'o':
if(std::string(optarg) == "79")
m_config.is_option_79 = true;
case '?':
option = std::string(argv[optind - 1]);
throw ArgumentException("Option " + option + " not recognized");
default:
abort();
}
}

if (!is_interface_set) {
throw ArgumentException("Must specify an interface");
}
}

arg_config ArgumentParser::get_arg() {
return this->m_config;
}

bool is_addr_gua(in6_addr addr) {

auto masked = addr.__in6_u.__u6_addr8[0] & 0xe0;
Expand Down Expand Up @@ -216,7 +170,7 @@ void prepare_relay_config(relay_config *interface_config, int local_sock, int fi
}
tmp.sin6_family = AF_INET6;
tmp.sin6_flowinfo = 0;
tmp.sin6_port = htons(547);
tmp.sin6_port = htons(RELAY_PORT);
tmp.sin6_scope_id = 0;
interface_config->servers.push_back(tmp);
}
Expand All @@ -229,8 +183,8 @@ void prepare_relay_config(relay_config *interface_config, int local_sock, int fi
addr[0] = 0;

if (getifaddrs(&ifa) == -1) {
syslog(LOG_WARNING, "getifaddrs: Unable to get network interfaces\n");
exit(1);
syslog(LOG_WARNING, "getifaddrs: Unable to get network interfaces\n");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: indentations are off. Please use space for indentation

exit(1);
}

ifa_tmp = ifa;
Expand All @@ -240,6 +194,7 @@ void prepare_relay_config(relay_config *interface_config, int local_sock, int fi
inet_ntop(AF_INET6, &in6->sin6_addr, addr, sizeof(addr));
if((strcmp(ifa_tmp->ifa_name, interface_config->interface.c_str()) == 0) && is_addr_gua(in6->sin6_addr)) {
non_link_local = in6;
break;
}
if((strcmp(ifa_tmp->ifa_name, interface_config->interface.c_str()) == 0) && is_addr_link_local(in6->sin6_addr)) {
link_local = in6;
Expand Down Expand Up @@ -304,7 +259,7 @@ void prepare_socket(int *local_sock, arg_config *context) {
syslog(LOG_ERR, "scoket: Failed to create socket\n");
}

addr.sin6_port = htons(547);
addr.sin6_port = htons(RELAY_PORT);

if (bind(*local_sock, (sockaddr *)&addr, sizeof(addr)) == -1) {
syslog(LOG_ERR, "bind: Failed to bind to socket\n");
Expand Down Expand Up @@ -400,7 +355,7 @@ void relay_client(int sock, const uint8_t *msg, int32_t len, const ip6_hdr *ip_h
memcpy(&target_addr.sin6_addr, &dhcp_relay_header->peer_address, sizeof(struct in6_addr));
target_addr.sin6_family = AF_INET6;
target_addr.sin6_flowinfo = 0;
target_addr.sin6_port = htons(546);
target_addr.sin6_port = htons(CLIENT_PORT);
target_addr.sin6_scope_id = if_nametoindex(ifname);

send_udp(sock, buffer, target_addr, current_buffer_position - buffer);
Expand All @@ -420,7 +375,7 @@ void relay_client(int sock, const uint8_t *msg, int32_t len, const ip6_hdr *ip_h
*/
void callback(evutil_socket_t fd, short event, void *arg) {
struct relay_config *config = (struct relay_config *)arg;
uint8_t message_buffer[4096];
static uint8_t message_buffer[4096];
uint32_t len = recv(config->filter, message_buffer, 4096, 0);
if (len <= 0) {
syslog(LOG_WARNING, "recv: Failed to receive data at filter socket\n");
Expand Down Expand Up @@ -450,10 +405,8 @@ void callback(evutil_socket_t fd, short event, void *arg) {

auto dhcp_header = parse_dhcpv6_hdr(current_position);

if ((ntohs(udp_header->dest)) == 547 ) {
if(dhcp_header->msg_type == SOLICIT || REQUEST || CONFIRM || RENEW || REBIND || RELEASE || DECLINE) {
relay_client(config->local_sock, current_position, ntohs(udp_header->len) - sizeof(udphdr), ip_header, ether_header, config);
}
if (((ntohs(udp_header->dest)) == RELAY_PORT) && (dhcp_header->msg_type == SOLICIT || REQUEST || CONFIRM || RENEW || REBIND || RELEASE || DECLINE)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This condition will always be true:
(dhcp_header->msg_type == SOLICIT || REQUEST || CONFIRM || RENEW || REBIND || RELEASE || DECLINE)

relay_client(config->local_sock, current_position, ntohs(udp_header->len) - sizeof(udphdr), ip_header, ether_header, config);
}
}

Expand Down
14 changes: 2 additions & 12 deletions src/dhcp6relay/src/relay.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

#define PACKED __attribute__ ((packed))

#define RELAY_PORT 547
#define CLIENT_PORT 546
#define HOP_LIMIT 32

#define lengthof(A) (sizeof (A) / sizeof (A)[0])
Expand Down Expand Up @@ -75,18 +77,6 @@ struct linklayer_addr_option {
uint16_t link_layer_type;
};

class ArgumentParser {
public:
void parse_args(int argc, char *argv[]);

arg_config get_arg();


private:
arg_config m_config;

};


void initialize_server(relay_config *context);

Expand Down