diff options
| author | Sebastien Bacher <seb128@ubuntu.com> | 2020-05-19 16:38:36 +0200 |
|---|---|---|
| committer | Sebastien Bacher <seb128@ubuntu.com> | 2020-05-19 17:09:07 +0200 |
| commit | ccf6dc06bbee82c3d49f451545c5317337e0777e (patch) | |
| tree | a8fddc8c6e2b3b99bebab1d5bb2a64581eff4bfd /shared/n-dhcp4 | |
| parent | f109e55ef130ce84054d5ba3acf4b71cd8c7564a (diff) | |
| parent | 7ffed1e6136de75188f10ba8763bcb942f932f8e (diff) | |
Merge remote-tracking branch 'salsa/debian/master' into ubuntu/master
Diffstat (limited to 'shared/n-dhcp4')
| -rw-r--r-- | shared/n-dhcp4/src/n-dhcp4-c-connection.c | 29 | ||||
| -rw-r--r-- | shared/n-dhcp4/src/n-dhcp4-c-probe.c | 1 | ||||
| -rw-r--r-- | shared/n-dhcp4/src/n-dhcp4-client.c | 56 | ||||
| -rw-r--r-- | shared/n-dhcp4/src/n-dhcp4-private.h | 1 |
4 files changed, 50 insertions, 37 deletions
diff --git a/shared/n-dhcp4/src/n-dhcp4-c-connection.c b/shared/n-dhcp4/src/n-dhcp4-c-connection.c index a5c8ea66..30514e28 100644 --- a/shared/n-dhcp4/src/n-dhcp4-c-connection.c +++ b/shared/n-dhcp4/src/n-dhcp4-c-connection.c @@ -1136,6 +1136,13 @@ int n_dhcp4_c_connection_dispatch_timer(NDhcp4CConnection *connection, return 0; } +/* + * Returns: + * 0 on success + * N_DHCP4_E_MALFORMED if a malformed packet was received + * N_DHCP4_E_UNEXPECTED if the packet received contains unexpected data + * N_DHCP4_E_AGAIN if there was another error (non fatal for the client) + */ int n_dhcp4_c_connection_dispatch_io(NDhcp4CConnection *connection, NDhcp4Incoming **messagep) { _c_cleanup_(n_dhcp4_incoming_freep) NDhcp4Incoming *message = NULL; @@ -1150,10 +1157,11 @@ int n_dhcp4_c_connection_dispatch_io(NDhcp4CConnection *connection, connection->scratch_buffer, sizeof(connection->scratch_buffer), &message); - if (r) + if (!r) + break; + else if (r == N_DHCP4_E_MALFORMED) return r; - - break; + return N_DHCP4_E_AGAIN; case N_DHCP4_C_CONNECTION_STATE_DRAINING: r = n_dhcp4_c_socket_packet_recv(connection->fd_packet, connection->scratch_buffer, @@ -1161,8 +1169,10 @@ int n_dhcp4_c_connection_dispatch_io(NDhcp4CConnection *connection, &message); if (!r) break; - else if (r != N_DHCP4_E_AGAIN) + else if (r == N_DHCP4_E_MALFORMED) return r; + else if (r != N_DHCP4_E_AGAIN) + return N_DHCP4_E_AGAIN; /* * The UDP socket is open and the packet socket has been shut down @@ -1180,18 +1190,21 @@ int n_dhcp4_c_connection_dispatch_io(NDhcp4CConnection *connection, connection->scratch_buffer, sizeof(connection->scratch_buffer), &message); - if (r) + if (!r) + break; + else if (r == N_DHCP4_E_MALFORMED) return r; - - break; + return N_DHCP4_E_AGAIN; default: abort(); return -ENOTRECOVERABLE; } r = n_dhcp4_c_connection_verify_incoming(connection, message, &type); - if (r) + if (r == N_DHCP4_E_MALFORMED || r == N_DHCP4_E_UNEXPECTED) return r; + else if (r != 0) + return N_DHCP4_E_AGAIN; if (type == N_DHCP4_MESSAGE_OFFER || type == N_DHCP4_MESSAGE_ACK) { n_dhcp4_c_log(connection->client_config, LOG_INFO, diff --git a/shared/n-dhcp4/src/n-dhcp4-c-probe.c b/shared/n-dhcp4/src/n-dhcp4-c-probe.c index e4477a7c..5e971298 100644 --- a/shared/n-dhcp4/src/n-dhcp4-c-probe.c +++ b/shared/n-dhcp4/src/n-dhcp4-c-probe.c @@ -1242,6 +1242,7 @@ int n_dhcp4_client_probe_dispatch_io(NDhcp4ClientProbe *probe, uint32_t events) return 0; } + abort(); return r; } diff --git a/shared/n-dhcp4/src/n-dhcp4-client.c b/shared/n-dhcp4/src/n-dhcp4-client.c index 4fa3d65d..6b015e81 100644 --- a/shared/n-dhcp4/src/n-dhcp4-client.c +++ b/shared/n-dhcp4/src/n-dhcp4-client.c @@ -388,14 +388,10 @@ _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) { - if (errno != EINVAL) - return -errno; + if (client->fd_timer < 0 && errno == EINVAL) client->fd_timer = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); - if (client->fd_timer < 0) - return -errno; - client->timerfd_is_monotonic = true; - } + if (client->fd_timer < 0) + return -errno; ev.data.u32 = N_DHCP4_CLIENT_EPOLL_TIMER; r = epoll_ctl(client->fd_epoll, EPOLL_CTL_ADD, client->fd_timer, &ev); @@ -498,41 +494,45 @@ int n_dhcp4_client_raise(NDhcp4Client *client, NDhcp4CEventNode **nodep, unsigne * must be called whenever a timeout on @client might have changed. */ void n_dhcp4_client_arm_timer(NDhcp4Client *client) { - uint64_t timeout = 0; + uint64_t now, offset, timeout = 0; int r; if (client->current_probe) 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; - } + /* + * Across our codebase, timeouts are specified as absolute + * timestamps on CLOCK_BOOTTIME. Unfortunately, there are + * systems with CLOCK_BOOTTIME support, but timerfd lacks it + * (in particular RHEL). Therefore, our timerfd might be on + * CLOCK_MONOTONIC. + * To account for this, we always schedule a relative timeout. + * We fetch the current time and then calculate the offset + * which we then schedule as relative timeout on the timerfd. + * This works regardless which clock the timerfd runs on. + * Once we no longer support CLOCK_MONOTONIC as fallback, we + * can simply switch to TFD_TIMER_ABSTIME here and specify + * `timeout` directly as value. + */ + now = n_dhcp4_gettime(CLOCK_BOOTTIME); + if (now >= timeout) + offset = 1; /* 0 would disarm the timerfd */ + else + offset = timeout - now; + r = timerfd_settime(client->fd_timer, - flags, + 0, &(struct itimerspec){ .it_value = { - .tv_sec = timeout / UINT64_C(1000000000), - .tv_nsec = timeout % UINT64_C(1000000000), + .tv_sec = offset / UINT64_C(1000000000), + .tv_nsec = offset % UINT64_C(1000000000), }, }, NULL); c_assert(r >= 0); - client->scheduled_timeout = scheduled_timeout; + client->scheduled_timeout = timeout; } } diff --git a/shared/n-dhcp4/src/n-dhcp4-private.h b/shared/n-dhcp4/src/n-dhcp4-private.h index f647cb5e..e285d95d 100644 --- a/shared/n-dhcp4/src/n-dhcp4-private.h +++ b/shared/n-dhcp4/src/n-dhcp4-private.h @@ -332,7 +332,6 @@ struct NDhcp4Client { uint64_t scheduled_timeout; bool preempted : 1; - bool timerfd_is_monotonic : 1; }; #define N_DHCP4_CLIENT_NULL(_x) { \ |