char * tftp_get(IPAddr server, char * file, void(*receiver)(Octet *, Uint32)) { UDP *sendBuf = (UDP *)enet_alloc(); UDPPort local = udp_allocPort(NULL); sendBuf->ip.dest = hton(server); sendBuf->udp.dest = htons(tftpPort); sendBuf->udp.srce = htons(local); TFTPHeader * sendHeader = (TFTPHeader *)&(sendBuf->data[0]); sendHeader->op = htons(tftpOpRRQ); Uint32 pos = tftpPosName; appendStr(sendBuf, &pos, file); appendStr(sendBuf, &pos, "octet"); Uint32 blockNum; for (blockNum = 1; ; blockNum++) { Uint32 recvLen; IP * recvBuf; TFTPHeader * recvHeader; Octet * recvData; Uint32 dataLen; int tries; for (tries = 0; ; tries++) { if (tries >= retryLimit) { udp_freePort(local); enet_free((Enet *)sendBuf); return "Timeout"; } udp_send(sendBuf, pos); recvLen = udp_recv(&recvBuf, local, timeout); if (recvBuf) { recvHeader = (TFTPHeader *)udp_payload(recvBuf); recvData = udp_payload(recvBuf) + tftpPosData; dataLen = recvLen - tftpPosData; if (ntohs(recvHeader->op) == tftpOpData) { if (ntohs(recvHeader->block) == blockNum) break; } else if (ntohs(recvHeader->op) == tftpOpError) { recvData[dataLen-1] = 0; // in case server omitted it udp_freePort(local); enet_free((Enet *)sendBuf); int slen = strlen((char *)recvData); char *s = malloc(slen+1); strncpy(s, (char *)recvData, slen+1); udp_recvDone(recvBuf); return s; } else { udp_freePort(local); enet_free((Enet *)sendBuf); udp_recvDone(recvBuf); return "Unknown opcode from server"; } // ignore other stuff - excess retransmissions udp_recvDone(recvBuf); } } // The only way to get here is by receiving the expected data block receiver(recvData, dataLen); UDPHeader *recvUDPHeader = (UDPHeader *)ip_payload(recvBuf); sendBuf->udp.dest = recvUDPHeader->srce; sendHeader->op = htons(tftpOpAck); sendHeader->block = recvHeader->block; pos = tftpPosData; udp_recvDone(recvBuf); if (dataLen < 512) break; } udp_send(sendBuf, pos); // final ACK, sent without retransmissions udp_freePort(local); enet_free((Enet *)sendBuf); return NULL; }
static int cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data) { //log_debug("entering callback"); //char buf[1025]; //nfq_snprintf_xml(buf, 1024, nfa, NFQ_XML_ALL); //log_debug("%s", buf); struct nfqnl_msg_packet_hdr *ph; ph = nfq_get_msg_packet_hdr(nfa); if (!ph) { log_error("nfq_get_msg_packet_hdr failed"); return -1; } u_int32_t id = ntohl(ph->packet_id); //log_debug("packet id: %d", id); char inout = nfq_get_outdev(nfa) ? 1 : 0; // 0 - in, 1 - out // get data (IP header + TCP header + payload) unsigned char *pkt_data; int plen = nfq_get_payload(nfa, &pkt_data); g_modified = 0; //if (plen >= 0) // log_debug("payload_len=%d", plen); //hex_dump(pkt_data, plen); struct mypacket packet; packet.data = pkt_data; packet.len = plen; packet.iphdr = ip_hdr(pkt_data); // parse ip //char sip[16], dip[16]; //ip2str(packet.iphdr->saddr, sip); //ip2str(packet.iphdr->daddr, dip); //log_debug("This packet goes from %s to %s.", sip, dip); //log_debugv("This packet goes from %s to %s.", sip, dip); if (is_ip_in_whitelist(packet.iphdr->saddr) || is_ip_in_whitelist(packet.iphdr->daddr)) { nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL); return 0; } int ret = 0; switch (packet.iphdr->protocol) { case 6: // TCP packet.tcphdr = tcp_hdr(pkt_data); packet.payload = tcp_payload(pkt_data); packet.payload_len = packet.len - packet.iphdr->ihl*4 - packet.tcphdr->th_off*4; //show_packet(&packet); ret = process_tcp_packet(&packet, inout); break; case 17: // UDP packet.udphdr = udp_hdr(pkt_data); packet.payload = udp_payload(pkt_data); packet.payload_len = packet.len - packet.iphdr->ihl*4 - 8; if (packet.payload_len != ntohs(packet.udphdr->uh_ulen) - 8) log_warn("UDP payload length unmatch! %d <> %d", packet.payload_len, ntohs(packet.udphdr->uh_ulen) - 8); //show_packet(&packet); ret = process_udp_packet(&packet, inout); break; default: log_error("Invalid protocol: %d", packet.iphdr->protocol); } int verdict_ret; if (ret == 0) { if (g_modified) { log_warn("Packet Modified."); //if (packet.iphdr->protocol == 6) { // packet.tcphdr->th_sum = tcp_checksum(packet.data, ntohs(packet.iphdr->tot_len)); //} //packet.iphdr->check = ip_checksum(packet.data, packet.len); verdict_ret = nfq_set_verdict(qh, id, NF_ACCEPT, packet.len, packet.data); //log_info("VERDICT MODIFIED ACCEPT"); } else { verdict_ret = nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL); //log_info("VERDICT ACCEPT"); } } else if (ret == 1) { usleep(DELAY_AFTER_PACKET_INJECTION); verdict_ret = nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL); //log_info("VERDICT DELAYED ACCEPT"); } else { verdict_ret = nfq_set_verdict(qh, id, NF_DROP, 0, NULL); //log_info("VERDICT DROP"); } // return <0 to stop processing return verdict_ret; }