概述
通過《原始套接字實例:發送 UDP 數據包》的學習,我們組 UDP 數據包時常考慮字節流順序、校驗和計算等問題,有時候會比較繁瑣,那麼,有沒有一種更簡單的方法呢?答案是:借助 libnet 函數庫。
libnet 是一個小型的接口函數庫,主要用 C 語言寫成,提供了低層網絡數據包的構造、處理和發送功能。
libnet 的開發目的是:建立一個簡單統一的網絡編程接口以屏蔽不同操作系統底層網絡編程的差別,使得程序員將精力集中在解決關鍵問題上。
libnet 庫提供的接口函數包含 15 種數據包生成器和兩種數據包發送器(IP 層和數據鏈路層)。
源代碼下載:
------------------------------------------分割線------------------------------------------
免費下載地址在 http://linux.linuxidc.com/
用戶名與密碼都是www.linuxidc.com
具體下載目錄在 /2015年資料/4月/13日/Linux 網絡編程—— libnet 使用指南/
下載方法見 http://www.linuxidc.com/Linux/2013-07/87684.htm
------------------------------------------分割線------------------------------------------
提供的接口函數包括:
1)內存管理(分配和釋放)函數
2)地址解析函數
3)各種協議類型的數據包構造函數
4)數據包發送函數(IP層和鏈路層)
5)一些輔助函數,如產生隨機數、錯誤報告、端口列表管理等
詳情請看《libnet 函數列表》http://www.linuxidc.com/Linux/2015-04/116152.htm。
libnet 的安裝
流程
利用libnet函數庫開發應用程序的基本步驟:
1)數據包內存初始化
2)構造數據包
3)發送數據
4)釋放資源
以發送 UDP 數據包為例,流程圖如下:
這裡需要注意的是組包的順序,由上層再到底層,這裡為 udp -> ip -> mac,不能反過來。
常用函數介紹
以下函數的使用需要包含頭文件 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
更多詳情見請繼續閱讀下一頁的精彩內容: http://www.linuxidc.com/Linux/2015-04/116151p2.htm