Ejemplo n.º 1
0
/* 
  Dug Song came up with this very cool checksuming implementation 
 * eliminating the need for explicit psuedoheader use. 
 * http://72.52.208.92/~gbpprorg/w00w00/files/sectools/fragrouter/Libnet-0.99b/src/checksum.c
 * We check it out for use.
*/
int Packet::do_checksum_(int protocol)
{
   int sum = 0;
   switch (protocol) 
   {
      case IPPROTO_TCP:
	 tcp_hdr->check = 0;
	 sum = in_cksum_((u_short *)&ip_hdr->ip_src, 8);
	 sum += ntohs(IPPROTO_TCP + get_ip_payload_len());
	 sum += in_cksum_((u_short *)tcp_hdr, get_ip_payload_len());
	 tcp_hdr->check = CKSUM_CARRY(sum);
	 break;		   
      case IPPROTO_ICMP:
         icmp_hdr->checksum = 0;
         sum += in_cksum_((uint16_t *)(icmp_hdr), get_ip_payload_len());
         icmp_hdr->checksum = CKSUM_CARRY(sum);
         break;
      case IPPROTO_IP:
	 ip_hdr->ip_sum = 0;
	 sum = in_cksum_((u_short *)ip_hdr, get_ip_hdr_len());
	 ip_hdr->ip_sum = CKSUM_CARRY(sum);
	 break;    
      default:
	 logger->PrintErr("[%s:%d] Unsupported protocol\n", __FILE__, __LINE__);
         return -1;
    }
    return 0;
}
Ejemplo n.º 2
0
unsigned short calculate_tcp_sum(mapipacket *p) {
    unsigned int sum;
    int len;
    u_int16_t pad = 0;

    if (p->iph) {
	len = ntohs(p->iph->ip_len) - sizeof(IPHdr) - p->ip_options_len;
	sum = in_cksum((u_int16_t *)&p->iph->ip_src, 8); // src and dst
    } else if (p->ip6h) {
	//         IPv6 payload length - extension header length
	len = ntohs(p->ip6h->ip6_plen) - ((char *)p->tcph - (char *)(p->ip6h + 1));
	sum = in_cksum((u_int16_t *)&p->ip6h->ip6_src, 32); // src and dst
    } else {
	// Should never be here
	return 0;
    }
    
    p->tcph->th_sum = 0;
    sum += htons(IPPROTO_TCP + len);
    if (len % 2) {
	len--;
	*(unsigned char *)&pad = ((unsigned char *)p->tcph)[len]; // net order
	sum += pad;
    }
    sum += in_cksum((u_int16_t *)p->tcph, len);
    return (unsigned short)(CKSUM_CARRY(sum));
}
Ejemplo n.º 3
0
unsigned short calculate_udp_sum(mapipacket *p) {
    unsigned int sum;
    int len;
    u_int16_t pad = 0;

    if (p->iph)
	sum = in_cksum((u_int16_t *)&p->iph->ip_src, 8); /* src and dst */
    else if (p->ip6h)
	sum = in_cksum((u_int16_t *)&p->ip6h->ip6_src, 32); /* src and dst */
    else
	return 0;
    
    p->udph->uh_chk = 0;
    sum += htons(IPPROTO_UDP);
    sum += p->udph->uh_len;
    
    len = ntohs(p->udph->uh_len);
    if (len % 2) {
	len--;
	*(unsigned char *)&pad = ((unsigned char *)p->udph)[len]; // net order
	sum += pad;
    }
    sum += in_cksum((u_int16_t *)p->udph, len);
    
    return (unsigned short)(CKSUM_CARRY(sum));
}
Ejemplo n.º 4
0
void
add_tcphdr(unsigned char *pkt, struct net_tuple *nt, uint8_t flags)
{
   struct tcphdr                tcp;
   struct _fakehead             fakehead;
   int sum;

   memset(&tcp, 0, sizeof(tcp));
   memset(&fakehead, 0, sizeof(fakehead));

   tcp.th_dport = nt->dport;
   tcp.th_sport = nt->sport;
   fakehead.saddr = nt->src;
 fakehead.daddr = nt->dst;
   fakehead.zero = 0,
   fakehead.protocol = 6;
   fakehead.tot_len = htons(TCP_SIZE);
   sum = in_cksum((u_short *)&fakehead, sizeof(fakehead));
   tcp.th_off = TCP_SIZE >> 2;
   tcp.th_seq = 31337;                         /* ###fixme */
   tcp.th_flags |= flags;                      /* ADD the flags */
   tcp.th_win = htons(0x3fff);
   sum += in_cksum((u_short *)&tcp, sizeof(tcp));
   tcp.th_sum = CKSUM_CARRY(sum);
   memcpy(pkt, &tcp, sizeof(tcp));
}
Ejemplo n.º 5
0
unsigned short calculate_ip_sum(mapipacket *p) {
    unsigned int sum;
    int ip_hl;
			
    p->iph->ip_csum = 0;
			
    ip_hl = IP2_HLEN(p->iph) << 2;
    sum = in_cksum((u_int16_t *)p->iph, ip_hl);
    return (unsigned short)(CKSUM_CARRY(sum));
}
Ejemplo n.º 6
0
int do_checksum(u_char *buf, int protocol, int len)
        /* len = protocol header length + payload length */
{
        struct ip *ip;
        int iplen, sum = 0;

        if (len == 0) {
                fprintf(stderr, "header length can't be zero");
                return -1;
        }

        ip = (struct ip *)buf;
        if (ip->ip_v != 4) {
                fprintf(stderr, "Unsupported IP protocol: %d", ip->ip_v);
                return -1;
        }
        iplen = ip->ip_hl << 2;

        switch (protocol) {
                case IPPROTO_TCP:
                {
                        struct tcphdr *tcp = (struct tcphdr *)(buf + iplen);
                        tcp->th_sum = 0;
                        sum = in_checksum((uint16_t *)&ip->ip_src, 8);
                        sum += ntohs(IPPROTO_TCP+len);
                        sum += in_checksum((uint16_t *)tcp, len);
                        tcp->th_sum = CKSUM_CARRY(sum);
                        break;
                }
                case IPPROTO_UDP:
                {
                        struct udphdr *udp = (struct udphdr *)(buf + iplen);
                        udp->uh_sum = 0;
                        sum = in_checksum((uint16_t *)&ip->ip_src, 8);
                        sum += ntohs(IPPROTO_UDP+len);
                        sum += in_checksum((uint16_t *)udp, len);
                        udp->uh_sum = CKSUM_CARRY(sum);
                        break;
                }
                case IPPROTO_ICMP:
                {
                        struct icmp *icmp = (struct icmp *)(buf + iplen);
                        icmp->icmp_cksum = 0;
                        sum = in_checksum((uint16_t *)icmp, len);
                        icmp->icmp_cksum = CKSUM_CARRY(sum);
                        break;
                }
                case IPPROTO_IP:
                {
                        ip->ip_sum = 0;
                        sum = in_checksum((uint16_t *)ip, ip->ip_hl);
                        ip->ip_sum = CKSUM_CARRY(sum);
                        break;
                }
                default:
                {
                        fprintf(stderr, "Unsupported protocol: %d", protocol);
                        return -1;
                }
        }
#ifdef _DEBUG
        printf("\nProtocol: %d: %x\n", protocol, CKSUM_CARRY(sum));
#endif
        return 0;
}
Ejemplo n.º 7
0
int do_checksum(char *buf, int protocol, int len)
{
    /* Set to NULL to avoid compiler warnings. */
    struct ip *iph_p = NULL;
    struct ip6_hdr *ip6h_p = NULL;
    int ip_hl;
    int sum = 0;
    int ip_version = buf[0] >> 4;

    if ( ip_version == 6 ) {
        int next_header;
        ip6h_p = (struct ip6_hdr *)buf;
        next_header = ip6h_p->ip6_ctlun.ip6_un1.ip6_un1_nxt;
        ip_hl = sizeof( struct ip6_hdr );

        while( next_header != protocol ) {
            switch ( next_header )
            {
                case IPPROTO_FRAGMENT:
                    next_header = ( (struct ip6_frag *) ( buf + ip_hl ) )->ip6f_nxt;
                    ip_hl += sizeof( struct ip6_frag );
                    break;
                case IPPROTO_DSTOPTS:
                    next_header = ( (struct ip6_dest *) ( buf + ip_hl ) )->ip6d_nxt;
                    ip_hl += ( ( (struct ip6_dest *) ( buf + ip_hl ) )->ip6d_len * 8 ) + 8;
                    break;
                default:
                    return 0;
            }
        }
    } else if ( ip_version == 4 ) {
        iph_p = (struct ip *)buf;
        /*
         * This should mask off the top 4 bits first, but we know they are
         * 0100 so shifting left by 2 means the top 2 bits are ignored.
         */
        ip_hl = iph_p->ip_hl << 2;
    } else {
        return (0);
    }
    if ( ip_hl < 0 ) return -2;

    /*
     *  Dug Song came up with this very cool checksuming implementation
     *  eliminating the need for explicit psuedoheader use.  Check it out.
     */
    switch (protocol)
    {
        /*
         *  Style note: normally I don't advocate declaring variables inside
         *  blocks of control, but it makes good sense here. -- MDS
         */
        case IPPROTO_UDP:
        {
            struct udphdr *udph_p =
                (struct udphdr *)(buf + ip_hl);
            //if ( ip_hl + sizeof( struct udphdr ) > len ) return -2;

            udph_p->uh_sum = 0;
            if (ip_version == 6)
            {
                sum = in_cksum((unsigned short *)&ip6h_p->ip6_src, 32);
            }
            else /* If not 6 we know it's 4 as we only allow 6 and 4 above. */
            {
                sum = in_cksum((unsigned short *)&iph_p->ip_src, 8);
            }
            sum += ntohs(IPPROTO_UDP + len);
            sum += in_cksum((unsigned short *)udph_p, len);
            udph_p->uh_sum = CKSUM_CARRY(sum);
            break;
        }
        case IPPROTO_TCP:
        {
            struct tcphdr *tcph_p =
                (struct tcphdr *)(buf + ip_hl);
            //if ( ip_hl + sizeof( struct tcphdr ) > len ) return -2;

            tcph_p->th_sum = 0;
            if (ip_version == 6)
            {
                sum = in_cksum((unsigned short *)&ip6h_p->ip6_src, 32);
            }
            else /* If not 6 we know it's 4 as we only allow 6 and 4 above. */
            {
                sum = in_cksum((unsigned short *)&iph_p->ip_src, 8);
            }
            sum += ntohs(IPPROTO_TCP + len);
            sum += in_cksum((unsigned short *)tcph_p, len);
            tcph_p->th_sum = CKSUM_CARRY(sum);
            break;
        }
        case IPPROTO_ICMP:
        {
            struct icmp *icmph_p =
                (struct icmp *)(buf + ip_hl);
            //if ( ip_hl + sizeof( struct icmphdr ) > len ) return -2;

            icmph_p->icmp_cksum = 0;
            sum = in_cksum((unsigned short *)icmph_p, len);
            icmph_p->icmp_cksum = CKSUM_CARRY(sum);
            break;
        }
        case IPPROTO_ICMPV6:
        {
            struct icmp6_hdr *icmp6h_p =
                (struct icmp6_hdr *)(buf + ip_hl);
            //if ( ip_hl + sizeof( struct icmp6_hdr ) > len ) return -2;

            if (ip_version == 6)
            {
                sum = in_cksum((unsigned short *)&ip6h_p->ip6_src, 32);
            }
            else
            {
                return 0;
            }
            sum += ntohs(IPPROTO_ICMPV6 + len);
            icmp6h_p->icmp6_cksum = 0;
            sum += in_cksum((unsigned short *)icmp6h_p, len);
            icmp6h_p->icmp6_cksum = CKSUM_CARRY(sum);
            break;
        }
        case IPPROTO_IP:
        {
            iph_p->ip_sum = 0;
            sum = in_cksum((unsigned short *)iph_p, len);
            iph_p->ip_sum = CKSUM_CARRY(sum);
            break;
        }
        default:
        {
            return (-1);
        }
    }
    return (1);
}
Ejemplo n.º 8
0
static int in_cksum(u_int16_t *addr, int len){
	int sum;
#if 0
	u_int16_t last_byte;

	sum = 0;
	last_byte = 0;
#else
	union {
		u_int16_t s;
		u_int8_t b[2];
	}pad;

	sum = 0;
#endif

	while(len > 1){
		sum += *addr++;
		len -= 2;
	}
#if 0
	if(len == 1){
		*(u_int8_t *)&last_byte = *(u_int8_t *)addr;
		sum += last_byte;
#else
	if(len == 1){
		pad.b[0] = *(u_int8_t *)addr;
		pad.b[1] = 0;
		sum += pad.s;
#endif
	}

	return sum;
}

/* modified from libnet_do_checksum() from libnet_checksum.c */
void do_checksum(int proto, void *buf, int len){
	struct iphdr *ip = (struct iphdr *)buf;
	int sum = 0;
	int ip_hl = ip->ihl << 2;

	if (len == 0)
		return;

	switch (proto){
		case IPPROTO_TCP: {
			struct tcphdr *tcp = (struct tcphdr *)(buf + ip_hl);
			tcp->check = 0;
			sum = in_cksum((u_int16_t *)&ip->saddr, 8);
			sum += ntohs(IPPROTO_TCP + len);
			sum += in_cksum((u_int16_t *)tcp, len);
			tcp->check = CKSUM_CARRY(sum);
			break;
		}
		case IPPROTO_UDP: {
			struct udphdr *udp = (struct udphdr *)(buf + ip_hl);
			udp->check = 0;
			sum = in_cksum((u_int16_t *)&ip->saddr, 8);
			sum += ntohs(IPPROTO_UDP + len);
			sum += in_cksum((u_int16_t *)udp, len);
			udp->check = CKSUM_CARRY(sum);
			break;
		}
		case IPPROTO_ICMP: {
			struct icmphdr *icmp =	(struct icmphdr *)(buf + ip_hl);
			icmp->checksum = 0;
			sum += in_cksum((u_int16_t *)icmp, len);
			icmp->checksum = CKSUM_CARRY(sum);
			break;
		}
	}
}