⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 527.htm

📁 unix高级编程原吗
💻 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="528.htm">下一篇</a>]
<hr><p align="left"><small>发信人: scz (小四), 信区: Security <br>

标  题: libnet使用举例(2) <br>

发信站: 武汉白云黄鹤站 (Wed Jul 26 16:46:31 2000), 站内信件 <br>

作者:小四 < mailto: scz@isbase.com > <br>

主页:http://www.isbase.com <br>

日期:2000-07-26 20:10 <br>

这篇先介绍libnet_init_packet()函数,其函数原型如下: <br>

int libnet_init_packet ( size_t p_size, u_char ** buf ); <br>

该函数实际调用了malloc函数做了一次内存分配,第一个形参就是指定内存分配的大 <br>

小。第二个形参用于返回指向这块内存的指针。如果p_size被省略或为负值,将默认 <br>

使用LIBNET_MAX_PACKET。内存分配成功后初始化成0,函数返回1,否则返回-1。显 <br>

然有一个对应的函数释放内存: <br>

int libnet_destroy_packet ( u_char ** buf ); <br>

这个函数除了调用free(),目前没有其他动作。 <br>

在/usr/include/libnet/libnet-macros.h中有如下定义: <br>

#define LIBNET_MAX_PACKET   0xffff <br>

事实上我们完全可以不使用这两个函数,它们并没有操作什么内部数据结构,仅仅为 <br>

了统一封装起见使用它们。 <br>

针对p_size,libnet在/usr/include/libnet/libnet-headers.h中定义了一批宏: <br>

#define LIBNET_ARP_H           0x1c    /* ARP header:          28 bytes */ <br>

#define LIBNET_DNS_H           0xc     /* DNS header base:     12 bytes */ <br>

#define LIBNET_ETH_H           0xe     /* Etherner header:     14 bytes */ <br>

#define LIBNET_ICMP_H          0x4     /* ICMP header base:     4 bytes */ <br>



#define LIBNET_IGMP_H          0x8     /* IGMP header:          8 bytes */ <br>

#define LIBNET_IP_H            0x14    /* IP header:           20 bytes */ <br>

#define LIBNET_RIP_H           0x18    /* RIP header base:     24 bytes */ <br>

#define LIBNET_TCP_H           0x14    /* TCP header:          20 bytes */ <br>

#define LIBNET_UDP_H           0x8     /* UDP header:           8 bytes */ <br>

上面仅仅列举了常用的几个宏,虽然不是必须使用,但建议尽量使用宏。 <br>

接下来介绍两个操作raw_socket的函数: <br>

int libnet_open_raw_sock ( int protocol ); <br>

int libnet_close_raw_sock ( int fd ); <br>

libnet_open_raw_sock()打开IPv4上指定协议类型的raw_socket,同时设置了 <br>

IP_HDRINCL选项,成功则返回socket,失败返回-1。libnet_close_raw_sock()关闭 <br>

前者打开的raw_socket,成功则返回1,失败返回-1。 <br>

实际上,形参protocol对应的就是socket()函数的第三个形参,所以可以指定 <br>

IPPROTO_RAW、IPPROTO_ICMP、IPPROTO_TCP等,当然还要看内核是否支持这样的指定。 <br>

  <br>

我们可以类似W.Richard.Stevens那样处理,封装一下这个函数: <br>

-------------------------------------------------------------------------- <br>

int Libnet_open_raw_sock ( int protocol ) <br>

