mirror of
https://github.com/rtbrick/bngblaster.git
synced 2024-05-06 15:54:57 +00:00
DHCP Enhancements and Fixes
This commit is contained in:
+5
-3
@@ -455,9 +455,11 @@ This section describes all attributes of the `dhcp` hierarchy.
|
||||
|
||||
Attribute | Description | Default
|
||||
--------- | ----------- | -------
|
||||
`enable` | This option allows to enable or disable DHCP | true
|
||||
|
||||
**WARNING**: DHCP (IPv4) is currently not supported!
|
||||
`enable` | This option allows to enable or disable DHCP | false
|
||||
`broadcast` | DHCP broadcast flag | false
|
||||
`timeout` | DHCP timeout in seconds | 5
|
||||
`tos` | IPv4 TOS for all DHCP control traffic | 0
|
||||
`vlan-priority` | VLAN PBIT for all DHCP control traffic | 0
|
||||
|
||||
## DHCPv6
|
||||
|
||||
|
||||
@@ -520,7 +520,7 @@ bbl_ctrl_job (timer_s *timer)
|
||||
/* Start IPoE session by sending DHCP discovery if enabled. */
|
||||
session->dhcp_state = BBL_DHCP_SELECTING;
|
||||
session->dhcp_xid = rand();
|
||||
session->send_requests |= BBL_SEND_DHCPREQUEST;
|
||||
session->send_requests |= BBL_SEND_DHCP_REQUEST;
|
||||
} else if (session->ip_address && session->peer_ip_address) {
|
||||
/* Start IPoE session by sending ARP request if local and
|
||||
* remote IP addresses are already provided. */
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
#define BBL_SEND_SESSION_IPV6PD 0x00008000
|
||||
#define BBL_SEND_ARP_REQUEST 0x00010000
|
||||
#define BBL_SEND_ARP_REPLY 0x00020000
|
||||
#define BBL_SEND_DHCPREQUEST 0x00040000
|
||||
#define BBL_SEND_DHCP_REQUEST 0x00040000
|
||||
#define BBL_SEND_ICMPV6_REPLY 0x00080000
|
||||
#define BBL_SEND_ICMPV6_NS 0x00100000
|
||||
#define BBL_SEND_ICMPV6_NA 0x00200000
|
||||
@@ -585,7 +585,7 @@ typedef struct bbl_ctx_
|
||||
/* DHCP */
|
||||
bool dhcp_enable;
|
||||
uint16_t dhcp_timeout;
|
||||
uint16_t dhcp_retry;
|
||||
uint8_t dhcp_tos;
|
||||
uint8_t dhcp_vlan_priority;
|
||||
bool dhcp_broadcast;
|
||||
|
||||
@@ -670,7 +670,7 @@ typedef enum {
|
||||
BBL_DHCP_REQUESTING = 2,
|
||||
BBL_DHCP_BOUND = 3,
|
||||
BBL_DHCP_RENEWING = 4,
|
||||
BBL_DHCP_DHCPRELEASE = 5,
|
||||
BBL_DHCP_RELEASE = 5,
|
||||
BBL_DHCP_MAX
|
||||
} __attribute__ ((__packed__)) dhcp_state_t;
|
||||
|
||||
@@ -833,8 +833,10 @@ typedef struct bbl_session_
|
||||
uint32_t dhcp_address;
|
||||
uint32_t dhcp_lease_time;
|
||||
uint32_t dhcp_t1;
|
||||
uint32_t dhcp_t2;
|
||||
uint32_t dhcp_t2;
|
||||
uint32_t dhcp_server;
|
||||
uint32_t dhcp_server_identifier;
|
||||
uint8_t dhcp_server_mac[ETH_ADDR_LEN];
|
||||
struct timespec dhcp_lease_timestamp;
|
||||
struct timespec dhcp_request_timestamp;
|
||||
char *dhcp_client_identifier;
|
||||
@@ -967,6 +969,12 @@ typedef struct bbl_session_
|
||||
|
||||
uint32_t dhcp_tx;
|
||||
uint32_t dhcp_rx;
|
||||
uint32_t dhcp_tx_discover;
|
||||
uint32_t dhcp_rx_offer;
|
||||
uint32_t dhcp_tx_request;
|
||||
uint32_t dhcp_rx_ack;
|
||||
uint32_t dhcp_rx_nak;
|
||||
uint32_t dhcp_tx_release;
|
||||
|
||||
uint64_t access_ipv4_rx;
|
||||
uint64_t access_ipv4_tx;
|
||||
|
||||
+2
-3
@@ -689,9 +689,9 @@ json_parse_config (json_t *root, bbl_ctx_s *ctx) {
|
||||
if (json_is_number(value)) {
|
||||
ctx->config.dhcp_timeout = json_number_value(value);
|
||||
}
|
||||
value = json_object_get(section, "retry");
|
||||
value = json_object_get(section, "tos");
|
||||
if (json_is_number(value)) {
|
||||
ctx->config.dhcp_retry = json_number_value(value);
|
||||
ctx->config.dhcp_tos = json_number_value(value);
|
||||
}
|
||||
value = json_object_get(section, "vlan-priority");
|
||||
if (json_is_number(value)) {
|
||||
@@ -1130,7 +1130,6 @@ bbl_config_init_defaults (bbl_ctx_s *ctx) {
|
||||
ctx->config.ip6cp_conf_request_retry = 10;
|
||||
ctx->config.dhcp_enable = false;
|
||||
ctx->config.dhcp_timeout = 5;
|
||||
ctx->config.dhcp_retry = 10;
|
||||
ctx->config.dhcpv6_enable = true;
|
||||
ctx->config.dhcpv6_rapid_commit = true;
|
||||
ctx->config.igmp_autostart = true;
|
||||
|
||||
+14
-8
@@ -73,7 +73,7 @@ dhcp_state_string(uint32_t state) {
|
||||
case BBL_DHCP_REQUESTING: return "Requesting";
|
||||
case BBL_DHCP_BOUND: return "Bound";
|
||||
case BBL_DHCP_RENEWING: return "Renewing";
|
||||
case BBL_DHCP_DHCPRELEASE: return "Releasing";
|
||||
case BBL_DHCP_RELEASE: return "Releasing";
|
||||
default: return "N/A";
|
||||
}
|
||||
}
|
||||
@@ -555,7 +555,7 @@ bbl_ctrl_session_info(int fd, bbl_ctx_s *ctx, uint32_t session_id, json_t* argum
|
||||
if(seconds <= session->dhcp_lease_time) lease_expire = session->dhcp_lease_time - seconds;
|
||||
if(seconds <= session->dhcp_t1) lease_expire_t1 = session->dhcp_t1 - seconds;
|
||||
if(seconds <= session->dhcp_t2) lease_expire_t2 = session->dhcp_t2 - seconds;
|
||||
root = json_pack("{ss si s{ss si ss ss si si ss ss* ss* ss* ss* si si si si ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* si si si so*}}",
|
||||
root = json_pack("{ss si s{ss si ss ss si si ss ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* ss* si si si si si si si si si si ss* ss* si si si so*}}",
|
||||
"status", "ok",
|
||||
"code", 200,
|
||||
"session-information",
|
||||
@@ -568,12 +568,6 @@ bbl_ctrl_session_info(int fd, bbl_ctx_s *ctx, uint32_t session_id, json_t* argum
|
||||
"mac", format_mac_address(session->client_mac),
|
||||
"agent-circuit-id", session->agent_circuit_id,
|
||||
"agent-remote-id", session->agent_remote_id,
|
||||
"dhcp-state", dhcp_state_string(session->dhcp_state),
|
||||
"dhcp-server", format_ipv4_address(&session->dhcp_server_identifier),
|
||||
"dhcp-lease-time", session->dhcp_lease_time,
|
||||
"dhcp-lease-expire", lease_expire,
|
||||
"dhcp-lease-expire-t1", lease_expire_t1,
|
||||
"dhcp-lease-expire-t2", lease_expire_t2,
|
||||
"ipv4-address", ipv4,
|
||||
"ipv4-netmask", ipv4_netmask,
|
||||
"ipv4-gateway", ipv4_gw,
|
||||
@@ -583,6 +577,18 @@ bbl_ctrl_session_info(int fd, bbl_ctx_s *ctx, uint32_t session_id, json_t* argum
|
||||
"ipv6-delegated-prefix", ipv6pd,
|
||||
"ipv6-dns1", ipv6_dns1,
|
||||
"ipv6-dns2", ipv6_dns2,
|
||||
"dhcp-state", dhcp_state_string(session->dhcp_state),
|
||||
"dhcp-server", format_ipv4_address(&session->dhcp_server_identifier),
|
||||
"dhcp-lease-time", session->dhcp_lease_time,
|
||||
"dhcp-lease-expire", lease_expire,
|
||||
"dhcp-lease-expire-t1", lease_expire_t1,
|
||||
"dhcp-lease-expire-t2", lease_expire_t2,
|
||||
"dhcp-tx-discover", session->stats.dhcp_tx_discover,
|
||||
"dhcp-tx-request", session->stats.dhcp_tx_request,
|
||||
"dhcp-tx-release", session->stats.dhcp_tx_release,
|
||||
"dhcp-rx-offer", session->stats.dhcp_rx_offer,
|
||||
"dhcp-rx-ack", session->stats.dhcp_rx_ack,
|
||||
"dhcp-rx-nak", session->stats.dhcp_rx_nak,
|
||||
"dhcpv6-dns1", dhcpv6_dns1,
|
||||
"dhcpv6-dns2", dhcpv6_dns2,
|
||||
"tx-packets", session->stats.packets_tx,
|
||||
|
||||
+29
-5
@@ -38,7 +38,9 @@ bbl_dhcp_restart(bbl_session_s *session) {
|
||||
session->dhcp_lease_time = 0;
|
||||
session->dhcp_t1 = 0;
|
||||
session->dhcp_t2 = 0;
|
||||
session->dhcp_server = 0;
|
||||
session->dhcp_server_identifier = 0;
|
||||
memset(&session->dhcp_server_mac, 0xff, ETH_ADDR_LEN); // init with broadcast MAC
|
||||
session->dhcp_lease_timestamp.tv_sec = 0;
|
||||
session->dhcp_lease_timestamp.tv_nsec = 0;
|
||||
session->dhcp_request_timestamp.tv_sec = 0;
|
||||
@@ -51,7 +53,7 @@ bbl_dhcp_restart(bbl_session_s *session) {
|
||||
free(session->dhcp_domain_name);
|
||||
session->dhcp_domain_name = NULL;
|
||||
}
|
||||
session->send_requests |= BBL_SEND_DHCPREQUEST;
|
||||
session->send_requests |= BBL_SEND_DHCP_REQUEST;
|
||||
bbl_session_tx_qnode_insert(session);
|
||||
|
||||
/* Reset session IP configuration */
|
||||
@@ -82,7 +84,7 @@ bbl_dhcp_t1(timer_s *timer) {
|
||||
session->dhcp_request_timestamp.tv_sec = 0;
|
||||
session->dhcp_request_timestamp.tv_nsec = 0;
|
||||
session->dhcp_state = BBL_DHCP_RENEWING;
|
||||
session->send_requests = BBL_SEND_DHCPREQUEST;
|
||||
session->send_requests = BBL_SEND_DHCP_REQUEST;
|
||||
bbl_session_tx_qnode_insert(session);
|
||||
}
|
||||
}
|
||||
@@ -113,21 +115,41 @@ bbl_dhcp_rx(bbl_ethernet_header_t *eth, bbl_dhcp_t *dhcp, bbl_session_s *session
|
||||
return;
|
||||
}
|
||||
|
||||
switch(dhcp->type) {
|
||||
case DHCP_MESSAGE_OFFER:
|
||||
session->stats.dhcp_rx_offer++;
|
||||
LOG(DHCP, "DHCP (ID: %u) DHCP-Offer received\n", session->session_id);
|
||||
break;
|
||||
case DHCP_MESSAGE_ACK:
|
||||
session->stats.dhcp_rx_ack++;
|
||||
LOG(DHCP, "DHCP (ID: %u) DHCP-ACK received\n", session->session_id);
|
||||
break;
|
||||
case DHCP_MESSAGE_NAK:
|
||||
session->stats.dhcp_rx_nak++;
|
||||
LOG(DHCP, "DHCP (ID: %u) DHCP-NAK received\n", session->session_id);
|
||||
break;
|
||||
default:
|
||||
/* Not expected ... */
|
||||
return;
|
||||
}
|
||||
|
||||
switch(session->dhcp_state) {
|
||||
case BBL_DHCP_SELECTING:
|
||||
if(dhcp->type == DHCP_MESSAGE_OFFER) {
|
||||
session->dhcp_state = BBL_DHCP_REQUESTING;
|
||||
session->dhcp_address = dhcp->header->yiaddr;
|
||||
session->dhcp_server = dhcp->header->siaddr;
|
||||
session->dhcp_server_identifier = dhcp->server_identifier;
|
||||
memcpy(session->dhcp_server_mac, eth->src, ETH_ADDR_LEN);
|
||||
session->dhcp_lease_time = dhcp->lease_time;
|
||||
session->dhcp_lease_timestamp.tv_sec = eth->timestamp.tv_sec;
|
||||
session->dhcp_lease_timestamp.tv_nsec = eth->timestamp.tv_nsec;
|
||||
if(!(session->dhcp_address && session->dhcp_server_identifier && session->dhcp_lease_time)) {
|
||||
LOG(ERROR, "DHCP (ID: %u) Invalid DHCP-OFFER!\n", session->session_id);
|
||||
LOG(ERROR, "DHCP (ID: %u) Invalid DHCP-Offer!\n", session->session_id);
|
||||
return bbl_dhcp_restart(session);
|
||||
}
|
||||
timer_add(&ctx->timer_root, &session->timer_dhcp_t2, "DHCP T2", session->dhcp_lease_time, 0, session, &bbl_dhcp_t2);
|
||||
session->send_requests |= BBL_SEND_DHCPREQUEST;
|
||||
session->send_requests |= BBL_SEND_DHCP_REQUEST;
|
||||
bbl_session_tx_qnode_insert(session);
|
||||
}
|
||||
break;
|
||||
@@ -135,6 +157,7 @@ bbl_dhcp_rx(bbl_ethernet_header_t *eth, bbl_dhcp_t *dhcp, bbl_session_s *session
|
||||
if(dhcp->type == DHCP_MESSAGE_ACK) {
|
||||
session->dhcp_state = BBL_DHCP_BOUND;
|
||||
session->dhcp_address = dhcp->header->yiaddr;
|
||||
session->dhcp_server = dhcp->header->siaddr;
|
||||
session->dhcp_server_identifier = dhcp->server_identifier;
|
||||
session->dhcp_lease_time = dhcp->lease_time;
|
||||
session->dhcp_lease_timestamp.tv_sec = eth->timestamp.tv_sec;
|
||||
@@ -193,12 +216,13 @@ bbl_dhcp_rx(bbl_ethernet_header_t *eth, bbl_dhcp_t *dhcp, bbl_session_s *session
|
||||
if(dhcp->type == DHCP_MESSAGE_ACK) {
|
||||
session->dhcp_state = BBL_DHCP_BOUND;
|
||||
session->dhcp_address = dhcp->header->yiaddr;
|
||||
session->dhcp_server = dhcp->header->siaddr;
|
||||
session->dhcp_server_identifier = dhcp->server_identifier;
|
||||
session->dhcp_lease_time = dhcp->lease_time;
|
||||
session->dhcp_lease_timestamp.tv_sec = eth->timestamp.tv_sec;
|
||||
session->dhcp_lease_timestamp.tv_nsec = eth->timestamp.tv_nsec;
|
||||
if(!(session->dhcp_address && session->dhcp_server_identifier && session->dhcp_lease_time)) {
|
||||
LOG(ERROR, "DHCP (ID: %u) Restart because of invalid DHCP-ACK!\n", session->session_id);
|
||||
LOG(ERROR, "DHCP (ID: %u) Invalid DHCP-ACK!\n", session->session_id);
|
||||
return bbl_dhcp_restart(session);
|
||||
}
|
||||
session->dhcp_t1 = 0.5 * session->dhcp_lease_time; if(!session->dhcp_t1) session->dhcp_t1 = 1;
|
||||
|
||||
+12
-1
@@ -273,7 +273,17 @@ bbl_session_clear(bbl_ctx_s *ctx, bbl_session_s *session)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
bbl_session_update_state(ctx, session, BBL_TERMINATED);
|
||||
if(session->dhcp_state > BBL_DHCP_SELECTING) {
|
||||
bbl_session_update_state(ctx, session, BBL_TERMINATING);
|
||||
session->dhcp_state = BBL_DHCP_RELEASE;
|
||||
session->dhcp_xid = rand();
|
||||
session->dhcp_request_timestamp.tv_sec = 0;
|
||||
session->dhcp_request_timestamp.tv_nsec = 0;
|
||||
session->send_requests |= BBL_SEND_DHCP_REQUEST;
|
||||
bbl_session_tx_qnode_insert(session);
|
||||
} else {
|
||||
bbl_session_update_state(ctx, session, BBL_TERMINATED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,6 +370,7 @@ bbl_sessions_init(bbl_ctx_s *ctx)
|
||||
return false;
|
||||
}
|
||||
memset(&session->server_mac, 0xff, ETH_ADDR_LEN); // init with broadcast MAC
|
||||
memset(&session->dhcp_server_mac, 0xff, ETH_ADDR_LEN); // init with broadcast MAC
|
||||
session->session_id = i; // BNG Blaster internal session identifier
|
||||
session->access_type = access_config->access_type;
|
||||
session->vlan_key.ifindex = access_config->access_if->ifindex;
|
||||
|
||||
+28
-11
@@ -1201,7 +1201,7 @@ bbl_dhcp_timeout (timer_s *timer)
|
||||
return;
|
||||
}
|
||||
|
||||
session->send_requests = BBL_SEND_DHCPREQUEST;
|
||||
session->send_requests = BBL_SEND_DHCP_REQUEST;
|
||||
bbl_session_tx_qnode_insert(session);
|
||||
}
|
||||
|
||||
@@ -1228,19 +1228,20 @@ bbl_encode_packet_dhcp (bbl_session_s *session) {
|
||||
|
||||
dhcp.header = &header;
|
||||
|
||||
eth.dst = session->dhcp_server_mac;
|
||||
eth.src = session->client_mac;
|
||||
eth.dst = (uint8_t*)broadcast_mac;
|
||||
eth.vlan_outer = session->vlan_key.outer_vlan_id;
|
||||
eth.vlan_inner = session->vlan_key.inner_vlan_id;
|
||||
eth.vlan_three = session->access_third_vlan;
|
||||
eth.vlan_outer_priority = ctx->config.pppoe_vlan_priority;
|
||||
eth.vlan_outer_priority = ctx->config.dhcp_vlan_priority;
|
||||
eth.vlan_inner_priority = eth.vlan_outer_priority;
|
||||
|
||||
eth.type = ETH_TYPE_IPV4;
|
||||
eth.next = &ipv4;
|
||||
ipv4.src = session->ip_address;
|
||||
ipv4.dst = IPV4_BROADCAST;
|
||||
ipv4.dst = session->dhcp_server;
|
||||
ipv4.ttl = 255;
|
||||
ipv4.tos = ctx->config.dhcp_tos;
|
||||
ipv4.protocol = PROTOCOL_IPV4_UDP;
|
||||
ipv4.next = &udp;
|
||||
udp.src = DHCP_UDP_CLIENT;
|
||||
@@ -1253,8 +1254,10 @@ bbl_encode_packet_dhcp (bbl_session_s *session) {
|
||||
header.htype = 1; /* fixed set to ethernet */
|
||||
header.hlen = 6;
|
||||
header.xid = session->dhcp_xid;
|
||||
if(ctx->config.dhcp_broadcast) {
|
||||
if(ctx->config.dhcp_broadcast && session->dhcp_state != BBL_DHCP_RELEASE) {
|
||||
header.flags = htobe16(1 << 15);
|
||||
eth.dst = (uint8_t*)broadcast_mac;
|
||||
ipv4.dst = IPV4_BROADCAST;
|
||||
}
|
||||
header.ciaddr = session->ip_address;
|
||||
memcpy(header.chaddr, session->client_mac, ETH_ADDR_LEN);
|
||||
@@ -1270,7 +1273,7 @@ bbl_encode_packet_dhcp (bbl_session_s *session) {
|
||||
}
|
||||
|
||||
/* Option 82 ... */
|
||||
if(session->agent_circuit_id || session->agent_remote_id) {
|
||||
if((session->agent_circuit_id || session->agent_remote_id) && session->dhcp_state != BBL_DHCP_RELEASE) {
|
||||
access_line.aci = session->agent_circuit_id;
|
||||
access_line.ari = session->agent_remote_id;
|
||||
dhcp.access_line = &access_line;
|
||||
@@ -1279,6 +1282,10 @@ bbl_encode_packet_dhcp (bbl_session_s *session) {
|
||||
switch(session->dhcp_state) {
|
||||
case BBL_DHCP_SELECTING:
|
||||
dhcp.type = DHCP_MESSAGE_DISCOVER;
|
||||
session->stats.dhcp_tx_discover++;
|
||||
LOG(DHCP, "DHCP (ID: %u) DHCP-Discover send\n", session->session_id);
|
||||
eth.dst = (uint8_t*)broadcast_mac;
|
||||
ipv4.dst = IPV4_BROADCAST;
|
||||
dhcp.parameter_request_list = true;
|
||||
dhcp.option_netmask = true;
|
||||
dhcp.option_dns1 = true;
|
||||
@@ -1293,6 +1300,8 @@ bbl_encode_packet_dhcp (bbl_session_s *session) {
|
||||
break;
|
||||
case BBL_DHCP_REQUESTING:
|
||||
dhcp.type = DHCP_MESSAGE_REQUEST;
|
||||
session->stats.dhcp_tx_request++;
|
||||
LOG(DHCP, "DHCP (ID: %u) DHCP-Request send\n", session->session_id);
|
||||
dhcp.option_address = true;
|
||||
dhcp.address = session->dhcp_address;
|
||||
dhcp.option_server_identifier = true;
|
||||
@@ -1307,16 +1316,24 @@ bbl_encode_packet_dhcp (bbl_session_s *session) {
|
||||
break;
|
||||
case BBL_DHCP_RENEWING:
|
||||
dhcp.type = DHCP_MESSAGE_REQUEST;
|
||||
session->stats.dhcp_tx_request++;
|
||||
LOG(DHCP, "DHCP (ID: %u) DHCP-Request send\n", session->session_id);
|
||||
break;
|
||||
case BBL_DHCP_DHCPRELEASE:
|
||||
case BBL_DHCP_RELEASE:
|
||||
dhcp.type = DHCP_MESSAGE_RELEASE;
|
||||
header.flags = 0;
|
||||
session->stats.dhcp_tx_release++;
|
||||
LOG(DHCP, "DHCP (ID: %u) DHCP-Release send\n", session->session_id);
|
||||
dhcp.option_server_identifier = true;
|
||||
dhcp.server_identifier = session->dhcp_server_identifier;
|
||||
if(session->session_state == BBL_TERMINATING) {
|
||||
bbl_session_update_state(ctx, session, BBL_TERMINATED);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return IGNORED;
|
||||
}
|
||||
|
||||
timer_add(&ctx->timer_root, &session->timer_dhcp_retry, "DHCP timeout", 5, 0, session, &bbl_dhcp_timeout);
|
||||
timer_add(&ctx->timer_root, &session->timer_dhcp_retry, "DHCP timeout", ctx->config.dhcp_timeout, 0, session, &bbl_dhcp_timeout);
|
||||
interface->stats.dhcp_tx++;
|
||||
|
||||
return encode_ethernet(session->write_buf, &session->write_idx, ð);
|
||||
@@ -1456,9 +1473,9 @@ bbl_encode_packet (bbl_session_s *session, uint8_t *buf, uint16_t *len, bool *ac
|
||||
} else if (session->send_requests & BBL_SEND_ARP_REPLY) {
|
||||
result = bbl_encode_packet_arp_reply(session);
|
||||
session->send_requests &= ~BBL_SEND_ARP_REPLY;
|
||||
} else if (session->send_requests & BBL_SEND_DHCPREQUEST) {
|
||||
} else if (session->send_requests & BBL_SEND_DHCP_REQUEST) {
|
||||
result = bbl_encode_packet_dhcp(session);
|
||||
session->send_requests &= ~BBL_SEND_DHCPREQUEST;
|
||||
session->send_requests &= ~BBL_SEND_DHCP_REQUEST;
|
||||
} else {
|
||||
session->send_requests = 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user