Files
w5500-eth/Internet/DHCP6/dhcpv6.c
2025-12-10 17:55:05 +03:00

1220 lines
36 KiB
C

//*****************************************************************************
//
//! \file dhcpv6.c
//! \brief DHCPv6 APIs implement file.
//! \details Processig DHCPv6 protocol as SOLICIT, ADVERTISE.
//! \version 0.0.1
//! \date 2016/06/08
//! \par Revision history
//! <2016/07/18> 1st Release
//! \author JustinKim
//! \copyright
//!
//! Copyright (c) 2016, WIZnet Co., LTD.
//! All rights reserved.
//!
//! Redistribution and use in source and binary forms, with or without
//! modification, are permitted provided that the following conditions
//! are met:
//!
//! * Redistributions of source code must retain the above copyright
//! notice, this list of conditions and the following disclaimer.
//! * Redistributions in binary form must reproduce the above copyright
//! notice, this list of conditions and the following disclaimer in the
//! documentation and/or other materials provided with the distribution.
//! * Neither the name of the <ORGANIZATION> nor the names of its
//! contributors may be used to endorse or promote products derived
//! from this software without specific prior written permission.
//!
//! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
//! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
//! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
//! ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
//! LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
//! CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
//! SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
//! INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
//! CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
//! ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
//! THE POSSIBILITY OF SUCH DAMAGE.
//
//*****************************************************************************
#include "dhcpv6.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#if (_WIZCHIP_ == W6100)
/* If you want to display debug & procssing message, Define _DHCP6_DEBUG_ in dhcpv6.h */
#define _DHCP6_DEBUG_
#ifdef _DHCP6_DEBUG_
#include <stdio.h>
#endif
/* DHCP6 state machine. */
#define STATE_DHCP6_INIT 0 ///< Initialize
#define STATE_DHCP6_SOLICIT 1 ///< send DISCOVER and wait OFFER
#define STATE_DHCP6_REQUEST 2 ///< send REQEUST and wait ACK or NACK
#define STATE_DHCP6_LEASED 3 ///< ReceiveD ACK and IP leased
#define STATE_DHCP6_REREQUEST 4 ///< send REQUEST for maintaining leased IP
#define STATE_DHCP6_RELEASE 5 ///< No use
#define STATE_DHCP6_STOP 6 ///< Stop procssing DHCPv6
/* DHCP6 message type */
#define DHCP6_SOLICIT 1 ///< DISCOVER message in OPT of @ref RIP_MSG
#define DHCP6_ADVERTISE 2 ///< OFFER message in OPT of @ref RIP_MSG
#define DHCP6_REQUEST 3 ///< REQUEST message in OPT of @ref RIP_MSG
#define DHCP6_CONFIRM 4 ///< DECLINE message in OPT of @ref RIP_MSG
#define DHCP6_RENEW 5 ///< ACK message in OPT of @ref RIP_MSG
#define DHCP6_REBIND 6 ///< NACK message in OPT of @ref RIP_MSG
#define DHCP6_REPLY 7 ///< RELEASE message in OPT of @ref RIP_MSG. No use
#define DHCP6_RELEASE 8 ///< INFORM message in OPT of @ref RIP_MSG. No use
#define DHCP6_DECLINE 9 ///< INFORM message in OPT of @ref RIP_MSG. No use
#define DHCP6_RECONFIGURE 10 ///< INFORM message in OPT of @ref RIP_MSG. No use
#define DHCP6_INFO_REQUEST 11 ///< INFORM message in OPT of @ref RIP_MSG. No use
uint8_t DNS6_Address[16] = {
0,
};
//todo
/*
@brief DHCPv6 option (cf. RFC3315)
*/
enum {
OPT_CLIENTID = 1,
OPT_SERVERID = 2,
OPT_IANA = 3,
OPT_IATA = 4,
OPT_IAADDR = 5,
OPT_REQUEST = 6,
OPT_PREFERENCE = 7,
OPT_ELAPSED_TIME = 8,
OPT_RELAY_MSG = 9,
OPT_AUTH = 11,
OPT_UNICAST = 12,
OPT_STATUS_CODE = 13,
OPT_RAPID_COMMIT = 14,
OPT_USER_CLASS = 15,
OPT_VENDOR_CLASS = 16,
OPT_VENDOR_OPTS = 17,
OPT_INTERFACE_ID = 18,
OPT_RECONF_MSG = 19,
OPT_RECONF_ACCEPT = 20,
SIP_Server_DNL = 21,
SIP_Server_V6ADDR = 22,
DNS_RecursiveNameServer = 23,
Domain_Search_List = 24,
OPT_IAPD = 25,
OPT_IAPREFIX = 26,
OPT_NIS_SERVERS = 27,
OPT_NISP_SERVERS = 28,
OPT_NIS_DOMAIN_NAME = 29,
OPT_NISP_DOMAIN_NAME = 30,
OPT_LIFETIME = 32,
FQ_DOMAIN_NAME = 39
};
/*
@brief DHCPv6 message format
*/
typedef struct {
uint8_t *OPT; ///< Option
} __attribute__((packed)) RIP_MSG;
uint8_t DHCP6_SOCKET; // Socket number for DHCPv6
// Network information from DHCPv6 Server
uint8_t DHCP6_allocated_ip[16] = {
0,
}; // IP address from DHCPv6
int8_t dhcp6_state = STATE_DHCP6_INIT; // DHCPv6 state
int8_t dhcp6_retry_count = 0;
volatile uint32_t dhcp6_tick_1s = 0; // unit 1 second
uint32_t dhcp6_tick_next = DHCP6_WAIT_TIME;
uint32_t DHCP6_XID; // Any number
RIP_MSG pDHCP6MSG; // Buffer pointer for DHCPv6 processing
uint8_t HOST_NAME6[] = DCHP6_HOST_NAME;
uint8_t DHCP6_CHADDR[6]; // DHCPv6 Client MAC address.
uint16_t DUID_type_s;
uint16_t Hardware_type_s;
uint8_t Time_s[4];
uint32_t Enterprise_num_s;
uint8_t Server_MAC[6];
uint8_t recv_IP[16];
uint32_t PreLifeTime;
uint32_t ValidLifeTime;
uint16_t code;
uint8_t IAID[4];
uint8_t T1[4];
uint8_t T2[4];
uint16_t iana_len;
uint16_t iaaddr_len;
uint16_t statuscode_len;
uint16_t Lstatuscode_len;
uint16_t serverid_len;
uint16_t clientid_len;
uint8_t status_msg[] = "";
unsigned size;
unsigned num;
unsigned num2 = 0;
unsigned growby;
/**
@brief
@param asize
@param agrowby
*/
void InitDhcp6Option(unsigned asize, unsigned agrowby) {
size = asize;
growby = agrowby;
num = 0;
}
/**
@brief
@param value
*/
void AppendDhcp6Option(uint8_t value) {
uint32_t need;
need = num + 1;
if (need > size) {
size++;
}
pDHCP6MSG.OPT[num] = value;
num++;
}
/**
@brief
@param sMark
*/
void DumpDhcp6Option(char *sMark) {
unsigned i;
printf("%20s => size=%02d,num=%02d : ", sMark, size, num);
for (i = num2; i < num; i++) {
printf("%.2x ", pDHCP6MSG.OPT[i]);
}
printf("\r\n");
num2 = num;
}
/**
@brief
@param option
*/
void DHCP6_Option_Select(uint8_t option) {
switch (option)
case OPT_CLIENTID:
case OPT_SERVERID:
case OPT_IANA:
case OPT_IATA:
case OPT_IAADDR:
case OPT_REQUEST:
case OPT_PREFERENCE:
case OPT_ELAPSED_TIME:
case OPT_RELAY_MSG:
case OPT_AUTH:
case OPT_UNICAST:
case OPT_STATUS_CODE:
case OPT_RAPID_COMMIT:
case OPT_USER_CLASS:
case OPT_VENDOR_CLASS:
case OPT_VENDOR_OPTS:
case OPT_INTERFACE_ID:
case OPT_RECONF_MSG:
case OPT_RECONF_ACCEPT:
case SIP_Server_DNL:
case SIP_Server_V6ADDR:
case DNS_RecursiveNameServer:
case Domain_Search_List:
case OPT_IAPD:
case OPT_IAPREFIX:
case OPT_NIS_SERVERS:
case OPT_NISP_SERVERS:
case OPT_NIS_DOMAIN_NAME:
case OPT_NISP_DOMAIN_NAME:
case FQ_DOMAIN_NAME:
break;
}
/**
@brief
*/
void send_DHCP6_SOLICIT(void) {
uint16_t j;
uint8_t ip[16];
uint8_t rip_msg_size;
size = 0;
num = 0;
growby = 0;
InitDhcp6Option(34, 1);
DumpDhcp6Option("option init");
AppendDhcp6Option(DHCP6_SOLICIT);
AppendDhcp6Option((uint8_t)((DHCP6_XID & 0x00FF0000) >> 16));
AppendDhcp6Option((uint8_t)((DHCP6_XID & 0x00FF0000) >> 8));
AppendDhcp6Option((uint8_t)((DHCP6_XID & 0x00FF0000) >> 0));
DumpDhcp6Option("Type&XID");
// Elapsed time
// AppendDhcp6Option(0x00);AppendDhcp6Option(OPT_ELAPSED_TIME);
// AppendDhcp6Option(0x00);AppendDhcp6Option(0x02);
// AppendDhcp6Option(0x0c);AppendDhcp6Option(0x1c);DumpDhcp6Option("Option Elapsed Time");
// Client Identifier
AppendDhcp6Option(0x00);
AppendDhcp6Option(OPT_CLIENTID);
AppendDhcp6Option(0x00);
AppendDhcp6Option(0x0a); //length
AppendDhcp6Option(0x00);
AppendDhcp6Option(0x03); //DUID_Type
AppendDhcp6Option(0x00);
AppendDhcp6Option(0x01); //Hard_Type
AppendDhcp6Option(DHCP6_CHADDR[0]);
AppendDhcp6Option(DHCP6_CHADDR[1]); // MAC Addr
AppendDhcp6Option(DHCP6_CHADDR[2]);
AppendDhcp6Option(DHCP6_CHADDR[3]);
AppendDhcp6Option(DHCP6_CHADDR[4]);
AppendDhcp6Option(DHCP6_CHADDR[5]);
DumpDhcp6Option("Option Client ID");
// Identity Association for Non-temporary Address
AppendDhcp6Option(0x00);
AppendDhcp6Option(OPT_IANA);
AppendDhcp6Option(0x00);
AppendDhcp6Option(0x0c); // length
AppendDhcp6Option(0x03);
AppendDhcp6Option(0x00); // IAID
AppendDhcp6Option(0x08);
AppendDhcp6Option(0xdc);
AppendDhcp6Option(0x00);
AppendDhcp6Option(0x00); // T1
AppendDhcp6Option(0x00);
AppendDhcp6Option(0x00);
AppendDhcp6Option(0x00);
AppendDhcp6Option(0x00); // T2
AppendDhcp6Option(0x00);
AppendDhcp6Option(0x00);
DumpDhcp6Option("Option IANA");
// Fully Qualified Domain Name
// AppendDhcp6Option(0x00);AppendDhcp6Option(39);
// AppendDhcp6Option(0x00);AppendDhcp6Option(0x06); // length
// AppendDhcp6Option(0x00);AppendDhcp6Option(0x04);
// AppendDhcp6Option(0x44);AppendDhcp6Option(0x45);
// AppendDhcp6Option(0x44);AppendDhcp6Option(0x59);DumpDhcp6Option("Option FQ Domain Name");
// Vendor Class
// AppendDhcp6Option(0x00);AppendDhcp6Option(16);
// AppendDhcp6Option(0x00);AppendDhcp6Option(0x0e); // length
// AppendDhcp6Option(0x00);AppendDhcp6Option(0x00);
// AppendDhcp6Option(0x01);AppendDhcp6Option(0x37);
// AppendDhcp6Option(0x00);AppendDhcp6Option(0x08);
// AppendDhcp6Option(0x4d);AppendDhcp6Option(0x53);
// AppendDhcp6Option(0x46);AppendDhcp6Option(0x54);
// AppendDhcp6Option(0x20);AppendDhcp6Option(0x35);
// AppendDhcp6Option(0x2e);AppendDhcp6Option(0x30);DumpDhcp6Option("Option Vendor Class");
// Option Request
// AppendDhcp6Option(0x00);AppendDhcp6Option(OPT_REQUEST);
// AppendDhcp6Option(0x00);AppendDhcp6Option(0x08); // length
// AppendDhcp6Option(0x00);AppendDhcp6Option(OPT_VENDOR_OPTS);
// AppendDhcp6Option(0x00);AppendDhcp6Option(DNS_RecursiveNameServer);
// AppendDhcp6Option(0x00);AppendDhcp6Option(Domain_Search_List);
// AppendDhcp6Option(0x00);AppendDhcp6Option(FQ_DOMAIN_NAME);DumpDhcp6Option("Option Request");
// send broadcasting packet
ip[0] = 0xff;
ip[1] = 0x02;
for (j = 2; j < 13; j++) {
ip[j] = 0x00;
}
ip[13] = 0x01;
ip[14] = 0x00;
ip[15] = 0x02;
rip_msg_size = size;
#ifdef _DHCP_DEBUG_
printf("> Send DHCP_DISCOVER\r\n");
#endif
sendto(DHCP6_SOCKET, (uint8_t *)pDHCP6MSG.OPT, rip_msg_size, ip, DHCP6_SERVER_PORT, 16);
#ifdef _DHCP_DEBUG_
printf("> %d, %d\r\n", ret, rip_msg_size);
#endif
//return ret
}
/**
@brief
@return uint8_t
*/
uint8_t send_DHCP6_REQUEST(void) {
//uint16_t i;
uint16_t j;
uint8_t ip[16];
uint8_t rip_msg_size;
uint8_t ret = 1;
size = 0;
num = 0;
growby = 0;
if (iana_len == 0) {
return 9;
}
printf("req : %x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x \r\n", recv_IP[0], recv_IP[1], recv_IP[2], recv_IP[3], recv_IP[4], recv_IP[5], recv_IP[6], recv_IP[7], recv_IP[8], recv_IP[9], recv_IP[10], recv_IP[11], recv_IP[12], recv_IP[13], recv_IP[14], recv_IP[15]);
InitDhcp6Option(60, 1);
DumpDhcp6Option("option init");
AppendDhcp6Option(DHCP6_REQUEST);
AppendDhcp6Option((uint8_t)((DHCP6_XID & 0x00FF0000) >> 16));
AppendDhcp6Option((uint8_t)((DHCP6_XID & 0x0000FF00) >> 8));
AppendDhcp6Option((uint8_t)((DHCP6_XID & 0x000000FF) >> 0));
DumpDhcp6Option("Type&XID");
// Elapsed time
//AppendDhcp6Option(0x00);AppendDhcp6Option(OPT_ELAPSED_TIME);
//AppendDhcp6Option(0x00);AppendDhcp6Option(0x02);
//AppendDhcp6Option(0x0c);AppendDhcp6Option(0x1c);DumpDhcp6Option("Option Elapsed Time");
// Identity Association for Non-temporary Address
AppendDhcp6Option(0x00);
AppendDhcp6Option(OPT_IANA);
AppendDhcp6Option((uint8_t)(iana_len >> 8));
AppendDhcp6Option((uint8_t)iana_len); // length
AppendDhcp6Option(IAID[0]);
AppendDhcp6Option(IAID[1]); // IAID
AppendDhcp6Option(IAID[2]);
AppendDhcp6Option(IAID[3]);
AppendDhcp6Option(T1[0]);
AppendDhcp6Option(T1[1]); // T1
AppendDhcp6Option(T1[2]);
AppendDhcp6Option(T1[3]);
AppendDhcp6Option(T2[0]);
AppendDhcp6Option(T2[1]); // T2
AppendDhcp6Option(T2[2]);
AppendDhcp6Option(T2[3]);
DumpDhcp6Option("Option IANA");
// IA Address
AppendDhcp6Option(0x00);
AppendDhcp6Option(OPT_IAADDR);
AppendDhcp6Option((uint8_t)(iaaddr_len >> 8));
AppendDhcp6Option((uint8_t)iaaddr_len); // length
AppendDhcp6Option(recv_IP[0]);
AppendDhcp6Option(recv_IP[1]); // IP
AppendDhcp6Option(recv_IP[2]);
AppendDhcp6Option(recv_IP[3]);
AppendDhcp6Option(recv_IP[4]);
AppendDhcp6Option(recv_IP[5]);
AppendDhcp6Option(recv_IP[6]);
AppendDhcp6Option(recv_IP[7]);
AppendDhcp6Option(recv_IP[8]);
AppendDhcp6Option(recv_IP[9]);
AppendDhcp6Option(recv_IP[10]);
AppendDhcp6Option(recv_IP[11]);
AppendDhcp6Option(recv_IP[12]);
AppendDhcp6Option(recv_IP[13]);
AppendDhcp6Option(recv_IP[14]);
AppendDhcp6Option(recv_IP[15]);
AppendDhcp6Option((uint8_t)(PreLifeTime >> 24));
AppendDhcp6Option((uint8_t)(PreLifeTime >> 16));
AppendDhcp6Option((uint8_t)(PreLifeTime >> 8));
AppendDhcp6Option((uint8_t)PreLifeTime);
AppendDhcp6Option((uint8_t)(ValidLifeTime >> 24));
AppendDhcp6Option((uint8_t)(ValidLifeTime >> 16));
AppendDhcp6Option((uint8_t)(ValidLifeTime >> 8));
AppendDhcp6Option((uint8_t)ValidLifeTime);
DumpDhcp6Option("Option IA_addr");
// Status code
#if 0
// 20190318
AppendDhcp6Option(0x00); AppendDhcp6Option(OPT_STATUS_CODE); DumpDhcp6Option("Option status_code type");
AppendDhcp6Option((uint8_t)(Lstatuscode_len >> 8)); AppendDhcp6Option((uint8_t)Lstatuscode_len); DumpDhcp6Option("Option status_code length"); // length
AppendDhcp6Option((uint8_t)(code >> 8)); AppendDhcp6Option((uint8_t)code); DumpDhcp6Option("Option status_code code"); // code
#endif
// for(i=0; i<(statuscode_len-2); i++)
// AppendDhcp6Option(status_msg[i]);
// DumpDhcp6Option("Option status_code msg");
#if 0
// 20190318
AppendDhcp6Option(0x41); AppendDhcp6Option(0x73);
AppendDhcp6Option(0x73); AppendDhcp6Option(0x69);
AppendDhcp6Option(0x67); AppendDhcp6Option(0x6e);
AppendDhcp6Option(0x65); AppendDhcp6Option(0x64);
AppendDhcp6Option(0x20); AppendDhcp6Option(0x61);
AppendDhcp6Option(0x6e); AppendDhcp6Option(0x20);
AppendDhcp6Option(0x61); AppendDhcp6Option(0x64);
AppendDhcp6Option(0x64); AppendDhcp6Option(0x72);
AppendDhcp6Option(0x65); AppendDhcp6Option(0x73);
AppendDhcp6Option(0x73); AppendDhcp6Option(0x2e);
#endif
// Client Identifier
AppendDhcp6Option(0x00);
AppendDhcp6Option(OPT_CLIENTID);
AppendDhcp6Option(0x00);
AppendDhcp6Option(0x0a); //length
AppendDhcp6Option(0x00);
AppendDhcp6Option(0x03); //DUID_Type
AppendDhcp6Option(0x00);
AppendDhcp6Option(0x01); //Hard_Type
AppendDhcp6Option(DHCP6_CHADDR[0]);
AppendDhcp6Option(DHCP6_CHADDR[1]); // MAC Addr
AppendDhcp6Option(DHCP6_CHADDR[2]);
AppendDhcp6Option(DHCP6_CHADDR[3]);
AppendDhcp6Option(DHCP6_CHADDR[4]);
AppendDhcp6Option(DHCP6_CHADDR[5]);
DumpDhcp6Option("Option Client ID");
// AppendDhcp6Option(0x00);AppendDhcp6Option(OPT_CLIENTID);
// AppendDhcp6Option((uint8_t)(clientid_len>>8));AppendDhcp6Option((uint8_t)clientid_len); //length
// AppendDhcp6Option((uint8_t)(DUID_type>>8));AppendDhcp6Option((uint8_t)DUID_type); //DUID_Type
// AppendDhcp6Option((uint8_t)(Hardware_type>>8));AppendDhcp6Option((uint8_t)Hardware_type); //Hard_Type
// AppendDhcp6Option(DHCP_CHADDR[0]);AppendDhcp6Option(DHCP_CHADDR[1]); // MAC Addr
// AppendDhcp6Option(DHCP_CHADDR[2]);AppendDhcp6Option(DHCP_CHADDR[3]);
// AppendDhcp6Option(DHCP_CHADDR[4]);AppendDhcp6Option(DHCP_CHADDR[5]);DumpDhcp6Option("Option Client ID");
//Server Identifier
AppendDhcp6Option(0x00);
AppendDhcp6Option(OPT_SERVERID);
AppendDhcp6Option((uint8_t)(serverid_len >> 8));
AppendDhcp6Option((uint8_t)serverid_len); //length
AppendDhcp6Option((uint8_t)(DUID_type_s >> 8));
AppendDhcp6Option((uint8_t)DUID_type_s); //DUID_Type
AppendDhcp6Option((uint8_t)(Hardware_type_s >> 8));
AppendDhcp6Option((uint8_t)Hardware_type_s); //Hard_Type
#if 0
// 20190318
AppendDhcp6Option(Time_s[0]); AppendDhcp6Option(Time_s[1]); // Time
AppendDhcp6Option(Time_s[2]); AppendDhcp6Option(Time_s[3]);
#endif
AppendDhcp6Option(Server_MAC[0]);
AppendDhcp6Option(Server_MAC[1]); // MAC Addr
AppendDhcp6Option(Server_MAC[2]);
AppendDhcp6Option(Server_MAC[3]);
AppendDhcp6Option(Server_MAC[4]);
AppendDhcp6Option(Server_MAC[5]);
DumpDhcp6Option("Option Server ID");
// Fully Qualified Domain Name
// AppendDhcp6Option(0x00);AppendDhcp6Option(39);
// AppendDhcp6Option(0x00);AppendDhcp6Option(0x06); // length
// AppendDhcp6Option(0x00);AppendDhcp6Option(0x04);
// AppendDhcp6Option(0x44);AppendDhcp6Option(0x45);
// AppendDhcp6Option(0x44);AppendDhcp6Option(0x59);DumpDhcp6Option("Option FQ Domain Name");
// Vendor Class
// AppendDhcp6Option(0x00);AppendDhcp6Option(16);
// AppendDhcp6Option(0x00);AppendDhcp6Option(0x0e); // length
// AppendDhcp6Option(0x00);AppendDhcp6Option(0x00);
// AppendDhcp6Option(0x01);AppendDhcp6Option(0x37);
// AppendDhcp6Option(0x00);AppendDhcp6Option(0x08);
// AppendDhcp6Option(0x4d);AppendDhcp6Option(0x53);
// AppendDhcp6Option(0x46);AppendDhcp6Option(0x54);
// AppendDhcp6Option(0x20);AppendDhcp6Option(0x35);
// AppendDhcp6Option(0x2e);AppendDhcp6Option(0x30);DumpDhcp6Option("Option Vendor Class");
// Option Request
// AppendDhcp6Option(0x00);AppendDhcp6Option(OPT_REQUEST);
// AppendDhcp6Option(0x00);AppendDhcp6Option(0x08); // length
// AppendDhcp6Option(0x00);AppendDhcp6Option(OPT_VENDOR_OPTS);
// AppendDhcp6Option(0x00);AppendDhcp6Option(DNS_RecursiveNameServer);
// AppendDhcp6Option(0x00);AppendDhcp6Option(Domain_Search_List);
// AppendDhcp6Option(0x00);AppendDhcp6Option(FQ_DOMAIN_NAME);DumpDhcp6Option("Option Request");
// send broadcasting packet
ip[0] = 0xff;
ip[1] = 0x02;
for (j = 2; j < 13; j++) {
ip[j] = 0x00;
}
ip[13] = 0x01;
ip[14] = 0x00;
ip[15] = 0x02;
rip_msg_size = size;
#ifdef _DHCP_DEBUG_
printf("> Send DHCP_REQUEST\r\n");
#endif
sendto(DHCP6_SOCKET, (uint8_t *)pDHCP6MSG.OPT, rip_msg_size, ip, DHCP6_SERVER_PORT, 16);
#ifdef _DHCP_DEBUG_
printf("> %d, %d\r\n", ret, rip_msg_size);
#endif
return ret;
}
/**
@brief
@return uint8_t
*/
uint8_t send_DHCP_INFOREQ(void) {
//uint16_t i;
uint16_t j;
uint8_t ip[16];
uint8_t rip_msg_size;
uint8_t ret = 0;
size = 0;
num = 0;
growby = 0;
//printf("req : %x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x:%x%x \r\n",recv_IP[0],recv_IP[1],recv_IP[2],recv_IP[3],recv_IP[4],recv_IP[5],recv_IP[6],recv_IP[7],recv_IP[8],recv_IP[9],recv_IP[10],recv_IP[11],recv_IP[12],recv_IP[13],recv_IP[14],recv_IP[15]);
InitDhcp6Option(30, 1);
DumpDhcp6Option("option init");
AppendDhcp6Option(DHCP6_INFO_REQUEST);
AppendDhcp6Option((uint8_t)((DHCP6_XID & 0x00FF0000) >> 16));
AppendDhcp6Option((uint8_t)((DHCP6_XID & 0x0000FF00) >> 8));
AppendDhcp6Option((uint8_t)((DHCP6_XID & 0x000000FF) >> 0));
DumpDhcp6Option("Type&XID");
// // Elapsed time
// AppendDhcp6Option(0x00);AppendDhcp6Option(OPT_ELAPSED_TIME);
// AppendDhcp6Option(0x00);AppendDhcp6Option(0x02);
// AppendDhcp6Option(0x0c);AppendDhcp6Option(0x1c);DumpDhcp6Option("Option Elapsed Time");
// Client Identifier
AppendDhcp6Option(0x00);
AppendDhcp6Option(OPT_CLIENTID);
AppendDhcp6Option(0x00);
AppendDhcp6Option(0x0a); //length
AppendDhcp6Option(0x00);
AppendDhcp6Option(0x03); //DUID_Type
AppendDhcp6Option(0x00);
AppendDhcp6Option(0x01); //Hard_Type
AppendDhcp6Option(DHCP6_CHADDR[0]);
AppendDhcp6Option(DHCP6_CHADDR[1]); // MAC Addr
AppendDhcp6Option(DHCP6_CHADDR[2]);
AppendDhcp6Option(DHCP6_CHADDR[3]);
AppendDhcp6Option(DHCP6_CHADDR[4]);
AppendDhcp6Option(DHCP6_CHADDR[5]);
DumpDhcp6Option("Option Client ID");
// Option Request
AppendDhcp6Option(0x00);
AppendDhcp6Option(OPT_REQUEST);
AppendDhcp6Option(0x00);
AppendDhcp6Option(0x06); // length
//AppendDhcp6Option(0x00);AppendDhcp6Option(OPT_VENDOR_OPTS);
AppendDhcp6Option(0x00);
AppendDhcp6Option(DNS_RecursiveNameServer);
AppendDhcp6Option(0x00);
AppendDhcp6Option(Domain_Search_List);
AppendDhcp6Option(0x00);
AppendDhcp6Option(OPT_LIFETIME);
DumpDhcp6Option("Option Request");
// send broadcasting packet
ip[0] = 0xff;
ip[1] = 0x02;
for (j = 2; j < 13; j++) {
ip[j] = 0x00;
}
ip[13] = 0x01;
ip[14] = 0x00;
ip[15] = 0x02;
rip_msg_size = size;
#ifdef _DHCP_DEBUG_
printf("> Send DHCP_REQUEST\r\n");
#endif
sendto(DHCP6_SOCKET, (uint8_t *)pDHCP6MSG.OPT, rip_msg_size, ip, DHCP6_SERVER_PORT, 16);
#ifdef _DHCP_DEBUG_
printf("> %d, %d\r\n", ret, rip_msg_size);
#endif
return ret;
}
/**
@brief
@return int8_t
*/
int8_t parseDHCP6MSG(void) {
uint8_t svr_addr[16];
uint16_t svr_port;
uint8_t addlen;
uint16_t len;
uint8_t *p;
uint8_t *e;
uint8_t type, i;
uint16_t opt_len;
uint32_t end_point;
if ((len = getSn_RX_RSR(DHCP6_SOCKET)) > 0) {
len = recvfrom(DHCP6_SOCKET, (uint8_t *)pDHCP6MSG.OPT, len, svr_addr, (uint16_t *)&svr_port, &addlen);
#ifdef _DHCP6_DEBUG_
printf("DHCP message : %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x(%d) %d received. \r\n", svr_addr[0], svr_addr[1], svr_addr[2], svr_addr[3], svr_addr[4], svr_addr[5], svr_addr[6], svr_addr[7], svr_addr[8], svr_addr[9], svr_addr[10], svr_addr[11], svr_addr[12], svr_addr[13], svr_addr[14], svr_addr[15], svr_port, len);
#endif
} else {
return 0;
}
type = 0;
p = (uint8_t *)(pDHCP6MSG.OPT);
e = p + len;
#ifdef _DHCP6_DEBUG_
printf("in server port %x\r\n", *p);
#endif
i = 0;
/*
while(p<e){
printf("%.2x ",*p);
i8f(i%16 == 1){
printf("\r\n");
}
p++;i++;
}
i=0;*/
switch (*p) {
case DHCP6_ADVERTISE:
case DHCP6_REPLY: {
#ifdef _DHCP6_DEBUG_
printf("in ADVER or REPLY(7) type : %x \r\n", *p);
#endif
type = *p++; // type
p++; // xid[0]
p++; // xid[1]
p++; // xid[2]
while (p < e) {
p++;
switch (*p) {
case OPT_CLIENTID: {
#ifdef _DHCP6_DEBUG_
printf("in clientid \r\n");
#endif
p++;
opt_len = (*p++ << 8);
clientid_len = opt_len + (*p++);
#ifdef _DHCP6_DEBUG_
printf("opt_len : %.4x\r\n", clientid_len);
#endif
end_point = (uint32_t)p + clientid_len;
while ((uint32_t)p != end_point) {
p++;
}
break;
}
case OPT_IANA: {
#ifdef _DHCP6_DEBUG_
printf("in iana \r\n");
#endif
p++;
opt_len = (*p++ << 8);
iana_len = opt_len + (*p++);
end_point = (uint32_t)p + iana_len;
//IAID
IAID[0] = *p++;
IAID[1] = *p++;
IAID[2] = *p++;
IAID[3] = *p++;
//T1
T1[0] = *p++;
T1[1] = *p++;
T1[2] = *p++;
T1[3] = *p++;
//T2
T2[0] = *p++;
T2[1] = *p++;
T2[2] = *p++;
T2[3] = *p++;
//IA_NA-options
while ((uint32_t)p < end_point) {
p++;
switch (*p) {
case OPT_IAADDR: {
#ifdef _DHCP6_DEBUG_
printf("in IA addr \r\n");
#endif
p++;
opt_len = (*p++ << 8);
iaaddr_len = opt_len + (*p++);
recv_IP[0] = *p++;
recv_IP[1] = *p++;
recv_IP[2] = *p++;
recv_IP[3] = *p++;
recv_IP[4] = *p++;
recv_IP[5] = *p++;
recv_IP[6] = *p++;
recv_IP[7] = *p++;
recv_IP[8] = *p++;
recv_IP[9] = *p++;
recv_IP[10] = *p++;
recv_IP[11] = *p++;
recv_IP[12] = *p++;
recv_IP[13] = *p++;
recv_IP[14] = *p++;
recv_IP[15] = *p++;
PreLifeTime = (*p++ << 24);
PreLifeTime += (*p++ << 16);
PreLifeTime += (*p++ << 8);
PreLifeTime += (*p++);
ValidLifeTime = (*p++ << 24);
ValidLifeTime += (*p++ << 16);
ValidLifeTime += (*p++ << 8);
ValidLifeTime += (*p++);
printf("IANA : %.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x:%.2x%.2x \r\n", recv_IP[0], recv_IP[1], recv_IP[2], recv_IP[3], recv_IP[4], recv_IP[5], recv_IP[6], recv_IP[7], recv_IP[8], recv_IP[9], recv_IP[10], recv_IP[11], recv_IP[12], recv_IP[13], recv_IP[14], recv_IP[15]);
break;
}
case OPT_STATUS_CODE: {
#ifdef _DHCP6_DEBUG_
printf("in status code \r\n");
#endif
p++;
opt_len = (*p++ << 8);
statuscode_len = opt_len + (*p++);
Lstatuscode_len = statuscode_len;
#ifdef _DHCP6_DEBUG_
printf("status_len : %x\r\n", statuscode_len);
printf("Lstatus_len : %x\r\n", Lstatuscode_len);
#endif
code = (*p++ << 8);
code = code + (*p++);
//printf("status_code : %x\r\n", code);
//for(i=0; i<(statuscode_len-2); i++)
// status_msg[i] = *p++;
//printf("status_msg : %s \r\n", status_msg);
p += statuscode_len - 2;
break;
}
default: {
#ifdef _DHCP6_DEBUG_
printf("in default \r\n");
#endif
p++;
opt_len = (*p++ << 8);
opt_len = opt_len + (*p++);
p += opt_len;
break;
}
}
}
break;
}
case OPT_IATA: {
#ifdef _DHCP6_DEBUG_
printf("in iata \r\n");
#endif
p++;
opt_len = (*p++ << 8);
opt_len = opt_len + (*p++);
//IA_TA-options
p += opt_len;
break;
}
case OPT_SERVERID: {
#ifdef _DHCP6_DEBUG_
printf("in serverid \r\n");
#endif
p++;
opt_len = (*p++ << 8);
serverid_len = opt_len + (*p++);
#ifdef _DHCP6_DEBUG_
printf("opt_len : %.4x\r\n", serverid_len);
#endif
end_point = (uint32_t)p + serverid_len;
DUID_type_s = (*p++ << 8);
DUID_type_s = DUID_type_s + (*p++);
#ifdef _DHCP6_DEBUG_
printf("DUID_type : %.4x\r\n", DUID_type_s);
#endif
if (DUID_type_s == 0x02) {
Enterprise_num_s = (*p++ << 24);
Enterprise_num_s = Enterprise_num_s + (*p++ << 16);
Enterprise_num_s = Enterprise_num_s + (*p++ << 8);
Enterprise_num_s = Enterprise_num_s + (*p++);
} else {
Hardware_type_s = (*p++ << 8);
Hardware_type_s = Hardware_type_s + (*p++);
#ifdef _DHCP6_DEBUG_
printf("Hardware_type : %.4x\r\n", Hardware_type_s);
#endif
}
if (DUID_type_s == 0x01) {
Time_s[0] = *p++;
Time_s[1] = *p++;
Time_s[2] = *p++;
Time_s[3] = *p++;
#ifdef _DHCP6_DEBUG_
printf("Time : ");
for (i = 0; i < 4; i++) {
printf("%.2x", Time_s[i]);
}
printf("\r\n");
#endif
}
Server_MAC[0] = *p++;
Server_MAC[1] = *p++;
Server_MAC[2] = *p++;
Server_MAC[3] = *p++;
Server_MAC[4] = *p++;
Server_MAC[5] = *p++;
#ifdef _DHCP6_DEBUG_
printf("Server_MAC : ");
for (i = 0; i < 6; i++) {
printf("%.2x", Server_MAC[i]);
}
printf("\r\n");
#endif
while ((uint32_t)p != end_point) {
p++;
}
break;
}
case DNS_RecursiveNameServer: {
#ifdef _DHCP6_DEBUG_
printf("in DNS Recursive Name Server \r\n");
#endif
p++;
opt_len = (*p++ << 8);
opt_len = opt_len + (*p++);
end_point = (uint32_t)p + opt_len;
DNS6_Address[0] = *p++;
DNS6_Address[1] = *p++;
DNS6_Address[2] = *p++;
DNS6_Address[3] = *p++;
DNS6_Address[4] = *p++;
DNS6_Address[5] = *p++;
DNS6_Address[6] = *p++;
DNS6_Address[7] = *p++;
DNS6_Address[8] = *p++;
DNS6_Address[9] = *p++;
DNS6_Address[10] = *p++;
DNS6_Address[11] = *p++;
DNS6_Address[12] = *p++;
DNS6_Address[13] = *p++;
DNS6_Address[14] = *p++;
DNS6_Address[15] = *p++;
while ((uint32_t)p < end_point) {
p++;
}
break;
}
case Domain_Search_List: {
#ifdef _DHCP6_DEBUG_
printf("in Domain Search List \r\n");
#endif
p++;
opt_len = (*p++ << 8);
opt_len = opt_len + (*p++);
end_point = (uint32_t)p + opt_len;
while ((uint32_t)p < end_point) {
p++;
}
break;
}
default: {
#ifdef _DHCP6_DEBUG_
printf("in default \r\n");
#endif
p++;
opt_len = (*p++ << 8);
opt_len = opt_len + (*p++);
p += opt_len;
break;
}
}
}
}
}
return type;
}
/**
@brief
@return uint8_t
*/
uint8_t DHCP6_run2(void) {
uint8_t type;
uint8_t ret;
if (dhcp6_state == STATE_DHCP6_STOP) {
return DHCP6_STOPPED; // Check DHCPv6 STOP State
}
if (getSn_SR(DHCP6_SOCKET) != SOCK_UDP) {
// Check DHCPv6 SOCKET == UDP
WIZCHIP_WRITE(_Sn_TTLR_(DHCP6_SOCKET), 0x01); // hop limit 1
socket(DHCP6_SOCKET, (Sn_MR_UDP6), DHCP6_CLIENT_PORT, 0x00);
}
ret = DHCP6_RUNNING;
type = parseDHCP6MSG();
switch (dhcp6_state) {
case STATE_DHCP6_INIT:
send_DHCP_INFOREQ();
dhcp6_state = STATE_DHCP6_RELEASE;
break;
case STATE_DHCP6_RELEASE:
return DHCP6_IP_LEASED;
default:
break;
}
return ret;
}
/**
@brief
@param netinfo
@return uint8_t
*/
uint8_t DHCP6_run(wiz_NetInfo *netinfo) {
uint8_t type;
uint8_t ret;
uint8_t i;
if (dhcp6_state == STATE_DHCP6_STOP) {
return DHCP6_STOPPED; // Check DHCPv6 STOP State
}
if (getSn_SR(DHCP6_SOCKET) != SOCK_UDP) {
// Check DHCPv6 SOCKET == UDP
WIZCHIP_WRITE(_Sn_TTLR_(DHCP6_SOCKET), 0x01); // hop limit 1
socket(DHCP6_SOCKET, (Sn_MR_UDP6), DHCP6_CLIENT_PORT, 0x00);
}
ret = DHCP6_RUNNING;
type = parseDHCPMSG();
printf("type:%d, dhcp_state :%d\r\n", type, dhcp6_state);
switch (dhcp6_state) {
case STATE_DHCP6_INIT:
DHCP6_allocated_ip[0] = 0;
DHCP6_allocated_ip[1] = 0;
DHCP6_allocated_ip[2] = 0;
DHCP6_allocated_ip[3] = 0;
DHCP6_allocated_ip[4] = 0;
DHCP6_allocated_ip[5] = 0;
DHCP6_allocated_ip[6] = 0;
DHCP6_allocated_ip[7] = 0;
DHCP6_allocated_ip[8] = 0;
DHCP6_allocated_ip[9] = 0;
DHCP6_allocated_ip[10] = 0;
DHCP6_allocated_ip[11] = 0;
DHCP6_allocated_ip[12] = 0;
DHCP6_allocated_ip[13] = 0;
DHCP6_allocated_ip[14] = 0;
DHCP6_allocated_ip[15] = 0;
send_DHCP6_SOLICIT();
dhcp6_state = STATE_DHCP6_SOLICIT;
break;
case STATE_DHCP6_SOLICIT:
if (type == DHCP6_ADVERTISE) {
#ifdef _DHCP6_DEBUG_
printf("> Receive DHCP_ADVERTISE\r\n");
#endif
DHCP6_allocated_ip[0] = recv_IP[0];
DHCP6_allocated_ip[1] = recv_IP[1];
DHCP6_allocated_ip[2] = recv_IP[2];
DHCP6_allocated_ip[3] = recv_IP[3];
DHCP6_allocated_ip[4] = recv_IP[4];
DHCP6_allocated_ip[5] = recv_IP[5];
DHCP6_allocated_ip[6] = recv_IP[6];
DHCP6_allocated_ip[7] = recv_IP[7];
DHCP6_allocated_ip[8] = recv_IP[8];
DHCP6_allocated_ip[9] = recv_IP[9];
DHCP6_allocated_ip[10] = recv_IP[10];
DHCP6_allocated_ip[11] = recv_IP[11];
DHCP6_allocated_ip[12] = recv_IP[12];
DHCP6_allocated_ip[13] = recv_IP[13];
DHCP6_allocated_ip[14] = recv_IP[14];
DHCP6_allocated_ip[15] = recv_IP[15];
ret = send_DHCP_REQUEST();
if (ret == 9) {
return 0;
}
dhcp6_state = STATE_DHCP6_REQUEST;
} //else ret = check_DHCP_timeout();
break;
case STATE_DHCP6_REQUEST:
// 20190318
//NETUNLOCK();
memcpy(netinfo->gua, recv_IP, 16);
//NETLOCK();
return DHCP6_IP_LEASED;
default:
break;
}
return ret;
}
/**
@brief
*/
void DHCP6_stop(void) {
close(DHCP6_SOCKET);
dhcp6_state = STATE_DHCP6_STOP;
}
/**
@brief
@return uint8_t
*/
uint8_t check_DHCP6_timeout(void) {
uint8_t ret = DHCP6_RUNNING;
if (dhcp6_retry_count < MAX_DHCP6_RETRY) {
if (dhcp6_tick_next < dhcp6_tick_1s) {
switch (dhcp6_state) {
case STATE_DHCP6_SOLICIT: {
#ifdef _DHCP6_DEBUG_
printf("<<timeout>> state : STATE_DHCP_DISCOVER\r\n");
#endif
send_DHCP6_SOLICIT();
break;
}
default: {
break;
}
}
dhcp6_tick_1s = 0;
dhcp6_tick_next = dhcp6_tick_1s + DHCP6_WAIT_TIME;
dhcp6_retry_count++;
}
} else {
// timeout occurred
switch (dhcp6_state) {
case STATE_DHCP6_SOLICIT:
dhcp6_state = STATE_DHCP6_INIT;
ret = DHCP6_FAILED;
break;
default:
break;
}
reset_DHCP6_timeout();
}
return ret;
}
/**
@brief
@param s
@param buf
*/
void DHCP6_init(uint8_t s, uint8_t *buf) {
uint8_t zeroip[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
getSHAR(DHCP6_CHADDR);
if ((DHCP6_CHADDR[0] | DHCP6_CHADDR[1] | DHCP6_CHADDR[2] | DHCP6_CHADDR[3] | DHCP6_CHADDR[4] | DHCP6_CHADDR[5]) == 0x00) {
#ifdef _DHCP6_DEBUG_
printf("DHCP_init-set MAC\r\n");
#endif
// assing temporary mac address, you should be set SHAR before call this function.
DHCP6_CHADDR[0] = 0x00;
DHCP6_CHADDR[1] = 0x08;
DHCP6_CHADDR[2] = 0xdc;
DHCP6_CHADDR[3] = 0x00;
DHCP6_CHADDR[4] = 0x00;
DHCP6_CHADDR[5] = 0x00;
setSHAR(DHCP6_CHADDR);
}
DHCP6_SOCKET = s; // SOCK_DHCP
memset(buf, 0, sizeof(buf));
pDHCP6MSG.OPT = buf;
DHCP6_XID = 0x515789;
reset_DHCP_timeout();
dhcp6_state = STATE_DHCP6_INIT;
}
/**
@brief
*/
void reset_DHCP6_timeout(void) {
dhcp6_tick_1s = 0;
dhcp6_tick_next = DHCP6_WAIT_TIME;
dhcp6_retry_count = 0;
}
/**
@brief
*/
void DHCP6_time_handler(void) {
dhcp6_tick_1s++;
}
#endif