Esempio n. 1
0
static int
udp_manip_pkt(struct sk_buff **pskb,
	      unsigned int hdroff,
	      const struct ip_conntrack_manip *manip,
	      enum ip_nat_manip_type maniptype)
{
	struct udphdr *hdr;
	u_int32_t oldip;
	u_int16_t *portptr;

	if (!skb_ip_make_writable(pskb, hdroff + sizeof(hdr)))
		return 0;

	hdr = (void *)(*pskb)->data + hdroff;
	if (maniptype == IP_NAT_MANIP_SRC) {
		/* Get rid of src ip and src pt */
		oldip = (*pskb)->nh.iph->saddr;
		portptr = &hdr->source;
	} else {
		/* Get rid of dst ip and dst pt */
		oldip = (*pskb)->nh.iph->daddr;
		portptr = &hdr->dest;
	}
	if (hdr->check) /* 0 is a special case meaning no checksum */
		hdr->check = ip_nat_cheat_check(~oldip, manip->ip,
					ip_nat_cheat_check(*portptr ^ 0xFFFF,
							   manip->u.udp.port,
							   hdr->check));
	*portptr = manip->u.udp.port;
	return 1;
}
Esempio n. 2
0
static void
tcp_manip_pkt(struct iphdr *iph, size_t len,
	      const struct ip_conntrack_manip *manip,
	      enum ip_nat_manip_type maniptype)
{
	struct tcphdr *hdr = (struct tcphdr *)((u_int32_t *)iph + iph->ihl);
	u_int32_t oldip;
	u_int16_t *portptr;

	if (maniptype == IP_NAT_MANIP_SRC) {
		/* Get rid of src ip and src pt */
		oldip = iph->saddr;
		portptr = &hdr->source;
	} else {
		/* Get rid of dst ip and dst pt */
		oldip = iph->daddr;
		portptr = &hdr->dest;
	}

	/* this could be a inner header returned in icmp packet; in such
	   cases we cannot update the checksum field since it is outside of
	   the 8 bytes of transport layer headers we are guaranteed */
	if(((void *)&hdr->check + sizeof(hdr->check) - (void *)iph) <= len) {
		hdr->check = ip_nat_cheat_check(~oldip, manip->ip,
					ip_nat_cheat_check(*portptr ^ 0xFFFF,
							   manip->u.tcp.port,
							   hdr->check));
	}

	*portptr = manip->u.tcp.port;
}
Esempio n. 3
0
static void
udp_manip_pkt(struct iphdr *iph, size_t len,
	      const struct ip_conntrack_manip *manip,
	      enum ip_nat_manip_type maniptype)
{
	struct udphdr *hdr = (struct udphdr *)((u_int32_t *)iph + iph->ihl);
	u_int32_t oldip;
	u_int16_t *portptr;

	if (maniptype == IP_NAT_MANIP_SRC) {
		/* Get rid of src ip and src pt */
		oldip = iph->saddr;
		portptr = &hdr->source;
	} else {
		/* Get rid of dst ip and dst pt */
		oldip = iph->daddr;
		portptr = &hdr->dest;
	}
	if (hdr->check) /* 0 is a special case meaning no checksum */
		hdr->check = ip_nat_cheat_check(~oldip, manip->ip,
					ip_nat_cheat_check(*portptr ^ 0xFFFF,
							   manip->u.udp.port,
							   hdr->check));
	*portptr = manip->u.udp.port;
}
Esempio n. 4
0
static int
tcp_manip_pkt(struct sk_buff **pskb,
	      unsigned int iphdroff,
	      const struct ip_conntrack_tuple *tuple,
	      enum ip_nat_manip_type maniptype)
{
	struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
	struct tcphdr *hdr;
	unsigned int hdroff = iphdroff + iph->ihl*4;
	u32 oldip, newip;
	u16 *portptr, newport, oldport;
	int hdrsize = 8; /* TCP connection tracking guarantees this much */

	/* this could be a inner header returned in icmp packet; in such
	   cases we cannot update the checksum field since it is outside of
	   the 8 bytes of transport layer headers we are guaranteed */
	if ((*pskb)->len >= hdroff + sizeof(struct tcphdr))
		hdrsize = sizeof(struct tcphdr);

	if (!skb_make_writable(pskb, hdroff + hdrsize))
		return 0;

	iph = (struct iphdr *)((*pskb)->data + iphdroff);
	hdr = (struct tcphdr *)((*pskb)->data + hdroff);

