Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
36ff9bb
F-11434: consume SYN-ACK after handshake completion in tcp_input
danielinux Sep 16, 2026
4d0c3cf
F-13765: gate tcp_ack dup-ACK arm on forward progress
danielinux Sep 16, 2026
ff18e66
F-13767: remove dead tcpsocket field last_ack
danielinux Sep 16, 2026
a3e502f
F-13206: bound DHCP lease timer deadlines to the heap horizon
danielinux Sep 16, 2026
60fe112
F-13764: collect the DHCP server ID like the other offer fields
danielinux Sep 16, 2026
151c6f5
DHCP: wait 10 s after DECLINE before re-DISCOVER (F-13776)
danielinux Sep 16, 2026
2481b00
F-11436: restore GCM SA state only on successful construction
danielinux Sep 16, 2026
3bd8d7a
F-11435: raise CB_EVENT_WRITABLE when the ICMP txbuf drains
danielinux Sep 16, 2026
f871593
F-12391: clear stale local_ip on ICMP bind to ANY
danielinux Sep 16, 2026
2daf3f1
F-13189: send ICMP Parameter Problem for malformed forwarded IP options
danielinux Sep 16, 2026
285d6f2
F-13190: document the RFC 1256 router discovery deviation
danielinux Sep 16, 2026
46a18a2
F-12390: plain teardown for aborted accept clones
danielinux Sep 16, 2026
9c6ff95
F-13167: getpeername for connected UDP sockets
danielinux Sep 16, 2026
1bfb480
F-13207: validate caller IHL in the IP_HDRINCL sendto path
danielinux Sep 16, 2026
0af8f24
F-13766: extend the VLAN delete EBUSY scan to the ICMP and AF_PACKET …
danielinux Sep 16, 2026
81a04d2
F-12389: print real version and header length in the IP debug dump
danielinux Sep 16, 2026
0164138
F-12393: fix the UDP debug dump for empty payloads
danielinux Sep 16, 2026
6fde1df
F-12394: correct the PMKSA fast reconnect contract
danielinux Sep 16, 2026
8ecce38
F-13189: validate IP option length before source-route drop
danielinux Sep 16, 2026
90bae3b
Fix NULL ll->send deref in Parameter Problem ESP path
danielinux Sep 16, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 27 additions & 9 deletions docs/advanced_ipv4_howto.md
Original file line number Diff line number Diff line change
Expand Up @@ -255,13 +255,12 @@ wolfIP is an endpoint stack first; the forwarding path deliberately omits IPv4
fragmentation and reassembly. These are documented, intended deviations, not
bugs:

- **No egress fragmentation.** A forwarded datagram is handed to the egress
interface at its declared IP total length, with no comparison against the
egress IP MTU and no fragment generation. If the frame exceeds the link MTU,
`wolfIP_ll_send_frame()` rejects it and the datagram is **dropped silently** —
no ICMP Destination Unreachable (Fragmentation Needed, type 3 code 4) is
sent, regardless of the DF bit. Datagrams that fit the egress MTU are
forwarded normally.
- **No egress fragmentation.** A forwarded datagram is never split into
fragments. A DF-set datagram larger than the egress IP MTU is dropped with
an ICMP Destination Unreachable (Fragmentation Needed, type 3 code 4)
carrying the egress next-hop MTU (RFC 1812 4.3.2.4); a DF-clear datagram
that does not fit is **dropped silently** on transmit. Datagrams that fit
the egress MTU are forwarded normally.
- **No reassembly.** The IP input path drops every fragment (MF set or non-zero
fragment offset); the stack never reassembles fragmented datagrams.
- **Locally generated UDP.** `wolfIP_sock_sendto()` fails with `-1` when the
Expand All @@ -274,8 +273,27 @@ The practical consequence for a router build: keep every link's MTU at or
above the largest datagram that traverses it (the usual 1500-byte Ethernet
baseline). A higher-MTU upstream (e.g. jumbo frames) that injects datagrams
larger than a downstream link's IP MTU will see them dropped at the egress
with no diagnostic ICMP. If your topology cannot guarantee that, IPv4
fragmentation is out of scope for wolfIP and a different stack is needed.
(no Fragmentation Needed reply when the DF bit is clear). If your topology
cannot guarantee that, IPv4 fragmentation is out of scope for wolfIP and a
different stack is needed.

