static int tcp_write(tcpcon_t *tc, const void *data, size_t len) { #ifdef MSG_NOSIGNAL return netSend(tc->fd, data, len, MSG_NOSIGNAL) != len ? ECONNRESET : 0; #else return netSend(tc->fd, data, len, 0 ) != len ? ECONNRESET : 0; #endif }
// returns 0 on success and a (negative) error number on failure int socketSendData(JsNetwork *net, JsVar *connection, int sckt, JsVar **sendData) { char *buf = alloca(net->chunkSize); // allocate on stack assert(!jsvIsEmptyString(*sendData)); size_t bufLen = httpStringGet(*sendData, buf, net->chunkSize); int num = netSend(net, sckt, buf, bufLen); if (num < 0) return num; // an error occurred // Now cut what we managed to send off the beginning of sendData if (num > 0) { JsVar *newSendData = 0; if (num < (int)jsvGetStringLength(*sendData)) { // we didn't send all of it... cut out what we did send newSendData = jsvNewFromStringVar(*sendData, (size_t)num, JSVAPPENDSTRINGVAR_MAXLENGTH); } else { // we sent all of it! Issue a drain event, unless we want to close, then we shouldn't // callback for more data bool wantClose = jsvGetBoolAndUnLock(jsvObjectGetChild(connection,HTTP_NAME_CLOSE,0)); if (!wantClose) { jsiQueueObjectCallbacks(connection, HTTP_NAME_ON_DRAIN, &connection, 1); } newSendData = jsvNewFromEmptyString(); } jsvUnLock(*sendData); *sendData = newSendData; } return 0; }
void debugPrintf(const char* fmt, ...) { char buffer[0x800]; va_list arg; va_start(arg, fmt); vsnprintf(buffer, sizeof(buffer), fmt, arg); va_end(arg); netSend(SocketFD, buffer, strlen(buffer), 0); }
// Attempt to send buffer on an established client connection, returns true if it sent something bool telnetSendBuf(JsNetwork *net) { if (tnSrv.sock == 0 || tnSrv.cliSock == 0) return false; // if we have nothing buffered, that's it if (tnSrv.txBufLen == 0) return false; // try to send the tx buffer int sent = netSend(net, tnSrv.cliSock, tnSrv.txBuf, tnSrv.txBufLen); if (sent == tnSrv.txBufLen) { tnSrv.txBufLen = 0; } else if (sent > 0) { // shift remaining chars up in the buffer memmove(tnSrv.txBuf, tnSrv.txBuf+sent, (size_t)(tnSrv.txBufLen-sent)); tnSrv.txBufLen -= (uint16_t)sent; } else if (sent < 0) { telnetRelease(net); } if (sent != 0) { //printf("tnSrv: sent sock=%d, %d bytes, %d left\n", tnSrv.sock, sent, tnSrv.txBufLen); } return sent != 0; }
/** * Sends an ARP request for an ARP table entry over a network interface. * @param entry ARP table entry * @return OK if packet was sent, otherwise SYSERR */ syscall arpSendRqst(struct arpEntry *entry) { struct netif *netptr = NULL; struct packet *pkt = NULL; struct arpPkt *arp = NULL; int result; /* Error check pointers */ if (NULL == entry) { return SYSERR; } ARP_TRACE("Sending ARP request"); /* Setup pointer to network interface */ netptr = entry->nif; /* Obtain a buffer for the packet */ pkt = netGetbuf(); if (SYSERR == (int)pkt) { ARP_TRACE("Failed to acquire packet buffer"); return SYSERR; } /* Place ARP header at end of packet buffer */ pkt->nif = netptr; pkt->len = ARP_CONST_HDR_LEN + netptr->hwaddr.len * 2 + netptr->ip.len * 2; pkt->curr -= pkt->len; arp = (struct arpPkt *)pkt->curr; /* Fill in ARP header */ arp->hwtype = hs2net(netptr->hwaddr.type); arp->prtype = hs2net(netptr->ip.type); arp->hwalen = netptr->hwaddr.len; arp->pralen = netptr->ip.len; arp->op = hs2net(ARP_OP_RQST); ARP_TRACE("Filled in types, lens, and op"); memcpy(&arp->addrs[ARP_ADDR_SHA(arp)], netptr->hwaddr.addr, arp->hwalen); memcpy(&arp->addrs[ARP_ADDR_SPA(arp)], netptr->ip.addr, arp->pralen); memcpy(&arp->addrs[ARP_ADDR_DPA(arp)], entry->praddr.addr, arp->pralen); ARP_TRACE("Filled in addrs"); /* Send packet */ result = netSend(pkt, &netptr->hwbrc, NULL, ETHER_TYPE_ARP); ARP_TRACE("Sent packet"); /* Free buffer for the packet */ if (SYSERR == netFreebuf(pkt)) { ARP_TRACE("Failed to free packet buffer"); return SYSERR; } /* Return result of netSend */ return result; }
ssize_t netSendPeerEvent(NetPath *netPath, const Octet *buf, UInteger16 length, TimeInternal* time) { return netSend(buf, length, time, &netPath->peerMulticastAddr, netPath->eventPcb); }
ssize_t netSendPeerGeneral(NetPath *netPath, const Octet *buf, UInteger16 length) { return netSend(buf, length, NULL, &netPath->peerMulticastAddr, netPath->generalPcb); }
/** * Tests the network interfaces. * @return OK when testing is complete */ thread test_netif(bool verbose) { bool passed = TRUE; int i = 0; struct netaddr ip; struct netaddr mask; struct netaddr gate; struct netaddr hw; struct netaddr brc; struct pcap_file_header pcap; struct pcap_pkthdr phdr; struct packet *pkt; struct netif *netptr; uchar *data; enable(); ip.type = NETADDR_IPv4; ip.len = IPv4_ADDR_LEN; ip.addr[0] = 192; ip.addr[1] = 168; ip.addr[2] = 1; ip.addr[3] = 6; mask.type = NETADDR_IPv4; mask.len = IPv4_ADDR_LEN; mask.addr[0] = 255; mask.addr[1] = 255; mask.addr[2] = 255; mask.addr[3] = 0; gate.type = NETADDR_IPv4; gate.len = IPv4_ADDR_LEN; gate.addr[0] = 192; gate.addr[1] = 168; gate.addr[2] = 1; gate.addr[3] = 1; brc.type = NETADDR_IPv4; brc.len = IPv4_ADDR_LEN; brc.addr[0] = 255; brc.addr[1] = 255; brc.addr[2] = 255; brc.addr[3] = 255; testPrint(verbose, "Open loopback ethernet device"); failif((SYSERR == open(ELOOP)), ""); testPrint(verbose, "Start network interface"); if (SYSERR == netUp(ELOOP, &ip, &mask, &gate)) { failif(TRUE, "Returned SYSERR"); } else { for (i = 0; i < NNETIF; i++) { if ((NET_ALLOC == netiftab[i].state) && (ELOOP == netiftab[i].dev)) { break; } } netptr = &netiftab[i]; if ((i >= NNETIF) || (netptr->state != NET_ALLOC) || (netptr->mtu != ELOOP_MTU) || (netptr->linkhdrlen != ELOOP_LINKHDRSIZE) || (FALSE == netaddrequal(&netptr->ip, &ip)) || (FALSE == netaddrequal(&netptr->mask, &mask)) || (FALSE == netaddrequal(&netptr->gateway, &gate))) { failif(TRUE, "Incorrect structure setup"); } else { for (i = 0; i < NET_NTHR; i++) { if (isbadtid(netptr->recvthr[i])) { failif(TRUE, "Bad recvthr"); break; } } if (NET_NTHR == i) { failif(FALSE, ""); } } } testPrint(verbose, "Stop network interface"); failif((SYSERR == netDown(ELOOP)), ""); testPrint(verbose, "Start network interface (no gateway)"); failif((SYSERR == netUp(ELOOP, &ip, &mask, NULL)), ""); for (i = 0; i < NNETIF; i++) { if ((NET_ALLOC == netiftab[i].state) && (ELOOP == netiftab[i].dev)) { break; } } /* Kill receiver threads */ netptr = &netiftab[i]; for (i = 0; i < NET_NTHR; i++) { kill(netptr->recvthr[i]); netptr->recvthr[i] = BADTID; } testPrint(verbose, "Get packet buffer"); pkt = netGetbuf(); failif((SYSERR == (int)pkt), ""); data = (uchar *)&_binary_data_testnetif_pcap_start; memcpy(&pcap, data, sizeof(pcap)); data += sizeof(pcap); memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } pkt->nif = netptr; pkt->len = phdr.caplen - netptr->linkhdrlen; pkt->curr = pkt->curr - pkt->len; memcpy(pkt->curr, data + netptr->linkhdrlen, pkt->len); hw.type = NETADDR_ETHERNET; hw.len = ETH_ADDR_LEN; hw.addr[0] = 0xAA; hw.addr[1] = 0xBB; hw.addr[2] = 0xCC; hw.addr[3] = 0xDD; hw.addr[4] = 0xEE; hw.addr[5] = 0xAA; testPrint(verbose, "Send packet (known hardware address)"); if (SYSERR == netSend(pkt, &hw, NULL, ETHER_TYPE_ARP)) { failif(TRUE, "Returned SYSERR"); } else { if ((SYSERR == read(netptr->dev, pkt, phdr.caplen)) || (memcmp(pkt, data, phdr.caplen) != 0)) { failif(TRUE, "Packet did not match"); } else { failif(FALSE, ""); } } testPrint(verbose, "Free packet buffer"); failif((SYSERR == netFreebuf(pkt)), ""); testPrint(verbose, "Stop network interface"); failif(((SYSERR == netDown(ELOOP)) || (SYSERR == close(ELOOP))), ""); if (passed) { testPass(TRUE, ""); } else { testFail(TRUE, ""); } return OK; }
/** * Fragments packet into maximum transmission unit sized chunks. * @param pkt the packet to fragment * @return OK */ syscall ipv4SendFrag(struct packet *pkt, struct netaddr *nxthop) { uint ihl; uchar *data; uint dRem = 0; // The amount of data remaining to be fragmented ushort froff; ushort lastFlag; ushort dLen; // Incoming packet structures struct ipv4Pkt *ip; // Outgoing packet structures struct ipv4Pkt *outip; struct packet *outpkt; IPv4_TRACE("Declaration"); if (NULL == pkt) { return SYSERR; } // Setup incoming packet structures ip = (struct ipv4Pkt *)pkt->curr; if (net2hs(ip->len) <= pkt->nif->mtu) { IPv4_TRACE("NetSend"); if (netaddrequal(&pkt->nif->ipbrc, nxthop)) { IPv4_TRACE("Subnet Broadcast"); return netSend(pkt, &NETADDR_GLOBAL_ETH_BRC, nxthop, ETHER_TYPE_IPv4); } return netSend(pkt, NULL, nxthop, ETHER_TYPE_IPv4); } // Verify header does not have DF if (net2hs(ip->flags_froff) & IPv4_FLAG_DF) { IPv4_TRACE("net2hs of froff"); /* Send ICMP message */ icmpDestUnreach(pkt, ICMP_FOFF_DFSET); return SYSERR; } ihl = (ip->ver_ihl & IPv4_IHL) * 4; data = ((uchar *)ip) + ihl; dRem = net2hs(ip->len) - ihl; froff = net2hs(ip->flags_froff) & IPv4_FROFF; lastFlag = net2hs(ip->flags_froff) & IPv4_FLAGS; // Length of data in this packet will be MTU - header length, // rounded down to nearest multiple of 8 bytes. dLen = (pkt->nif->mtu - ihl) & ~0x7; pkt->len = ihl + dLen; ip->len = hs2net(pkt->len); // Set more fragments flag ip->flags_froff = IPv4_FLAG_MF & froff; ip->flags_froff = hs2net(ip->flags_froff); ip->chksum = 0; ip->chksum = netChksum((uchar *)ip, ihl); netSend(pkt, NULL, nxthop, ETHER_TYPE_IPv4); dRem -= dLen; data += dLen; froff += (dLen / 8); // Get memory from stack for outgoing fragment outpkt = netGetbuf(); if (SYSERR == (int)outpkt) { IPv4_TRACE("allocating outpkt"); return SYSERR; } // Set up outgoing packet pointers and variables outpkt->curr -= pkt->nif->mtu; outip = (struct ipv4Pkt *)outpkt->curr; outpkt->nif = pkt->nif; memcpy(outip, ip, IPv4_HDR_LEN); // While packet must be fragmented while (dRem > 0) { if (((dRem + 7) & ~0x7) > pkt->nif->mtu + IPv4_HDR_LEN) { dLen = (pkt->nif->mtu - IPv4_HDR_LEN) & ~0x7; } else { dLen = dRem; } // Copy data segment memcpy(outip->opts, data, dLen); // Set more fragments flag if (dLen == dRem) { outip->flags_froff = lastFlag & froff; } else { outip->flags_froff = IPv4_FLAG_MF & froff; } outip->flags_froff = hs2net(outip->flags_froff); // Update fields outip->len = hs2net(IPv4_HDR_LEN + dLen); outip->chksum = 0; outip->chksum = netChksum((uchar *)outip, IPv4_HDR_LEN); // Update outgoing packet length outpkt->len = net2hs(outip->len); // Send fragment netSend(outpkt, NULL, nxthop, ETHER_TYPE_IPv4); dRem -= dLen; data += dLen; froff += (dLen / 8); } IPv4_TRACE("freeing outpkt"); netFreebuf(outpkt); return OK; }
static void handleclient(u64 conn_s_p) { // todo: clean up int conn_s = (int)conn_s_p; int list_s_data = -1; int conn_s_data = -1; int datareq = 0; char cwd[256]; char rnfr[256]; char filename[256]; char user[32]; u32 rest = 0; int authd = 0; int active = 1; Lv2FsFile tempfd; char buf[BUFFER_SIZE]; char buffer[1024]; char client_cmd[8][128]; ssize_t bytes; #if LOGIN_CHECK == 1 // load password file char passwordcheck[33]; // check if password file exists - if not, use default password if(exists(PASSWORD_FPATH) == 0) { Lv2FsFile fd; u64 read; lv2FsOpen(PASSWORD_FPATH, LV2_O_RDONLY, &fd, 0, NULL, 0); lv2FsRead(fd, passwordcheck, 32, &read); lv2FsClose(fd); if(strlen(passwordcheck) != 32) { strcpy(passwordcheck, LOGIN_PASSWORD); } } else { strcpy(passwordcheck, LOGIN_PASSWORD); } #endif // start directory strcpy(cwd, "/"); // welcome message swritel(conn_s, "220-OpenPS3FTP by @jjolano\r\n"); sprintf(buffer, "220 Version %s\r\n", VERSION); swritel(conn_s, buffer); while(exitapp == 0 && active && (bytes = sreadl(conn_s, buffer, 1024)) > 0) { // get rid of the newline at the end of the string buffer[strcspn(buffer, "\n")] = '\0'; buffer[strcspn(buffer, "\r")] = '\0'; // parse received string into array int parameter_count = 0; char *result = strtok(buffer, " "); strcpy(client_cmd[0], result); while(parameter_count < 7 && (result = strtok(NULL, " ")) != NULL) { parameter_count++; strcpy(client_cmd[parameter_count], result); } // identify the command int cmd_id; for(cmd_id = 0; cmd_id < client_cmds_count; cmd_id++) { if(strcasecmp(client_cmd[0], client_cmds[cmd_id]) == 0) { break; } } // execute command if(authd == 0) { // not logged in switch(cmd_id) { case 0: // USER #if LOGIN_CHECK == 1 if(parameter_count >= 1) { int i; for(i = 2; i <= parameter_count; i++) { strcat(client_cmd[1], " "); strcat(client_cmd[1], client_cmd[i]); } strcpy(user, client_cmd[1]); sprintf(buffer, "331 User %s OK. Password required\r\n", user); swritel(conn_s, buffer); } else { swritel(conn_s, "501 Please provide a username\r\n"); } #else sprintf(buffer, "331 User %s OK. Password (not really) required\r\n", user); swritel(conn_s, buffer); #endif break; case 1: // PASS #if LOGIN_CHECK == 1 if(parameter_count >= 1) { int i; for(i = 2; i <= parameter_count; i++) { strcat(client_cmd[1], " "); strcat(client_cmd[1], client_cmd[i]); } // hash the password given char output[33]; md5(output, client_cmd[1]); if(strcmp(user, LOGIN_USERNAME) == 0 && strcmp(output, passwordcheck) == 0) { swritel(conn_s, "230 Successful authentication\r\n"); authd = 1; } else { swritel(conn_s, "430 Invalid username or password - \r\n"); } } else { swritel(conn_s, "501 Invalid username or password\r\n"); } #else swritel(conn_s, "230 Successful authentication\r\n"); authd = 1; #endif break; case 2: // QUIT swritel(conn_s, "221 See you later\r\n"); active = 0; break; default: swritel(conn_s, "530 You are not logged in\r\n"); } } else { // logged in switch(cmd_id) { case 0: // USER case 1: // PASS swritel(conn_s, "530 You are already logged in\r\n"); break; case 2: // QUIT swritel(conn_s, "221 See you later\r\n"); active = 0; break; case 3: // PASV rest = 0; netSocketInfo snf; int ret = netGetSockInfo(conn_s, &snf, 1); if(ret >= 0 && snf.local_adr.s_addr != 0) { // assign a random port for passive mode srand(conn_s); int rand1 = (rand() % 251) + 4; int rand2 = rand() % 256; sprintf(buffer, "227 Entering Passive Mode (%u,%u,%u,%u,%i,%i)\r\n", (snf.local_adr.s_addr & 0xFF000000) >> 24, (snf.local_adr.s_addr & 0xFF0000) >> 16, (snf.local_adr.s_addr & 0xFF00) >> 8, (snf.local_adr.s_addr & 0xFF), rand1, rand2); short int pasvport = (rand1 * 256) + rand2; struct sockaddr_in servaddr; memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(pasvport); list_s_data = netSocket(AF_INET, SOCK_STREAM, 0); netBind(list_s_data, (struct sockaddr *) &servaddr, sizeof(servaddr)); netListen(list_s_data, 1); swritel(conn_s, buffer); if((conn_s_data = netAccept(list_s_data, NULL, NULL)) == -1) { swritel(conn_s, "550 PASV command failed\r\n"); } else { datareq = 1; } break; } swritel(conn_s, "550 PASV command failed\r\n"); break; case 4: // PORT if(parameter_count == 1) { rest = 0; char connectinfo[32]; strcpy(connectinfo, client_cmd[1]); char data[7][4]; int i = 0; char *result = strtok(connectinfo, ","); strcpy(data[0], result); while(i < 6 && (result = strtok(NULL, ",")) != NULL) { i++; strcpy(data[i], result); } char conn_ipaddr[16]; sprintf(conn_ipaddr, "%s.%s.%s.%s", data[0], data[1], data[2], data[3]); struct sockaddr_in servaddr; memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_port = htons((atoi(data[4]) * 256) + atoi(data[5])); inet_pton(AF_INET, conn_ipaddr, &servaddr.sin_addr); conn_s_data = netSocket(AF_INET, SOCK_STREAM, 0); if(connect(conn_s_data, (struct sockaddr *)&servaddr, sizeof(servaddr)) == 0) { swritel(conn_s, "200 PORT command successful\r\n"); datareq = 1; } else { swritel(conn_s, "550 PORT command failed\r\n"); } } else { swritel(conn_s, "501 Syntax error\r\n"); } break; case 5: // SITE if(strcasecmp(client_cmd[1], "CHMOD") == 0) { int i; for(i = 4; i <= parameter_count; i++) { strcat(client_cmd[3], " "); strcat(client_cmd[3], client_cmd[i]); } absPath(filename, client_cmd[3], cwd); char perms[4]; sprintf(perms, "0%s", client_cmd[2]); if(lv2FsChmod(filename, S_IFMT | strtol(perms, NULL, 8)) == 0) { swritel(conn_s, "250 File permissions successfully set\r\n"); } else { swritel(conn_s, "550 Failed to set file permissions\r\n"); } } else { swritel(conn_s, "500 Unrecognized SITE command\r\n"); } break; case 6: // FEAT swritel(conn_s, "211- Extensions supported:\r\n"); int i; for(i = 0; i < feat_cmds_count; i++) { sprintf(buffer, " %s\r\n", feat_cmds[i]); swritel(conn_s, buffer); } swritel(conn_s, "211 End.\r\n"); break; case 7: // TYPE swritel(conn_s, "200 TYPE command successful\r\n"); break; case 8: // REST if(parameter_count == 1) { rest = atoi(client_cmd[1]); swritel(conn_s, "350 REST command successful\r\n"); } else { swritel(conn_s, "501 Syntax error\r\n"); } break; case 9: // RETR if(parameter_count >= 1) { if(conn_s_data == -1) { swritel(conn_s, "425 No data connection\r\n"); break; } swritel(conn_s, "150 Opening data connection\r\n"); int i; for(i = 2; i <= parameter_count; i++) { strcat(client_cmd[1], " "); strcat(client_cmd[1], client_cmd[i]); } absPath(filename, client_cmd[1], cwd); u64 pos; u64 read = -1; Lv2FsFile fd; lv2FsOpen(filename, LV2_O_RDONLY, &fd, 0, NULL, 0); lv2FsLSeek64(fd, (s64)rest, SEEK_SET, &pos); if(fd >= 0) { while(lv2FsRead(fd, buf, BUFFER_SIZE - 1, &read) == 0 && read > 0) { netSend(conn_s_data, buf, read, 0); } if(read == 0) { swritel(conn_s, "226 Transfer complete\r\n"); } else { swritel(conn_s, "426 Transfer failed\r\n"); } } else { swritel(conn_s, "452 File access error\r\n"); } lv2FsClose(fd); } else { swritel(conn_s, "501 Syntax error\r\n"); } break; case 10: // PWD sprintf(buffer, "257 \"%s\" is the current directory\r\n", cwd); swritel(conn_s, buffer); break; case 11: // CWD if(parameter_count >= 1) { int i; for(i = 2; i <= parameter_count; i++) { strcat(client_cmd[1], " "); strcat(client_cmd[1], client_cmd[i]); } strcpy(filename, client_cmd[1]); if(strcmp(filename, "../") == 0) { for(int i = strlen(cwd) - 2; i > 0; i--) { if(cwd[i] != '/') { cwd[i] = '\0'; } else { break; } } sprintf(buffer, "250 Directory change successful: %s\r\n", cwd); swritel(conn_s, buffer); break; } if(filename[0] == '/') { strcpy(cwd, (strlen(filename) == 1) ? "/" : filename); } else { strcat(cwd, filename); } if(cwd[strlen(cwd) - 1] != '/') { strcat(cwd, "/"); } if(isDir(cwd)) { sprintf(buffer, "250 Directory change successful: %s\r\n", cwd); } else { sprintf(buffer, "550 Could not change directory: %s\r\n", cwd); } swritel(conn_s, buffer); } else { sprintf(buffer, "257 \"%s\" is the current directory\r\n", cwd); swritel(conn_s, buffer); } break; case 12: // CDUP for(int i = strlen(cwd) - 2; i > 0; i--) { if(cwd[i] != '/') { cwd[i] = '\0'; } else { break; } } sprintf(buffer, "250 Directory change successful: %s\r\n", cwd); swritel(conn_s, buffer); break; case 13: // NLST if(conn_s_data == -1) { swritel(conn_s, "425 No data connection\r\n"); break; } swritel(conn_s, "150 Opening data connection\r\n"); if(parameter_count >= 1) { int i; for(i = 2; i <= parameter_count; i++) { strcat(client_cmd[1], " "); strcat(client_cmd[1], client_cmd[i]); } absPath(filename, client_cmd[1], cwd); } else { strcpy(filename, cwd); } if(lv2FsOpenDir(filename, &tempfd) == 0) { u64 read; Lv2FsDirent ent; while(lv2FsReadDir(tempfd, &ent, &read) == 0 && read != 0) { sprintf(buffer, "%s\r\n", ent.d_name); swritel(conn_s_data, buffer); } swritel(conn_s, "226 Transfer complete\r\n"); } else { swritel(conn_s, "451 Cannot access directory\r\n"); } lv2FsCloseDir(tempfd); break; case 14: // LIST if(conn_s_data == -1) { swritel(conn_s, "425 No data connection\r\n"); break; } swritel(conn_s, "150 Opening data connection\r\n"); if(parameter_count >= 1) { int i; for(i = 2; i <= parameter_count; i++) { strcat(client_cmd[1], " "); strcat(client_cmd[1], client_cmd[i]); } absPath(filename, client_cmd[1], cwd); } else { strcpy(filename, cwd); } if(lv2FsOpenDir(filename, &tempfd) == 0) { u64 read; Lv2FsDirent ent; while(lv2FsReadDir(tempfd, &ent, &read) == 0 && read != 0) { sprintf(filename, "%s%s", cwd, ent.d_name); Lv2FsStat entry; lv2FsStat(filename, &entry); struct tm *tm; char timebuf[32]; tm = localtime(&entry.st_mtime); strftime(timebuf, 31, "%b %d %Y", tm); sprintf(buffer, "%s%s%s%s%s%s%s%s%s%s 1 root root %lu %s %s\r\n", ((entry.st_mode & S_IFDIR) != 0)?"d":"-", ((entry.st_mode & S_IRUSR) != 0)?"r":"-", ((entry.st_mode & S_IWUSR) != 0)?"w":"-", ((entry.st_mode & S_IXUSR) != 0)?"x":"-", ((entry.st_mode & S_IRGRP) != 0)?"r":"-", ((entry.st_mode & S_IWGRP) != 0)?"w":"-", ((entry.st_mode & S_IXGRP) != 0)?"x":"-", ((entry.st_mode & S_IROTH) != 0)?"r":"-", ((entry.st_mode & S_IWOTH) != 0)?"w":"-", ((entry.st_mode & S_IXOTH) != 0)?"x":"-", (long unsigned int)entry.st_size, timebuf, ent.d_name); swritel(conn_s_data, buffer); } swritel(conn_s, "226 Transfer complete\r\n"); } else { swritel(conn_s, "451 Cannot access directory\r\n"); } lv2FsCloseDir(tempfd); break; case 15: // STOR if(parameter_count >= 1) { if(conn_s_data == -1) { swritel(conn_s, "425 No data connection\r\n"); break; } swritel(conn_s, "150 Opening data connection\r\n"); int i; for(i = 2; i <= parameter_count; i++) { strcat(client_cmd[1], " "); strcat(client_cmd[1], client_cmd[i]); } absPath(filename, client_cmd[1], cwd); u64 pos; u64 read = -1; u64 write = -1; Lv2FsFile fd; lv2FsOpen(filename, LV2_O_WRONLY | LV2_O_CREAT, &fd, 0, NULL, 0); lv2FsChmod(filename, S_IFMT | 0666); lv2FsLSeek64(fd, (s32)rest, SEEK_SET, &pos); if(fd >= 0) { while((read = (u64)netRecv(conn_s_data, buf, BUFFER_SIZE - 1, MSG_WAITALL)) > 0) { lv2FsWrite(fd, buf, read, &write); if(write != read) { break; } } if(read == 0) { swritel(conn_s, "226 Transfer complete\r\n"); } else { swritel(conn_s, "426 Transfer failed\r\n"); } } else { swritel(conn_s, "452 File access error\r\n"); } lv2FsClose(fd); } else { swritel(conn_s, "501 Syntax error\r\n"); } break; case 16: // NOOP swritel(conn_s, "200 Zzzz...\r\n"); break; case 17: // DELE if(parameter_count >= 1) { int i; for(i = 2; i <= parameter_count; i++) { strcat(client_cmd[1], " "); strcat(client_cmd[1], client_cmd[i]); } absPath(filename, client_cmd[1], cwd); if(lv2FsUnlink(filename) == 0) { swritel(conn_s, "250 File successfully deleted\r\n"); } else { swritel(conn_s, "550 Failed to delete file\r\n"); } } else { swritel(conn_s, "501 Syntax error\r\n"); } break; case 18: // MKD if(parameter_count >= 1) { int i; for(i = 2; i <= parameter_count; i++) { strcat(client_cmd[1], " "); strcat(client_cmd[1], client_cmd[i]); } absPath(filename, client_cmd[1], cwd); if(lv2FsMkdir(filename, 0775) == 0) { swritel(conn_s, "250 Directory successfully created\r\n"); } else { swritel(conn_s, "550 Failed to create directory\r\n"); } } else { swritel(conn_s, "501 Syntax error\r\n"); } break; case 19: // RMD if(parameter_count >= 1) { int i; for(i = 2; i <= parameter_count; i++) { strcat(client_cmd[1], " "); strcat(client_cmd[1], client_cmd[i]); } absPath(filename, client_cmd[1], cwd); if(lv2FsRmdir(filename) == 0) { swritel(conn_s, "250 Directory successfully deleted\r\n"); } else { swritel(conn_s, "550 Failed to remove directory\r\n"); } } else { swritel(conn_s, "501 Syntax error\r\n"); } break; case 20: // RNFR if(parameter_count >= 1) { int i; for(i = 2; i <= parameter_count; i++) { strcat(client_cmd[1], " "); strcat(client_cmd[1], client_cmd[i]); } absPath(rnfr, client_cmd[1], cwd); if(exists(rnfr) == 0) { swritel(conn_s, "350 RNFR successful - ready for destination\r\n"); } else { swritel(conn_s, "550 RNFR failed - file does not exist\r\n"); } } else { swritel(conn_s, "501 Syntax error\r\n"); } break; case 21: // RNTO if(parameter_count >= 1) { int i; for(i = 2; i <= parameter_count; i++) { strcat(client_cmd[1], " "); strcat(client_cmd[1], client_cmd[i]); } absPath(filename, client_cmd[1], cwd); if(lv2FsRename(rnfr, filename) == 0) { swritel(conn_s, "250 File successfully renamed\r\n"); } else { swritel(conn_s, "550 Failed to rename file\r\n"); } } else { swritel(conn_s, "501 Syntax error\r\n"); } break; case 22: // SIZE if(parameter_count >= 1) { int i; for(i = 2; i <= parameter_count; i++) { strcat(client_cmd[1], " "); strcat(client_cmd[1], client_cmd[i]); } absPath(filename, client_cmd[1], cwd); Lv2FsStat entry; if(lv2FsStat(filename, &entry) == 0) { sprintf(buffer, "213 %lu\r\n", (long unsigned int)entry.st_size); } else { sprintf(buffer, "550 Requested file doesn't exist\r\n"); } swritel(conn_s, buffer); } else { swritel(conn_s, "501 Syntax error\r\n"); } break; case 23: // SYST swritel(conn_s, "215 UNIX Type: L8\r\n"); break; case 24: // HELP swritel(conn_s, "214 No help for you.\r\n"); break; case 25: // PASSWD if(parameter_count >= 1) { int i; for(i = 2; i <= parameter_count; i++) { strcat(client_cmd[1], " "); strcat(client_cmd[1], client_cmd[i]); } // hash the password given char output[33]; md5(output, client_cmd[1]); Lv2FsFile fd; u64 written; lv2FsOpen(PASSWORD_FPATH, LV2_O_WRONLY | LV2_O_CREAT, &fd, 0, NULL, 0); lv2FsWrite(fd, output, 32, &written); lv2FsClose(fd); swritel(conn_s, "200 Password successfully changed\r\n"); } else { swritel(conn_s, "501 Invalid password\r\n"); } break; case 26: // MLSD if(conn_s_data == -1) { swritel(conn_s, "425 No data connection\r\n"); break; } swritel(conn_s, "150 Opening data connection\r\n"); if(parameter_count >= 1) { int i; for(i = 2; i <= parameter_count; i++) { strcat(client_cmd[1], " "); strcat(client_cmd[1], client_cmd[i]); } absPath(filename, client_cmd[1], cwd); } else { strcpy(filename, cwd); } if(lv2FsOpenDir(filename, &tempfd) == 0) { u64 read; Lv2FsDirent ent; while(lv2FsReadDir(tempfd, &ent, &read) == 0 && read != 0) { sprintf(filename, "%s%s", cwd, ent.d_name); Lv2FsStat entry; lv2FsStat(filename, &entry); struct tm *tm; char timebuf[32]; tm = localtime(&entry.st_mtime); strftime(timebuf, 31, "%Y%m%d%H%M%S", tm); int permint = 0; permint += (((entry.st_mode & S_IRUSR) != 0)?400:0) + (((entry.st_mode & S_IWUSR) != 0)?200:0) + (((entry.st_mode & S_IXUSR) != 0)?100:0); permint += (((entry.st_mode & S_IRGRP) != 0)?40:0) + (((entry.st_mode & S_IWGRP) != 0)?20:0) + (((entry.st_mode & S_IXGRP) != 0)?10:0); permint += (((entry.st_mode & S_IROTH) != 0)?4:0) + (((entry.st_mode & S_IWOTH) != 0)?2:0) + (((entry.st_mode & S_IXOTH) != 0)?1:0); sprintf(buffer, "type=%s;size=%lu;modify=%s;UNIX.mode=0%i;UNIX.uid=root;UNIX.gid=root; %s\r\n", ((entry.st_mode & S_IFDIR) != 0)?"dir":"file", (long unsigned int)entry.st_size, timebuf, permint, ent.d_name); swritel(conn_s_data, buffer); } swritel(conn_s, "226 Transfer complete\r\n"); } else { swritel(conn_s, "501 Directory access error\r\n"); } lv2FsCloseDir(tempfd); break; case 27: // MLST swritel(conn_s, "250- Listing directory"); if(parameter_count >= 1) { int i; for(i = 2; i <= parameter_count; i++) { strcat(client_cmd[1], " "); strcat(client_cmd[1], client_cmd[i]); } absPath(filename, client_cmd[1], cwd); } else { strcpy(filename, cwd); } if(lv2FsOpenDir(filename, &tempfd) == 0) { u64 read; Lv2FsDirent ent; while(lv2FsReadDir(tempfd, &ent, &read) == 0 && read != 0) { sprintf(filename, "%s%s", cwd, ent.d_name); Lv2FsStat entry; lv2FsStat(filename, &entry); struct tm *tm; char timebuf[32]; tm = localtime(&entry.st_mtime); strftime(timebuf, 31, "%Y%m%d%H%M%S", tm); int permint = 0; permint += (((entry.st_mode & S_IRUSR) != 0)?400:0) + (((entry.st_mode & S_IWUSR) != 0)?200:0) + (((entry.st_mode & S_IXUSR) != 0)?100:0); permint += (((entry.st_mode & S_IRGRP) != 0)?40:0) + (((entry.st_mode & S_IWGRP) != 0)?20:0) + (((entry.st_mode & S_IXGRP) != 0)?10:0); permint += (((entry.st_mode & S_IROTH) != 0)?4:0) + (((entry.st_mode & S_IWOTH) != 0)?2:0) + (((entry.st_mode & S_IXOTH) != 0)?1:0); sprintf(buffer, " type=%s;size=%lu;modify=%s;UNIX.mode=0%i;UNIX.uid=root;UNIX.gid=root; %s\r\n", ((entry.st_mode & S_IFDIR) != 0)?"dir":"file", (long unsigned int)entry.st_size, timebuf, permint, ent.d_name); swritel(conn_s, buffer); } } swritel(conn_s, "250 End\r\n"); lv2FsCloseDir(tempfd); break; case 28: // EXITAPP swritel(conn_s, "221 Exiting OpenPS3FTP, bye\r\n"); exitapp = 1; break; case 29: // TEST swritel(conn_s, "211-Listing parameters\r\n"); sprintf(buffer, "211-Count: %i\r\n", parameter_count); swritel(conn_s, buffer); int tx; for(tx = 0; tx <= parameter_count; tx++) { sprintf(buffer, " %i:%s\r\n", tx, client_cmd[tx]); swritel(conn_s, buffer); } swritel(conn_s, "211 End\r\n"); break; default: swritel(conn_s, "500 Unrecognized command\r\n"); } if(datareq == 1) { datareq = 0; } else { // close any active data connections if(conn_s_data > -1) { netShutdown(conn_s_data, 2); netClose(conn_s_data); conn_s_data = -1; } if(list_s_data > -1) { netShutdown(list_s_data, 2); netClose(list_s_data); list_s_data = -1; } } } }
ssize_t netSendPeerEvent(NetPath *netPath, const octet_t *buf, int16_t length, TimeInternal* time) { return netSend(buf, length, time, &netPath->peerMulticastAddr, netPath->eventPcb); }
ssize_t netSendPeerGeneral(NetPath *netPath, const octet_t *buf, int16_t length) { return netSend(buf, length, NULL, &netPath->peerMulticastAddr, netPath->generalPcb); }