1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
4 * Network commands File: ui_netcmds.c
6 * Network user interface
8 * Author: Mitch Lichtenberg (mpl@broadcom.com)
10 *********************************************************************
12 * Copyright 2000,2001,2002,2003
13 * Broadcom Corporation. All rights reserved.
15 * This software is furnished under license and may be used and
16 * copied only in accordance with the following terms and
17 * conditions. Subject to these conditions, you may download,
18 * copy, install, use, modify and distribute modified or unmodified
19 * copies of this software in source and/or binary form. No title
20 * or ownership is transferred hereby.
22 * 1) Any source code used, modified or distributed must reproduce
23 * and retain this copyright notice and list of conditions
24 * as they appear in the source file.
26 * 2) No right is granted to use any trade name, trademark, or
27 * logo of Broadcom Corporation. The "Broadcom Corporation"
28 * name may not be used to endorse or promote products derived
29 * from this software without the prior written permission of
30 * Broadcom Corporation.
32 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
33 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
34 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
35 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
36 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
37 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
38 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
40 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
41 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
42 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
43 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
44 * THE POSSIBILITY OF SUCH DAMAGE.
45 ********************************************************************* */
49 #include "lib_types.h"
50 #include "lib_string.h"
51 #include "lib_queue.h"
52 #include "lib_malloc.h"
53 #include "lib_printf.h"
56 #include "cfe_device.h"
57 #include "cfe_console.h"
58 #include "cfe_devfuncs.h"
59 #include "cfe_timer.h"
60 #include "cfe_ioctl.h"
62 #include "cfe_error.h"
65 #include "ui_command.h"
67 #include "bsp_config.h"
70 #include "net_ether.h"
74 #include "cfe_fileops.h"
76 #define ip_addriszero(a) (((a)[0]|(a)[1]|(a)[2]|(a)[3]) == 0)
77 #define isdigit(d) (((d) >= '0') && ((d) <= '9'))
79 int ui_init_netcmds(void);
82 static int ui_cmd_ifconfig(ui_cmdline_t
*cmd
,int argc
,char *argv
[]);
83 static int ui_cmd_arp(ui_cmdline_t
*cmd
,int argc
,char *argv
[]);
84 static int ui_cmd_ping(ui_cmdline_t
*cmd
,int argc
,char *argv
[]);
86 extern int ui_init_tcpcmds(void);
90 typedef struct netparam_s
{
95 const static netparam_t loopbacktypes
[] = {
96 {"off",ETHER_LOOPBACK_OFF
},
97 {"internal",ETHER_LOOPBACK_INT
},
98 {"external",ETHER_LOOPBACK_EXT
},
101 const static netparam_t speedtypes
[] = {
102 {"auto",ETHER_SPEED_AUTO
},
103 {"10hdx",ETHER_SPEED_10HDX
},
104 {"10fdx",ETHER_SPEED_10FDX
},
105 {"100hdx",ETHER_SPEED_100HDX
},
106 {"100fdx",ETHER_SPEED_100FDX
},
107 {"1000hdx",ETHER_SPEED_1000HDX
},
108 {"1000fdx",ETHER_SPEED_1000FDX
},
112 int ui_init_netcmds(void)
115 cmd_addcmd("ifconfig",
118 "Configure the Ethernet interface",
119 "ifconfig device [options..]\n\n"
120 "Activates and configures the specified Ethernet interface and sets its\n"
121 "IP address, netmask, and other parameters.\n"
123 "The -auto switch can be used to set this information via DHCP.\n"
125 "-auto;Configure interface automatically via DHCP|"
128 #endif /* CFG_DHCP */
129 "-off;Deactivate the specified interface|"
130 "-addr=*;Specifies the IP address of the interface|"
131 "-mask=*;Specifies the subnet mask for the interface|"
132 "-gw=*;Specifies the gateway address for the interface|"
133 "-dns=*;Specifies the name server address for the interface|"
134 "-domain=*;Specifies the default domain for name service queries|"
135 "-speed=*;Sets the interface speed (auto,10fdx,10hdx,\n100fdx,\n"
136 "100hdx,1000fdx,1000hdx)|"
137 "-loopback=*;Sets the loopback mode (off,internal,external) "
138 "External\nloopback causes the phy to be placed in loopback mode|"
139 "-hwaddr=*;Sets the hardware address (overrides environment)");
144 "Display or modify the ARP Table",
145 "arp [-d] [ip-address] [dest-address]\n\n"
146 "Without any parameters, the arp command will display the contents of the\n"
147 "arp table. With two parameters, arp can be used to add permanent arp\n"
148 "entries to the table (permanent arp entries do not time out)",
149 "-d;Delete the specified ARP entry. If specified, ip-address\n"
150 "may be * to delete all entries.");
155 "Ping a remote IP host.",
156 "ping [-t] remote-host\n\n"
157 "This command sends an ICMP ECHO message to a remote host and waits for \n"
158 "a reply. The network interface must be configured and operational for\n"
159 "this command to work. If the interface is configured for loopback mode\n"
160 "the packet will be sent through the network interface, so this command\n"
161 "can be used for a simple network test.",
162 "-t;Ping forever, or until the ENTER key is struck|"
163 "-x;Exit immediately on first error (use with -f or -t)|"
164 "-f;Flood ping (use carefully!) - ping as fast as possible|"
165 "-s=*;Specify the number of ICMP data bytes|"
166 "-c=*;Specify number of packets to echo|"
167 "-A;don't abort even if key is pressed|"
168 "-E;Require all packets sent to be returned, for successful return status");
182 static int parsexdigit(char str
)
186 if ((str
>= '0') && (str
<= '9')) digit
= str
- '0';
187 else if ((str
>= 'a') && (str
<= 'f')) digit
= str
- 'a' + 10;
188 else if ((str
>= 'A') && (str
<= 'F')) digit
= str
- 'A' + 10;
195 static int parsehwaddr(char *str
,uint8_t *hwaddr
)
200 while (*str
&& (idx
> 0)) {
201 digit1
= parsexdigit(*str
);
202 if (digit1
< 0) return -1;
204 if (!*str
) return -1;
206 if ((*str
== ':') || (*str
== '-')) {
211 digit2
= parsexdigit(*str
);
212 if (digit2
< 0) return -1;
216 *hwaddr
++ = (digit1
<< 4) | digit2
;
219 if (*str
== '-') str
++;
220 if (*str
== ':') str
++;
227 static int ui_ifdown(void)
231 devname
= (char *) net_getparam(NET_DEVNAME
);
233 xprintf("Device %s has been deactivated.\n",devname
);
241 static void ui_showifconfig(void)
246 devname
= (char *) net_getparam(NET_DEVNAME
);
247 if (devname
== NULL
) {
248 xprintf("Network interface has not been configured\n");
252 xprintf("Device %s: ",devname
);
254 addr
= net_getparam(NET_HWADDR
);
255 if (addr
) xprintf(" hwaddr %a",addr
);
257 addr
= net_getparam(NET_IPADDR
);
259 if (ip_addriszero(addr
)) xprintf(", ipaddr not set");
260 else xprintf(", ipaddr %I",addr
);
263 addr
= net_getparam(NET_NETMASK
);
265 if (ip_addriszero(addr
)) xprintf(", mask not set");
266 else xprintf(", mask %I",addr
);
272 addr
= net_getparam(NET_GATEWAY
);
274 if (ip_addriszero(addr
)) xprintf("gateway not set");
275 else xprintf("gateway %I",addr
);
278 addr
= net_getparam(NET_NAMESERVER
);
280 if (ip_addriszero(addr
)) xprintf(", nameserver not set");
281 else xprintf(", nameserver %I",addr
);
284 addr
= net_getparam(NET_DOMAIN
);
286 xprintf(", domain %s",addr
);
293 static int ui_ifconfig_auto(ui_cmdline_t
*cmd
,char *devname
)
296 dhcpreply_t
*reply
= NULL
;
302 err
= net_init(devname
);
304 xprintf("Could not activate device %s: %s\n",
305 devname
,cfe_errortext(err
));
309 if (cmd_sw_value(cmd
,"-hwaddr",&x
)) {
310 if (parsehwaddr(x
,hwaddr
) != 0) {
311 xprintf("Invalid hardware address: %s\n",x
);
313 return CFE_ERR_INV_PARAM
;
316 net_setparam(NET_HWADDR
,hwaddr
);
320 err
= dhcp_bootrequest(&reply
);
323 xprintf("DHCP registration failed on device %s\n",devname
);
325 return CFE_ERR_NETDOWN
;
328 net_setparam(NET_IPADDR
,reply
->dr_ipaddr
);
329 net_setparam(NET_NETMASK
,reply
->dr_netmask
);
330 net_setparam(NET_GATEWAY
,reply
->dr_gateway
);
331 net_setparam(NET_NAMESERVER
,reply
->dr_nameserver
);
332 net_setparam(NET_DOMAIN
,(uint8_t *)reply
->dr_domainname
);
334 dhcp_set_envvars(reply
);
336 if (reply
) dhcp_free_reply(reply
);
342 #endif /* CFG_DHCP */
344 static int ui_ifconfig_getsw(ui_cmdline_t
*cmd
,char *swname
,char *descr
,uint8_t *addr
)
350 if (cmd_sw_value(cmd
,swname
,&x
) == 0) return 0;
352 if ((x
== NULL
) || (parseipaddr(x
,addr
) < 0)) {
353 xprintf("Invalid %s: %s\n",descr
,x
? x
: "(none)");
360 static int ui_ifconfig_lookup(char *name
,char *val
,const netparam_t
*list
)
362 const netparam_t
*p
= list
;
365 if (strcmp(p
->str
,val
) == 0) return p
->num
;
369 xprintf("Invalid parameter for %s: Valid options are: ");
373 xprintf("%s ",p
->str
);
383 #define FLG_NETMASK 2
384 #define FLG_GATEWAY 4
385 #define FLG_NAMESERVER 8
386 #define FLG_DOMAIN 16
387 #define FLG_LOOPBACK 32
389 #define FLG_HWADDR 128
391 static int ui_cmd_ifconfig(ui_cmdline_t
*cmd
,int argc
,char *argv
[])
395 uint8_t ipaddr
[IP_ADDR_LEN
];
396 uint8_t netmask
[IP_ADDR_LEN
];
397 uint8_t gateway
[IP_ADDR_LEN
];
398 uint8_t nameserver
[IP_ADDR_LEN
];
400 int speed
= ETHER_SPEED_AUTO
;
401 int loopback
= ETHER_LOOPBACK_OFF
;
411 devname
= cmd_getarg(cmd
,0);
413 if (cmd_sw_isset(cmd
,"-off")) {
418 if (cmd_sw_isset(cmd
,"-auto")) {
419 return ui_ifconfig_auto(cmd
,devname
);
421 #endif /* CFG_DHCP */
423 res
= ui_ifconfig_getsw(cmd
,"-addr","interface IP address",ipaddr
);
424 if (res
< 0) return CFE_ERR_INV_PARAM
;
429 res
= ui_ifconfig_getsw(cmd
,"-mask","netmask",netmask
);
430 if (res
< 0) return CFE_ERR_INV_PARAM
;
432 flags
|= FLG_NETMASK
;
435 res
= ui_ifconfig_getsw(cmd
,"-gw","gateway IP address",gateway
);
436 if (res
< 0) return CFE_ERR_INV_PARAM
;
438 flags
|= FLG_GATEWAY
;
441 res
= ui_ifconfig_getsw(cmd
,"-dns","name server IP address",nameserver
);
442 if (res
< 0) return CFE_ERR_INV_PARAM
;
444 flags
|= FLG_NAMESERVER
;
447 if (cmd_sw_value(cmd
,"-domain",&domain
)) {
448 if (domain
) flags
|= FLG_DOMAIN
;
451 if (cmd_sw_value(cmd
,"-speed",&x
)) {
452 speed
= ui_ifconfig_lookup("-speed",x
,speedtypes
);
453 if (speed
>= 0) flags
|= FLG_SPEED
;
454 else return CFE_ERR_INV_PARAM
;
457 if (cmd_sw_value(cmd
,"-loopback",&x
)) {
458 loopback
= ui_ifconfig_lookup("-loopback",x
,loopbacktypes
);
459 if (loopback
>= 0) flags
|= FLG_LOOPBACK
;
460 else return CFE_ERR_INV_PARAM
;
463 if (cmd_sw_value(cmd
,"-hwaddr",&x
)) {
464 if (parsehwaddr(x
,hwaddr
) != 0) {
465 xprintf("Invalid hardware address: %s\n",x
);
466 return CFE_ERR_INV_PARAM
;
474 * If the network is running and the device name is
475 * different, uninit the net first.
478 x
= (char *) net_getparam(NET_DEVNAME
);
480 if ((x
!= NULL
) && (strcmp(x
,devname
) != 0)) {
485 * Okay, initialize the network if it is not already on. If it
486 * is OFF, the "net_devname" parameter will be NULL.
490 res
= net_init(devname
); /* turn interface on */
492 ui_showerror(res
,"Could not activate network interface '%s'",devname
);
501 if (flags
& FLG_HWADDR
) net_setparam(NET_HWADDR
,hwaddr
);
502 if (flags
& FLG_IPADDR
) net_setparam(NET_IPADDR
,ipaddr
);
503 if (flags
& FLG_NETMASK
) net_setparam(NET_NETMASK
,netmask
);
504 if (flags
& FLG_GATEWAY
) net_setparam(NET_GATEWAY
,gateway
);
505 if (flags
& FLG_NAMESERVER
) net_setparam(NET_NAMESERVER
,nameserver
);
506 if (flags
& FLG_DOMAIN
) net_setparam(NET_DOMAIN
,(uint8_t *)domain
);
507 if (flags
& FLG_SPEED
) net_setparam(NET_SPEED
,(uint8_t *) &speed
);
508 if (flags
& FLG_LOOPBACK
) net_setparam(NET_LOOPBACK
,(uint8_t *) &loopback
);
517 static int ui_cmd_arp(ui_cmdline_t
*cmd
,int argc
,char *argv
[])
520 uint8_t ipaddr
[IP_ADDR_LEN
];
521 uint8_t hwaddr
[ENET_ADDR_LEN
];
525 if (cmd_sw_isset(cmd
,"-d")) {
526 if ((x
= cmd_getarg(cmd
,0)) == NULL
) {
527 return ui_showusage(cmd
);
530 if (strcmp(x
,"*") == 0) {
531 while (arp_enumerate(0,ipaddr
,hwaddr
) >= 0) {
536 if (parseipaddr(x
,ipaddr
) < 0) {
537 xprintf("Invalid IP address: %s\n",x
);
538 return CFE_ERR_INV_PARAM
;
546 * Get the IP address. If NULL, display the table.
549 x
= cmd_getarg(cmd
,0);
552 while (arp_enumerate(idx
,ipaddr
,hwaddr
) >= 0) {
554 xprintf("Hardware Address IP Address\n");
555 xprintf("----------------- ---------------\n");
558 xprintf("%a %I\n",hwaddr
,ipaddr
);
561 if (idx
== 0) xprintf("No ARP entries.\n");
565 if (parseipaddr(x
,ipaddr
) < 0) {
566 xprintf("Invalid IP address: %s\n",x
);
567 return CFE_ERR_INV_PARAM
;
571 * Get the hardware address.
574 x
= cmd_getarg(cmd
,1);
576 return ui_showusage(cmd
);
579 if (parsehwaddr(x
,hwaddr
) < 0) {
580 xprintf("Invalid hardware address: %s\n",x
);
581 return CFE_ERR_INV_PARAM
;
584 arp_add(ipaddr
,hwaddr
);
589 #define IP_HDR_LENGTH 20
590 #define ICMP_HDR_LENGTH 8
591 #define PING_HDR_LENGTH (IP_HDR_LENGTH+ICMP_HDR_LENGTH)
592 #define MAX_PKT_LENGTH 1500
594 static int ui_cmd_ping(ui_cmdline_t
*cmd
,int argc
,char *argv
[])
597 uint8_t hostaddr
[IP_ADDR_LEN
];
603 int countreturned
= 0;
612 host
= cmd_getarg(cmd
,0);
613 if (!host
) return -1;
615 if (cmd_sw_isset(cmd
,"-t")) {
619 /* Per traditional Unix usage, the size argument to ping is
620 the number of ICMP data bytes. The frame on the wire will also
621 include the ethernet, IP and ICMP headers (14, 20, and
622 8 bytes respectively) and ethernet trailer (CRC, 4 bytes). */
623 if (cmd_sw_value(cmd
,"-s",&x
)) {
627 if (size
> MAX_PKT_LENGTH
- PING_HDR_LENGTH
)
628 size
= MAX_PKT_LENGTH
- PING_HDR_LENGTH
;
631 if (cmd_sw_isset(cmd
,"-f")) {
636 if (cmd_sw_isset(cmd
,"-x")) {
640 if (cmd_sw_value(cmd
,"-c",&x
)) {
646 if (cmd_sw_isset(cmd
,"-A")) {
650 if (cmd_sw_isset(cmd
,"-E")) {
654 if (isdigit(*host
)) {
655 if (parseipaddr(host
,hostaddr
) < 0) {
656 xprintf("Invalid IP address: %s\n",host
);
661 res
= dns_lookup(host
,hostaddr
);
663 return ui_showerror(res
,"Could not resolve IP address of host %s",host
);
667 if (forever
) xprintf("Press ENTER to stop pinging\n");
670 res
= icmp_ping(hostaddr
,seq
,size
);
673 xprintf("Could not transmit echo request\n");
674 retval
= CFE_ERR_IOERR
;
678 xprintf("%s (%I) is not responding (seq=%d)\n",host
,hostaddr
,seq
);
679 retval
= CFE_ERR_TIMEOUT
;
680 if (exitonerror
) break;
684 if (!flood
|| ((seq
% 10000) == 0)) {
685 if (forever
|| (ttlcount
> 1)) {
686 xprintf("%s (%I) is alive (seq=%d)\n",host
,hostaddr
,seq
);
688 else xprintf("%s (%I) is alive\n",host
,hostaddr
);
692 if ((forever
|| (count
> 1)) && !flood
) {
693 if (res
> 0) cfe_sleep(CFE_HZ
);
699 } while ((forever
|| (count
> 0)) && (noabort
|| !console_status()));
701 xprintf("%s (%I): %d packets sent, %d received\n",host
,hostaddr
,
702 ttlcount
-count
,countreturned
);
703 return (needexact
? (countreturned
!= ttlcount
) : (countreturned
== 0));