	if (maniptype == IP_NAT_MANIP_SRC) {
		/* Get rid of src ip and src pt */
		oldip = iph->saddr;
		newip = tuple->src.ip;
		newport = tuple->src.u.tcp.port;
		portptr = &hdr->source;
	} else {
		/* Get rid of dst ip and dst pt */
		oldip = iph->daddr;
		newip = tuple->dst.ip;
		newport = tuple->dst.u.tcp.port;
		portptr = &hdr->dest;
	}

	oldport = *portptr;
	*portptr = newport;

	if (hdrsize < sizeof(*hdr))
		return 1;

	hdr->check = ip_nat_cheat_check(~oldip, newip,
					ip_nat_cheat_check(oldport ^ 0xFFFF,
							   newport,
							   hdr->check));
	return 1;
}
Esempio n. 5
0
static int
udp_manip_pkt(struct sk_buff **pskb,
	      unsigned int iphdroff,
	      const struct ip_conntrack_tuple *tuple,
	      enum ip_nat_manip_type maniptype)
{
	struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
	struct udphdr *hdr;
	unsigned int hdroff = iphdroff + iph->ihl*4;
	u32 oldip, newip;
	u16 *portptr, newport;

	if (!skb_make_writable(pskb, hdroff + sizeof(*hdr)))
		return 0;

	iph = (struct iphdr *)((*pskb)->data + iphdroff);
	hdr = (struct udphdr *)((*pskb)->data + hdroff);

	if (maniptype == IP_NAT_MANIP_SRC) {
		/* Get rid of src ip and src pt */
		oldip = iph->saddr;
		newip = tuple->src.ip;
		newport = tuple->src.u.udp.port;
		portptr = &hdr->source;
	} else {
		/* Get rid of dst ip and dst pt */
		oldip = iph->daddr;
		newip = tuple->dst.ip;
		newport = tuple->dst.u.udp.port;
		portptr = &hdr->dest;
	}
	if (hdr->check) { /* 0 is a special case meaning no checksum */
#ifdef CONFIG_XEN
		if ((*pskb)->proto_csum_blank)
			hdr->check = ip_nat_cheat_check(oldip, ~newip, hdr->check);
		else
#endif
			hdr->check = ip_nat_cheat_check(~oldip, newip,
					ip_nat_cheat_check(*portptr ^ 0xFFFF,
							   newport,
							   hdr->check));
	}
	*portptr = newport;
	return 1;
}
/* manipulate a GRE packet according to maniptype */
static int
gre_manip_pkt(struct sk_buff **pskb,
	      unsigned int iphdroff,
	      const struct ip_conntrack_tuple *tuple,
	      enum ip_nat_manip_type maniptype)
{
	struct gre_hdr *greh;
	struct gre_hdr_pptp *pgreh;
	struct iphdr *iph = (struct iphdr *)((*pskb)->data + iphdroff);
	unsigned int hdroff = iphdroff + iph->ihl*4;

	/* pgreh includes two optional 32bit fields which are not required
	 * to be there.  That's where the magic '8' comes from */
	if (!skb_make_writable(pskb, hdroff + sizeof(*pgreh)-8))
		return 0;

	greh = (void *)(*pskb)->data + hdroff;
	pgreh = (struct gre_hdr_pptp *) greh;

	/* we only have destination manip of a packet, since 'source key' 
	 * is not present in the packet itself */
	if (maniptype == IP_NAT_MANIP_DST) {
		/* key manipulation is always dest */
		switch (greh->version) {
		case 0:
			if (!greh->key) {
				DEBUGP("can't nat GRE w/o key\n");
				break;
			}
			if (greh->csum) {
				/* FIXME: Never tested this code... */
				*(gre_csum(greh)) = 
					ip_nat_cheat_check(~*(gre_key(greh)),
							tuple->dst.u.gre.key,
							*(gre_csum(greh)));
			}
			*(gre_key(greh)) = tuple->dst.u.gre.key;
			break;
		case GRE_VERSION_PPTP:
			DEBUGP("call_id -> 0x%04x\n", 
				ntohs(tuple->dst.u.gre.key));
			pgreh->call_id = tuple->dst.u.gre.key;
			break;
		default:
			DEBUGP("can't nat unknown GRE version\n");
			return 0;
			break;
		}
	}
	return 1;
}
/* manipulate a GRE packet according to maniptype */
static void 
gre_manip_pkt(struct iphdr *iph, size_t len, 
	      const struct ip_conntrack_manip *manip,
	      enum ip_nat_manip_type maniptype)
{
	struct gre_hdr *greh = (struct gre_hdr *)((u_int32_t *)iph+iph->ihl);
	struct gre_hdr_pptp *pgreh = (struct gre_hdr_pptp *) greh;

