diff options
Diffstat (limited to 'shared/n-dhcp4/src')
| -rw-r--r-- | shared/n-dhcp4/src/n-dhcp4-c-connection.c | 67 | ||||
| -rw-r--r-- | shared/n-dhcp4/src/n-dhcp4-c-lease.c | 12 | ||||
| -rw-r--r-- | shared/n-dhcp4/src/n-dhcp4-c-probe.c | 25 | ||||
| -rw-r--r-- | shared/n-dhcp4/src/n-dhcp4-client.c | 42 | ||||
| -rw-r--r-- | shared/n-dhcp4/src/n-dhcp4-incoming.c | 5 | ||||
| -rw-r--r-- | shared/n-dhcp4/src/n-dhcp4-private.h | 25 | ||||
| -rw-r--r-- | shared/n-dhcp4/src/n-dhcp4-socket.c | 4 | ||||
| -rw-r--r-- | shared/n-dhcp4/src/n-dhcp4.h | 5 |
8 files changed, 165 insertions, 20 deletions
diff --git a/shared/n-dhcp4/src/n-dhcp4-c-connection.c b/shared/n-dhcp4/src/n-dhcp4-c-connection.c index 5c50dacf..8a2ddb36 100644 --- a/shared/n-dhcp4/src/n-dhcp4-c-connection.c +++ b/shared/n-dhcp4/src/n-dhcp4-c-connection.c @@ -513,6 +513,7 @@ static int n_dhcp4_c_connection_new_message(NDhcp4CConnection *connection, n_dhcp4_c_connection_init_header(connection, header); message->userdata.type = type; + message->userdata.message_type = message_type; /* * Note that some implementations expect the MESSAGE_TYPE option to be @@ -690,6 +691,7 @@ int n_dhcp4_c_connection_select_new(NDhcp4CConnection *connection, */ message->userdata.start_time = offer->userdata.start_time; message->userdata.base_time = offer->userdata.base_time; + message->userdata.client_addr = client.s_addr; n_dhcp4_incoming_get_xid(offer, &xid); n_dhcp4_outgoing_set_xid(message, xid); @@ -763,6 +765,7 @@ int n_dhcp4_c_connection_renew_new(NDhcp4CConnection *connection, if (r) return r; + message->userdata.client_addr = connection->client_ip; *requestp = message; message = NULL; return 0; @@ -796,6 +799,7 @@ int n_dhcp4_c_connection_rebind_new(NDhcp4CConnection *connection, if (r) return r; + message->userdata.client_addr = connection->client_ip; *requestp = message; message = NULL; return 0; @@ -847,6 +851,7 @@ int n_dhcp4_c_connection_decline_new(NDhcp4CConnection *connection, return r; } + message->userdata.client_addr = client.s_addr; *requestp = message; message = NULL; return 0; @@ -889,6 +894,7 @@ int n_dhcp4_c_connection_inform_new(NDhcp4CConnection *connection, if (r) return r; + message->userdata.client_addr = connection->client_ip; *requestp = message; message = NULL; return 0; @@ -955,9 +961,36 @@ int n_dhcp4_c_connection_release_new(NDhcp4CConnection *connection, return 0; } +static const char *message_type_to_str(uint8_t type) { + switch (type) { + case N_DHCP4_MESSAGE_DISCOVER: + return "DISCOVER"; + case N_DHCP4_MESSAGE_OFFER: + return "OFFER"; + case N_DHCP4_MESSAGE_REQUEST: + return "REQUEST"; + case N_DHCP4_MESSAGE_DECLINE: + return "DECLINE"; + case N_DHCP4_MESSAGE_ACK: + return "ACK"; + case N_DHCP4_MESSAGE_NAK: + return "NACK"; + case N_DHCP4_MESSAGE_RELEASE: + return "RELEASE"; + case N_DHCP4_MESSAGE_INFORM: + return "INFORM"; + case N_DHCP4_MESSAGE_FORCERENEW: + return "FORCERENEW"; + default: + return "UNKNOWN"; + } +} + static int n_dhcp4_c_connection_send_request(NDhcp4CConnection *connection, NDhcp4Outgoing *request, uint64_t timestamp) { + char server_addr[INET_ADDRSTRLEN]; + char client_addr[INET_ADDRSTRLEN]; int r; /* @@ -1015,6 +1048,22 @@ static int n_dhcp4_c_connection_send_request(NDhcp4CConnection *connection, c_assert(0); } + if (request->userdata.client_addr == INADDR_ANY) { + n_dhcp4_c_log(connection->client_config, LOG_INFO, + "sent %s to %s", + message_type_to_str(request->userdata.message_type), + inet_ntop(AF_INET, &connection->server_ip, + server_addr, sizeof(server_addr))); + } else { + n_dhcp4_c_log(connection->client_config, LOG_INFO, + "sent %s of %s to %s", + message_type_to_str(request->userdata.message_type), + inet_ntop(AF_INET, &request->userdata.client_addr, + client_addr, sizeof(client_addr)), + inet_ntop(AF_INET, &connection->server_ip, + server_addr, sizeof(server_addr))); + } + ++request->userdata.n_send; return 0; } @@ -1066,6 +1115,8 @@ int n_dhcp4_c_connection_dispatch_timer(NDhcp4CConnection *connection, int n_dhcp4_c_connection_dispatch_io(NDhcp4CConnection *connection, NDhcp4Incoming **messagep) { _c_cleanup_(n_dhcp4_incoming_freep) NDhcp4Incoming *message = NULL; + char serv_addr[INET_ADDRSTRLEN]; + char client_addr[INET_ADDRSTRLEN]; uint8_t type; int r; @@ -1118,6 +1169,22 @@ int n_dhcp4_c_connection_dispatch_io(NDhcp4CConnection *connection, if (r) return r; + if (type == N_DHCP4_MESSAGE_OFFER || type == N_DHCP4_MESSAGE_ACK) { + n_dhcp4_c_log(connection->client_config, LOG_INFO, + "received %s of %s from %s", + message_type_to_str(type), + inet_ntop(AF_INET, &message->message.header.yiaddr, + client_addr, sizeof(client_addr)), + inet_ntop(AF_INET, &message->message.header.siaddr, + serv_addr, sizeof(serv_addr))); + } else { + n_dhcp4_c_log(connection->client_config, LOG_INFO, + "received %s from %s", + message_type_to_str(type), + inet_ntop(AF_INET, &message->message.header.siaddr, + serv_addr, sizeof(serv_addr))); + } + switch (type) { case N_DHCP4_MESSAGE_OFFER: case N_DHCP4_MESSAGE_ACK: diff --git a/shared/n-dhcp4/src/n-dhcp4-c-lease.c b/shared/n-dhcp4/src/n-dhcp4-c-lease.c index c14a9daf..695a112a 100644 --- a/shared/n-dhcp4/src/n-dhcp4-c-lease.c +++ b/shared/n-dhcp4/src/n-dhcp4-c-lease.c @@ -218,6 +218,18 @@ _c_public_ void n_dhcp4_client_lease_get_siaddr(NDhcp4ClientLease *lease, struct } /** + * n_dhcp4_client_lease_get_basetime() - get the timestamp when the lease was received. + * @lease: the lease to operate on + * @ns_basetimep: return argument for the base time in nano seconds + * + * Gets the timestamp when the lease was received in CLOCK_BOOTTIME. This + * is also the base timestamp for the expiration of the lifetime and t1/t2. + */ +_c_public_ void n_dhcp4_client_lease_get_basetime(NDhcp4ClientLease *lease, uint64_t *ns_basetimep) { + *ns_basetimep = lease->message->userdata.base_time; +} + +/** * n_dhcp4_client_lease_get_lifetime() - get the lifetime * @lease: the lease to operate on * @ns_lifetimep: return argument for the lifetime in nano seconds diff --git a/shared/n-dhcp4/src/n-dhcp4-c-probe.c b/shared/n-dhcp4/src/n-dhcp4-c-probe.c index 107c18bb..2bced4cf 100644 --- a/shared/n-dhcp4/src/n-dhcp4-c-probe.c +++ b/shared/n-dhcp4/src/n-dhcp4-c-probe.c @@ -800,7 +800,8 @@ static int n_dhcp4_client_probe_transition_lifetime(NDhcp4ClientProbe *probe) { return 0; } -static int n_dhcp4_client_probe_transition_offer(NDhcp4ClientProbe *probe, NDhcp4Incoming *message) { +static int n_dhcp4_client_probe_transition_offer(NDhcp4ClientProbe *probe, NDhcp4Incoming *message_take) { + _c_cleanup_(n_dhcp4_incoming_freep) NDhcp4Incoming *message = message_take; _c_cleanup_(n_dhcp4_client_lease_unrefp) NDhcp4ClientLease *lease = NULL; NDhcp4CEventNode *node; int r; @@ -818,7 +819,7 @@ static int n_dhcp4_client_probe_transition_offer(NDhcp4ClientProbe *probe, NDhcp if (r) return r; - /* message consumed, do not fail */ + message = NULL; /* consumed */ n_dhcp4_client_lease_link(lease, probe); @@ -843,7 +844,8 @@ static int n_dhcp4_client_probe_transition_offer(NDhcp4ClientProbe *probe, NDhcp return 0; } -static int n_dhcp4_client_probe_transition_ack(NDhcp4ClientProbe *probe, NDhcp4Incoming *message) { +static int n_dhcp4_client_probe_transition_ack(NDhcp4ClientProbe *probe, NDhcp4Incoming *message_take) { + _c_cleanup_(n_dhcp4_incoming_freep) NDhcp4Incoming *message = message_take; _c_cleanup_(n_dhcp4_client_lease_unrefp) NDhcp4ClientLease *lease = NULL; NDhcp4CEventNode *node; int r; @@ -862,7 +864,7 @@ static int n_dhcp4_client_probe_transition_ack(NDhcp4ClientProbe *probe, NDhcp4I if (r) return r; - /* message consumed, do not fail */ + message = NULL; /* consumed */ n_dhcp4_client_lease_link(lease, probe); @@ -885,7 +887,7 @@ static int n_dhcp4_client_probe_transition_ack(NDhcp4ClientProbe *probe, NDhcp4I if (r) return r; - /* message consumed, don to fail */ + message = NULL; /* consumed */ n_dhcp4_client_lease_link(lease, probe); @@ -1100,16 +1102,17 @@ int n_dhcp4_client_probe_dispatch_timer(NDhcp4ClientProbe *probe, uint64_t ns_no r = n_dhcp4_client_probe_transition_lifetime(probe); if (r) return r; - } else if (ns_now >= probe->current_lease->t2) { + } else if (ns_now >= probe->current_lease->t2 && + probe->state != N_DHCP4_CLIENT_PROBE_STATE_REBINDING) { r = n_dhcp4_client_probe_transition_t2(probe, ns_now); if (r) return r; - } else if (ns_now >= probe->current_lease->t1) { + } else if (ns_now >= probe->current_lease->t1 && + probe->state == N_DHCP4_CLIENT_PROBE_STATE_BOUND) { r = n_dhcp4_client_probe_transition_t1(probe, ns_now); if (r) return r; } - break; default: /* ignore */ @@ -1167,17 +1170,15 @@ int n_dhcp4_client_probe_dispatch_io(NDhcp4ClientProbe *probe, uint32_t events) switch (type) { case N_DHCP4_MESSAGE_OFFER: r = n_dhcp4_client_probe_transition_offer(probe, message); + message = NULL; /* consumed */ if (r) return r; - else - message = NULL; /* consumed */ break; case N_DHCP4_MESSAGE_ACK: r = n_dhcp4_client_probe_transition_ack(probe, message); + message = NULL; /* consumed */ if (r) return r; - else - message = NULL; /* consumed */ break; case N_DHCP4_MESSAGE_NAK: r = n_dhcp4_client_probe_transition_nak(probe); diff --git a/shared/n-dhcp4/src/n-dhcp4-client.c b/shared/n-dhcp4/src/n-dhcp4-client.c index 5f7794fb..0bfe48ee 100644 --- a/shared/n-dhcp4/src/n-dhcp4-client.c +++ b/shared/n-dhcp4/src/n-dhcp4-client.c @@ -94,6 +94,9 @@ int n_dhcp4_client_config_dup(NDhcp4ClientConfig *config, NDhcp4ClientConfig **d dup->n_mac = config->n_mac; memcpy(dup->broadcast_mac, config->broadcast_mac, sizeof(dup->broadcast_mac)); dup->n_broadcast_mac = config->n_broadcast_mac; + dup->log.level = config->log.level; + dup->log.func = config->log.func; + dup->log.data = config->log.data; r = n_dhcp4_client_config_set_client_id(dup, config->client_id, @@ -248,6 +251,15 @@ _c_public_ int n_dhcp4_client_config_set_client_id(NDhcp4ClientConfig *config, c return 0; } +_c_public_ void n_dhcp4_client_config_set_log_level(NDhcp4ClientConfig *config, int level) { + config->log.level = level; +} + +_c_public_ void n_dhcp4_client_config_set_log_func(NDhcp4ClientConfig *config, NDhcp4LogFunc func, void *data) { + config->log.func = func; + config->log.data = data; +} + /** * n_dhcp4_c_event_node_new() - allocate new event * @nodep: output argument for new event @@ -376,8 +388,14 @@ _c_public_ int n_dhcp4_client_new(NDhcp4Client **clientp, NDhcp4ClientConfig *co return -errno; client->fd_timer = timerfd_create(CLOCK_BOOTTIME, TFD_CLOEXEC | TFD_NONBLOCK); - if (client->fd_timer < 0) - return -errno; + if (client->fd_timer < 0) { + if (errno != EINVAL) + return -errno; + client->fd_timer = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); + if (client->fd_timer < 0) + return -errno; + client->timerfd_is_monotonic = true; + } ev.data.u32 = N_DHCP4_CLIENT_EPOLL_TIMER; r = epoll_ctl(client->fd_epoll, EPOLL_CTL_ADD, client->fd_timer, &ev); @@ -487,8 +505,24 @@ void n_dhcp4_client_arm_timer(NDhcp4Client *client) { n_dhcp4_client_probe_get_timeout(client->current_probe, &timeout); if (timeout != client->scheduled_timeout) { + uint64_t scheduled_timeout = timeout; + int flags = TFD_TIMER_ABSTIME; + + if ( timeout != 0 + && client->timerfd_is_monotonic) { + uint64_t now; + + /* the timerfd ticks with CLOCK_MONOTONIC. Calculate and set the relative + * timeout. */ + now = n_dhcp4_gettime(CLOCK_BOOTTIME); + if (timeout <= now) + timeout = 1; + else + timeout = timeout - now; + flags = 0; + } r = timerfd_settime(client->fd_timer, - TFD_TIMER_ABSTIME, + flags, &(struct itimerspec){ .it_value = { .tv_sec = timeout / UINT64_C(1000000000), @@ -498,7 +532,7 @@ void n_dhcp4_client_arm_timer(NDhcp4Client *client) { NULL); c_assert(r >= 0); - client->scheduled_timeout = timeout; + client->scheduled_timeout = scheduled_timeout; } } diff --git a/shared/n-dhcp4/src/n-dhcp4-incoming.c b/shared/n-dhcp4/src/n-dhcp4-incoming.c index 255da458..e7234c0a 100644 --- a/shared/n-dhcp4/src/n-dhcp4-incoming.c +++ b/shared/n-dhcp4/src/n-dhcp4-incoming.c @@ -365,10 +365,7 @@ static int n_dhcp4_incoming_query_u32(NDhcp4Incoming *message, uint8_t option, u memcpy(&be32, data, sizeof(be32)); - if (be32 == (uint32_t)-1) - *u32p = 0; - else - *u32p = ntohl(be32); + *u32p = ntohl(be32); return 0; } diff --git a/shared/n-dhcp4/src/n-dhcp4-private.h b/shared/n-dhcp4/src/n-dhcp4-private.h index c38ddbfc..1cf5f25e 100644 --- a/shared/n-dhcp4/src/n-dhcp4-private.h +++ b/shared/n-dhcp4/src/n-dhcp4-private.h @@ -11,6 +11,7 @@ #include <stdlib.h> #include <time.h> #include <unistd.h> +#include <syslog.h> #include "n-dhcp4.h" typedef struct NDhcp4CConnection NDhcp4CConnection; @@ -198,6 +199,8 @@ struct NDhcp4Outgoing { struct { uint8_t type; + uint8_t message_type; + uint32_t client_addr; uint64_t start_time; uint64_t base_time; uint64_t send_time; @@ -239,6 +242,11 @@ struct NDhcp4ClientConfig { size_t n_broadcast_mac; uint8_t *client_id; size_t n_client_id; + struct { + int level; + NDhcp4LogFunc func; + void *data; + } log; }; #define N_DHCP4_CLIENT_CONFIG_NULL(_x) { \ @@ -324,6 +332,7 @@ struct NDhcp4Client { uint64_t scheduled_timeout; bool preempted : 1; + bool timerfd_is_monotonic : 1; }; #define N_DHCP4_CLIENT_NULL(_x) { \ @@ -686,3 +695,19 @@ static inline uint64_t n_dhcp4_gettime(clockid_t clock) { return ts.tv_sec * 1000ULL * 1000ULL * 1000ULL + ts.tv_nsec; } + +#define n_dhcp4_c_log(_config, _level, ...) \ + do { \ + const NDhcp4ClientConfig *__config = _config; \ + \ + if (_level <= __config->log.level && __config->log.func) { \ + if (1) { \ + _config->log.func(_level, \ + __config->log.data, \ + __VA_ARGS__); \ + } else { \ + /* To have the compiler check arguments */ \ + printf(__VA_ARGS__); \ + } \ + } \ + } while (0) diff --git a/shared/n-dhcp4/src/n-dhcp4-socket.c b/shared/n-dhcp4/src/n-dhcp4-socket.c index b9ac176f..c7e89772 100644 --- a/shared/n-dhcp4/src/n-dhcp4-socket.c +++ b/shared/n-dhcp4/src/n-dhcp4-socket.c @@ -195,6 +195,10 @@ int n_dhcp4_c_socket_udp_new(int *sockfdp, if (sockfd < 0) return -errno; + r = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); + if (r < 0) + return -errno; + r = setsockopt(sockfd, SOL_SOCKET, SO_ATTACH_FILTER, &fprog, sizeof(fprog)); if (r < 0) return -errno; diff --git a/shared/n-dhcp4/src/n-dhcp4.h b/shared/n-dhcp4/src/n-dhcp4.h index ef75eca7..d3747662 100644 --- a/shared/n-dhcp4/src/n-dhcp4.h +++ b/shared/n-dhcp4/src/n-dhcp4.h @@ -29,6 +29,8 @@ typedef struct NDhcp4ServerEvent NDhcp4ServerEvent; typedef struct NDhcp4ServerIp NDhcp4ServerIp; typedef struct NDhcp4ServerLease NDhcp4ServerLease; +typedef void (*NDhcp4LogFunc)(int level, void *data, const char *fmt, ...); + #define N_DHCP4_CLIENT_START_DELAY_RFC2131 (UINT64_C(9000)) enum { @@ -111,6 +113,8 @@ void n_dhcp4_client_config_set_request_broadcast(NDhcp4ClientConfig *config, boo void n_dhcp4_client_config_set_mac(NDhcp4ClientConfig *config, const uint8_t *mac, size_t n_mac); void n_dhcp4_client_config_set_broadcast_mac(NDhcp4ClientConfig *config, const uint8_t *mac, size_t n_mac); int n_dhcp4_client_config_set_client_id(NDhcp4ClientConfig *config, const uint8_t *id, size_t n_id); +void n_dhcp4_client_config_set_log_level(NDhcp4ClientConfig *config, int level); +void n_dhcp4_client_config_set_log_func(NDhcp4ClientConfig *config, NDhcp4LogFunc func, void *data); /* client-probe configs */ @@ -157,6 +161,7 @@ NDhcp4ClientLease *n_dhcp4_client_lease_unref(NDhcp4ClientLease *lease); void n_dhcp4_client_lease_get_yiaddr(NDhcp4ClientLease *lease, struct in_addr *yiaddr); void n_dhcp4_client_lease_get_siaddr(NDhcp4ClientLease *lease, struct in_addr *siaddr); +void n_dhcp4_client_lease_get_basetime(NDhcp4ClientLease *lease, uint64_t *ns_basetimep); void n_dhcp4_client_lease_get_lifetime(NDhcp4ClientLease *lease, uint64_t *ns_lifetimep); int n_dhcp4_client_lease_query(NDhcp4ClientLease *lease, uint8_t option, uint8_t **datap, size_t *n_datap); |