Пример #1
0
void ip_checksum(void *buf, size_t len) {
	struct ip *ip;
	int hl, off, sum;

	if (len < sizeof(struct ip))
		return;
	
	ip = (struct ip *)buf;
	hl = ip->ip_hl << 2;
	ip->ip_sum = 0;
	sum = ip_cksum_add(ip, hl, 0);
	ip->ip_sum = ip_cksum_carry(sum);

	off = htons(ip->ip_off);
	
	if ((off & IP_OFFMASK) != 0 || (off & IP_MF) != 0)
		return;
	
	len -= hl;
	
	if (ip->ip_p == IPPROTO_UDP) {
		struct udphdr *udp = (struct udphdr *)((u_char *)ip + hl);

		if (len >= sizeof(struct udphdr)) {
			udp->uh_sum = 0;
			sum = ip_cksum_add(udp, len, 0) + htons(ip->ip_p + len);
			sum = ip_cksum_add(&ip->ip_src, 8, sum);
			udp->uh_sum = ip_cksum_carry(sum);
			if (!udp->uh_sum)
				udp->uh_sum = 0xffff;	/* RFC 768 */
		}
	}
}
Пример #2
0
int gre_encapsulate(ip_t *honeyd_ip, struct addr *src, struct addr *dst,
		struct ip_hdr *iip, u_int iiplen)
{
	struct ip_hdr *oip = (struct ip_hdr *) pkt;
	struct gre_hdr *gre = (struct gre_hdr *) (oip + 1);
	u_char *data = (u_char *) (gre + 1);
	u_int iplen, sum;

	iplen = sizeof(struct ip_hdr) + sizeof(struct gre_hdr) + iiplen;

	if (iplen > sizeof(pkt))
	{
		syslog(LOG_ERR, "%s: packet too long: %d", __func__, iplen);
		return (-1);
	}

	ip_pack_hdr(pkt, 0, iplen, rand_uint16(honeyd_rand), 0, honeyd_ttl,
			IP_PROTO_GRE, src->addr_ip, dst->addr_ip);

	memset(gre, 0, sizeof(struct gre_hdr));
	gre->gre_flags = htons(GRE_CHECKSUM | GRE_VERSION);
	gre->gre_proto = htons(GRE_IP4PROTO);

	/* Copy the payload */
	memcpy(data, iip, iiplen);

	/* Calculate the checksum */
	sum = ip_cksum_add(gre, iiplen + sizeof(struct gre_hdr), 0);
	gre->gre_sum = ip_cksum_carry(sum);

	ip_checksum(oip, iplen);