### Deviations from RFC 1256: no ICMP Router Discovery

wolfIP's forwarding path does not implement the router portion of ICMP
Router Discovery (RFC 1256): it neither sends Router Advertisements
(type 9), solicited or periodic, nor answers Router Solicitations (type 10).
This is a documented, intended deviation, not a bug:

- wolfIP hosts are configured by DHCP or static configuration; the stack has
no host-side router-discovery consumer that would need the router side.
- Routing is connected-subnet plus static routes only (no dynamic protocol),
so there is no route information to advertise beyond what DHCP or a static
default gateway already provides.
- Periodic advertisement would add per-interface timer and scheduling state
to the forwarding path for no in-ecosystem consumer.

Hosts attached to a wolfIP router must obtain their default gateway from
DHCP or be configured with the router's address statically.

### Wiring a router

Expand Down
14 changes: 9 additions & 5 deletions src/supplicant/supplicant.h
Original file line number Diff line number Diff line change
Expand Up @@ -409,11 +409,15 @@ int wolfip_supplicant_get_pmkid(const struct wolfip_supplicant *s,

/* Set up a PMKSA "fast reconnect": when a valid PMKSA is cached for the
* current SSID + BSSID (from a prior AUTHENTICATED session on this context),
* reuse the cached PMK + PMKID, skip the SAE/EAP authentication entirely,
* include the PMKID in the (Re)Assoc RSN IE, and go straight to the 4-way
* handshake on the next wolfip_supplicant_kick(). Call after _init() (which
* preserves the cache) and before kick(). Returns 0 if a usable PMKSA was
* found and armed, -1 otherwise (caller should fall back to a full auth). */
* reuse the cached PMK + PMKID, skip the authentication exchange, include
* the PMKID in the (Re)Assoc RSN IE, and go straight to the 4-way handshake
* on the next wolfip_supplicant_kick(). Call after _init() (which preserves
* the cache) and before kick(). Returns 0 if a usable PMKSA was found and
* armed, -1 otherwise (caller should fall back to a full auth).
*
* Note: the cached entry must carry a PMKID, which is only stored for SAE
* authentication; EAP/PEAP sessions do not produce one, so they never
* satisfy this API and always perform a full EAP authentication. */
int wolfip_supplicant_pmksa_reconnect(struct wolfip_supplicant *s);

#ifdef __cplusplus
Expand Down
19 changes: 18 additions & 1 deletion src/test/unit/unit.c
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ Suite *wolf_suite(void)
tcase_add_test(tc_utils, test_port_alloc_returns_zero_when_range_exhausted);
tcase_add_test(tc_utils, test_sock_bind_udp_filter_blocks);
tcase_add_test(tc_utils, test_sock_bind_icmp_success);
tcase_add_test(tc_utils, test_sock_bind_icmp_any_resets_stale_local_ip);
tcase_add_test(tc_utils, test_sock_connect_wrong_family);
tcase_add_test(tc_utils, test_sock_accept_error_paths);
tcase_add_test(tc_utils, test_sock_accept_non_tcp_socket_sets_addrlen);
Expand Down Expand Up @@ -606,6 +607,7 @@ Suite *wolf_suite(void)
tcase_add_test(tc_utils, test_tcp_syn_sent_to_established);
tcase_add_test(tc_utils, test_tcp_input_syn_sent_unexpected_flags);
tcase_add_test(tc_utils, test_tcp_input_syn_sent_synack_transitions);
tcase_add_test(tc_utils, test_tcp_input_syn_sent_synack_queues_single_ack);
tcase_add_test(tc_utils, test_tcp_input_syn_sent_synack_invalid_ack_rejected);
tcase_add_test(tc_utils, test_tcp_input_syn_listen_does_not_scale_syn_window);
tcase_add_test(tc_utils, test_tcp_input_syn_sent_does_not_scale_synack_window);
Expand Down Expand Up @@ -744,6 +746,7 @@ Suite *wolf_suite(void)
tcase_add_test(tc_utils, test_tcp_consume_ooo_wrap_drop_fully_acked);
tcase_add_test(tc_utils, test_tcp_store_ooo_overlap_does_not_exhaust_cache);
tcase_add_test(tc_utils, test_tcp_ack_sack_early_retransmit_before_three_dupack);
tcase_add_test(tc_utils, test_tcp_ack_forward_ack_after_retransmit_not_duplicate);
tcase_add_test(tc_utils, test_tcp_input_listen_syn_without_sack_disables_sack);
tcase_add_test(tc_utils, test_tcp_input_listen_syn_arms_control_rto);
tcase_add_test(tc_utils, test_tcp_input_listen_syn_sends_synack_immediately);
Expand Down Expand Up @@ -945,6 +948,7 @@ Suite *wolf_suite(void)
tcase_add_test(tc_proto, test_regression_forwarding_rpf_drops_spoofed_source);
tcase_add_test(tc_proto, test_regression_forwarding_drops_source_routed_packet);
tcase_add_test(tc_proto, test_regression_forwarding_drops_source_route_behind_undersized_option);
tcase_add_test(tc_proto, test_regression_forwarding_malformed_source_route_param_problem);
tcase_add_test(tc_proto, test_regression_loopback_source_dropped_on_non_loopback_iface);
tcase_add_test(tc_proto, test_regression_icmp_echo_request_non_local_dst_no_reply);
tcase_add_test(tc_proto, test_tcp_listen_rejects_wrong_interface);
Expand Down Expand Up @@ -990,6 +994,10 @@ Suite *wolf_suite(void)
tcase_add_test(tc_proto, test_dns_query_and_callback_a);
tcase_add_test(tc_proto, test_dhcp_option_u32_macros_round_trip_wire_order);
tcase_add_test(tc_proto, test_dhcp_parse_offer_and_ack);
tcase_add_test(tc_proto, test_dhcp_lease_ip_sane_rejects_bad_mask_and_network_addr);
tcase_add_test(tc_proto, test_dhcp_long_lease_renewal_checkpoint_rearm);
tcase_add_test(tc_proto, test_dhcp_parse_offer_reject_does_not_commit_server_id);
tcase_add_test(tc_proto, test_dhcp_dad_conflict_waits_10s_before_rediscover);
tcase_add_test(tc_proto, test_dhcp_schedule_lease_timer_defaults_t1_t2);
tcase_add_test(tc_proto, test_dhcp_schedule_lease_timer_small_lease_clamps_t1_t2);
tcase_add_test(tc_proto, test_dhcp_parse_offer_defaults_mask_when_missing);
Expand Down Expand Up @@ -1250,6 +1258,7 @@ Suite *wolf_suite(void)
tcase_add_test(tc_core, test_sock_sendto_raw_null_dest_no_remote_ip);
tcase_add_test(tc_core, test_sock_sendto_raw_hdrincl_dst_from_buf);
tcase_add_test(tc_core, test_raw_hdrincl_dst_override_recomputes_ip_checksum);
tcase_add_test(tc_core, test_raw_hdrincl_oversized_ihl_rejected);
tcase_add_test(tc_core, test_sock_sendto_raw_invalid_fd);
tcase_add_test(tc_core, test_sock_sendto_raw_fifo_full_returns_eagain);
tcase_add_test(tc_core, test_sock_setsockopt_raw_hdrincl);
Expand Down Expand Up @@ -1291,6 +1300,9 @@ Suite *wolf_suite(void)
tcase_add_test(tc_core, test_sock_getpeername_tcp_success);
tcase_add_test(tc_core, test_sock_getpeername_tcp_invalid_fd);
tcase_add_test(tc_core, test_sock_getpeername_tcp_null_addr);
tcase_add_test(tc_core, test_sock_getpeername_udp_connected);
tcase_add_test(tc_core, test_sock_getpeername_udp_unconnected);
tcase_add_test(tc_core, test_sock_getpeername_udp_invalid_fd);
#if WOLFIP_RAWSOCKETS
tcase_add_test(tc_core, test_sock_getpeername_raw_success);
tcase_add_test(tc_core, test_sock_getpeername_raw_no_remote_ip);
Expand Down Expand Up @@ -1388,7 +1400,7 @@ Suite *wolf_suite(void)
tcase_add_test(tc_core, test_sock_close_close_wait_disarms_callback);
tcase_add_test(tc_core, test_rst_in_fin_wait_1_delivers_close_event);
tcase_add_test(tc_core, test_last_ack_final_ack_delivers_close_event);
/* --- unit_tests_poll_dispatcher.c (47 tests) --- */
/* --- unit_tests_poll_dispatcher.c (48 tests) --- */
tcase_add_test(tc_core, test_poll_device_poll_returns_zero_exits_loop);
tcase_add_test(tc_core, test_poll_device_poll_returns_negative_exits_loop);
tcase_add_test(tc_core, test_poll_device_non_ethernet_path_receives);
Expand Down Expand Up @@ -1421,6 +1433,7 @@ Suite *wolf_suite(void)
tcase_add_test(tc_core, test_poll_tx_udp_filter_ip_blocks_send);
tcase_add_test(tc_core, test_poll_tx_udp_eagain_retains_queue);
tcase_add_test(tc_core, test_poll_tx_udp_drain_sets_writable);
tcase_add_test(tc_core, test_poll_tx_icmp_drain_sets_writable);
tcase_add_test(tc_core, test_poll_tx_udp_broadcast_sets_ff_mac);
tcase_add_test(tc_core, test_poll_tx_udp_loopback_path_no_crash);
tcase_add_test(tc_core, test_poll_tx_icmp_sends_on_arp_hit);
Expand Down Expand Up @@ -1548,6 +1561,9 @@ Suite *wolf_suite(void)
tcase_add_test(tc_core, test_ip_recv_forward_ttl1_partial_payload_quoted);
tcase_add_test(tc_core, test_forward_ttl_exceeded_copies_orig_tos);
tcase_add_test(tc_core, test_ip_recv_forward_df_oversize_sends_frag_needed);
tcase_add_test(tc_core, test_ip_recv_forward_bad_option_sends_param_problem);
tcase_add_test(tc_core, test_ip_recv_local_bad_option_silent_drop);
tcase_add_test(tc_core, test_ip_recv_forward_bad_option_icmp_error_suppressed);
tcase_add_test(tc_core, test_ip_recv_forward_nodf_oversize_dropped);
tcase_add_test(tc_core, test_ip_recv_forward_df_at_mtu_forwarded);
tcase_add_test(tc_core, test_ip_recv_forward_directed_bcast_ingress_net_not_forwarded);
Expand Down Expand Up @@ -1731,6 +1747,7 @@ Suite *wolf_suite(void)
tcase_add_test(tc_proto, test_vlan_delete_rejected_with_route);
#endif
tcase_add_test(tc_proto, test_vlan_delete_rejected_with_socket);
tcase_add_test(tc_proto, test_vlan_delete_rejected_with_icmp_socket);
tcase_add_test(tc_proto, test_vlan_api_get_null_args_rejected);
tcase_add_test(tc_proto, test_vlan_api_get_dangling_parent_pointer_rejected);
tcase_add_test(tc_proto, test_vlan_tx_active_without_parent_rejected);
Expand Down
75 changes: 75 additions & 0 deletions src/test/unit/unit_esp.c
Original file line number Diff line number Diff line change
Expand Up @@ -2412,6 +2412,80 @@ START_TEST(test_esp_state_persistence_keeps_64bit_bitmap)
}
END_TEST

