1 //==========================================================================
5 // Stand-alone network logical I/O support for RedBoot
7 //==========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
12 // Copyright (C) 2002, 2003, 2004 Gary Thomas
14 // eCos is free software; you can redistribute it and/or modify it under
15 // the terms of the GNU General Public License as published by the Free
16 // Software Foundation; either version 2 or (at your option) any later version.
18 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
19 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 // You should have received a copy of the GNU General Public License along
24 // with eCos; if not, write to the Free Software Foundation, Inc.,
25 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
27 // As a special exception, if other files instantiate templates or use macros
28 // or inline functions from this file, or you compile this file and link it
29 // with other works to produce a work based on this file, this file does not
30 // by itself cause the resulting work to be covered by the GNU General Public
31 // License. However the source code for this file must still be made available
32 // in accordance with section (3) of the GNU General Public License.
34 // This exception does not invalidate any other reasons why a work based on
35 // this file might be covered by the GNU General Public License.
37 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
38 // at http://sources.redhat.com/ecos/ecos-license/
39 // -------------------------------------------
40 //####ECOSGPLCOPYRIGHTEND####
41 //==========================================================================
42 //#####DESCRIPTIONBEGIN####
45 // Contributors: gthomas
50 // This code is part of RedBoot (tm).
52 //####DESCRIPTIONEND####
54 //==========================================================================
58 #include <cyg/hal/hal_misc.h> // Helper functions
59 #include <cyg/hal/hal_if.h> // HAL I/O interfaces
60 #include <cyg/hal/drv_api.h>
61 #include <cyg/hal/hal_intr.h>
62 #include <cyg/infra/cyg_ass.h> // assertion macros
64 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
65 #include <flash_config.h>
67 RedBoot_config_option("GDB connection port",
71 CYGNUM_REDBOOT_NETWORKING_TCP_PORT
73 RedBoot_config_option("Network debug at boot time",
79 #if defined(CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1)
80 RedBoot_config_option("Default network device",
84 CYGDAT_REDBOOT_DEFAULT_NETWORK_DEVICE
87 // Note: the following options are related. If 'bootp' is false, then
88 // the other values are used in the configuration. Because of the way
89 // that configuration tables are generated, they should have names which
90 // are related. The configuration options will show up lexicographically
91 // ordered, thus the peculiar naming. In this case, the 'use' option is
92 // negated (if false, the others apply) which makes the names even more
95 #ifndef CYGSEM_REDBOOT_DEFAULT_NO_BOOTP
96 #define CYGSEM_REDBOOT_DEFAULT_NO_BOOTP 0
98 RedBoot_config_option("Use BOOTP for network configuration",
100 ALWAYS_ENABLED, true,
102 !CYGSEM_REDBOOT_DEFAULT_NO_BOOTP
104 RedBoot_config_option("Local IP address",
110 #ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
111 RedBoot_config_option("Local IP address mask",
117 RedBoot_config_option("Gateway IP address",
124 RedBoot_config_option("Default server IP address",
126 ALWAYS_ENABLED, true,
131 // Note: the following options are related too.
132 RedBoot_config_option("Force console for special debug messages",
134 ALWAYS_ENABLED, true,
138 RedBoot_config_option("Console number for special debug messages",
140 "info_console_force", true,
146 #define TCP_CHANNEL CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS
152 static tcp_socket_t tcp_sock;
154 static int _timeout = 500;
155 static int orig_console, orig_debug;
157 static int in_buflen = 0;
158 static unsigned char in_buf[64];
159 static unsigned char *in_bufp;
160 static int out_buflen = 0;
161 static unsigned char out_buf[1024];
162 static unsigned char *out_bufp;
163 static bool flush_output_lines = false;
165 // Functions in this module
166 static void net_io_flush(void);
167 static void net_io_revert_console(void);
168 static void net_io_putc(void*, cyg_uint8);
170 // Special characters used by Telnet - must be interpretted here
171 #define TELNET_IAC 0xFF // Interpret as command (escape)
172 #define TELNET_IP 0xF4 // Interrupt process
173 #define TELNET_WILL 0xFB // I Will do XXX
174 #define TELNET_WONT 0xFC // I Won't do XXX
175 #define TELNET_DO 0xFD // Will you XXX
176 #define TELNET_DONT 0xFE // Don't you XXX
177 #define TELNET_TM 0x06 // Time marker (special DO/WONT after IP)
180 _net_io_getc_nonblock(void *__ch_data, cyg_uint8 *ch)
182 if (in_buflen == 0) {
184 if (tcp_sock.state == _CLOSE_WAIT) {
185 // This connection is breaking
186 if (tcp_sock.data_bytes == 0 && tcp_sock.rxcnt == 0) {
187 __tcp_close(&tcp_sock);
191 if (tcp_sock.state == _CLOSED) {
192 // The connection is gone
193 net_io_revert_console();
197 in_buflen = __tcp_read(&tcp_sock, in_buf, sizeof(in_buf));
200 if (show_tcp && (in_buflen > 0)) {
202 old_console = start_console();
203 diag_printf("%s:%d\n", __FUNCTION__, __LINE__);
204 diag_dump_buf(in_buf, in_buflen);
205 end_console(old_console);
219 net_io_getc_nonblock(void *__ch_data, cyg_uint8 *ch)
223 if (!_net_io_getc_nonblock(__ch_data, ch))
226 if (gdb_active || *ch != TELNET_IAC)
229 // Telnet escape - need to read/handle more
230 while (!_net_io_getc_nonblock(__ch_data, &esc)) ;
234 // The other special case - escaped escape
237 // Special case for ^C == Interrupt Process
239 // Just in case the other end needs synchronizing
240 net_io_putc(__ch_data, TELNET_IAC);
241 net_io_putc(__ch_data, TELNET_WONT);
242 net_io_putc(__ch_data, TELNET_TM);
247 while (!_net_io_getc_nonblock(__ch_data, &esc)) ;
248 // Respond with WONT option
249 net_io_putc(__ch_data, TELNET_IAC);
250 net_io_putc(__ch_data, TELNET_WONT);
251 net_io_putc(__ch_data, esc);
252 return false; // Ignore this whole thing!
254 // Telnet WILL option
255 while (!_net_io_getc_nonblock(__ch_data, &esc)) ;
256 // Respond with DONT option
257 net_io_putc(__ch_data, TELNET_IAC);
258 net_io_putc(__ch_data, TELNET_DONT);
259 net_io_putc(__ch_data, esc);
260 return false; // Ignore this whole thing!
267 net_io_getc(void *__ch_data)
270 int idle_timeout = 10; // 10ms
272 CYGARC_HAL_SAVE_GP();
274 if (net_io_getc_nonblock(__ch_data, &ch)) break;
275 if (--idle_timeout == 0) {
280 CYGARC_HAL_RESTORE_GP();
293 old_console = start_console();
294 diag_printf("%s.%d\n", __FUNCTION__, __LINE__);
295 diag_dump_buf(out_buf, out_buflen);
296 end_console(old_console);
299 n = __tcp_write_block(&tcp_sock, bp, out_buflen);
301 // The connection is gone!
302 net_io_revert_console();
307 out_bufp = out_buf; out_buflen = 0;
308 // Check interrupt flag
309 if (CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG()) {
310 CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG_SET(0);
311 cyg_hal_user_break(0);
316 net_io_putc(void *__ch_data, cyg_uint8 c)
318 static bool have_dollar, have_hash;
319 static int hash_count;
321 CYGARC_HAL_SAVE_GP();
323 if (c == '$') have_dollar = true;
324 if (have_dollar && (c == '#')) {
328 if ((++out_buflen == sizeof(out_buf)) ||
329 (flush_output_lines && c == '\n') ||
330 (have_hash && (++hash_count == 3))) {
334 CYGARC_HAL_RESTORE_GP();
338 net_io_write(void *__ch_data, const cyg_uint8 *__buf, cyg_uint32 __len)
342 old_console = start_console();
343 diag_printf("%s.%d\n", __FUNCTION__, __LINE__);
344 end_console(old_console);
346 CYGARC_HAL_SAVE_GP();
349 net_io_putc(__ch_data, *__buf++);
351 CYGARC_HAL_RESTORE_GP();
356 net_io_read(void *__ch_data, cyg_uint8 *__buf, cyg_uint32 __len)
360 old_console = start_console();
361 diag_printf("%s.%d\n", __FUNCTION__, __LINE__);
362 end_console(old_console);
364 CYGARC_HAL_SAVE_GP();
367 *__buf++ = net_io_getc(__ch_data);
369 CYGARC_HAL_RESTORE_GP();
374 net_io_getc_timeout(void *__ch_data, cyg_uint8 *ch)
379 CYGARC_HAL_SAVE_GP();
380 net_io_flush(); // Make sure any output has been sent
381 delay_count = _timeout;
384 res = net_io_getc_nonblock(__ch_data, ch);
385 if (res || 0 == delay_count--)
389 CYGARC_HAL_RESTORE_GP();
395 net_io_control(void *__ch_data, __comm_control_cmd_t __func, ...)
397 static int vector = 0;
399 static int irq_state = 0;
401 CYGARC_HAL_SAVE_GP();
404 case __COMMCTL_IRQ_ENABLE:
407 vector = eth_drv_int_vector();
409 HAL_INTERRUPT_UNMASK(vector);
411 case __COMMCTL_IRQ_DISABLE:
415 vector = eth_drv_int_vector();
417 HAL_INTERRUPT_MASK(vector);
419 case __COMMCTL_DBG_ISR_VECTOR:
422 case __COMMCTL_SET_TIMEOUT:
426 va_start(ap, __func);
429 _timeout = va_arg(ap, cyg_uint32);
434 case __COMMCTL_FLUSH_OUTPUT:
437 case __COMMCTL_ENABLE_LINE_FLUSH:
438 flush_output_lines = true;
440 case __COMMCTL_DISABLE_LINE_FLUSH:
441 flush_output_lines = false;
446 CYGARC_HAL_RESTORE_GP();
451 net_io_isr(void *__ch_data, int *__ctrlc,
452 CYG_ADDRWORD __vector, CYG_ADDRWORD __data)
456 CYGARC_HAL_SAVE_GP();
458 if (net_io_getc_nonblock(__ch_data, &ch)) {
463 CYGARC_HAL_RESTORE_GP();
464 return CYG_ISR_HANDLED;
473 CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
475 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
477 if ( flash_get_config( "info_console_force", &i, CONFIG_BOOL) )
479 if ( ! flash_get_config( "info_console_number", &i, CONFIG_INT) )
480 i = 0; // the default, if that call failed.
482 CYGACC_CALL_IF_SET_CONSOLE_COMM(i);
485 CYGACC_CALL_IF_SET_CONSOLE_COMM(0);
491 end_console(int old_console)
493 // Restore original console
494 CYGACC_CALL_IF_SET_CONSOLE_COMM(old_console);
499 net_io_revert_console(void)
501 #ifdef CYGPKG_REDBOOT_ANY_CONSOLE
502 console_selected = false;
504 CYGACC_CALL_IF_SET_CONSOLE_COMM(orig_console);
505 CYGACC_CALL_IF_SET_DEBUG_COMM(orig_debug);
510 net_io_assume_console(void)
512 #ifdef CYGPKG_REDBOOT_ANY_CONSOLE
513 console_selected = true;
515 console_echo = false;
516 orig_console = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
517 CYGACC_CALL_IF_SET_CONSOLE_COMM(TCP_CHANNEL);
518 orig_debug = CYGACC_CALL_IF_SET_DEBUG_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
519 CYGACC_CALL_IF_SET_DEBUG_COMM(TCP_CHANNEL);
527 hal_virtual_comm_table_t *comm;
528 int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
530 // Setup procs in the vector table
531 CYGACC_CALL_IF_SET_CONSOLE_COMM(TCP_CHANNEL);
532 comm = CYGACC_CALL_IF_CONSOLE_PROCS();
533 //CYGACC_COMM_IF_CH_DATA_SET(*comm, chan);
534 CYGACC_COMM_IF_WRITE_SET(*comm, net_io_write);
535 CYGACC_COMM_IF_READ_SET(*comm, net_io_read);
536 CYGACC_COMM_IF_PUTC_SET(*comm, net_io_putc);
537 CYGACC_COMM_IF_GETC_SET(*comm, net_io_getc);
538 CYGACC_COMM_IF_CONTROL_SET(*comm, net_io_control);
539 CYGACC_COMM_IF_DBG_ISR_SET(*comm, net_io_isr);
540 CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, net_io_getc_timeout);
542 // Disable interrupts via this interface to set static
543 // state into correct state.
544 net_io_control( comm, __COMMCTL_IRQ_DISABLE );
546 // Restore original console
547 CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
552 __tcp_listen(&tcp_sock, gdb_port);
553 state = tcp_sock.state;
555 diag_printf("show tcp = %p\n", &show_tcp);
559 // Check for incoming TCP debug connection
561 net_io_test(bool is_idle)
563 if (!is_idle) return; // Only care about idle case
564 if (!have_net) return;
566 if (state != tcp_sock.state) {
567 // Something has changed
568 if (tcp_sock.state == _ESTABLISHED) {
569 // A new connection has arrived
570 net_io_assume_console();
571 in_bufp = in_buf; in_buflen = 1; *in_bufp = '\r';
572 out_bufp = out_buf; out_buflen = 0;
574 if (tcp_sock.state == _CLOSED) {
575 net_io_init(); // Get ready for another connection
578 state = tcp_sock.state;
581 // This schedules the 'net_io_test()' function to be run by RedBoot's
582 // main command loop when idle (i.e. when no input arrives after some
584 RedBoot_idle(net_io_test, RedBoot_IDLE_NETIO);
587 // Network initialization
589 #include <cyg/io/eth/eth_drv.h>
590 #include <cyg/io/eth/netdev.h>
591 #include <cyg/hal/hal_tables.h>
593 // Define table boundaries
594 CYG_HAL_TABLE_BEGIN( __NETDEVTAB__, netdev );
595 CYG_HAL_TABLE_END( __NETDEVTAB_END__, netdev );
597 RedBoot_init(net_init, RedBoot_INIT_NET);
602 diag_printf("IP: %s", inet_ntoa((in_addr_t *)&__local_ip_addr));
603 #ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
604 diag_printf("/%s", inet_ntoa((in_addr_t *)&__local_ip_mask));
605 diag_printf(", Gateway: %s\n", inet_ntoa((in_addr_t *)&__local_ip_gate));
609 diag_printf("Default server: %s", inet_ntoa(&my_bootp_info.bp_siaddr));
610 #ifdef CYGPKG_REDBOOT_NETWORKING_DNS
616 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
618 flash_get_IP(char *id, ip_addr_t *val)
623 if (flash_get_config(id, &my_ip, CONFIG_IP)) {
624 if (my_ip[0] != 0 || my_ip[1] != 0 ||
625 my_ip[2] != 0 || my_ip[3] != 0) {
626 // 'id' is set to something so let it override any static IP
628 (*val)[i] = my_ip[i];
634 static cyg_netdevtab_entry_t *
635 net_devtab_entry(unsigned index)
637 cyg_netdevtab_entry_t *t = &__NETDEVTAB__[index];
639 if (t < &__NETDEVTAB__[0] || t >= &__NETDEVTAB_END__)
646 net_devname(unsigned index)
648 cyg_netdevtab_entry_t *t = net_devtab_entry(index);
655 net_devindex(char *name)
660 for (index = 0; (devname = net_devname(index)) != NULL; index++)
661 if (!strcmp(name, devname))
669 diag_printf("Ethernet %s: MAC address %02x:%02x:%02x:%02x:%02x:%02x\n",
670 __local_enet_sc->dev_name,
671 __local_enet_addr[0],
672 __local_enet_addr[1],
673 __local_enet_addr[2],
674 __local_enet_addr[3],
675 __local_enet_addr[4],
676 __local_enet_addr[5]);
682 cyg_netdevtab_entry_t *t;
684 struct eth_drv_sc *primary_net = (struct eth_drv_sc *)0;
685 #if defined(CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1)
686 char *default_devname = CYGDAT_REDBOOT_DEFAULT_NETWORK_DEVICE;
689 #ifdef CYGDAT_REDBOOT_DEFAULT_BOOTP_SERVER_IP_ADDR
693 // Set defaults as appropriate
694 #ifdef CYGSEM_REDBOOT_DEFAULT_NO_BOOTP
699 #ifdef CYGDBG_REDBOOT_NET_DEBUG
704 gdb_port = CYGNUM_REDBOOT_NETWORKING_TCP_PORT;
705 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
706 // Fetch values from saved config data, if available
707 #if defined(CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1)
708 flash_get_config("net_device", &default_devname, CONFIG_NETPORT);
710 flash_get_config("net_debug", &net_debug, CONFIG_BOOL);
711 flash_get_config("gdb_port", &gdb_port, CONFIG_INT);
712 flash_get_config("bootp", &use_bootp, CONFIG_BOOL);
714 flash_get_IP("bootp_my_ip", &__local_ip_addr);
715 #ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
716 flash_get_IP("bootp_my_ip_mask", &__local_ip_mask);
717 flash_get_IP("bootp_my_gateway_ip", &__local_ip_gate);
721 # ifdef CYGDBG_IO_ETH_DRIVERS_DEBUG
722 // Don't override if the user has deliberately set something more
724 if (0 == cyg_io_eth_net_debug)
725 cyg_io_eth_net_debug = net_debug;
728 // Make sure the recv buffers are set up
729 eth_drv_buffers_init();
732 // Initialize network device(s).
733 #if defined(CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1)
734 default_index = net_devindex(default_devname);
735 if (default_index < 0)
737 #ifdef CYGSEM_REDBOOT_NETWORK_INIT_ONE_DEVICE
738 if ((t = net_devtab_entry(default_index)) != NULL && t->init(t)) {
739 t->status = CYG_NETDEVTAB_STATUS_AVAIL;
740 primary_net = __local_enet_sc;
743 #endif // (CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1)
744 for (index = 0; (t = net_devtab_entry(index)) != NULL; index++) {
745 #ifdef CYGSEM_REDBOOT_NETWORK_INIT_ONE_DEVICE
746 if (index == default_index)
750 t->status = CYG_NETDEVTAB_STATUS_AVAIL;
751 if (primary_net == (struct eth_drv_sc *)0) {
752 primary_net = __local_enet_sc;
754 #if defined(CYGHWR_NET_DRIVERS) && (CYGHWR_NET_DRIVERS > 1)
755 # ifdef CYGSEM_REDBOOT_NETWORK_INIT_ONE_DEVICE
758 if (index == default_index) {
759 primary_net = __local_enet_sc;
761 # endif // CYGSEM_REDBOOT_NETWORK_INIT_ONE_DEVICE
765 __local_enet_sc = primary_net;
767 if (!__local_enet_sc) {
768 diag_printf("No network interfaces found\n");
771 // Initialize the network [if present]
773 if (__bootp_find_local_ip(&my_bootp_info) == 0) {
776 // Is it an unset address, or has it been set to a static addr
777 if (__local_ip_addr[0] == 0 && __local_ip_addr[1] == 0 &&
778 __local_ip_addr[2] == 0 && __local_ip_addr[3] == 0) {
780 diag_printf("Can't get BOOTP info for device!\n");
782 diag_printf("Can't get BOOTP info, using default IP address\n");
787 if (__local_ip_addr[0] == 0 && __local_ip_addr[1] == 0 &&
788 __local_ip_addr[2] == 0 && __local_ip_addr[3] == 0) {
790 diag_printf("No IP info for device!\n");
792 enet_addr_t enet_addr;
793 have_net = true; // Assume values in FLASH were OK
794 // Tell the world that we are using this fixed IP address
795 if (__arp_request((ip_addr_t *)__local_ip_addr, &enet_addr, 1) >= 0) {
796 diag_printf("Warning: IP address %s in use\n",
797 inet_ntoa((in_addr_t *)&__local_ip_addr));
803 #ifdef CYGDAT_REDBOOT_DEFAULT_BOOTP_SERVER_IP_ADDR
804 diag_sprintf(ip_addr, "%d.%d.%d.%d",
805 CYGDAT_REDBOOT_DEFAULT_BOOTP_SERVER_IP_ADDR);
806 inet_aton(ip_addr, &my_bootp_info.bp_siaddr);
808 #ifdef CYGSEM_REDBOOT_FLASH_CONFIG
809 flash_get_IP("bootp_server_ip", (ip_addr_t *)&my_bootp_info.bp_siaddr);
811 #ifdef CYGPKG_REDBOOT_NETWORKING_DNS
812 redboot_dns_res_init();
819 static char usage[] = "[-b] [-l <local_ip_address>[/<mask_len>]] [-h <server_address>]"
820 #ifdef CYGPKG_REDBOOT_NETWORKING_DNS
821 " [-d <dns_server_address>]"
822 #ifdef CYGPKG_REDBOOT_NETWORKING_DNS_FCONFIG_DOMAIN
823 " [-D <dns_domain_name>]"
828 // Exported CLI function
829 static void do_ip_addr(int argc, char *argv[]);
830 RedBoot_cmd("ip_address",
831 "Set/change IP addresses",
837 do_ip_addr(int argc, char *argv[])
839 struct option_info opts[5];
840 char *ip_addr, *host_addr;
841 bool ip_addr_set, host_addr_set;
842 bool do_bootp = false;
843 struct sockaddr_in host;
844 #ifdef CYGPKG_REDBOOT_NETWORKING_DNS
847 #ifdef CYGPKG_REDBOOT_NETWORKING_DNS_FCONFIG_DOMAIN
856 if (!__local_enet_sc) {
857 diag_printf("Sorry, networking is not available.\n");
862 init_opts(&opts[0], 'l', true, OPTION_ARG_TYPE_STR,
863 &ip_addr, &ip_addr_set, "local IP address");
864 init_opts(&opts[1], 'h', true, OPTION_ARG_TYPE_STR,
865 &host_addr, &host_addr_set, "default server address");
866 init_opts(&opts[2], 'b', false, OPTION_ARG_TYPE_FLG,
867 &do_bootp, 0, "use BOOTP");
869 #ifdef CYGPKG_REDBOOT_NETWORKING_DNS
870 init_opts(&opts[num_opts], 'd', true, OPTION_ARG_TYPE_STR,
871 &dns_addr, &dns_addr_set, "DNS server address");
873 #ifdef CYGPKG_REDBOOT_NETWORKING_DNS_FCONFIG_DOMAIN
874 init_opts(&opts[num_opts], 'D', true, OPTION_ARG_TYPE_STR,
875 &dns_domain, &dns_domain_set, "DNS domain");
879 CYG_ASSERT(num_opts <= NUM_ELEMS(opts), "Too many options");
881 if (!scan_opts(argc, argv, 1, opts, num_opts, 0, 0, "")) {
885 if (__bootp_find_local_ip(&my_bootp_info) != 0) {
886 diag_printf("Failed to get BOOTP address\n");
890 #ifdef CYGSEM_REDBOOT_NETWORKING_USE_GATEWAY
892 /* see if the (optional) mask length was given */
893 if( (slash_pos = strchr(ip_addr, '/')) ) {
894 unsigned long mask_len;
898 if( !parse_num(slash_pos, &mask_len, 0, 0) ||
899 mask_len <= 0 || mask_len > 32 ) {
900 diag_printf("Invalid mask length: %s\n", slash_pos);
903 mask = htonl((~0 << (32 - mask_len)) & ~0);
904 memcpy(&__local_ip_mask, &mask, 4);
907 if (!_gethostbyname(ip_addr, (in_addr_t *)&host)) {
908 diag_printf("Invalid local IP address: %s\n", ip_addr);
911 // Of course, each address goes in its own place :-)
912 memcpy(&__local_ip_addr, &host.sin_addr, sizeof(host.sin_addr));
915 if (!_gethostbyname(host_addr, (in_addr_t *)&host)) {
916 diag_printf("Invalid server address: %s\n", host_addr);
919 my_bootp_info.bp_siaddr = host.sin_addr;
921 #ifdef CYGPKG_REDBOOT_NETWORKING_DNS
925 #ifdef CYGPKG_REDBOOT_NETWORKING_DNS_FCONFIG_DOMAIN
926 if (dns_domain_set) {
927 setdomainname(dns_domain, strlen(dns_domain));