/** * Sends rdate message to destination and retrieves date * @param dest the destination of the rdate message * @return aquired date for success, SYSERR for syntax error */ long getRdate(char *dest) { ushort dev = 0; uchar buf[4]; struct netaddr host; struct netaddr *localhost; struct netif *interface; bzero((uchar *)buf, 4); /* Open Device on rdate port */ if ((ushort)SYSERR == (dev = udpAlloc())) { return SYSERR; } if (SYSERR == dot2ipv4(dest, &host)) { return SYSERR; } /* Look up local ip info */ interface = netLookup((ethertab[0].dev)->num); if (NULL == interface) { fprintf(stderr, "No network interface found\n"); return 1; } localhost = &(interface->ip); if (SYSERR == open(dev, localhost, &host, NULL, UDP_PORT_RDATE)) { return SYSERR; } /* Write Message to destination */ if (SYSERR == write(dev, buf, 4)) { return SYSERR; } /* If we read an invalid amount, then rdate failed */ if (SYSERR == read(dev, buf, 4)) { return SYSERR; } /* Close device after completion */ if (SYSERR == (long)close(dev)) { return SYSERR; } /* convert bytes to long */ return (buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + buf[3]; }
/** * Shell command (netup) to start a network interface. * @param nargs number of arguments in args array * @param args array of arguments * @return OK for success, SYSERR for syntax error */ shellcmd xsh_netup(int nargs, char *args[]) { int descrp; struct netaddr ip; struct netaddr mask; struct netaddr gateway; char *str_ip, *str_mask, *str_gateway; char nvramLookup[DEVMAXNAME + NVRAM_STRMAX]; /* Enable interrupts */ enable(); /* Help */ if ((2 == nargs) && (0 == strncmp(args[1], "--help", 7))) { usage(args[0]); return SHELL_OK; } /* Parse device */ if (nargs > 1) { descrp = getdev(args[1]); if (SYSERR == descrp) { fprintf(stderr, "%s is not a valid device.\n", args[1]); return SHELL_ERROR; } } else { /* assume first ethernet interface */ descrp = (ethertab[0].dev)->num; } if (5 == nargs) { /* grab string data */ str_ip = args[2]; str_mask = args[3]; str_gateway = args[4]; } else if (nargs < 3) { /* lookup information in nvram */ bzero(nvramLookup, DEVMAXNAME + NVRAM_STRMAX); sprintf(nvramLookup, "%s_%s", (ethertab[0].dev)->name, NET_LAN_IPADDR); #if NVRAM str_ip = nvramGet(nvramLookup); if (NULL == str_ip) { str_ip = nvramGet("lan_ipaddr"); } #else str_ip = NULL; #endif /* NVRAM */ bzero(nvramLookup, DEVMAXNAME + NVRAM_STRMAX); sprintf(nvramLookup, "%s_%s", (ethertab[0].dev)->name, NET_SUBNET_MASK); #if NVRAM str_mask = nvramGet(nvramLookup); if (NULL == str_mask) { str_mask = nvramGet("lan_netmask"); } #else str_mask = NULL; #endif /* NVRAM */ #if NVRAM str_gateway = nvramGet(NET_GATEWAY); if (NULL == str_gateway) { str_gateway = nvramGet("lan_gateway"); } #else str_gateway = NULL; #endif /* NVRAM */ } else { fprintf(stderr, "Invalid number of arguments\n"); return SHELL_ERROR; } /* Make sure we have valid IPv4 style parameters */ if (NULL == str_ip) { str_ip = "0.0.0.0"; } if (NULL == str_mask) { str_mask = "0.0.0.0"; } if (NULL == str_gateway) { str_gateway = "0.0.0.0"; } /* Parse IP */ if (SYSERR == dot2ipv4(str_ip, &ip)) { fprintf(stderr, "%s is not a valid IPv4 address.\n", str_ip); return SHELL_ERROR; } /* Parse Mask */ if (SYSERR == dot2ipv4(str_mask, &mask)) { fprintf(stderr, "%s is not a valid IPv4 address mask.\n", str_mask); return SHELL_ERROR; } /* Parse Gateway */ if (SYSERR == dot2ipv4(str_gateway, &gateway)) { fprintf(stderr, "%s is not a valid IPv4 address.\n", str_gateway); return SHELL_ERROR; } if (SYSERR == netUp(descrp, &ip, &mask, &gateway)) { fprintf(stderr, "Failed to start network interface on %s\n", args[1]); return SHELL_ERROR; } printf("%s is %s with netmask %s (gateway: %s)\n", devtab[descrp].name, str_ip, str_mask, str_gateway); return SHELL_OK; }
/** * @ingroup shell * * Shell command (telnet). * @param nargs number of arguments in args array * @param args array of arguments * @return 0 for success, 1 for error */ shellcmd xsh_telnet(int nargs, char *args[]) { int i; ushort port = 0; struct netaddr host; struct netaddr *localhost; struct netif *interface; tid_typ recvthr; tid_typ sendthr; int msg = 0; int dev; for (i = 1; i < nargs; i++) { /* Help */ if (0 == strcmp(args[i], "--help")) { usage(args[0]); return 0; } /* Host */ if (0 == host.len) { if (SYSERR == dot2ipv4(args[i], &host)) { fprintf(stderr, "Invalid hostname\n"); return 1; } continue; } /* Port */ if (0 == port) { port = atoi(args[i]); if (port == 0) { fprintf(stderr, "Port must be greater than 0\n"); return 1; } continue; } /* Otherwise */ fprintf(stderr, "Invalid number of arguments\n"); return 1; } /* Verify a valid number of arguments were processed */ if (0 == host.len) { fprintf(stderr, "Invalid number of arguments\n"); return 1; } /* Set default port if none is specified */ if (port == 0) { port = TELNET_PORT; } /* Print that the client is trying to connect to the server */ printf("Trying %s...\n", args[1]); interface = netLookup((ethertab[0].dev)->num); if (NULL == interface) { fprintf(stderr, "No network interface found\n"); return 1; } localhost = &(interface->ip); /* Open connection */ #if NTCP dev = tcpAlloc(); #else dev = SYSERR; #endif /* NTCP */ if (SYSERR == dev) { fprintf(stderr, "Failed to allocate TCP device\n"); return 1; } if (SYSERR == open(dev, localhost, &host, NULL, port, TCP_ACTIVE)) { fprintf(stderr, "Failed to establish connection\n"); return 1; } /* Display a connection prompt and tell the user how to quit */ printf("Connected to %s.\nQuit character is '^]'.\n", args[1]); recvthr = create(telnetRecv, SHELL_CMDSTK, SHELL_CMDPRIO, "telnet_recv", 1, dev); sendthr = create(telnetSend, SHELL_CMDSTK, SHELL_CMDPRIO, "telnet_send", 1, dev); if ((SYSERR == recvthr) || (SYSERR == sendthr)) { kill(recvthr); kill(sendthr); close(dev); return 1; } thrtab[recvthr].fdesc[0] = stdin; thrtab[recvthr].fdesc[1] = stdout; thrtab[recvthr].fdesc[2] = stderr; thrtab[sendthr].fdesc[0] = stdin; thrtab[sendthr].fdesc[1] = stdout; thrtab[sendthr].fdesc[2] = stderr; /* Start both threads */ while (recvclr() != NOMSG); control(stdin, TTY_CTRL_SET_IFLAG, TTY_ECHO, NULL); control(stdin, TTY_CTRL_CLR_IFLAG, TTY_IRAW, NULL); ready(recvthr, RESCHED_YES); ready(sendthr, RESCHED_NO); /* Wait for one thread to die */ while ((msg != recvthr) && (msg != sendthr)) { msg = receive(); } sleep(10); /* Kill both threads */ kill(recvthr); kill(sendthr); close(dev); control(stdin, TTY_CTRL_SET_IFLAG, TTY_ECHO, NULL); control(stdin, TTY_CTRL_CLR_IFLAG, TTY_IRAW, NULL); return 0; }
/** * @ingroup shell * * Shell command (ping). * @param nargs number of arguments in args array * @param args array of arguments * @return OK for success, SYSERR for syntax error */ shellcmd xsh_ping(int nargs, char *args[]) { int i = 0; int interval = 1000, count = 10, recv = 0, echoq = 0; ulong rtt = 0, min = 0, max = 0, total = 0; ulong startsec = 0, startms = 0; struct netaddr target; struct packet *pkt = NULL; char str[50]; /* Output help, if '--help' argument was supplied */ if (nargs == 2 && strncmp(args[1], "--help", 7) == 0) { printf("Usage: ping <IP>\n\n"); printf("Description:\n"); printf("\tSend ICMP echo requests to network hosts\n"); printf("Options:\n"); printf("\t<IP>\t\tIP address\n"); printf("\t-c count\tstop after sending count packets\n"); printf ("\t-i interval\tsleep interval milliseconds between pings\n"); printf("\t--help\t\tdisplay this help and exit\n"); return OK; } /* Check for correct number of arguments */ if (nargs < 2) { fprintf(stderr, "ping: too few arguments\n"); fprintf(stderr, "Try 'ping --help' for more information\n"); return SHELL_ERROR; } i = 1; while (i < nargs) { if (0 == strncmp(args[i], "-c", 3)) { i++; if (i < nargs) { count = atoi(args[i]); } else { fprintf(stderr, "ping: -c requires integer argument\n"); return SHELL_ERROR; } } else if (0 == strncmp(args[i], "-i", 3)) { i++; if (i < nargs) { interval = atoi(args[i]); } else { fprintf(stderr, "ping: -i requires integer argument\n"); return SHELL_ERROR; } } else if (SYSERR == dot2ipv4(args[i], &target)) { fprintf(stderr, "ping: %s is not a valid IPv4 address.\n", args[i]); return SHELL_ERROR; } i++; } netaddrsprintf(str, &target); if (0 == strncmp(str, "ERROR", 6)) { fprintf(stderr, "ping: destination IP address required.\n"); return SHELL_ERROR; } printf("PING %s\n", str); echoq = echoQueueAlloc(); if (SYSERR == echoq) { printf("...No free echo queues!\n"); return SHELL_ERROR; } startsec = clktime; startms = clkticks; for (i = 0; i < count; i++) { // Send ping packet if (SYSERR == icmpEchoRequest(&target, gettid(), i)) { printf("...Failed to reach %s\n", str); return SHELL_ERROR; } sleep(interval); if (NOMSG != recvclr()) { // pick reply packets off of the queue pkt = echoQueueGet(echoq); while ((NULL != (ulong)pkt) && (SYSERR != (ulong)pkt)) { rtt = echoTripTime(pkt); total += rtt; if ((rtt < min) || (0 == min)) { min = rtt; } if (rtt > max) { max = rtt; } echoPrintPkt(pkt, rtt); netFreebuf(pkt); recv++; pkt = echoQueueGet(echoq); } } } echoQueueDealloc(echoq); netaddrsprintf(str, &target); printf("--- %s ping statistics ---\n", str); printf("%d packets transmitted, %d received,", count, recv); printf(" %d%% packet loss,", (count - recv) * 100 / count); printf(" time %dms\n", (clktime - startsec) * 1000 + ((clkticks - startms) * 1000) / CLKTICKS_PER_SEC); printf("rtt min/avg/max = %d.%03d/", min / 1000, min % 1000); if (0 != recv) { printf("%d.%03d/", (total / recv) / 1000, (total / recv) % 1000); } else { printf("-/"); } printf("%d.%03d ms\n", max / 1000, max % 1000); return SHELL_OK; }
/** * @ingroup shell * * Shell command (nc). * @param nargs number of arguments in args array * @param args array of arguments * @return 0 for success, 1 for error */ shellcmd xsh_nc(int nargs, char *args[]) { int a; ushort port; bool listen = FALSE; struct netaddr dst; struct netaddr src; tid_typ recvthr; tid_typ sendthr; int msg = 0; int dev; /* Output help, if '--help' argument was supplied */ if (nargs == 2 && 0 == strncmp(args[1], "--help", 7)) { usage(args[0]); return 0; } port = 0; dst.type = NULL; src.type = NULL; /* Parse arguments */ for (a = 1; a < nargs; a++) { if (args[a][0] != '-') { if (!listen && NULL == dst.type) { if (!isdigit(args[a][0])) { return argError(args[a]); } dot2ipv4(args[a], &dst); } else if (listen && NULL == src.type) { if (!isdigit(args[a][0])) { return argError(args[a]); } dot2ipv4(args[a], &src); } else if (NULL == port) { if (!isdigit(args[a][0])) { return argError(args[a]); } port = atoi(args[a]); } } else { switch (args[a][1]) { /* Listen on port */ case 'l': listen = TRUE; break; /* Source IP */ case 's': a++; if (a >= nargs || !isdigit(args[a][0])) { return argError(args[a - 1]); } dot2ipv4(args[a], &src); break; default: return argError(args[a]); } } } /* Verify arguments */ if (NULL == src.type) { fprintf(stderr, "Source/listen IP address required\n"); return 1; } if (NULL == port) { fprintf(stderr, "Invalid port\n"); return 1; } if (!listen && NULL == dst.type) { fprintf(stderr, "Remote IP address required\n"); return 1; } /* Allocate a TCP device */ #ifdef NTCP dev = tcpAlloc(); #else dev = SYSERR; #endif /* NTCP */ if (SYSERR == dev) { return connError(); } if (listen) { if (SYSERR == open(dev, &src, NULL, port, NULL, TCP_PASSIVE)) { close(dev); return connError(); } } else { if (SYSERR == open(dev, &src, &dst, NULL, port, TCP_ACTIVE)) { close(dev); return connError(); } } recvthr = create(ncRecv, SHELL_CMDSTK, SHELL_CMDPRIO, "nc_recv", 1, dev); sendthr = create(ncSend, SHELL_CMDSTK, SHELL_CMDPRIO, "nc_send", 1, dev); if ((SYSERR == recvthr) || (SYSERR == sendthr)) { kill(recvthr); kill(sendthr); close(dev); fprintf(stderr, "Failed to spawn threads"); return 1; } thrtab[recvthr].fdesc[0] = stdin; thrtab[recvthr].fdesc[1] = stdout; thrtab[recvthr].fdesc[2] = stderr; thrtab[sendthr].fdesc[0] = stdin; thrtab[sendthr].fdesc[1] = stdout; thrtab[sendthr].fdesc[2] = stderr; /* Start both threads */ while (recvclr() != NOMSG); ready(recvthr, RESCHED_YES); ready(sendthr, RESCHED_NO); /* Wait for one thread to die */ while ((msg != recvthr) && (msg != sendthr)) { msg = receive(); } sleep(10); /* Kill both threads */ kill(recvthr); kill(sendthr); close(dev); return 0; }
/** * @ingroup shell * * Shell command (route) displays routing information. * @param nargs number of arguments * @param args array of arguments * @return non-zero value on error */ shellcmd xsh_route(int nargs, char *args[]) { int i; char c[32]; device *pdev; struct netif *netptr; struct netaddr dst; struct netaddr mask; struct netaddr gateway; /* Check for correct number of arguments */ if (nargs > 6) { fprintf(stderr, "%s: too many arguments\n", args[0]); fprintf(stderr, "Try '%s --help' for more information\n", args[0]); return SYSERR; } /* Output help, if '--help' argument was supplied */ if (nargs == 2 && strcmp(args[1], "--help") == 0) { printf("\nUsage: %s ", args[0]); printf("[add <DESTINATION> <GATEWAY> <MASK> <INTERFACE>] "); printf("[del <DESTINATION>]\n\n"); printf("Description:\n"); printf("\tDisplays routing table\n"); printf("Options:\n"); printf("\tadd <DESTINATION> <GATEWAY> <MASK> <INTERFACE>\n"); printf("\t\t\t\tadd route entry into table.\n"); printf("\t\t\t\t(<INTERFACE> must be in all caps.)\n"); printf("\tdel <DESTINATION>"); printf("\tdelete route entry from table.\n"); printf("\t--help\t\t\tdisplay this help and exit\n"); return OK; } if (nargs == 6 && strcmp(args[1], "add") == 0) { /* Parse destination */ if (strcmp(args[2], "default") == 0) { args[2] = ""; } if (SYSERR == dot2ipv4(args[2], &dst)) { fprintf(stderr, "%s is not a valid IPv4 address.\n", args[2]); return SYSERR; } /* Parse gateway */ if (SYSERR == dot2ipv4(args[3], &gateway)) { fprintf(stderr, "%s is not a valid IPv4 address.\n", args[3]); return SYSERR; } /* Parse mask */ if (SYSERR == dot2ipv4(args[4], &mask)) { fprintf(stderr, "%s is not a valid IPv4 address mask.\n", args[4]); return SYSERR; } /* Parse interface */ #if NNETIF for (i = 0; i < NNETIF; i++) { if (NET_ALLOC == netiftab[i].state) { netptr = &netiftab[i]; pdev = (device *)&devtab[netptr->dev]; if (strcmp(pdev->name, args[5]) == 0) { if (SYSERR == rtAdd(&dst, &gateway, &mask, netptr)) { fprintf(stderr, "Failed to add route.\n"); return SYSERR; } return OK; } } } #endif fprintf(stderr, "%s is not a valid network interface.\n", args[5]); return SYSERR; } else if (nargs == 3 && strcmp(args[1], "del") == 0) { /* Parse destination */ if (strcmp(args[2], "default") == 0) { args[2] = ""; } if (SYSERR == dot2ipv4(args[2], &dst)) { fprintf(stderr, "%s is not a valid IPv4 address.\n", args[2]); return SYSERR; } if (SYSERR == rtRemove(&dst)) { fprintf(stderr, "Failed to delete route.\n"); return SYSERR; } return OK; } printf ("Destination Gateway Mask Interface\r\n"); for (i = 0; i < RT_NENTRY; i++) { if (RT_USED == rttab[i].state) { if (0 == rttab[i].masklen) sprintf(c, "default"); else netaddrsprintf(c, &rttab[i].dst); printf("%-16s", c); netaddrsprintf(c, &rttab[i].gateway); if (strcmp(c, "NULL") == 0) sprintf(c, "*"); printf("%-16s", c); netaddrsprintf(c, &rttab[i].mask); printf("%-16s", c); netptr = rttab[i].nif; pdev = (device *)&devtab[netptr->dev]; printf("%s\r\n", pdev->name); } } return 0; }
/** * Shell command for VoIP functionality. * @param nargs number of arguments * @param args array of arguments * @return OK for success, SYSERR for syntax error */ shellcmd xsh_voip(int nargs, char *args[]) { int i, rxPort = UDP_PORT, txPort = UDP_PORT; ushort uart = NULL, udpRx = NULL, udpTx = NULL; ushort mode = MODE_SERIAL, check = CHECK_BASIC; struct netaddr *localhost; struct netaddr host; #ifdef ELOOP struct netaddr mask; #endif struct netif *netptr; struct thrent *thrptr; if (nargs < 2) { fprintf(stderr, "%s: too few arguments\n", args[0]); fprintf(stderr, "Try '%s --help' for more information\n", args[0]); return SYSERR; } else if (nargs == 2 && strncmp(args[1], "--help", 6) == 0) { printf ("\nUsage: %s [-p <rx port> <tx port>] [-s] [serial] [localhost] [IP address]\n", args[0]); printf("Description:\n"); printf("\tUses the second serial port and the network to "); printf("transmit and receive audio.\n"); printf("Options:\n"); printf ("\t-p\t\tSpecify UDP receive and transmit port numbers.\n"); printf("\t-s\t\tEmbed sequence information in each packet.\n"); printf("\tserial\t\tOperate in serial loopback mode.\n"); printf("\tlocalhost\tOperate in network loopback mode.\n"); printf("\tIP address\tSend and receive from this IP address.\n"); return OK; } else { for (i = 1; i < nargs; i++) { if (strncmp(args[i], "-s", 2) == 0) { check = CHECK_SEQ; } else if (strncmp(args[i], "-p", 2) == 0) { if ((i + 2) < nargs) { i++; rxPort = atol(args[i]); i++; txPort = atol(args[i]); } else { fprintf(stderr, "Insufficient number of arguments for port numbers.\n"); return SYSERR; } } else if (strncmp(args[i], "serial", 6) == 0) { mode = MODE_SERIAL; } else if (strncmp(args[i], "localhost", 9) == 0) { mode = MODE_LOCAL; } else if (SYSERR != dot2ipv4(args[i], &host)) { mode = MODE_IP; } else { fprintf(stderr, "Failed to parse destination IP address.\n"); return SYSERR; } } } enable(); #ifdef TTY1 /* Kill the SHELL1 thread */ for (i = 0; i < NTHREAD; i++) { thrptr = &thrtab[i]; if (thrptr->state == THRFREE) { continue; } if (0 == strncmp(thrptr->name, "SHELL1", 6)) { kill(i); } } /* Close TTY1 so we can use SERIAL1 */ close(TTY1); #else thrptr = NULL; #endif /* TTY1 */ #ifdef SERIAL1 uart = SERIAL1; #else uart = SYSERR; #endif /* SERIAL1 */ if (SYSERR == (short)uart) { fprintf(stderr, "Failed to select a uart device."); return SYSERR; } switch (mode) { case MODE_SERIAL: ready(create ((void *)serial_loop, INITSTK, 20, "voip-serial", 1, uart), RESCHED_YES); return OK; #ifdef ELOOP case MODE_LOCAL: if (SYSERR == open(ELOOP)) { fprintf(stderr, "Failed to open loopback device."); return SYSERR; } dot2ipv4("127.0.0.1", &host); localhost = &host; dot2ipv4("255.255.255.0", &mask); if (SYSERR == netUp(ELOOP, &host, &mask, NULL)) { close(ELOOP); fprintf(stderr, "Failed to bring up network on loopback device.\n"); return SYSERR; } break; #endif /* ELOOP */ case MODE_IP: netptr = netLookup((ethertab[0].dev)->num); if (NULL == netptr) { fprintf(stderr, "No network interface found.\n"); return SYSERR; } localhost = &(netptr->ip); srand(localhost->addr[3]); /* Seed the random number generator */ break; default: return SYSERR; } #ifdef NUDP if (UDP_PORT == rxPort && UDP_PORT == txPort) { /* If both ports are the default, use one UDP device */ udpRx = udpAlloc(); udpTx = udpRx; } else { /* Otherwise, use two UDP devices */ udpRx = udpAlloc(); udpTx = udpAlloc(); } #else udpRx = SYSERR; udpTx = SYSERR; #endif /* NUDP */ if (SYSERR == (short)udpRx || SYSERR == (short)udpTx) { fprintf(stderr, "Unable to allocate a UDP device.\n"); return SYSERR; } if (udpRx == udpTx) { if (SYSERR == open(udpRx, localhost, &host, rxPort, txPort)) { fprintf(stderr, "Failed to open UDP device.\n"); return SYSERR; } printf("Opened a single UDP device.\n"); } else { if (SYSERR == open(udpRx, localhost, NULL, rxPort, NULL)) { fprintf(stderr, "Failed to open UDP device.\n"); return SYSERR; } if (SYSERR == open(udpTx, localhost, &host, NULL, txPort)) { fprintf(stderr, "Failed to open UDP device.\n"); return SYSERR; } printf("Opened two UDP devices.\n"); } switch (check) { case CHECK_BASIC: ready(create ((void *)basic_send, INITSTK, 20, "voip-send", 2, uart, udpTx), RESCHED_YES); ready(create ((void *)basic_receive, INITSTK, 20, "voip-receive", 2, uart, udpRx), RESCHED_YES); break; case CHECK_SEQ: #ifdef NUDP control(udpRx, UDP_CTRL_SETFLAG, UDP_FLAG_NOBLOCK, NULL); control(udpTx, UDP_CTRL_SETFLAG, UDP_FLAG_NOBLOCK, NULL); #endif /* NUDP */ ready(create ((void *)seq_send, INITSTK, 20, "voip-send", 2, uart, udpTx), RESCHED_YES); ready(create ((void *)seq_receive, INITSTK, 20, "voip-receive", 2, uart, udpRx), RESCHED_YES); break; } return OK; }