这个重点是如这样创建socket:  sock_send = socket ( PF_PACKET , SOCK_PACKET , htons ( ETH_P_ARP) ) ;

其后所有收发的数据都是原始的网络数据包。

代码如下:在X86和ARM平台上都测试通过。调用arp_scaner_init之后 ,调用send_arp来发送ARP数据包,thread_read_arp中就会收到对端的反馈,并将其保存。

在此非常感谢其他同仁的分享,使我学会了这个用法。

#include <unistd.h>

#include <errno.h>

#include <netdb.h>

#include <signal.h>

#include <sys/socket.h>

#include <sys/poll.h>

#include <sys/ioctl.h>

#include <netinet/if_ether.h>

#include <net/if_arp.h>

#include <netinet/udp.h>

#include <netinet/ip.h>

#include <stdio.h>

#include <stdarg.h>

#include <net/if.h>

#include <arpa/inet.h>

#include <string.h>

#include "adapter.h"

struct arp_msg {

/* Ethernet header */

uint8_t h_dest[ 6] ; /* 00 destination ether addr */

uint8_t h_source[ 6] ; /* 06 source ether addr */

uint16_t h_proto; /* 0c packet type ID field */

/* ARP packet */

uint16_t htype; /* 0e hardware type (must be ARPHRD_ETHER) */

uint16_t ptype; /* 10 protocol type (must be ETH_P_IP) */

uint8_t hwAddrLen; /* 12 hardware address length (must be 6) */

uint8_t protoAddrLen; /* 13 protocol address length (must be 4) */

uint16_t operation; /* 14 ARP opcode */

uint8_t srcMac[ 6] ; /* 16 sender's hardware address */

uint8_t srcIP[ 4] ; /* 1c sender's IP address */

uint8_t dstMac[ 6] ; /* 20 target's hardware address */

uint8_t dstIP[ 4] ; /* 26 target's IP address */

//     uint8_t pad[ 18] ; /* 2a pad for min. ethernet payload (60 bytes) */

}PACKED;

bool g_system_running=true;

uint32_t local_ip;

uint8_t local_mac[ 6 ];

pthread_mutex_t g_cfglock;

volatile uint32_t g_mac_count=0;

char (*mac_list)[18];

int  mac_list_max=0;

uint8_t raw_mac[64][6];

int setsockopt_broadcast( int fd)

{

const int const_int_1 =1;

return setsockopt ( fd,SOL_SOCKET,SO_BROADCAST, & const_int_1, sizeof ( const_int_1) ) ;

}

void prmac(u_char *ptr)

{

printf("MAC is: %02x:%02x:%02x:%02x:%02x:%02x\n",*ptr,*(ptr+1),*(ptr+2),*(ptr+3),*(ptr+4),*(ptr+5));

}

void printIP(const char *msg, uint8_t* ip)

{

printf("%s IP:%d.%d.%d.%d\n",msg,ip[0],ip[1],ip[2],ip[3]);

}

int send_arp( uint32_t test_ip, uint32_t from_ip, uint8_t * my_mac, const char * interface)

{

int sock_send;

int rv =1; /* "no reply received" yet */

struct sockaddr addr; /* for interface name */

struct arp_msg arp;

sock_send = socket ( PF_PACKET , SOCK_PACKET , htons ( ETH_P_ARP) ) ;

if ( sock_send == - 1) {

perror ( "raw_socket" ) ;

return - 1;

}

if ( setsockopt_broadcast( sock_send ) == - 1) {

perror ( "cannot enable bcast on raw socket" ) ;

goto ret;

}

/* send arp request */

memset ( & arp,0, sizeof ( arp) ) ;

memset ( arp. h_dest,0xff,6) ; /* MAC DA */

memcpy ( arp. h_source,my_mac,6) ; /* MAC SA */

arp. h_proto = htons ( ETH_P_ARP) ; /* protocol type (Ethernet) */

arp. htype = htons ( ARPHRD_ETHER) ; /* hardware type */

arp. ptype = htons ( ETH_P_IP) ; /* protocol type (ARP message) */

arp. hwAddrLen =6; /* hardware address length */

arp. protoAddrLen =4; /* protocol address length */

arp. operation = htons ( ARPOP_REQUEST) ; /* ARP op code */

memcpy ( arp. srcMac,my_mac,6) ; /* source hardware address */

memcpy ( arp. srcIP, & from_ip, sizeof ( from_ip) ) ; /* source IP address */

memcpy ( arp. dstIP, & test_ip, sizeof ( test_ip) ) ; /* target IP address */

memset ( & addr,0, sizeof ( addr) ) ;

strncpy( addr. sa_data,interface, sizeof ( addr. sa_data) ) ;

if ( sendto ( sock_send, & arp, sizeof ( arp) ,0, & addr, sizeof ( addr) ) <0) {

perror("sendto error");

}

ret:

close (sock_send) ;

return rv;

}