/* F-11436: the GCM constructor is the only SA constructor with a
* fallible step (pre-iv RNG) after the slot is filled. Its restore must
* run on the success path only; on the RNG failure path the SA is wiped
* and -1 returned, without querying the read callback with the wiped
* zero SPI. This test pins the success path: a GCM SA recreated with a
* known SPI picks up its persisted window. */
static uint8_t state_gcm_spi[ESP_SPI_LEN] = {0x11, 0x22, 0x33, 0x44};
static uint32_t state_gcm_oseq = 0;
static uint32_t state_gcm_hi_seq = 0;
static uint64_t state_gcm_bitmap = 0;
static int state_gcm_read_calls = 0;

static int state_gcm_read_cb(const uint8_t *spi, uint32_t *oseq,
uint32_t *hi_seq, uint64_t *bitmap)
{
state_gcm_read_calls++;
if (memcmp(spi, state_gcm_spi, ESP_SPI_LEN) == 0) {
*oseq = state_gcm_oseq;
*hi_seq = state_gcm_hi_seq;
*bitmap = state_gcm_bitmap;
return 0;
}
return -1; /* unknown SPI: start fresh */
}

static int state_gcm_write_cb(const uint8_t *spi, uint32_t oseq,
uint32_t hi_seq, uint64_t bitmap)
{
if (memcmp(spi, state_gcm_spi, ESP_SPI_LEN) == 0) {
state_gcm_oseq = oseq;
state_gcm_hi_seq = hi_seq;
state_gcm_bitmap = bitmap;
}
return 0;
}

