diff --git a/components/libc/dlib/README.md b/components/libc/dlib/README.md new file mode 100644 index 0000000000..846eb3f5c0 --- /dev/null +++ b/components/libc/dlib/README.md @@ -0,0 +1,4 @@ +Dlib(IAR) porting for RT-Thread. + +Please define RT_USING_LIBC and compile RT-Thread with IAR compiler. + diff --git a/components/libc/dlib/SConscript b/components/libc/dlib/SConscript new file mode 100644 index 0000000000..f0e53a9f3e --- /dev/null +++ b/components/libc/dlib/SConscript @@ -0,0 +1,15 @@ +from building import * +import rtconfig + +src = Glob('*.c') +cwd = GetCurrentDir() +group = [] + +CPPPATH = [cwd] +CPPDEFINES = ['RT_USING_DLIBC'] + +if rtconfig.PLATFORM == 'iar': + group = DefineGroup('dlib', src, depend = ['RT_USING_LIBC'], + CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES, LIBS = LIBS) + +Return('group') diff --git a/components/libc/dlib/environ.c b/components/libc/dlib/environ.c new file mode 100644 index 0000000000..1e44eb1627 --- /dev/null +++ b/components/libc/dlib/environ.c @@ -0,0 +1,25 @@ +/* File: environ.c + * this file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2015, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2015-01-28 Bernard first version + */ + +const char *__environ = "OS=RT-Thread"; + diff --git a/components/libc/dlib/rmtx.c b/components/libc/dlib/rmtx.c new file mode 100644 index 0000000000..d6ce920d67 --- /dev/null +++ b/components/libc/dlib/rmtx.c @@ -0,0 +1,73 @@ +/* + * File : rmtx.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2015, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2015-01-28 Bernard first version + */ +#include +#include + +/* + * for IAR compiler, we recommand to define _DLIB_THREAD_SUPPORT + * as 2 for dlib multi-thread support. + */ + +#if _DLIB_THREAD_SUPPORT +void _Mtxinit(_Rmtx *m) +{ + rt_mutex_t mutex; + + RT_ASSERT(m != RT_NULL); + + mutex = (rt_mutex_t)m; + rt_mutex_init(mutex, "iarMtx", RT_IPC_FLAG_FIFO); +} + +void _Mtxdst(_Rmtx *m) +{ + rt_mutex_t mutex; + + RT_ASSERT(m != RT_NULL); + + mutex = (rt_mutex_t)m; + rt_mutex_detach(mutex); +} + +void _Mtxlock(_Rmtx *m) +{ + rt_mutex_t mutex; + + RT_ASSERT(m != RT_NULL); + + mutex = (rt_mutex_t)m; + rt_mutex_take(mutex, RT_WAITING_FOREVER); +} + +void _Mtxunlock(_Rmtx *m) +{ + rt_mutex_t mutex; + + RT_ASSERT(m != RT_NULL); + + mutex = (rt_mutex_t)m; + rt_mutex_release(mutex); +} +#endif + diff --git a/components/libc/dlib/syscall_open.c b/components/libc/dlib/syscall_open.c new file mode 100644 index 0000000000..0aa0caf0cd --- /dev/null +++ b/components/libc/dlib/syscall_open.c @@ -0,0 +1,64 @@ +/* + * File : syscall_open.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2015, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2015-01-28 Bernard first version + */ + +#include +#include +#ifdef RT_USING_DFS +#include +#endif + +#pragma module_name = "?__open" + +int __open(const char *filename, int mode) +{ + if (mode & _LLIO_CREAT) + { + } + + if (mode & _LLIO_TEXT) + { + /* we didn't support text mode */ + } + + switch (mode & _LLIO_RDWRMASK) + { + case _LLIO_RDONLY: + /* The file should be opened for read only. */ + break; + + case _LLIO_WRONLY: + /* The file should be opened for write only. */ + break; + + case _LLIO_RDWR: + /* The file should be opened for both reads and writes. */ + break; + + default: + return -1; + } + + return handle; +} + diff --git a/components/libc/dlib/syscall_read.c b/components/libc/dlib/syscall_read.c new file mode 100644 index 0000000000..f109badb55 --- /dev/null +++ b/components/libc/dlib/syscall_read.c @@ -0,0 +1,51 @@ +/* + * File : syscall_read.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2015, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2015-01-28 Bernard first version + */ + +#include +#include + +#pragma module_name = "?__read" +size_t __read(int handle, unsigned char *buf, size_t len) +{ +#ifdef RT_USING_DFS + int size; +#endif + + if (handle == _LLIO_STDIN) + { + /* TODO */ + return 0; + } + + if ((handle == _LLIO_STDOUT) || (handle == _LLIO_STDERR)) + return _LLIO_ERROR; + +#ifndef RT_USING_DFS + return _LLIO_ERROR; +#else + size = read(handle - STDERR - 1, buf, len); + return size; +#endif +} + diff --git a/components/libc/dlib/syscall_write.c b/components/libc/dlib/syscall_write.c new file mode 100644 index 0000000000..5f21bf9bb9 --- /dev/null +++ b/components/libc/dlib/syscall_write.c @@ -0,0 +1,59 @@ +/* + * File : syscall_write.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2015, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2015-01-28 Bernard first version + */ + +#include +#include + +#pragma module_name = "?__write" + +size_t __write(int handle, const unsigned char *buf, size_t len) +{ +#ifdef RT_USING_DFS + int size; +#endif + + if ((handle == _LLIO_STDOUT) || (handle == _LLIO_STDERR)) + { +#ifndef RT_USING_CONSOLE + return _LLIO_ERROR; +#else + rt_device_t console_device; + + console_device = rt_console_get_device(); + if (console_device != 0) rt_device_write(console_device, 0, buf, len); + + return len; +#endif + } + + if (handle == STDIN) return -1; + +#ifndef RT_USING_DFS + return _LLIO_ERROR; +#else + size = write(handle - STDERR - 1, buf, len); + return size; +#endif +} + diff --git a/components/libc/dlib/syscalls.c b/components/libc/dlib/syscalls.c new file mode 100644 index 0000000000..f1802a98b8 --- /dev/null +++ b/components/libc/dlib/syscalls.c @@ -0,0 +1,68 @@ +/* + * File : syscalls.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2015, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2015-01-28 Bernard first version + */ +#include +#ifdef RT_USING_DFS +#include +#endif +#include + +#pragma module_name = "?__close" +int __close(int handle) +{ + if (handle == _LLIO_STDOUT || + handle == _LLIO_STDERR || + handle == _LLIO_STDIN) + return _LLIO_ERROR; + +#ifdef RT_USING_DFS + return close(handle); +#else + return 0; +#endif +} + +#pragma module_name = "?remove" +int remove(const char *val) +{ +#ifdef RT_USING_DFS + dfs_file_unlink(val); +#endif + + return 0; +} + +#pragma module_name = "?__lseek" +long __lseek(int handle, long offset, int whence) +{ +#ifdef RT_USING_DFS +#endif + + if (handle == _LLIO_STDOUT || + handle == _LLIO_STDERR || + handle == _LLIO_STDIN) + return _LLIO_ERROR; + + return lseek(handle, offset, whence); +} + diff --git a/components/libc/dlib/syscalls.h b/components/libc/dlib/syscalls.h new file mode 100644 index 0000000000..2c38854f72 --- /dev/null +++ b/components/libc/dlib/syscalls.h @@ -0,0 +1,23 @@ +/* File: syscalls.h + * this file is part of RT-Thread RTOS + * COPYRIGHT (C) 2006 - 2015, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2015-01-28 Bernard first version + */ + diff --git a/components/net/lwip-1.4.1/src/lwipopts.h b/components/net/lwip-1.4.1/src/lwipopts.h index db2019bd72..cb7def8ae6 100644 --- a/components/net/lwip-1.4.1/src/lwipopts.h +++ b/components/net/lwip-1.4.1/src/lwipopts.h @@ -162,9 +162,9 @@ #define SYS_LIGHTWEIGHT_PROT (NO_SYS==0) #ifdef LWIP_USING_NAT -#define LWIP_NAT 1 +#define IP_NAT 1 #else -#define LWIP_NAT 0 +#define IP_NAT 0 #endif /* ---------- TCP options ---------- */ diff --git a/components/net/lwip_dhcpd/SConscript b/components/net/lwip_dhcpd/SConscript new file mode 100644 index 0000000000..d5704c8c8b --- /dev/null +++ b/components/net/lwip_dhcpd/SConscript @@ -0,0 +1,10 @@ +from building import * + +cwd = GetCurrentDir() +src = Glob('*.c') + +CPPPATH = [cwd] + +group = DefineGroup('LwIP', src, depend = ['RT_USING_LWIP', 'LWIP_USING_DHCPD'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/net/lwip_dhcpd/dhcp_server.c b/components/net/lwip_dhcpd/dhcp_server.c new file mode 100644 index 0000000000..47547a598b --- /dev/null +++ b/components/net/lwip_dhcpd/dhcp_server.c @@ -0,0 +1,398 @@ +/* + * File : dhcp_server.c + * A simple DHCP server implementation + * + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2013-2015, Shanghai Real-Thread Technology Co., Ltd + * http://www.rt-thread.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2013-01-30 aozima the first version + * 2013-08-08 aozima support different network segments. + * 2015-01-30 bernard release to RT-Thread RTOS. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* DHCP server option */ + +/* allocated client ip range */ +#ifndef DHCPD_CLIENT_IP_MIN +#define DHCPD_CLIENT_IP_MIN 2 +#endif +#ifndef DHCPD_CLIENT_IP_MAX +#define DHCPD_CLIENT_IP_MAX 254 +#endif + +/* the DHCP server address */ +#ifndef DHCPD_SERVER_IPADDR0 +#define DHCPD_SERVER_IPADDR0 192UL +#define DHCPD_SERVER_IPADDR1 168UL +#define DHCPD_SERVER_IPADDR2 169UL +#define DHCPD_SERVER_IPADDR3 1UL +#endif + +//#define DHCP_DEBUG_PRINTF + +#ifdef DHCP_DEBUG_PRINTF +#define DEBUG_PRINTF rt_kprintf("[DHCP] "); rt_kprintf +#else +#define DEBUG_PRINTF(...) +#endif /* DHCP_DEBUG_PRINTF */ + +/* we need some routines in the DHCP of lwIP */ +#undef LWIP_DHCP +#define LWIP_DHCP 1 +#include + +/* buffer size for receive DHCP packet */ +#define BUFSZ 1024 + +static uint8_t next_client_ip = DHCPD_CLIENT_IP_MIN; +static rt_err_t _low_level_dhcp_send(struct netif *netif, + const void *buffer, + rt_size_t size) +{ + struct pbuf *p; + struct eth_hdr *ethhdr; + struct ip_hdr *iphdr; + struct udp_hdr *udphdr; + + p = pbuf_alloc(PBUF_LINK, + SIZEOF_ETH_HDR + sizeof(struct ip_hdr) + + sizeof(struct udp_hdr) + size, + PBUF_RAM); + if (p == RT_NULL) return -RT_ENOMEM; + + ethhdr = (struct eth_hdr *)p->payload; + iphdr = (struct ip_hdr *)((char *)ethhdr + SIZEOF_ETH_HDR); + udphdr = (struct udp_hdr *)((char *)iphdr + sizeof(struct ip_hdr)); + + ETHADDR32_COPY(ðhdr->dest, (struct eth_addr *)ðbroadcast); + ETHADDR16_COPY(ðhdr->src, netif->hwaddr); + ethhdr->type = PP_HTONS(ETHTYPE_IP); + + iphdr->src.addr = 0x00000000; /* src: 0.0.0.0 */ + iphdr->dest.addr = 0xFFFFFFFF; /* src: 255.255.255.255 */ + + IPH_VHL_SET(iphdr, 4, IP_HLEN / 4); + IPH_TOS_SET(iphdr, 0x00); + IPH_LEN_SET(iphdr, htons(IP_HLEN + sizeof(struct udp_hdr) + size)); + IPH_ID_SET(iphdr, htons(2)); + IPH_OFFSET_SET(iphdr, 0); + IPH_TTL_SET(iphdr, 255); + IPH_PROTO_SET(iphdr, IP_PROTO_UDP); + IPH_CHKSUM_SET(iphdr, 0); + IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN)); + + udphdr->src = htons(DHCP_SERVER_PORT); + udphdr->dest = htons(DHCP_CLIENT_PORT); + udphdr->len = htons(sizeof(struct udp_hdr) + size); + udphdr->chksum = 0; + + memcpy((char *)udphdr + sizeof(struct udp_hdr), + buffer, size); + + return netif->linkoutput(netif, p); +} + +static void dhcpd_thread_entry(void *parameter) +{ + struct netif *netif = RT_NULL; + int sock; + int bytes_read; + char *recv_data; + rt_uint32_t addr_len; + struct sockaddr_in server_addr, client_addr; + struct dhcp_msg *msg; + int optval = 1; + + /* get ethernet interface. */ + netif = (struct netif*) parameter; + RT_ASSERT(netif != RT_NULL); + + /* our DHCP server information */ + DEBUG_PRINTF("DHCP server IP: %d.%d.%d.%d client IP: %d.%d.%d.%d-%d\n", + DHCPD_SERVER_IPADDR0, DHCPD_SERVER_IPADDR1, + DHCPD_SERVER_IPADDR2, DHCPD_SERVER_IPADDR3, + DHCPD_SERVER_IPADDR0, DHCPD_SERVER_IPADDR1, + DHCPD_SERVER_IPADDR2, DHCPD_CLIENT_IP_MIN, DHCPD_CLIENT_IP_MAX); + + /* allocate buffer for receive */ + recv_data = rt_malloc(BUFSZ); + if (recv_data == RT_NULL) + { + /* No memory */ + DEBUG_PRINTF("Out of memory\n"); + return; + } + + /* create a socket with UDP */ + if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) + { + DEBUG_PRINTF("create socket failed, errno = %d\n", errno); + rt_free(recv_data); + return; + } + + /* set to receive broadcast packet */ + setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)); + + /* initialize server address */ + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(DHCP_SERVER_PORT); + server_addr.sin_addr.s_addr = INADDR_ANY; + rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero)); + + /* bind socket to the server address */ + if (bind(sock, (struct sockaddr *)&server_addr, + sizeof(struct sockaddr)) == -1) + { + /* bind failed. */ + DEBUG_PRINTF("bind server address failed, errno=%d\n", errno); + rt_free(recv_data); + return; + } + + addr_len = sizeof(struct sockaddr); + DEBUG_PRINTF("DHCP server listen on port %d...\n", DHCP_SERVER_PORT); + + while (1) + { + bytes_read = recvfrom(sock, recv_data, BUFSZ - 1, 0, + (struct sockaddr *)&client_addr, &addr_len); + if (bytes_read < DHCP_MSG_LEN) + { + DEBUG_PRINTF("packet too short, wait for next!\n"); + continue; + } + + msg = (struct dhcp_msg *)recv_data; + /* check message type to make sure we can handle it */ + if ((msg->op != DHCP_BOOTREQUEST) || (msg->cookie != PP_HTONL(DHCP_MAGIC_COOKIE))) + { + continue; + } + + /* handler. */ + { + uint8_t *dhcp_opt; + uint8_t option; + uint8_t length; + + uint8_t message_type = 0; + uint8_t finished = 0; + uint32_t request_ip = 0; + + dhcp_opt = (uint8_t *)msg + DHCP_OPTIONS_OFS; + while (finished == 0) + { + option = *dhcp_opt; + length = *(dhcp_opt + 1); + + switch (option) + { + case DHCP_OPTION_REQUESTED_IP: + request_ip = *(dhcp_opt + 2) << 24 | *(dhcp_opt + 3) << 16 + | *(dhcp_opt + 4) << 8 | *(dhcp_opt + 5); + break; + + case DHCP_OPTION_END: + finished = 1; + break; + + case DHCP_OPTION_MESSAGE_TYPE: + message_type = *(dhcp_opt + 2); + break; + + default: + break; + } /* switch(option) */ + + dhcp_opt += (2 + length); + } + + /* reply. */ + dhcp_opt = (uint8_t *)msg + DHCP_OPTIONS_OFS; + + /* check. */ + if (request_ip) + { + uint32_t client_ip = DHCPD_SERVER_IPADDR0 << 24 | DHCPD_SERVER_IPADDR1 << 16 + | DHCPD_SERVER_IPADDR2 << 8 | (next_client_ip); + + if (request_ip != client_ip) + { + *dhcp_opt++ = DHCP_OPTION_MESSAGE_TYPE; + *dhcp_opt++ = DHCP_OPTION_MESSAGE_TYPE_LEN; + *dhcp_opt++ = DHCP_NAK; + *dhcp_opt++ = DHCP_OPTION_END; + + DEBUG_PRINTF("requested IP invalid, reply DHCP_NAK\n"); + if (netif != RT_NULL) + { + int send_byte = (dhcp_opt - (uint8_t *)msg); + _low_level_dhcp_send(netif, msg, send_byte); + DEBUG_PRINTF("DHCP server send %d byte\n", send_byte); + } + next_client_ip++; + if (next_client_ip > DHCPD_CLIENT_IP_MAX) + next_client_ip = DHCPD_CLIENT_IP_MIN; + continue; + } + } + + if (message_type == DHCP_DISCOVER) + { + DEBUG_PRINTF("request DHCP_DISCOVER\n"); + DEBUG_PRINTF("reply DHCP_OFFER\n"); + + // DHCP_OPTION_MESSAGE_TYPE + *dhcp_opt++ = DHCP_OPTION_MESSAGE_TYPE; + *dhcp_opt++ = DHCP_OPTION_MESSAGE_TYPE_LEN; + *dhcp_opt++ = DHCP_OFFER; + + // DHCP_OPTION_SERVER_ID + *dhcp_opt++ = DHCP_OPTION_SERVER_ID; + *dhcp_opt++ = 4; + *dhcp_opt++ = DHCPD_SERVER_IPADDR0; + *dhcp_opt++ = DHCPD_SERVER_IPADDR1; + *dhcp_opt++ = DHCPD_SERVER_IPADDR2; + *dhcp_opt++ = DHCPD_SERVER_IPADDR3; + + // DHCP_OPTION_LEASE_TIME + *dhcp_opt++ = DHCP_OPTION_LEASE_TIME; + *dhcp_opt++ = 4; + *dhcp_opt++ = 0x00; + *dhcp_opt++ = 0x01; + *dhcp_opt++ = 0x51; + *dhcp_opt++ = 0x80; + } + else if (message_type == DHCP_REQUEST) + { + DEBUG_PRINTF("request DHCP_REQUEST\n"); + DEBUG_PRINTF("reply DHCP_ACK\n"); + + // DHCP_OPTION_MESSAGE_TYPE + *dhcp_opt++ = DHCP_OPTION_MESSAGE_TYPE; + *dhcp_opt++ = DHCP_OPTION_MESSAGE_TYPE_LEN; + *dhcp_opt++ = DHCP_ACK; + + // DHCP_OPTION_SERVER_ID + *dhcp_opt++ = DHCP_OPTION_SERVER_ID; + *dhcp_opt++ = 4; + *dhcp_opt++ = DHCPD_SERVER_IPADDR0; + *dhcp_opt++ = DHCPD_SERVER_IPADDR1; + *dhcp_opt++ = DHCPD_SERVER_IPADDR2; + *dhcp_opt++ = DHCPD_SERVER_IPADDR3; + + // DHCP_OPTION_SUBNET_MASK + *dhcp_opt++ = DHCP_OPTION_SUBNET_MASK; + *dhcp_opt++ = 4; + *dhcp_opt++ = 0xFF; + *dhcp_opt++ = 0xFF; + *dhcp_opt++ = 0xFF; + *dhcp_opt++ = 0x00; + +#ifdef DHCPD_USING_ROUTER + // DHCP_OPTION_ROUTER + *dhcp_opt++ = DHCP_OPTION_ROUTER; + *dhcp_opt++ = 4; + *dhcp_opt++ = DHCPD_SERVER_IPADDR0; + *dhcp_opt++ = DHCPD_SERVER_IPADDR1; + *dhcp_opt++ = DHCPD_SERVER_IPADDR2; + *dhcp_opt++ = 1; +#endif + + // DHCP_OPTION_DNS_SERVER, use the default DNS server address in lwIP + *dhcp_opt++ = DHCP_OPTION_DNS_SERVER; + *dhcp_opt++ = 4; + *dhcp_opt++ = 208; + *dhcp_opt++ = 67; + *dhcp_opt++ = 222; + *dhcp_opt++ = 222; + + // DHCP_OPTION_LEASE_TIME + *dhcp_opt++ = DHCP_OPTION_LEASE_TIME; + *dhcp_opt++ = 4; + *dhcp_opt++ = 0x00; + *dhcp_opt++ = 0x01; + *dhcp_opt++ = 0x51; + *dhcp_opt++ = 0x80; + } + else + { + DEBUG_PRINTF("un handle message:%d\n", message_type); + } + + // append DHCP_OPTION_END + *dhcp_opt++ = DHCP_OPTION_END; + + /* send reply. */ + if ((message_type == DHCP_DISCOVER) || (message_type == DHCP_REQUEST)) + { + msg->op = DHCP_BOOTREPLY; + IP4_ADDR(&msg->yiaddr, + DHCPD_SERVER_IPADDR0, DHCPD_SERVER_IPADDR1, + DHCPD_SERVER_IPADDR2, next_client_ip); + + client_addr.sin_addr.s_addr = INADDR_BROADCAST; + + if (netif != RT_NULL) + { + int send_byte = (dhcp_opt - (uint8_t *)msg); + _low_level_dhcp_send(netif, msg, send_byte); + DEBUG_PRINTF("DHCP server send %d byte\n", send_byte); + } + } + } /* handler. */ + } +} + +void dhcpd_start(char* netif_name) +{ + rt_thread_t thread; + struct netif *netif = RT_NULL; + + /* find ethernet interface. */ + netif = netif_find(netif_name); + if (netif == RT_NULL) + { + DEBUG_PRINTF("Not found network interface:%s\n", netif_name); + } + + thread = rt_thread_create("dhcpd", + dhcpd_thread_entry, netif, + 1024, + RT_THREAD_PRIORITY_MAX - 3, + 2); + if (thread != RT_NULL) + { + rt_thread_startup(thread); + } +} + diff --git a/components/net/lwip_dhcpd/dhcp_server.h b/components/net/lwip_dhcpd/dhcp_server.h new file mode 100644 index 0000000000..4bd1163706 --- /dev/null +++ b/components/net/lwip_dhcpd/dhcp_server.h @@ -0,0 +1,36 @@ +/* + * File : dhcp_server.h + * A simple DHCP server implementation + * + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2013-2015, Shanghai Real-Thread Technology Co., Ltd + * http://www.rt-thread.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2013-01-30 aozima the first version + * 2013-08-08 aozima support different network segments. + * 2015-01-30 bernard release to RT-Thread RTOS. + */ + +#ifndef DHCPV4_SERVER_H__ +#define DHCPV4_SERVER_H__ + +void dhcpd_start(char* netif_name); + +#endif + diff --git a/components/net/lwip_nat/ipv4_nat.c b/components/net/lwip_nat/ipv4_nat.c index 58fe18562d..13c1877f2c 100644 --- a/components/net/lwip_nat/ipv4_nat.c +++ b/components/net/lwip_nat/ipv4_nat.c @@ -103,6 +103,7 @@ #include "lwip/udp.h" #include "lwip/mem.h" #include "lwip/sys.h" +#include "lwip/timers.h" #include "netif/etharp.h" #include @@ -116,9 +117,10 @@ #define LWIP_NAT_TTL_INFINITE (INT_MAX) #define LWIP_NAT_DEFAULT_TTL_SECONDS (128) #define LWIP_NAT_FORWARD_HEADER_SIZE_MIN (sizeof(struct eth_hdr)) -#define LWIP_NAT_DEFAULT_STATE_TABLES_ICMP (2) -#define LWIP_NAT_DEFAULT_STATE_TABLES_TCP (16) -#define LWIP_NAT_DEFAULT_STATE_TABLES_UDP (16) + +#define LWIP_NAT_DEFAULT_STATE_TABLES_ICMP (4) +#define LWIP_NAT_DEFAULT_STATE_TABLES_TCP (32) +#define LWIP_NAT_DEFAULT_STATE_TABLES_UDP (32) #define LWIP_NAT_DEFAULT_TCP_SOURCE_PORT (40000) #define LWIP_NAT_DEFAULT_UDP_SOURCE_PORT (40000) @@ -249,12 +251,12 @@ ip_nat_init(void) IPNAT_ENTRY_RESET(&ip_nat_udp_table[i].common); } - /* we must lock scheduler to protect following code */ + /* we must lock scheduler to protect following code */ rt_enter_critical(); - + /* add a lwip timer for NAT */ sys_timeout(LWIP_NAT_TMR_INTERVAL_SEC, nat_timer, NULL); - + /* un-protect */ rt_exit_critical(); } @@ -360,7 +362,7 @@ ip_nat_reset_state(ip_nat_conf_t *cfg) { int i; - /* @todo: optimize this!!! + /* @todo: optimize this!!! why do we search for it anyway, if we have the pointer??? */ for (i = 0; i < LWIP_NAT_DEFAULT_STATE_TABLES_ICMP; i++) { if(ip_nat_icmp_table[i].common.cfg == cfg) { @@ -391,7 +393,7 @@ ip_nat_shallnat(const struct ip_hdr *iphdr) ip_nat_conf_t *nat_config = ip_nat_cfg; for (nat_config = ip_nat_cfg; nat_config != NULL; nat_config = nat_config->next) { - if (ip_addr_netcmp(&(iphdr->dest), &(nat_config->entry.dest_net), + if (ip_addr_netcmp(&(iphdr->dest), &(nat_config->entry.dest_net), &(nat_config->entry.dest_netmask)) || ip_addr_netcmp(&(iphdr->src), &(nat_config->entry.source_net), &(nat_config->entry.source_netmask))) { @@ -434,7 +436,7 @@ ip_nat_check_header(struct pbuf *p, u16_t min_size) * @return 1 if the packet has been consumed (it was a NAT packet), * 0 if the packet has not been consumed (no NAT packet) */ -u8_t +u8_t ip_nat_input(struct pbuf *p) { struct ip_hdr *iphdr = (struct ip_hdr*)p->payload; @@ -537,6 +539,7 @@ ip_nat_input(struct pbuf *p) q = pbuf_alloc(PBUF_LINK, 0, PBUF_RAM); if (q == NULL) { LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_input: no pbuf for outgoing header\n")); + // rt_kprintf("ip_nat_input: no pbuf for outgoing header\n"); /* @todo: stats? */ pbuf_free(p); p = NULL; @@ -548,11 +551,13 @@ ip_nat_input(struct pbuf *p) /* restore p->payload to IP header */ if (pbuf_header(p, -PBUF_LINK_HLEN)) { LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_input: restoring header failed\n")); + // rt_kprintf("ip_nat_input: restoring header failed\n"); /* @todo: stats? */ pbuf_free(p); p = NULL; return 1; } + else q = p; } /* if we come here, q is the pbuf to send (either points to p or to a chain) */ in_if = nat_entry.cmn->cfg->entry.in_if; @@ -571,6 +576,7 @@ ip_nat_input(struct pbuf *p) LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_input: failed to send rewritten packet. link layer returned %d\n", err)); + // rt_kprintf("ip_nat_input: failed to send rewritten packet. link layer returned %d\n", err); } /* now that q (and/or p) is sent (or not), give up the reference to it this frees the input pbuf (p) as we have consumed it. */ @@ -735,6 +741,7 @@ ip_nat_out(struct pbuf *p) if (err != ERR_OK) { LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_out: failed to send rewritten packet. link layer returned %d\n", err)); + // rt_kprintf("ip_nat_out: failed to send rewritten packet. link layer returned %d\n", err); } else { sent = 1; } @@ -841,6 +848,7 @@ ip_nat_udp_lookup_outgoing(ip_nat_conf_t *nat_config, const struct ip_hdr *iphdr nat_entry.udp); } else { LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_udp_lookup_outgoing: no more NAT entries available\n")); + // rt_kprintf("ip_nat_udp_lookup_outgoing: no more NAT entries available\n"); } } } @@ -925,6 +933,7 @@ ip_nat_tcp_lookup_outgoing(ip_nat_conf_t *nat_config, const struct ip_hdr *iphdr nat_entry.tcp); } else { LWIP_DEBUGF(LWIP_NAT_DEBUG, ("ip_nat_udp_lookup_outgoing: no more NAT entries available\n")); + // rt_kprintf("ip_nat_udp_lookup_outgoing: no more NAT entries available\n"); } } } @@ -1004,9 +1013,9 @@ ip_nat_dbg_dump(const char *msg, const struct ip_hdr *iphdr) LWIP_ASSERT("NULL != msg", NULL != msg); LWIP_ASSERT("NULL != iphdr", NULL != iphdr); LWIP_DEBUGF(LWIP_NAT_DEBUG, ("%s: IP: (", msg)); - ip_nat_dbg_dump_ip(&iphdr->src); + ip_nat_dbg_dump_ip((ip_addr_t *)&(iphdr->src)); LWIP_DEBUGF(LWIP_NAT_DEBUG, (" --> ")); - ip_nat_dbg_dump_ip(&iphdr->dest); + ip_nat_dbg_dump_ip((ip_addr_t *)&(iphdr->dest)); LWIP_DEBUGF(LWIP_NAT_DEBUG, (" id=%" U16_F ", chksum=%" U16_F ")\n", ntohs(IPH_ID(iphdr)), ntohs(IPH_CHKSUM(iphdr)))); }