mirror of
https://github.com/rtbrick/bngblaster.git
synced 2024-05-06 15:54:57 +00:00
add support for IPv6 TCP and LDP (initial draft)
This commit is contained in:
@@ -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)) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user