2121#include "hexdecoct.h"
2222#include "hostname-util.h"
2323#include "in-addr-util.h"
24+ #include "io-util.h"
2425#include "network-common.h"
2526#include "random-util.h"
2627#include "socket-util.h"
@@ -1341,13 +1342,14 @@ static int client_parse_message(
13411342 return 0 ;
13421343}
13431344
1344- static int client_receive_reply (sd_dhcp6_client * client , DHCP6Message * reply , size_t len ) {
1345+ static int client_receive_reply (sd_dhcp6_client * client , DHCP6Message * reply , size_t len , const triple_timestamp * t ) {
13451346 _cleanup_ (sd_dhcp6_lease_unrefp ) sd_dhcp6_lease * lease = NULL ;
13461347 bool rapid_commit ;
13471348 int r ;
13481349
13491350 assert (client );
13501351 assert (reply );
1352+ assert (t );
13511353
13521354 if (reply -> type != DHCP6_MESSAGE_REPLY )
13531355 return 0 ;
@@ -1356,6 +1358,8 @@ static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply, si
13561358 if (r < 0 )
13571359 return - ENOMEM ;
13581360
1361+ lease -> timestamp = * t ;
1362+
13591363 r = client_parse_message (client , reply , len , lease );
13601364 if (r < 0 )
13611365 return r ;
@@ -1375,18 +1379,24 @@ static int client_receive_reply(sd_dhcp6_client *client, DHCP6Message *reply, si
13751379 return DHCP6_STATE_BOUND ;
13761380}
13771381
1378- static int client_receive_advertise (sd_dhcp6_client * client , DHCP6Message * advertise , size_t len ) {
1382+ static int client_receive_advertise (sd_dhcp6_client * client , DHCP6Message * advertise , size_t len , const triple_timestamp * t ) {
13791383 _cleanup_ (sd_dhcp6_lease_unrefp ) sd_dhcp6_lease * lease = NULL ;
13801384 uint8_t pref_advertise = 0 , pref_lease = 0 ;
13811385 int r ;
13821386
1387+ assert (client );
1388+ assert (advertise );
1389+ assert (t );
1390+
13831391 if (advertise -> type != DHCP6_MESSAGE_ADVERTISE )
13841392 return 0 ;
13851393
13861394 r = dhcp6_lease_new (& lease );
13871395 if (r < 0 )
13881396 return r ;
13891397
1398+ lease -> timestamp = * t ;
1399+
13901400 r = client_parse_message (client , advertise , len , lease );
13911401 if (r < 0 )
13921402 return r ;
@@ -1417,6 +1427,17 @@ static int client_receive_message(
14171427
14181428 sd_dhcp6_client * client = userdata ;
14191429 DHCP6_CLIENT_DONT_DESTROY (client );
1430+ /* This needs to be initialized with zero. See #20741. */
1431+ CMSG_BUFFER_TYPE (CMSG_SPACE_TIMEVAL ) control = {};
1432+ struct iovec iov ;
1433+ struct msghdr msg = {
1434+ .msg_iov = & iov ,
1435+ .msg_iovlen = 1 ,
1436+ .msg_control = & control ,
1437+ .msg_controllen = sizeof (control ),
1438+ };
1439+ struct cmsghdr * cmsg ;
1440+ triple_timestamp t = {};
14201441 _cleanup_free_ DHCP6Message * message = NULL ;
14211442 ssize_t buflen , len ;
14221443 int r = 0 ;
@@ -1427,9 +1448,8 @@ static int client_receive_message(
14271448
14281449 buflen = next_datagram_size_fd (fd );
14291450 if (buflen == - ENETDOWN )
1430- /* the link is down. Don't return an error or the I/O event
1431- source will be disconnected and we won't be able to receive
1432- packets again when the link comes back. */
1451+ /* the link is down. Don't return an error or the I/O event source will be disconnected
1452+ * and we won't be able to receive packets again when the link comes back. */
14331453 return 0 ;
14341454 if (buflen < 0 )
14351455 return buflen ;
@@ -1438,7 +1458,9 @@ static int client_receive_message(
14381458 if (!message )
14391459 return - ENOMEM ;
14401460
1441- len = recv (fd , message , buflen , 0 );
1461+ iov = IOVEC_MAKE (message , buflen );
1462+
1463+ len = recvmsg_safe (fd , & msg , MSG_DONTWAIT );
14421464 if (len < 0 ) {
14431465 /* see comment above for why we shouldn't error out on ENETDOWN. */
14441466 if (IN_SET (errno , EAGAIN , EINTR , ENETDOWN ))
@@ -1452,6 +1474,16 @@ static int client_receive_message(
14521474 return 0 ;
14531475 }
14541476
1477+ CMSG_FOREACH (cmsg , & msg ) {
1478+ if (cmsg -> cmsg_level == SOL_SOCKET &&
1479+ cmsg -> cmsg_type == SO_TIMESTAMP &&
1480+ cmsg -> cmsg_len == CMSG_LEN (sizeof (struct timeval )))
1481+ triple_timestamp_from_realtime (& t , timeval_load ((struct timeval * ) CMSG_DATA (cmsg )));
1482+ }
1483+
1484+ if (!triple_timestamp_is_set (& t ))
1485+ triple_timestamp_get (& t );
1486+
14551487 if (!IN_SET (message -> type , DHCP6_MESSAGE_ADVERTISE , DHCP6_MESSAGE_REPLY , DHCP6_MESSAGE_RECONFIGURE )) {
14561488 const char * type_str = dhcp6_message_type_to_string (message -> type );
14571489 if (type_str )
@@ -1466,7 +1498,7 @@ static int client_receive_message(
14661498
14671499 switch (client -> state ) {
14681500 case DHCP6_STATE_INFORMATION_REQUEST :
1469- r = client_receive_reply (client , message , len );
1501+ r = client_receive_reply (client , message , len , & t );
14701502 if (r < 0 ) {
14711503 log_dhcp6_client_errno (client , r , "Failed to process received reply message, ignoring: %m" );
14721504 return 0 ;
@@ -1479,7 +1511,7 @@ static int client_receive_message(
14791511 break ;
14801512
14811513 case DHCP6_STATE_SOLICITATION :
1482- r = client_receive_advertise (client , message , len );
1514+ r = client_receive_advertise (client , message , len , & t );
14831515 if (r < 0 ) {
14841516 log_dhcp6_client_errno (client , r , "Failed to process received advertise message, ignoring: %m" );
14851517 return 0 ;
@@ -1495,7 +1527,7 @@ static int client_receive_message(
14951527 case DHCP6_STATE_RENEW :
14961528 case DHCP6_STATE_REBIND :
14971529
1498- r = client_receive_reply (client , message , len );
1530+ r = client_receive_reply (client , message , len , & t );
14991531 if (r < 0 ) {
15001532 log_dhcp6_client_errno (client , r , "Failed to process received reply message, ignoring: %m" );
15011533 return 0 ;
0 commit comments