#include #include #include extern VALUE cLibnet; static VALUE net_s_decode_ethernet(VALUE self, VALUE bytes) { VALUE eth_obj; VALUE str; VALUE payload; struct libnet_ethernet_hdr *eth; u_int16_t ether_type; eth_obj = rb_funcall(self, rb_intern("new"), 0); str = StringValue(bytes); if (RSTRING(str)->len < LIBNET_ETH_H) { rb_raise(rb_eArgError, "string is too small to contain an Ethernet header"); } eth = (struct libnet_ethernet_hdr *)RSTRING(str)->ptr; ether_type = ntohs(eth->ether_type); /* rb_iv_set(eth_obj, "@dst", rb_str_new(eth->ether_dhost, ETHER_ADDR_LEN)); rb_iv_set(eth_obj, "@src", rb_str_new(eth->ether_shost, ETHER_ADDR_LEN)); rb_iv_set(eth_obj, "@type", UINT2NUM(ether_type)); */ rb_funcall(eth_obj, rb_intern("dst="), 1, rb_str_new((char *)eth->ether_dhost, ETHER_ADDR_LEN)); rb_funcall(eth_obj, rb_intern("src="), 1, rb_str_new((char *)eth->ether_shost, ETHER_ADDR_LEN)); rb_funcall(eth_obj, rb_intern("type="), 1, UINT2NUM(ether_type)); if (RSTRING(str)->len > LIBNET_ETH_H) { payload = rb_str_new(RSTRING(str)->ptr + LIBNET_ETH_H, RSTRING(str)->len - LIBNET_ETH_H); } else { payload = Qnil; } //rb_iv_set(eth_obj, "@payload", payload); rb_funcall(eth_obj, rb_intern("payload="), 1, payload); return eth_obj; } static VALUE net_build_ethernet(int argc, VALUE *argv, VALUE self) { libnet_t *l; VALUE eth, v; u_int8_t *dst = NULL; u_int8_t *src = NULL; u_int16_t type; char *payload = NULL; u_int32_t payload_s = 0; VALUE ptag_obj; libnet_ptag_t ptag = 0; rb_scan_args(argc, argv, "01", ð); Data_Get_Struct(self, libnet_t, l); if (NIL_P(eth)) { eth = rb_class_new_instance(0, NULL, rb_const_get(cLibnet, rb_intern("Ethernet"))); rb_yield(eth); } /* check that all required fields are set */ rb_funcall(eth, rb_intern("check_packable"), 0); /* required parameters */ v = rb_funcall(eth, rb_intern("dst"), 0); dst = (u_int8_t *)StringValuePtr(v); v = rb_funcall(eth, rb_intern("type"), 0); type = NUM2UINT(v); /* optional parameters */ v = rb_funcall(eth, rb_intern("src"), 0); src = (u_int8_t *)StringValuePtr(v); if ((v = rb_funcall(eth, rb_intern("payload"), 0)) != Qnil) { v = StringValue(v); payload = RSTRING(v)->ptr; payload_s = RSTRING(v)->len; } ptag_obj = rb_iv_get(eth, "@ptag"); if (!NIL_P(ptag_obj)) { ptag = NUM2LONG(ptag_obj); } ptag = libnet_build_ethernet(dst, src, type, (u_int8_t *)payload, payload_s, l, ptag); if (ptag == -1) { rb_raise(rb_eRuntimeError, libnet_geterror(l)); } rb_iv_set(eth, "@ptag", LONG2NUM(ptag)); return eth; } void define_ethernet_methods() { VALUE cEthernet = rb_const_get(cLibnet, rb_intern("Ethernet")); rb_define_singleton_method(cEthernet, "decode", net_s_decode_ethernet, 1); rb_define_method(cLibnet, "build_ethernet", net_build_ethernet, -1); }