add support for IPv6 TCP and LDP (initial draft)

This commit is contained in:
Christian Giese
2023-04-20 12:31:47 +00:00
parent b585e36fd8
commit 4e0550441c
17 changed files with 574 additions and 124 deletions
+22 -1
View File
@@ -1653,7 +1653,10 @@ json_parse_ldp_config(json_t *ldp, ldp_config_s *ldp_config)
const char *schema[] = {
"instance-id", "keepalive-time", "hold-time",
"teardown-time", "hostname", "lsr-id",
"ipv4-transport-address", "raw-update-file"
"ipv4-transport", "ipv4-transport-address",
"ipv6-transport", "ipv6-transport-address",
"prefer-ipv4-transport"
"raw-update-file"
};
if(!schema_validate(ldp, "ldp", schema,
sizeof(schema)/sizeof(schema[0]))) {
@@ -1704,6 +1707,14 @@ json_parse_ldp_config(json_t *ldp, ldp_config_s *ldp_config)
fprintf(stderr, "JSON config error: Invalid value for ldp->lsr-id\n");
return false;
}
if(json_unpack(ldp, "{s:s}", "ipv6-transport-address", &s) == 0) {
if(!inet_pton(AF_INET6, s, &ldp_config->ipv6_transport_address)) {
fprintf(stderr, "JSON config error: Invalid value for ldp->ipv6-transport-address\n");
return false;
}
}
if(json_unpack(ldp, "{s:s}", "ipv4-transport-address", &s) == 0) {
if(!inet_pton(AF_INET, s, &ldp_config->ipv4_transport_address)) {
fprintf(stderr, "JSON config error: Invalid value for ldp->ipv4-transport-address\n");
@@ -1713,6 +1724,16 @@ json_parse_ldp_config(json_t *ldp, ldp_config_s *ldp_config)
ldp_config->ipv4_transport_address = ldp_config->lsr_id;
}
value = json_object_get(ldp, "no-ipv4-transport");
if(json_is_boolean(value)) {
ldp_config->no_ipv4_transport = json_boolean_value(value);
}
value = json_object_get(ldp, "prefer-ipv4-transport");
if(json_is_boolean(value)) {
ldp_config->prefer_ipv4_transport = json_boolean_value(value);
}
if(json_unpack(ldp, "{s:s}", "raw-update-file", &s) == 0) {
ldp_config->raw_update_file = strdup(s);
if(!ldp_raw_update_load(ldp_config->raw_update_file, true)) {
+2 -1
View File
@@ -99,7 +99,8 @@ static const ipv6_prefix mock_ipv6_ia_pd = {
#define BBL_IF_SEND_ICMPV6_NS 0x00000002
#define BBL_IF_SEND_ICMPV6_RA 0x00000004
#define BBL_IF_SEND_ISIS_P2P_HELLO 0x00000008
#define BBL_IF_SEND_LDP_HELLO 0x00000010
#define BBL_IF_SEND_LDP_HELLO_IPV4 0x00000010
#define BBL_IF_SEND_LDP_HELLO_IPV6 0x00000020
#define BBL_AVG_SAMPLES 5
#define BBL_MAX_STREAM_OVERHEAD 128
+17 -1
View File
@@ -419,7 +419,7 @@ bbl_network_rx_handler(bbl_network_interface_s *interface,
/* LDP hello is send to all routers multicast address and therefore
* processed before check on local MAC address. */
if(udp->protocol == UDP_PROTOCOL_LDP) {
ldp_hello_rx(interface, eth, ipv4, (bbl_ldp_hello_s*)udp->next);
ldp_hello_ipv4_rx(interface, eth, ipv4, (bbl_ldp_hello_s*)udp->next);
return;
}
if(memcmp(interface->mac, eth->dst, ETH_ADDR_LEN) != 0) {
@@ -456,6 +456,22 @@ bbl_network_rx_handler(bbl_network_interface_s *interface,
if(ipv6->protocol == IPV6_NEXT_HEADER_ICMPV6) {
bbl_network_rx_icmpv6(interface, eth);
return;
} else if(ipv6->protocol == IPV6_NEXT_HEADER_UDP) {
udp = (bbl_udp_s*)ipv6->next;
/* LDP hello is send to all routers multicast address and therefore
* processed before check on local MAC address. */
if(udp->protocol == UDP_PROTOCOL_LDP) {
ldp_hello_ipv6_rx(interface, eth, ipv6, (bbl_ldp_hello_s*)udp->next);
return;
}
} else if(ipv6->protocol == IPV6_NEXT_HEADER_TCP) {
if(memcmp(interface->mac, eth->dst, ETH_ADDR_LEN) != 0) {
/* Drop wrong MAC */
return;
}
interface->stats.tcp_rx++;
bbl_tcp_ipv6_rx(interface, eth, ipv6);
return;
}
break;
case ISIS_PROTOCOL_IDENTIFIER:
+60 -12
View File
@@ -59,7 +59,7 @@ _checksum(void *buf, ssize_t len)
static uint32_t
_fold(uint32_t sum)
{
while (sum>>16) {
while (sum >> 16) {
sum = (sum & 0xffff) + (sum >> 16);
}
return sum;
@@ -616,11 +616,16 @@ encode_dhcp(uint8_t *buf, uint16_t *len,
static protocol_error_t
encode_ldp_hello(uint8_t *buf, uint16_t *len, bbl_ldp_hello_s *ldp)
{
uint8_t *start = buf;
uint16_t pdu_len;
uint16_t msg_len;
/* PDU version and length */
*(uint16_t*)buf = htobe16(1);
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
*(uint16_t*)buf = htobe16(30);
*(uint16_t*)buf = 0;
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
pdu_len = *len;
/* LDP identifier (LSR ID + label space) */
*(uint32_t*)buf = ldp->lsr_id;
@@ -631,8 +636,9 @@ encode_ldp_hello(uint8_t *buf, uint16_t *len, bbl_ldp_hello_s *ldp)
/* LDP message type and length */
*(uint16_t*)buf = htobe16(LDP_MESSAGE_TYPE_HELLO);
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
*(uint16_t*)buf = htobe16(20);
*(uint16_t*)buf = 0;
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
msg_len = *len;
/* LDP message ID */
*(uint32_t*)buf = htobe32(ldp->msg_id);
@@ -649,12 +655,42 @@ encode_ldp_hello(uint8_t *buf, uint16_t *len, bbl_ldp_hello_s *ldp)
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
/* IPv4 transport address TLV */
*(uint16_t*)buf = htobe16(LDP_TLV_TYPE_IPV4_TRANSPORT_ADDRESS);
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
*(uint16_t*)buf = htobe16(4);
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
*(uint32_t*)buf = ldp->ipv4_transport_address;
BUMP_WRITE_BUFFER(buf, len, sizeof(uint32_t));
if(ldp->ipv4_transport_address) {
*(uint16_t*)buf = htobe16(LDP_TLV_TYPE_IPV4_TRANSPORT_ADDRESS);
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
*(uint16_t*)buf = htobe16(sizeof(uint32_t));
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
*(uint32_t*)buf = ldp->ipv4_transport_address;
BUMP_WRITE_BUFFER(buf, len, sizeof(uint32_t));
}
/* IPv6 transport address TLV */
if(ldp->ipv6_transport_address) {
*(uint16_t*)buf = htobe16(LDP_TLV_TYPE_IPV6_TRANSPORT_ADDRESS);
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
*(uint16_t*)buf = htobe16(sizeof(ipv6addr_t));
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
memcpy(buf, ldp->ipv6_transport_address, sizeof(ipv6addr_t));
BUMP_WRITE_BUFFER(buf, len, sizeof(ipv6addr_t));
}
/* Dual-Stack capability TLV */
if(ldp->dual_stack_capability) {
*(uint16_t*)buf = htobe16(LDP_TLV_TYPE_DUAL_STACK_CAPABILITY);
*buf |= 0x80;
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
*(uint16_t*)buf = htobe16(sizeof(uint32_t));
BUMP_WRITE_BUFFER(buf, len, sizeof(uint16_t));
*(uint32_t*)buf = 0;
*buf = (ldp->dual_stack_capability << 4) & 0xF0;
BUMP_WRITE_BUFFER(buf, len, sizeof(uint32_t));
}
/* Update total length */
pdu_len = *len - pdu_len;
msg_len = *len - msg_len;
*(uint16_t*)(start + 2) = htobe16(pdu_len);
*(uint16_t*)(start + 12) = htobe16(msg_len);
return PROTOCOL_SUCCESS;
}
@@ -826,7 +862,6 @@ encode_icmpv6(uint8_t *buf, uint16_t *len,
/* Update checksum */
*(uint16_t*)(start + 2) = bbl_checksum(start, icmp_len);
return PROTOCOL_SUCCESS;
}
@@ -2991,7 +3026,7 @@ decode_ldp_hello(uint8_t *buf, uint16_t len,
/* LDP TLV's */
while(len >= LDP_TLV_LEN_MIN) {
tlv_type = be16toh(*(uint16_t*)buf);
tlv_type = be16toh(*(uint16_t*)buf) & LDP_TLV_TYPE_MASK;
BUMP_BUFFER(buf, len, sizeof(uint16_t));
tlv_len = be16toh(*(uint16_t*)buf);
BUMP_BUFFER(buf, len, sizeof(uint16_t));
@@ -3006,11 +3041,23 @@ decode_ldp_hello(uint8_t *buf, uint16_t len,
ldp->hold_time = be16toh(*(uint16_t*)buf);
break;
case LDP_TLV_TYPE_IPV4_TRANSPORT_ADDRESS:
if(tlv_len != 4) {
if(tlv_len != sizeof(uint32_t)) {
return DECODE_ERROR;
}
ldp->ipv4_transport_address = *(uint32_t*)buf;
break;
case LDP_TLV_TYPE_IPV6_TRANSPORT_ADDRESS:
if(tlv_len != sizeof(ipv6addr_t)) {
return DECODE_ERROR;
}
ldp->ipv6_transport_address = (ipv6addr_t*)buf;
break;
case LDP_TLV_TYPE_DUAL_STACK_CAPABILITY:
if(tlv_len != 4) {
return DECODE_ERROR;
}
ldp->dual_stack_capability = (*buf >> 4) & 0x0F;
break;
default:
break;
}
@@ -3182,6 +3229,7 @@ decode_ipv6(uint8_t *buf, uint16_t len,
ipv6->dst = buf;
BUMP_BUFFER(buf, len, IPV6_ADDR_LEN);
ipv6->payload = buf;
if(ipv6->payload_len > len) {
return DECODE_ERROR;
}
+7 -5
View File
@@ -552,11 +552,13 @@ typedef struct bbl_isis_ {
} bbl_isis_s;
typedef struct bbl_ldp_hello_ {
uint32_t lsr_id;
uint16_t label_space_id;
uint32_t msg_id;
uint32_t ipv4_transport_address;
uint16_t hold_time;
uint32_t lsr_id;
uint16_t label_space_id;
uint16_t hold_time;
uint32_t msg_id;
uint32_t ipv4_transport_address;
ipv6addr_t *ipv6_transport_address;
uint8_t dual_stack_capability;
} bbl_ldp_hello_s;
typedef struct bbl_bbl_ {
+149 -54
View File
@@ -188,14 +188,14 @@ bbl_tcp_error_cb(void *arg, err_t err)
if(tcpc->af == AF_INET) {
LOG(TCP, "TCP (%s %s:%u - %s:%u) error %d (%s)\n",
tcpc->interface->name,
format_ipv4_address(&tcpc->local_ipv4), tcpc->local_port,
format_ipv4_address(&tcpc->remote_ipv4), tcpc->remote_port,
format_ipv4_address(&tcpc->local_addr.u_addr.ip4.addr), tcpc->local_port,
format_ipv4_address(&tcpc->remote_addr.u_addr.ip4.addr), tcpc->remote_port,
err, tcp_err_string(err));
} else {
LOG(TCP, "TCP (%s %s:%u - %s:%u) error %d (%s)\n",
tcpc->interface->name,
format_ipv6_address(&tcpc->local_ipv6), tcpc->local_port,
format_ipv6_address(&tcpc->remote_ipv6), tcpc->remote_port,
format_ipv6_address((ipv6addr_t*)&tcpc->local_addr.u_addr.ip6.addr), tcpc->local_port,
format_ipv6_address((ipv6addr_t*)&tcpc->local_addr.u_addr.ip6.addr), tcpc->remote_port,
err, tcp_err_string(err));
}
@@ -240,13 +240,13 @@ bbl_tcp_connected(void *arg, struct tcp_pcb *tpcb, err_t err)
if(tcpc->af == AF_INET) {
LOG(TCP, "TCP (%s %s:%u - %s:%u) session connected\n",
tcpc->interface->name,
format_ipv4_address(&tcpc->local_ipv4), tcpc->local_port,
format_ipv4_address(&tcpc->remote_ipv4), tcpc->remote_port);
format_ipv4_address(&tcpc->local_addr.u_addr.ip4.addr), tcpc->local_port,
format_ipv4_address(&tcpc->remote_addr.u_addr.ip4.addr), tcpc->remote_port);
} else {
LOG(TCP, "TCP (%s %s:%u - %s:%u) session connected\n",
tcpc->interface->name,
format_ipv6_address(&tcpc->local_ipv6), tcpc->local_port,
format_ipv6_address(&tcpc->remote_ipv6), tcpc->remote_port);
format_ipv6_address((ipv6addr_t*)&tcpc->local_addr.u_addr.ip6.addr), tcpc->local_port,
format_ipv6_address((ipv6addr_t*)&tcpc->remote_addr.u_addr.ip6.addr), tcpc->remote_port);
}
tcpc->state = BBL_TCP_STATE_IDLE;
@@ -260,7 +260,7 @@ bbl_tcp_connected(void *arg, struct tcp_pcb *tpcb, err_t err)
}
err_t
bbl_tcp_ipv4_listen_accepted(void *arg, struct tcp_pcb *tpcb, err_t err)
bbl_tcp_listen_accepted(void *arg, struct tcp_pcb *tpcb, err_t err)
{
bbl_tcp_ctx_s *listen = arg;
bbl_tcp_ctx_s *tcpc;
@@ -297,25 +297,24 @@ bbl_tcp_ipv4_listen_accepted(void *arg, struct tcp_pcb *tpcb, err_t err)
tcp_err(tpcb, bbl_tcp_error_cb);
if(tcpc->af == AF_INET) {
tcpc->local_ipv4 = tpcb->local_ip.u_addr.ip4.addr;
tcpc->remote_ipv4 = tpcb->remote_ip.u_addr.ip4.addr;
tcpc->local_addr.u_addr.ip4.addr = tpcb->local_ip.u_addr.ip4.addr;
tcpc->remote_addr.u_addr.ip4.addr = tpcb->remote_ip.u_addr.ip4.addr;
LOG(TCP, "TCP (%s %s:%u - %s:%u) session accepted\n",
tcpc->interface->name,
format_ipv4_address(&tcpc->local_ipv4), tcpc->local_port,
format_ipv4_address(&tcpc->remote_ipv4), tcpc->remote_port);
format_ipv4_address(&tcpc->local_addr.u_addr.ip4.addr), tcpc->local_port,
format_ipv4_address(&tcpc->remote_addr.u_addr.ip4.addr), tcpc->remote_port);
} else {
memcpy(tcpc->local_ipv6, tpcb->local_ip.u_addr.ip6.addr, IPV6_ADDR_LEN);
memcpy(tcpc->remote_ipv6, tpcb->remote_ip.u_addr.ip6.addr, IPV6_ADDR_LEN);
memcpy(&tcpc->local_addr.u_addr.ip6.addr, &tpcb->local_ip.u_addr.ip6.addr, IPV6_ADDR_LEN);
memcpy(&tcpc->remote_addr.u_addr.ip6.addr, &tpcb->remote_ip.u_addr.ip6.addr, IPV6_ADDR_LEN);
LOG(TCP, "TCP (%s %s:%u - %s:%u) session accepted\n",
tcpc->interface->name,
format_ipv6_address(&tcpc->local_ipv6), tcpc->local_port,
format_ipv6_address(&tcpc->remote_ipv6), tcpc->remote_port);
format_ipv6_address((ipv6addr_t*)&tcpc->local_addr.u_addr.ip6.addr), tcpc->local_port,
format_ipv6_address((ipv6addr_t*)&tcpc->remote_addr.u_addr.ip6.addr), tcpc->remote_port);
}
/* Call application TCP accepted callback function. */
if(listen->accepted_cb) {
if((listen->accepted_cb)(tcpc, listen->arg) != ERR_OK) {
free(tcpc);
tcp_abort(tpcb);
return ERR_ABRT;
};
@@ -355,23 +354,72 @@ bbl_tcp_ipv4_listen(bbl_network_interface_s *interface, ipv4addr_t *address, uin
}
/* Bind local IP address and port */
if(tcp_bind(tcpc->pcb, (const ip_addr_t*)address, port) != ERR_OK) {
tcpc->local_addr.u_addr.ip4.addr = *address;
if(tcp_bind(tcpc->pcb, &tcpc->local_addr, port) != ERR_OK) {
bbl_tcp_ctx_free(tcpc);
}
tcpc->pcb = tcp_listen(tcpc->pcb);
tcp_accept(tcpc->pcb, bbl_tcp_ipv4_listen_accepted);
tcp_accept(tcpc->pcb, bbl_tcp_listen_accepted);
tcpc->listen = true;
tcpc->af = AF_INET;
tcpc->local_port = port;
tcpc->local_ipv4 = *address;
tcpc->pcb->local_ip.type = IPADDR_TYPE_V4;
tcpc->pcb->remote_ip.type = IPADDR_TYPE_V4;
tcpc->state = BBL_TCP_STATE_LISTEN;
LOG(TCP, "TCP (%s %s:%u) listen\n",
interface->name,
format_ipv4_address(&tcpc->local_ipv4), tcpc->local_port);
format_ipv4_address(&tcpc->local_addr.u_addr.ip4.addr),
tcpc->local_port);
return tcpc;
}
/**
* bbl_tcp_ipv6_listen
*
* @param interface interface
* @param address local address
* @param port local port
* @return TCP context
*/
bbl_tcp_ctx_s *
bbl_tcp_ipv6_listen(bbl_network_interface_s *interface, ipv6addr_t *address, uint16_t port)
{
bbl_tcp_ctx_s *tcpc;
if(!g_ctx->tcp) {
/* TCP not enabled! */
return NULL;
}
tcpc = bbl_tcp_ctx_new(interface);
if(!tcpc) {
return NULL;
}
/* Bind local IP address and port */
memcpy(&tcpc->local_addr.u_addr.ip6.addr, address, sizeof(ip6_addr_t));
tcpc->local_addr.type = IPADDR_TYPE_V6;
if(tcp_bind(tcpc->pcb, &tcpc->local_addr, port) != ERR_OK) {
bbl_tcp_ctx_free(tcpc);
}
tcpc->pcb = tcp_listen(tcpc->pcb);
tcp_accept(tcpc->pcb, bbl_tcp_listen_accepted);
tcpc->listen = true;
tcpc->af = AF_INET6;
tcpc->local_port = port;
tcpc->remote_addr.type = IPADDR_TYPE_V6;
tcpc->pcb->local_ip.type = IPADDR_TYPE_V6;
tcpc->pcb->remote_ip.type = IPADDR_TYPE_V6;
tcpc->state = BBL_TCP_STATE_LISTEN;
LOG(TCP, "TCP (%s %s:%u) listen\n",
interface->name,
format_ipv6_address((ipv6addr_t*)&tcpc->local_addr.u_addr.ip6.addr),
tcpc->local_port);
return tcpc;
}
@@ -401,13 +449,15 @@ bbl_tcp_ipv4_connect(bbl_network_interface_s *interface, ipv4addr_t *src, ipv4ad
}
/* Bind local IP address and port */
tcp_bind(tcpc->pcb, (const ip_addr_t*)src, 0);
tcpc->local_addr.u_addr.ip4.addr = *src;
tcp_bind(tcpc->pcb, &tcpc->local_addr, 0);
/* Disable nagle algorithm */
tcp_nagle_disable(tcpc->pcb);
/* Connect session */
if(tcp_connect(tcpc->pcb, (const ip_addr_t*)dst, port, bbl_tcp_connected) != ERR_OK) {
tcpc->remote_addr.u_addr.ip4.addr = *dst;
if(tcp_connect(tcpc->pcb, &tcpc->remote_addr, port, bbl_tcp_connected) != ERR_OK) {
bbl_tcp_ctx_free(tcpc);
return NULL;
}
@@ -416,15 +466,72 @@ bbl_tcp_ipv4_connect(bbl_network_interface_s *interface, ipv4addr_t *src, ipv4ad
tcpc->af = AF_INET;
tcpc->local_port = tcpc->pcb->local_port;
tcpc->remote_port = port;
tcpc->local_ipv4 = *src;
tcpc->remote_ipv4 = *dst;
tcpc->pcb->local_ip.type = IPADDR_TYPE_V4;
tcpc->pcb->remote_ip.type = IPADDR_TYPE_V4;
tcpc->state = BBL_TCP_STATE_CONNECTING;
LOG(TCP, "TCP (%s %s:%u - %s:%u) connect\n",
interface->name,
format_ipv4_address(&tcpc->local_ipv4), tcpc->local_port,
format_ipv4_address(&tcpc->remote_ipv4), tcpc->remote_port);
format_ipv4_address(&tcpc->local_addr.u_addr.ip4.addr),
tcpc->local_port,
format_ipv4_address(&tcpc->remote_addr.u_addr.ip4.addr),
tcpc->remote_port);
return tcpc;
}
/**
* bbl_tcp_ipv6_connect
*
* @param interface interface
* @param src source address
* @param dst destination address
* @param port destination port
* @return TCP context
*/
bbl_tcp_ctx_s *
bbl_tcp_ipv6_connect(bbl_network_interface_s *interface, ipv6addr_t *src, ipv6addr_t *dst, uint16_t port)
{
bbl_tcp_ctx_s *tcpc;
if(!g_ctx->tcp) {
/* TCP not enabled! */
return NULL;
}
tcpc = bbl_tcp_ctx_new(interface);
if(!tcpc) {
return NULL;
}
/* Bind local IP address and port */
memcpy(&tcpc->local_addr.u_addr.ip6.addr, src, sizeof(ip6_addr_t));
tcpc->local_addr.type = IPADDR_TYPE_V6;
tcp_bind(tcpc->pcb, &tcpc->local_addr, 0);
/* Disable nagle algorithm */
tcp_nagle_disable(tcpc->pcb);
/* Connect session */
memcpy(&tcpc->remote_addr.u_addr.ip6.addr, dst, sizeof(ip6_addr_t));
tcpc->remote_addr.type = IPADDR_TYPE_V6;
if(tcp_connect(tcpc->pcb, &tcpc->remote_addr, port, bbl_tcp_connected) != ERR_OK) {
bbl_tcp_ctx_free(tcpc);
return NULL;
}
tcp_err(tcpc->pcb, bbl_tcp_error_cb);
tcpc->af = AF_INET;
tcpc->local_port = tcpc->pcb->local_port;
tcpc->remote_port = port;
tcpc->pcb->local_ip.type = IPADDR_TYPE_V6;
tcpc->pcb->remote_ip.type = IPADDR_TYPE_V6;
tcpc->state = BBL_TCP_STATE_CONNECTING;
LOG(TCP, "TCP (%s %s:%u - %s:%u) connect\n",
interface->name,
format_ipv6_address((ipv6addr_t*)&tcpc->local_addr.u_addr.ip6.addr),
tcpc->local_port,
format_ipv6_address((ipv6addr_t*)&tcpc->remote_addr.u_addr.ip6.addr),
tcpc->remote_port);
return tcpc;
}
@@ -465,30 +572,6 @@ bbl_tcp_ipv4_rx(bbl_network_interface_s *interface, bbl_ethernet_header_s *eth,
tcp_input(pbuf, &interface->netif);
}
/**
* bbl_tcp_ipv6_connect
*
* @param interface interface
* @param src source address
* @param dst destination address
* @param port destination port
* @return TCP context
*/
bbl_tcp_ctx_s *
bbl_tcp_ipv6_connect(bbl_network_interface_s *interface, ipv6addr_t *src, ipv6addr_t *dst, uint16_t port)
{
if(!g_ctx->tcp) {
/* TCP not enabled! */
return NULL;
}
UNUSED(interface);
UNUSED(src);
UNUSED(dst);
UNUSED(port);
return NULL;
}
/**
* bbl_tcp_ipv6_rx
*
@@ -517,6 +600,18 @@ bbl_tcp_ipv6_rx(bbl_network_interface_s *interface, bbl_ethernet_header_s *eth,
pbuf = pbuf_alloc_reference(ipv6->hdr, ipv6->len, PBUF_ROM);
interface->netif.input(pbuf, &interface->netif);
ip_data.current_netif = &interface->netif;
ip_data.current_input_netif = &interface->netif;
memcpy(&ip_data.current_iphdr_dest.u_addr.ip6.addr, ipv6->dst, sizeof(ip6_addr_t));
ip_data.current_iphdr_dest.u_addr.ip6.zone = 0;
ip_data.current_iphdr_dest.type = IPADDR_TYPE_V6;
memcpy(&ip_data.current_iphdr_src.u_addr.ip6.addr, ipv6->src, sizeof(ip6_addr_t));
ip_data.current_iphdr_src.u_addr.ip6.zone = 0;
ip_data.current_iphdr_src.type = IPADDR_TYPE_V6;
pbuf = pbuf_alloc_reference(ipv6->payload, ipv6->payload_len, PBUF_ROM);
tcp_input(pbuf, &interface->netif);
}
/**
@@ -625,7 +720,7 @@ bbl_tcp_network_interface_init(bbl_network_interface_s *interface, bbl_network_c
}
void
bbl_tcp_simer(timer_s *timer)
bbl_tcp_timer(timer_s *timer)
{
UNUSED(timer);
sys_check_timeouts();
@@ -648,5 +743,5 @@ bbl_tcp_init()
/* Start TCP timer */
timer_add_periodic(&g_ctx->timer_root, &g_ctx->tcp_timer, "TCP",
0, BBL_TCP_INTERVAL, g_ctx, &bbl_tcp_simer);
0, BBL_TCP_INTERVAL, g_ctx, &bbl_tcp_timer);
}
+8 -7
View File
@@ -39,12 +39,10 @@ typedef struct bbl_tcp_ctx_
uint8_t af; /* AF_INET or AF_INET6 */
uint16_t local_port;
ipv4addr_t local_ipv4;
ipv6addr_t local_ipv6;
ip_addr_t local_addr;
uint16_t remote_port;
ipv4addr_t remote_ipv4;
ipv6addr_t remote_ipv6;
ip_addr_t remote_addr;
struct tcp_pcb *pcb;
@@ -90,14 +88,17 @@ bbl_tcp_ctx_s *
bbl_tcp_ipv4_listen(bbl_network_interface_s *interface, ipv4addr_t *address, uint16_t port);
bbl_tcp_ctx_s *
bbl_tcp_ipv4_connect(bbl_network_interface_s *interface, ipv4addr_t *src, ipv4addr_t *dst, uint16_t port);
bbl_tcp_ipv6_listen(bbl_network_interface_s *interface, ipv6addr_t *address, uint16_t port);
void
bbl_tcp_ipv4_rx(bbl_network_interface_s *interface, bbl_ethernet_header_s *eth, bbl_ipv4_s *ipv4);
bbl_tcp_ctx_s *
bbl_tcp_ipv4_connect(bbl_network_interface_s *interface, ipv4addr_t *src, ipv4addr_t *dst, uint16_t port);
bbl_tcp_ctx_s *
bbl_tcp_ipv6_connect(bbl_network_interface_s *interface, ipv6addr_t *src, ipv6addr_t *dst, uint16_t port);
void
bbl_tcp_ipv4_rx(bbl_network_interface_s *interface, bbl_ethernet_header_s *eth, bbl_ipv4_s *ipv4);
void
bbl_tcp_ipv6_rx(bbl_network_interface_s *interface, bbl_ethernet_header_s *eth, bbl_ipv6_s *ipv6);
+6 -3
View File
@@ -1465,9 +1465,12 @@ bbl_tx_encode_network_packet(bbl_network_interface_s *interface, uint8_t *buf, u
} 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, &eth);
} else if(interface->send_requests & BBL_IF_SEND_LDP_HELLO) {
interface->send_requests &= ~BBL_IF_SEND_LDP_HELLO;
result = ldp_hello_encode(interface, buf, len, &eth);
} else if(interface->send_requests & BBL_IF_SEND_LDP_HELLO_IPV6) {
interface->send_requests &= ~BBL_IF_SEND_LDP_HELLO_IPV6;
result = ldp_hello_ipv6_encode(interface, buf, len, &eth);
} else if(interface->send_requests & BBL_IF_SEND_LDP_HELLO_IPV4) {
interface->send_requests &= ~BBL_IF_SEND_LDP_HELLO_IPV4;
result = ldp_hello_ipv4_encode(interface, buf, len, &eth);
} else {
interface->send_requests = 0;
}
+12 -2
View File
@@ -86,6 +86,8 @@ ldp_ctrl_session_json(ldp_session_s *session)
json_t *stats = NULL;
const char *raw_update_file = NULL;
char *local_address;
char *peer_address;
if(!session) {
return NULL;
@@ -107,12 +109,20 @@ ldp_ctrl_session_json(ldp_session_s *session)
return NULL;
}
if(session->ipv6) {
local_address = format_ipv6_address(&session->local.ipv6_address);
peer_address = format_ipv6_address(&session->peer.ipv6_address);
} else {
local_address = format_ipv4_address(&session->local.ipv4_address);
peer_address = format_ipv4_address(&session->peer.ipv4_address);
}
root = json_pack("{si ss ss ss ss ss ss si ss* ss* so*}",
"ldp-instance-id", session->instance->config->id,
"interface", session->interface->name,
"local-address", format_ipv4_address(&session->local.ipv4_address),
"local-address", local_address,
"local-identifier", ldp_id_to_str(session->local.lsr_id, session->local.label_space_id),
"peer-address", format_ipv4_address(&session->peer.ipv4_address),
"peer-address", peer_address,
"peer-identifier", ldp_id_to_str(session->peer.lsr_id, session->peer.label_space_id),
"state", ldp_session_state_string(session->state),
"state-transitions", session->state_transitions,
+16 -1
View File
@@ -33,6 +33,7 @@
#define LDP_MESSAGE_TYPE_LABEL_RELEASE 0x0403
#define LDP_MESSAGE_TYPE_ABORT_REQUEST 0x0404
#define LDP_TLV_TYPE_MASK 0x3FFF
#define LDP_TLV_TYPE_FEC 0x0100
#define LDP_TLV_TYPE_ADDRESS_LIST 0x0101
#define LDP_TLV_TYPE_HOP_COUNT 0x0103
@@ -48,6 +49,7 @@
#define LDP_TLV_TYPE_IPV6_TRANSPORT_ADDRESS 0x0403
#define LDP_TLV_TYPE_COMMON_SESSION_PARAMETERS 0x0500
#define LDP_TLV_TYPE_LABEL_REQUEST_ID 0x0600
#define LDP_TLV_TYPE_DUAL_STACK_CAPABILITY 0x0701
#define LDP_TLV_LEN_MIN 4
#define LDP_FEC_LEN_MIN 4
@@ -141,7 +143,13 @@ typedef struct ldp_config_ {
uint16_t id; /* LDP instance identifier */
uint32_t lsr_id;
uint32_t ipv4_transport_address;
bool prefer_ipv4_transport;
bool no_ipv4_transport;
uint32_t ipv4_transport_address;
ipv6addr_t ipv6_transport_address;
const char *lsr_id_str;
const char *hostname;
@@ -188,7 +196,9 @@ typedef struct ldp_session_ {
uint16_t max_pdu_len;
uint16_t keepalive_time;
bool ipv6; /* True for IPv6 transport session. */
struct {
ipv6addr_t ipv6_address;
uint32_t ipv4_address;
uint32_t lsr_id;
uint16_t label_space_id;
@@ -197,6 +207,7 @@ typedef struct ldp_session_ {
} local;
struct {
ipv6addr_t ipv6_address;
uint32_t ipv4_address;
uint32_t lsr_id;
uint16_t label_space_id;
@@ -235,6 +246,10 @@ typedef struct ldp_adjacency_ {
bbl_network_interface_s *interface;
ldp_instance_s *instance;
bool hello_ipv4;
bool hello_ipv6;
bool prefer_ipv4_transport;
struct timer_ *hello_timer;
struct timer_ *hold_timer;
+150 -15
View File
@@ -9,7 +9,7 @@
#include "ldp.h"
/**
* ldp_hello_encode
* ldp_hello_ipv4_encode
*
* @param interface send interface
* @param buf send buffer
@@ -18,9 +18,9 @@
* @return PROTOCOL_SUCCESS on success
*/
protocol_error_t
ldp_hello_encode(bbl_network_interface_s *interface,
uint8_t *buf, uint16_t *len,
bbl_ethernet_header_s *eth)
ldp_hello_ipv4_encode(bbl_network_interface_s *interface,
uint8_t *buf, uint16_t *len,
bbl_ethernet_header_s *eth)
{
protocol_error_t result;
@@ -48,20 +48,86 @@ ldp_hello_encode(bbl_network_interface_s *interface,
ldp.lsr_id = config->lsr_id;
ldp.hold_time = config->hold_time;
ldp.ipv4_transport_address = config->ipv4_transport_address;
if(adjacency->hello_ipv6) {
if(adjacency->prefer_ipv4_transport) {
ldp.dual_stack_capability = 4;
} else {
ldp.dual_stack_capability = 6;
}
}
result = encode_ethernet(buf, len, eth);
if(result == PROTOCOL_SUCCESS) {
LOG(DEBUG, "LDP TX hello on interface %s\n", interface->name);
LOG(DEBUG, "LDP TX IPv4 hello on interface %s\n", interface->name);
adjacency->interface->stats.ldp_udp_tx++;
}
return result;
}
protocol_error_t
ldp_hello_ipv6_encode(bbl_network_interface_s *interface,
uint8_t *buf, uint16_t *len,
bbl_ethernet_header_s *eth)
{
protocol_error_t result;
bbl_ipv6_s ipv6 = {0};
bbl_udp_s udp = {0};
bbl_ldp_hello_s ldp = {0};
uint8_t mac[ETH_ADDR_LEN];
ldp_adjacency_s *adjacency = interface->ldp_adjacency;
ldp_instance_s *instance = adjacency->instance;
ldp_config_s *config = instance->config;
/* Build packet ... */
ipv6_multicast_mac(ipv6_multicast_all_routers, mac);
eth->dst = mac;
eth->type = ETH_TYPE_IPV6;
eth->next = &ipv6;
ipv6.dst = (void*)ipv6_multicast_all_routers;
ipv6.src = interface->ip6_ll;
ipv6.protocol = IPV6_NEXT_HEADER_UDP;
ipv6.next = &udp;
ipv6.ttl = 255;
udp.src = LDP_PORT;
udp.dst = LDP_PORT;
udp.protocol = UDP_PROTOCOL_LDP;
udp.next = &ldp;
ldp.lsr_id = config->lsr_id;
ldp.hold_time = config->hold_time;
ldp.ipv6_transport_address = &config->ipv6_transport_address;
if(adjacency->hello_ipv4) {
if(adjacency->prefer_ipv4_transport) {
ldp.dual_stack_capability = 4;
} else {
ldp.dual_stack_capability = 6;
}
}
result = encode_ethernet(buf, len, eth);
if(result == PROTOCOL_SUCCESS) {
LOG(DEBUG, "LDP TX IPv6 hello on interface %s\n", interface->name);
adjacency->interface->stats.ldp_udp_tx++;
}
return result;
}
static void
ldp_hello_send_requests(ldp_adjacency_s *adjacency)
{
bbl_network_interface_s *interface = adjacency->interface;
if(adjacency->hello_ipv4) {
interface->send_requests |= BBL_IF_SEND_LDP_HELLO_IPV4;
}
if(adjacency->hello_ipv6) {
interface->send_requests |= BBL_IF_SEND_LDP_HELLO_IPV6;
}
}
void
ldp_hello_job(timer_s *timer)
{
ldp_adjacency_s *adjacency = timer->data;
bbl_network_interface_s *interface = adjacency->interface;
interface->send_requests |= BBL_IF_SEND_LDP_HELLO;
ldp_hello_send_requests(adjacency);
}
/**
@@ -77,6 +143,7 @@ ldp_hello_start(ldp_adjacency_s *adjacency)
if(!hello_interval) {
hello_interval = 1;
}
ldp_hello_send_requests(adjacency);
timer_add_periodic(&g_ctx->timer_root, &adjacency->hello_timer,
"LDP Hello", hello_interval, 0, adjacency,
&ldp_hello_job);
@@ -108,7 +175,7 @@ ldp_hello_restart_hold_timeout(ldp_adjacency_s *adjacency)
}
/**
* ldp_hello_rx
* ldp_hello_ipv4_rx
*
* This function handles all received LDP hello packets.
*
@@ -118,10 +185,10 @@ ldp_hello_restart_hold_timeout(ldp_adjacency_s *adjacency)
* @param ldp LDP header of received packet
*/
void
ldp_hello_rx(bbl_network_interface_s *interface,
bbl_ethernet_header_s *eth,
bbl_ipv4_s *ipv4,
bbl_ldp_hello_s *ldp)
ldp_hello_ipv4_rx(bbl_network_interface_s *interface,
bbl_ethernet_header_s *eth,
bbl_ipv4_s *ipv4,
bbl_ldp_hello_s *ldp)
{
ldp_adjacency_s *adjacency = interface->ldp_adjacency;
ldp_instance_s *instance;
@@ -130,11 +197,11 @@ ldp_hello_rx(bbl_network_interface_s *interface,
UNUSED(eth);
interface->stats.ldp_udp_rx++;
if(!adjacency) {
if(!(adjacency && adjacency->hello_ipv4)) {
return;
}
LOG(DEBUG, "LDP RX hello on interface %s\n", interface->name);
LOG(DEBUG, "LDP RX IPv4 hello on interface %s\n", interface->name);
instance = adjacency->instance;
session = instance->sessions;
@@ -157,6 +224,74 @@ ldp_hello_rx(bbl_network_interface_s *interface,
session = session->next;
}
if(ldp->dual_stack_capability &&
ldp->dual_stack_capability != 4) {
return;
}
/* Init LDP session. */
ldp_session_init(session, adjacency, ipv4, ldp);
ldp_session_ipv4_init(session, adjacency, ipv4, ldp);
return;
}
/**
* ldp_hello_ipv6_rx
*
* This function handles all received LDP hello packets.
*
* @param interface receiving interface
* @param eth received ethernet header
* @param ipv6 received ipv6 header
* @param ldp LDP header of received packet
*/
void
ldp_hello_ipv6_rx(bbl_network_interface_s *interface,
bbl_ethernet_header_s *eth,
bbl_ipv6_s *ipv6,
bbl_ldp_hello_s *ldp)
{
ldp_adjacency_s *adjacency = interface->ldp_adjacency;
ldp_instance_s *instance;
ldp_session_s *session;
UNUSED(eth);
interface->stats.ldp_udp_rx++;
if(!(adjacency && adjacency->hello_ipv6)) {
return;
}
LOG(DEBUG, "LDP RX IPv6 hello on interface %s\n", interface->name);
instance = adjacency->instance;
session = instance->sessions;
if(ldp->hold_time > 0 && ldp->hold_time < adjacency->hold_time) {
adjacency->hold_time = ldp->hold_time;
ldp_hello_start(adjacency);
}
ldp_hello_restart_hold_timeout(adjacency);
while(session) {
if(session->peer.lsr_id == ldp->lsr_id &&
session->peer.label_space_id == ldp->label_space_id) {
if(session->state == LDP_CLOSED) {
break;
} else {
return;
}
}
session = session->next;
}
if(ldp->dual_stack_capability &&
ldp->dual_stack_capability != 6) {
return;
}
/* Init LDP session. */
ldp_session_ipv6_init(session, adjacency, ipv6, ldp);
return;
}
+15 -4
View File
@@ -10,17 +10,28 @@
#define __BBL_LDP_HELLO_H__
protocol_error_t
ldp_hello_encode(bbl_network_interface_s *interface,
uint8_t *buf, uint16_t *len,
bbl_ethernet_header_s *eth);
ldp_hello_ipv4_encode(bbl_network_interface_s *interface,
uint8_t *buf, uint16_t *len,
bbl_ethernet_header_s *eth);
protocol_error_t
ldp_hello_ipv6_encode(bbl_network_interface_s *interface,
uint8_t *buf, uint16_t *len,
bbl_ethernet_header_s *eth);
void
ldp_hello_start(ldp_adjacency_s *adjacency);
void
ldp_hello_rx(bbl_network_interface_s *interface,
ldp_hello_ipv4_rx(bbl_network_interface_s *interface,
bbl_ethernet_header_s *eth,
bbl_ipv4_s *ipv4,
bbl_ldp_hello_s *ldp);
void
ldp_hello_ipv6_rx(bbl_network_interface_s *interface,
bbl_ethernet_header_s *eth,
bbl_ipv6_s *ipv6,
bbl_ldp_hello_s *ldp);
#endif
+9 -1
View File
@@ -35,7 +35,15 @@ ldp_interface_init(bbl_network_interface_s *interface,
adjacency->interface = interface;
adjacency->hold_time = config->hold_time;
interface->ldp_adjacency = adjacency;
if(!config->no_ipv4_transport) {
adjacency->hello_ipv4 = true;
adjacency->prefer_ipv4_transport = config->prefer_ipv4_transport;
}
if(ipv6_addr_not_zero(&config->ipv6_transport_address)) {
adjacency->hello_ipv6 = true;
}
ldp_hello_start(adjacency);
return true;
}
+88 -11
View File
@@ -317,11 +317,19 @@ ldp_session_connect_job(timer_s *timer)
timeout = 1;
} else if(session->state == LDP_IDLE) {
/* Connect TCP session */
session->tcpc = bbl_tcp_ipv4_connect(
session->interface,
&session->local.ipv4_address,
&session->peer.ipv4_address,
LDP_PORT);
if(session->ipv6) {
session->tcpc = bbl_tcp_ipv6_connect(
session->interface,
&session->local.ipv6_address,
&session->peer.ipv6_address,
LDP_PORT);
} else {
session->tcpc = bbl_tcp_ipv4_connect(
session->interface,
&session->local.ipv4_address,
&session->peer.ipv4_address,
LDP_PORT);
}
if(session->tcpc) {
session->tcpc->arg = session;
@@ -357,10 +365,18 @@ ldp_session_connect_job(timer_s *timer)
static void
ldp_session_listen(ldp_session_s *session)
{
session->listen_tcpc = bbl_tcp_ipv4_listen(
session->interface,
&session->local.ipv4_address,
LDP_PORT);
if(session->ipv6) {
session->listen_tcpc = bbl_tcp_ipv6_listen(
session->interface,
&session->local.ipv6_address,
LDP_PORT);
} else {
session->listen_tcpc = bbl_tcp_ipv4_listen(
session->interface,
&session->local.ipv4_address,
LDP_PORT);
}
if(session->listen_tcpc) {
session->listen_tcpc->arg = session;
@@ -437,7 +453,7 @@ ldp_session_connect(ldp_session_s *session, time_t delay)
}
/**
* ldp_session_init
* ldp_session_ipv4_init
*
* @param session LDP session (optional)
* @param adjacency LDP adjacency
@@ -445,7 +461,7 @@ ldp_session_connect(ldp_session_s *session, time_t delay)
* @param ldp received LDP hello PDU
*/
void
ldp_session_init(ldp_session_s *session, ldp_adjacency_s *adjacency,
ldp_session_ipv4_init(ldp_session_s *session, ldp_adjacency_s *adjacency,
bbl_ipv4_s *ipv4, bbl_ldp_hello_s *ldp)
{
ldp_instance_s *instance = adjacency->instance;
@@ -494,6 +510,67 @@ ldp_session_init(ldp_session_s *session, ldp_adjacency_s *adjacency,
ldp_session_connect(session, 0);
}
/**
* ldp_session_ipv4_init
*
* @param session LDP session (optional)
* @param adjacency LDP adjacency
* @param ipv6 received IPv6 header
* @param ldp received LDP hello PDU
*/
void
ldp_session_ipv6_init(ldp_session_s *session, ldp_adjacency_s *adjacency,
bbl_ipv6_s *ipv6, bbl_ldp_hello_s *ldp)
{
ldp_instance_s *instance = adjacency->instance;
ldp_config_s *config = instance->config;
if(!session) {
session = calloc(1, sizeof(ldp_session_s));
session->instance = instance;
session->ipv6 = true;
memcpy(&session->local.ipv6_address, &config->ipv6_transport_address, sizeof(ipv6addr_t));
session->local.lsr_id = config->lsr_id;
session->local.label_space_id = 0;
session->local.keepalive_time = config->keepalive_time;
session->local.max_pdu_len = LDP_MAX_PDU_LEN_INIT;
if(config->raw_update_file) {
session->raw_update_start = ldp_raw_update_load(config->raw_update_file, true);
}
session->next = instance->sessions;
instance->sessions = session;
}
session->interface = adjacency->interface;
session->max_pdu_len = session->local.max_pdu_len;
session->keepalive_time = session->local.keepalive_time;
if(ldp->ipv6_transport_address) {
memcpy(&session->peer.ipv6_address, ldp->ipv6_transport_address, sizeof(ipv6addr_t));
} else {
memcpy(&session->peer.ipv6_address, ipv6->src, sizeof(ipv6addr_t));
}
session->peer.lsr_id = ldp->lsr_id;
session->peer.label_space_id = ldp->label_space_id;
session->peer.keepalive_time = 0;
session->peer.max_pdu_len = 0;
/* Init read/write buffer */
session->read_buf.data = malloc(LDP_BUF_SIZE);
session->read_buf.size = LDP_BUF_SIZE;
session->write_buf.data = malloc(LDP_BUF_SIZE);
session->write_buf.size = LDP_BUF_SIZE;
if(memcmp(&session->local.ipv6_address, &session->peer.ipv6_address, sizeof(ipv6addr_t)) > 0) {
session->active = true;
} else {
session->active = false;
}
ldp_session_connect(session, 0);
}
void
ldp_session_close_job(timer_s *timer)
{
+6 -2
View File
@@ -25,8 +25,12 @@ void
ldp_session_connect(ldp_session_s *session, time_t delay);
void
ldp_session_init(ldp_session_s *session, ldp_adjacency_s *adjacency,
bbl_ipv4_s *ipv4, bbl_ldp_hello_s *ldp);
ldp_session_ipv4_init(ldp_session_s *session, ldp_adjacency_s *adjacency,
bbl_ipv4_s *ipv4, bbl_ldp_hello_s *ldp);
void
ldp_session_ipv6_init(ldp_session_s *session, ldp_adjacency_s *adjacency,
bbl_ipv6_s *ipv6, bbl_ldp_hello_s *ldp);
void
ldp_session_close(ldp_session_s *session);
+6 -3
View File
@@ -54,9 +54,12 @@ extern unsigned char debug_flags;
#define LWIP_IPV4 1
#define LWIP_IPV6 1
#define LWIP_IPV6_REASS 0
#define LWIP_IPV6_FRAG 1
#define LWIP_IPV6_REASS 1
#define LWIP_IPV6_AUTOCONFIG 0
#define IPV6_FRAG_COPYHEADER 1
/* ---------- Memory options ---------- */
/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which
lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2
@@ -168,8 +171,8 @@ a lot of data that needs to be copied, this should be set high. */
/* IP reassembly and segmentation.These are orthogonal even
* if they both deal with IP fragments */
#define IP_REASSEMBLY 0
#define IP_FRAG 0
#define IP_REASSEMBLY 1
#define IP_FRAG 1
/* ---------- ICMP options ---------- */
#define ICMP_TTL 255
+1 -1
View File
@@ -202,7 +202,7 @@ PACK_STRUCT_END
#define IP6_ROUT_SEG_LEFT(hdr) ((hdr)->_segments_left)
/* Fragment header. */
#define IP6_FRAG_HLEN 8
#define IP6_FRAG_HLEN 8
#define IP6_FRAG_OFFSET_MASK 0xfff8
#define IP6_FRAG_MORE_FLAG 0x0001