{ <br>

    int s; <br>

    if ( ( s = libnet_open_raw_sock( protocol ) ) == -1 ) <br>

    { <br>

    { <br>

        libnet_error( LIBNET_ERR_FATAL, "Can't open raw socket %08x\n", proc <br>

otol <br>

 ); <br>

    } <br>

    return( s ); <br>

}  /* end of Libnet_open_raw_sock */ <br>

-------------------------------------------------------------------------- <br>

在不使用libnet库编程的时候,打开raw_socket,接下来就是要构造IP头,libnet使 <br>

用如下函数完成这个工作: <br>

int libnet_build_ip ( u_short len, u_char tos, u_short id, u_short frag, <br>

                      u_char ttl, u_char prot, u_long saddr, u_long daddr, <br>

                      const u_char * payload, int payload_s, u_char * buf ); <br>

  <br>

形参len指定的是IP数据区长度,既不是IP头部长度,也不是IP报文总长度,并没有 <br>

一个结构成员对应这个形参,习惯了socket编程的兄弟要注意。saddr和daddr均以网 <br>

络字节序提供,也就是big-endian序。payload指向可选的IP选项以及可能出现的填 <br>

充,payload_s指定这些数据的长度。至于最后一个参数buf,指向通过 <br>

libnet_init_packet分配并初始化过的数据区,将来包括IP头都要出现在该数据区, <br>

此时buf指向的实际是IP头。当然这里举例是以IP报文举例,如果是其他类型的报文, <br>

就不是这个结论了。不要把payload和IP数据区混淆了,否则libnet构造IP头的时候 <br>

出现混乱。 <br>

libnet使用下面这个函数进一步在IP报文上构造TCP头: <br>



int libnet_build_tcp ( u_short sport, u_short dport, u_long seq, <br>

                       u_long ack, u_char control, u_short win, u_short urg, <br>

  <br>

                       const u_char * payload, int payload_s, u_char * buf ) <br>

; <br>

形参control对应我们熟悉的SYN、ACK、RST等标志的逻辑或。最后一个形参需要指向 <br>

一个已分配好的数据区,TCP头从该指针开始。类似IP层,这里payload指向可选的 <br>

TCP选项以及可能出现的填充,不要和TCP数据区相混淆。 <br>

接下来可能是你曾经如许头疼的TCP/UDP校验和计算问题: <br>

int libnet_do_checksum ( u_char * buf, int protocol, int len ); <br>

该函数用于计算传输层校验和并填写到适当头部位置,包括TCP/UDP校验和的计算。 <br>

显然该函数应该在传输层报文包括数据区构造完毕之后被调用,否则计算得到的校验 <br>

和必将因为传输层数据区的改变而失效。成功则返回1,否则返回-1。第一个形参需 <br>

要指向IP头,而不是TCP头什么的,第二个形参指定传输层协议类型,第三个形参指 <br>

定了IP数据区长度,不包括IP头部。 <br>

说点题外话,在raw_socket层上,IP头部校验和总是由内核亲自计算,但是如果直接 <br>

在链路层构造报文,必须显式计算IP头部校验和。 <br>

对于所有的build_*函数,如果buf指针为NULL,运行时会检查到这个错误并返回-1。 <br>

但是payload_s超长、头部超出预先分配大小等等,是无法检测到的,必须意识到这 <br>

个问题所在。 <br>

计算TCP/UDP头部校验和相对其他校验和的计算是显得复杂了点,却也没有想象的那 <br>

么的可怕,主要是现在很多书上并没有解释清楚、翻译清楚原意,可以参考许多现成 <br>



的源代码。libnet库提供这么一个封装过的函数固然不错,还是希望你能真正了解校 <br>

验和的计算过程。 <br>

下面要做的是把这样一个精心构造的报文丢到网络上去: <br>

int libnet_write_ip ( int sock, u_char * packet, int len ); <br>

第一个形参即libnet_open_raw_sock()的返回值,第二个形参指向IP头,第三个形参 <br>

指明了整个IP报文总长度。函数返回值对应发送出去的字节数,注意不见得构造多大 <br>

的报文就能发送出去这么大的报文,必须检查返回值。 <br>

到此为止,我们企图编写一个syn-flood的主力舰队都到齐了,至于如何编队、何时 <br>

出发且听下回分解,总得给我个灌水的机会吧,都一次灌完了如何长我那可怜的经验 <br>

值呢? <br>

<待续> <br>

-- <br>

            也许有一天,他再从海上蓬蓬的雨点中升起, <br>

            飞向西来,再形成一道江流,再冲倒两旁的石壁, <br>

            再来寻夹岸的桃花。然而,我不敢说来生,也不敢信来生...... <br>

</small><hr>
<p align="center">[<a href="index.htm">回到开始</a>][<a href="519.htm">上一层</a>][<a href="528.htm">下一篇</a>]
<p align="center"><a href="http://cterm.163.net">欢迎访问Cterm主页</a></p>
</table>
</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -