Exemple #1
0
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;
}
Exemple #2
0
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;
}