mirror of
https://github.com/cesanta/mongoose.git
synced 2024-11-27 12:49:01 +08:00
DNS and SNTP via DHCP
This commit is contained in:
parent
c1f630f5ed
commit
be58d73a0a
42
mongoose.c
42
mongoose.c
@ -5040,6 +5040,10 @@ struct pkt {
|
||||
struct dhcp *dhcp;
|
||||
};
|
||||
|
||||
static void mg_tcpip_call(struct mg_tcpip_if *ifp, int ev, void *ev_data) {
|
||||
if (ifp->fn != NULL) ifp->fn(ifp, ev, ev_data);
|
||||
}
|
||||
|
||||
static void send_syn(struct mg_connection *c);
|
||||
|
||||
static void mkpay(struct pkt *pkt, void *p) {
|
||||
@ -5109,6 +5113,7 @@ static void onstatechange(struct mg_tcpip_if *ifp) {
|
||||
} else if (ifp->state == MG_TCPIP_STATE_DOWN) {
|
||||
MG_ERROR(("Link down"));
|
||||
}
|
||||
mg_tcpip_call(ifp, MG_TCPIP_EV_ST_CHG, &ifp->state);
|
||||
}
|
||||
|
||||
static struct ip *tx_ip(struct mg_tcpip_if *ifp, uint8_t *mac_dst,
|
||||
@ -5169,20 +5174,25 @@ static void tx_dhcp(struct mg_tcpip_if *ifp, uint8_t *mac_dst, uint32_t ip_src,
|
||||
|
||||
static const uint8_t broadcast[] = {255, 255, 255, 255, 255, 255};
|
||||
|
||||
// RFC-2131 #4.3.6, #4.4.1
|
||||
// RFC-2131 #4.3.6, #4.4.1; RFC-2132 #9.8
|
||||
static void tx_dhcp_request_sel(struct mg_tcpip_if *ifp, uint32_t ip_req,
|
||||
uint32_t ip_srv) {
|
||||
uint8_t opts[] = {
|
||||
53, 1, 3, // Type: DHCP request
|
||||
55, 2, 1, 3, // GW and mask
|
||||
12, 3, 'm', 'i', 'p', // Host name: "mip"
|
||||
54, 4, 0, 0, 0, 0, // DHCP server ID
|
||||
50, 4, 0, 0, 0, 0, // Requested IP
|
||||
255 // End of options
|
||||
53, 1, 3, // Type: DHCP request
|
||||
12, 3, 'm', 'i', 'p', // Host name: "mip"
|
||||
54, 4, 0, 0, 0, 0, // DHCP server ID
|
||||
50, 4, 0, 0, 0, 0, // Requested IP
|
||||
55, 2, 1, 3, 255, 255, // GW, mask [DNS] [SNTP]
|
||||
255 // End of options
|
||||
};
|
||||
memcpy(opts + 14, &ip_srv, sizeof(ip_srv));
|
||||
memcpy(opts + 20, &ip_req, sizeof(ip_req));
|
||||
tx_dhcp(ifp, (uint8_t *) broadcast, 0, 0xffffffff, opts, sizeof(opts), false);
|
||||
uint8_t addopts = 0;
|
||||
memcpy(opts + 10, &ip_srv, sizeof(ip_srv));
|
||||
memcpy(opts + 16, &ip_req, sizeof(ip_req));
|
||||
if (ifp->enable_req_dns) opts[24 + addopts++] = 6; // DNS
|
||||
if (ifp->enable_req_sntp) opts[24 + addopts++] = 42; // SNTP
|
||||
opts[21] += addopts;
|
||||
tx_dhcp(ifp, (uint8_t *) broadcast, 0, 0xffffffff, opts,
|
||||
sizeof(opts) + addopts - 2, false);
|
||||
MG_DEBUG(("DHCP req sent"));
|
||||
}
|
||||
|
||||
@ -5278,7 +5288,7 @@ static void rx_icmp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
||||
}
|
||||
|
||||
static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
||||
uint32_t ip = 0, gw = 0, mask = 0, lease = 0;
|
||||
uint32_t ip = 0, gw = 0, mask = 0, lease = 0, dns = 0, sntp = 0;
|
||||
uint8_t msgtype = 0, state = ifp->state;
|
||||
// perform size check first, then access fields
|
||||
uint8_t *p = pkt->dhcp->options,
|
||||
@ -5291,6 +5301,12 @@ static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
||||
} else if (p[0] == 3 && p[1] == sizeof(ifp->gw) && p + 6 < end) { // GW
|
||||
memcpy(&gw, p + 2, sizeof(gw));
|
||||
ip = pkt->dhcp->yiaddr;
|
||||
} else if (ifp->enable_req_dns && p[0] == 6 && p[1] == sizeof(dns) &&
|
||||
p + 6 < end) { // DNS
|
||||
memcpy(&dns, p + 2, sizeof(dns));
|
||||
} else if (ifp->enable_req_sntp && p[0] == 42 && p[1] == sizeof(sntp) &&
|
||||
p + 6 < end) { // SNTP
|
||||
memcpy(&sntp, p + 2, sizeof(sntp));
|
||||
} else if (p[0] == 51 && p[1] == 4 && p + 6 < end) { // Lease
|
||||
memcpy(&lease, p + 2, sizeof(lease));
|
||||
lease = mg_ntohl(lease);
|
||||
@ -5319,6 +5335,10 @@ static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
||||
uint64_t rand;
|
||||
mg_random(&rand, sizeof(rand));
|
||||
srand((unsigned int) (rand + mg_millis()));
|
||||
if (ifp->enable_req_dns && dns != 0)
|
||||
mg_tcpip_call(ifp, MG_TCPIP_EV_DHCP_DNS, &dns);
|
||||
if (ifp->enable_req_sntp && sntp != 0)
|
||||
mg_tcpip_call(ifp, MG_TCPIP_EV_DHCP_SNTP, &sntp);
|
||||
} else if (ifp->state == MG_TCPIP_STATE_READY && ifp->ip == ip) { // renew
|
||||
ifp->lease_expire = ifp->now + lease * 1000;
|
||||
MG_INFO(("Lease: %u sec (%lld)", lease, ifp->lease_expire / 1000));
|
||||
|
13
mongoose.h
13
mongoose.h
@ -2568,6 +2568,16 @@ struct mg_tcpip_driver {
|
||||
bool (*up)(struct mg_tcpip_if *); // Up/down status
|
||||
};
|
||||
|
||||
typedef void (*mg_tcpip_event_handler_t)(struct mg_tcpip_if *ifp, int ev,
|
||||
void *ev_data);
|
||||
|
||||
enum {
|
||||
MG_TCPIP_EV_ST_CHG, // state change uint8_t * (&ifp->state)
|
||||
MG_TCPIP_EV_DHCP_DNS, // DHCP DNS assignment uint32_t *ipaddr
|
||||
MG_TCPIP_EV_DHCP_SNTP, // DHCP SNTP assignment uint32_t *ipaddr
|
||||
MG_TCPIP_EV_USER // Starting ID for user events
|
||||
};
|
||||
|
||||
// Network interface
|
||||
struct mg_tcpip_if {
|
||||
uint8_t mac[6]; // MAC address. Must be set to a valid MAC
|
||||
@ -2576,10 +2586,13 @@ struct mg_tcpip_if {
|
||||
bool enable_dhcp_client; // Enable DCHP client
|
||||
bool enable_dhcp_server; // Enable DCHP server
|
||||
bool enable_get_gateway; // DCHP server sets client as gateway
|
||||
bool enable_req_dns; // DCHP client requests DNS server
|
||||
bool enable_req_sntp; // DCHP client requests SNTP server
|
||||
bool enable_crc32_check; // Do a CRC check on RX frames and strip it
|
||||
bool enable_mac_check; // Do a MAC check on RX frames
|
||||
struct mg_tcpip_driver *driver; // Low level driver
|
||||
void *driver_data; // Driver-specific data
|
||||
mg_tcpip_event_handler_t fn; // User-specified event handler function
|
||||
struct mg_mgr *mgr; // Mongoose event manager
|
||||
struct mg_queue recv_queue; // Receive queue
|
||||
uint16_t mtu; // Interface MTU
|
||||
|
@ -138,6 +138,10 @@ struct pkt {
|
||||
struct dhcp *dhcp;
|
||||
};
|
||||
|
||||
static void mg_tcpip_call(struct mg_tcpip_if *ifp, int ev, void *ev_data) {
|
||||
if (ifp->fn != NULL) ifp->fn(ifp, ev, ev_data);
|
||||
}
|
||||
|
||||
static void send_syn(struct mg_connection *c);
|
||||
|
||||
static void mkpay(struct pkt *pkt, void *p) {
|
||||
@ -207,6 +211,7 @@ static void onstatechange(struct mg_tcpip_if *ifp) {
|
||||
} else if (ifp->state == MG_TCPIP_STATE_DOWN) {
|
||||
MG_ERROR(("Link down"));
|
||||
}
|
||||
mg_tcpip_call(ifp, MG_TCPIP_EV_ST_CHG, &ifp->state);
|
||||
}
|
||||
|
||||
static struct ip *tx_ip(struct mg_tcpip_if *ifp, uint8_t *mac_dst,
|
||||
@ -267,20 +272,25 @@ static void tx_dhcp(struct mg_tcpip_if *ifp, uint8_t *mac_dst, uint32_t ip_src,
|
||||
|
||||
static const uint8_t broadcast[] = {255, 255, 255, 255, 255, 255};
|
||||
|
||||
// RFC-2131 #4.3.6, #4.4.1
|
||||
// RFC-2131 #4.3.6, #4.4.1; RFC-2132 #9.8
|
||||
static void tx_dhcp_request_sel(struct mg_tcpip_if *ifp, uint32_t ip_req,
|
||||
uint32_t ip_srv) {
|
||||
uint8_t opts[] = {
|
||||
53, 1, 3, // Type: DHCP request
|
||||
55, 2, 1, 3, // GW and mask
|
||||
12, 3, 'm', 'i', 'p', // Host name: "mip"
|
||||
54, 4, 0, 0, 0, 0, // DHCP server ID
|
||||
50, 4, 0, 0, 0, 0, // Requested IP
|
||||
255 // End of options
|
||||
53, 1, 3, // Type: DHCP request
|
||||
12, 3, 'm', 'i', 'p', // Host name: "mip"
|
||||
54, 4, 0, 0, 0, 0, // DHCP server ID
|
||||
50, 4, 0, 0, 0, 0, // Requested IP
|
||||
55, 2, 1, 3, 255, 255, // GW, mask [DNS] [SNTP]
|
||||
255 // End of options
|
||||
};
|
||||
memcpy(opts + 14, &ip_srv, sizeof(ip_srv));
|
||||
memcpy(opts + 20, &ip_req, sizeof(ip_req));
|
||||
tx_dhcp(ifp, (uint8_t *) broadcast, 0, 0xffffffff, opts, sizeof(opts), false);
|
||||
uint8_t addopts = 0;
|
||||
memcpy(opts + 10, &ip_srv, sizeof(ip_srv));
|
||||
memcpy(opts + 16, &ip_req, sizeof(ip_req));
|
||||
if (ifp->enable_req_dns) opts[24 + addopts++] = 6; // DNS
|
||||
if (ifp->enable_req_sntp) opts[24 + addopts++] = 42; // SNTP
|
||||
opts[21] += addopts;
|
||||
tx_dhcp(ifp, (uint8_t *) broadcast, 0, 0xffffffff, opts,
|
||||
sizeof(opts) + addopts - 2, false);
|
||||
MG_DEBUG(("DHCP req sent"));
|
||||
}
|
||||
|
||||
@ -376,7 +386,7 @@ static void rx_icmp(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
||||
}
|
||||
|
||||
static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
||||
uint32_t ip = 0, gw = 0, mask = 0, lease = 0;
|
||||
uint32_t ip = 0, gw = 0, mask = 0, lease = 0, dns = 0, sntp = 0;
|
||||
uint8_t msgtype = 0, state = ifp->state;
|
||||
// perform size check first, then access fields
|
||||
uint8_t *p = pkt->dhcp->options,
|
||||
@ -389,6 +399,12 @@ static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
||||
} else if (p[0] == 3 && p[1] == sizeof(ifp->gw) && p + 6 < end) { // GW
|
||||
memcpy(&gw, p + 2, sizeof(gw));
|
||||
ip = pkt->dhcp->yiaddr;
|
||||
} else if (ifp->enable_req_dns && p[0] == 6 && p[1] == sizeof(dns) &&
|
||||
p + 6 < end) { // DNS
|
||||
memcpy(&dns, p + 2, sizeof(dns));
|
||||
} else if (ifp->enable_req_sntp && p[0] == 42 && p[1] == sizeof(sntp) &&
|
||||
p + 6 < end) { // SNTP
|
||||
memcpy(&sntp, p + 2, sizeof(sntp));
|
||||
} else if (p[0] == 51 && p[1] == 4 && p + 6 < end) { // Lease
|
||||
memcpy(&lease, p + 2, sizeof(lease));
|
||||
lease = mg_ntohl(lease);
|
||||
@ -417,6 +433,10 @@ static void rx_dhcp_client(struct mg_tcpip_if *ifp, struct pkt *pkt) {
|
||||
uint64_t rand;
|
||||
mg_random(&rand, sizeof(rand));
|
||||
srand((unsigned int) (rand + mg_millis()));
|
||||
if (ifp->enable_req_dns && dns != 0)
|
||||
mg_tcpip_call(ifp, MG_TCPIP_EV_DHCP_DNS, &dns);
|
||||
if (ifp->enable_req_sntp && sntp != 0)
|
||||
mg_tcpip_call(ifp, MG_TCPIP_EV_DHCP_SNTP, &sntp);
|
||||
} else if (ifp->state == MG_TCPIP_STATE_READY && ifp->ip == ip) { // renew
|
||||
ifp->lease_expire = ifp->now + lease * 1000;
|
||||
MG_INFO(("Lease: %u sec (%lld)", lease, ifp->lease_expire / 1000));
|
||||
|
@ -14,6 +14,16 @@ struct mg_tcpip_driver {
|
||||
bool (*up)(struct mg_tcpip_if *); // Up/down status
|
||||
};
|
||||
|
||||
typedef void (*mg_tcpip_event_handler_t)(struct mg_tcpip_if *ifp, int ev,
|
||||
void *ev_data);
|
||||
|
||||
enum {
|
||||
MG_TCPIP_EV_ST_CHG, // state change uint8_t * (&ifp->state)
|
||||
MG_TCPIP_EV_DHCP_DNS, // DHCP DNS assignment uint32_t *ipaddr
|
||||
MG_TCPIP_EV_DHCP_SNTP, // DHCP SNTP assignment uint32_t *ipaddr
|
||||
MG_TCPIP_EV_USER // Starting ID for user events
|
||||
};
|
||||
|
||||
// Network interface
|
||||
struct mg_tcpip_if {
|
||||
uint8_t mac[6]; // MAC address. Must be set to a valid MAC
|
||||
@ -22,10 +32,13 @@ struct mg_tcpip_if {
|
||||
bool enable_dhcp_client; // Enable DCHP client
|
||||
bool enable_dhcp_server; // Enable DCHP server
|
||||
bool enable_get_gateway; // DCHP server sets client as gateway
|
||||
bool enable_req_dns; // DCHP client requests DNS server
|
||||
bool enable_req_sntp; // DCHP client requests SNTP server
|
||||
bool enable_crc32_check; // Do a CRC check on RX frames and strip it
|
||||
bool enable_mac_check; // Do a MAC check on RX frames
|
||||
struct mg_tcpip_driver *driver; // Low level driver
|
||||
void *driver_data; // Driver-specific data
|
||||
mg_tcpip_event_handler_t fn; // User-specified event handler function
|
||||
struct mg_mgr *mgr; // Mongoose event manager
|
||||
struct mg_queue recv_queue; // Receive queue
|
||||
uint16_t mtu; // Interface MTU
|
||||
|
@ -42,6 +42,23 @@ static size_t tap_rx(void *buf, size_t len, struct mg_tcpip_if *ifp) {
|
||||
return (size_t) received;
|
||||
}
|
||||
|
||||
char *s_dns = NULL, *s_sntp = NULL;
|
||||
|
||||
static void mif_fn(struct mg_tcpip_if *ifp, int ev, void *ev_data) {
|
||||
if (ev == MG_TCPIP_EV_ST_CHG) {
|
||||
MG_INFO(("State change: %u", *(uint8_t *) ev_data));
|
||||
} else if (ev == MG_TCPIP_EV_DHCP_DNS) {
|
||||
free(s_dns);
|
||||
s_dns = mg_mprintf("udp://%M:53", mg_print_ip4, (uint32_t *) ev_data);
|
||||
ifp->mgr->dns4.url = s_dns;
|
||||
MG_INFO(("Set DNS to %s", ifp->mgr->dns4.url));
|
||||
} else if (ev == MG_TCPIP_EV_DHCP_SNTP) {
|
||||
free(s_sntp);
|
||||
s_sntp = mg_mprintf("udp://%M:123", mg_print_ip4, (uint32_t *) ev_data);
|
||||
MG_INFO(("Set SNTP to %s", s_sntp));
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
const char *iface = "tap0"; // Network iface
|
||||
const char *mac = "02:00:01:02:03:77"; // MAC address
|
||||
@ -93,7 +110,11 @@ int main(int argc, char *argv[]) {
|
||||
mg_mgr_init(&mgr); // Initialise event manager
|
||||
|
||||
struct mg_tcpip_driver driver = {.tx = tap_tx, .up = tap_up, .rx = tap_rx};
|
||||
struct mg_tcpip_if mif = {.driver = &driver, .driver_data = &fd};
|
||||
struct mg_tcpip_if mif = {.driver = &driver,
|
||||
.driver_data = &fd,
|
||||
.enable_req_dns = true,
|
||||
.enable_req_sntp = true,
|
||||
.fn = mif_fn};
|
||||
sscanf(mac, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &mif.mac[0], &mif.mac[1],
|
||||
&mif.mac[2], &mif.mac[3], &mif.mac[4], &mif.mac[5]);
|
||||
mg_tcpip_init(&mgr, &mif);
|
||||
@ -107,6 +128,8 @@ int main(int argc, char *argv[]) {
|
||||
web_init(&mgr);
|
||||
while (s_signo == 0) mg_mgr_poll(&mgr, 100); // Infinite event loop
|
||||
|
||||
free(s_dns);
|
||||
free(s_sntp);
|
||||
mg_mgr_free(&mgr);
|
||||
close(fd);
|
||||
printf("Exiting on signal %d\n", s_signo);
|
||||
|
Loading…
Reference in New Issue
Block a user