@@ -976,6 +976,7 @@ static int wolfIP_filter_notify_icmp(enum wolfIP_filter_reason reason,
976976#define DHCP_OFFER 2
977977#define DHCP_REQUEST 3
978978#define DHCP_ACK 5
979+ #define DHCP_NAK 6
979980
980981#define DHCP_MAGIC 0x63825363
981982#define DHCP_SERVER_PORT 67
@@ -5387,6 +5388,42 @@ static int dhcp_parse_offer(struct wolfIP *s, struct dhcp_msg *msg, uint32_t msg
53875388}
53885389
53895390
5391+ /* Return the DHCP message type from a validated message, or -1 on error. */
5392+ static int dhcp_msg_type (struct wolfIP * s , struct dhcp_msg * msg , uint32_t msg_len )
5393+ {
5394+ uint8_t * opt = (uint8_t * )msg -> options ;
5395+ uint8_t * opt_end ;
5396+ if (msg_len < DHCP_HEADER_LEN )
5397+ return -1 ;
5398+ if (ee32 (msg -> magic ) != DHCP_MAGIC )
5399+ return -1 ;
5400+ if (ee32 (msg -> xid ) != s -> dhcp_xid )
5401+ return -1 ;
5402+ if (msg_len - DHCP_HEADER_LEN > sizeof (msg -> options ))
5403+ opt_end = (uint8_t * )msg -> options + sizeof (msg -> options );
5404+ else
5405+ opt_end = (uint8_t * )msg -> options + (msg_len - DHCP_HEADER_LEN );
5406+ while (opt < opt_end ) {
5407+ uint8_t code = opt [0 ];
5408+ uint8_t len ;
5409+ if (code == DHCP_OPTION_END )
5410+ break ;
5411+ if (code == 0 ) {
5412+ opt ++ ;
5413+ continue ;
5414+ }
5415+ if (opt + 2 > opt_end )
5416+ break ;
5417+ len = opt [1 ];
5418+ if (opt + 2 + len > opt_end )
5419+ break ;
5420+ if (code == DHCP_OPTION_MSG_TYPE && len == 1 )
5421+ return opt [2 ];
5422+ opt += 2 + len ;
5423+ }
5424+ return -1 ;
5425+ }
5426+
53905427static int dhcp_parse_ack (struct wolfIP * s , struct dhcp_msg * msg , uint32_t msg_len )
53915428{
53925429 uint8_t * opt = (uint8_t * )msg -> options ;
@@ -5520,19 +5557,28 @@ static int dhcp_poll(struct wolfIP *s)
55205557 return -1 ;
55215558 if ((s -> dhcp_state == DHCP_DISCOVER_SENT ) && (dhcp_parse_offer (s , & msg , (uint32_t )len ) == 0 ))
55225559 dhcp_send_request (s );
5523- else if (( s -> dhcp_state == DHCP_REQUEST_SENT ||
5560+ else if (s -> dhcp_state == DHCP_REQUEST_SENT ||
55245561 s -> dhcp_state == DHCP_RENEWING ||
5525- s -> dhcp_state == DHCP_REBINDING ) &&
5526- (dhcp_parse_ack (s , & msg , (uint32_t )len ) == 0 )) {
5527- struct ipconf * primary = wolfIP_primary_ipconf (s );
5528- LOG ("DHCP configuration received.\n" );
5529- if (primary ) {
5530- LOG ("IP Address: %u.%u.%u.%u\n" , (unsigned int )((primary -> ip >> 24 ) & 0xFF ), (unsigned int )((primary -> ip >> 16 ) & 0xFF ), (unsigned int )((primary -> ip >> 8 ) & 0xFF ), (unsigned int )((primary -> ip >> 0 ) & 0xFF ));
5531- LOG ("Subnet Mask: %u.%u.%u.%u\n" , (unsigned int )((primary -> mask >> 24 ) & 0xFF ), (unsigned int )((primary -> mask >> 16 ) & 0xFF ), (unsigned int )((primary -> mask >> 8 ) & 0xFF ), (unsigned int )((primary -> mask >> 0 ) & 0xFF ));
5532- LOG ("Gateway: %u.%u.%u.%u\n" , (unsigned int )((primary -> gw >> 24 ) & 0xFF ), (unsigned int )((primary -> gw >> 16 ) & 0xFF ), (unsigned int )((primary -> gw >> 8 ) & 0xFF ), (unsigned int )((primary -> gw >> 0 ) & 0xFF ));
5533- }
5534- if (s -> dns_server )
5535- LOG ("DNS Server: %u.%u.%u.%u\n" , (unsigned int )((s -> dns_server >> 24 ) & 0xFF ), (unsigned int )((s -> dns_server >> 16 ) & 0xFF ), (unsigned int )((s -> dns_server >> 8 ) & 0xFF ), (unsigned int )((s -> dns_server >> 0 ) & 0xFF ));
5562+ s -> dhcp_state == DHCP_REBINDING ) {
5563+ /* RFC 2131 s4.4.1: if the client receives a DHCPNAK,
5564+ * it must restart the configuration process. */
5565+ if (dhcp_msg_type (s , & msg , (uint32_t )len ) == DHCP_NAK ) {
5566+ dhcp_cancel_timer (s );
5567+ s -> dhcp_state = DHCP_OFF ;
5568+ dhcp_send_discover (s );
5569+ return 0 ;
5570+ }
5571+ if (dhcp_parse_ack (s , & msg , (uint32_t )len ) == 0 ) {
5572+ struct ipconf * primary = wolfIP_primary_ipconf (s );
5573+ LOG ("DHCP configuration received.\n" );
5574+ if (primary ) {
5575+ LOG ("IP Address: %u.%u.%u.%u\n" , (unsigned int )((primary -> ip >> 24 ) & 0xFF ), (unsigned int )((primary -> ip >> 16 ) & 0xFF ), (unsigned int )((primary -> ip >> 8 ) & 0xFF ), (unsigned int )((primary -> ip >> 0 ) & 0xFF ));
5576+ LOG ("Subnet Mask: %u.%u.%u.%u\n" , (unsigned int )((primary -> mask >> 24 ) & 0xFF ), (unsigned int )((primary -> mask >> 16 ) & 0xFF ), (unsigned int )((primary -> mask >> 8 ) & 0xFF ), (unsigned int )((primary -> mask >> 0 ) & 0xFF ));
5577+ LOG ("Gateway: %u.%u.%u.%u\n" , (unsigned int )((primary -> gw >> 24 ) & 0xFF ), (unsigned int )((primary -> gw >> 16 ) & 0xFF ), (unsigned int )((primary -> gw >> 8 ) & 0xFF ), (unsigned int )((primary -> gw >> 0 ) & 0xFF ));
5578+ }
5579+ if (s -> dns_server )
5580+ LOG ("DNS Server: %u.%u.%u.%u\n" , (unsigned int )((s -> dns_server >> 24 ) & 0xFF ), (unsigned int )((s -> dns_server >> 16 ) & 0xFF ), (unsigned int )((s -> dns_server >> 8 ) & 0xFF ), (unsigned int )((s -> dns_server >> 0 ) & 0xFF ));
5581+ }
55365582 }
55375583 return 0 ;
55385584}
0 commit comments