START_TEST(test_esp_state_restore_gcm)
{
int ret;
wolfIP_esp_sa *esp_sa;

esp_setup();
state_gcm_oseq = 5;
state_gcm_hi_seq = 40;
state_gcm_bitmap = (1ULL << 10) | 1ULL;
state_gcm_read_calls = 0;

ret = wolfIP_esp_state_set_cbs(state_gcm_write_cb, state_gcm_read_cb);
ck_assert_int_eq(ret, 0);

ret = wolfIP_esp_sa_new_gcm(1, (uint8_t *)state_gcm_spi,
atoip4(T_SRC), atoip4(T_DST),
ESP_ENC_GCM_RFC4543,
(uint8_t *)k_aes256_gcm,
sizeof(k_aes256_gcm));
ck_assert_int_eq(ret, 0);
ck_assert_int_eq(state_gcm_read_calls, 1);
esp_sa = esp_sa_get(1, (uint8_t *)state_gcm_spi);
ck_assert_ptr_nonnull(esp_sa);
ck_assert_uint_eq(esp_sa->replay.oseq, 5U);
ck_assert_uint_eq(esp_sa->replay.hi_seq, 40U);
ck_assert_uint_eq(esp_sa->replay.bitmap, (1ULL << 10) | 1ULL);

/* The restored window rejects the duplicate (seq 30, bit 10) and
* accepts a new sequence (41). */
ck_assert_int_ne(esp_replay_check(&esp_sa->replay, 30U), 0);
ck_assert_int_eq(esp_replay_check(&esp_sa->replay, 41U), 0);

wolfIP_esp_sa_del_all();
ret = wolfIP_esp_state_set_cbs(NULL, NULL);
ck_assert_int_eq(ret, 0);
}
END_TEST