	/* we only have destination manip of a packet, since 'source key' 
	 * is not present in the packet itself */
	if (maniptype == IP_NAT_MANIP_DST) {
		/* key manipulation is always dest */
		switch (greh->version) {
		case 0:
			if (!greh->key) {
				DEBUGP("can't nat GRE w/o key\n");
				break;
			}
			if (greh->csum) {
				/* FIXME: Never tested this code... */
				*(gre_csum(greh)) = 
					ip_nat_cheat_check(~*(gre_key(greh)),
							manip->u.gre.key,
							*(gre_csum(greh)));
			}
			*(gre_key(greh)) = manip->u.gre.key;
			break;
		case GRE_VERSION_PPTP:
			DEBUGP("call_id -> 0x%04x\n", 
				ntohl(manip->u.gre.key));
			pgreh->call_id = htons(ntohl(manip->u.gre.key));
			break;
		default:
			DEBUGP("can't nat unknown GRE version\n");
			break;
		}
	}
}
Esempio n. 8
0
int udp_user_read(int fd, void *buf, int len, struct udp_data *pri)
{
    char buffer[BUF_SIZE], *udpStart = buffer + sizeof(struct iphdr);
    CHECK_SOCKET(fd);

#ifdef INCLUDE_MAC
#error INCLUDE_MAC support does not work
#endif
    const int invalidPacketLen = -1;
    struct sockaddr_in srcAddr;
    int srcAddrLen = sizeof(struct sockaddr_in);
    int rcv_packet_len = invalidPacketLen;
    __u32 srcIP;

    if ((rcv_packet_len = recvfrom(fd, udpStart, BUF_SIZE, 0,
                                   (struct sockaddr *) & srcAddr, &srcAddrLen)) <= 0) {
        //DEBUG(1, "recvfrom");
        return 0;
    }
    srcIP = srcAddr.sin_addr.s_addr;

    if(rcv_packet_len > 0) {
        DEBUG(2,"Packet recv'd(%d); need to perform unwrap operation\n",
              rcv_packet_len);
        /* XXX Copy unwrap code from kernel-level skbuff reorg stuff
         * */
        struct ipudp *iuh = (struct ipudp *)udpStart;
        char *dataStart = (char*)(iuh + 1);
        struct iphdr *iph = ((struct iphdr*)dataStart) - 1;
        struct tcphdr *th = (struct tcphdr *)dataStart;

        int cookedLen = rcv_packet_len - sizeof(struct ipudp) +
                        sizeof(struct iphdr);

        if(cookedLen < sizeof(struct tcphdr)) {
            printk("Cooked length is shorter than minimum tcp "
                   "header len\n");
            return 0;
        }

        __u16 origCheck = th->check;
        // This code does NOT respect the ipudp src and dest addresses
        // Remove UDP header; push on IP header
        if(iuh->saddr != srcIP) {
#ifndef SUPPORT_NAT
            addrPrintComp("IPUDP header src did not match addr",
                          "!=",iuh->saddr, srcIP);
            return 0;
#else
            // th->check adjustment needed
            th->check =
                ip_nat_cheat_check(~iuh->saddr, srcIP,
                                   th->check);
#endif
        }

        if(iuh->daddr != pri->local_addr) {
#ifndef SUPPORT_NAT
            addrPrintComp("IPUDP header dest did not match addr",
                          "!=",iuh->daddr, pri->local_addr);
            return 0;
#else
            // th->check adjustment needed
            th->check =
                ip_nat_cheat_check(~iuh->daddr, pri->local_addr,
                                   th->check);
#endif
        }

        int ihl = sizeof(*iph);

        iph->version = 4;
        iph->ihl = ihl / 4;
        iph->tos = 0;
        iph->tot_len = htons(cookedLen);
        static int ip_id = 0;
        iph->id = ip_id++;
        iph->frag_off = 0;
        iph->ttl = 255;
        iph->protocol = IPPROTO_TCP;
        iph->check = 0;
#ifdef SUPPORT_NAT
        iph->saddr = srcIP;
        iph->daddr = pri->local_addr;
#else
        iph->saddr = iuh->saddr;
        iph->daddr = iuh->daddr;
#endif
        iph->check = ip_compute_csum((unsigned char *)iph, ihl);

        // XXX should copy protocol from an ipudp field
        DEBUG(2,"Returning cooked length %d, "
              "origCheck = %d, newCheck = %d\n",
              cookedLen, origCheck, th->check);
        DEBUG_GUARD(2, printk("IPH: "); hexdump((char*)iph, ihl) );

        memcpy(buf, (char*)iph, cookedLen);
        return(cookedLen);
    }