From: Patrik Flykt Date: Mon, 9 Dec 2013 21:43:31 +0000 (+0200) Subject: dhcp: Add notification callback X-Git-Tag: v209~972 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=751246ee37cf0cd72baf378f1b9c1ac04f8b8c9b;ds=sidebyside dhcp: Add notification callback Define a notification callback and events for stopping and client lease expiry. Add functions to fetch IP parameters from a lease. --- diff --git a/src/libsystemd-dhcp/dhcp-client.c b/src/libsystemd-dhcp/dhcp-client.c index d03435b92..03a846df3 100644 --- a/src/libsystemd-dhcp/dhcp-client.c +++ b/src/libsystemd-dhcp/dhcp-client.c @@ -63,6 +63,8 @@ struct sd_dhcp_client { sd_event_source *timeout_t1; sd_event_source *timeout_t2; sd_event_source *timeout_expire; + sd_dhcp_client_cb_t cb; + void *userdata; DHCPLease *lease; }; @@ -75,6 +77,17 @@ static const uint8_t default_req_opts[] = { DHCP_OPTION_NTP_SERVER, }; +int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_cb_t cb, + void *userdata) +{ + assert_return(client, -EINVAL); + + client->cb = cb; + client->userdata = userdata; + + return 0; +} + int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option) { size_t i; @@ -143,8 +156,99 @@ int sd_dhcp_client_set_mac(sd_dhcp_client *client, return 0; } +int sd_dhcp_client_get_address(sd_dhcp_client *client, struct in_addr *addr) +{ + assert_return(client, -EINVAL); + assert_return(addr, -EINVAL); + + switch (client->state) { + case DHCP_STATE_INIT: + case DHCP_STATE_SELECTING: + case DHCP_STATE_INIT_REBOOT: + case DHCP_STATE_REBOOTING: + case DHCP_STATE_REQUESTING: + return -EADDRNOTAVAIL; + + case DHCP_STATE_BOUND: + case DHCP_STATE_RENEWING: + case DHCP_STATE_REBINDING: + addr->s_addr = client->lease->address; + + break; + } + + return 0; +} + +int sd_dhcp_client_get_netmask(sd_dhcp_client *client, struct in_addr *addr) +{ + assert_return(client, -EINVAL); + assert_return(addr, -EINVAL); + + switch (client->state) { + case DHCP_STATE_INIT: + case DHCP_STATE_SELECTING: + case DHCP_STATE_INIT_REBOOT: + case DHCP_STATE_REBOOTING: + case DHCP_STATE_REQUESTING: + return -EADDRNOTAVAIL; + + case DHCP_STATE_BOUND: + case DHCP_STATE_RENEWING: + case DHCP_STATE_REBINDING: + addr->s_addr = client->lease->subnet_mask; + + break; + } + + return 0; +} + +int sd_dhcp_client_prefixlen(const struct in_addr *addr) +{ + int len = 0; + uint32_t mask; + + assert_return(addr, -EADDRNOTAVAIL); + + mask = be32toh(addr->s_addr); + while (mask) { + len++; + mask = mask << 1; + } + + return len; +} + +int sd_dhcp_client_get_router(sd_dhcp_client *client, struct in_addr *addr) +{ + assert_return(client, -EINVAL); + assert_return(addr, -EINVAL); + + switch (client->state) { + case DHCP_STATE_INIT: + case DHCP_STATE_SELECTING: + case DHCP_STATE_INIT_REBOOT: + case DHCP_STATE_REBOOTING: + case DHCP_STATE_REQUESTING: + return -EADDRNOTAVAIL; + + case DHCP_STATE_BOUND: + case DHCP_STATE_RENEWING: + case DHCP_STATE_REBINDING: + addr->s_addr = client->lease->router; + + break; + } + + return 0; +} + static int client_notify(sd_dhcp_client *client, int event) { + if (client->cb) + client->cb(client, event, client->userdata); + return 0; } @@ -169,6 +273,8 @@ static int client_stop(sd_dhcp_client *client, int error) client->attempt = 1; + client_notify(client, error); + switch (client->state) { case DHCP_STATE_INIT: @@ -463,6 +569,10 @@ error: static int client_timeout_expire(sd_event_source *s, uint64_t usec, void *userdata) { + sd_dhcp_client *client = userdata; + + client_stop(client, DHCP_EVENT_EXPIRED); + return 0; } @@ -848,7 +958,7 @@ error: int sd_dhcp_client_stop(sd_dhcp_client *client) { - return client_stop(client, 0); + return client_stop(client, DHCP_EVENT_STOP); } sd_dhcp_client *sd_dhcp_client_new(sd_event *event) diff --git a/src/systemd/sd-dhcp-client.h b/src/systemd/sd-dhcp-client.h index ed72cf1a7..395c12d25 100644 --- a/src/systemd/sd-dhcp-client.h +++ b/src/systemd/sd-dhcp-client.h @@ -28,13 +28,21 @@ #include "sd-event.h" enum { + DHCP_EVENT_STOP = 0, DHCP_EVENT_NO_LEASE = 1, DHCP_EVENT_IP_ACQUIRE = 2, DHCP_EVENT_IP_CHANGE = 3, + DHCP_EVENT_EXPIRED = 4, }; typedef struct sd_dhcp_client sd_dhcp_client; +typedef void (*sd_dhcp_client_cb_t)(sd_dhcp_client *client, int event, + void *userdata); +int sd_dhcp_client_set_callback(sd_dhcp_client *client, sd_dhcp_client_cb_t cb, + void *userdata); + + int sd_dhcp_client_set_request_option(sd_dhcp_client *client, uint8_t option); int sd_dhcp_client_set_request_address(sd_dhcp_client *client, const struct in_addr *last_address); @@ -42,6 +50,11 @@ int sd_dhcp_client_set_index(sd_dhcp_client *client, int interface_index); int sd_dhcp_client_set_mac(sd_dhcp_client *client, const struct ether_addr *addr); +int sd_dhcp_client_get_address(sd_dhcp_client *client, struct in_addr *addr); +int sd_dhcp_client_get_netmask(sd_dhcp_client *client, struct in_addr *addr); +int sd_dhcp_client_prefixlen(const struct in_addr *addr); +int sd_dhcp_client_get_router(sd_dhcp_client *client, struct in_addr *addr); + int sd_dhcp_client_stop(sd_dhcp_client *client); int sd_dhcp_client_start(sd_dhcp_client *client); sd_dhcp_client *sd_dhcp_client_new(sd_event *event);