📄 536.htm
字号:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
<title>CTerm非常精华下载</title>
</head>
<body bgcolor="#FFFFFF">
<table border="0" width="100%" cellspacing="0" cellpadding="0" height="577">
<tr><td width="32%" rowspan="3" height="123"><img src="DDl_back.jpg" width="300" height="129" alt="DDl_back.jpg"></td><td width="30%" background="DDl_back2.jpg" height="35"><p align="center"><a href="http://apue.dhs.org"><font face="黑体"><big><big>apue</big></big></font></a></td></tr>
<tr>
<td width="68%" background="DDl_back2.jpg" height="44"><big><big><font face="黑体"><p align="center"> ● UNIX网络编程 (BM: clown) </font></big></big></td></tr>
<tr>
<td width="68%" height="44" bgcolor="#000000"><font face="黑体"><big><big><p align="center"></big></big><a href="http://cterm.163.net"><img src="banner.gif" width="400" height="60" alt="banner.gif"border="0"></a></font></td>
</tr>
<tr><td width="100%" colspan="2" height="100" align="center" valign="top"><br><p align="center">[<a href="index.htm">回到开始</a>][<a href="519.htm">上一层</a>][<a href="537.htm">下一篇</a>]
<hr><p align="left"><small>发信人: scz (小四), 信区: Security WWW-POST <br>
标 题: libnet使用举例(12) <br>
发信站: 武汉白云黄鹤站 (Fri Dec 15 10:08:22 2000) , 站内信件 <br>
作者:小四 < mailto: scz@nsfocus.com > <br>
主页:http://www.nsfocus.com <br>
日期:2000-12-12 16:20 <br>
本系列1-11都是raw socket layer programming,今天介绍link layer programming, <br>
<br>
下面是链路层编程用到的部分关键函数: <br>
int libnet_build_ethernet ( u_char * daddr, u_char * saddr, u_short id, <br>
const u_char * payload, int payload_s, <br>
u_char * buf ); <br>
该函数用于构造以太网物理帧,daddr、saddr分别指向一个6字节数组,对应物理帧 <br>
的目标MAC、源MAC。id指定物理帧类型,有效值如下: <br>
值 代表的类型 <br>
ETHERTYPE_PUP PUP protocol <br>
ETHERTYPE_IP IP protocol <br>
ETHERTYPE_ARP ARP protocol <br>
ETHERTYPE_REVARP Reverse ARP protocol <br>
ETHERTYPE_VLAN IEEE VLAN tagging <br>
ETHERTYPE_LOOPBACK Used to test intefaces <br>
payload为NULL,payload_s为零。最后一个参数buf,指向通过libnet_init_packet <br>
分配并初始化过的数据区,此时buf指向的实际是物理帧头。 <br>
必须意识到,某些链路层接口(比如BPF)不允许伪装物理帧源MAC,除非你自己更改内 <br>
核。 <br>
int libnet_build_arp ( u_short hrd, u_short pro, u_short hln, u_short pln, <br>
u_short op, u_char * sha, u_char * spa, u_char * tha, <br>
<br>
u_char * tpa, const u_char * payload, int payload_s, <br>
u_char * buf ); <br>
该函数用于构造ARP报文。对于常见应用来说,hrd为ARPHRD_ETHER,pro为 <br>
ETHERTYPE_IP,hln为ETHER_ADDR_LEN(就是6,MAC地址长度),pln为4(IPv4地址长度), <br>
<br>
op指定ARP操作类型,有效取值有ARPOP_REQUEST、ARPOP_REPLY、ARPOP_REVREQUEST、 <br>
ARPOP_REVREPLY、ARPOP_INVREQUEST 以及 ARPOP_INVREPLY,我不知道最后两种类型 <br>
是什么意思,这里op以主机字节序提供,比如0x0002就是ARPOP_REPLY。sha指定发送 <br>
方MAC地址,spa指定发送方IP地址,tha指定接收方MAC地址,tpa指定接收方IP地址, <br>
payload为NULL,payload_s为零。形参buf需要指向一个已分配好的数据区,ARP层从 <br>
该指针开始。 <br>
struct libnet_link_int * libnet_open_link_interface ( char * device, char * <br>
ebuf <br>
); <br>
int libnet_close_link_interface ( struct libnet_link_int * l ); <br>
如果需要直接发送链路层物理帧,必须事先使用libnet_open_link_interface()打开 <br>
接口设备。device指定接口设备名,对于Linux就是"eth0"一类的名字。ebuf通常定 <br>
义如下: <br>
char err_buf[ LIBNET_ERRBUF_SIZE ]; <br>
/usr/include/libnet/libnet-macros.h: <br>
#define LIBNET_ERRBUF_SIZE 256 <br>
如果调用失败返回NULL,成功则填充一个libnet_link_int结构,并返回这个结构指 <br>
针。libnet_close_link_interface()与libnet_open_link_interface()对应,关闭 <br>
先前打开的接口设备,失败返回-1,成功返回1。 <br>
int libnet_select_device ( struct sockaddr_in * sin, u_char ** device, u_cha <br>
r * <br>
ebuf ); <br>
如果你不能确定libnet_open_link_interface()第一形参使用什么样的接口设备名, <br>
可以调用libnet_select_device()获取它。后者遍历接口链表,从中选择第一个可用 <br>
的非回送接口。sin、device不得为NULL,sin必须指向一个sockaddr_in结构, <br>
device必须指向一个指针,*sin、*device的初值无所谓。调用成功返回1,*device <br>
指向一个有效接口设备名,可以用于后续的libnet_open_link_interface()调用。失 <br>
败返回-1,ebuf将包含失败原因。 <br>
struct ether_addr * libnet_get_hwaddr ( struct libnet_link_int * l, <br>
const u_char * device, <br>
const u_char * ebuf ); <br>
第一形参来自libnet_open_link_interface(),device指向接口设备名。成功则返回 <br>
指定接口的MAC地址,失败返回0(NULL),ebuf将包含失败原因。 <br>
int libnet_write_link_layer ( struct libnet_link_int * l, const u_char * dev <br>
ice, <br>
u_char * buf, int len ); <br>
该函数用于直接发送链路层物理帧,第一形参来自libnet_open_link_interface(), <br>
device指向接口设备名。buf指向物理帧头,一般由libnet_init_packet分配并初始 <br>
化,libnet_destroy_packet()负责释放。len指定物理帧长度。失败返回-1,否则返 <br>
回发送出去的字节数。 <br>
写个arpsend程序来验证这些可爱的函数,recvMac必须为真实有效的MAC地址,否则 <br>
谁接收呢。sendMac根据需要可以伪装,但链路层支持为BPF时无法伪装,除非自己更 <br>
改内核。关于ARP协议本身的讨论太多,不做进一步说明。没有提供随机数支持,如 <br>
果你自己有特殊需要,可以参看本系列1-11中反复使用的技术,也可以直接使用 <br>
libnet本身提供的libnet_seed_prand()、libnet_get_prand()函数。如果有时间, <br>
会提供另外一个程序演示这两个随机函数。 <br>
-------------------------------------------------------------------------- <br>
/* <br>
* File : arpsend program for I386/Linux using libnet <br>
* Version: 0.01 aleph <br>
* Author : scz < mailto: scz@nsfocus.com > <br>
* : http://www.nsfocus.com <br>
* Complie: gcc -O3 -o arpsend arpsend.c `libnet-config --defines --cflags` <br>
`lib <br>
net-config --libs` -Wall <br>
* Usage : ./arpsend --recv 000000111111 --si 192.168.8.90 --sm 00000022222 <br>
2 -- <br>
num 30 <br>
* Date : 2000-12-13 16:43 <br>
*/ <br>
/******************************************************************* <br>
* * <br>
* Head File * <br>
* * <br>
*******************************************************************/ <br>
#define _GNU_SOURCE <br>
#include <stdio.h> <br>
#include <stdlib.h> <br>
#include <getopt.h> /* for getopt() */ <br>
#include <libnet.h> <br>
/******************************************************************* <br>
* * <br>
* Macro * <br>
* * <br>
*******************************************************************/ <br>
#define SUCCESS 0 <br>
#define FAILURE -1 <br>
#define DEFAULTARPNUMBER 0x5 /* 缺省发送ARP报文数目 */ <br>
/******************************************************************* <br>
* * <br>
* Static Global Var * <br>
* * <br>
*******************************************************************/ <br>
static u_char * packet = NULL; <br>
static size_t packet_size = LIBNET_ETH_H + LIBNET_ARP_H; <br>
static struct libnet_link_int * link_handler = NULL; <br>
/******************************************************************* <br>
* * <br>
* Function Prototype * <br>
* * <br>
*******************************************************************/ <br>
static void Libnet_close_link_interface ( struct libnet_link_int * l ); <br>
/* <br>
static void Libnet_get_hwaddr ( struct libnet_link_int * l, cons <br>
t u_ <br>
char * device, u_char * mac ); <br>
*/ <br>
static void Libnet_init_packet ( size_t p_size, u_char ** buf ); <br>
static struct libnet_link_int * Libnet_open_link_interface ( char * device ) <br>
; <br>
; <br>
static void Libnet_select_device ( u_char ** device ); <br>
static void Libnet_write_link_layer ( struct libnet_link_int * l, cons <br>
t u_ <br>
char * device, u_char * buf, int len ); <br>
static char * Strncpy ( char * dest, const char * src, s <br>
ize_ <br>
t n ); <br>
static void usage ( char * arg ); <br>
/*----------------------------------------------------------------------*/ <br>
static void Libnet_close_link_interface ( struct libnet_link_int * l ) <br>
{ <br>
if ( libnet_close_link_interface( l ) == -1 ) <br>
{ <br>
libnet_error( LIBNET_ERR_WARNING, "libnet_close_link_interface faile <br>
d\n" <br>
); <br>
} <br>
return; <br>
} /* end of Libnet_close_link_interface */ <br>
/* <br>
static void Libnet_get_hwaddr ( struct libnet_link_int * l, const u_char * d <br>
evic <br>
evic <br>
e, u_char * mac ) <br>
{ <br>
char err_buf[ LIBNET_ERRBUF_SIZE ]; <br>
struct ether_addr * m = NULL; <br>
if ( mac == NULL ) <br>
{ <br>
return; <br>
} <br>
m = libnet_get_hwaddr( l, device, err_buf ); <br>
if ( m == NULL ) <br>
{ <br>
libnet_error( LIBNET_ERR_WARNING, "libnet_get_hwaddr failed: %s\n", <br>
err_ <br>
buf ); <br>
} <br>
else <br>
{ <br>
memmove( mac, ( u_char * )m, 6 ); <br>
} <br>
return; <br>
} <br>
*/ <br>
*/ <br>
static void Libnet_init_packet ( size_t p_size, u_char ** buf ) <br>
{ <br>
if ( libnet_init_packet( p_size, buf ) == -1 ) <br>
{ <br>
libnet_error( LIBNET_ERR_FATAL, "Can't initialize packet\n" ); <br>
} <br>
return; <br>
} /* end of Libnet_init_packet */ <br>
static struct libnet_link_int * Libnet_open_link_interface ( char * device ) <br>
<br>
{ <br>
struct libnet_link_int * link = NULL; <br>
char err_buf[ LIBNET_ERRBUF_SIZE ]; <br>
if ( ( link = libnet_open_link_interface( device, err_buf ) ) == NULL ) <br>
{ <br>
libnet_error( LIBNET_ERR_FATAL, "libnet_open_link_interface failed: <br>
%s\n <br>
", err_buf ); <br>
} <br>
return( link ); <br>
} /* end of Libnet_open_link_interface */ <br>
static void Libnet_select_device ( u_char ** device ) <br>
{ <br>
struct sockaddr_in sin; <br>
char err_buf[ LIBNET_ERRBUF_SIZE ]; <br>
if ( device == NULL ) <br>
{ <br>
libnet_error( LIBNET_ERR_FATAL, "Can't locate a device\n" ); <br>
} <br>
if ( libnet_select_device( &sin, device, err_buf ) == -1 ) <br>
{ <br>
libnet_error( LIBNET_ERR_FATAL, "libnet_select_device failed: %s\n", <br>
err <br>
_buf ); <br>
} <br>
fprintf( stderr, "[ device --> %s ]\n", *device ); <br>
return; <br>
} /* end of Libnet_select_device */ <br>
static void Libnet_write_link_layer ( struct libnet_link_int * l, <br>
const u_char * device, u_char * buf, i <br>
nt l <br>
en ) <br>
{ <br>
int w; <br>
int w; <br>
if ( ( w = libnet_write_link_layer( l, device, buf, len ) ) < len ) <br>
{ <br>
libnet_error( LIBNET_ERR_WARNING, "libnet_write_link_layer only wrot <br>
e %d <br>
bytes\n", w ); <br>
} <br>
return; <br>
} /* end of Libnet_write_link_layer */ <br>
static char * Strncpy ( char * dest, const char * src, size_t n ) <br>
{ <br>
char * pChar; <br>
pChar = strncpy( dest, src, n ); <br>
if ( pChar == NULL ) <br>
{ <br>
exit( FAILURE ); <br>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -