metasploit-framework/external/ruby-pcapx/icmp_packet.c

445 lines
16 KiB
C

/*
* icmp_packet.c
*
* $Id: icmp_packet.c,v 1.1.1.1 1999/10/27 09:54:38 fukusima Exp $
*
* Copyright (C) 1999 Masaki Fukushima
*/
#include "ruby_pcap.h"
/* rfc1256 */
#ifndef ICMP_ROUTERADVERT
#define ICMP_ROUTERADVERT 9
#endif
#ifndef ICMP_ROUTERSOLICIT
#define ICMP_ROUTERSOLICIT 10
#endif
/* rfc1393 */
#ifndef ICMP_TROUTE
#define ICMP_TROUTE 30
#endif
/* rfc1788 */
#ifndef ICMP_DOMAIN
#define ICMP_DOMAIN 37
#endif
#ifndef ICMP_DOMAINREPLY
#define ICMP_DOMAINREPLY 38
#endif
/* rfc1700 */
#ifndef ICMP_UNREACH_NET_UNKNOWN
#define ICMP_UNREACH_NET_UNKNOWN 6
#endif
#ifndef ICMP_UNREACH_HOST_UNKNOWN
#define ICMP_UNREACH_HOST_UNKNOWN 7
#endif
#ifndef ICMP_UNREACH_ISOLATED
#define ICMP_UNREACH_ISOLATED 8
#endif
#ifndef ICMP_UNREACH_NET_PROHIB
#define ICMP_UNREACH_NET_PROHIB 9
#endif
#ifndef ICMP_UNREACH_HOST_PROHIB
#define ICMP_UNREACH_HOST_PROHIB 10
#endif
#ifndef ICMP_UNREACH_TOSNET
#define ICMP_UNREACH_TOSNET 11
#endif
#ifndef ICMP_UNREACH_TOSHOST
#define ICMP_UNREACH_TOSHOST 12
#endif
/* rfc1716 */
#ifndef ICMP_UNREACH_FILTER_PROHIB
#define ICMP_UNREACH_FILTER_PROHIB 13
#endif
#ifndef ICMP_UNREACH_HOST_PRECEDENCE
#define ICMP_UNREACH_HOST_PRECEDENCE 14
#endif
#ifndef ICMP_UNREACH_PRECEDENCE_CUTOFF
#define ICMP_UNREACH_PRECEDENCE_CUTOFF 15
#endif
#ifndef ICMP_PARAMPROB_OPTABSENT
#define ICMP_PARAMPROB_OPTABSENT 1
#endif
#define ICMP_HDR(pkt) ((struct icmp *)LAYER4_HDR(pkt))
#define ICMP_DATA(pkt) ((u_char *)LAYER5_HDR(pkt))
#define ICMP_DATALEN(pkt) \
(ntohs(IP_HDR(pkt)->ip_len) - (IP_HDR(pkt)->ip_hl * 4 + 8))
#define ICMP_CAPLEN(pkt) (pkt->hdr.pkthdr.caplen - pkt->hdr.layer4_off)
VALUE cICMPPacket;
#define CheckTruncateICMP(pkt, need) \
CheckTruncate(pkt, pkt->hdr.layer4_off, need, "truncated ICMP")
struct icmp_type_info {
char *name;
VALUE klass;
};
static struct icmp_type_info icmp_types[] = {
{/* 0 */ "echo reply" },
{},{},
{/* 3 */ "unreachable" },
{/* 4 */ "source quench" },
{/* 5 */ "redirect" },
{},{},
{/* 8 */ "echo request" },
{/* 9 */ "router advertisement" },
{/* 10 */ "router solicitation" },
{/* 11 */ "time exceeded" },
{/* 12 */ "parameter problem" },
{/* 13 */ "time stamp request" },
{/* 14 */ "time stamp reply" },
{/* 15 */ "information request" },
{/* 16 */ "information reply" },
{/* 17 */ "address mask request" },
{/* 18 */ "address mask reply" },
{},{},{},{},{},{},{},{},{},{},{},
{/* 30 */ "traceroute" },
{},{},{},{},{},{},
{/* 37 */ "domain name request" },
{/* 38 */ "domain name reply" }
#define ICMP_TYPE_MAX 38
};
VALUE
setup_icmp_packet(pkt, tl_len)
struct packet_object *pkt;
int tl_len;
{
VALUE klass = cICMPPacket;
if (tl_len >= 1) {
struct icmp *icmp = ICMP_HDR(pkt);
if (icmp->icmp_type <= ICMP_TYPE_MAX
&& icmp_types[icmp->icmp_type].klass) {
klass = icmp_types[icmp->icmp_type].klass;
}
}
return klass;
}
#define ICMPP_METHOD(func, need, val) \
static VALUE\
(func)(self)\
VALUE self;\
{\
struct packet_object *pkt;\
struct icmp *icmp;\
GetPacket(self, pkt);\
CheckTruncateICMP(pkt, (need));\
icmp = ICMP_HDR(pkt);\
return (val);\
}
/*
* Common methods (icmp_type independent)
*/
ICMPP_METHOD(icmpp_type, 1, INT2FIX(icmp->icmp_type))
ICMPP_METHOD(icmpp_code, 2, INT2FIX(icmp->icmp_code))
ICMPP_METHOD(icmpp_cksum, 4, INT2FIX(ntohs(icmp->icmp_cksum)))
ICMPP_METHOD(icmpp_typestr, 1,
(icmp->icmp_type <= ICMP_TYPE_MAX
&&icmp_types[icmp->icmp_type].name)
? rb_str_new2(icmp_types[icmp->icmp_type].name)
: rb_obj_as_string(INT2FIX(icmp->icmp_type)))
/*
* icmp_type specific methods
*/
ICMPP_METHOD(icmpp_pptr, 5, INT2FIX(icmp->icmp_pptr))
ICMPP_METHOD(icmpp_gwaddr, 8, new_ipaddr(&icmp->icmp_gwaddr))
ICMPP_METHOD(icmpp_id, 6, INT2FIX(ntohs(icmp->icmp_id)))
ICMPP_METHOD(icmpp_seq, 8, INT2FIX(ntohs(icmp->icmp_seq)))
#ifdef WORDS_BIGENDIAN
ICMPP_METHOD(icmpp_seqle, 8, INT2FIX(((0x00ff&icmp->icmp_seq)<<8) +
(icmp->icmp_seq >> 8)))
#else
ICMPP_METHOD(icmpp_seqle, 8, INT2FIX(icmp->icmp_seq))
#endif
/* rfc1191 */
struct mtu_discovery {
u_short unused;
u_short nextmtu;
};
#define MTUD(icmp) ((struct mtu_discovery *)&icmp->icmp_void)
static VALUE
icmpp_nextmtu(self)
VALUE self;
{
struct packet_object *pkt;
struct icmp *icmp;
GetPacket(self, pkt);
CheckTruncateICMP(pkt, 8);
icmp = ICMP_HDR(pkt);
if (icmp->icmp_code != ICMP_UNREACH_NEEDFRAG)
rb_raise(rb_eRuntimeError, "not ICMP_UNREACH_NEEDFRAG");
return INT2FIX(ntohs(MTUD(icmp)->nextmtu));
}
/* rfc1256 */
struct ih_rdiscovery {
u_char num_addrs;
u_char wpa;
u_short lifetime;
};
#define IHRD(icmp) ((struct ih_rdiscovery *)&icmp->icmp_void)
struct id_rdiscovery {
struct in_addr ird_addr;
long ird_pref;
};
#define IDRD(icmp) ((struct id_rdiscovery *)icmp->icmp_data)
ICMPP_METHOD(icmpp_num_addrs, 5, INT2FIX(IHRD(icmp)->num_addrs))
ICMPP_METHOD(icmpp_wpa, 6, INT2FIX(IHRD(icmp)->wpa))
ICMPP_METHOD(icmpp_lifetime, 8, INT2FIX(ntohs(IHRD(icmp)->lifetime)))
static VALUE
icmpp_radv(self, ind)
VALUE self, ind;
{
struct packet_object *pkt;
struct icmp *icmp;
int i = NUM2INT(ind);
VALUE ary;
GetPacket(self, pkt);
CheckTruncateICMP(pkt, 5);
if (i > IHRD(icmp)->num_addrs)
rb_raise(rb_eRuntimeError, "num_addrs = %d, requested radv(%d)",
(int)IHRD(icmp)->num_addrs, i);
CheckTruncateICMP(pkt, 8 + i*8);
icmp = ICMP_HDR(pkt);
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;
}
#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)))
static VALUE
icmpp_ip(self)
VALUE self;
{
struct packet_object *pkt;
struct icmp *icmp;
struct pcap_pkthdr pkthdr;
GetPacket(self, pkt);
CheckTruncateICMP(pkt, 9);
icmp = ICMP_HDR(pkt);
pkthdr.caplen = ICMP_CAPLEN(pkt) - 8;
pkthdr.len = 0;
pkthdr.ts.tv_sec = 0;
pkthdr.ts.tv_usec = 0;
return new_packet((char *)&icmp->icmp_ip, &pkthdr, DLT_RAW);
}
ICMPP_METHOD(icmpp_mask, 12, UINT32_2_NUM(ntohl(icmp->icmp_mask)))
ICMPP_METHOD(icmpp_data, 9, rb_str_new(icmp->icmp_data, ICMP_CAPLEN(pkt)-8))
/* rfc1393 */
struct traceroute {
u_short ohc;
u_short rhc;
u_long lspeed;
u_long lmtu;
};
#define TROUTE(icmp) ((struct traceroute *)icmp->icmp_data)
ICMPP_METHOD(icmpp_ohc, 10, INT2FIX(ntohs(TROUTE(icmp)->ohc)))
ICMPP_METHOD(icmpp_rhc, 12, INT2FIX(ntohs(TROUTE(icmp)->rhc)))
ICMPP_METHOD(icmpp_lspeed, 16, UINT32_2_NUM(ntohl(TROUTE(icmp)->lspeed)))
ICMPP_METHOD(icmpp_lmtu, 20, UINT32_2_NUM(ntohl(TROUTE(icmp)->lmtu)))
/* rfc1788 */
struct domain_reply {
u_long ttl;
char names[1];
};
#define DOMAIN(icmp) ((struct domain_reply *)icmp->icmp_data)
ICMPP_METHOD(icmpp_ttl, 12, UINT32_2_NUM(ntohl(DOMAIN(icmp)->ttl)))
void
Init_icmp_packet(void)
{
VALUE klass;
rb_define_const(mPcap, "ICMP_ECHOREPLY", INT2NUM(ICMP_ECHOREPLY));
rb_define_const(mPcap, "ICMP_UNREACH", INT2NUM(ICMP_UNREACH));
rb_define_const(mPcap, "ICMP_SOURCEQUENCH",INT2NUM(ICMP_SOURCEQUENCH));
rb_define_const(mPcap, "ICMP_REDIRECT", INT2NUM(ICMP_REDIRECT));
rb_define_const(mPcap, "ICMP_ECHO", INT2NUM(ICMP_ECHO));
rb_define_const(mPcap, "ICMP_TIMXCEED", INT2NUM(ICMP_TIMXCEED));
rb_define_const(mPcap, "ICMP_PARAMPROB", INT2NUM(ICMP_PARAMPROB));
rb_define_const(mPcap, "ICMP_TSTAMP", INT2NUM(ICMP_TSTAMP));
rb_define_const(mPcap, "ICMP_TSTAMPREPLY", INT2NUM(ICMP_TSTAMPREPLY));
rb_define_const(mPcap, "ICMP_IREQ", INT2NUM(ICMP_IREQ));
rb_define_const(mPcap, "ICMP_IREQREPLY", INT2NUM(ICMP_IREQREPLY));
rb_define_const(mPcap, "ICMP_MASKREQ", INT2NUM(ICMP_MASKREQ));
rb_define_const(mPcap, "ICMP_MASKREPLY", INT2NUM(ICMP_MASKREPLY));
/* UNREACH codes */
rb_define_const(mPcap, "ICMP_UNREACH_NET", INT2NUM(ICMP_UNREACH_NET));
rb_define_const(mPcap, "ICMP_UNREACH_HOST", INT2NUM(ICMP_UNREACH_HOST));
rb_define_const(mPcap, "ICMP_UNREACH_PROTOCOL", INT2NUM(ICMP_UNREACH_PROTOCOL));
rb_define_const(mPcap, "ICMP_UNREACH_PORT", INT2NUM(ICMP_UNREACH_PORT));
rb_define_const(mPcap, "ICMP_UNREACH_NEEDFRAG", INT2NUM(ICMP_UNREACH_NEEDFRAG));
rb_define_const(mPcap, "ICMP_UNREACH_SRCFAIL", INT2NUM(ICMP_UNREACH_SRCFAIL));
rb_define_const(mPcap, "ICMP_UNREACH_NET_UNKNOWN", INT2NUM(ICMP_UNREACH_NET_UNKNOWN));
rb_define_const(mPcap, "ICMP_UNREACH_HOST_UNKNOWN", INT2NUM(ICMP_UNREACH_HOST_UNKNOWN));
rb_define_const(mPcap, "ICMP_UNREACH_ISOLATED", INT2NUM(ICMP_UNREACH_ISOLATED));
rb_define_const(mPcap, "ICMP_UNREACH_NET_PROHIB", INT2NUM(ICMP_UNREACH_NET_PROHIB));
rb_define_const(mPcap, "ICMP_UNREACH_HOST_PROHIB", INT2NUM(ICMP_UNREACH_HOST_PROHIB));
rb_define_const(mPcap, "ICMP_UNREACH_TOSNET", INT2NUM(ICMP_UNREACH_TOSNET));
rb_define_const(mPcap, "ICMP_UNREACH_TOSHOST", INT2NUM(ICMP_UNREACH_TOSHOST));
rb_define_const(mPcap, "ICMP_UNREACH_FILTER_PROHIB", INT2NUM(ICMP_UNREACH_FILTER_PROHIB));
rb_define_const(mPcap, "ICMP_UNREACH_HOST_PRECEDENCE", INT2NUM(ICMP_UNREACH_HOST_PRECEDENCE));
rb_define_const(mPcap, "ICMP_UNREACH_PRECEDENCE_CUTOFF", INT2NUM(ICMP_UNREACH_PRECEDENCE_CUTOFF));
/* REDIRECT codes */
rb_define_const(mPcap, "ICMP_REDIRECT_NET", INT2NUM(ICMP_REDIRECT_NET));
rb_define_const(mPcap, "ICMP_REDIRECT_HOST", INT2NUM(ICMP_REDIRECT_HOST));
rb_define_const(mPcap, "ICMP_REDIRECT_TOSNET", INT2NUM(ICMP_REDIRECT_TOSNET));
rb_define_const(mPcap, "ICMP_REDIRECT_TOSHOST", INT2NUM(ICMP_REDIRECT_TOSHOST));
/* TIMEXCEED codes */
rb_define_const(mPcap, "ICMP_TIMXCEED_INTRANS", INT2NUM(ICMP_TIMXCEED_INTRANS));
rb_define_const(mPcap, "ICMP_TIMXCEED_REASS", INT2NUM(ICMP_TIMXCEED_REASS));
/* PARAMPROB code */
rb_define_const(mPcap, "ICMP_PARAMPROB_OPTABSENT", INT2NUM(ICMP_PARAMPROB_OPTABSENT));
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);
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);
rb_define_method(klass, "icmp_seqle", icmpp_seqle, 0);
rb_define_method(klass, "icmp_data", icmpp_data, 0);
klass = rb_define_class_under(mPcap, "ICMPUnreach", cICMPPacket);
icmp_types[ICMP_UNREACH].klass = klass;
rb_define_method(klass, "icmp_nextmtu", icmpp_nextmtu, 0);
rb_define_method(klass, "icmp_ip", icmpp_ip, 0);
klass = rb_define_class_under(mPcap, "ICMPSourceQuench", cICMPPacket);
icmp_types[ICMP_SOURCEQUENCH].klass = klass;
rb_define_method(klass, "icmp_ip", icmpp_ip, 0);
klass = rb_define_class_under(mPcap, "ICMPRedirect", cICMPPacket);
icmp_types[ICMP_REDIRECT].klass = klass;
rb_define_method(klass, "icmp_gwaddr", icmpp_gwaddr, 0);
rb_define_method(klass, "icmp_ip", icmpp_ip, 0);
klass = rb_define_class_under(mPcap, "ICMPEcho", cICMPPacket);
icmp_types[ICMP_ECHO].klass = klass;
rb_define_method(klass, "icmp_id", icmpp_id, 0);
rb_define_method(klass, "icmp_seq", icmpp_seq, 0);
rb_define_method(klass, "icmp_seqle", icmpp_seqle, 0);
rb_define_method(klass, "icmp_data", icmpp_data, 0);
klass = rb_define_class_under(mPcap, "ICMPRouterAdvert", cICMPPacket);
icmp_types[ICMP_ROUTERADVERT].klass = klass;
rb_define_method(klass, "icmp_num_addrs", icmpp_num_addrs, 0);
rb_define_method(klass, "icmp_wpa", icmpp_wpa, 0);
rb_define_method(klass, "icmp_lifetime", icmpp_lifetime, 0);
rb_define_method(klass, "icmp_radv", icmpp_radv, 1);
klass = rb_define_class_under(mPcap, "ICMPRouterSolicit", cICMPPacket);
icmp_types[ICMP_ROUTERSOLICIT].klass = klass;
klass = rb_define_class_under(mPcap, "ICMPTimxceed", cICMPPacket);
icmp_types[ICMP_TIMXCEED].klass = klass;
rb_define_method(klass, "icmp_ip", icmpp_ip, 0);
klass = rb_define_class_under(mPcap, "ICMPParamProb", cICMPPacket);
icmp_types[ICMP_PARAMPROB].klass = klass;
rb_define_method(klass, "icmp_pptr", icmpp_pptr, 0);
rb_define_method(klass, "icmp_ip", icmpp_ip, 0);
klass = rb_define_class_under(mPcap, "ICMPTStamp", cICMPPacket);
icmp_types[ICMP_TSTAMP].klass = klass;
rb_define_method(klass, "icmp_id", icmpp_id, 0);
rb_define_method(klass, "icmp_seq", icmpp_seq, 0);
rb_define_method(klass, "icmp_otime", icmpp_otime, 0);
rb_define_method(klass, "icmp_rtime", icmpp_rtime, 0);
rb_define_method(klass, "icmp_ttime", icmpp_ttime, 0);
klass = rb_define_class_under(mPcap, "ICMPTStampReply", cICMPPacket);
icmp_types[ICMP_TSTAMPREPLY].klass = klass;
rb_define_method(klass, "icmp_id", icmpp_id, 0);
rb_define_method(klass, "icmp_seq", icmpp_seq, 0);
rb_define_method(klass, "icmp_otime", icmpp_otime, 0);
rb_define_method(klass, "icmp_rtime", icmpp_rtime, 0);
rb_define_method(klass, "icmp_ttime", icmpp_ttime, 0);
klass = rb_define_class_under(mPcap, "ICMPIReq", cICMPPacket);
icmp_types[ICMP_IREQ].klass = klass;
rb_define_method(klass, "icmp_id", icmpp_id, 0);
rb_define_method(klass, "icmp_seq", icmpp_seq, 0);
klass = rb_define_class_under(mPcap, "ICMPIReqReply", cICMPPacket);
icmp_types[ICMP_IREQREPLY].klass = klass;
rb_define_method(klass, "icmp_id", icmpp_id, 0);
rb_define_method(klass, "icmp_seq", icmpp_seq, 0);
klass = rb_define_class_under(mPcap, "ICMPMaskReq", cICMPPacket);
icmp_types[ICMP_MASKREQ].klass = klass;
rb_define_method(klass, "icmp_id", icmpp_id, 0);
rb_define_method(klass, "icmp_seq", icmpp_seq, 0);
/*rb_define_method(klass, "icmp_mask", icmpp_mask, 0);*/
klass = rb_define_class_under(mPcap, "ICMPMaskReply", cICMPPacket);
icmp_types[ICMP_MASKREPLY].klass = klass;
rb_define_method(klass, "icmp_id", icmpp_id, 0);
rb_define_method(klass, "icmp_seq", icmpp_seq, 0);
/*rb_define_method(klass, "icmp_mask", icmpp_mask, 0);*/
klass = rb_define_class_under(mPcap, "ICMPTRoute", cICMPPacket);
icmp_types[ICMP_TROUTE].klass = klass;
rb_define_method(klass, "icmp_id", icmpp_id, 0);
rb_define_method(klass, "icmp_ohc", icmpp_ohc, 0);
rb_define_method(klass, "icmp_rhc", icmpp_rhc, 0);
rb_define_method(klass, "icmp_lspeed", icmpp_lspeed, 0);
rb_define_method(klass, "icmp_lmtu", icmpp_lmtu, 0);
klass = rb_define_class_under(mPcap, "ICMPDomain", cICMPPacket);
icmp_types[ICMP_DOMAIN].klass = klass;
rb_define_method(klass, "icmp_id", icmpp_id, 0);
rb_define_method(klass, "icmp_seq", icmpp_seq, 0);
klass = rb_define_class_under(mPcap, "ICMPDomainReply", cICMPPacket);
icmp_types[ICMP_DOMAINREPLY].klass = klass;
rb_define_method(klass, "icmp_id", icmpp_id, 0);
rb_define_method(klass, "icmp_seq", icmpp_seq, 0);
rb_define_method(klass, "icmp_ttl", icmpp_ttl, 0);
/*rb_define_method(klass, "icmp_names", icmpp_names, 0);*/
}