Linux网络编程——原始套接字编程
原始套接字编程和之前的 UDP 编程差不多,无非就是创建一个套接字后,通过这个套接字接收数据或者发送数据。区别在于,原始套接字可以自行组装数据包(伪装本地 IP,本地 MAC),可以接收本机网卡上所有的数据帧(数据包)。另外,必须在管理员权限下才能使用原始套接字。
int socket ( int family, int type, int protocol );
参数:
family:协议族 这里写 PF_PACKET
type: 套接字类,这里写 SOCK_RAW
protocol:协议类别,指定可以接收或发送的数据包类型,不能写 “0”,取值如下,注意,传参时需要用 htons() 进行字节序转换。
ETH_P_IP:IPV4数据包
ETH_P_ARP:ARP数据包
ETH_P_ALL:任何协议类型的数据包
返回值:
成功( >0 ):套接字,这里为链路层的套接字
失败( <0 ):出错
实例如下:
// 所需头文件
#include <sys/socket.h>
#include <netinet/ether.h>
#include <stdio.h> // perror int main(int argc,char *argv[])
{
int sock_raw_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL) ); if(sock_raw_fd < ){
perror("socket");
return -;
} return ;
}
获取链路层的数据包:
ssize_t recvfrom( int sockfd,
void *buf,
size_t nbytes,
int flags,
struct sockaddr *from,
socklen_t *addrlen );
参数:
sockfd: 原始套接字
buf: 接收数据缓冲区
nbytes: 接收数据缓冲区的大小
flags: 套接字标志(常为0)
from: 这里没有用,写 NULL
addrlen:这里没有用,写 NULL
返回值:
成功:接收到的字符数
失败:-1
实例如下:
#include <stdio.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <netinet/ether.h> int main(int argc,char *argv[])
{
unsigned char buf[] = {};
int sock_raw_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); //获取链路层的数据包
int len = recvfrom(sock_raw_fd, buf, sizeof(buf), , NULL, NULL);
printf("len = %d\n", len); return ;
}
混杂模式
默认的情况下,我们接收数据,目的地址是本地地址,才会接收。有时候我们想接收所有经过网卡的所有数据流,而不论其目的地址是否是它,这时候我们需要设置网卡为混杂模式。
网卡的混杂模式一般在网络管理员分析网络数据作为网络故障诊断手段时用到,同时这个模式也被网络黑客利用来作为网络数据窃听的入口。在 Linux 操作系统中设置网卡混杂模式时需要管理员权限。在 Windows 操作系统和 Linux 操作系统中都有使用混杂模式的抓包工具,比如著名的开源软件 Wireshark。
通过命令给 Linux 网卡设置混杂模式(需要管理员权限)
设置混杂模式:ifconfig eth0 promisc
取消混杂模式:ifconfig eth0 -promisc
通过代码给 Linux 网卡设置混杂模式
代码如下:
struct ifreq ethreq; //网络接口地址 strncpy(ethreq.ifr_name, "eth0", IFNAMSIZ); //指定网卡名称
if(- == ioctl(sock_raw_fd, SIOCGIFINDEX, ðreq)) //获取网络接口
{
perror("ioctl");
close(sock_raw_fd);
exit(-);
} ethreq.ifr_flags |= IFF_PROMISC;
if(- == ioctl(sock_raw_fd, SIOCSIFINDEX, ðreq)) //网卡设置混杂模式
{
perror("ioctl");
close(sock_raw_fd);
exit(-);
}
发送自定义的数据包:
ssize_t sendto( int sockfd,
const void *buf,
size_t nbytes,int flags,
const struct sockaddr *to,
socklen_t addrlen );
参数:
sockfd: 原始套接字
buf: 发送数据缓冲区
nbytes: 发送数据缓冲区的大小
flags: 一般为 0
to: 本机网络接口,指发送的数据应该从本机的哪个网卡出去,而不是以前的目的地址
addrlen:to 所指向内容的长度
返回值:
成功:发送数据的字符数
失败: -1
本机网络接口的定义
发送完整代码如下:
struct sockaddr_ll sll; //原始套接字地址结构
struct ifreq ethreq; //网络接口地址 strncpy(ethreq.ifr_name, "eth0", IFNAMSIZ); //指定网卡名称
if(- == ioctl(sock_raw_fd, SIOCGIFINDEX, ðreq)) //获取网络接口
{
perror("ioctl");
close(sock_raw_fd);
exit(-);
} /*将网络接口赋值给原始套接字地址结构*/
bzero(&sll, sizeof(sll));
sll.sll_ifindex = ethreq.ifr_ifindex; // 发送数据
// send_msg, msg_len 这里还没有定义,模拟一下
int len = sendto(sock_raw_fd, send_msg, msg_len, , (struct sockaddr *)&sll, sizeof(sll));
if(len == -)
{
perror("sendto");
}
这里头文件情况如下:
#include <net/if.h>// struct ifreq
#include <sys/ioctl.h> // ioctl、SIOCGIFADDR
#include <sys/socket.h> // socket
#include <netinet/ether.h> // ETH_P_ALL
#include <netpacket/packet.h> // struct sockaddr_ll
转自:http://blog.csdn.net/tennysonsky/article/details/44676377
Linux网络编程——原始套接字编程的更多相关文章
- Linux网络编程——原始套接字实例:MAC 头部报文分析
通过<Linux网络编程——原始套接字编程>得知,我们可以通过原始套接字以及 recvfrom( ) 可以获取链路层的数据包,那我们接收的链路层数据包到底长什么样的呢? 链路层封包格式 M ...
- Linux Socket 原始套接字编程
对于linux网络编程来说,可以简单的分为标准套接字编程和原始套接字编程,标准套接字主要就是应用层数据的传输,原始套接字则是可以获得不止是应用层的其他层不同协议的数据.与标准套接字相区别的主要是要开发 ...
- UNIX网络编程——原始套接字(dos攻击)
原始套接字(SOCK_RAW).应用原始套接字,我们可以编写出由TCP和UDP套接字不能够实现的功能. 注意原始套接字只能够由有 root权限的人创建. 可以参考前面的博客<<UNIX网络 ...
- UNIX网络编程——原始套接字的魔力【续】
如何从链路层直接发送数据帧 上一篇里面提到的是从链路层"收发"数据,该篇是从链路层发送数据帧. 上一节我们主要研究了如何从链路层直接接收数据帧,可以通过bind函数来将原始套接字绑 ...
- UNIX网络编程——原始套接字的魔力【上】
基于原始套接字编程 在开发面向连接的TCP和面向无连接的UDP程序时,我们所关心的核心问题在于数据收发层面,数据的传输特性由TCP或UDP来保证: 也就是说,对于TCP或UDP的程序开发,焦点在Dat ...
- Linux网络编程——原始套接字能干什么?
通常情况下程序员接所接触到的套接字(Socket)为两类: (1)流式套接字(SOCK_STREAM):一种面向连接的 Socket,针对于面向连接的TCP 服务应用: (2)数据报式套接字(SOCK ...
- LINUX 网络编程 原始套接字
一 原始套接字 原始套接字(SOCK_RAW)是一种不同于SOCK_STREAM.SOCK_DGRAM的套接字,它实现于系统核心.然而,原始套接字能做什么呢?首先来说,普通的套接字无法处理ICMP.I ...
- 关于linux 原始套接字编程
关于linux 网络编程最权威的书是<<unix网络编程>>,但是看这本书时有些内容你可能理解的不是很深刻,或者说只知其然而不知其所以然,那么如果你想搞懂的话那么我建议你可以看 ...
- UNIX网络编程——原始套接字SOCK_RAW
实际上,我们常用的网络编程都是在应用层的报文的收发操作,也就是大多数程序员接触到的流式套接字(SOCK_STREAM)和数据包式套接字(SOCK_DGRAM).而这些数据包都是由系统提供的协议栈实现, ...
随机推荐
- 【2017"百度之星"程序设计大赛 - 初赛(A)】今夕何夕
[链接]http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=775&pid=1005 [题意] 在这里写题意 [题 ...
- HTML5梦幻星空,可用作网页背景
<html> <head> <title>星空</title> <META http-equiv="X-UA-Compatible&qu ...
- perl模块 Compress::Raw::Lzma 的安装
perl模块 Compress::Raw::Lzma 的安装 用 cpan 安装任意perl模块总是提示 Couldn't untar Compress-Raw-Lzma-2.070.tar: 'Ca ...
- Android学习笔记进阶十之Matrix错切变换
刚开始我也不懂啥叫错切变换,一看效果图你就恍然大悟. 对图像的错切变换做个总结: x = x0 + b*y0; y = d*x0 + y0; 与之对应的方法是: Matrix matrix = new ...
- 3. Spring Boot Servlet
转自:https://blog.csdn.net/catoop/article/details/50501686
- CSS笔记 - fgm练习 - 三个div变色 - CSS div等分布局
<title>三个div变红</title> <style> *{margin: 0; padding: 0} body{ text-align: center; ...
- python整除
1.'/'除号与c不同,单个'/'是浮点除,两个除号'//'才是整除
- js课程 5-13 js事件绑定和鼠标事件注意事项有哪些
js课程 5-13 js事件绑定和鼠标事件注意事项有哪些 一.总结 一句话总结:js代码的灵魂就是改变标签的属性和样式,就这两种. 1.js触发改的东西是哪两样? 属性和样式 2.js如何让页面用标 ...
- 【POJ 1226】Substrings
[链接]h在这里写链接 [题意] 给你n个字符串. 让你找一个字符串s. 设s'为这个字符串的逆序. 要求s或者s'在每个字符串里都能够找得到. 并且要求s的长度最长. 求出这个最长的串的长度. [题 ...
- php语法同java语法的基本区别(实例项目需求,php才能熟)
php语法同java语法的基本区别(实例项目需求,php才能熟) 一.总结 看下面 二.PHP基本语法以及和Java的区别 .表示字符串相加 ->同Java中的. $作为变量的前缀,除此之外,变 ...