START_TEST(test_esp_state_persistence_callbacks)
{
static uint8_t buf[LINK_MTU + 256];
Expand Down Expand Up @@ -2589,6 +2663,7 @@ static Suite *esp_suite(void)
tcase_add_test(tc, test_esp_state_persistence_callbacks);
tcase_add_test(tc, test_esp_state_restore_failed_read_keeps_fresh_state);
tcase_add_test(tc, test_esp_state_persistence_keeps_64bit_bitmap);
tcase_add_test(tc, test_esp_state_restore_gcm);
suite_add_tcase(s, tc);

/* Replay window */
Expand Down
31 changes: 31 additions & 0 deletions src/test/unit/unit_tests_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -1709,6 +1709,37 @@ START_TEST(test_sock_bind_icmp_success)
}
END_TEST

START_TEST(test_sock_bind_icmp_any_resets_stale_local_ip)
{
struct wolfIP s;
int icmp_sd;
struct tsocket *ts;
struct wolfIP_sockaddr_in sin;

wolfIP_init(&s);
mock_link_init(&s);
/* No ipconfig: no interface holds a configured address. */

icmp_sd = wolfIP_sock_socket(&s, AF_INET, IPSTACK_SOCK_DGRAM, WI_IPPROTO_ICMP);
ck_assert_int_gt(icmp_sd, 0);
ts = &s.icmpsockets[SOCKET_UNMARK(icmp_sd)];
/* Stale local address from an earlier bind/send while the interface
* still held 10.0.0.1 (F-12391). */
ts->local_ip = 0x0A000001U;

memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = ee16(7);
sin.sin_addr.s_addr = ee32(IPADDR_ANY);

ck_assert_int_eq(wolfIP_sock_bind(&s, icmp_sd, (struct wolfIP_sockaddr *)&sin, sizeof(sin)), 0);
/* Re-binding ANY with no configured address must clear the stale
* local_ip, as the UDP and TCP bind arms do. */
ck_assert_uint_eq(ts->local_ip, IPADDR_ANY);
ck_assert_uint_eq(ts->src_port, 7U);
}
END_TEST