	return (ip_send(honeyd_ip, pkt, iplen) != iplen ? -1 : 0);
}
Пример #3
0
void
ip6_checksum(void *buf, size_t len)
{
	struct ip6_hdr *ip6 = (struct ip6_hdr *)buf;
	struct ip6_ext_hdr *ext;
	u_char *p, nxt;
	int i, sum;

	nxt = ip6->ip6_nxt;

	for (i = IP6_HDR_LEN; IP6_IS_EXT(nxt); i += (ext->ext_len + 1) << 3) {
		if (i >= (int)len) return;
		ext = (struct ip6_ext_hdr *)((u_char *)buf + i);
		nxt = ext->ext_nxt;
	}
	p = (u_char *)buf + i;
	len -= i;

	if (nxt == IP_PROTO_TCP) {
		struct tcp_hdr *tcp = (struct tcp_hdr *)p;

		if (len >= TCP_HDR_LEN) {
			tcp->th_sum = 0;
			sum = ip_cksum_add(tcp, len, 0) + htons(nxt + (u_short)len);
			sum = ip_cksum_add(&ip6->ip6_src, 32, sum);
			tcp->th_sum = ip_cksum_carry(sum);
		}
	} else if (nxt == IP_PROTO_UDP) {
		struct udp_hdr *udp = (struct udp_hdr *)p;

		if (len >= UDP_HDR_LEN) {
			udp->uh_sum = 0;
			sum = ip_cksum_add(udp, len, 0) + htons(nxt + (u_short)len);
			sum = ip_cksum_add(&ip6->ip6_src, 32, sum);
			if ((udp->uh_sum = ip_cksum_carry(sum)) == 0)
				udp->uh_sum = 0xffff;
		}
	} else if (nxt == IP_PROTO_ICMPV6) {
		struct icmp_hdr *icmp = (struct icmp_hdr *)p;

		if (len >= ICMP_HDR_LEN) {
			icmp->icmp_cksum = 0;
			sum = ip_cksum_add(icmp, len, 0) + htons(nxt + (u_short)len);
			sum = ip_cksum_add(&ip6->ip6_src, 32, sum);
			icmp->icmp_cksum = ip_cksum_carry(sum);
		}
	} else if (nxt == IP_PROTO_ICMP || nxt == IP_PROTO_IGMP) {
		struct icmp_hdr *icmp = (struct icmp_hdr *)p;

		if (len >= ICMP_HDR_LEN) {
			icmp->icmp_cksum = 0;
			sum = ip_cksum_add(icmp, len, 0);
			icmp->icmp_cksum = ip_cksum_carry(sum);
		}
	}
}
Пример #4
0
// Calculate IP checksum over the buffer :
void ip_checksum(void *buf, size_t len)
{
	struct ip_hdr *ip;
	int hl, off, sum;

	if (len < IP_HDR_LEN)
		return;
	
	ip = (struct ip_hdr *)buf;
	hl = ip->ip_hl << 2;
	ip->ip_sum = 0;
	sum = ip_cksum_add(ip, hl, 0);
	ip->ip_sum = ip_cksum_carry(sum);

	off = htons(ip->ip_off);
	
	if ((off & IP_OFFMASK) != 0 || (off & IP_MF) != 0)
		return;
	
	len -= hl;
	
	if (ip->ip_p == IP_PROTO_TCP) {
		struct tcp_hdr *tcp = (struct tcp_hdr *)((u_char *)ip + hl);
		
		if (len >= TCP_HDR_LEN) {
			tcp->th_sum = 0;
			sum = ip_cksum_add(tcp, len, 0) +
			    htons(ip->ip_p + (unsigned short) len);
			sum = ip_cksum_add(&ip->ip_src, 8, sum);
			tcp->th_sum = ip_cksum_carry(sum);
		}
	} else if (ip->ip_p == IP_PROTO_UDP) {
		struct udp_hdr *udp = (struct udp_hdr *)((u_char *)ip + hl);

		if (len >= UDP_HDR_LEN) {
			udp->uh_sum = 0;
			sum = ip_cksum_add(udp, len, 0) +
			    htons(ip->ip_p + (unsigned short) len);
			sum = ip_cksum_add(&ip->ip_src, 8, sum);
			udp->uh_sum = ip_cksum_carry(sum);
			if (!udp->uh_sum)
				udp->uh_sum = 0xffff;	/* RFC 768 */
		}
	} else if (ip->ip_p == IP_PROTO_ICMP || ip->ip_p == IP_PROTO_IGMP) {
		struct icmp_hdr *icmp = (struct icmp_hdr *)((u_char *)ip + hl);
		
		if (len >= ICMP_HDR_LEN) {
			icmp->icmp_cksum = 0;
			sum = ip_cksum_add(icmp, len, 0);
			icmp->icmp_cksum = ip_cksum_carry(sum);
		}
	}
}
Пример #5
0
int gre_decapsulate(struct ip_hdr *oip, u_short oiplen, struct ip_hdr **pip,
		u_short *piplen)
{
	struct gre_hdr *gre;
	struct ip_hdr *ip;
	u_char *end = (u_char *) oip + oiplen;
	u_char *data;
	uint16_t flags, proto, iplen;

	gre = (struct gre_hdr *) ((u_char *) oip + (oip->ip_hl << 2));
	data = (u_char *) (gre + 1);

	if (end <= data)
		return (-1);

	/* We support only RFC 2784 */
	flags = ntohs(gre->gre_flags);
	if ((flags & ~GRE_CHECKSUM) != 0)
	{
		syslog(LOG_DEBUG, "%s: dropping RFC 1701 encapsulation: flags = %x",
				__func__, flags);
		return (-1);
	}

	proto = ntohs(gre->gre_proto);
	if (proto != GRE_IP4PROTO)
	{
		syslog(LOG_DEBUG, "%s: dropping encapsulated packet: bad protocol %d",
				__func__, proto);
		return (-1);
	}

	if (!(flags & GRE_CHECKSUM))
		data = GRE_NOCKSUM_DATA(gre);

	/* Check for the proper length of the packet */
	ip = (struct ip_hdr *) data;
	if (data + sizeof(struct ip_hdr) > end)
		return (-1);

	iplen = ntohs(ip->ip_len);
	if (data + iplen > end)
		return (-1);

	if (flags & GRE_CHECKSUM)
	{
		u_int sum = gre->gre_sum, tmp;
		gre->gre_sum = 0;

		tmp = ip_cksum_add(gre, sizeof(struct gre_hdr) + iplen, 0);
		tmp = ip_cksum_carry(tmp);
		if (sum != tmp)
		{
			syslog(LOG_INFO,
					"%s: dropping encapsulated packet: bad checksum: %x vs %x",
					__func__, ntohs(sum), ntohs(tmp));
			return (-1);
		}
	}

	*pip = ip;
	*piplen = iplen;

	return (0);
}