您当前的位置:首页 > 电脑百科 > 软件技术 > 操作系统 > linux

Linux 网络编程之如何使用函数库libnet详解

时间:2020-07-30 09:46:41  来源:  作者:

li.NET 是一个小型的接口函数库,主要用 C 语言写成,提供了低层网络数据包的构造、处理和发送功能。

libnet 的开发目的是:建立一个简单统一的网络编程接口以屏蔽不同操作系统底层网络编程的差别,使得程序员将精力集中在解决关键问题上。

libnet 库提供的接口函数包含 15 种数据包生成器和两种数据包发送器(IP 层和数据链路层)。
提供的接口函数包括:

1)内存管理(分配和释放)函数

2)地址解析函数

3)各种协议类型的数据包构造函数

4)数据包发送函数(IP层和链路层)

5)一些辅助函数,如产生随机数、错误报告、端口列表管理等

详情请看《libnet 函数列表》。

libnet 的安装

Linux 网络编程之如何使用函数库libnet详解

 

流程

利用libnet函数库开发应用程序的基本步骤:

1)数据包内存初始化

2)构造数据包

3)发送数据

4)释放资源

以发送 UDP 数据包为例,流程图如下:

Linux 网络编程之如何使用函数库libnet详解

 

这里需要注意的是组包的顺序,由上层再到底层,这里为 udp -> ip -> mac,不能反过来。

注:需要C/C++ linux高级服务器架构师学习资料私信“资料”(资料包括C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQLredis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等),免费分享

Linux 网络编程之如何使用函数库libnet详解

 

常用函数介绍

以下函数的使用需要包含头文件: libnet.h

libnet_t *libnet_init(int injection_type, char *device, char *err_buf);

功能:

数据包内存初始化及环境建立

参数:

injection_type:构造的类型

LIBNET_LINK,链路层

LIBNET_RAW4,网络接口层(网络层)
LIBNET_LINK_ADV,链路层高级版本

LIBNET_RAW4_ADV, 网络层高级版本

device:网络接口,如 "eth0",或 IP 地址,亦可为 NULL (自动查询搜索)

err_buf:存放出错的信息

返回值:

成功:一个 libnet * 类型的指针,后面的操作都得使用这个指针

失败:NULL

void libnet_destroy(libnet_t *l);

功能:

释放资源

参数:

l:libnet_init() 返回的 libnet * 指针

返回值:

char* libnet_addr2name4(u_int32_t in, u_int8_t use_name);

功能:

将网络字节序转换成点分十进制数串

参数:

in:网络字节序的 ip 地址

use_name:

LIBNET_RESOLVE, 对应主机名

LIBNET_DONT_RESOLVE,对应点分十进制 IPv4 地址

返回值:

成功:点分十进制 ip 地址

失败:NULL

u_int32_t libnet_name2addr4(libnet_t *l, char *host_name, u_int8_t use_name);

功能:

将点分十进制数串转换为网络字节序 ip 地址

参数:

l:libnet_init() 返回的 libnet * 指针

host_name:

LIBNET_RESOLVE, 对应主机名

LIBNET_DONT_RESOLVE,对应点分十进制 IPv4 地址

 

返回值:

成功:网络字节序 ip 地址

失败:-1

u_int32_t libnet_get_ipaddr4(libnet_t *l);

功能:

获取接口设备 ip 地址

参数:

l:libnet_init() 返回的 libnet * 指针

返回值:

成功:网络字节序的 ip 地址

失败:-1

struct libnet_ether_addr* libnet_get_hwaddr(libnet_t *l);

功能:

获取接口设备硬件地址

参数:

l:libnet_init() 返回的 libnet * 指针

返回值:

成功:指向 MAC 地址的指针

失败:NULL

libnet_ptag_t libnet_build_udp(

u_int16_t sp, u_int16_t dp,

u_int16_t len, u_int16_t sum,

u_int8_t *payload, u_int32_t payload_s,

libnet_t *l, libnet_ptag_t ptag);

功能:

构造 udp 数据包

参数:

sp: 源端口号

dp:目的端口号

len:udp 包总长度

sum:校验和,设为 0,libnet 自动填充

payload:负载,为给应用程序发送的文本内容,没有内容时可设置为 NULL

payload_s:负载长度,给应用程序发送文本内容的长度,或为 0

l:libnet_init() 返回的 libnet * 指针

ptag:协议标记,第一次组新的发送包时,这里写 0,同一个应用程序,下一次再组包时,这个位置的值写此函数的返回值。

返回值:

成功:协议标记

失败:-1

libnet_ptag_t libnet_build_tcp(

u_int16_t sp, u_int16_t dp,

u_int32_t seq, u_int32_t ack,

u_int8_t control, u_int16_t win

u_int16_t sum, u_int16_t urg,

u_int16_t len, u_int8_t *payload,

u_int32_t payload_s, libnet_t *l,

libnet_ptag_t ptag );