int read_interface( const char * interface, int * i, uint32_t * addr, uint8_t * arp)

{

int fd;

struct ifreq ifr;

struct sockaddr_in * our_ip;

memset ( & ifr,0, sizeof ( ifr) ) ;

fd = socket(AF_INET, SOCK_DGRAM, 0);

ifr. ifr_addr. sa_family = AF_INET ;

strncpy( ifr.ifr_name,interface, sizeof(ifr.ifr_name) );

if ( arp) {

if ( ioctl( fd, SIOCGIFHWADDR , & ifr) !=0) {

printf("SIOCGIFHWADDR error\n");

close ( fd) ;

return - 1;

}

memcpy ( arp,ifr. ifr_hwaddr. sa_data,6) ;

prmac ( arp ) ;

}

if ( addr) {

if ( ioctl( fd, SIOCGIFADDR , & ifr) !=0) {

perror ( "ioctl" ) ;

close ( fd) ;

return - 1;

}

our_ip = ( struct sockaddr_in * ) & ifr. ifr_addr;

* addr =our_ip-> sin_addr. s_addr;

}

close ( fd);

return 0;

}

void* thread_read_arp(void* param)

{

struct sockaddr repsa;

socklen_t salen, recved_len ;

struct arp_msg response;

int recvfd = socket(PF_PACKET, SOCK_PACKET, htons(ETH_P_ARP));

bzero(&response, sizeof(response));

bzero(&repsa, sizeof(repsa));

salen = sizeof(repsa);

while(g_system_running){

if((recved_len = recvfrom(recvfd, &response, sizeof(response), 0, (struct sockaddr *)&repsa, &salen)) <= 0) {

perror("Recvfrom error");

break;

}

printf("Response %d bytes received\n",recved_len);

printIP("response", response.srcIP);

if( memcmp(response.dstIP ,&local_ip,  4 ) ==0

&& memcmp(response.dstMac,local_mac, 6 ) ==0){

printf("get a data\n");

}

}

close(recvfd);

}

int arp_scaner_init( const char * interface )

{

pthread_t tid;

read_interface( interface, NULL,&local_ip,local_mac);

printf("local IP");

printIP("", (uint8_t*)&local_ip );

pthread_mutex_init(&g_cfglock, NULL);

ipc_createthread(&tid, thread_read_arp, NULL, "arp-reading");

send_arp( find_ip,local_ip,local_mac,interface);

}

