| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406 | 
							- /*
 
-  * 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"
 
- #include "usb_eth.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()
 
- {
 
- 	int i;
 
- 	for (i = 0; i < config->num_entry; i++)
 
- 		if (is_vacant(config->entries + i))
 
- 			return config->entries + 1;
 
- 	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 route
 
- //						*option_ptr++ = DHCP_STATICROUTE;
 
- //						*option_ptr++ = 8;
 
- //						*option_ptr++ = ((uint8_t *)&server_ip)[0];
 
- //						*option_ptr++ = ((uint8_t *)&server_ip)[1];
 
- //						*option_ptr++ = ((uint8_t *)&server_ip)[2];
 
- //						*option_ptr++ = 0;
 
- //						memcpy(option_ptr, &server_ip, 4);
 
- //						option_ptr += 4;
 
- //*/
 
- ///*
 
- //						*option_ptr++ = 0x2e; // NetBIOS over TCP/IP Node Type Option
 
- //						*option_ptr++ = 1;
 
- //						*option_ptr++ = 1;
 
- //						
 
- //						*option_ptr++ = 0x2c; // NetBIOS over TCP/IP Name Server Option
 
- //						*option_ptr++ = 4;
 
- //						memcpy(option_ptr, &server_ip, 4);
 
- //						option_ptr += 4;
 
- //*/
 
- //						/*
 
- //						*option_ptr++ = DHCP_MSCSR;
 
- //						*option_ptr++ = 8;
 
- //						*option_ptr++ = 24;
 
- //						*option_ptr++ = 192;
 
- //						*option_ptr++ = 168;
 
- //						*option_ptr++ = 0;
 
- //						*option_ptr++ = 192;
 
- //						*option_ptr++ = 168;
 
- //						*option_ptr++ = 0;
 
- //						*option_ptr++ = 11;
 
- //						*/
 
- //						// renewal time
 
- //						
 
- //						*option_ptr++ = DHCP_RENEWALTIME;
 
- //						*option_ptr++ = 4;
 
- //						*option_ptr++ = 0;
 
- //						*option_ptr++ = 0;
 
- //						*option_ptr++ = 0x38;
 
- //						*option_ptr++ = 0x40;
 
- //						
 
- //	
 
- //					// rebinding time
 
- //						
 
- //						*option_ptr++ = DHCP_REBINDTIME;
 
- //						*option_ptr++ = 4;
 
- //						*option_ptr++ = 0;
 
- //						*option_ptr++ = 0;
 
- //						*option_ptr++ = 0x62;
 
- //						*option_ptr++ = 0x70;
 
- //						
 
- ///*
 
- //						// domain name
 
- //						*option_ptr++ = DHCP_DNSDOMAIN;
 
- //						int len = sprintf((char*)option_ptr+1, "stm32f4.net");
 
- //						*option_ptr = (len + 1);
 
- //						option_ptr += (len + 2);
 
- //						// Option: (31) Perform Router Discover
 
- //						*option_ptr++ = DHCP_PERFORMROUTERDISC;
 
- //						*option_ptr++ = 1;
 
- //						*option_ptr++ = 1;
 
- //*/
 
- 						// end
 
- }
 
- static void udp_recv_proc(void *arg, struct udp_pcb *upcb, struct pbuf *p, struct ip_addr *addr, u16_t port)
 
- {
 
- 	uint8_t *ptr;
 
- 	dhcp_entry_t *entry;
 
- 	struct pbuf *pp;
 
- 	int 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);
 
- 			udp_sendto_if(upcb, pp, IP_ADDR_BROADCAST, port, &netif_data);
 
- 			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);
 
- 			udp_sendto_if(upcb, pp, IP_ADDR_BROADCAST, port, &netif_data);
 
- 			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;
 
- 	}
 
-     //typedef void (*udp_recv_fn)(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port);
 
- 	udp_recv(pcb, (udp_recv_fn)udp_recv_proc, NULL);
 
- 	config = c;
 
- 	return ERR_OK;
 
- }
 
- void dhserv_free(void)
 
- {
 
- 	if (pcb == NULL) return;
 
- 	udp_remove(pcb);
 
- 	pcb = NULL;
 
- }
 
 
  |