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这篇文章。

 

转载于:https://my.oschina.net/alphajay/blog/5508

Libnet核心数据结构相关推荐

  1. Nginx源码分析:核心数据结构ngx_cycle_t与内存池概述

    nginx源码分析 nginx-1.11.1 参考书籍<深入理解nginx模块开发与架构解析> 核心数据结构与内存池概述 在Nginx中的核心数据结构就是ngx_cycle_t结构,在初始 ...

  2. tensorflow:图(Graph)的核心数据结构与通用函数(Utility function)

    Tensorflow一些常用基本概念与函数(2) 1. 图(Graph)的核心数据结构 tf.Graph.__init__:建立一个空图: tf.Graph.as_default():一个将某图设置为 ...

  3. 01-Redis核心数据结构和高性能原理

    Redis核心数据结构和高性能原理 Redis安装 核心数据结构以及用法 String结构 字符串常用操作 原子加减 应用场景 Hash结构 Hash常用操作 Hash应用场景 Hash结构优缺点 L ...

  4. redis核心数据结构以及他的应用场景

    文章目录 redis核心数据结构 1.string字符串 1.1应用场景 2.hash哈希 2.1应用场景 2.2优缺点 3.list数组列表 3.1应用场景 4.set集合 4.1应用场景 5.zs ...

  5. OpenCV实战(2)——OpenCV核心数据结构

    OpenCV实战(2)--OpenCV核心数据结构 0. 前言 1. cv::Mat 数据结构 1.1 cv::Mat 简介 1.2 cv::Mat 属性 1.3 完整代码示例 2. 探索 cv::M ...

  6. 输入法核心数据结构及算法的设计

    输入法核心数据结构及算法的设计 突然想到了去年腾讯招实习生时笔试的附加题目,就是让你给出一个输入法的设计方案,要求能够提供智能的输入提示,具体题目要求我不太记得了,简单岂见我们只考虑英文输入法~ 问题 ...

  7. 一文读懂以太坊存储数据核心数据结构:MPT

    作者 | JouyPub 来源 | 简书 出品 | 区块链大本营 MPT (Merkle Patricia Tries) 是以太坊存储数据的核心数据结构,它是由 Merkle Tree 和 Patri ...

  8. 二、HBase的核心数据结构 跳跃表、LSM树、布隆过滤器

    文章目录 HBase的核心数据结构 跳跃表(SkipList) LSM树 布隆过滤器 布隆过滤器算法示例 HBase与布隆过滤器 HBase的核心数据结构 HBase的一个列簇(Column Fami ...

  9. linux文件系统的页高速缓存page cache中的核心数据结构address_space

    address_space对象是文件系统中关于内存中页高速缓存的核心数据结构.这篇博客以address_space对象为切入点,分析文件系统的页高速缓存.(这里大部分都是从原作者那里复制过来的,外加上 ...

  10. Redis核心数据结构List应用场景-商品列表、缓存击穿、PV阅读量、抢红包、推送帖子、普通分布式锁、Redis可重入锁与红锁

    List应用场景 Redis之List 一. Redis list命令实战 二.商品列表 高并发的淘宝聚划算实现技术方案 SpringBoot+Redis实现商品列表功能 二.缓存击穿 什么是缓存击穿 ...

最新文章

  1. 零基础全方位学习java的方法
  2. WsusAgent检测脚本
  3. 【ElasticSearch】深入理解 ElasticSearch Doc Values
  4. 分布式架构高可用与高并发那些在工作中常用到的那些变态应用
  5. 周鸿祎评互联网大佬的编程能力:我能排前三,谁排第一?
  6. Mac OS 系统工具使用
  7. vb程序设计编程科学计算机,Visual Basic程序设计教程:计算机类
  8. i510300h和i710750h的区别 哪个好
  9. 【万人千题】结对编程排位赛(第一期) 第一周 排名公布,这也太卷了
  10. lvds输入悬空_lvds接口定义
  11. 计算机怎么盲打键盘,键盘指法,教您盲打及快速打字指法练习的步骤
  12. kz服务器速度显示,CSGO(KZ模式)服务器搭建常见问题答疑(示例代码)
  13. 度中心度(Degree Centrality)
  14. Spring boot视频播放(解决MP4大文件无法播放),整合ffmpeg,用m3u8切片播放。
  15. 大数据分析python r matlab_大数据分析之如何让 Python, R, Matlab 与 Tableau 红尘作伴,玩的潇潇洒洒...
  16. C/C++ 静态库(lib)的概念和使用方法
  17. SaltStack_rhel6.5
  18. springboot使用validator进行参数校验
  19. 一生一芯 预学习阶段 搭建verilator仿真环境 之 示例:双控开关
  20. 00 全国计算机技术与软件专业技术资格(软考)考试介绍

热门文章

  1. Android中使用Fragment实现标题栏(不可滑动)
  2. ios 开发常用技巧
  3. 米家扫地机器人是石头代工的_石头科技的隐忧:智能扫地机器人前有高山 后有追兵...
  4. python代码如何做成应用程序_如何发布你的Python应用程序
  5. 入门嵌入式HTML/CSS/脚本引擎 sciter
  6. 基于XMLHttpRequest封装Ajax请求
  7. 编码基本功:关于构建(build)号,不懂不要装
  8. You need libtool version 1.5.14 or newer to build
  9. cygwin/msys: fatal error LNK1104: 无法打开文件“kernel32.lib”
  10. VS编译NPAPI:jref类型出错