linux系统中使用socket直接发送ARP数据的更多相关文章

  1. 如何从Linux系统中获取带宽、流量网络数据

    引入 国外的云主机厂商,例如AWS提供的网络数据是以流量为单位的,例如下面的图片: 从上图来看,其取值方式为 每隔5分钟取值1次,(每次)每个点显示为1分钟内的流量字节数(Bytes) 带宽与流量 我 ...

  2. linux系统中的进程状态分析

    转载地址:https://blog.csdn.net/shenwansangz/article/details/51981459 linux是一个多用户,多任务的系统,可以同时运行多个用户的多个程序, ...

  3. Linux 系统中僵尸进程

    Linux 系统中僵尸进程和现实中僵尸(虽然我也没见过)类似,虽然已经死了,但是由于没人给它们收尸,还能四处走动.僵尸进程指的是那些虽然已经终止的进程,但仍然保留一些信息,等待其父进程为其收尸.配图源 ...

  4. 获得Unix/Linux系统中的IP、MAC地址等信息

    获得Unix/Linux系统中的IP.MAC地址等信息 中高级  |  2010-07-13 16:03  |  分类:①C语言. Unix/Linux. 网络编程 ②手册  |  4,471 次阅读 ...

  5. 为什么在 Linux 系统中,不建议超频

    CPU 是一部计算机内的心脏啦!因为不论你做什么事情都需要 CPU 来加以运作的!(虽然有时工作量大.有时工作量小!),在 586 以前的计算机( 包含 386, 486, 与 586 ) ,CPU ...

  6. (转)浅谈 Linux 系统中的 SNMP Trap

    原文:https://www.ibm.com/developerworks/cn/linux/l-cn-snmp/index.html 简介 本文讲解 SNMP Trap,在介绍 Trap 概念之前, ...

  7. 详解Linux系统中的文件名和文件种类以及文件权限

    Linux文件种类与副文件名 一直强调一个概念,那就是:任何装置在Linux底下都是文件, 不仅如此,连资料沟通的介面也有专属的文件在负责-所以,你会瞭解到,Linux的文件种类真的很多- 除了前面提 ...

  8. linux系统中文件的几种类型

    Linux系统是以文件的形式来进行管理的.Linux文件类型常见的有:普通文件.目录.字符设备文件.块设备文件.符号链接文件等,如果想了解这方面知识的弟兄,就进来了解了解. Linux系统不同于win ...

  9. Linux系统中的Device Mapper学习

    在linux系统中你使用一些命令时(例如nmon.iostat 如下截图所示),有可能会看到一些名字为dm-xx的设备,那么这些设备到底是什么设备呢,跟磁盘有什么关系呢?以前不了解的时候,我也很纳闷. ...

随机推荐

  1. eclipse-jee-kepler 如何设置编译compiler为1.8

    最新下载了jdk1.8,想在eclipse里面用一下 jdk1.8的新特性 但是,貌似eclipse(eclipse-jee-kepler-SR2-win32-x86_64.zip)最高的编译级别为: ...

  2. C#移动及改变控件大小

    //代码比较简单,就不多解析了. #region 移动窗体保存数据 Point mouseOff;//鼠标移动位置变量 bool leftFlag; //标志是否为左键 bool largeFlag; ...

  3. java实现将包含多个<REC>的文件拆成若干只包含一个<REC>的文件

    遍历文件夹里的文件,将包含多个<REC>的文件拆成若干只包含一个<REC>的文件 package com.prepub; import java.io.BufferedRead ...

  4. poj2777(线段树)

    题目链接:https://vjudge.net/problem/POJ-2777 题意:有L块连续的板子,每块板子最多染一种颜色,有T种(<=30)颜色,刚开始将所有板子染成颜色1,O次操作(包 ...

  5. 2018-2019-2 《网络对抗技术》Exp0 Kali安装

    2018-2019-2 <网络对抗技术>Exp0 Kali安装 ---20165110 一.实验要求 1.下载 2.安装Kali 3.连接网络 4.共享文件 5.更新软件源 二.实验步骤 ...

  6. Mysql数据库左外连接,右外连接,模糊查询

    内连接,左外连接,右外连接都是数据库的常用连接与使用手段 内连接 select * from assets_car c inner join category c on a.id = c.id; 左外 ...

  7. django RESTful设计方法

    1. 域名 应该尽量将API部署在专用域名之下. https://api.example.com 如果确定API很简单,不会有进一步扩展,可以考虑放在主域名下. https://example.org ...

  8. Winform 时间

    using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawi ...

  9. 【Thread】CountdownEvent任务并行[z]

    System.Threading.CountdownEvent  是一个同步基元,它在收到一定次数的信号之后,将会解除对其等待线程的锁定. CountdownEvent  专门用于以下情况:您必须使用 ...

  10. strcat的用法

    原型: char *strcat(char *str1,char *str2); strcat的实现: char* MyStrcat(char *dst, const char*src) { if ( ...