diff --git a/code/bngblaster/src/bbl_config.c b/code/bngblaster/src/bbl_config.c index 7de5e42f..d3cc10f4 100644 --- a/code/bngblaster/src/bbl_config.c +++ b/code/bngblaster/src/bbl_config.c @@ -584,6 +584,13 @@ json_parse_network_interface(json_t *network_interface, bbl_network_config_s *ne return false; } } + value = json_object_get(network_interface, "ipv6-router-advertisement"); + if(json_is_boolean(value)) { + network_config->ipv6_ra = json_boolean_value(value); + } else { + network_config->ipv6_ra = true; + } + if(json_unpack(network_interface, "{s:s}", "gateway-mac", &s) == 0) { if(sscanf(s, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &network_config->gateway_mac[0], diff --git a/code/bngblaster/src/bbl_config.h b/code/bngblaster/src/bbl_config.h index bbfc636a..89686f4b 100644 --- a/code/bngblaster/src/bbl_config.h +++ b/code/bngblaster/src/bbl_config.h @@ -100,6 +100,7 @@ typedef struct bbl_network_config_ ipv4_prefix ip; ipv4addr_t gateway; + bool ipv6_ra; ipv6_prefix ip6; ipv6addr_t gateway6; diff --git a/code/bngblaster/src/bbl_def.h b/code/bngblaster/src/bbl_def.h index bf4970c8..645aeca4 100644 --- a/code/bngblaster/src/bbl_def.h +++ b/code/bngblaster/src/bbl_def.h @@ -89,8 +89,9 @@ /* Network Interface Send Mask */ #define BBL_IF_SEND_ARP_REQUEST 0x00000001 #define BBL_IF_SEND_ICMPV6_NS 0x00000002 -#define BBL_IF_SEND_ISIS_P2P_HELLO 0x00000004 -#define BBL_IF_SEND_LDP_HELLO 0x00000008 +#define BBL_IF_SEND_ICMPV6_RA 0x00000004 +#define BBL_IF_SEND_ISIS_P2P_HELLO 0x00000008 +#define BBL_IF_SEND_LDP_HELLO 0x00000010 #define BBL_AVG_SAMPLES 5 #define BBL_MAX_STREAM_OVERHEAD 128 diff --git a/code/bngblaster/src/bbl_network.c b/code/bngblaster/src/bbl_network.c index 1b628042..24cb8f02 100644 --- a/code/bngblaster/src/bbl_network.c +++ b/code/bngblaster/src/bbl_network.c @@ -118,6 +118,10 @@ bbl_network_interfaces_add() network_interface->ip6_ll[13] = network_interface->mac[3]; network_interface->ip6_ll[14] = network_interface->mac[4]; network_interface->ip6_ll[15] = network_interface->mac[5]; + if(network_config->ipv6_ra) { + network_interface->ipv6_ra = true; + network_interface->send_requests |= BBL_IF_SEND_ICMPV6_RA; + } /* Init IPv6 */ if(ipv6_prefix_not_zero(&network_config->ip6) && @@ -366,6 +370,8 @@ bbl_network_rx_icmpv6(bbl_network_interface_s *interface, secondary_ip6 = secondary_ip6->next; } } + } else if(icmpv6->type == IPV6_ICMPV6_ROUTER_SOLICITATION && interface->ipv6_ra) { + interface->send_requests |= BBL_IF_SEND_ICMPV6_RA; } else if(icmpv6->type == IPV6_ICMPV6_ECHO_REQUEST) { bbl_network_icmpv6_echo_reply(interface, eth, ipv6, icmpv6); } diff --git a/code/bngblaster/src/bbl_network.h b/code/bngblaster/src/bbl_network.h index 7acc9834..bd654ac1 100644 --- a/code/bngblaster/src/bbl_network.h +++ b/code/bngblaster/src/bbl_network.h @@ -34,6 +34,9 @@ typedef struct bbl_network_interface_ ipv4_prefix ip; ipv4addr_t gateway; + bool ipv6_enabled; + bool ipv6_ra; + ipv6_prefix ip6; /* global IPv6 address */ ipv6addr_t ip6_ll; /* link-local IPv6 address */ ipv6addr_t gateway6; diff --git a/code/bngblaster/src/bbl_protocols.c b/code/bngblaster/src/bbl_protocols.c index 246682d1..c1b13722 100644 --- a/code/bngblaster/src/bbl_protocols.c +++ b/code/bngblaster/src/bbl_protocols.c @@ -713,6 +713,24 @@ encode_icmpv6(uint8_t *buf, uint16_t *len, *(uint32_t*)buf = 0; BUMP_WRITE_BUFFER(buf, len, sizeof(uint32_t)); break; + case IPV6_ICMPV6_ROUTER_ADVERTISEMENT: + *buf = 64; /* Hop Limit */ + BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t)); + *buf = 0; /* Flags */ + BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t)); + *(uint16_t*)buf = htobe16(30); /* Router lifetime */ + BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t)); + *(uint32_t*)buf = 0; /* Reachable time */ + BUMP_WRITE_BUFFER(buf, len, sizeof(uint32_t)); + *(uint32_t*)buf = 0; /* Retrans time */ + BUMP_WRITE_BUFFER(buf, len, sizeof(uint32_t)); + *buf = 1; /* Source link-layer address */ + BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t)); + *buf = 1; /* Length (1 = 8 byte) */ + BUMP_WRITE_BUFFER(buf, len, sizeof(uint8_t)); + memcpy(buf, icmp->mac, ETH_ADDR_LEN); + BUMP_WRITE_BUFFER(buf, len, ETH_ADDR_LEN); + break; case IPV6_ICMPV6_NEIGHBOR_SOLICITATION: *(uint32_t*)buf = 0; /* Reserved */ BUMP_WRITE_BUFFER(buf, len, sizeof(uint32_t)); diff --git a/code/bngblaster/src/bbl_tx.c b/code/bngblaster/src/bbl_tx.c index 4ed1c606..6d7863bc 100644 --- a/code/bngblaster/src/bbl_tx.c +++ b/code/bngblaster/src/bbl_tx.c @@ -1373,6 +1373,13 @@ bbl_tx_network_nd_timeout(timer_s *timer) interface->send_requests |= BBL_IF_SEND_ICMPV6_NS; } +void +bbl_tx_network_ra_timeout(timer_s *timer) +{ + bbl_network_interface_s *interface = timer->data; + interface->send_requests |= BBL_IF_SEND_ICMPV6_RA; +} + static protocol_error_t bbl_tx_encode_network_packet(bbl_network_interface_s *interface, uint8_t *buf, uint16_t *len) { @@ -1426,6 +1433,22 @@ bbl_tx_encode_network_packet(bbl_network_interface_s *interface, uint8_t *buf, u 1, 0, interface, &bbl_tx_network_nd_timeout); } result = encode_ethernet(buf, len, ð); + } else if(interface->send_requests & BBL_IF_SEND_ICMPV6_RA) { + interface->send_requests &= ~BBL_IF_SEND_ICMPV6_RA; + ipv6_multicast_mac(ipv6_multicast_all_nodes, mac); + eth.dst = mac; + eth.type = ETH_TYPE_IPV6; + eth.next = &ipv6; + ipv6.src = interface->ip6_ll; + ipv6.dst = (void*)ipv6_multicast_all_nodes; + ipv6.protocol = IPV6_NEXT_HEADER_ICMPV6; + ipv6.next = &icmpv6; + ipv6.ttl = 255; + icmpv6.type = IPV6_ICMPV6_ROUTER_ADVERTISEMENT; + icmpv6.mac = interface->mac; + timer_add(&g_ctx->timer_root, &interface->timer_nd, "RA timer", + 10, 0, interface, &bbl_tx_network_ra_timeout); + result = encode_ethernet(buf, len, ð); } else if(interface->send_requests & BBL_IF_SEND_ISIS_P2P_HELLO) { interface->send_requests &= ~BBL_IF_SEND_ISIS_P2P_HELLO; result = isis_p2p_hello_encode(interface, buf, len, ð);