151 lines
4.0 KiB
C
151 lines
4.0 KiB
C
|
|
/**
|
|||
|
|
******************************************************************************
|
|||
|
|
* @file dns_eloop.c
|
|||
|
|
* @author HUGE-IC Application Team
|
|||
|
|
* @version V1.0.0
|
|||
|
|
* @date 2021-07-16
|
|||
|
|
* @brief a simple dns server
|
|||
|
|
******************************************************************************
|
|||
|
|
* @attention
|
|||
|
|
*
|
|||
|
|
* <h2><center>© COPYRIGHT 2021 HUGE-IC</center></h2>
|
|||
|
|
*
|
|||
|
|
*
|
|||
|
|
******************************************************************************
|
|||
|
|
*/
|
|||
|
|
|
|||
|
|
#include "typesdef.h"
|
|||
|
|
#include "list.h"
|
|||
|
|
#include "osal/task.h"
|
|||
|
|
#include "osal/string.h"
|
|||
|
|
#include "osal/sleep.h"
|
|||
|
|
#include "lib/common/sysevt.h"
|
|||
|
|
#include "lwip/opt.h"
|
|||
|
|
#include "lwip/sockets.h"
|
|||
|
|
#include "netif/ethernetif.h"
|
|||
|
|
#include "lwip/ip.h"
|
|||
|
|
#include "lwip/init.h"
|
|||
|
|
#include "lwip/prot/dns.h"
|
|||
|
|
//#include "lib/net/dns/dns.h"
|
|||
|
|
#include "dns_eloop.h"
|
|||
|
|
#include "event.h"
|
|||
|
|
|
|||
|
|
|
|||
|
|
#define dns_dbg(fmt, ...) os_printf(fmt, ##__VA_ARGS__)
|
|||
|
|
#define dns_err(fmt, ...) os_printf(fmt, ##__VA_ARGS__)
|
|||
|
|
|
|||
|
|
#define DNS_RECVBUF_SIZE (512)
|
|||
|
|
|
|||
|
|
struct dns_mgr {
|
|||
|
|
struct netif *netif;
|
|||
|
|
int32 sock;
|
|||
|
|
uint8 recvbuf[DNS_RECVBUF_SIZE];
|
|||
|
|
uint8 stop: 1;
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
static struct dns_mgr *dns;
|
|||
|
|
|
|||
|
|
static void dns_query_refuse(struct sockaddr_in *addr, uint8 *data, uint32 len)
|
|||
|
|
{
|
|||
|
|
struct dns_hdr *hdr = (struct dns_hdr *)data;
|
|||
|
|
// 置起flags中response,并且返回query失败原因, 我们并未实现dns功能,只是拒绝了查询
|
|||
|
|
hdr->flags1 |= DNS_FLAG1_RESPONSE;
|
|||
|
|
hdr->flags2 &= ~DNS_FLAG2_ERR_MASK;
|
|||
|
|
hdr->flags2 |= 5; // 5: Refused - 服务器拒绝执行请求操作
|
|||
|
|
sendto(dns->sock, data, len, 0, (const struct sockaddr *)addr, sizeof(struct sockaddr));
|
|||
|
|
//dns_dbg("dns query refused - %s:%d\r\n", inet_ntoa(addr->sin_addr), ntohs(addr->sin_port));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
static void dns_task_eloop(void *ei, void *d)
|
|||
|
|
{
|
|||
|
|
int32 ret = 0;
|
|||
|
|
socklen_t len = 16; // 接收socket地址需要用
|
|||
|
|
struct sockaddr_in addr;
|
|||
|
|
struct dns_hdr *hdr;
|
|||
|
|
|
|||
|
|
ret = recvfrom(dns->sock, dns->recvbuf, DNS_RECVBUF_SIZE, 0, (struct sockaddr *)&addr, &len);
|
|||
|
|
// 最少dns_hdr长度12
|
|||
|
|
if (ret >= 12 && !dns->stop) {
|
|||
|
|
hdr = (struct dns_hdr *)dns->recvbuf;
|
|||
|
|
// 最少dns_hdr + dns_query = 12 + 4
|
|||
|
|
if (hdr->numquestions > 0 && ret >= (12 + 4)) {
|
|||
|
|
dns_query_refuse(&addr, dns->recvbuf, ret);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
__init static int32 _dns_start(char *ifname)
|
|||
|
|
{
|
|||
|
|
int32 ret = -1;
|
|||
|
|
int32 sock = -1;
|
|||
|
|
int32 optval = 1;
|
|||
|
|
struct sockaddr_in local_addr;
|
|||
|
|
struct ifreq nif;
|
|||
|
|
|
|||
|
|
dns = os_zalloc(sizeof(struct dns_mgr));
|
|||
|
|
if(dns == NULL)
|
|||
|
|
return -ENOMEM;
|
|||
|
|
|
|||
|
|
dns->netif = netif_find(ifname);
|
|||
|
|
if (dns->netif == NULL) {
|
|||
|
|
dns_err("netif:%s is not exist\r\n", ifname);
|
|||
|
|
return RET_ERR;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
sock = socket(AF_INET, SOCK_DGRAM, 0);
|
|||
|
|
if (sock == -1) {
|
|||
|
|
dns_err("create socket failed\r\n");
|
|||
|
|
return RET_ERR;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fcntl(sock, F_SETFL, O_NONBLOCK);
|
|||
|
|
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval));
|
|||
|
|
os_strncpy(nif.ifr_name, dns->netif->name, 2);
|
|||
|
|
setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &nif, sizeof(nif));
|
|||
|
|
os_memset(&local_addr, 0, sizeof(local_addr));
|
|||
|
|
local_addr.sin_family = AF_INET;
|
|||
|
|
local_addr.sin_port = htons(53);
|
|||
|
|
local_addr.sin_addr.s_addr = dns->netif->ip_addr.addr;
|
|||
|
|
ret = bind(sock, (struct sockaddr *)&local_addr, sizeof(struct sockaddr));
|
|||
|
|
if (ret == -1) {
|
|||
|
|
dns_err("bind fail\r\n");
|
|||
|
|
closesocket(sock);
|
|||
|
|
return RET_ERR;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
dns->sock = sock;
|
|||
|
|
dns_dbg("dns sock :%x\r\n", (uint32)sock);
|
|||
|
|
eloop_add_fd(dns->sock, EVENT_READ, EVENT_F_ENABLED, dns_task_eloop, NULL);
|
|||
|
|
|
|||
|
|
return RET_OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int32 dns_start_eloop(char *ifname)
|
|||
|
|
{
|
|||
|
|
int32 ret = 0;
|
|||
|
|
|
|||
|
|
if (ifname == NULL) {
|
|||
|
|
dns_err("invalid param!\r\n");
|
|||
|
|
return RET_ERR;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (dns) {
|
|||
|
|
dns->stop = 0;
|
|||
|
|
dns_err("dns already running ...\r\n");
|
|||
|
|
return RET_OK;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
ret = _dns_start(ifname);
|
|||
|
|
ASSERT(!ret);
|
|||
|
|
return ret;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
void dns_stop_eloop(char *ifname)
|
|||
|
|
{
|
|||
|
|
if(dns){
|
|||
|
|
dns->stop = 1;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
|