/** * 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]; }
/** * HTTP server thread * @param host IP address of interface on which to listen * @param gentcpdev the allocated tcp device for general listening * @return OK or SYSERR */ thread httpServer(int netDescrp, int gentcpdev) { tid_typ shelltid, killtid; int tcpdev, httpdev; char thrname[TNMLEN]; bool noGenHTTP; struct netaddr *host; struct netif *nif; enable(); noGenHTTP = FALSE; wait(maxhttp); /* Make sure max HTTP threads not reached */ /* Allocate HTTP device */ httpdev = httpAlloc(); /* Received bad http device, close out allocated resources */ if (isbadhttp(httpdev)) { printf("failed to allocate proper HTTP device\n"); signal(maxhttp); return SYSERR; } /* Back up the general tcpdev number */ tcpdev = gentcpdev; /* Look up the network descriptor */ nif = netLookup(netDescrp); if (SYSERR == (int)nif) { fprintf(stderr, "%s is not associated with an active network", devtab[netDescrp].name); fprintf(stderr, " interface.\n"); return SYSERR; } host = &(nif->ip); /* Open HTTP device */ if (SYSERR == (long)open(httpdev, tcpdev)) { fprintf(stderr, "httpOpen SYSERR\n"); close(tcpdev); close(httpdev); return SYSERR; } /* Create web shell */ sprintf(thrname, "XWebShell_%d\0", (devtab[tcpdev].minor)); shelltid = create((void *)shell, INITSTK, INITPRIO, thrname, 3, httpdev, httpdev, DEVNULL); if (isbadtid(shelltid)) { fprintf(stderr, "shell creation bad tid\n"); close(httpdev); close(tcpdev); return SYSERR; } /* Spawn thread that will wait for kill httpserver thread signal */ sprintf(thrname, "XWebKillerD_%d\0", (devtab[tcpdev].minor)); killtid = create((void *)killHttpServer, INITSTK, INITPRIO, thrname, 3, httpdev, shelltid, tcpdev); /* Ready spawned threads */ ready(shelltid, RESCHED_NO); ready(killtid, RESCHED_NO); /* Open TCP device */ if (SYSERR == (long)open(tcpdev, host, NULL, HTTP_LOCAL_PORT, NULL, TCP_PASSIVE)) { int temp; sleep(TCP_TWOMSL + 500); if (SYSERR == (temp = (long)open(tcpdev, host, NULL, HTTP_LOCAL_PORT, NULL, TCP_PASSIVE))) { fprintf(CONSOLE, "open returns: %d\n", temp); fprintf(stderr, "tcpOpen SYSERR, devnum: %d\n", tcpdev); kill(shelltid); close(tcpdev); close(httpdev); return SYSERR; } fprintf(CONSOLE, "open returns: %d\n", temp); } /* Allocate TCP device */ gentcpdev = tcpAlloc(); if (isbadtcp(gentcpdev)) { /* Wait for a free http device */ wait(maxhttp); /* Acquire a TCP device through allocation */ while ((ushort)SYSERR == (gentcpdev = tcpAlloc())) { /* Do nothing, yield processor */ yield(); } /* Everything acquired, spawn general http device listener */ if (semcount(activeXWeb) <= 0) { sprintf(thrname, "XWeb_%d\0", (devtab[gentcpdev].minor)); ready(create((void *)httpServer, INITSTK, INITPRIO, thrname, 2, netDescrp, gentcpdev), RESCHED_NO); } /* Did not consume http device, just waited for availability */ signal(maxhttp); } else { sprintf(thrname, "XWeb_%d\0", (devtab[gentcpdev].minor)); ready(create((void *)httpServer, INITSTK, INITPRIO, thrname, 2, netDescrp, gentcpdev), RESCHED_NO); } return 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 dhcpc * * DHCP (Dynamic Host Configuration Protocol) client for IPv4 autoconfiguration. * * TODO: This function returns immediately once the IP address has been * assigned. It does not handle renewing leases. * * @param[in] descrp * Device descriptor for the network device on which to open the DHCP * client on. This must be a network device that is open but has no * network interface brought up on it. * @param[in] timeout * Seconds to wait before timing out (must be a positive integer). * @param[out] data * On success, this structure is filled in with the information about the * IPv4 configuration. At least the @ref dhcpData::ip "ip" and @ref * dhcpData::mask "mask" members will be valid. The @ref dhcpData::gateway * "gateway", @ref dhcpData::bootfile "bootfile", and @ref * dhcpData::next_server "next_server" members are optional and will be * left as all 0's if not provided. * * @return * ::OK if successful; ::SYSERR if sending a DHCPDISCOVER packet failed or * if a parameter was invalid; ::TIMEOUT if timed out. */ syscall dhcpClient(int descrp, uint timeout, struct dhcpData *data) { int retval; uint recvTimeout = 2000; /* Milliseconds to wait before timing out a given receive (not the whole client) */ uint delay = 1000; /* Milliseconds to wait after non-timeout error */ ulong starttime = clktime; /* Check for invalid parameters. */ #if NETHER if (descrp < ETH0 || descrp >= ETH0 + NETHER) #endif { DHCP_TRACE("Bad device descriptor.\n"); return SYSERR; } if (0 == timeout) { DHCP_TRACE("Timeout cannot be zero.\n"); return SYSERR; } if (NULL == data) { DHCP_TRACE("No data buffer provided.\n"); return SYSERR; } if (NULL != netLookup(descrp)) { DHCP_TRACE("Network interface is up on device.\n"); return SYSERR; } bzero(data, sizeof(*data)); data->state = DHCPC_STATE_INIT; while (clktime <= starttime + timeout) { switch (data->state) { case DHCPC_STATE_INIT: /* Initialize transfer data. */ data->cxid = rand(); /* Choose random context ID */ data->starttime = clktime; /* Set starting time */ data->clientIpv4Addr = 0; /* Client IP address is unknown */ data->serverIpv4Addr = 0; /* Server IP address is unknown */ /* Client hardware address is known; get it from network device. */ if (SYSERR == control(descrp, NET_GET_HWADDR, (long)data->clientHwAddr, 0)) { DHCP_TRACE("Failed to get client hardware address"); return SYSERR; } /* Server hardware address is unknown */ bzero(data->serverHwAddr, ETH_ADDR_LEN); /* Broadcast DHCPDISCOVER. */ DHCP_TRACE("Sending DHCPDISCOVER"); retval = dhcpSendRequest(descrp, data); if (OK == retval) { DHCP_TRACE("Sent DHCPDISCOVER"); data->state = DHCPC_STATE_SELECTING; } else { DHCP_TRACE("Failed to send DHCPDISCOVER; returning failure"); return SYSERR; } break; case DHCPC_STATE_SELECTING: /* Wait for DHCPOFFER from any server. */ DHCP_TRACE("Waiting for DHCPOFFER"); retval = dhcpRecvReply(descrp, data, recvTimeout); if (OK != retval) { DHCP_TRACE("Failed to receive DHCPOFFER"); data->state = DHCPC_STATE_INIT; if (TIMEOUT != retval) { sleep(delay); } break; } /* Send DHCPREQUEST to the server based on the DHCPOFFER. */ DHCP_TRACE("Sending DHCPREQUEST"); retval = dhcpSendRequest(descrp, data); if (OK == retval) { DHCP_TRACE("Sent DHCPREQUEST"); data->state = DHCPC_STATE_REQUESTING; } else { DHCP_TRACE("Failed to send DHCPREQUEST"); data->state = DHCPC_STATE_INIT; sleep(delay); } break; case DHCPC_STATE_REQUESTING: /* Wait for DHCPACK from the server to whom we sent the DHCPREQUEST. * */ DHCP_TRACE("Waiting for DHCPACK"); retval = dhcpRecvReply(descrp, data, recvTimeout); if (OK == retval) { DHCP_TRACE("Received DHCPACK"); data->state = DHCPC_STATE_BOUND; return OK; } else { DHCP_TRACE("Failed to receive DHCPACK"); data->state = DHCPC_STATE_INIT; if (TIMEOUT != retval) { sleep(delay); } } break; } } return TIMEOUT; }
/** * 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; }
static void kexec_from_network(int netdev, char *boot) { #if defined(WITH_DHCPC) && NETHER != 0 struct dhcpData data; int result; const struct netaddr *gatewayptr; struct netif *nif; void *kernel; uint size; char str_ip[20]; char str_mask[20]; char str_gateway[20]; const char *netdevname = devtab[netdev].name; /* Bring network interface (if any) down. */ netDown(netdev); /* Run DHCP client on the device for at most 10 seconds. */ printf("Running DHCP on %s\n", netdevname); result = dhcpClient(netdev, 10, &data); if (OK != result) { fprintf(stderr, "ERROR: DHCP failed.\n"); return; } /* Ensure the DHCP server provided the boot filename and TFTP server IP * address. */ if (('\0' == data.bootfile[0] || 0 == data.next_server.type) && boot == NULL) { fprintf(stderr, "ERROR: DHCP server did not provide boot file " "and TFTP server address.\n"); return; } /* Bring up the network interface. */ netaddrsprintf(str_ip, &data.ip); netaddrsprintf(str_mask, &data.mask); if (0 != data.gateway.len) { netaddrsprintf(str_gateway, &data.gateway); printf("Bringing up %s as %s with mask %s (gateway %s)\n", netdevname, str_ip, str_mask, str_gateway); gatewayptr = &data.gateway; } else { printf("Bringing up %s as %s with mask %s (no gateway)\n", netdevname, str_ip, str_mask); gatewayptr = NULL; } result = netUp(netdev, &data.ip, &data.mask, gatewayptr); if (OK != result) { fprintf(stderr, "ERROR: failed to bring up %s.\n", netdevname); return; } nif = netLookup(netdev); /* Download new kernel using TFTP. */ netaddrsprintf(str_ip, &data.next_server); if (boot == NULL) { printf("Downloading bootfile \"%s\" from TFTP server %s\n", data.bootfile, str_ip); kernel = (void*)tftpGetIntoBuffer(data.bootfile, &nif->ip, &data.next_server, &size); }else { printf("Downloading bootfile \"%s\" from TFTP server %s\n", boot, str_ip); kernel = (void*)tftpGetIntoBuffer(boot, &nif->ip, &data.next_server, &size); } if (SYSERR == (int)kernel) { fprintf(stderr, "ERROR: TFTP failed.\n"); return; } /* Execute the new kernel. */ printf("Executing new kernel (size=%u)\n", size); sleep(100); /* Wait just a fraction of a second for printf()s to finish (no guarantees though). */ kexec(kernel, size); fprintf(stderr, "ERROR: kexec() returned!\n"); #else /* WITH_DHCPC && NETHER != 0 */ fprintf(stderr, "ERROR: Network boot is not supported in this configuration.\n" " Please make sure you have enabled one or more network\n" " devices, along with the DHCP and TFTP clients.\n"); #endif /* !(WITH_DHCPC && NETHER != 0) */ }