@@ -303,6 +303,16 @@ static int dhcpc_sendmsg(FAR struct dhcpc_state_s *pdhcpc,
303303 serverid = presult -> serverid .s_addr ;
304304 break ;
305305
306+ /* Send RELEASE message to the server to relinquish the lease */
307+
308+ case DHCPRELEASE :
309+
310+ memcpy (pdhcpc -> packet .ciaddr , & presult -> ipaddr .s_addr , 4 );
311+ pend = dhcpc_addserverid (& presult -> serverid , pend );
312+ pend = dhcpc_addclientid (pdhcpc -> macaddr , pdhcpc -> maclen , pend );
313+ serverid = presult -> serverid .s_addr ;
314+ break ;
315+
306316 default :
307317 errno = EINVAL ;
308318 return ERROR ;
@@ -950,3 +960,104 @@ int dhcpc_request_async(FAR void *handle, dhcpc_callback_t callback)
950960
951961 return OK ;
952962}
963+
964+ /****************************************************************************
965+ * Name: dhcpc_release
966+ ****************************************************************************/
967+
968+ int dhcpc_release (FAR void * handle , FAR struct dhcpc_state * presult )
969+ {
970+ FAR struct dhcpc_state_s * pdhcpc = (FAR struct dhcpc_state_s * )handle ;
971+ int ret ;
972+ int retries = 0 ;
973+ #ifdef CONFIG_NETUTILS_DHCPC_RELEASE_CLEAR_IP
974+ struct in_addr zero_addr ;
975+ #endif
976+
977+ if (!handle || !presult )
978+ {
979+ errno = EINVAL ;
980+ return ERROR ;
981+ }
982+
983+ /* Check that we have valid IP address and server ID to release */
984+
985+ if (presult -> ipaddr .s_addr == 0 || presult -> serverid .s_addr == 0 )
986+ {
987+ errno = EINVAL ;
988+ return ERROR ;
989+ }
990+
991+ /* Increment transaction ID for the release message */
992+
993+ pdhcpc -> xid [3 ]++ ;
994+
995+ /* Send DHCPRELEASE message to the server with retry mechanism.
996+ * According to RFC 2131, no response is expected from the server.
997+ */
998+
999+ for (; ; )
1000+ {
1001+ ret = dhcpc_sendmsg (pdhcpc , presult , DHCPRELEASE );
1002+ if (ret > 0 )
1003+ {
1004+ ninfo ("DHCPRELEASE message sent successfully (%d bytes)\n" , ret );
1005+ break ;
1006+ }
1007+ else
1008+ {
1009+ retries ++ ;
1010+ nerr ("Failed send DHCPRELEASE (attempt %d/%d), ret=%d, errno=%d\n" ,
1011+ retries , CONFIG_NETUTILS_DHCPC_RELEASE_RETRIES , ret , errno );
1012+
1013+ if (retries >= CONFIG_NETUTILS_DHCPC_RELEASE_RETRIES )
1014+ {
1015+ nerr ("ERROR: Failed to send DHCPRELEASE after %d attempts\n" ,
1016+ CONFIG_NETUTILS_DHCPC_RELEASE_RETRIES );
1017+ return ERROR ;
1018+ }
1019+
1020+ usleep (1000 * CONFIG_NETUTILS_DHCPC_RELEASE_TRANSMISSION_DELAY_MS );
1021+ }
1022+ }
1023+
1024+ #ifdef CONFIG_NETUTILS_DHCPC_RELEASE_ENSURE_TRANSMISSION
1025+ /* Ensure the DHCPRELEASE packet has time to be transmitted.
1026+ * Since DHCP RELEASE has no ACK response and UDP is connectionless,
1027+ * we use a delay to give the network stack time to actually send
1028+ * the packet before the function returns.
1029+ */
1030+
1031+ usleep (1000 * CONFIG_NETUTILS_DHCPC_RELEASE_TRANSMISSION_DELAY_MS );
1032+ #endif
1033+
1034+ #ifdef CONFIG_NETUTILS_DHCPC_RELEASE_CLEAR_IP
1035+ /* Clear all network configuration that was obtained via DHCP */
1036+
1037+ zero_addr .s_addr = INADDR_ANY ;
1038+
1039+ ret = netlib_set_ipv4addr (pdhcpc -> interface , & zero_addr );
1040+ if (ret < 0 )
1041+ {
1042+ nwarn ("Warning: Failed clear IP address from interface (errno=%d)\n" ,
1043+ errno );
1044+ }
1045+
1046+ ret = netlib_set_ipv4netmask (pdhcpc -> interface , & zero_addr );
1047+ if (ret < 0 )
1048+ {
1049+ nwarn ("Warning: Failed clear netmask from interface (errno=%d)\n" ,
1050+ errno );
1051+ }
1052+
1053+ ret = netlib_set_dripv4addr (pdhcpc -> interface , & zero_addr );
1054+ if (ret < 0 )
1055+ {
1056+ nwarn ("Warning: Failed clear gateway from interface (errno=%d)\n" ,
1057+ errno );
1058+ }
1059+ #endif
1060+
1061+ ninfo ("DHCP released successfully\n" );
1062+ return OK ;
1063+ }
0 commit comments