Libnet核心数据结构

Libnet核心数据结构

http://blog.chinaunix.net/u3/114769/showart_2236587.html

Libnet入门学习

http://blog.chinaunix.net/u3/114769/showart_2236590.html 

利用libnet创建新的网络包结构
http://blog.chinaunix.net/u3/114769/showart_2236592.html

 

 

 

libnet是一个小型的接口函数库,
  主要用C语言写成,
  提供了低层网络数据包的构造、处理和发送功能。
  libnet的开发目的是:
  建立一个简单统一的网络编程接口以屏蔽不同操作系统底层网络编程的差别,
  使得程序员将精力集中在解决关键问题上。
  它的主要特点是:
  高层接口:libnet主要用C语言写成
  可移植性:libnet目前可以在Linux、FreeBSD、Solaris、WindowsNT等操作系统上运行,并且提供了统一的接口
  数据包构造:libnet提供了一系列的TCP/IP数据报文的构造函数以方便用户使用
  数据包的处理:libnet提供了一系列的辅助函数,利用这些辅助函数,帮助用户简化那些烦琐的事务性的编程工作
  数据包发送:libnet允许用户在两种不同的数据包发送方法中选择。

libnet提供的接口函数按其作用可分为四类:
  * 内存管理(分配和释放)函数
  * 地址解析函数
  * 数据包构造函数
  * 数据包发送函数
  以下分别列出这些接口函数及其功能(其参数含义简单易懂,不再解释):
  ★ 内存管理函数
  单数据包内存初始化:
  int libnet_init_packet(u_short packet_size, u_char **buf);
  单数据包内存释放:
  void libnet_destroy_packet(u_char **buf);
  多数据包内存初始化:
  int libnet_init_packet_arena(struct libnet_arena **arena,
  u_short packet_num, u_short packet_size);
  访问多数据包内存中的下一个数据包:
  u_char *libnet_next_packet_from_arena(struct libnet_arena **arena,
  u_short packet_size);
  多数据包内存释放:
  void libnet_destroy_packet_arena(struct libnet_arena **arena);
  ★ 地址解析函数
  解析主机名:
  u_char *libnet_host_lookup(u_long ip, u_short use_name);
  解析主机名(可重入函数):
  void libnet_host_lookup_r(u_long ip, u_short use_name, u_char *buf);
  域名解析:
  u_long libnet_name_resolve(u_char *ip, u_short use_name);
  获取接口设备IP地址:
  u_long libnet_get_ipaddr(struct libnet_link_int *l,
  const u_char *device, const u_char *ebuf);
  获取接口设备硬件地址:
  struct ether_addr *libnet_get_hwaddr(struct libnet_link_int *l,
  const u_char *device,
  const u_char *ebuf);
  ★ 数据包构造函数
  ARP协议数据包:
  int libnet_build_arp(u_short hrdw, u_short prot, u_short h_len,
  u_short p_len, u_short op, u_char *s_ha,
  u_char *s_pa, u_char *t_ha, u_char *t_pa,
  const u_char *payload, int payload_len,
  u_char *packet_buf);
  DNS协议数据包:
  int libnet_build_dns(u_short id, u_short flags, u_short num_q,
  u_short num_answ_rr, u_short num_auth_rr,
  u_short num_add_rr, const u_char * payload,
  int payload_len, u_char *packet_buf);
  以太网协议数据包:
  int libnet_build_ethernet(u_char *daddr, u_char *saddr, u_short id,
  const u_char *payload, int payload_len,
  u_char *packet_buf);
  ICMP协议数据包(ICMP_ECHO / ICMP_ECHOREPLY):
  int libnet_build_icmp_echo(u_char type, u_char code, u_short id,
  u_short seq, const u_char *payload,
  int payload_len, u_char *packet_buf);
  ICMP协议数据包(ICMP_MASKREQ / ICMP_MASKREPLY):
  int libnet_build_icmp_mask(u_char type, u_char code, u_short id,
  u_short seq, u_long mask,
  const u_char *payload, int payload_len,
  u_char *packet_buf);
  ICMP协议数据包(ICMP_UNREACH):
  int libnet_build_icmp_unreach(u_char type, u_char code,
  u_short orig_len, u_char orig_tos,
  u_short orig_id, u_short orig_frag,
  u_char orig_ttl, u_char orig_prot,
  u_long orig_saddr, u_long orig_daddr,
  const u_char *payload, int payload_len,
  u_char *packet_buf);
  ICMP协议数据包(ICMP_TIMEXCEED):
  int libnet_build_icmp_timeexceed(u_char type, u_char code,
  u_short orig_len, u_char orig_tos,
  u_short orig_id, u_short orig_frag,
  u_char orig_ttl, u_char orig_prot,
  u_long orig_saddr, u_long orig_daddr,
  const u_char *payload, int payload_len,
  u_char *packet_buf);
  ICMP协议数据包(ICMP_REDIRECT):
  int libnet_build_icmp_redirect(u_char type, u_char code, u_long gateway,
  u_short orig_len, u_char orig_tos,
  u_short orig_id, u_short orig_frag,
  u_char orig_ttl, u_char orig_prot,
  u_long orig_saddr, u_long orig_daddr,
  const u_char *payload, int payload_len,
  u_char *packet_buf);
  ICMP协议数据包(ICMP_TSTAMP / ICMP_TSTAMPREPLY):
  int libnet_build_icmp_timestamp(u_char type, u_char code, u_short id,
  u_short seq, n_time otime, n_time rtime,
  n_time ttime, const u_char *payload,
  int payload_len, u_char *packet_buf);
  IGMP协议数据包:
  int libnet_build_igmp(u_char type, u_char code, u_long ip,
  const u_char *payload, int payload_len,
  u_char *packet_buf);
  IP协议数据包:
  int libnet_build_ip(u_short len, u_char tos, u_short ip_id, u_short frag,
  u_char ttl, u_char protocol, u_long saddr,
  u_long daddr, const u_char *payload, int payload_len,
  u_char *packet_buf);
  OSPF路由协议数据包:
  int libnet_build_ospf(u_short len, u_char type, u_long router_id,
  u_long area_id, u_short auth_type,
  const char *payload, int payload_s, u_char *buf);
  OSPF路由协议数据包(Hello):
  int libnet_build_ospf_hello(u_long netmask, u_short interval,
  u_char options, u_char priority,
  u_int dead_interval, u_long des_router,
  u_long backup, u_long neighbor,
  const char *payload, int payload_s,
  u_char *buf);
  OSPF路由协议数据包(DataBase Description (DBD)):
  int libnet_build_ospf_dbd(u_short len, u_char options, u_char type,
  u_int sequence_num, const char *payload,
  int payload_s, u_char *buf);
  OSPF路由协议数据包(Link State Request (LSR)):
  int libnet_build_ospf_lsr(u_int type, u_int ls_id, u_long adv_router,
  const char *payload, int payload_s,
  u_char *buf);
  OSPF路由协议数据包(Link State Update (LSU)):
  int libnet_build_ospf_lsu(u_int num, const char *payload,
  int payload_s, u_char *buf);
  OSPF路由协议数据包(Link State Acknowledgement (LSA)):
  int libnet_build_ospf_lsa(u_short age, u_char options, u_char type,
  u_int ls_id, u_long adv_router,
  u_int sequence_num, u_short len,
  const char *payload, int payload_s,
  u_char *buf);
  OSPF路由协议数据包(OSPF Link Sate NetworkLink State Router):
  int libnet_build_ospf_lsa_net(u_long netmask, u_int router_id,
  const char *payload, int payload_s,
  u_char *buf);
  OSPF路由协议数据包(Link State Router):
  int libnet_build_ospf_lsa_rtr(u_short flags, u_short num, u_int id,
  u_int data, u_char type, u_char tos,
  u_short metric, const char *payload,
  int payload_s, u_char *buf);
  OSPF路由协议数据包(Link State Summary):
  int libnet_build_ospf_lsa_sum(u_long netmask, u_int metric, u_int tos,
  const char *payload, int payload_s,
  u_char *buf);
  OSPF路由协议数据包(Link State AS External):
  int libnet_build_ospf_lsa_as(u_long netmask, u_int metric,
  u_long fwd_addr, u_int tag,
  const char *payload, int payload_s,
  u_char *buf);
  RIP路由协议数据包:
  int libnet_build_rip(u_char cmd, u_char ver, u_short domain,
  u_short addr_fam, u_short route_tag, u_long ip,
  u_long mask, u_long next_hop, u_long metric,
  const u_char *payload, int payload_len,
  u_char *packet_buf);
  TCP协议数据包:
  int libnet_build_tcp(u_short th_sport, u_short th_dport, u_long th_seq,
  u_long th_ack, u_char th_flags, u_short th_win,
  u_short th_urg, const u_char *payload,
  int payload_len, u_char *packet_buf);
  UDP协议数据包:
  int libnet_build_udp(u_short sport, u_short dport, const u_char *payload,
  int payload_len, u_char *packet_buf);
  IP协议数据包选项:
  int libnet_insert_ipo(struct ipoption *opt, u_char opt_len,
  u_char *packet_buf);
  TCP协议数据包选项:
  int libnet_insert_tcpo(struct tcpoption *opt, u_char opt_len,
  u_char *packet_buf);
  ★ 数据包发送函数
  打开raw socket:
  int libnet_open_raw_sock(int protocol);
  关闭raw socket:
  int libnet_close_raw_sock(int socket);
  选择接口设备:
  int libnet_select_device(struct sockaddr_in *sin,
  u_char **device, u_char *ebuf);
  打开链路层接口设备:
  struct libnet_link_int *libnet_open_link_interface(char *device,
  char *ebuf);
  关闭链路层接口设备:
  int libnet_close_link_interface(struct libnet_link_int *l);
  发送IP数据包:
  int libnet_write_ip(int socket, u_char *packet, int packet_size);
  发送链路层数据包:
  int libnet_write_link_layer(struct libnet_link_int *l,
  const u_char *device, u_char *packet,
  int packet_size);
  检验和计算:
  int libnet_do_checksum(u_char *packet, int protocol, int packet_size);
  ★ 相关的支持函数
  随机数种子生成器:
  int libnet_seed_prand();
  获取随机数:
  u_long libnet_get_prand(int modulus);
  16进制数据输出:
  void libnet_hex_dump(u_char * buf, int len, int swap, FILE *stream);
  端口列表链初始化:
  int libnet_plist_chain_new(struct libnet_plist_chain **plist,
  char *token_list);
  获取端口列表链的下一项(端口范围):
  int libnet_plist_chain_next_pair(struct libnet_plist_chain *plist,
  u_short *bport, u_short *eport);
  端口列表链输出显示:
  int libnet_plist_chain_dump(struct libnet_plist_chain *plist);
  获取端口列表链:
  u_char *libnet_plist_chain_dump_string(struct libnet_plist_chain *plist);
  端口列表链内存释放:
  void libnet_plist_chain_free(struct libnet_plist_chain *plist);

