RT-AC66 3.0.0.4.374.130 core
[tomato.git] / release / src-rt-6.x / cfe / cfe / ui / ui_netcmds.c
blob0be725db606c3b19c0548c2c9843abd15354a672
1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
3 *
4 * Network commands File: ui_netcmds.c
5 *
6 * Network user interface
7 *
8 * Author: Mitch Lichtenberg (mpl@broadcom.com)
9 *
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"
55 #include "cfe_iocb.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"
64 #include "env_subr.h"
65 #include "ui_command.h"
66 #include "cfe.h"
67 #include "bsp_config.h"
69 #include "net_ebuf.h"
70 #include "net_ether.h"
72 #include "net_api.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);
81 #if CFG_NETWORK
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[]);
85 #if CFG_TCP
86 extern int ui_init_tcpcmds(void);
87 #endif
88 #endif
90 typedef struct netparam_s {
91 const char *str;
92 int num;
93 } netparam_t;
95 const static netparam_t loopbacktypes[] = {
96 {"off",ETHER_LOOPBACK_OFF},
97 {"internal",ETHER_LOOPBACK_INT},
98 {"external",ETHER_LOOPBACK_EXT},
99 {0,NULL}};
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},
109 {0,NULL}};
112 int ui_init_netcmds(void)
114 #if CFG_NETWORK
115 cmd_addcmd("ifconfig",
116 ui_cmd_ifconfig,
117 NULL,
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"
122 #if CFG_DHCP
123 "The -auto switch can be used to set this information via DHCP.\n"
125 "-auto;Configure interface automatically via DHCP|"
126 #else
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)");
141 cmd_addcmd("arp",
142 ui_cmd_arp,
143 NULL,
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.");
152 cmd_addcmd("ping",
153 ui_cmd_ping,
154 NULL,
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");
170 #if CFG_TCP
171 ui_init_tcpcmds();
172 #endif
175 #endif
177 return 0;
181 #if CFG_NETWORK
182 static int parsexdigit(char str)
184 int digit;
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;
189 else return -1;
191 return digit;
195 static int parsehwaddr(char *str,uint8_t *hwaddr)
197 int digit1,digit2;
198 int idx = 6;
200 while (*str && (idx > 0)) {
201 digit1 = parsexdigit(*str);
202 if (digit1 < 0) return -1;
203 str++;
204 if (!*str) return -1;
206 if ((*str == ':') || (*str == '-')) {
207 digit2 = digit1;
208 digit1 = 0;
210 else {
211 digit2 = parsexdigit(*str);
212 if (digit2 < 0) return -1;
213 str++;
216 *hwaddr++ = (digit1 << 4) | digit2;
217 idx--;
219 if (*str == '-') str++;
220 if (*str == ':') str++;
222 return 0;
227 static int ui_ifdown(void)
229 char *devname;
231 devname = (char *) net_getparam(NET_DEVNAME);
232 if (devname) {
233 xprintf("Device %s has been deactivated.\n",devname);
234 net_uninit();
235 net_setnetvars();
238 return 0;
241 static void ui_showifconfig(void)
243 char *devname;
244 uint8_t *addr;
246 devname = (char *) net_getparam(NET_DEVNAME);
247 if (devname == NULL) {
248 xprintf("Network interface has not been configured\n");
249 return;
252 xprintf("Device %s: ",devname);
254 addr = net_getparam(NET_HWADDR);
255 if (addr) xprintf(" hwaddr %a",addr);
257 addr = net_getparam(NET_IPADDR);
258 if (addr) {
259 if (ip_addriszero(addr)) xprintf(", ipaddr not set");
260 else xprintf(", ipaddr %I",addr);
263 addr = net_getparam(NET_NETMASK);
264 if (addr) {
265 if (ip_addriszero(addr)) xprintf(", mask not set");
266 else xprintf(", mask %I",addr);
269 xprintf("\n");
270 xprintf(" ");
272 addr = net_getparam(NET_GATEWAY);
273 if (addr) {
274 if (ip_addriszero(addr)) xprintf("gateway not set");
275 else xprintf("gateway %I",addr);
278 addr = net_getparam(NET_NAMESERVER);
279 if (addr) {
280 if (ip_addriszero(addr)) xprintf(", nameserver not set");
281 else xprintf(", nameserver %I",addr);
284 addr = net_getparam(NET_DOMAIN);
285 if (addr) {
286 xprintf(", domain %s",addr);
289 xprintf("\n");
292 #if CFG_DHCP
293 static int ui_ifconfig_auto(ui_cmdline_t *cmd,char *devname)
295 int err;
296 dhcpreply_t *reply = NULL;
297 char *x;
298 uint8_t hwaddr[6];
300 net_uninit();
302 err = net_init(devname);
303 if (err < 0) {
304 xprintf("Could not activate device %s: %s\n",
305 devname,cfe_errortext(err));
306 return err;
309 if (cmd_sw_value(cmd,"-hwaddr",&x)) {
310 if (parsehwaddr(x,hwaddr) != 0) {
311 xprintf("Invalid hardware address: %s\n",x);
312 net_uninit();
313 return CFE_ERR_INV_PARAM;
315 else {
316 net_setparam(NET_HWADDR,hwaddr);
320 err = dhcp_bootrequest(&reply);
322 if (err < 0) {
323 xprintf("DHCP registration failed on device %s\n",devname);
324 net_uninit();
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);
338 ui_showifconfig();
339 net_setnetvars();
340 return 0;
342 #endif /* CFG_DHCP */
344 static int ui_ifconfig_getsw(ui_cmdline_t *cmd,char *swname,char *descr,uint8_t *addr)
346 char *x;
348 x = NULL;
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)");
354 return -1;
357 return 1;
360 static int ui_ifconfig_lookup(char *name,char *val,const netparam_t *list)
362 const netparam_t *p = list;
364 while (p->str) {
365 if (strcmp(p->str,val) == 0) return p->num;
366 p++;
369 xprintf("Invalid parameter for %s: Valid options are: ");
371 p = list;
372 while (p->str) {
373 xprintf("%s ",p->str);
374 p++;
377 xprintf("\n");
378 return -1;
382 #define FLG_IPADDR 1
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
388 #define FLG_SPEED 64
389 #define FLG_HWADDR 128
391 static int ui_cmd_ifconfig(ui_cmdline_t *cmd,int argc,char *argv[])
393 char *devname;
394 int flags = 0;
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];
399 uint8_t hwaddr[6];
400 int speed = ETHER_SPEED_AUTO;
401 int loopback = ETHER_LOOPBACK_OFF;
402 char *domain = NULL;
403 int res;
404 char *x;
406 if (argc < 1) {
407 ui_showifconfig();
408 return 0;
411 devname = cmd_getarg(cmd,0);
413 if (cmd_sw_isset(cmd,"-off")) {
414 return ui_ifdown();
417 #if CFG_DHCP
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;
425 if (res > 0) {
426 flags |= FLG_IPADDR;
429 res = ui_ifconfig_getsw(cmd,"-mask","netmask",netmask);
430 if (res < 0) return CFE_ERR_INV_PARAM;
431 if (res > 0) {
432 flags |= FLG_NETMASK;
435 res = ui_ifconfig_getsw(cmd,"-gw","gateway IP address",gateway);
436 if (res < 0) return CFE_ERR_INV_PARAM;
437 if (res > 0) {
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;
443 if (res > 0) {
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;
468 else {
469 flags |= FLG_HWADDR;
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)) {
481 net_uninit();
485 * Okay, initialize the network if it is not already on. If it
486 * is OFF, the "net_devname" parameter will be NULL.
489 if (x == NULL) {
490 res = net_init(devname); /* turn interface on */
491 if (res < 0) {
492 ui_showerror(res,"Could not activate network interface '%s'",devname);
493 return res;
498 * Set the parameters
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);
510 ui_showifconfig();
511 net_setnetvars();
513 return 0;
517 static int ui_cmd_arp(ui_cmdline_t *cmd,int argc,char *argv[])
519 int idx;
520 uint8_t ipaddr[IP_ADDR_LEN];
521 uint8_t hwaddr[ENET_ADDR_LEN];
522 char *x;
523 int once = 0;
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) {
532 arp_delete(ipaddr);
535 else {
536 if (parseipaddr(x,ipaddr) < 0) {
537 xprintf("Invalid IP address: %s\n",x);
538 return CFE_ERR_INV_PARAM;
540 arp_delete(ipaddr);
542 return 0;
546 * Get the IP address. If NULL, display the table.
549 x = cmd_getarg(cmd,0);
550 if (x == NULL) {
551 idx = 0;
552 while (arp_enumerate(idx,ipaddr,hwaddr) >= 0) {
553 if (once == 0) {
554 xprintf("Hardware Address IP Address\n");
555 xprintf("----------------- ---------------\n");
556 once = 1;
558 xprintf("%a %I\n",hwaddr,ipaddr);
559 idx++;
561 if (idx == 0) xprintf("No ARP entries.\n");
562 return 0;
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);
575 if (x == NULL) {
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);
586 return 0;
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[])
596 char *host;
597 uint8_t hostaddr[IP_ADDR_LEN];
598 int res;
599 int seq = 0;
600 int forever = 0;
601 int count = 1;
602 int ttlcount = 1;
603 int countreturned = 0;
604 int size = 56;
605 int flood = 0;
606 int retval = 0;
607 int exitonerror = 0;
608 int needexact = 0;
609 int noabort = 0;
610 char *x;
612 host = cmd_getarg(cmd,0);
613 if (!host) return -1;
615 if (cmd_sw_isset(cmd,"-t")) {
616 forever = 1;
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)) {
624 size = atoi(x);
625 if (size < 0)
626 size = 0;
627 if (size > MAX_PKT_LENGTH - PING_HDR_LENGTH)
628 size = MAX_PKT_LENGTH - PING_HDR_LENGTH;
631 if (cmd_sw_isset(cmd,"-f")) {
632 flood = 1;
633 forever = 1;
636 if (cmd_sw_isset(cmd,"-x")) {
637 exitonerror = 1;
640 if (cmd_sw_value(cmd,"-c",&x)) {
641 count = atoi(x);
642 ttlcount = count;
643 forever = 0;
646 if (cmd_sw_isset(cmd,"-A")) {
647 noabort = 1;
650 if (cmd_sw_isset(cmd,"-E")) {
651 needexact = 1;
654 if (isdigit(*host)) {
655 if (parseipaddr(host,hostaddr) < 0) {
656 xprintf("Invalid IP address: %s\n",host);
657 return -1;
660 else {
661 res = dns_lookup(host,hostaddr);
662 if (res < 0) {
663 return ui_showerror(res,"Could not resolve IP address of host %s",host);
667 if (forever) xprintf("Press ENTER to stop pinging\n");
669 do {
670 res = icmp_ping(hostaddr,seq,size);
672 if (res < 0) {
673 xprintf("Could not transmit echo request\n");
674 retval = CFE_ERR_IOERR;
675 break;
677 else if (res == 0) {
678 xprintf("%s (%I) is not responding (seq=%d)\n",host,hostaddr,seq);
679 retval = CFE_ERR_TIMEOUT;
680 if (exitonerror) break;
682 else {
683 countreturned++;
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);
696 seq++;
697 count--;
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));
706 #endif