START_TEST(test_sock_connect_wrong_family)
{
struct wolfIP s;
Expand Down
29 changes: 19 additions & 10 deletions src/test/unit/unit_tests_dhcp_edges.c
Original file line number Diff line number Diff line change
Expand Up @@ -1325,14 +1325,14 @@ START_TEST(test_dhcp_timer_cb_default_state_noop)
wolfIP_init(&s);
mock_link_init(&s);
s.dhcp_xid = 0x5678U;
s.dhcp_state = DHCP_OFF; /* unhandled in switch */
s.dhcp_state = 99; /* not a real state: default branch */
s.dhcp_timeout_count = 0;

dhcp_timer_cb(&s);

/* Timer must reset to NO_TIMER and state must stay DHCP_OFF */
/* Timer must reset to NO_TIMER and state must be untouched */
ck_assert_int_eq(s.dhcp_timer, NO_TIMER);
ck_assert_int_eq(s.dhcp_state, DHCP_OFF);
ck_assert_int_eq(s.dhcp_state, 99);
}
END_TEST

Expand Down Expand Up @@ -1716,9 +1716,15 @@ START_TEST(test_dhcp_dad_conflict_releases_and_rediscover)

arp_recv(&s, TEST_PRIMARY_IF, &reply, sizeof(reply));

/* Address released, DAD aborted, back to discovery. */
/* Address released, DAD aborted. RFC 2131 4.4.2: the re-DISCOVER
* is deferred 10 s behind the DECLINE. */
ck_assert_uint_eq(s.dhcp_dad_probes, 0U);
ck_assert_uint_eq(primary->ip, 0U);
ck_assert_int_eq(s.dhcp_state, DHCP_OFF);

/* The wait expires: the re-DISCOVER goes out. */
s.last_tick += 10000U;
handle_timers(&s, s.last_tick);
ck_assert_int_eq(s.dhcp_state, DHCP_DISCOVER_SENT);
}
END_TEST
Expand Down Expand Up @@ -1771,8 +1777,9 @@ START_TEST(test_dhcp_dad_request_claiming_candidate_conflict)

arp_recv(&s, TEST_PRIMARY_IF, &req, sizeof(req));

/* Conflict detected: DAD aborted, lease released, back to DISCOVER. */
ck_assert_int_eq(s.dhcp_state, DHCP_DISCOVER_SENT);
/* Conflict detected: DAD aborted, lease released. The re-DISCOVER
* waits 10 s behind the DECLINE (RFC 2131 4.4.2). */
ck_assert_int_eq(s.dhcp_state, DHCP_OFF);
ck_assert_uint_eq(s.dhcp_dad_probes, 0U);
ck_assert_uint_eq(primary->ip, 0U);
}
Expand Down Expand Up @@ -1824,8 +1831,9 @@ START_TEST(test_dhcp_dad_probe_for_candidate_conflict)

arp_recv(&s, TEST_PRIMARY_IF, &req, sizeof(req));

/* Conflict detected: DAD aborted, lease released, back to DISCOVER. */
ck_assert_int_eq(s.dhcp_state, DHCP_DISCOVER_SENT);
/* Conflict detected: DAD aborted, lease released. The re-DISCOVER
* waits 10 s behind the DECLINE (RFC 2131 4.4.2). */
ck_assert_int_eq(s.dhcp_state, DHCP_OFF);
ck_assert_uint_eq(s.dhcp_dad_probes, 0U);
ck_assert_uint_eq(primary->ip, 0U);
}
Expand Down Expand Up @@ -1878,8 +1886,9 @@ START_TEST(test_dhcp_dad_garp_announcement_conflict)

arp_recv(&s, TEST_PRIMARY_IF, &req, sizeof(req));

/* Conflict detected: DAD aborted, lease released, back to DISCOVER. */
ck_assert_int_eq(s.dhcp_state, DHCP_DISCOVER_SENT);
/* Conflict detected: DAD aborted, lease released. The re-DISCOVER
* waits 10 s behind the DECLINE (RFC 2131 4.4.2). */
ck_assert_int_eq(s.dhcp_state, DHCP_OFF);
ck_assert_uint_eq(s.dhcp_dad_probes, 0U);
ck_assert_uint_eq(primary->ip, 0U);
}
Expand Down
Loading
Loading