功能:

构造 tcp 数据包

参数:

sp:源端口号

dp:目的端口号

seq:序号

ack:ack 标记

control:控制标记

win:窗口大小

sum:校验和,设为 0,libnet 自动填充

urg:紧急指针

len:tcp包长度

payload:负载,为给应用程序发送的文本内容,可设置为 NULL

payload_s:负载长度,或为 0

l:libnet_init() 返回的 libnet * 指针

ptag:协议标记,第一次组新的发送包时,这里写 0,同一个应用程序,下一次再组包时,这个位置的值写此函数的返回值。

返回值:

成功:协议标记

失败:-1

libnet_ptag_t libnet_build_tcp_options(

u_int8_t *options,

u_int32_t options_s,

libnet_t *l,

libnet_ptag_t ptag );

功能:

构造 tcp 选项数据包

参数:

options:tcp 选项字符串

options_s:选项长度

l:libnet 句柄,libnet_init() 返回的 libnet * 指针

ptag:协议标记,第一次组新的发送包时,这里写 0,同一个应用程序,下一次再组包时,这个位置的值写此函数的返回值。

返回值:

成功:协议标记

失败:-1

libnet_ptag_t libnet_build_ipv4(

u_int16_t ip_len, u_int8_t tos,

u_int16_t id, u_int16_t flag,

u_int8_t ttl, u_int8_t prot,

u_int16 sum, u_int32_t src,

u_int32_t dst, u_int8_t *payload,

u_int32_t payload_s,libnet_t *l,

libnet_ptag_t ptag );

功能:

构造一个 IPv4 数据包

参数:

ip_len:ip 包总长

tos:服务类型

id:ip 标识

flag:片偏移

ttl:生存时间

prot:上层协议

sum:校验和,设为 0,libnet 自动填充

src:源 ip 地址

dst:目的ip地址

payload:负载,可设置为 NULL(这里通常写 NULL)

payload_s:负载长度,或为 0(这里通常写 0 )

l:libnet 句柄,libnet_init() 返回的 libnet * 指针

ptag:协议标记,第一次组新的发送包时,这里写 0,同一个应用程序,下一次再组包时,这个位置的值写此函数的返回值。

返回值:

成功:协议标记

失败:-1

libnet_ptag_t libnet_build_ipv4_options(

u_int8_t*options, u_int32_t options,

libnet_t*l, libnet_ptag_t ptag);

功能:

构造 IPv4 选项数据包

参数:

options:tcp 选项字符串

options_s:选项长度

l:libnet 句柄,libnet_init() 返回的 libnet * 指针

ptag:协议标记,若为 0,建立一个新的协议

返回值:

成功:协议标记

失败:-1

libnet_ptag_t libnet_build_arp(

u_int16_t hrd, u_int16_t pro,

u_int8_t hln, u_int8_t pln,

u_int16_t op, u_int8_t *sha,

u_int8_t *spa, u_int8_t *tha,

u_int8_t *tpa, u_int8_t *payload,

u_int32_t payload_s, libnet_t *l,

libnet_ptag_t ptag );

功能:

构造 arp 数据包

参数:

hrd:硬件地址格式,ARPHRD_ETHER(以太网)

pro:协议地址格式,ETHERTYPE_IP( IP协议)

hln:硬件地址长度

pln:协议地址长度

op:ARP协议操作类型(1:ARP请求,2:ARP回应,3:RARP请求,4:RARP回应)

sha:发送者硬件地址

spa:发送者协议地址

tha:目标硬件地址

tpa:目标协议地址

payload:负载,可设置为 NULL(这里通常写 NULL)

payload_s:负载长度,或为 0(这里通常写 0 )

l:libnet 句柄,libnet_init() 返回的 libnet * 指针

ptag:协议标记,第一次组新的发送包时,这里写 0,同一个应用程序,下一次再组包时,这个位置的值写此函数的返回值。

返回值:

成功:协议标记

失败:-1

libnet_ptag_t libnet_build_ethernet(

u_int8_t*dst, u_int8_t *src,

 

u_int16_ttype, u_int8_t*payload,

 

u_int32_tpayload_s, libnet_t*l,

 

libnet_ptag_t ptag );

功能:

构造一个以太网数据包

参数:

dst:目的 mac

 

src:源 mac

 

type:上层协议类型

 

payload:负载,即附带的数据,可设置为 NULL(这里通常写 NULL)

 

payload_s:负载长度,或为 0(这里通常写 0 )

 

l:libnet 句柄,libnet_init() 返回的 libnet * 指针

 

ptag:协议标记,第一次组新的发送包时,这里写 0,同一个应用程序,下一次再组包时,这个位置的值写此函数的返回值。

