1 /* 2 * File : dhcp_server_raw.c 3 * A simple DHCP server implementation 4 * COPYRIGHT (C) 2011-2018, Shanghai Real-Thread Technology Co., Ltd 5 * http://www.rt-thread.com 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without modification, 9 * are permitted provided that the following conditions are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright notice, 12 * this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright notice, 14 * this list of conditions and the following disclaimer in the documentation 15 * and/or other materials provided with the distribution. 16 * 3. The name of the author may not be used to endorse or promote products 17 * derived from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 20 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 22 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 24 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 28 * OF SUCH DAMAGE. 29 * 30 * Change Logs: 31 * Date Author Notes 32 * 2014-04-01 Ren.Haibo the first version 33 * 2018-06-12 aozima ignore DHCP_OPTION_SERVER_ID. 34 */ 35 36 #include <stdio.h> 37 #include <stdint.h> 38 39 #include <rtthread.h> 40 41 #include <lwip/opt.h> 42 #include <lwip/sockets.h> 43 #include <lwip/inet_chksum.h> 44 #include <netif/etharp.h> 45 #include <netif/ethernetif.h> 46 #include <lwip/ip.h> 47 #include <lwip/init.h> 48 49 #if (LWIP_VERSION) < 0x02000000U 50 #error "not support old LWIP" 51 #endif 52 53 #if !LWIP_IPV4 54 #error "must enable IPV4" 55 #endif 56 57 #if (LWIP_VERSION) >= 0x02000000U 58 #include <lwip/prot/dhcp.h> 59 #endif 60 61 /* DHCP server option */ 62 63 /* allocated client ip range */ 64 #ifndef DHCPD_CLIENT_IP_MIN 65 #define DHCPD_CLIENT_IP_MIN 2 66 #endif 67 #ifndef DHCPD_CLIENT_IP_MAX 68 #define DHCPD_CLIENT_IP_MAX 254 69 #endif 70 71 /* the DHCP server address */ 72 #ifndef DHCPD_SERVER_IP 73 #define DHCPD_SERVER_IP "192.168.169.1" 74 #endif 75 76 #define DHCP_DEBUG_PRINTF 77 78 #ifdef DHCP_DEBUG_PRINTF 79 #define DEBUG_PRINTF rt_kprintf("[DHCP] "); rt_kprintf 80 #else 81 #define DEBUG_PRINTF(...) 82 #endif /* DHCP_DEBUG_PRINTF */ 83 84 /* we need some routines in the DHCP of lwIP */ 85 #undef LWIP_DHCP 86 #define LWIP_DHCP 1 87 #include <lwip/dhcp.h> 88 89 /** Mac address length */ 90 #define DHCP_MAX_HLEN 6 91 /** dhcp default live time */ 92 #define DHCP_DEFAULT_LIVE_TIME 0x80510100 93 94 /** Minimum length for request before packet is parsed */ 95 #define DHCP_MIN_REQUEST_LEN 44 96 97 #define LWIP_NETIF_LOCK(...) 98 #define LWIP_NETIF_UNLOCK(...) 99 100 /** 101 * The dhcp client node struct. 102 */ 103 struct dhcp_client_node 104 { 105 struct dhcp_client_node *next; 106 u8_t chaddr[DHCP_MAX_HLEN]; 107 ip4_addr_t ipaddr; 108 u32_t lease_end; 109 }; 110 111 /** 112 * The dhcp server struct. 113 */ 114 struct dhcp_server 115 { 116 struct dhcp_server *next; 117 struct netif *netif; 118 struct udp_pcb *pcb; 119 struct dhcp_client_node *node_list; 120 ip4_addr_t start; 121 ip4_addr_t end; 122 ip4_addr_t current; 123 }; 124 125 static u8_t *dhcp_server_option_find(u8_t *buf, u16_t len, u8_t option); 126 127 /** 128 * The dhcp server struct list. 129 */ 130 static struct dhcp_server *lw_dhcp_server; 131 132 /** 133 * Find a dhcp client node by mac address 134 * 135 * @param dhcpserver The dhcp server 136 * @param chaddr Mac address 137 * @param hlen Mac address length 138 * @return dhcp client node 139 */ 140 static struct dhcp_client_node * 141 dhcp_client_find_by_mac(struct dhcp_server *dhcpserver, const u8_t *chaddr, u8_t hlen) 142 { 143 struct dhcp_client_node *node; 144 145 for (node = dhcpserver->node_list; node != NULL; node = node->next) 146 { 147 if (memcmp(node->chaddr, chaddr, hlen) == 0) 148 { 149 return node; 150 } 151 } 152 153 return NULL; 154 } 155 156 /** 157 * Find a dhcp client node by ip address 158 * 159 * @param dhcpserver The dhcp server 160 * @param chaddr Mac address 161 * @param hlen Mac address length 162 * @return dhcp client node 163 */ 164 static struct dhcp_client_node * 165 dhcp_client_find_by_ip(struct dhcp_server *dhcpserver, const ip4_addr_t *ip) 166 { 167 struct dhcp_client_node *node; 168 169 for (node = dhcpserver->node_list; node != NULL; node = node->next) 170 { 171 if (ip4_addr_cmp(&node->ipaddr, ip)) 172 { 173 return node; 174 } 175 } 176 177 return NULL; 178 } 179 180 /** 181 * Find a dhcp client node by ip address 182 * 183 * @param dhcpserver The dhcp server 184 * @param chaddr Mac address 185 * @param hlen Mac address length 186 * @return dhcp client node 187 */ 188 static struct dhcp_client_node * 189 dhcp_client_find(struct dhcp_server *dhcpserver, struct dhcp_msg *msg, 190 u8_t *opt_buf, u16_t len) 191 { 192 u8_t *opt; 193 //u32_t ipaddr; 194 struct dhcp_client_node *node; 195 196 node = dhcp_client_find_by_mac(dhcpserver, msg->chaddr, msg->hlen); 197 if (node != NULL) 198 { 199 return node; 200 } 201 202 opt = dhcp_server_option_find(opt_buf, len, DHCP_OPTION_REQUESTED_IP); 203 if (opt != NULL) 204 { 205 node = dhcp_client_find_by_ip(dhcpserver, (ip4_addr_t *)(&opt[2])); 206 if (node != NULL) 207 { 208 return node; 209 } 210 } 211 212 return NULL; 213 } 214 215 /** 216 * Find a dhcp client node by ip address 217 * 218 * @param dhcpserver The dhcp server 219 * @param chaddr Mac address 220 * @param hlen Mac address length 221 * @return dhcp client node 222 */ 223 static struct dhcp_client_node * 224 dhcp_client_alloc(struct dhcp_server *dhcpserver, struct dhcp_msg *msg, 225 u8_t *opt_buf, u16_t len) 226 { 227 u8_t *opt; 228 u32_t ipaddr; 229 struct dhcp_client_node *node; 230 231 node = dhcp_client_find_by_mac(dhcpserver, msg->chaddr, msg->hlen); 232 if (node != NULL) 233 { 234 return node; 235 } 236 237 opt = dhcp_server_option_find(opt_buf, len, DHCP_OPTION_REQUESTED_IP); 238 if (opt != NULL) 239 { 240 node = dhcp_client_find_by_ip(dhcpserver, (ip4_addr_t *)(&opt[2])); 241 if (node != NULL) 242 { 243 return node; 244 } 245 } 246 247 dhcp_alloc_again: 248 node = dhcp_client_find_by_ip(dhcpserver, &dhcpserver->current); 249 if (node != NULL) 250 { 251 ipaddr = (ntohl(dhcpserver->current.addr) + 1); 252 if (ipaddr > ntohl(dhcpserver->end.addr)) 253 { 254 ipaddr = ntohl(dhcpserver->start.addr); 255 } 256 dhcpserver->current.addr = htonl(ipaddr); 257 goto dhcp_alloc_again; 258 } 259 node = (struct dhcp_client_node *)mem_malloc(sizeof(struct dhcp_client_node)); 260 if (node == NULL) 261 { 262 return NULL; 263 } 264 SMEMCPY(node->chaddr, msg->chaddr, msg->hlen); 265 node->ipaddr = dhcpserver->current; 266 267 node->next = dhcpserver->node_list; 268 dhcpserver->node_list = node; 269 270 return node; 271 } 272 273 /** 274 * find option from buffer. 275 * 276 * @param buf The buffer to find option 277 * @param len The buffer length 278 * @param option Which option to find 279 * @return dhcp option buffer 280 */ 281 static u8_t * 282 dhcp_server_option_find(u8_t *buf, u16_t len, u8_t option) 283 { 284 u8_t *end = buf + len; 285 while ((buf < end) && (*buf != DHCP_OPTION_END)) 286 { 287 if (*buf == option) 288 { 289 return buf; 290 } 291 buf += (buf[1] + 2); 292 } 293 return NULL; 294 } 295 296 /** 297 * If an incoming DHCP message is in response to us, then trigger the state machine 298 */ 299 static void 300 dhcp_server_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *recv_addr, u16_t port) 301 { 302 struct dhcp_server *dhcp_server = (struct dhcp_server *)arg; 303 struct dhcp_msg *msg; 304 struct pbuf *q; 305 u8_t *opt_buf; 306 u8_t *opt; 307 struct dhcp_client_node *node; 308 u8_t msg_type; 309 u16_t length; 310 ip_addr_t addr = *recv_addr; 311 u32_t tmp; 312 313 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("[%s:%d] %c%c recv %d\n", __FUNCTION__, __LINE__, dhcp_server->netif->name[0], dhcp_server->netif->name[1], p->tot_len)); 314 /* prevent warnings about unused arguments */ 315 LWIP_UNUSED_ARG(pcb); 316 LWIP_UNUSED_ARG(addr); 317 LWIP_UNUSED_ARG(port); 318 319 if (p->len < DHCP_MIN_REQUEST_LEN) 320 { 321 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("DHCP request message or pbuf too short\n")); 322 pbuf_free(p); 323 return; 324 } 325 326 q = pbuf_alloc(PBUF_TRANSPORT, 1500, PBUF_RAM); 327 if (q == NULL) 328 { 329 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("pbuf_alloc dhcp_msg failed!\n")); 330 pbuf_free(p); 331 return; 332 } 333 if (q->tot_len < p->tot_len) 334 { 335 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("pbuf_alloc dhcp_msg too small %d:%d\n", q->tot_len, p->tot_len)); 336 pbuf_free(p); 337 return; 338 } 339 340 pbuf_copy(q, p); 341 pbuf_free(p); 342 343 msg = (struct dhcp_msg *)q->payload; 344 if (msg->op != DHCP_BOOTREQUEST) 345 { 346 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("not a DHCP request message, but type %"U16_F"\n", (u16_t)msg->op)); 347 goto free_pbuf_and_return; 348 } 349 350 if (msg->cookie != PP_HTONL(DHCP_MAGIC_COOKIE)) 351 { 352 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE | LWIP_DBG_LEVEL_WARNING, ("bad DHCP_MAGIC_COOKIE!\n")); 353 goto free_pbuf_and_return; 354 } 355 356 if (msg->hlen > DHCP_MAX_HLEN) 357 { 358 goto free_pbuf_and_return; 359 } 360 361 opt_buf = (u8_t *)msg + DHCP_OPTIONS_OFS; 362 length = q->tot_len - DHCP_OPTIONS_OFS; 363 opt = dhcp_server_option_find(opt_buf, length, DHCP_OPTION_MESSAGE_TYPE); 364 if (opt) 365 { 366 msg_type = *(opt + 2); 367 if (msg_type == DHCP_DISCOVER) 368 { 369 node = dhcp_client_alloc(dhcp_server, msg, opt_buf, length); 370 if (node == NULL) 371 { 372 goto free_pbuf_and_return; 373 } 374 node->lease_end = DHCP_DEFAULT_LIVE_TIME; 375 /* create dhcp offer and send */ 376 msg->op = DHCP_BOOTREPLY; 377 msg->hops = 0; 378 msg->secs = 0; 379 SMEMCPY(&msg->siaddr, &(dhcp_server->netif->ip_addr), 4); 380 msg->sname[0] = '\0'; 381 msg->file[0] = '\0'; 382 msg->cookie = PP_HTONL(DHCP_MAGIC_COOKIE); 383 SMEMCPY(&msg->yiaddr, &node->ipaddr, 4); 384 385 opt_buf = (u8_t *)msg + DHCP_OPTIONS_OFS; 386 /* add msg type */ 387 *opt_buf++ = DHCP_OPTION_MESSAGE_TYPE; 388 *opt_buf++ = 1; 389 *opt_buf++ = DHCP_OFFER; 390 391 /* add server id */ 392 *opt_buf++ = DHCP_OPTION_SERVER_ID; 393 *opt_buf++ = 4; 394 SMEMCPY(opt_buf, &(dhcp_server->netif->ip_addr), 4); 395 opt_buf += 4; 396 397 /* add_lease_time */ 398 *opt_buf++ = DHCP_OPTION_LEASE_TIME; 399 *opt_buf++ = 4; 400 tmp = PP_HTONL(DHCP_DEFAULT_LIVE_TIME); 401 SMEMCPY(opt_buf, &tmp, 4); 402 opt_buf += 4; 403 404 /* add config */ 405 *opt_buf++ = DHCP_OPTION_SUBNET_MASK; 406 *opt_buf++ = 4; 407 SMEMCPY(opt_buf, &ip_2_ip4(&dhcp_server->netif->netmask)->addr, 4); 408 opt_buf += 4; 409 410 *opt_buf++ = DHCP_OPTION_DNS_SERVER; 411 *opt_buf++ = 4; 412 #ifdef DHCP_DNS_SERVER_IP 413 { 414 ip_addr_t dns_addr; 415 ipaddr_aton(DHCP_DNS_SERVER_IP, &dns_addr); 416 SMEMCPY(opt_buf, &ip_2_ip4(&dns_addr)->addr, 4); 417 } 418 #else 419 /* default use gatewary dns server */ 420 SMEMCPY(opt_buf, &(dhcp_server->netif->ip_addr), 4); 421 #endif /* DHCP_DNS_SERVER_IP */ 422 opt_buf += 4; 423 424 *opt_buf++ = DHCP_OPTION_ROUTER; 425 *opt_buf++ = 4; 426 SMEMCPY(opt_buf, &ip_2_ip4(&dhcp_server->netif->ip_addr)->addr, 4); 427 opt_buf += 4; 428 429 /* add option end */ 430 *opt_buf++ = DHCP_OPTION_END; 431 432 length = (u32_t)opt_buf - (u32_t)msg; 433 if (length < q->tot_len) 434 { 435 pbuf_realloc(q, length); 436 } 437 438 ip_2_ip4(&addr)->addr = INADDR_BROADCAST; 439 udp_sendto_if(pcb, q, &addr, port, dhcp_server->netif); 440 } 441 else 442 { 443 if (1) 444 { 445 if (msg_type == DHCP_REQUEST) 446 { 447 node = dhcp_client_find(dhcp_server, msg, opt_buf, length); 448 if (node != NULL) 449 { 450 /* Send ack */ 451 node->lease_end = DHCP_DEFAULT_LIVE_TIME; 452 /* create dhcp offer and send */ 453 msg->op = DHCP_BOOTREPLY; 454 msg->hops = 0; 455 msg->secs = 0; 456 SMEMCPY(&msg->siaddr, &(dhcp_server->netif->ip_addr), 4); 457 msg->sname[0] = '\0'; 458 msg->file[0] = '\0'; 459 msg->cookie = PP_HTONL(DHCP_MAGIC_COOKIE); 460 SMEMCPY(&msg->yiaddr, &node->ipaddr, 4); 461 opt_buf = (u8_t *)msg + DHCP_OPTIONS_OFS; 462 463 /* add msg type */ 464 *opt_buf++ = DHCP_OPTION_MESSAGE_TYPE; 465 *opt_buf++ = 1; 466 *opt_buf++ = DHCP_ACK; 467 468 /* add server id */ 469 *opt_buf++ = DHCP_OPTION_SERVER_ID; 470 *opt_buf++ = 4; 471 SMEMCPY(opt_buf, &(dhcp_server->netif->ip_addr), 4); 472 opt_buf += 4; 473 474 /* add_lease_time */ 475 *opt_buf++ = DHCP_OPTION_LEASE_TIME; 476 *opt_buf++ = 4; 477 tmp = PP_HTONL(DHCP_DEFAULT_LIVE_TIME); 478 SMEMCPY(opt_buf, &tmp, 4); 479 opt_buf += 4; 480 481 /* add config */ 482 *opt_buf++ = DHCP_OPTION_SUBNET_MASK; 483 *opt_buf++ = 4; 484 SMEMCPY(opt_buf, &ip_2_ip4(&dhcp_server->netif->netmask)->addr, 4); 485 opt_buf += 4; 486 487 *opt_buf++ = DHCP_OPTION_DNS_SERVER; 488 *opt_buf++ = 4; 489 #ifdef DHCP_DNS_SERVER_IP 490 { 491 ip_addr_t dns_addr; 492 ipaddr_aton(DHCP_DNS_SERVER_IP, &dns_addr); 493 SMEMCPY(opt_buf, &ip_2_ip4(&dns_addr)->addr, 4); 494 } 495 #else 496 /* default use gatewary dns server */ 497 SMEMCPY(opt_buf, &(dhcp_server->netif->ip_addr), 4); 498 #endif /* DHCP_DNS_SERVER_IP */ 499 opt_buf += 4; 500 501 *opt_buf++ = DHCP_OPTION_ROUTER; 502 *opt_buf++ = 4; 503 SMEMCPY(opt_buf, &ip_2_ip4(&dhcp_server->netif->ip_addr)->addr, 4); 504 opt_buf += 4; 505 506 /* add option end */ 507 *opt_buf++ = DHCP_OPTION_END; 508 509 length = (u32_t)opt_buf - (u32_t)msg; 510 if (length < q->tot_len) 511 { 512 pbuf_realloc(q, length); 513 } 514 515 ip_2_ip4(&addr)->addr = INADDR_BROADCAST; 516 udp_sendto_if(pcb, q, &addr, port, dhcp_server->netif); 517 } 518 else 519 { 520 /* Send no ack */ 521 /* create dhcp offer and send */ 522 msg->op = DHCP_BOOTREPLY; 523 msg->hops = 0; 524 msg->secs = 0; 525 SMEMCPY(&msg->siaddr, &(dhcp_server->netif->ip_addr), 4); 526 msg->sname[0] = '\0'; 527 msg->file[0] = '\0'; 528 msg->cookie = PP_HTONL(DHCP_MAGIC_COOKIE); 529 memset(&msg->yiaddr, 0, 4); 530 opt_buf = (u8_t *)msg + DHCP_OPTIONS_OFS; 531 532 /* add msg type */ 533 *opt_buf++ = DHCP_OPTION_MESSAGE_TYPE; 534 *opt_buf++ = 1; 535 *opt_buf++ = DHCP_NAK; 536 537 /* add server id */ 538 *opt_buf++ = DHCP_OPTION_SERVER_ID; 539 *opt_buf++ = 4; 540 SMEMCPY(opt_buf, &(dhcp_server->netif->ip_addr), 4); 541 opt_buf += 4; 542 543 /* add option end */ 544 *opt_buf++ = DHCP_OPTION_END; 545 length = (u32_t)opt_buf - (u32_t)msg; 546 if (length < q->tot_len) 547 { 548 pbuf_realloc(q, length); 549 } 550 551 ip_2_ip4(&addr)->addr = INADDR_BROADCAST; 552 udp_sendto_if(pcb, q, &addr, port, dhcp_server->netif); 553 } 554 } 555 else if (msg_type == DHCP_RELEASE) 556 { 557 struct dhcp_client_node *node_prev = NULL; 558 559 for (node = dhcp_server->node_list; node != NULL; node = node->next) 560 { 561 if (memcmp(node->chaddr, msg->chaddr, msg->hlen) == 0) 562 { 563 if (node == dhcp_server->node_list) 564 { 565 dhcp_server->node_list = node->next; 566 } 567 else 568 { 569 node_prev->next = node->next; 570 } 571 break; 572 } 573 node_prev = node; 574 node = node->next; 575 } 576 577 if (node != NULL) 578 { 579 mem_free(node); 580 } 581 } 582 else if (msg_type == DHCP_DECLINE) 583 { 584 ; 585 } 586 else if (msg_type == DHCP_INFORM) 587 { 588 ; 589 } 590 } 591 } 592 } 593 594 free_pbuf_and_return: 595 pbuf_free(q); 596 } 597 598 /** 599 * start dhcp server for a netif 600 * 601 * @param netif The netif which use dhcp server 602 * @param start The Start IP address 603 * @param end The netif which use dhcp server 604 * @return lwIP error code 605 * - ERR_OK - No error 606 * - ERR_MEM - Out of memory 607 */ 608 err_t 609 dhcp_server_start(struct netif *netif, ip4_addr_t *start, ip4_addr_t *end) 610 { 611 struct dhcp_server *dhcp_server; 612 613 /* If this netif alreday use the dhcp server. */ 614 for (dhcp_server = lw_dhcp_server; dhcp_server != NULL; dhcp_server = dhcp_server->next) 615 { 616 if (dhcp_server->netif == netif) 617 { 618 dhcp_server->start = *start; 619 dhcp_server->end = *end; 620 dhcp_server->current = *start; 621 return ERR_OK; 622 } 623 } 624 625 dhcp_server = NULL; 626 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_server_start(): starting new DHCP server\n")); 627 dhcp_server = (struct dhcp_server *)mem_malloc(sizeof(struct dhcp_server)); 628 if (dhcp_server == NULL) 629 { 630 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_server_start(): could not allocate dhcp\n")); 631 return ERR_MEM; 632 } 633 634 /* clear data structure */ 635 memset(dhcp_server, 0, sizeof(struct dhcp_server)); 636 637 /* store this dhcp server to list */ 638 dhcp_server->next = lw_dhcp_server; 639 lw_dhcp_server = dhcp_server; 640 dhcp_server->netif = netif; 641 dhcp_server->node_list = NULL; 642 dhcp_server->start = *start; 643 dhcp_server->end = *end; 644 dhcp_server->current = *start; 645 646 /* allocate UDP PCB */ 647 dhcp_server->pcb = udp_new(); 648 if (dhcp_server->pcb == NULL) 649 { 650 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_server_start(): could not obtain pcb\n")); 651 return ERR_MEM; 652 } 653 654 ip_set_option(dhcp_server->pcb, SOF_BROADCAST); 655 /* set up local and remote port for the pcb */ 656 udp_bind(dhcp_server->pcb, IP_ADDR_ANY, DHCP_SERVER_PORT); 657 //udp_connect(dhcp_server->pcb, IP_ADDR_ANY, DHCP_CLIENT_PORT); 658 /* set up the recv callback and argument */ 659 udp_recv(dhcp_server->pcb, dhcp_server_recv, dhcp_server); 660 LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_TRACE, ("dhcp_server_start(): starting DHCP server\n")); 661 662 return ERR_OK; 663 } 664 665 666 void dhcpd_start(const char *netif_name) 667 { 668 struct netif *netif = netif_list; 669 err_t res; 670 671 DEBUG_PRINTF("%s: %s\r\n", __FUNCTION__, netif_name); 672 673 LWIP_NETIF_LOCK(); 674 if (strlen(netif_name) > sizeof(netif->name)) 675 { 676 DEBUG_PRINTF("network interface name too long!\r\n"); 677 goto _exit; 678 } 679 680 while (netif != RT_NULL) 681 { 682 if (strncmp(netif_name, netif->name, sizeof(netif->name)) == 0) 683 break; 684 685 netif = netif->next; 686 if (netif == RT_NULL) 687 { 688 DEBUG_PRINTF("network interface: %s not found!\r\n", netif_name); 689 break; 690 } 691 } 692 693 if (netif == RT_NULL) 694 { 695 goto _exit; 696 } 697 698 if (1) 699 { 700 extern void set_if(const char *netif_name, const char *ip_addr, const char *gw_addr, const char *nm_addr); 701 702 dhcp_stop(netif); 703 704 set_if(netif_name, DHCPD_SERVER_IP, "0.0.0.0", "255.255.255.0"); 705 706 netif_set_up(netif); 707 } 708 709 { 710 char str_tmp[4 * 4 + 4] = DHCPD_SERVER_IP; 711 char *p = str_tmp; 712 ip4_addr_t ip_start, ip_end; 713 714 p = strchr(str_tmp, '.'); 715 if (p) 716 { 717 p = strchr(p + 1, '.'); 718 if (p) 719 { 720 p = strchr(p + 1, '.'); 721 } 722 } 723 if (!p) 724 { 725 DEBUG_PRINTF("DHCPD_SERVER_IP: %s error!\r\n", str_tmp); 726 goto _exit; 727 } 728 p = p + 1; /* move to xxx.xxx.xxx.^ */ 729 730 sprintf(p, "%d", DHCPD_CLIENT_IP_MIN); 731 ip4addr_aton(str_tmp, &ip_start); 732 DEBUG_PRINTF("ip_start: [%s]\r\n", str_tmp); 733 sprintf(p, "%d", DHCPD_CLIENT_IP_MAX); 734 ip4addr_aton(str_tmp, &ip_end); 735 DEBUG_PRINTF("ip_start: [%s]\r\n", str_tmp); 736 737 res = dhcp_server_start(netif, &ip_start, &ip_end); 738 if (res != 0) 739 { 740 DEBUG_PRINTF("dhcp_server_start res: %s.\r\n", res); 741 } 742 } 743 744 _exit: 745 LWIP_NETIF_UNLOCK(); 746 return; 747 } 748 749 750