=====================================================================================

“ linux下,对link层的访问都是基于AF_PACKET socket的,与BSD的bpf使用设备/dev/pf有所不同,不管是pcap和libnet的实现都是如此。另外libnet和pcap都存在 windows版本,不要将两者与winpcap混淆,还有就是libnet只能发包,pcap只能抓包,winpcap则是收发都能做到。当然 libnet和pcap在windows中与winpcap的底层都所以一样的。”

          libpcap 与libnet可以说是,网络TCP/IP协议族数据包处理的一阴一阳,一个用于抓取数据包,一个用于产生和发送数据包。一个数据包的建立一般分为以下几步:

一.libnet_init()

建立libnet上下文,以下的所有构造数据包的操作基本上都是围绕它进行的。

二.libnet_built_xxx()。在libnet中,建立一个完整的数据包是分步,由高层到低层进行的。如图所示,

建立一个udp数据包并封装成以太网帧,要经过三个步骤,其实也就是要依次调用:

1. libnet_build_udp()
2. libnet_build_ipv4()
3. libnet_build_ethernet()

以上每一个函数都在pblock链表中建立对应协议的pblock(协议块)。
在每一个libnet_built_xxx()中依次调用了三个函数:

1.libnet_pblock_probe(),根据协议块标签ptag数据是否为0调用libnet_pblock_new()来创建新的协议块或者调用lib_pblock_find()来更新已经存在的标签为ptag的协议块。

2.libnet_pblock_append(),将协议头数据挂载到协议块的buf中,修改copied字段,指明已经使用的buf

3.libnet_pblock_update(),获取ptag,填充协议块的其他字段。

三.libnet_write()

此函数调用了libnet_pblock_coalesce(),将所有协议块组建为一个可以发送的数据包(数据帧)。根据开始时设置的发送模式调用不同的socket发送数据。

有些问题笔者没有了解清楚,比如在创建arp数据包的时候为什么要多次调用libnet_pblock_append(),只是完成组建一个arp 头,这样效率就会很低,完全可以组建好整个数据包头以后,一次挂载即可。这里只是笔者的猜测。另外为什么在使用高级模式的时候要调用两次 libnet_pblock_coalesce()。所以这里只能是蜻蜓点水。

详细的讲解请看libnet作者写的 :The Evolution of libnet这篇文章。

 

你可能感兴趣的:(Libnet核心数据结构)