mirror of
https://github.com/sakumisu/CherryUSB.git
synced 2025-05-09 00:21:44 +08:00
feat: add dhcp-server and dns-server module
This commit is contained in:
parent
35807fb9d9
commit
8fa517016e
338
third_party/dhcp-server/dhserver.c
vendored
Normal file
338
third_party/dhcp-server/dhserver.c
vendored
Normal file
@ -0,0 +1,338 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015 by Sergey Fetisov <fsenok@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "dhserver.h"
|
||||
|
||||
/* DHCP message type */
|
||||
#define DHCP_DISCOVER 1
|
||||
#define DHCP_OFFER 2
|
||||
#define DHCP_REQUEST 3
|
||||
#define DHCP_DECLINE 4
|
||||
#define DHCP_ACK 5
|
||||
#define DHCP_NAK 6
|
||||
#define DHCP_RELEASE 7
|
||||
#define DHCP_INFORM 8
|
||||
|
||||
/* DHCP options */
|
||||
enum DHCP_OPTIONS {
|
||||
DHCP_PAD = 0,
|
||||
DHCP_SUBNETMASK = 1,
|
||||
DHCP_ROUTER = 3,
|
||||
DHCP_DNSSERVER = 6,
|
||||
DHCP_HOSTNAME = 12,
|
||||
DHCP_DNSDOMAIN = 15,
|
||||
DHCP_MTU = 26,
|
||||
DHCP_BROADCAST = 28,
|
||||
DHCP_PERFORMROUTERDISC = 31,
|
||||
DHCP_STATICROUTE = 33,
|
||||
DHCP_NISDOMAIN = 40,
|
||||
DHCP_NISSERVER = 41,
|
||||
DHCP_NTPSERVER = 42,
|
||||
DHCP_VENDOR = 43,
|
||||
DHCP_IPADDRESS = 50,
|
||||
DHCP_LEASETIME = 51,
|
||||
DHCP_OPTIONSOVERLOADED = 52,
|
||||
DHCP_MESSAGETYPE = 53,
|
||||
DHCP_SERVERID = 54,
|
||||
DHCP_PARAMETERREQUESTLIST = 55,
|
||||
DHCP_MESSAGE = 56,
|
||||
DHCP_MAXMESSAGESIZE = 57,
|
||||
DHCP_RENEWALTIME = 58,
|
||||
DHCP_REBINDTIME = 59,
|
||||
DHCP_CLASSID = 60,
|
||||
DHCP_CLIENTID = 61,
|
||||
DHCP_USERCLASS = 77, /* RFC 3004 */
|
||||
DHCP_FQDN = 81,
|
||||
DHCP_DNSSEARCH = 119, /* RFC 3397 */
|
||||
DHCP_CSR = 121, /* RFC 3442 */
|
||||
DHCP_MSCSR = 249, /* MS code for RFC 3442 */
|
||||
DHCP_END = 255
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
uint8_t dp_op; /* packet opcode type */
|
||||
uint8_t dp_htype; /* hardware addr type */
|
||||
uint8_t dp_hlen; /* hardware addr length */
|
||||
uint8_t dp_hops; /* gateway hops */
|
||||
uint32_t dp_xid; /* transaction ID */
|
||||
uint16_t dp_secs; /* seconds since boot began */
|
||||
uint16_t dp_flags;
|
||||
uint8_t dp_ciaddr[4]; /* client IP address */
|
||||
uint8_t dp_yiaddr[4]; /* 'your' IP address */
|
||||
uint8_t dp_siaddr[4]; /* server IP address */
|
||||
uint8_t dp_giaddr[4]; /* gateway IP address */
|
||||
uint8_t dp_chaddr[16]; /* client hardware address */
|
||||
uint8_t dp_legacy[192];
|
||||
uint8_t dp_magic[4];
|
||||
uint8_t dp_options[275]; /* options area */
|
||||
} DHCP_TYPE;
|
||||
|
||||
DHCP_TYPE dhcp_data;
|
||||
static struct udp_pcb *pcb = NULL;
|
||||
static dhcp_config_t *config = NULL;
|
||||
|
||||
char magic_cookie[] = { 0x63, 0x82, 0x53, 0x63 };
|
||||
|
||||
static dhcp_entry_t *entry_by_ip(uint32_t ip)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < config->num_entry; i++)
|
||||
if (*(uint32_t *)config->entries[i].addr == ip)
|
||||
return &config->entries[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static dhcp_entry_t *entry_by_mac(uint8_t *mac)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < config->num_entry; i++)
|
||||
if (memcmp(config->entries[i].mac, mac, 6) == 0)
|
||||
return &config->entries[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline bool is_vacant(dhcp_entry_t *entry)
|
||||
{
|
||||
return memcmp("\0\0\0\0\0", entry->mac, 6) == 0;
|
||||
}
|
||||
|
||||
static dhcp_entry_t *vacant_address(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < config->num_entry; i++)
|
||||
if (is_vacant(config->entries + i))
|
||||
return config->entries + i;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void free_entry(dhcp_entry_t *entry)
|
||||
{
|
||||
memset(entry->mac, 0, 6);
|
||||
}
|
||||
|
||||
uint8_t *find_dhcp_option(uint8_t *attrs, int size, uint8_t attr)
|
||||
{
|
||||
int i = 0;
|
||||
while ((i + 1) < size) {
|
||||
int next = i + attrs[i + 1] + 2;
|
||||
if (next > size)
|
||||
return NULL;
|
||||
if (attrs[i] == attr)
|
||||
return attrs + i;
|
||||
i = next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int fill_options(void *dest,
|
||||
uint8_t msg_type,
|
||||
const char *domain,
|
||||
uint32_t dns,
|
||||
int lease_time,
|
||||
uint32_t serverid,
|
||||
uint32_t router,
|
||||
uint32_t subnet)
|
||||
{
|
||||
uint8_t *ptr = (uint8_t *)dest;
|
||||
/* ACK message type */
|
||||
*ptr++ = 53;
|
||||
*ptr++ = 1;
|
||||
*ptr++ = msg_type;
|
||||
|
||||
/* dhcp server identifier */
|
||||
*ptr++ = DHCP_SERVERID;
|
||||
*ptr++ = 4;
|
||||
*(uint32_t *)ptr = serverid;
|
||||
ptr += 4;
|
||||
|
||||
/* lease time */
|
||||
*ptr++ = DHCP_LEASETIME;
|
||||
*ptr++ = 4;
|
||||
*ptr++ = (lease_time >> 24) & 0xFF;
|
||||
*ptr++ = (lease_time >> 16) & 0xFF;
|
||||
*ptr++ = (lease_time >> 8) & 0xFF;
|
||||
*ptr++ = (lease_time >> 0) & 0xFF;
|
||||
|
||||
/* subnet mask */
|
||||
*ptr++ = DHCP_SUBNETMASK;
|
||||
*ptr++ = 4;
|
||||
*(uint32_t *)ptr = subnet;
|
||||
ptr += 4;
|
||||
|
||||
/* router */
|
||||
if (router != 0) {
|
||||
*ptr++ = DHCP_ROUTER;
|
||||
*ptr++ = 4;
|
||||
*(uint32_t *)ptr = router;
|
||||
ptr += 4;
|
||||
}
|
||||
|
||||
/* domain name */
|
||||
if (domain != NULL) {
|
||||
int len = strlen(domain);
|
||||
*ptr++ = DHCP_DNSDOMAIN;
|
||||
*ptr++ = len;
|
||||
memcpy(ptr, domain, len);
|
||||
ptr += len;
|
||||
}
|
||||
|
||||
/* domain name server (DNS) */
|
||||
if (dns != 0) {
|
||||
*ptr++ = DHCP_DNSSERVER;
|
||||
*ptr++ = 4;
|
||||
*(uint32_t *)ptr = dns;
|
||||
ptr += 4;
|
||||
}
|
||||
|
||||
/* end */
|
||||
*ptr++ = DHCP_END;
|
||||
return ptr - (uint8_t *)dest;
|
||||
}
|
||||
|
||||
static void udp_recv_proc(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
|
||||
{
|
||||
(void)arg;
|
||||
(void)addr;
|
||||
uint8_t *ptr;
|
||||
dhcp_entry_t *entry;
|
||||
struct pbuf *pp;
|
||||
|
||||
uint32_t n = p->len;
|
||||
if (n > sizeof(dhcp_data))
|
||||
n = sizeof(dhcp_data);
|
||||
memcpy(&dhcp_data, p->payload, n);
|
||||
switch (dhcp_data.dp_options[2]) {
|
||||
case DHCP_DISCOVER:
|
||||
entry = entry_by_mac(dhcp_data.dp_chaddr);
|
||||
if (entry == NULL)
|
||||
entry = vacant_address();
|
||||
if (entry == NULL)
|
||||
break;
|
||||
|
||||
dhcp_data.dp_op = 2; /* reply */
|
||||
dhcp_data.dp_secs = 0;
|
||||
dhcp_data.dp_flags = 0;
|
||||
*(uint32_t *)dhcp_data.dp_yiaddr = *(uint32_t *)entry->addr;
|
||||
memcpy(dhcp_data.dp_magic, magic_cookie, 4);
|
||||
|
||||
memset(dhcp_data.dp_options, 0, sizeof(dhcp_data.dp_options));
|
||||
|
||||
fill_options(dhcp_data.dp_options,
|
||||
DHCP_OFFER,
|
||||
config->domain,
|
||||
*(uint32_t *)config->dns,
|
||||
entry->lease,
|
||||
*(uint32_t *)config->addr,
|
||||
*(uint32_t *)config->addr,
|
||||
*(uint32_t *)entry->subnet);
|
||||
|
||||
pp = pbuf_alloc(PBUF_TRANSPORT, sizeof(dhcp_data), PBUF_POOL);
|
||||
if (pp == NULL)
|
||||
break;
|
||||
memcpy(pp->payload, &dhcp_data, sizeof(dhcp_data));
|
||||
udp_sendto(upcb, pp, IP_ADDR_BROADCAST, port);
|
||||
pbuf_free(pp);
|
||||
break;
|
||||
|
||||
case DHCP_REQUEST:
|
||||
/* 1. find requested ipaddr in option list */
|
||||
ptr = find_dhcp_option(dhcp_data.dp_options, sizeof(dhcp_data.dp_options), DHCP_IPADDRESS);
|
||||
if (ptr == NULL)
|
||||
break;
|
||||
if (ptr[1] != 4)
|
||||
break;
|
||||
ptr += 2;
|
||||
|
||||
/* 2. does hw-address registered? */
|
||||
entry = entry_by_mac(dhcp_data.dp_chaddr);
|
||||
if (entry != NULL)
|
||||
free_entry(entry);
|
||||
|
||||
/* 3. find requested ipaddr */
|
||||
entry = entry_by_ip(*(uint32_t *)ptr);
|
||||
if (entry == NULL)
|
||||
break;
|
||||
if (!is_vacant(entry))
|
||||
break;
|
||||
|
||||
/* 4. fill struct fields */
|
||||
memcpy(dhcp_data.dp_yiaddr, ptr, 4);
|
||||
dhcp_data.dp_op = 2; /* reply */
|
||||
dhcp_data.dp_secs = 0;
|
||||
dhcp_data.dp_flags = 0;
|
||||
memcpy(dhcp_data.dp_magic, magic_cookie, 4);
|
||||
|
||||
/* 5. fill options */
|
||||
memset(dhcp_data.dp_options, 0, sizeof(dhcp_data.dp_options));
|
||||
|
||||
fill_options(dhcp_data.dp_options,
|
||||
DHCP_ACK,
|
||||
config->domain,
|
||||
*(uint32_t *)config->dns,
|
||||
entry->lease,
|
||||
*(uint32_t *)config->addr,
|
||||
*(uint32_t *)config->addr,
|
||||
*(uint32_t *)entry->subnet);
|
||||
|
||||
/* 6. send ACK */
|
||||
pp = pbuf_alloc(PBUF_TRANSPORT, sizeof(dhcp_data), PBUF_POOL);
|
||||
if (pp == NULL)
|
||||
break;
|
||||
memcpy(entry->mac, dhcp_data.dp_chaddr, 6);
|
||||
memcpy(pp->payload, &dhcp_data, sizeof(dhcp_data));
|
||||
udp_sendto(upcb, pp, IP_ADDR_BROADCAST, port);
|
||||
pbuf_free(pp);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
pbuf_free(p);
|
||||
}
|
||||
|
||||
err_t dhserv_init(dhcp_config_t *c)
|
||||
{
|
||||
err_t err;
|
||||
udp_init();
|
||||
dhserv_free();
|
||||
pcb = udp_new();
|
||||
if (pcb == NULL)
|
||||
return ERR_MEM;
|
||||
err = udp_bind(pcb, IP_ADDR_ANY, c->port);
|
||||
if (err != ERR_OK) {
|
||||
dhserv_free();
|
||||
return err;
|
||||
}
|
||||
udp_recv(pcb, udp_recv_proc, NULL);
|
||||
config = c;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void dhserv_free(void)
|
||||
{
|
||||
if (pcb == NULL)
|
||||
return;
|
||||
udp_remove(pcb);
|
||||
pcb = NULL;
|
||||
}
|
61
third_party/dhcp-server/dhserver.h
vendored
Normal file
61
third_party/dhcp-server/dhserver.h
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015 by Sergey Fetisov <fsenok@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* version: 1.0 demo (7.02.2015)
|
||||
* brief: tiny dhcp ipv4 server using lwip (pcb)
|
||||
* ref: https://lists.gnu.org/archive/html/lwip-users/2012-12/msg00016.html
|
||||
*/
|
||||
|
||||
#ifndef DHSERVER_H
|
||||
#define DHSERVER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "netif/etharp.h"
|
||||
|
||||
typedef struct dhcp_entry {
|
||||
uint8_t mac[6];
|
||||
uint8_t addr[4];
|
||||
uint8_t subnet[4];
|
||||
uint32_t lease;
|
||||
} dhcp_entry_t;
|
||||
|
||||
typedef struct dhcp_config {
|
||||
uint8_t addr[4];
|
||||
uint16_t port;
|
||||
uint8_t dns[4];
|
||||
const char *domain;
|
||||
int num_entry;
|
||||
dhcp_entry_t *entries;
|
||||
} dhcp_config_t;
|
||||
|
||||
err_t dhserv_init(dhcp_config_t *config);
|
||||
void dhserv_free(void);
|
||||
|
||||
#endif /* DHSERVER_H */
|
198
third_party/dns-server/dnserver.c
vendored
Normal file
198
third_party/dns-server/dnserver.c
vendored
Normal file
@ -0,0 +1,198 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015 by Sergey Fetisov <fsenok@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* version: 1.0 demo (7.02.2015)
|
||||
* brief: tiny dns ipv4 server using lwip (pcb)
|
||||
*/
|
||||
|
||||
#include "dnserver.h"
|
||||
|
||||
#define DNS_MAX_HOST_NAME_LEN 128
|
||||
|
||||
static struct udp_pcb *pcb;
|
||||
dns_query_proc_t query_proc;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
typedef struct {
|
||||
#if BYTE_ORDER == LITTLE_ENDIAN
|
||||
uint8_t rd : 1, /* Recursion Desired */
|
||||
tc : 1, /* Truncation Flag */
|
||||
aa : 1, /* Authoritative Answer Flag */
|
||||
opcode : 4, /* Operation code */
|
||||
qr : 1; /* Query/Response Flag */
|
||||
uint8_t rcode : 4, /* Response Code */
|
||||
z : 3, /* Zero */
|
||||
ra : 1; /* Recursion Available */
|
||||
#else
|
||||
uint8_t qr : 1, /* Query/Response Flag */
|
||||
opcode : 4, /* Operation code */
|
||||
aa : 1, /* Authoritative Answer Flag */
|
||||
tc : 1, /* Truncation Flag */
|
||||
rd : 1; /* Recursion Desired */
|
||||
uint8_t ra : 1, /* Recursion Available */
|
||||
z : 3, /* Zero */
|
||||
rcode : 4; /* Response Code */
|
||||
#endif
|
||||
} dns_header_flags_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t id;
|
||||
dns_header_flags_t flags;
|
||||
uint16_t n_record[4];
|
||||
} dns_header_t;
|
||||
|
||||
typedef struct dns_answer {
|
||||
uint16_t name;
|
||||
uint16_t type;
|
||||
uint16_t Class;
|
||||
uint32_t ttl;
|
||||
uint16_t len;
|
||||
uint32_t addr;
|
||||
} dns_answer_t;
|
||||
#pragma pack(pop)
|
||||
|
||||
typedef struct dns_query {
|
||||
char name[DNS_MAX_HOST_NAME_LEN];
|
||||
uint16_t type;
|
||||
uint16_t Class;
|
||||
} dns_query_t;
|
||||
|
||||
static int parse_next_query(void *data, int size, dns_query_t *query)
|
||||
{
|
||||
int len;
|
||||
int lables;
|
||||
uint8_t *ptr;
|
||||
|
||||
len = 0;
|
||||
lables = 0;
|
||||
ptr = (uint8_t *)data;
|
||||
|
||||
while (true) {
|
||||
uint8_t lable_len;
|
||||
if (size <= 0)
|
||||
return -1;
|
||||
lable_len = *ptr++;
|
||||
size--;
|
||||
if (lable_len == 0)
|
||||
break;
|
||||
if (lables > 0) {
|
||||
if (len == DNS_MAX_HOST_NAME_LEN)
|
||||
return -2;
|
||||
query->name[len++] = '.';
|
||||
}
|
||||
if (lable_len > size)
|
||||
return -1;
|
||||
if (len + lable_len >= DNS_MAX_HOST_NAME_LEN)
|
||||
return -2;
|
||||
memcpy(&query->name[len], ptr, lable_len);
|
||||
len += lable_len;
|
||||
ptr += lable_len;
|
||||
size -= lable_len;
|
||||
lables++;
|
||||
}
|
||||
|
||||
if (size < 4)
|
||||
return -1;
|
||||
query->name[len] = 0;
|
||||
query->type = *(uint16_t *)ptr;
|
||||
ptr += 2;
|
||||
query->Class = *(uint16_t *)ptr;
|
||||
ptr += 2;
|
||||
return ptr - (uint8_t *)data;
|
||||
}
|
||||
|
||||
static void udp_recv_proc(void *arg, struct udp_pcb *upcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
|
||||
{
|
||||
(void)arg;
|
||||
int len;
|
||||
dns_header_t *header;
|
||||
static dns_query_t query;
|
||||
struct pbuf *out;
|
||||
ip_addr_t host_addr;
|
||||
dns_answer_t *answer;
|
||||
|
||||
if (p->len <= sizeof(dns_header_t))
|
||||
goto error;
|
||||
header = (dns_header_t *)p->payload;
|
||||
if (header->flags.qr != 0)
|
||||
goto error;
|
||||
if (ntohs(header->n_record[0]) != 1)
|
||||
goto error;
|
||||
|
||||
len = parse_next_query(header + 1, p->len - sizeof(dns_header_t), &query);
|
||||
if (len < 0)
|
||||
goto error;
|
||||
if (!query_proc(query.name, &host_addr))
|
||||
goto error;
|
||||
|
||||
len += sizeof(dns_header_t);
|
||||
out = pbuf_alloc(PBUF_TRANSPORT, len + 16, PBUF_POOL);
|
||||
if (out == NULL)
|
||||
goto error;
|
||||
|
||||
memcpy(out->payload, p->payload, len);
|
||||
header = (dns_header_t *)out->payload;
|
||||
header->flags.qr = 1;
|
||||
header->n_record[1] = htons(1);
|
||||
answer = (struct dns_answer *)((uint8_t *)out->payload + len);
|
||||
answer->name = htons(0xC00C);
|
||||
answer->type = htons(1);
|
||||
answer->Class = htons(1);
|
||||
answer->ttl = htonl(32);
|
||||
answer->len = htons(4);
|
||||
answer->addr = host_addr.addr;
|
||||
|
||||
udp_sendto(upcb, out, addr, port);
|
||||
pbuf_free(out);
|
||||
|
||||
error:
|
||||
pbuf_free(p);
|
||||
}
|
||||
|
||||
err_t dnserv_init(const ip_addr_t *bind, uint16_t port, dns_query_proc_t qp)
|
||||
{
|
||||
err_t err;
|
||||
udp_init();
|
||||
dnserv_free();
|
||||
pcb = udp_new();
|
||||
if (pcb == NULL)
|
||||
return ERR_MEM;
|
||||
err = udp_bind(pcb, bind, port);
|
||||
if (err != ERR_OK) {
|
||||
dnserv_free();
|
||||
return err;
|
||||
}
|
||||
udp_recv(pcb, udp_recv_proc, NULL);
|
||||
query_proc = qp;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void dnserv_free(void)
|
||||
{
|
||||
if (pcb == NULL)
|
||||
return;
|
||||
udp_remove(pcb);
|
||||
pcb = NULL;
|
||||
}
|
47
third_party/dns-server/dnserver.h
vendored
Normal file
47
third_party/dns-server/dnserver.h
vendored
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2015 by Sergey Fetisov <fsenok@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* version: 1.0 demo (7.02.2015)
|
||||
* brief: tiny dns ipv4 server using lwip (pcb)
|
||||
*/
|
||||
|
||||
#ifndef DNSERVER
|
||||
#define DNSERVER
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "netif/etharp.h"
|
||||
|
||||
typedef bool (*dns_query_proc_t)(const char *name, ip_addr_t *addr);
|
||||
|
||||
err_t dnserv_init(const ip_addr_t *bind, uint16_t port, dns_query_proc_t query_proc);
|
||||
void dnserv_free(void);
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user