static int test_client_solicit(sd_event *e) { sd_dhcp6_client *client; usec_t time_now = now(clock_boottime_or_monotonic()); struct in6_addr address = { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01 } } }; int val; if (verbose) printf("* %s\n", __FUNCTION__); assert_se(sd_dhcp6_client_new(&client) >= 0); assert_se(client); assert_se(sd_dhcp6_client_attach_event(client, e, 0) >= 0); assert_se(sd_dhcp6_client_set_ifindex(client, test_index) == 0); assert_se(sd_dhcp6_client_set_mac(client, (const uint8_t *) &mac_addr, sizeof (mac_addr), ARPHRD_ETHER) >= 0); assert_se(sd_dhcp6_client_set_fqdn(client, "host.lab.intra") == 1); assert_se(sd_dhcp6_client_get_information_request(client, &val) >= 0); assert_se(val == 0); assert_se(sd_dhcp6_client_set_information_request(client, 42) >= 0); assert_se(sd_dhcp6_client_get_information_request(client, &val) >= 0); assert_se(val); assert_se(sd_dhcp6_client_set_callback(client, test_client_information_cb, e) >= 0); assert_se(sd_event_add_time(e, &hangcheck, clock_boottime_or_monotonic(), time_now + 2 * USEC_PER_SEC, 0, test_hangcheck, NULL) >= 0); assert_se(sd_dhcp6_client_set_local_address(client, &address) >= 0); assert_se(sd_dhcp6_client_start(client) >= 0); sd_event_loop(e); hangcheck = sd_event_source_unref(hangcheck); assert_se(!sd_dhcp6_client_unref(client)); test_dhcp_fd[1] = safe_close(test_dhcp_fd[1]); return 0; }
int dhcp6_request_address(Link *link, int ir) { int r, inf_req; bool running; assert(link); assert(link->dhcp6_client); assert(in_addr_is_link_local(AF_INET6, (const union in_addr_union*)&link->ipv6ll_address) > 0); r = sd_dhcp6_client_is_running(link->dhcp6_client); if (r < 0) return r; else running = !!r; if (running) { r = sd_dhcp6_client_get_information_request(link->dhcp6_client, &inf_req); if (r < 0) return r; if (inf_req == ir) return 0; r = sd_dhcp6_client_stop(link->dhcp6_client); if (r < 0) return r; } else { r = sd_dhcp6_client_set_local_address(link->dhcp6_client, &link->ipv6ll_address); if (r < 0) return r; } r = sd_dhcp6_client_set_information_request(link->dhcp6_client, ir); if (r < 0) return r; r = sd_dhcp6_client_start(link->dhcp6_client); if (r < 0) return r; return 0; }
static void test_client_information_cb(sd_dhcp6_client *client, int event, void *userdata) { sd_event *e = userdata; sd_dhcp6_lease *lease; struct in6_addr *addrs; struct in6_addr address = { { { 0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01 } } }; char **domains; assert_se(e); assert_se(event == SD_DHCP6_CLIENT_EVENT_INFORMATION_REQUEST); assert_se(sd_dhcp6_client_get_lease(client, &lease) >= 0); assert_se(sd_dhcp6_lease_get_domains(lease, &domains) == 1); assert_se(!strcmp("lab.intra", domains[0])); assert_se(domains[1] == NULL); assert_se(sd_dhcp6_lease_get_dns(lease, &addrs) == 1); assert_se(!memcmp(addrs, &msg_advertise[124], 16)); assert_se(sd_dhcp6_lease_get_ntp_addrs(lease, &addrs) == 1); assert_se(!memcmp(addrs, &msg_advertise[159], 16)); if (verbose) printf(" got DHCPv6 event %d\n", event); assert_se(sd_dhcp6_client_set_information_request(client, false) == -EBUSY); assert_se(sd_dhcp6_client_set_callback(client, NULL, e) >= 0); assert_se(sd_dhcp6_client_stop(client) >= 0); assert_se(sd_dhcp6_client_set_information_request(client, false) >= 0); assert_se(sd_dhcp6_client_set_callback(client, test_client_solicit_cb, e) >= 0); assert_se(sd_dhcp6_client_set_local_address(client, &address) >= 0); assert_se(sd_dhcp6_client_start(client) >= 0); }
int dhcp6_request_address(Link *link) { int r, inf_req; bool running; assert(link); assert(link->dhcp6_client); r = sd_dhcp6_client_get_information_request(link->dhcp6_client, &inf_req); if (r < 0) return r; if (!inf_req) return 0; r = sd_dhcp6_client_is_running(link->dhcp6_client); if (r < 0) return r; else running = !!r; if (running) { r = sd_dhcp6_client_stop(link->dhcp6_client); if (r < 0) return r; } r = sd_dhcp6_client_set_information_request(link->dhcp6_client, false); if (r < 0) return r; if (running) { r = sd_dhcp6_client_start(link->dhcp6_client); if (r < 0) return r; } return 0; }
static int dhcp6_configure(Link *link, int event) { int r; bool information_request; assert_return(link, -EINVAL); assert_return(IN_SET(event, SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_TIMEOUT, SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_OTHER, SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_MANAGED), -EINVAL); link->dhcp6_configured = false; if (link->dhcp6_client) { r = sd_dhcp6_client_get_information_request(link->dhcp6_client, &information_request); if (r < 0) { log_link_warning_errno(link, r, "Could not get DHCPv6 Information request setting: %m"); goto error; } if (information_request && event != SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_OTHER) { r = sd_dhcp6_client_stop(link->dhcp6_client); if (r < 0) { log_link_warning_errno(link, r, "Could not stop DHCPv6 while setting Managed mode: %m"); goto error; } r = sd_dhcp6_client_set_information_request(link->dhcp6_client, false); if (r < 0) { log_link_warning_errno(link, r, "Could not unset DHCPv6 Information request: %m"); goto error; } } r = sd_dhcp6_client_start(link->dhcp6_client); if (r < 0 && r != -EALREADY) { log_link_warning_errno(link, r, "Could not restart DHCPv6: %m"); goto error; } if (r == -EALREADY) link->dhcp6_configured = true; return r; } r = sd_dhcp6_client_new(&link->dhcp6_client); if (r < 0) goto error; r = sd_dhcp6_client_attach_event(link->dhcp6_client, NULL, 0); if (r < 0) goto error; r = sd_dhcp6_client_set_mac(link->dhcp6_client, (const uint8_t *) &link->mac, sizeof (link->mac), ARPHRD_ETHER); if (r < 0) goto error; r = sd_dhcp6_client_set_index(link->dhcp6_client, link->ifindex); if (r < 0) goto error; r = sd_dhcp6_client_set_callback(link->dhcp6_client, dhcp6_handler, link); if (r < 0) goto error; if (event == SD_ICMP6_ND_EVENT_ROUTER_ADVERTISMENT_OTHER) { r = sd_dhcp6_client_set_information_request(link->dhcp6_client, true); if (r < 0) goto error; } r = sd_dhcp6_client_start(link->dhcp6_client); if (r < 0) goto error; return r; error: link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client); return r; }
static gboolean ip6_start (NMDhcpClient *client, const char *dhcp_anycast_addr, const struct in6_addr *ll_addr, gboolean info_only, NMSettingIP6ConfigPrivacy privacy, const GByteArray *duid) { NMDhcpSystemd *self = NM_DHCP_SYSTEMD (client); NMDhcpSystemdPrivate *priv = NM_DHCP_SYSTEMD_GET_PRIVATE (self); const char *iface = nm_dhcp_client_get_iface (client); const GByteArray *hwaddr; int r, i; g_assert (priv->client4 == NULL); g_assert (priv->client6 == NULL); g_return_val_if_fail (duid != NULL, FALSE); g_free (priv->lease_file); priv->lease_file = get_leasefile_path (iface, nm_dhcp_client_get_uuid (client), TRUE); priv->info_only = info_only; r = sd_dhcp6_client_new (&priv->client6); if (r < 0) { _LOGW ("failed to create client (%d)", r); return FALSE; } _LOGT ("dhcp-client6: set %p", priv->client4); if (info_only) sd_dhcp6_client_set_information_request (priv->client6, 1); /* NM stores the entire DUID which includes the uint16 "type", while systemd * wants the type passed separately from the following data. */ r = sd_dhcp6_client_set_duid (priv->client6, ntohs (((const guint16 *) duid->data)[0]), duid->data + 2, duid->len - 2); if (r < 0) { _LOGW ("failed to set DUID (%d)", r); return FALSE; } r = sd_dhcp6_client_attach_event (priv->client6, NULL, 0); if (r < 0) { _LOGW ("failed to attach event (%d)", r); goto error; } hwaddr = nm_dhcp_client_get_hw_addr (client); if (hwaddr) { r = sd_dhcp6_client_set_mac (priv->client6, hwaddr->data, hwaddr->len, get_arp_type (hwaddr)); if (r < 0) { _LOGW ("failed to set MAC address (%d)", r); goto error; } } r = sd_dhcp6_client_set_index (priv->client6, nm_dhcp_client_get_ifindex (client)); if (r < 0) { _LOGW ("failed to set ifindex (%d)", r); goto error; } r = sd_dhcp6_client_set_callback (priv->client6, dhcp6_event_cb, client); if (r < 0) { _LOGW ("failed to set callback (%d)", r); goto error; } /* Add requested options */ for (i = 0; dhcp6_requests[i].name; i++) { if (dhcp6_requests[i].include) sd_dhcp6_client_set_request_option (priv->client6, dhcp6_requests[i].num); } r = sd_dhcp6_client_set_local_address (priv->client6, ll_addr); if (r < 0) { _LOGW ("failed to set local address (%d)", r); goto error; } r = sd_dhcp6_client_start (priv->client6); if (r < 0) { _LOGW ("failed to start client (%d)", r); goto error; } return TRUE; error: sd_dhcp6_client_unref (priv->client6); priv->client6 = NULL; return FALSE; }
static int dhcp6_configure(Link *link, int event) { int r; bool information_request; assert_return(link, -EINVAL); if (link->dhcp6_client) { if (event != ICMP6_EVENT_ROUTER_ADVERTISMENT_MANAGED) return 0; r = sd_dhcp6_client_get_information_request(link->dhcp6_client, &information_request); if (r < 0) { log_link_warning(link, "Could not get DHCPv6 Information request setting: %s", strerror(-r)); link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client); return r; } if (!information_request) return r; r = sd_dhcp6_client_set_information_request(link->dhcp6_client, false); if (r < 0) { log_link_warning(link, "Could not unset DHCPv6 Information request: %s", strerror(-r)); link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client); return r; } r = sd_dhcp6_client_start(link->dhcp6_client); if (r < 0) { log_link_warning(link, "Could not restart DHCPv6 after enabling Information request: %s", strerror(-r)); link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client); return r; } return r; } r = sd_dhcp6_client_new(&link->dhcp6_client); if (r < 0) return r; r = sd_dhcp6_client_attach_event(link->dhcp6_client, NULL, 0); if (r < 0) { link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client); return r; } r = sd_dhcp6_client_set_mac(link->dhcp6_client, (const uint8_t *) &link->mac, sizeof (link->mac), ARPHRD_ETHER); if (r < 0) { link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client); return r; } r = sd_dhcp6_client_set_index(link->dhcp6_client, link->ifindex); if (r < 0) { link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client); return r; } r = sd_dhcp6_client_set_callback(link->dhcp6_client, dhcp6_handler, link); if (r < 0) { link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client); return r; } if (event == ICMP6_EVENT_ROUTER_ADVERTISMENT_OTHER) { r = sd_dhcp6_client_set_information_request(link->dhcp6_client, true); if (r < 0) { link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client); return r; } } r = sd_dhcp6_client_start(link->dhcp6_client); if (r < 0) link->dhcp6_client = sd_dhcp6_client_unref(link->dhcp6_client); return r; }