mirror of
https://github.com/logicog/RTLPlayground.git
synced 2026-08-30 14:52:51 +08:00
Initial support for dhcp server
This commit is contained in:
@@ -80,7 +80,7 @@ struct dhcp_pkt {
|
|||||||
#define DHCP_OPT ((__xdata uint8_t *)(uip_appdata) + sizeof (struct dhcp_pkt))
|
#define DHCP_OPT ((__xdata uint8_t *)(uip_appdata) + sizeof (struct dhcp_pkt))
|
||||||
|
|
||||||
__xdata uint32_t long_value;
|
__xdata uint32_t long_value;
|
||||||
|
__xdata struct dhcpd_cstate cstates[DHCPD_MAX_CLIENTS];
|
||||||
|
|
||||||
void dhcp_print_ip(uint8_t *a)
|
void dhcp_print_ip(uint8_t *a)
|
||||||
{
|
{
|
||||||
@@ -91,7 +91,7 @@ void dhcp_print_ip(uint8_t *a)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void dhcp_prepare_request(void)
|
void dhcp_prepare_msg(void)
|
||||||
{
|
{
|
||||||
DHCP_P->type = 1;
|
DHCP_P->type = 1;
|
||||||
DHCP_P->hw = DHCP_HW_TYPE_ETH;
|
DHCP_P->hw = DHCP_HW_TYPE_ETH;
|
||||||
@@ -148,7 +148,7 @@ void dhcp_addopt_server_id(void)
|
|||||||
void dhcp_send_discover(void)
|
void dhcp_send_discover(void)
|
||||||
{
|
{
|
||||||
print_string("dhcp_send_discover called\n");
|
print_string("dhcp_send_discover called\n");
|
||||||
dhcp_prepare_request();
|
dhcp_prepare_msg();
|
||||||
|
|
||||||
dhcp_state.opt_ptr = 0;
|
dhcp_state.opt_ptr = 0;
|
||||||
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_TYPE;
|
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_TYPE;
|
||||||
@@ -183,7 +183,7 @@ void dhcp_send_discover(void)
|
|||||||
void dhcp_send_request(void)
|
void dhcp_send_request(void)
|
||||||
{
|
{
|
||||||
print_string("dhcp_send_request called\n");
|
print_string("dhcp_send_request called\n");
|
||||||
dhcp_prepare_request();
|
dhcp_prepare_msg();
|
||||||
|
|
||||||
dhcp_state.opt_ptr = 0;
|
dhcp_state.opt_ptr = 0;
|
||||||
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_TYPE;
|
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_TYPE;
|
||||||
@@ -216,6 +216,41 @@ void dhcp_send_request(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dhcp_send_offer(void)
|
||||||
|
{
|
||||||
|
print_string("dhcp_send_offer called\n");
|
||||||
|
dhcp_prepare_msg();
|
||||||
|
|
||||||
|
dhcp_state.opt_ptr = 0;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_TYPE;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_TYPE_LEN;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_MESSAGE_OFFER;
|
||||||
|
|
||||||
|
dhcp_addopt_client_id();
|
||||||
|
dhcp_addopt_request_ip();
|
||||||
|
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAMS;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = 3;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAM_SUBNET;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAM_ROUTER;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_PARAM_DNS;
|
||||||
|
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = DHCP_END;
|
||||||
|
// Padding to 300 bytes
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
|
||||||
|
DHCP_OPT[dhcp_state.opt_ptr++] = 0;
|
||||||
|
|
||||||
|
uip_udp_send(sizeof(struct dhcp_pkt) + dhcp_state.opt_ptr);
|
||||||
|
dhcp_state.state = DHCP_DISCOVER_SENT;
|
||||||
|
dhcp_state.ticks = SYS_TICK_HZ;
|
||||||
|
dhcp_state.dhcp_timer = 30; // Timeout for discover
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ip_opt(uint8_t * __xdata ip)
|
void ip_opt(uint8_t * __xdata ip)
|
||||||
{
|
{
|
||||||
dhcp_state.opt_ptr++;
|
dhcp_state.opt_ptr++;
|
||||||
@@ -286,7 +321,7 @@ void parse_opts(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void parse_dhcp(void)
|
void parse_dhcp_response(void)
|
||||||
{
|
{
|
||||||
if (!DHCP_P->tid == HTONS(dhcp_state.transaction_id))
|
if (!DHCP_P->tid == HTONS(dhcp_state.transaction_id))
|
||||||
return;
|
return;
|
||||||
@@ -327,13 +362,61 @@ void parse_dhcp(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void parse_dhcp_request(void)
|
||||||
|
{
|
||||||
|
print_string("parse_dhcp_request called\n");
|
||||||
|
if (DHCP_P->cookie[0] != 0x63 || DHCP_P->cookie[1] != 0x82 || DHCP_P->cookie[2] != 0x53 || DHCP_P->cookie[3] != 0x63)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dhcp_state.opt_ptr = 0;
|
||||||
|
if (DHCP_OPT[dhcp_state.opt_ptr++] != DHCP_MESSAGE_TYPE || DHCP_OPT[dhcp_state.opt_ptr++] != DHCP_MESSAGE_TYPE_LEN)
|
||||||
|
return;
|
||||||
|
if (DHCP_OPT[dhcp_state.opt_ptr] == DHCP_MESSAGE_DISCOVER) {
|
||||||
|
dhcp_state.opt_ptr++;
|
||||||
|
dhcp_state.current_ip[0] = DHCP_P->your_ip[0];
|
||||||
|
dhcp_state.current_ip[1] = DHCP_P->your_ip[1];
|
||||||
|
dhcp_state.current_ip[2] = DHCP_P->your_ip[2];
|
||||||
|
dhcp_state.current_ip[3] = DHCP_P->your_ip[3];
|
||||||
|
parse_opts();
|
||||||
|
print_string("DHCP offer received for IP ");
|
||||||
|
print_byte(dhcp_state.current_ip[0]); print_byte(dhcp_state.current_ip[1]);
|
||||||
|
print_byte(dhcp_state.current_ip[2]); print_byte(dhcp_state.current_ip[3]);
|
||||||
|
write_char('\n');
|
||||||
|
dhcp_send_request();
|
||||||
|
} else if (DHCP_OPT[dhcp_state.opt_ptr++] == DHCP_MESSAGE_REQUEST) {
|
||||||
|
parse_opts();
|
||||||
|
print_string("DHCP ACK, our IP is ");
|
||||||
|
print_byte(dhcp_state.current_ip[0]); print_byte(dhcp_state.current_ip[1]);
|
||||||
|
print_byte(dhcp_state.current_ip[2]); print_byte(dhcp_state.current_ip[3]);
|
||||||
|
write_char('\n');
|
||||||
|
print_string("DHCP netmask ");
|
||||||
|
print_byte(dhcp_state.subnet[0]); print_byte(dhcp_state.subnet[1]);
|
||||||
|
print_byte(dhcp_state.subnet[2]); print_byte(dhcp_state.subnet[3]);
|
||||||
|
write_char('\n');
|
||||||
|
print_string("DHCP gateway ");
|
||||||
|
print_byte(dhcp_state.router[0]); print_byte(dhcp_state.router[1]);
|
||||||
|
print_byte(dhcp_state.router[2]); print_byte(dhcp_state.router[3]);
|
||||||
|
write_char('\n');
|
||||||
|
print_string("DHCP lease-time ");
|
||||||
|
print_long(dhcp_state.lease);
|
||||||
|
write_char('\n');
|
||||||
|
uip_ipaddr(&uip_hostaddr, dhcp_state.current_ip[0], dhcp_state.current_ip[1], dhcp_state.current_ip[2], dhcp_state.current_ip[3]);
|
||||||
|
uip_ipaddr(&uip_draddr, dhcp_state.router[0], dhcp_state.router[1], dhcp_state.router[2], dhcp_state.router[3]);
|
||||||
|
uip_ipaddr(&uip_netmask, dhcp_state.subnet[0], dhcp_state.subnet[1], dhcp_state.subnet[2], dhcp_state.subnet[3]);
|
||||||
|
dhcp_state.state = DHCP_LEASING;
|
||||||
|
dhcp_state.ticks = SYS_TICK_HZ;
|
||||||
|
dhcp_state.dhcp_timer = dhcp_state.renewal > 0xffff ? 0xffff : dhcp_state.renewal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void dhcp_start(void) __banked
|
void dhcp_start(void) __banked
|
||||||
{
|
{
|
||||||
uip_ipaddr(server, 255,255,255,255);
|
uip_ipaddr(server, 255,255,255,255);
|
||||||
dhcp_state.conn = uip_udp_new(&server, HTONS(DHCPC_SERVER_PORT));
|
dhcp_state.conn = uip_udp_new(&server, HTONS(DHCP_SERVER_PORT));
|
||||||
dhcp_state.current_ip[0] = dhcp_state.current_ip[1] = dhcp_state.current_ip[2] = dhcp_state.current_ip[3] = 0;
|
dhcp_state.current_ip[0] = dhcp_state.current_ip[1] = dhcp_state.current_ip[2] = dhcp_state.current_ip[3] = 0;
|
||||||
if(dhcp_state.conn) {
|
if(dhcp_state.conn) {
|
||||||
uip_udp_bind(dhcp_state.conn, HTONS(DHCPC_CLIENT_PORT));
|
uip_udp_bind(dhcp_state.conn, HTONS(DHCP_CLIENT_PORT));
|
||||||
} else {
|
} else {
|
||||||
print_string("dhcp_start failed to set up socket\n");
|
print_string("dhcp_start failed to set up socket\n");
|
||||||
return;
|
return;
|
||||||
@@ -345,6 +428,39 @@ void dhcp_start(void) __banked
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dhcpd_start(void) __banked
|
||||||
|
{
|
||||||
|
memset(&cstates[0], 0, sizeof (struct dhcpd_cstate) * DHCPD_MAX_CLIENTS);
|
||||||
|
dhcp_state.conn = uip_udp_new(0, 0);
|
||||||
|
if(dhcp_state.conn) {
|
||||||
|
uip_udp_bind(dhcp_state.conn, HTONS(DHCP_SERVER_PORT));
|
||||||
|
} else {
|
||||||
|
print_string("dhcpd_start failed to set up socket\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dhcp_state.state = DHCP_SERVER;
|
||||||
|
|
||||||
|
dhcp_state.server[0] = uip_hostaddr[0] >> 8; dhcp_state.server[1] = uip_hostaddr[0] & 0xff;
|
||||||
|
dhcp_state.server[2] = uip_hostaddr[1] >> 8; dhcp_state.server[3] = uip_hostaddr[1] & 0xff;
|
||||||
|
|
||||||
|
dhcp_state.router[0] = uip_draddr[0] >> 8; dhcp_state.router[1] = uip_draddr[0] & 0xff;
|
||||||
|
dhcp_state.router[2] = uip_draddr[1] >> 8; dhcp_state.router[3] = uip_draddr[1] & 0xff;
|
||||||
|
|
||||||
|
dhcp_state.subnet[0] = uip_netmask[0] >> 8; dhcp_state.subnet[1] = uip_netmask[0] & 0xff;
|
||||||
|
dhcp_state.subnet[2] = uip_netmask[1] >> 8; dhcp_state.subnet[3] = uip_netmask[1] & 0xff;
|
||||||
|
|
||||||
|
dhcp_state.broadcast[0] = dhcp_state.router[0]; dhcp_state.broadcast[1] = dhcp_state.router[1];
|
||||||
|
dhcp_state.broadcast[2] = dhcp_state.router[2]; dhcp_state.broadcast[3] = 0xff;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < DHCPD_MAX_CLIENTS; i++) {
|
||||||
|
cstates[i].mac[0] = 0x01; // We set the MC bit of all addresses to mark the entry unused
|
||||||
|
}
|
||||||
|
// TODO: DNS, correct broadcast address
|
||||||
|
|
||||||
|
print_string("dhcpd_start done\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void dhcp_stop(void) __banked
|
void dhcp_stop(void) __banked
|
||||||
{
|
{
|
||||||
print_string("dhcp_stop called\n");
|
print_string("dhcp_stop called\n");
|
||||||
@@ -352,6 +468,13 @@ void dhcp_stop(void) __banked
|
|||||||
dhcp_state.state = DHCP_OFF;
|
dhcp_state.state = DHCP_OFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dhcpd_stop(void) __banked
|
||||||
|
{
|
||||||
|
print_string("dhcpd_stop called\n");
|
||||||
|
uip_udp_remove(dhcp_state.conn);
|
||||||
|
dhcp_state.state = DHCP_OFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void dhcp_callback(void) __banked
|
void dhcp_callback(void) __banked
|
||||||
{
|
{
|
||||||
@@ -360,8 +483,10 @@ void dhcp_callback(void) __banked
|
|||||||
if (uip_closed()) {
|
if (uip_closed()) {
|
||||||
print_string("Closed\n");
|
print_string("Closed\n");
|
||||||
return;
|
return;
|
||||||
|
} else if (dhcp_state.state == DHCP_SERVER && uip_newdata()) {
|
||||||
|
parse_dhcp_request();
|
||||||
} else if (uip_newdata()) {
|
} else if (uip_newdata()) {
|
||||||
parse_dhcp();
|
parse_dhcp_response();
|
||||||
} else {
|
} else {
|
||||||
if (dhcp_state.state == DHCP_START) {
|
if (dhcp_state.state == DHCP_START) {
|
||||||
dhcp_send_discover();
|
dhcp_send_discover();
|
||||||
|
|||||||
@@ -3,22 +3,23 @@
|
|||||||
|
|
||||||
#include "uipopt.h"
|
#include "uipopt.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#define DHCPD_MAX_CLIENTS 10
|
||||||
|
#define DHCPD_START_IP 100
|
||||||
|
|
||||||
#define DHCPC_SERVER_PORT 67
|
#define DHCP_SERVER_PORT 67
|
||||||
#define DHCPC_CLIENT_PORT 68
|
#define DHCP_CLIENT_PORT 68
|
||||||
|
|
||||||
#define DHCP_OFF 0
|
#define DHCP_OFF 0
|
||||||
#define DHCP_START 1
|
#define DHCP_START 1
|
||||||
#define DHCP_DISCOVER_SENT 2
|
#define DHCP_DISCOVER_SENT 2
|
||||||
#define DHCP_REQUEST_SENT 3
|
#define DHCP_REQUEST_SENT 3
|
||||||
#define DHCP_LEASING 4
|
#define DHCP_LEASING 4
|
||||||
|
#define DHCP_SERVER 5
|
||||||
|
|
||||||
void dhcp_start(void) __banked;
|
void dhcp_start(void) __banked;
|
||||||
void dhcp_stop(void) __banked;
|
void dhcp_stop(void) __banked;
|
||||||
// void dhcp_periodic(void) __banked;
|
|
||||||
void dhcp_callback(void) __banked;
|
void dhcp_callback(void) __banked;
|
||||||
|
|
||||||
|
|
||||||
struct dhcp_state {
|
struct dhcp_state {
|
||||||
uint8_t state;
|
uint8_t state;
|
||||||
uint32_t transaction_id;
|
uint32_t transaction_id;
|
||||||
@@ -38,6 +39,18 @@ struct dhcp_state {
|
|||||||
struct uip_udp_conn *conn;
|
struct uip_udp_conn *conn;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct dhcpd_cstate {
|
||||||
|
uint8_t cstate;
|
||||||
|
uint16_t timer;
|
||||||
|
uint32_t transaction_id;
|
||||||
|
uint8_t mac[6];
|
||||||
|
uint8_t ip[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void dhcpd_start(void) __banked;
|
||||||
|
void dhcpd_stop(void) __banked;
|
||||||
|
|
||||||
typedef struct dhcp_state uip_udp_appstate_t;
|
typedef struct dhcp_state uip_udp_appstate_t;
|
||||||
|
|
||||||
/* Finally we define the application function to be called by uIP. */
|
/* Finally we define the application function to be called by uIP. */
|
||||||
|
|||||||
Reference in New Issue
Block a user