返回值:

成功:协议标记

失败:-1

int libnet_write(libnet_t * l);

功能:

发送数据包

参数:

l:libnet 句柄,libnet_init() 返回的 libnet * 指针

返回值:

成功:发送数据包的长度

失败:返回 -1

使用实例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libnet.h>

int main(int argc, char *argv[])
{
char send_msg[1000] = "";
char err_buf[100] = "";
libnet_t *lib_net = NULL;
int lens = 0;
libnet_ptag_t lib_t = 0;
unsigned char src_mac[6] = {0x00,0x0c,0x29,0x97,0xc7,0xc1};//发送者网卡地址00:0c:29:97:c7:c1
unsigned char dst_mac[6] = {0x74,0x27,0xea,0xb5,0xff,0xd8};//接收者网卡地址‎74-27-EA-B5-FF-D8
char *src_ip_str = "192.168.31.163"; //源主机IP地址
char *dst_ip_str = "192.168.31.248"; //目的主机IP地址
unsigned long src_ip,dst_ip = 0;

lens = sprintf(send_msg, "%s", "this is for the udp test");

lib_net = libnet_init(LIBNET_LINK_ADV, "eth0", err_buf); //初始化
if(NULL == lib_net)
{
perror("libnet_init");
exit(-1);
}

src_ip = libnet_name2addr4(lib_net,src_ip_str,LIBNET_RESOLVE); //将字符串类型的ip转换为顺序网络字节流
dst_ip = libnet_name2addr4(lib_net,dst_ip_str,LIBNET_RESOLVE);

lib_t = libnet_build_udp( //构造udp数据包
8080,
8080,
8+lens,
0,
send_msg,
lens,
lib_net,
0
);

lib_t = libnet_build_ipv4( //构造ip数据包
20+8+lens,
0,
500,
0,
10,
17,
0,
src_ip,
dst_ip,
NULL,
0,
lib_net,
0
);

lib_t = libnet_build_ethernet( //构造以太网数据包
(u_int8_t *)dst_mac,
(u_int8_t *)src_mac,
0x800, // 或者,ETHERTYPE_IP
NULL,
0,
lib_net,
0
);
int res = 0;
res = libnet_write(lib_net); //发送数据包
if(-1 == res)
{
perror("libnet_write");
exit(-1);
}

libnet_destroy(lib_net); //销毁资源

printf("----ok-----n");
return 0;
编译代码时,需要加上 -lnet:
Linux 网络编程之如何使用函数库libnet详解


Tags:Linux   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
Linux 系统日常巡检脚本,巡检内容包含了,磁盘,内存 cpu 进程 文件更改 用户登录等一系列的操作 直接用就行了。报告以邮件发送到邮箱 在log下生成巡检报告。#!/bin/bash# @Aut...【详细内容】
2022-07-14  Tags: Linux  点击:(1)  评论:(0)  加入收藏
linux 文件压缩命令 .Z 使用 compress 压缩文件 .zip 使用zip压缩文件 .gz 使用gzip压缩文件 .bz2 使用bzip2压缩文件 .xz 使用xz压缩文件 .tar 使用tar 工具打包归档,没有压...【详细内容】
2022-07-11  Tags: Linux  点击:(9)  评论:(0)  加入收藏
软链接就类似快捷方式,或者网页上超级链接:跟原文件一样,也同步更新,但不占空间。如果原文件被删除,那磁盘空间立刻释放(文件真没了),软链接本身不会被删除,但由于指向的文件已经不在...【详细内容】
2022-06-24  Tags: Linux  点击:(42)  评论:(0)  加入收藏
下载软件以及选择适合的Linux系统VMware Workstation 下载地址: 涓嬭浇 VMware Workstation Pro | CN阿里巴巴镜像源地址:阿里巴巴开源镜像站-OPSX镜像站-阿里云开发者社区配...【详细内容】
2022-06-14  Tags: Linux  点击:(47)  评论:(0)  加入收藏
1、修改配置文件此处yaml文件,不同机器可能略有不同,我当前机器的配置文件如下。1 root@hanyw:/etc/netplan# cat 00-installer-config.yaml2 # This is the network config w...【详细内容】
2022-06-01  Tags: Linux  点击:(110)  评论:(0)  加入收藏
服务器加固是通过各种方法增强服务器安全性的过程。我们有很多步骤来保护服务器。通过保护您的 Linux 系统免受黑客、破解者和攻击者的侵害,让您和您的公司远离您!您可以通过...【详细内容】
2022-05-25  Tags: Linux  点击:(42)  评论:(0)  加入收藏
Linux 内核 5.18 包括一个英特尔驱动程序,该驱动程序可能允许芯片制造商在用户支付许可证后启用新的芯片功能。Linux的创建者Linux Torvalds在通过开发的最后一周后宣布了稳...【详细内容】
2022-05-24  Tags: Linux  点击:(46)  评论:(0)  加入收藏
Kali Linux 2022.2 是今年的第二次更新,增加了一些有趣的内容。Kali Linux 不是你寻常使用的 Linux 发行版。它是专门为渗透测试和道德黑客学习及实验而量身打造的。在新的 K...【详细内容】
2022-05-19  Tags: Linux  点击:(141)  评论:(0)  加入收藏
一、概述这曾经发生在你身上吗?你意识到你错误地删除了一个文件---要么通过Del键,要么在命令行中使用rm。在第一种情况下,您可以使用回站站(GNOME界面),然后将其恢复到原始位置。...【详细内容】
2022-05-09  Tags: Linux  点击:(88)  评论:(0)  加入收藏
安装 依次执行以下命令# wget https://file.cnxiaobai.com/Linux/Safe-rm/safe-rm-0.13.tar.gz# tar -zxvf safe-rm-0.13.tar.gz -C /usr/local/# mv safe-rm-0.13/ safe-rm...【详细内容】
2022-04-25  Tags: Linux  点击:(68)  评论:(0)  加入收藏
▌简易百科推荐
在Linux中,创建一个文件时,该文件的拥有者都是创建该文件的用户。该文件用户可以修改该文件的拥有者及用户组别;或者在root用户下,这样可以修改任何文件的拥有者及用户组。而修...【详细内容】
2022-07-14  网站建设和维护    Tags:文件   点击:(5)  评论:(0)  加入收藏
Linux 系统日常巡检脚本,巡检内容包含了,磁盘,内存 cpu 进程 文件更改 用户登录等一系列的操作 直接用就行了。报告以邮件发送到邮箱 在log下生成巡检报告。#!/bin/bash# @Aut...【详细内容】
2022-07-14  IT运维社区    Tags:巡检脚本   点击:(1)  评论:(0)  加入收藏
引入在linux内核中,各个子系统之间有很强的相互关系,某些子系统可能对其他子系统产生的事件比较感兴趣。因此内核引入了notifier机制,当然了notifier机制只能用在内核子系统之...【详细内容】
2022-07-14  原天堂没有代码    Tags:Notifier   点击:(4)  评论:(0)  加入收藏
一 前言内存对于系统资源来说,非常重要,内存问题可以导致系统延迟增大,系统内存泄漏,进程被kill等多种严重问题,所以分析进程的内存占用很有必要。本文重点分析了程序中动态申请...【详细内容】
2022-07-12  码农世界    Tags:内存   点击:(8)  评论:(0)  加入收藏
linux 文件压缩命令 .Z 使用 compress 压缩文件 .zip 使用zip压缩文件 .gz 使用gzip压缩文件 .bz2 使用bzip2压缩文件 .xz 使用xz压缩文件 .tar 使用tar 工具打包归档,没有压...【详细内容】
2022-07-11  斩获必有所得    Tags:Linux 压缩   点击:(9)  评论:(0)  加入收藏
linux重命名文件和文件夹可以使用mv命令来实现。mv命令:Linux mv 命令用来为文件或目录改名、或将文件或目录移入其它位置。实例:比如:before.txt是修改之前的文件名,after.txt...【详细内容】
2022-07-07  网站建设和维护    Tags:linux   点击:(38)  评论:(0)  加入收藏
一、top &ndash; 实时显示系统运行状态top 命令的功能是用于实时显示系统运行状态,包含处理器、内存、服务、进程等重要资源信息。运维工程师们常常会把 top 命令比作是 “加...【详细内容】
2022-07-06  特斯汀软件测试    Tags:Linux   点击:(28)  评论:(0)  加入收藏
运行c语言文件,执行如下命令:sudo gedit test.cgcc -o test 文件名.c./test运行 .sh文件首先要开启权限,然后执行如下命令chmod 777 文件名.sh./文件名.sh...【详细内容】
2022-07-05  网站建设和维护    Tags:linux   点击:(29)  评论:(0)  加入收藏
前言学习linux少不了和vim打交道,今天我们就来了解一下什么是vim,如何高效使用vim以及如何配置vim。vi和vim都是linux下多模式的编辑器,两者关系类似于c/c++的关系,vim是vi的升...【详细内容】
2022-07-04  Java架构学习指南    Tags:vim   点击:(26)  评论:(0)  加入收藏
Crontab是linux下定时调度配置文件,通过它,我们可以让系统的程序、脚本、命令、任务按设定的时间、间隔、周期循环的运行。 在Crontab里时间粒度最小的是分钟。也就是说,通过Cr...【详细内容】
2022-07-04  网站建设和维护    Tags:Crontab   点击:(59)  评论:(0)  加入收藏
站内最新
站内热门
站内头条