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

343 lines
8.1 KiB
C

/*
* ip_packet.c
*
* $Id: ip_packet.c,v 1.1.1.1 1999/10/27 09:54:38 fukusima Exp $
*
* Copyright (C) 1998, 1999 Masaki Fukushima
*/
#include "ruby_pcap.h"
#include <netdb.h>
VALUE cIPPacket;
static VALUE cIPAddress;
#define CheckTruncateIp(pkt, need) \
CheckTruncate(pkt, pkt->hdr.layer3_off, need, "truncated IP")
VALUE
setup_ip_packet(pkt, nl_len)
struct packet_object *pkt;
int nl_len;
{
VALUE class;
DEBUG_PRINT("setup_ip_packet");
if (nl_len > 0 && IP_HDR(pkt)->ip_v != 4) {
return cPacket;
}
class = cIPPacket;
nl_len = MIN(nl_len, ntohs(IP_HDR(pkt)->ip_len));
if (nl_len > 20) {
int hl = IP_HDR(pkt)->ip_hl * 4;
int tl_len = nl_len - hl;
if (tl_len > 0) {
pkt->hdr.layer4_off = pkt->hdr.layer3_off + hl;
/* if this is fragment zero, setup upper layer */
if ((ntohs(IP_HDR(pkt)->ip_off) & IP_OFFMASK) == 0) {
switch (IP_HDR(pkt)->ip_p) {
case IPPROTO_TCP:
class = setup_tcp_packet(pkt, tl_len);
break;
case IPPROTO_UDP:
class = setup_udp_packet(pkt, tl_len);
break;
case IPPROTO_ICMP:
class = setup_icmp_packet(pkt, tl_len);
break;
}
}
}
}
return class;
}
#define IPP_METHOD(func, need, val) \
static VALUE\
(func)(self)\
VALUE self;\
{\
struct packet_object *pkt;\
struct ip *ip;\
\
DEBUG_PRINT(#func);\
GetPacket(self, pkt);\
CheckTruncateIp(pkt, (need));\
ip = IP_HDR(pkt);\
return (val);\
}
IPP_METHOD(ipp_ver, 1, INT2FIX(ip->ip_v))
IPP_METHOD(ipp_hlen, 1, INT2FIX(ip->ip_hl))
IPP_METHOD(ipp_tos, 2, INT2FIX(ip->ip_tos))
IPP_METHOD(ipp_len, 4, INT2FIX(ntohs(ip->ip_len)))
IPP_METHOD(ipp_id, 6, INT2FIX(ntohs(ip->ip_id)))
IPP_METHOD(ipp_flags, 8, INT2FIX((ntohs(ip->ip_off) & ~IP_OFFMASK) >> 13))
IPP_METHOD(ipp_df, 8, ntohs(ip->ip_off) & IP_DF ? Qtrue : Qfalse)
IPP_METHOD(ipp_mf, 8, ntohs(ip->ip_off) & IP_MF ? Qtrue : Qfalse)
IPP_METHOD(ipp_off, 8, INT2FIX(ntohs(ip->ip_off) & IP_OFFMASK))
IPP_METHOD(ipp_ttl, 9, INT2FIX(ip->ip_ttl))
IPP_METHOD(ipp_proto, 10, INT2FIX(ip->ip_p))
IPP_METHOD(ipp_sum, 12, INT2FIX(ntohs(ip->ip_sum)))
IPP_METHOD(ipp_src, 16, new_ipaddr(&ip->ip_src))
IPP_METHOD(ipp_dst, 20, new_ipaddr(&ip->ip_dst))
static VALUE
ipp_sumok(self)
VALUE self;
{
struct packet_object *pkt;
struct ip *ip;
int hlen, i, sum;
unsigned short *ipus;
GetPacket(self, pkt);
CheckTruncateIp(pkt, 20);
ip = IP_HDR(pkt);
hlen = ip->ip_hl * 4;
CheckTruncateIp(pkt, hlen);
ipus = (unsigned short *)ip;
sum = 0;
hlen /= 2; /* 16-bit word */
for (i = 0; i < hlen; i++) {
sum += ntohs(ipus[i]);
sum = (sum & 0xffff) + (sum >> 16);
}
if (sum == 0xffff)
return Qtrue;
return Qfalse;
}
static VALUE
ipp_data(self)
VALUE self;
{
struct packet_object *pkt;
struct ip *ip;
int len, hlen;
DEBUG_PRINT("ipp_data");
GetPacket(self, pkt);
CheckTruncateIp(pkt, 20);
ip = IP_HDR(pkt);
hlen = ip->ip_hl * 4;
len = pkt->hdr.pkthdr.caplen - pkt->hdr.layer3_off - hlen;
return rb_str_new((u_char *)ip + hlen, len);
}
/*
* IPAddress
*/
/* IPv4 adress (32bit) is stored by immediate value */
#if SIZEOF_VOIDP < 4
# error IPAddress assumes sizeof(void *) >= 4
#endif
#define GetIPAddress(obj, addr) {\
Check_Type(obj, T_DATA);\
addr = (struct in_addr *)&(DATA_PTR(obj));\
}
VALUE
new_ipaddr(addr)
struct in_addr *addr;
{
VALUE self;
self = Data_Wrap_Struct(cIPAddress, 0, 0, (void *)addr->s_addr);
return self;
}
#ifndef INADDR_NONE
# define INADDR_NONE (0xffffffff)
#endif
static VALUE
ipaddr_s_new(self, val)
VALUE self, val;
{
struct in_addr addr;
struct hostent *hent;
char *hname;
switch(TYPE(val)) {
case T_STRING:
hname = RSTRING(val)->ptr;
hent = gethostbyname(hname);
if (hent == NULL) {
extern int h_errno;
switch (h_errno) {
case HOST_NOT_FOUND:
rb_raise(ePcapError, "host not found: %s", hname);
break;
default:
#ifdef HAVE_HSTRERROR
rb_raise(ePcapError, (char *)hstrerror(h_errno));
#else
rb_raise(ePcapError, "host not found: %s", hname);
#endif
}
}
addr = *(struct in_addr *)hent->h_addr;
break;
case T_FIXNUM:
case T_BIGNUM:
addr.s_addr = htonl(NUM2ULONG(val));
break;
default:
rb_raise(rb_eTypeError, "String or Integer required");
}
return new_ipaddr(&addr);
}
static VALUE
ipaddr_to_i(self)
VALUE self;
{
struct in_addr *addr;
GetIPAddress(self, addr);
return UINT32_2_NUM(ntohl(addr->s_addr));
}
static VALUE
ipaddr_num_s(self)
VALUE self;
{
struct in_addr *addr;
GetIPAddress(self, addr);
return rb_str_new2(inet_ntoa(*addr));
}
static VALUE
ipaddr_hostname(self)
VALUE self;
{
struct in_addr *addr;
struct hostent *host;
GetIPAddress(self, addr);
host = gethostbyaddr((char *)&addr->s_addr, sizeof addr->s_addr, AF_INET);
if (host == NULL)
return ipaddr_num_s(self);
return rb_str_new2(host->h_name);
}
static VALUE
ipaddr_to_s(self)
VALUE self;
{
if (RTEST(rbpcap_convert))
return ipaddr_hostname(self);
else
return ipaddr_num_s(self);
}
static VALUE
ipaddr_equal(self, other)
VALUE self, other;
{
struct in_addr *addr1;
struct in_addr *addr2;
GetIPAddress(self, addr1);
if (rb_class_of(other) == cIPAddress) {
GetIPAddress(other, addr2);
if (addr1->s_addr == addr2->s_addr)
return Qtrue;
}
return Qfalse;
}
static VALUE
ipaddr_hash(self)
VALUE self;
{
struct in_addr *addr;
GetIPAddress(self, addr);
return INT2FIX(ntohl(addr->s_addr));
}
static VALUE
ipaddr_dump(self, limit)
VALUE self;
VALUE limit;
{
struct in_addr *addr;
GetIPAddress(self, addr);
return rb_str_new((char *)addr, sizeof addr);
}
static VALUE
ipaddr_s_load(klass, str)
VALUE klass;
VALUE str;
{
struct in_addr addr;
int i;
if (RSTRING(str)->len != sizeof addr) {
rb_raise(rb_eArgError, "dump format error (IPAddress)");
}
for (i = 0; i < sizeof addr; i++) {
((char *)&addr)[i] = RSTRING(str)->ptr[i];
}
return new_ipaddr(&addr);
}
void
Init_ip_packet(void)
{
DEBUG_PRINT("Init_ip_packet");
cIPPacket = rb_define_class_under(mPcap, "IPPacket", cPacket);
rb_define_method(cIPPacket, "ip_ver", ipp_ver, 0);
rb_define_method(cIPPacket, "ip_hlen", ipp_hlen, 0);
rb_define_method(cIPPacket, "ip_tos", ipp_tos, 0);
rb_define_method(cIPPacket, "ip_len", ipp_len, 0);
rb_define_method(cIPPacket, "ip_id", ipp_id, 0);
rb_define_method(cIPPacket, "ip_flags", ipp_flags, 0);
rb_define_method(cIPPacket, "ip_df?", ipp_df, 0);
rb_define_method(cIPPacket, "ip_mf?", ipp_mf, 0);
rb_define_method(cIPPacket, "ip_off", ipp_off, 0);
rb_define_method(cIPPacket, "ip_ttl", ipp_ttl, 0);
rb_define_method(cIPPacket, "ip_proto", ipp_proto, 0);
rb_define_method(cIPPacket, "ip_sum", ipp_sum, 0);
rb_define_method(cIPPacket, "ip_sumok?", ipp_sumok, 0);
rb_define_method(cIPPacket, "ip_src", ipp_src, 0);
rb_define_method(cIPPacket, "src", ipp_src, 0);
rb_define_method(cIPPacket, "ip_dst", ipp_dst, 0);
rb_define_method(cIPPacket, "dst", ipp_dst, 0);
rb_define_method(cIPPacket, "ip_data", ipp_data, 0);
cIPAddress = rb_define_class_under(mPcap, "IPAddress", rb_cObject);
rb_define_singleton_method(cIPAddress, "new", ipaddr_s_new, 1);
rb_define_method(cIPAddress, "to_i", ipaddr_to_i, 0);
rb_define_method(cIPAddress, "to_s", ipaddr_to_s, 0);
rb_define_method(cIPAddress, "num_s", ipaddr_num_s, 0);
rb_define_method(cIPAddress, "to_num_s", ipaddr_num_s, 0); /* BWC */
rb_define_method(cIPAddress, "hostname", ipaddr_hostname, 0);
rb_define_method(cIPAddress, "sym_s", ipaddr_hostname, 0);
rb_define_method(cIPAddress, "==", ipaddr_equal, 1);
rb_define_method(cIPAddress, "===", ipaddr_equal, 1);
rb_define_method(cIPAddress, "eql?", ipaddr_equal, 1);
rb_define_method(cIPAddress, "hash", ipaddr_hash, 0);
rb_define_method(cIPAddress, "_dump", ipaddr_dump, 1);
rb_define_singleton_method(cIPAddress, "_load", ipaddr_s_load, 1);
Init_tcp_packet();
Init_udp_packet();
Init_icmp_packet();
}