diff --git a/docs/config.md b/docs/config.md index 1b75b8ed..26a317b1 100644 --- a/docs/config.md +++ b/docs/config.md @@ -694,6 +694,8 @@ Attribute | Description | Default `network-ipv6-address` | Overwrite network interface IPv6 address | `destination-ipv4-address` | Overwrite the IPv4 destination address | `destination-ipv6-address` | Overwrite the IPv6 destination address | +`access-ipv4-source-address` | Overwrite the access IPv4 source address (client) | +`access-ipv6-source-address` | Overwrite the access IPv6 source address (client) | `threaded` | Run those streams in separate threads | false `thread-group` | Assign this stream to thread group (1-255) | 0 (thread per stream) @@ -702,6 +704,10 @@ For L2TP downstream traffic the IPv4 TOS is applied to the outer IPv4 and inner The `pps` option supports also float numbers like 0.1, or 2.5 PPS and has priority over `bps` where second is only a helper to calculate the `pps` based on given `bps` and `length`. +The options `access-ipv4-source-address` and `access-ipv6-source-address` are used +to test the BNG RPF functionality with traffic send from source addresses different +to those assigned to the client. + ## Access-Line This section describes all attributes of the `access-line` hierarchy. diff --git a/src/bbl_config.c b/src/bbl_config.c index fe7e5e56..47db286b 100644 --- a/src/bbl_config.c +++ b/src/bbl_config.c @@ -748,6 +748,20 @@ json_parse_stream (bbl_ctx_s *ctx, json_t *stream, bbl_stream_config *stream_con } if (!stream_config->pps) stream_config->pps = 1; + if (json_unpack(stream, "{s:s}", "access-ipv4-source-address", &s) == 0) { + if (!inet_pton(AF_INET, s, &stream_config->ipv4_access_src_address)) { + fprintf(stderr, "JSON config error: Invalid value for stream->access-ipv4-source-address\n"); + return false; + } + } + + if (json_unpack(stream, "{s:s}", "access-ipv6-source-address", &s) == 0) { + if (!inet_pton(AF_INET6, s, &stream_config->ipv6_access_src_address)) { + fprintf(stderr, "JSON config error: Invalid value for stream->access-ipv6-source-address\n"); + return false; + } + } + if (json_unpack(stream, "{s:s}", "network-ipv4-address", &s) == 0) { if (!inet_pton(AF_INET, s, &stream_config->ipv4_network_address)) { fprintf(stderr, "JSON config error: Invalid value for stream->network-ipv4-address\n"); diff --git a/src/bbl_stream.c b/src/bbl_stream.c index cca72e90..134284a3 100644 --- a/src/bbl_stream.c +++ b/src/bbl_stream.c @@ -155,7 +155,11 @@ bbl_stream_build_access_pppoe_packet(bbl_stream *stream) { pppoe.protocol = PROTOCOL_IPV4; pppoe.next = &ipv4; /* Source address */ - ipv4.src = session->ip_address; + if(stream->config->ipv4_access_src_address) { + ipv4.src = stream->config->ipv4_access_src_address; + } else { + ipv4.src = session->ip_address; + } /* Destination address */ if(stream->config->ipv4_destination_address) { ipv4.dst = stream->config->ipv4_destination_address; @@ -180,10 +184,14 @@ bbl_stream_build_access_pppoe_packet(bbl_stream *stream) { pppoe.protocol = PROTOCOL_IPV6; pppoe.next = &ipv6; /* Source address */ - if(stream->config->type == STREAM_IPV6) { - ipv6.src = session->ipv6_address; + if(*(uint64_t*)stream->config->ipv6_access_src_address) { + ipv6.src = stream->config->ipv6_access_src_address; } else { - ipv6.src = session->delegated_ipv6_address; + if(stream->config->type == STREAM_IPV6) { + ipv6.src = session->ipv6_address; + } else { + ipv6.src = session->delegated_ipv6_address; + } } /* Destination address */ if(*(uint64_t*)stream->config->ipv6_destination_address) { @@ -195,7 +203,6 @@ bbl_stream_build_access_pppoe_packet(bbl_stream *stream) { ipv6.dst = network_if->ip6.address; } } - ipv6.src = session->ipv6_address; ipv6.ttl = 64; ipv6.tos = config->priority; ipv6.protocol = IPV6_NEXT_HEADER_UDP; @@ -403,7 +410,11 @@ bbl_stream_build_access_ipoe_packet(bbl_stream *stream) { eth.type = ETH_TYPE_IPV4; eth.next = &ipv4; /* Source address */ - ipv4.src = session->ip_address; + if(stream->config->ipv4_access_src_address) { + ipv4.src = stream->config->ipv4_access_src_address; + } else { + ipv4.src = session->ip_address; + } /* Destination address */ if(stream->config->ipv4_destination_address) { ipv4.dst = stream->config->ipv4_destination_address; @@ -428,10 +439,14 @@ bbl_stream_build_access_ipoe_packet(bbl_stream *stream) { eth.type = ETH_TYPE_IPV6; eth.next = &ipv6; /* Source address */ - if(stream->config->type == STREAM_IPV6) { - ipv6.src = session->ipv6_address; + if(*(uint64_t*)stream->config->ipv6_access_src_address) { + ipv6.src = stream->config->ipv6_access_src_address; } else { - ipv6.src = session->delegated_ipv6_address; + if(stream->config->type == STREAM_IPV6) { + ipv6.src = session->ipv6_address; + } else { + ipv6.src = session->delegated_ipv6_address; + } } /* Destination address */ if(*(uint64_t*)stream->config->ipv6_destination_address) { @@ -443,7 +458,6 @@ bbl_stream_build_access_ipoe_packet(bbl_stream *stream) { ipv6.dst = network_if->ip6.address; } } - ipv6.src = session->ipv6_address; ipv6.ttl = 64; ipv6.tos = config->priority; ipv6.protocol = IPV6_NEXT_HEADER_UDP; diff --git a/src/bbl_stream.h b/src/bbl_stream.h index 7577a4ef..f4592db4 100644 --- a/src/bbl_stream.h +++ b/src/bbl_stream.h @@ -34,6 +34,8 @@ typedef struct bbl_stream_config_ uint8_t priority; /* IPv4 TOS or IPv6 TC */ uint8_t vlan_priority; + uint32_t ipv4_access_src_address; /* overwrite default IPv4 access address */ + ipv6addr_t ipv6_access_src_address; /* overwrite default IPv6 access address */ uint32_t ipv4_network_address; /* overwrite default IPv4 network address */ ipv6addr_t ipv6_network_address; /* overwrite default IPv6 network address */ uint32_t ipv4_destination_address; /* overwrite IPv4 destination address */