X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Flibsystemd-dhcp%2Fdhcp-client.c;h=fe410676003541fdf36611defb1ab17d5c87e880;hp=d03435b9298912c7623a1021a2c5c9b651220540;hb=3b349af69aab440a625fedb21377e2bdc461098e;hpb=51debc1e396a14d7c1204d8661c4eb1056c47670 diff --git a/src/libsystemd-dhcp/dhcp-client.c b/src/libsystemd-dhcp/dhcp-client.c index d03435b92..fe4106760 100644 --- a/src/libsystemd-dhcp/dhcp-client.c +++ b/src/libsystemd-dhcp/dhcp-client.c @@ -36,10 +36,10 @@ struct DHCPLease { uint32_t t1; uint32_t t2; uint32_t lifetime; - uint32_t address; - uint32_t server_address; - uint32_t subnet_mask; - uint32_t router; + be32_t address; + be32_t server_address; + be32_t subnet_mask; + be32_t router; }; typedef struct DHCPLease DHCPLease; @@ -54,7 +54,7 @@ struct sd_dhcp_client { sd_event_source *receive_message; uint8_t *req_opts; size_t req_opts_size; - uint32_t last_addr; + be32_t last_addr; struct ether_addr mac_addr; uint32_t xid; usec_t start_time; @@ -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; } @@ -787,6 +897,9 @@ static int client_receive_raw_message(sd_event_source *s, int fd, client->receive_message = sd_event_source_unref(client->receive_message); } + + r = 0; + break; case DHCP_STATE_INIT: @@ -800,7 +913,7 @@ static int client_receive_raw_message(sd_event_source *s, int fd, } error: - if (r < 0) + if (r < 0 || r == DHCP_EVENT_NO_LEASE) return client_stop(client, r); return 0; @@ -848,7 +961,20 @@ 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_free(sd_dhcp_client *client) +{ + assert_return(client, NULL); + + sd_dhcp_client_stop(client); + + sd_event_unref(client->event); + free(client->req_opts); + free(client); + + return NULL; } sd_dhcp_client *sd_dhcp_client_new(sd_event *event)