From 4e0550441cb67d5230a59915bdeced6345bb6adf Mon Sep 17 00:00:00 2001 From: Christian Giese Date: Thu, 20 Apr 2023 12:31:47 +0000 Subject: [PATCH] add support for IPv6 TCP and LDP (initial draft) --- code/bngblaster/src/bbl_config.c | 23 ++- code/bngblaster/src/bbl_def.h | 3 +- code/bngblaster/src/bbl_network.c | 18 ++- code/bngblaster/src/bbl_protocols.c | 72 +++++++-- code/bngblaster/src/bbl_protocols.h | 12 +- code/bngblaster/src/bbl_tcp.c | 203 +++++++++++++++++------- code/bngblaster/src/bbl_tcp.h | 15 +- code/bngblaster/src/bbl_tx.c | 9 +- code/bngblaster/src/ldp/ldp_ctrl.c | 14 +- code/bngblaster/src/ldp/ldp_def.h | 17 +- code/bngblaster/src/ldp/ldp_hello.c | 165 +++++++++++++++++-- code/bngblaster/src/ldp/ldp_hello.h | 19 ++- code/bngblaster/src/ldp/ldp_interface.c | 10 +- code/bngblaster/src/ldp/ldp_session.c | 99 ++++++++++-- code/bngblaster/src/ldp/ldp_session.h | 8 +- code/bngblaster/src/lwip/lwipopts.h | 9 +- code/lwip/src/include/lwip/prot/ip6.h | 2 +- 17 files changed, 574 insertions(+), 124 deletions(-) diff --git a/code/bngblaster/src/bbl_config.c b/code/bngblaster/src/bbl_config.c index 79dbccab..41e636a2 100644 --- a/code/bngblaster/src/bbl_config.c +++ b/code/bngblaster/src/bbl_config.c @@ -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)) { diff --git a/code/bngblaster/src/bbl_def.h b/code/bngblaster/src/bbl_def.h index 921566c5..e7a85efe 100644 --- a/code/bngblaster/src/bbl_def.h +++ b/code/bngblaster/src/bbl_def.h @@ -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 diff --git a/code/bngblaster/src/bbl_network.c b/code/bngblaster/src/bbl_network.c index 948596e5..185526f2 100644 --- a/code/bngblaster/src/bbl_network.c +++ b/code/bngblaster/src/bbl_network.c @@ -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: diff --git a/code/bngblaster/src/bbl_protocols.c b/code/bngblaster/src/bbl_protocols.c index d38a9be0..f1100130 100644 --- a/code/bngblaster/src/bbl_protocols.c +++ b/code/bngblaster/src/bbl_protocols.c @@ -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; } diff --git a/code/bngblaster/src/bbl_protocols.h b/code/bngblaster/src/bbl_protocols.h index 2301878f..cf599f1a 100644 --- a/code/bngblaster/src/bbl_protocols.h +++ b/code/bngblaster/src/bbl_protocols.h @@ -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_ { diff --git a/code/bngblaster/src/bbl_tcp.c b/code/bngblaster/src/bbl_tcp.c index 3387fd7a..1c5d4181 100644 --- a/code/bngblaster/src/bbl_tcp.c +++ b/code/bngblaster/src/bbl_tcp.c @@ -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); } \ No newline at end of file diff --git a/code/bngblaster/src/bbl_tcp.h b/code/bngblaster/src/bbl_tcp.h index b44f0b02..14bbeaa9 100644 --- a/code/bngblaster/src/bbl_tcp.h +++ b/code/bngblaster/src/bbl_tcp.h @@ -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); diff --git a/code/bngblaster/src/bbl_tx.c b/code/bngblaster/src/bbl_tx.c index 3adade5b..88d95b2d 100644 --- a/code/bngblaster/src/bbl_tx.c +++ b/code/bngblaster/src/bbl_tx.c @@ -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, ð); - } 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, ð); + } 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, ð); + } 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, ð); } else { interface->send_requests = 0; } diff --git a/code/bngblaster/src/ldp/ldp_ctrl.c b/code/bngblaster/src/ldp/ldp_ctrl.c index 41ae84d9..4cec2d3f 100644 --- a/code/bngblaster/src/ldp/ldp_ctrl.c +++ b/code/bngblaster/src/ldp/ldp_ctrl.c @@ -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, diff --git a/code/bngblaster/src/ldp/ldp_def.h b/code/bngblaster/src/ldp/ldp_def.h index 6ecd1c4b..6d898700 100644 --- a/code/bngblaster/src/ldp/ldp_def.h +++ b/code/bngblaster/src/ldp/ldp_def.h @@ -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; diff --git a/code/bngblaster/src/ldp/ldp_hello.c b/code/bngblaster/src/ldp/ldp_hello.c index edce6a65..21bc53cd 100644 --- a/code/bngblaster/src/ldp/ldp_hello.c +++ b/code/bngblaster/src/ldp/ldp_hello.c @@ -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; } \ No newline at end of file diff --git a/code/bngblaster/src/ldp/ldp_hello.h b/code/bngblaster/src/ldp/ldp_hello.h index ec2d341e..fe3cc807 100644 --- a/code/bngblaster/src/ldp/ldp_hello.h +++ b/code/bngblaster/src/ldp/ldp_hello.h @@ -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 \ No newline at end of file diff --git a/code/bngblaster/src/ldp/ldp_interface.c b/code/bngblaster/src/ldp/ldp_interface.c index 7bdf181c..f983e8b5 100644 --- a/code/bngblaster/src/ldp/ldp_interface.c +++ b/code/bngblaster/src/ldp/ldp_interface.c @@ -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; } \ No newline at end of file diff --git a/code/bngblaster/src/ldp/ldp_session.c b/code/bngblaster/src/ldp/ldp_session.c index f771eaf5..45d35be4 100644 --- a/code/bngblaster/src/ldp/ldp_session.c +++ b/code/bngblaster/src/ldp/ldp_session.c @@ -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) { diff --git a/code/bngblaster/src/ldp/ldp_session.h b/code/bngblaster/src/ldp/ldp_session.h index 2daa852e..eb9dcafc 100644 --- a/code/bngblaster/src/ldp/ldp_session.h +++ b/code/bngblaster/src/ldp/ldp_session.h @@ -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); diff --git a/code/bngblaster/src/lwip/lwipopts.h b/code/bngblaster/src/lwip/lwipopts.h index 8e564821..184c664a 100644 --- a/code/bngblaster/src/lwip/lwipopts.h +++ b/code/bngblaster/src/lwip/lwipopts.h @@ -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 diff --git a/code/lwip/src/include/lwip/prot/ip6.h b/code/lwip/src/include/lwip/prot/ip6.h index 437d5098..957fb3a3 100644 --- a/code/lwip/src/include/lwip/prot/ip6.h +++ b/code/lwip/src/include/lwip/prot/ip6.h @@ -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