#include #include #include #include #include VALUE cLibnet; extern void define_ipv4_methods(void); extern void define_ipv6_methods(void); extern void define_udp_methods(void); extern void define_ipv4_methods(void); extern void define_ethernet_methods(void); extern void define_vlan_methods(void); extern void define_arp_methods(void); /* call-seq: * Libnet.new(injection_type=:raw4, device=nil) # -> a new Libnet object * * Creates a new Libnet object. The +injection_type+ parameter defines * how the constructed packet get injected into the network. * * If +injection_type+ is :link, the packet gets injected at the data * link layer (which provides more granular control over the IP layer). If * +injection_type+ is :link and +device+ is not +nil+, Libnet * attempts to use the specified network device for packet injection. The * +device+ parameter is either a canonical string that references the device * (such as "eth0" for a 100MB Ethernet card on Linux or "fxp0" for a 100MB * Ethernet card on OpenBSD) or the dotted decimal representation of the * device's IP address (e.g. 192.168.0.1). If +device+ is +nil+, Libnet * attempts to find a suitable device to use. * * If +injection_type+ is :raw4, the packet gets injected using a raw * socket interface. */ static VALUE net_s_new(int argc, VALUE *argv, VALUE self) { libnet_t *l; VALUE obj; char errbuf[LIBNET_ERRBUF_SIZE]; int inj_type = LIBNET_RAW4_ADV; char *inj_str = NULL; size_t inj_str_len = 0; char *dev_str = NULL; /* get the injection type */ if (argc > 0) { switch (TYPE(argv[0])) { case T_STRING: inj_str = RSTRING(argv[0])->ptr; inj_str_len = RSTRING(argv[0])->len; break; case T_SYMBOL: inj_str = rb_id2name(SYM2ID(argv[0])); inj_str_len = strlen(inj_str); break; default: rb_raise(rb_eTypeError, "invalid type, expecting a String or Symbol"); } if (strncasecmp("raw", inj_str, inj_str_len) == 0 || strncasecmp("raw4", inj_str, inj_str_len) == 0) { inj_type = LIBNET_RAW4_ADV; } else if (strncasecmp("raw6", inj_str, inj_str_len) == 0) { inj_type = LIBNET_RAW6_ADV; } else if (strncasecmp("link", inj_str, inj_str_len) == 0) { inj_type = LIBNET_LINK_ADV; } else { rb_raise(rb_eArgError, "%s is not a valid initialization type, should be one of: 'raw4', 'raw6', or 'link'", inj_str); } } /* get the device string */ if (argc > 1) { dev_str = StringValuePtr(argv[1]); } l = libnet_init(inj_type, dev_str, errbuf); if (l == NULL) { rb_raise(rb_eRuntimeError, errbuf); } obj = Data_Wrap_Struct(self, NULL, libnet_destroy, l); /* set the injection type attribute */ switch (inj_type) { case LIBNET_RAW4_ADV: rb_iv_set(obj, "@injection_type", ID2SYM(rb_intern("raw4"))); break; case LIBNET_RAW6_ADV: rb_iv_set(obj, "@injection_type", ID2SYM(rb_intern("raw6"))); break; case LIBNET_LINK_ADV: rb_iv_set(obj, "@injection_type", ID2SYM(rb_intern("link"))); break; default: rb_bug("BUG: %d is an invalid injection type (this should not happen)", inj_type); } return obj; } /* call-seq: * Libnet.addr2name4(addr, do_dns_lookup=true) # -> DNS name or dotted decimal string * * Takes a network byte ordered IPv4 address and returns a string containing * either the canonical DNS name (if it has one) or a dotted decimal * respresentation of the IP address. This may incur a DNS lookup if the * +do_dns_lookup+ parameter is set to true. If the +do_dns_lookup+ * parameter is set to false, no DNS lookup will be performed and the dotted * decimal representation of the IP address will be returned. */ static VALUE net_s_addr2name4(int argc, VALUE *argv, VALUE self) { VALUE addr_v, use_name_v, name_v; u_int32_t addr; u_int8_t use_name = LIBNET_RESOLVE; char *name = NULL; rb_scan_args(argc, argv, "11", &addr_v, &use_name_v); addr = NUM2ULONG(addr_v); addr = htonl(addr); if (!NIL_P(use_name_v) && use_name_v == Qfalse) { use_name = LIBNET_DONT_RESOLVE; } name = libnet_addr2name4(addr, use_name); name_v = rb_str_new2(name); /* don't free the returned name here as its stored in a static buffer by * libnet */ return name_v; } /* call-seq: * Libnet.addr2name6(addr, do_dns_lookup=true) # -> DNS name or printable IPv6 string * * Takes a 16 byte IPv6 address and returns either the canonical DNS name (if * it has one) or a printable representation of the address. */ static VALUE net_s_addr2name6(int argc, VALUE *argv, VALUE self) { VALUE addr_v, use_name_v, name_v; struct libnet_in6_addr addr; u_int8_t use_name = LIBNET_RESOLVE; char name[100]; rb_scan_args(argc, argv, "11", &addr_v, &use_name_v); if (RSTRING(addr_v)->len != 16) { rb_raise(rb_eArgError, "invalid IPv6 address"); } memcpy(addr.libnet_s6_addr, RSTRING(addr_v)->ptr, sizeof(addr.libnet_s6_addr)); if (!NIL_P(use_name_v) && use_name_v == Qfalse) { use_name = LIBNET_DONT_RESOLVE; } libnet_addr2name6_r(addr, use_name, name, sizeof(name)); name_v = rb_str_new2(name); return name_v; } /* call-seq: * Libnet.hex_aton(string) # -> string * * Takes a colon separated hexidecimal address and returns a byte string * suitable for use in a protocol builder method. */ static VALUE net_s_hex_aton(VALUE self, VALUE str) { u_int8_t *rv; int len; VALUE s; rv = libnet_hex_aton((int8_t *)StringValuePtr(str), &len); if (rv == NULL) { rb_raise(rb_eArgError, "could not convert input string"); } s = rb_str_new((char *)rv, len); free(rv); return s; } /* call-seq: * Libnet.ipv4_aton(string) # -> integer * * Takes a dotted-decimal representation of an IPv4 address and returns a 4 * byte integer suitable for use in a header builder method. */ static VALUE net_s_ipv4_aton(VALUE self, VALUE str) { char *ip_s; int len = RSTRING(str)->len; unsigned long ipv4; VALUE r; ip_s = malloc(len + 1); memcpy(ip_s, RSTRING(str)->ptr, len); ip_s[len] = '\0'; if (inet_pton(AF_INET, ip_s, &ipv4) == 1) { ipv4 = htonl(ipv4); r = ULONG2NUM(ipv4); } else { free(ip_s); rb_raise(rb_eArgError, "invalid IPv4 address: %s\n", ip_s); } free(ip_s); return r; } /* call-seq: * Libnet.ipv6_aton(string) # -> integer * * Takes a string representation of an IPv6 address and returns a 16 * byte string suitable for use in a header builder method. */ static VALUE net_s_ipv6_aton(VALUE self, VALUE str) { char *ip_s; int len = RSTRING(str)->len; unsigned char ipv6[16]; VALUE r; ip_s = malloc(len + 1); memcpy(ip_s, RSTRING(str)->ptr, len); ip_s[len] = '\0'; if (inet_pton(AF_INET6, ip_s, ipv6) == 1) { r = rb_str_new(ipv6, sizeof(ipv6)); } else { free(ip_s); rb_raise(rb_eArgError, "invalid IPv6 address: %s\n", ip_s); } free(ip_s); return r; } /* call-seq: * Libnet.ipv4_ntoa(integer) # -> string * * Takes a network formated IPv4 address and converts it to its dotted-decimal * string representation. */ static VALUE net_s_ipv4_ntoa(VALUE self, VALUE integer) { unsigned long ipv4 = NUM2ULONG(integer); char pbuf[100]; VALUE r; ipv4 = htonl(ipv4); if (inet_ntop(AF_INET, &ipv4, pbuf, sizeof(pbuf))) { r = rb_str_new2(pbuf); } else { rb_raise(rb_eArgError, "could not convert integer value %#x to a printable IPv4 string", ipv4); } return r; } /* call-seq: * Libnet.ipv6_ntoa(string) # -> string * * Takes a network formated IPv6 address and converts it to its printable * format. */ static VALUE net_s_ipv6_ntoa(VALUE self, VALUE str) { char *ip_s; int len = RSTRING(str)->len; char pbuf[100]; VALUE r; if (len != 16) { rb_raise(rb_eArgError, "invalid IPv6 address"); } ip_s = malloc(len + 1); memcpy(ip_s, RSTRING(str)->ptr, len); ip_s[len] = '\0'; if (inet_ntop(AF_INET6, ip_s, pbuf, sizeof(pbuf))) { r = rb_str_new2(pbuf); } else { rb_raise(rb_eArgError, "could not convert IPv6 address to a printable string"); } return r; } /* call-seq: * l.get_device # -> string * * Returns the canonical name of the device used for packet injection. */ static VALUE net_get_device(VALUE self) { libnet_t *l; char *dev; Data_Get_Struct(self, libnet_t, l); dev = (char *)libnet_getdevice(l); if (dev == NULL) { dev = ""; } return rb_str_new2(dev); } /* call-seq: * l.write # -> num bytes written * * Writes a prebuilt packet to the network. The method assumes that a * packet has been constructed inside the Libnet object via one or more * Libnet#build_* methods and is ready to go. Depending on how this * Libnet object was initialized, the method will write the packet to the * wire either via the raw or link layer interface. * * Note: It is necessary for the UID or EUID of the process running this method * to be 0. */ static VALUE net_write(VALUE self) { libnet_t *l; int num_bytes; Data_Get_Struct(self, libnet_t, l); num_bytes = libnet_write(l); if (num_bytes == -1) { rb_raise(rb_eRuntimeError, libnet_geterror(l)); } return INT2NUM(num_bytes); } /* call-seq: * l.write_bytes(string) # -> num bytes written * * Writes a packet to the wire. This method is usedful to write a packet * that has been constructed by hand or to write a packet that has been * returned from Libnet#pack. * * Note: It is necessary for the UID or EUID of the process running this method * to be 0. */ static VALUE net_write_bytes(VALUE self, VALUE bytes) { libnet_t *l; int num_bytes; VALUE str; VALUE inj_type; str = StringValue(bytes); Data_Get_Struct(self, libnet_t, l); inj_type = rb_iv_get(self, "@injection_type"); if (ID2SYM(rb_intern("raw4")) == inj_type) { num_bytes = libnet_write_raw_ipv4(l, RSTRING(str)->ptr, RSTRING(str)->len); } else if (ID2SYM(rb_intern("raw6")) == inj_type) { num_bytes = libnet_write_raw_ipv6(l, RSTRING(str)->ptr, RSTRING(str)->len); } else if (ID2SYM(rb_intern("link")) == inj_type) { num_bytes = libnet_write_link(l, RSTRING(str)->ptr, RSTRING(str)->len); } else { rb_bug("BUG: invalid injection type found (this should not happen)"); } if (num_bytes == -1) { rb_raise(rb_eRuntimeError, libnet_geterror(l)); } return INT2NUM(num_bytes); } /* call-seq: * l.pack # -> string * * Yanks a prebuilt, wire-ready packet from the Libnet object. */ static VALUE net_pack(VALUE self) { libnet_t *l; u_int8_t *packet; u_int32_t packet_s; VALUE str; Data_Get_Struct(self, libnet_t, l); if (libnet_pblock_coalesce(l, &packet, &packet_s) == -1) { rb_raise(rb_eRuntimeError, libnet_geterror(l)); } str = rb_str_new((char *)packet, packet_s); libnet_adv_free_packet(l, packet); return str; } /* call-seq: * l.dump # -> nil * * Prints the contents of the Libnet object to STDOUT. */ static VALUE net_dump(VALUE self) { libnet_t *l; Data_Get_Struct(self, libnet_t, l); libnet_diag_dump_context(l); return Qnil; } /* call-seq: * l.clear # -> nil * * Clears the current packet inside the Libnet object. Should be called * when the programmer wants to send a completely new packet of a different * type using the same Libnet object. */ static VALUE net_clear(VALUE self) { libnet_t *l; Data_Get_Struct(self, libnet_t, l); libnet_clear_packet(l); return Qnil; } /* call-seq: * l.hwaddr # -> string * * Returns the MAC address for the device the Libnet object was initialized * with. If the Libnet object was initialized without a device, the method * will attempt to find one. If the method fails to find a device, a * RuntimeError will be raised. */ static VALUE net_hwaddr(VALUE self) { libnet_t *l; struct libnet_ether_addr *eth; int i; char eth_s[18]; char byte_s[3]; Data_Get_Struct(self, libnet_t, l); eth = libnet_get_hwaddr(l); if (eth == NULL) { rb_raise(rb_eRuntimeError, libnet_geterror(l)); } memset(eth_s, 0, sizeof(eth_s)); for (i = 0; i < 6; i++) { snprintf(byte_s, sizeof(byte_s), "%02x", eth->ether_addr_octet[i]); strcat(eth_s, byte_s); if (i != 5) { strcat(eth_s, ":"); } } return rb_str_new2(eth_s); } /* Ruby bindings for the Libnet[http://www.packetfactory.net/libnet/] Packet * Construction Library. */ void Init_libnet4r() { cLibnet = rb_define_class("Libnet", rb_cObject); /* libnet header length constants */ rb_define_const(cLibnet, "HL_802_1Q", INT2FIX(LIBNET_802_1Q_H)); rb_define_const(cLibnet, "HL_802_1X", INT2FIX(LIBNET_802_1X_H)); rb_define_const(cLibnet, "HL_802_2", INT2FIX(LIBNET_802_2_H)); rb_define_const(cLibnet, "HL_802_2SNAP", INT2FIX(LIBNET_802_2SNAP_H)); rb_define_const(cLibnet, "HL_802_3", INT2FIX(LIBNET_802_3_H)); rb_define_const(cLibnet, "HL_ARP", INT2FIX(LIBNET_ARP_H)); rb_define_const(cLibnet, "HL_ARP_ETH_IP", INT2FIX(LIBNET_ARP_ETH_IP_H)); rb_define_const(cLibnet, "HL_BGP4_HEADER", INT2FIX(LIBNET_BGP4_HEADER_H)); rb_define_const(cLibnet, "HL_BGP4_OPEN", INT2FIX(LIBNET_BGP4_OPEN_H)); rb_define_const(cLibnet, "HL_BGP4_UPDATE", INT2FIX(LIBNET_BGP4_UPDATE_H)); rb_define_const(cLibnet, "HL_BGP4_NOTIFICATION", INT2FIX(LIBNET_BGP4_NOTIFICATION_H)); rb_define_const(cLibnet, "HL_CDP", INT2FIX(LIBNET_CDP_H)); rb_define_const(cLibnet, "HL_DHCPV4", INT2FIX(LIBNET_DHCPV4_H)); rb_define_const(cLibnet, "HL_UDP_DNSV4", INT2FIX(LIBNET_UDP_DNSV4_H)); rb_define_const(cLibnet, "HL_TCP_DNSV4", INT2FIX(LIBNET_TCP_DNSV4_H)); rb_define_const(cLibnet, "HL_ETH", INT2FIX(LIBNET_ETH_H)); rb_define_const(cLibnet, "HL_FDDI", INT2FIX(LIBNET_FDDI_H)); rb_define_const(cLibnet, "HL_ICMPV4", INT2FIX(LIBNET_ICMPV4_H)); rb_define_const(cLibnet, "HL_ICMPV4_ECHO", INT2FIX(LIBNET_ICMPV4_ECHO_H)); rb_define_const(cLibnet, "HL_ICMPV4_MASK", INT2FIX(LIBNET_ICMPV4_MASK_H)); rb_define_const(cLibnet, "HL_ICMPV4_UNREACH", INT2FIX(LIBNET_ICMPV4_UNREACH_H)); rb_define_const(cLibnet, "HL_ICMPV4_TIMXCEED", INT2FIX(LIBNET_ICMPV4_TIMXCEED_H)); rb_define_const(cLibnet, "HL_ICMPV4_REDIRECT", INT2FIX(LIBNET_ICMPV4_REDIRECT_H)); rb_define_const(cLibnet, "HL_ICMPV4_TS", INT2FIX(LIBNET_ICMPV4_TS_H)); rb_define_const(cLibnet, "HL_ICMPV6", INT2FIX(LIBNET_ICMPV6_H)); rb_define_const(cLibnet, "HL_IGMP", INT2FIX(LIBNET_IGMP_H)); rb_define_const(cLibnet, "HL_IPV4", INT2FIX(LIBNET_IPV4_H)); rb_define_const(cLibnet, "HL_IPV6", INT2FIX(LIBNET_IPV6_H)); rb_define_const(cLibnet, "HL_IPV6_FRAG", INT2FIX(LIBNET_IPV6_FRAG_H)); rb_define_const(cLibnet, "HL_IPV6_ROUTING", INT2FIX(LIBNET_IPV6_ROUTING_H)); rb_define_const(cLibnet, "HL_IPV6_DESTOPTS", INT2FIX(LIBNET_IPV6_DESTOPTS_H)); rb_define_const(cLibnet, "HL_IPV6_HBHOPTS", INT2FIX(LIBNET_IPV6_HBHOPTS_H)); rb_define_const(cLibnet, "HL_IPSEC_ESP_HDR", INT2FIX(LIBNET_IPSEC_ESP_HDR_H)); rb_define_const(cLibnet, "HL_IPSEC_ESP_FTR", INT2FIX(LIBNET_IPSEC_ESP_FTR_H)); rb_define_const(cLibnet, "HL_IPSEC_AH", INT2FIX(LIBNET_IPSEC_AH_H)); rb_define_const(cLibnet, "HL_ISL", INT2FIX(LIBNET_ISL_H)); rb_define_const(cLibnet, "HL_GRE", INT2FIX(LIBNET_GRE_H)); rb_define_const(cLibnet, "HL_GRE_SRE", INT2FIX(LIBNET_GRE_SRE_H)); rb_define_const(cLibnet, "HL_MPLS", INT2FIX(LIBNET_MPLS_H)); rb_define_const(cLibnet, "HL_OSPF", INT2FIX(LIBNET_OSPF_H)); rb_define_const(cLibnet, "HL_OSPF_HELLO", INT2FIX(LIBNET_OSPF_HELLO_H)); rb_define_const(cLibnet, "HL_OSPF_DBD", INT2FIX(LIBNET_OSPF_DBD_H)); rb_define_const(cLibnet, "HL_OSPF_LSR", INT2FIX(LIBNET_OSPF_LSR_H)); rb_define_const(cLibnet, "HL_OSPF_LSU", INT2FIX(LIBNET_OSPF_LSU_H)); rb_define_const(cLibnet, "HL_OSPF_LSA", INT2FIX(LIBNET_OSPF_LSA_H)); rb_define_const(cLibnet, "HL_OSPF_AUTH", INT2FIX(LIBNET_OSPF_AUTH_H)); rb_define_const(cLibnet, "HL_OSPF_CKSUM", INT2FIX(LIBNET_OSPF_CKSUM)); rb_define_const(cLibnet, "HL_OSPF_LS_RTR", INT2FIX(LIBNET_OSPF_LS_RTR_H)); rb_define_const(cLibnet, "HL_OSPF_LS_NET", INT2FIX(LIBNET_OSPF_LS_NET_H)); rb_define_const(cLibnet, "HL_OSPF_LS_SUM", INT2FIX(LIBNET_OSPF_LS_SUM_H)); rb_define_const(cLibnet, "HL_OSPF_LS_AS_EXT", INT2FIX(LIBNET_OSPF_LS_AS_EXT_H)); rb_define_const(cLibnet, "HL_NTP", INT2FIX(LIBNET_NTP_H)); rb_define_const(cLibnet, "HL_RIP", INT2FIX(LIBNET_RIP_H)); rb_define_const(cLibnet, "HL_RPC_CALL", INT2FIX(LIBNET_RPC_CALL_H)); rb_define_const(cLibnet, "HL_RPC_CALL_TCP", INT2FIX(LIBNET_RPC_CALL_TCP_H)); rb_define_const(cLibnet, "HL_SEBEK", INT2FIX(LIBNET_SEBEK_H)); rb_define_const(cLibnet, "HL_STP_CONF", INT2FIX(LIBNET_STP_CONF_H)); rb_define_const(cLibnet, "HL_STP_TCN", INT2FIX(LIBNET_STP_TCN_H)); rb_define_const(cLibnet, "HL_TOKEN_RING", INT2FIX(LIBNET_TOKEN_RING_H)); rb_define_const(cLibnet, "HL_TCP", INT2FIX(LIBNET_TCP_H)); rb_define_const(cLibnet, "HL_UDP", INT2FIX(LIBNET_UDP_H)); rb_define_const(cLibnet, "HL_VRRP", INT2FIX(LIBNET_VRRP_H)); /* IP protocol constants */ #ifdef HAVE_IPPROTO_IP rb_define_const(cLibnet, "IPPROTO_IP", INT2FIX(IPPROTO_IP)); #endif #ifdef HAVE_IPPROTO_HOPOPTS rb_define_const(cLibnet, "IPPROTO_HOPOPTS", INT2FIX(IPPROTO_HOPOPTS)); #endif #ifdef HAVE_IPPROTO_ICMP rb_define_const(cLibnet, "IPPROTO_ICMP", INT2FIX(IPPROTO_ICMP)); #endif #ifdef HAVE_IPPROTO_IGMP rb_define_const(cLibnet, "IPPROTO_IGMP", INT2FIX(IPPROTO_IGMP)); #endif #ifdef HAVE_IPPROTO_GGP rb_define_const(cLibnet, "IPPROTO_GGP", INT2FIX(IPPROTO_GGP)); #endif #ifdef HAVE_IPPROTO_ENCAP rb_define_const(cLibnet, "IPPROTO_ENCAP", INT2FIX(IPPROTO_ENCAP)); #endif #ifdef HAVE_IPPROTO_TCP rb_define_const(cLibnet, "IPPROTO_TCP", INT2FIX(IPPROTO_TCP)); #endif #ifdef HAVE_IPPROTO_EGP rb_define_const(cLibnet, "IPPROTO_EGP", INT2FIX(IPPROTO_EGP)); #endif #ifdef HAVE_IPPROTO_PUP rb_define_const(cLibnet, "IPPROTO_PUP", INT2FIX(IPPROTO_PUP)); #endif #ifdef HAVE_IPPROTO_UDP rb_define_const(cLibnet, "IPPROTO_UDP", INT2FIX(IPPROTO_UDP)); #endif #ifdef HAVE_IPPROTO_IDP rb_define_const(cLibnet, "IPPROTO_IDP", INT2FIX(IPPROTO_IDP)); #endif #ifdef HAVE_IPPROTO_IPV6 rb_define_const(cLibnet, "IPPROTO_IPV6", INT2FIX(IPPROTO_IPV6)); #endif #ifdef HAVE_IPPROTO_ROUTING rb_define_const(cLibnet, "IPPROTO_ROUTING", INT2FIX(IPPROTO_ROUTING)); #endif #ifdef HAVE_IPPROTO_FRAGMENT rb_define_const(cLibnet, "IPPROTO_FRAGMENT", INT2FIX(IPPROTO_FRAGMENT)); #endif #ifdef HAVE_IPPROTO_RSVP rb_define_const(cLibnet, "IPPROTO_RSVP", INT2FIX(IPPROTO_RSVP)); #endif #ifdef HAVE_IPPROTO_ESP rb_define_const(cLibnet, "IPPROTO_ESP", INT2FIX(IPPROTO_ESP)); #endif #ifdef HAVE_IPPROTO_AH rb_define_const(cLibnet, "IPPROTO_AH", INT2FIX(IPPROTO_AH)); #endif #ifdef HAVE_IPPROTO_ICMPV6 rb_define_const(cLibnet, "IPPROTO_ICMPV6", INT2FIX(IPPROTO_ICMPV6)); #endif #ifdef HAVE_IPPROTO_NONE rb_define_const(cLibnet, "IPPROTO_NONE", INT2FIX(IPPROTO_NONE)); #endif #ifdef HAVE_IPPROTO_DSTOPTS rb_define_const(cLibnet, "IPPROTO_DSTOPTS", INT2FIX(IPPROTO_DSTOPTS)); #endif #ifdef HAVE_IPPROTO_HELLO rb_define_const(cLibnet, "IPPROTO_HELLO", INT2FIX(IPPROTO_HELLO)); #endif #ifdef HAVE_IPPROTO_ND rb_define_const(cLibnet, "IPPROTO_ND", INT2FIX(IPPROTO_ND)); #endif #ifdef HAVE_IPPROTO_EON rb_define_const(cLibnet, "IPPROTO_EON", INT2FIX(IPPROTO_EON)); #endif #ifdef HAVE_IPPROTO_PIM rb_define_const(cLibnet, "IPPROTO_PIM", INT2FIX(IPPROTO_PIM)); #endif #ifdef HAVE_IPPROTO_SCTP rb_define_const(cLibnet, "IPPROTO_SCTP", INT2FIX(IPPROTO_SCTP)); #endif #ifdef HAVE_IPPROTO_RAW rb_define_const(cLibnet, "IPPROTO_RAW", INT2FIX(IPPROTO_RAW)); #endif #ifdef HAVE_IPPROTO_MAX rb_define_const(cLibnet, "IPPROTO_MAX", INT2FIX(IPPROTO_MAX)); #endif /* require the pure ruby protocol classes */ rb_require("libnet4r/libnet.rb"); rb_require("libnet4r/helpers.rb"); rb_require("libnet4r/header.rb"); /* class methods */ rb_define_singleton_method(cLibnet, "new", net_s_new, -1); rb_define_singleton_method(cLibnet, "addr2name4", net_s_addr2name4, -1); rb_define_singleton_method(cLibnet, "addr2name6", net_s_addr2name6, -1); rb_define_singleton_method(cLibnet, "hex_aton", net_s_hex_aton, 1); rb_define_singleton_method(cLibnet, "ipv4_aton", net_s_ipv4_aton, 1); rb_define_singleton_method(cLibnet, "ipv4_ntoa", net_s_ipv4_ntoa, 1); rb_define_singleton_method(cLibnet, "ipv6_aton", net_s_ipv6_aton, 1); rb_define_singleton_method(cLibnet, "ipv6_ntoa", net_s_ipv6_ntoa, 1); /* instance methods */ rb_define_method(cLibnet, "device", net_get_device, 0); rb_define_method(cLibnet, "write", net_write, 0); rb_define_method(cLibnet, "write_bytes", net_write_bytes, 1); rb_define_method(cLibnet, "cull_packet", net_pack, 0); rb_define_method(cLibnet, "pack", net_pack, 0); rb_define_method(cLibnet, "hwaddr", net_hwaddr, 0); rb_define_method(cLibnet, "dump", net_dump, 0); rb_define_method(cLibnet, "clear", net_clear, 0); /* define the individual protocol methods */ define_udp_methods(); define_ipv4_methods(); define_ipv6_methods(); define_ethernet_methods(); define_vlan_methods(); define_arp_methods(); }