ext/pcap/icmp_packet.c in ruby-pcap-0.7.9 vs ext/pcap/icmp_packet.c in ruby-pcap-0.8.0

- old
+ new

@@ -230,11 +230,45 @@ ary = rb_ary_new(); rb_ary_push(ary, new_ipaddr(&IDRD(icmp)->ird_addr)); rb_ary_push(ary, INT2NUM(ntohl(IDRD(icmp)->ird_pref))); return ary; } +static VALUE +icmpp_csumok(self) + VALUE self; +{ + struct packet_object *pkt; + struct ip *ip; + struct icmp *icmp; + GetPacket(self, pkt); + ip = IP_HDR(pkt); + icmp = ICMP_HDR(pkt); + long sum = 0; + unsigned short *temp = (unsigned short *)icmp; + int len = ntohs(ip->ip_len) - ip->ip_hl*4; // length of ip data + int csum = ntohs(icmp->icmp_cksum); // keep the checksum in packet + + icmp->icmp_cksum = 0; + while(len > 1){ + sum += ntohs(*temp++); + len -= 2; + } + if(len) + sum += ntohs((unsigned short) *((unsigned char *)temp)); + while(sum>>16) + sum = (sum & 0xFFFF) + (sum >> 16); + unsigned short answer = ~sum; + + icmp->icmp_cksum = csum; //restore the checkum in packet + if (DEBUG_CHECKSUM) + printf("ICMP csum in packet:%d should be %d\n", csum, answer); + if (answer == csum) + return Qtrue; + return Qfalse; +} + #define time_new_msec(t) rb_time_new((t)/1000, (t)%1000 * 1000) ICMPP_METHOD(icmpp_otime, 12, time_new_msec(ntohl(icmp->icmp_otime))) ICMPP_METHOD(icmpp_rtime, 16, time_new_msec(ntohl(icmp->icmp_rtime))) ICMPP_METHOD(icmpp_ttime, 20, time_new_msec(ntohl(icmp->icmp_ttime))) @@ -334,9 +368,10 @@ cICMPPacket = rb_define_class_under(mPcap, "ICMPPacket", cIPPacket); rb_define_method(cICMPPacket, "icmp_type", icmpp_type, 0); rb_define_method(cICMPPacket, "icmp_typestr", icmpp_typestr, 0); rb_define_method(cICMPPacket, "icmp_code", icmpp_code, 0); rb_define_method(cICMPPacket, "icmp_cksum", icmpp_cksum, 0); + rb_define_method(cICMPPacket, "icmp_csum_ok?", icmpp_csumok, 0); klass = rb_define_class_under(mPcap, "ICMPEchoReply", cICMPPacket); icmp_types[ICMP_ECHOREPLY].klass = klass; rb_define_method(klass, "icmp_id", icmpp_id, 0); rb_define_method(klass, "icmp_seq", icmpp_seq, 0);