Linux(Ubuntu)でcプログラミングを使用してarpパケットを送受信しようとしています
プログラムは正常に動作します(つまり、エラーなしで実行されます)が、Wiresharkを使用してパケットをトレースできません。
ソースコード:
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <asm/types.h>
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#define BUF_SIZE 42
#define DEVICE "eth0"
#define ETH_P_NULL 0x0
#define ETH_MAC_LEN ETH_ALEN
#define ETH_ARP 0x0806
int s = 0; /*Socketdescriptor*/
void* buffer = NULL;
long total_packets = 0;
long answered_packets = 0;
void sigint(int signum);
struct __attribute__((packed)) arp_header
{
unsigned short arp_hd;
unsigned short arp_pr;
unsigned char arp_hdl;
unsigned char arp_prl;
unsigned short arp_op;
unsigned char arp_sha[6];
unsigned char arp_spa[4];
unsigned char arp_dha[6];
unsigned char arp_dpa[4];
};
int main(void) {
buffer = (void*)malloc(BUF_SIZE); /*Buffer for Ethernet Frame*/
unsigned char* etherhead = buffer; /*Pointer to Ethenet Header*/
struct ethhdr *eh = (struct ethhdr *)etherhead; /*Another pointer to
ethernet header*/
unsigned char* arphead = buffer + 14;
struct arp_header *ah;
unsigned char src_mac[6]; /*our MAC address*/
struct ifreq ifr;
struct sockaddr_ll socket_address;
int ifindex = 0; /*Ethernet Interface index*/
int i;
int length; /*length of received packet*/
int sent;
printf("Server started, entering initialiation phase...\n");
/*open socket*/
s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (s == -1) {
perror("socket():");
exit(1);
}
printf("Successfully opened socket: %i\n", s);
/*retrieve ethernet interface index*/
strncpy(ifr.ifr_name, DEVICE, IFNAMSIZ);
if (ioctl(s, SIOCGIFINDEX, &ifr) == -1) {
perror("SIOCGIFINDEX");
exit(1);
}
ifindex = ifr.ifr_ifindex;
printf("Successfully got interface index: %i\n", ifindex);
/*retrieve corresponding MAC*/
if (ioctl(s, SIOCGIFHWADDR, &ifr) == -1) {
perror("SIOCGIFINDEX");
exit(1);
}
for (i = 0; i < 6; i++) {
src_mac[i] = ifr.ifr_hwaddr.sa_data[i];
}
printf("Successfully got our MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
src_mac[0],src_mac[1],src_mac[2],src_mac[3],src_mac[4],src_mac[5]);
/*prepare sockaddr_ll*/
socket_address.sll_family = PF_PACKET;
socket_address.sll_protocol = htons(ETH_P_IP);
socket_address.sll_ifindex = ifindex;
socket_address.sll_hatype = ARPHRD_ETHER;
socket_address.sll_pkttype = PACKET_OTHERHOST;
socket_address.sll_halen = 0;
socket_address.sll_addr[6] = 0x00;
socket_address.sll_addr[7] = 0x00;
/*establish signal handler*/
signal(SIGINT, sigint);
printf("Successfully established signal handler for SIGINT\n");
printf("We are in production state, waiting for incoming packets....\n");
while (1) {
/*Wait for incoming packet...*/
length = recvfrom(s, buffer, BUF_SIZE, 0, NULL, NULL);
if (length == -1)
{
perror("recvfrom():");
exit(1);
}
if(htons(eh->h_proto) == 0x806)
{
unsigned char buf_arp_dha[6];
unsigned char buf_arp_dpa[4];
ah = (struct arp_header *)arphead;
if(htons(ah->arp_op) != 0x0001)
continue;
printf("buffer is---------------- %s \n",(char*)ah);
printf("H/D TYPE : %x PROTO TYPE : %x \n",ah->arp_hd,ah->arp_pr);
printf("H/D leng : %x PROTO leng : %x \n",ah->arp_hdl,ah->arp_prl);
printf("OPERATION : %x \n", ah->arp_op);
printf("SENDER MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
ah->arp_sha[0],
ah->arp_sha[1],
ah->arp_sha[2],
ah->arp_sha[3],
ah->arp_sha[4],
ah->arp_sha[5]
);
printf("SENDER IP address: %02d:%02d:%02d:%02d\n",
ah->arp_spa[0],
ah->arp_spa[1],
ah->arp_spa[2],
ah->arp_spa[3]
);
if(ah->arp_spa[0]==10&&ah->arp_spa[1]==00&&ah->arp_spa[2]==00&&ah->arp_spa[3]==01)
{
printf("Sender ip is .............bam bam..........................................\n");
system("Sudo arp -s 10.0.0.1 00:1e:73:91:04:0d");
}
printf("TARGET MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
ah->arp_dha[0],
ah->arp_dha[1],
ah->arp_dha[2],
ah->arp_dha[3],
ah->arp_dha[4],
ah->arp_dha[5]
);
printf("TARGET IP address: %02d:%02d:%02d:%02d\n",
ah->arp_dpa[0],
ah->arp_dpa[1],
ah->arp_dpa[2],
ah->arp_dpa[3]
);
printf("+++++++++++++++++++++++++++++++++++++++\n" );
printf("ETHER DST MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
eh->h_dest[0],
eh->h_dest[1],
eh->h_dest[2],
eh->h_dest[3],
eh->h_dest[4],
eh->h_dest[5]
);
printf("ETHER SRC MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
eh->h_source[0],
eh->h_source[1],
eh->h_source[2],
eh->h_source[3],
eh->h_source[4],
eh->h_source[5]
);
memcpy( (void*)etherhead, (const void*)(etherhead+ETH_MAC_LEN),
ETH_MAC_LEN);
memcpy( (void*)(etherhead+ETH_MAC_LEN), (const void*)src_mac,
ETH_MAC_LEN);
eh->h_proto = ETH_ARP;
printf("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& \n");
printf("ETHER DST MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
eh->h_dest[0],
eh->h_dest[1],
eh->h_dest[2],
eh->h_dest[3],
eh->h_dest[4],
eh->h_dest[5]
);
printf("ETHER SRC MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
eh->h_source[0],
eh->h_source[1],
eh->h_source[2],
eh->h_source[3],
eh->h_source[4],
eh->h_source[5]
);
ah->arp_hd = ntohs(ah->arp_hd);
ah->arp_pr = ntohs(ah->arp_pr);
ah->arp_op = 0x0002;
buf_arp_dpa[0] = ah->arp_dpa[0];
buf_arp_dpa[1] = ah->arp_dpa[1];
buf_arp_dpa[2] = ah->arp_dpa[2];
buf_arp_dpa[3] = ah->arp_dpa[3];
ah->arp_dha[0] = ah->arp_sha[0];
ah->arp_dha[1] = ah->arp_sha[1];
ah->arp_dha[2] = ah->arp_sha[2];
ah->arp_dha[3] = ah->arp_sha[3];
ah->arp_dha[4] = ah->arp_sha[4];
ah->arp_dha[5] = ah->arp_sha[5];
ah->arp_dpa[0] = ah->arp_spa[0];
ah->arp_dpa[1] = ah->arp_spa[1];
ah->arp_dpa[2] = ah->arp_spa[2];
ah->arp_dpa[3] = ah->arp_spa[3];
ah->arp_spa[0] = buf_arp_dpa[0];
ah->arp_spa[1] = buf_arp_dpa[1];
ah->arp_spa[2] = buf_arp_dpa[2];
ah->arp_spa[3] = buf_arp_dpa[3];
//change the sender mac address
ah->arp_sha[0] = 0x00;
ah->arp_sha[1] = 0x1e;
ah->arp_sha[2] = 0x73;
ah->arp_sha[3] = 0x78;
ah->arp_sha[4] = 0x9a;
ah->arp_sha[5] = 0x0d;
socket_address.sll_addr[0] = eh->h_dest[0];
socket_address.sll_addr[1] = eh->h_dest[1];
socket_address.sll_addr[2] = eh->h_dest[2];
socket_address.sll_addr[3] = eh->h_dest[3];
socket_address.sll_addr[4] = eh->h_dest[4];
socket_address.sll_addr[5] = eh->h_dest[5];
printf("=======================================\n" );
printf("SENDER MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
ah->arp_sha[0],
ah->arp_sha[1],
ah->arp_sha[2],
ah->arp_sha[3],
ah->arp_sha[4],
ah->arp_sha[5]
);
printf("SENDER IP address: %02d:%02d:%02d:%02d\n",
ah->arp_spa[0],
ah->arp_spa[1],
ah->arp_spa[2],
ah->arp_spa[3]
);
if((ah->arp_spa[0]==10 && ah->arp_spa[1]==0 && ah->arp_spa[2]==0 && ah->arp_spa[3]==1))
printf("------------------------------------------10.0.0.1-----------------------------------------\n");
printf("TARGET MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
ah->arp_dha[0],
ah->arp_dha[1],
ah->arp_dha[2],
ah->arp_dha[3],
ah->arp_dha[4],
ah->arp_dha[5]
);
printf("TARGET IP address: %02d:%02d:%02d:%02d\n",
ah->arp_dpa[0],
ah->arp_dpa[1],
ah->arp_dpa[2],
ah->arp_dpa[3]
);
printf("H/D TYPE : %x PROTO TYPE : %x \n",ah->arp_hd,ah->arp_pr);
printf("H/D leng : %x PROTO leng : %x \n",ah->arp_hdl,ah->arp_prl);
printf("OPERATION : %x \n", ah->arp_op);
sent = sendto(s, buffer, BUF_SIZE, 0, (struct
sockaddr*)&socket_address, sizeof(socket_address));
if (sent == -1)
{
perror("sendto():");
exit(1);
}
answered_packets++;
}
total_packets++;
}
}
void sigint(int signum) {
/*Clean up.......*/
struct ifreq ifr;
if (s == -1)
return;
strncpy(ifr.ifr_name, DEVICE, IFNAMSIZ);
ioctl(s, SIOCGIFFLAGS, &ifr);
ifr.ifr_flags &= ~IFF_PROMISC;
ioctl(s, SIOCSIFFLAGS, &ifr);
close(s);
free(buffer);
printf("Server terminating....\n");
printf("Totally received: %ld packets\n", total_packets);
printf("Answered %ld packets\n", answered_packets);
exit(0);
}
ワイヤー/エアでパケットを取得するためのいくつかのこと。
<linux/if_ether.h>
のETH_P_ARPです。Ah-> arp_opの設定時にエンディアンにエラーがありました。これは2オクテットのネットワークバイトオーダーフィールドなので、htons()を使用します。
一般に、コードはネットワークとホストのバイトオーダーについて少し混乱しています。現在は非常に複雑な返信を送信していますが、それがコードの悪意によるものなのか、事故によるものなのかは不明です。実際の正しいIPアドレスを送信する場合は、応答を作成するときにhtonlおよびhtonsを使用します。
エンディアンを修正するには:
<arpa/inet.h>
を適切に含める要約すると、私が行った変更は1).sll_protocol = htons(ETH_P_ARP)でした。 (データ送信時)2)ah-> arp_op = htons(ARPOP_REPLY)(応答arp内)3)ah-> arp_hdおよびah-> arp_prの無意味なntohs()を削除しました。送信バッファーにデータを入力するときに、データをホストバイトオーダーに変換したくない場合(実際に実際に実行する場合を除く)4)ntohs()変換を追加し、一部の比較で適切な定義5)その他の小さな修正6)ビット実行システムを無効化(「須藤...」)!
Pastebin の完全なコード。ここに差分があります:
thuovila@glx:~/src/so/arp$ diff arp2.c arp_orig.c
13d12
< #include <arpa/inet.h>
20c19
< #define DEVICE "eth1"
---
> #define DEVICE "eth0"
25c24
< int s = -1; /*Socketdescriptor*/
---
> int s = 0; /*Socketdescriptor*/
92c91
< socket_address.sll_protocol = htons(ETH_P_ARP);
---
> socket_address.sll_protocol = htons(ETH_P_IP);
95c94
< socket_address.sll_pkttype = 0; //PACKET_OTHERHOST;
---
> socket_address.sll_pkttype = PACKET_OTHERHOST;
112c111
< if(ntohs(eh->h_proto) == ETH_P_ARP)
---
> if(htons(eh->h_proto) == 0x806)
119c118
< if(ntohs(ah->arp_op) != ARPOP_REQUEST)
---
> if(htons(ah->arp_op) != 0x0001)
139d137
< #if 0
145d142
< #endif
182c179
< eh->h_proto = htons(ETH_P_ARP);
---
> eh->h_proto = ETH_ARP;
200,201c197,198
< //ah->arp_hd = ntohs(ah->arp_hd);
< //ah->arp_pr = ntohs(ah->arp_pr);
---
> ah->arp_hd = ntohs(ah->arp_hd);
> ah->arp_pr = ntohs(ah->arp_pr);
203c200
< ah->arp_op = htons(ARPOP_REPLY);
---
> ah->arp_op = 0x0002;
[〜#〜] edit [〜#〜]ワイヤーシャークのアドバイス。キャプチャether proto 0x0806(またはarp略して)。パケットをキャプチャする疑似デバイスを使用します。パケットが見えるようになります。
Linuxでは、ネットワークスタックの干渉を防ぐには、次のコマンドを使用します。echo "8">/proc/sys/net/ipv4/conf/all/arp_ignore
EDIT#2ETH_P_ARPについて完全にはわかりません。それは私の側の簡単な判断だったかもしれません。 ATHヘッダーフィールドでETH_P_IPを使用することは正しいですが、パケットソケットsll_protocolにどちらを使用するかわかりません。また、送信時にsocket_address.sll_pkttype = PACKET_OTHERHOST;
は効果がないことにも注意してください(man 7パケットを参照)。また、必須のSO観察、常に少なくとも-Wall(gccまたはclangを使用する場合)を次のように使用する必要がありますコンパイルフラグ。
EDIT#3プログラムをもう少し変更しました。それに応じて回答と差分を更新しました。驚くべきことに、.sll_protocolはETH_P_ARPである必要があるようです。 man 7パケットの私のコピーは、それが何のためにも使用されているとは言いませんが、パケットはそれなしではARPとしてネットワークに送信されません。
私はuser6343961のコードを取り、いくつかのクリーニングとスプライシングを行い、インターフェイスIPアドレスを自動的に取得するためのサポートを実装しました。また、パラメーターはハードコーディングではなくCLIから取得されます。 bind()は、必要なインターフェースからARPのみを取得するためにも使用されます。楽しんで。このコードは私にとってはうまくいきます。
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <asm/types.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#include <arpa/inet.h> //htons etc
#define PROTO_ARP 0x0806
#define ETH2_HEADER_LEN 14
#define HW_TYPE 1
#define MAC_LENGTH 6
#define IPV4_LENGTH 4
#define ARP_REQUEST 0x01
#define ARP_REPLY 0x02
#define BUF_SIZE 60
#define debug(x...) printf(x);printf("\n");
#define info(x...) printf(x);printf("\n");
#define warn(x...) printf(x);printf("\n");
#define err(x...) printf(x);printf("\n");
struct arp_header {
unsigned short hardware_type;
unsigned short protocol_type;
unsigned char hardware_len;
unsigned char protocol_len;
unsigned short opcode;
unsigned char sender_mac[MAC_LENGTH];
unsigned char sender_ip[IPV4_LENGTH];
unsigned char target_mac[MAC_LENGTH];
unsigned char target_ip[IPV4_LENGTH];
};
/*
* Converts struct sockaddr with an IPv4 address to network byte order uin32_t.
* Returns 0 on success.
*/
int int_ip4(struct sockaddr *addr, uint32_t *ip)
{
if (addr->sa_family == AF_INET) {
struct sockaddr_in *i = (struct sockaddr_in *) addr;
*ip = i->sin_addr.s_addr;
return 0;
} else {
err("Not AF_INET");
return 1;
}
}
/*
* Formats sockaddr containing IPv4 address as human readable string.
* Returns 0 on success.
*/
int format_ip4(struct sockaddr *addr, char *out)
{
if (addr->sa_family == AF_INET) {
struct sockaddr_in *i = (struct sockaddr_in *) addr;
const char *ip = inet_ntoa(i->sin_addr);
if (!ip) {
return -2;
} else {
strcpy(out, ip);
return 0;
}
} else {
return -1;
}
}
/*
* Writes interface IPv4 address as network byte order to ip.
* Returns 0 on success.
*/
int get_if_ip4(int fd, const char *ifname, uint32_t *ip) {
int err = -1;
struct ifreq ifr;
memset(&ifr, 0, sizeof(struct ifreq));
if (strlen(ifname) > (IFNAMSIZ - 1)) {
err("Too long interface name");
goto out;
}
strcpy(ifr.ifr_name, ifname);
if (ioctl(fd, SIOCGIFADDR, &ifr) == -1) {
perror("SIOCGIFADDR");
goto out;
}
if (int_ip4(&ifr.ifr_addr, ip)) {
goto out;
}
err = 0;
out:
return err;
}
/*
* Sends an ARP who-has request to dst_ip
* on interface ifindex, using source mac src_mac and source ip src_ip.
*/
int send_arp(int fd, int ifindex, const unsigned char *src_mac, uint32_t src_ip, uint32_t dst_ip)
{
int err = -1;
unsigned char buffer[BUF_SIZE];
memset(buffer, 0, sizeof(buffer));
struct sockaddr_ll socket_address;
socket_address.sll_family = AF_PACKET;
socket_address.sll_protocol = htons(ETH_P_ARP);
socket_address.sll_ifindex = ifindex;
socket_address.sll_hatype = htons(ARPHRD_ETHER);
socket_address.sll_pkttype = (PACKET_BROADCAST);
socket_address.sll_halen = MAC_LENGTH;
socket_address.sll_addr[6] = 0x00;
socket_address.sll_addr[7] = 0x00;
struct ethhdr *send_req = (struct ethhdr *) buffer;
struct arp_header *arp_req = (struct arp_header *) (buffer + ETH2_HEADER_LEN);
int index;
ssize_t ret, length = 0;
//Broadcast
memset(send_req->h_dest, 0xff, MAC_LENGTH);
//Target MAC zero
memset(arp_req->target_mac, 0x00, MAC_LENGTH);
//Set source mac to our MAC address
memcpy(send_req->h_source, src_mac, MAC_LENGTH);
memcpy(arp_req->sender_mac, src_mac, MAC_LENGTH);
memcpy(socket_address.sll_addr, src_mac, MAC_LENGTH);
/* Setting protocol of the packet */
send_req->h_proto = htons(ETH_P_ARP);
/* Creating ARP request */
arp_req->hardware_type = htons(HW_TYPE);
arp_req->protocol_type = htons(ETH_P_IP);
arp_req->hardware_len = MAC_LENGTH;
arp_req->protocol_len = IPV4_LENGTH;
arp_req->opcode = htons(ARP_REQUEST);
debug("Copy IP address to arp_req");
memcpy(arp_req->sender_ip, &src_ip, sizeof(uint32_t));
memcpy(arp_req->target_ip, &dst_ip, sizeof(uint32_t));
ret = sendto(fd, buffer, 42, 0, (struct sockaddr *) &socket_address, sizeof(socket_address));
if (ret == -1) {
perror("sendto():");
goto out;
}
err = 0;
out:
return err;
}
/*
* Gets interface information by name:
* IPv4
* MAC
* ifindex
*/
int get_if_info(const char *ifname, uint32_t *ip, char *mac, int *ifindex)
{
debug("get_if_info for %s", ifname);
int err = -1;
struct ifreq ifr;
int sd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP));
if (sd <= 0) {
perror("socket()");
goto out;
}
if (strlen(ifname) > (IFNAMSIZ - 1)) {
printf("Too long interface name, MAX=%i\n", IFNAMSIZ - 1);
goto out;
}
strcpy(ifr.ifr_name, ifname);
//Get interface index using name
if (ioctl(sd, SIOCGIFINDEX, &ifr) == -1) {
perror("SIOCGIFINDEX");
goto out;
}
*ifindex = ifr.ifr_ifindex;
printf("interface index is %d\n", *ifindex);
//Get MAC address of the interface
if (ioctl(sd, SIOCGIFHWADDR, &ifr) == -1) {
perror("SIOCGIFINDEX");
goto out;
}
//Copy mac address to output
memcpy(mac, ifr.ifr_hwaddr.sa_data, MAC_LENGTH);
if (get_if_ip4(sd, ifname, ip)) {
goto out;
}
debug("get_if_info OK");
err = 0;
out:
if (sd > 0) {
debug("Clean up temporary socket");
close(sd);
}
return err;
}
/*
* Creates a raw socket that listens for ARP traffic on specific ifindex.
* Writes out the socket's FD.
* Return 0 on success.
*/
int bind_arp(int ifindex, int *fd)
{
debug("bind_arp: ifindex=%i", ifindex);
int ret = -1;
// Submit request for a raw socket descriptor.
*fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP));
if (*fd < 1) {
perror("socket()");
goto out;
}
debug("Binding to ifindex %i", ifindex);
struct sockaddr_ll sll;
memset(&sll, 0, sizeof(struct sockaddr_ll));
sll.sll_family = AF_PACKET;
sll.sll_ifindex = ifindex;
if (bind(*fd, (struct sockaddr*) &sll, sizeof(struct sockaddr_ll)) < 0) {
perror("bind");
goto out;
}
ret = 0;
out:
if (ret && *fd > 0) {
debug("Cleanup socket");
close(*fd);
}
return ret;
}
/*
* Reads a single ARP reply from fd.
* Return 0 on success.
*/
int read_arp(int fd)
{
debug("read_arp");
int ret = -1;
unsigned char buffer[BUF_SIZE];
ssize_t length = recvfrom(fd, buffer, BUF_SIZE, 0, NULL, NULL);
int index;
if (length == -1) {
perror("recvfrom()");
goto out;
}
struct ethhdr *rcv_resp = (struct ethhdr *) buffer;
struct arp_header *arp_resp = (struct arp_header *) (buffer + ETH2_HEADER_LEN);
if (ntohs(rcv_resp->h_proto) != PROTO_ARP) {
debug("Not an ARP packet");
goto out;
}
if (ntohs(arp_resp->opcode) != ARP_REPLY) {
debug("Not an ARP reply");
goto out;
}
debug("received ARP len=%ld", length);
struct in_addr sender_a;
memset(&sender_a, 0, sizeof(struct in_addr));
memcpy(&sender_a.s_addr, arp_resp->sender_ip, sizeof(uint32_t));
debug("Sender IP: %s", inet_ntoa(sender_a));
debug("Sender MAC: %02X:%02X:%02X:%02X:%02X:%02X",
arp_resp->sender_mac[0],
arp_resp->sender_mac[1],
arp_resp->sender_mac[2],
arp_resp->sender_mac[3],
arp_resp->sender_mac[4],
arp_resp->sender_mac[5]);
ret = 0;
out:
return ret;
}
/*
*
* Sample code that sends an ARP who-has request on
* interface <ifname> to IPv4 address <ip>.
* Returns 0 on success.
*/
int test_arping(const char *ifname, const char *ip) {
int ret = -1;
uint32_t dst = inet_addr(ip);
if (dst == 0 || dst == 0xffffffff) {
printf("Invalid source IP\n");
return 1;
}
int src;
int ifindex;
char mac[MAC_LENGTH];
if (get_if_info(ifname, &src, mac, &ifindex)) {
err("get_if_info failed, interface %s not found or no IP set?", ifname);
goto out;
}
int arp_fd;
if (bind_arp(ifindex, &arp_fd)) {
err("Failed to bind_arp()");
goto out;
}
if (send_arp(arp_fd, ifindex, mac, src, dst)) {
err("Failed to send_arp");
goto out;
}
while(1) {
int r = read_arp(arp_fd);
if (r == 0) {
info("Got reply, break out");
break;
}
}
ret = 0;
out:
if (arp_fd) {
close(arp_fd);
arp_fd = 0;
}
return ret;
}
int main(int argc, const char **argv) {
int ret = -1;
if (argc != 3) {
printf("Usage: %s <INTERFACE> <DEST_IP>\n", argv[0]);
return 1;
}
const char *ifname = argv[1];
const char *ip = argv[2];
return test_arping(ifname, ip);
}
私はこれが非常に古い記事であることを知っています。このコードは私に大いに役立ちました。 ARP要求をIPに送信し、応答からMACアドレスを抽出するようにコードを変更しました。以下の私のコードを見つけてください
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <asm/types.h>
#include <math.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <linux/if_arp.h>
#define PROTO_ARP 0x0806
#define ETH2_HEADER_LEN 14
#define HW_TYPE 1
#define PROTOCOL_TYPE 0x800
#define MAC_LENGTH 6
#define IPV4_LENGTH 4
#define ARP_REQUEST 0x01
#define ARP_REPLY 0x02
#define BUF_SIZE 60
struct arp_header
{
unsigned short hardware_type;
unsigned short protocol_type;
unsigned char hardware_len;
unsigned char protocol_len;
unsigned short opcode;
unsigned char sender_mac[MAC_LENGTH];
unsigned char sender_ip[IPV4_LENGTH];
unsigned char target_mac[MAC_LENGTH];
unsigned char target_ip[IPV4_LENGTH];
};
int main()
{
int sd;
unsigned char buffer[BUF_SIZE];
unsigned char source_ip[4] = {10,222,190,160};
unsigned char target_ip[4] = {10,222,190,139};
struct ifreq ifr;
struct ethhdr *send_req = (struct ethhdr *)buffer;
struct ethhdr *rcv_resp= (struct ethhdr *)buffer;
struct arp_header *arp_req = (struct arp_header *)(buffer+ETH2_HEADER_LEN);
struct arp_header *arp_resp = (struct arp_header *)(buffer+ETH2_HEADER_LEN);
struct sockaddr_ll socket_address;
int index,ret,length=0,ifindex;
memset(buffer,0x00,60);
/*open socket*/
sd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
if (sd == -1) {
perror("socket():");
exit(1);
}
strcpy(ifr.ifr_name,"eth1.30");
/*retrieve ethernet interface index*/
if (ioctl(sd, SIOCGIFINDEX, &ifr) == -1) {
perror("SIOCGIFINDEX");
exit(1);
}
ifindex = ifr.ifr_ifindex;
printf("interface index is %d\n",ifindex);
/*retrieve corresponding MAC*/
if (ioctl(sd, SIOCGIFHWADDR, &ifr) == -1) {
perror("SIOCGIFINDEX");
exit(1);
}
close (sd);
for (index = 0; index < 6; index++)
{
send_req->h_dest[index] = (unsigned char)0xff;
arp_req->target_mac[index] = (unsigned char)0x00;
/* Filling the source mac address in the header*/
send_req->h_source[index] = (unsigned char)ifr.ifr_hwaddr.sa_data[index];
arp_req->sender_mac[index] = (unsigned char)ifr.ifr_hwaddr.sa_data[index];
socket_address.sll_addr[index] = (unsigned char)ifr.ifr_hwaddr.sa_data[index];
}
printf("Successfully got eth1 MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
send_req->h_source[0],send_req->h_source[1],send_req->h_source[2],
send_req->h_source[3],send_req->h_source[4],send_req->h_source[5]);
printf(" arp_reqMAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
arp_req->sender_mac[0],arp_req->sender_mac[1],arp_req->sender_mac[2],
arp_req->sender_mac[3],arp_req->sender_mac[4],arp_req->sender_mac[5]);
printf("socket_address MAC address: %02X:%02X:%02X:%02X:%02X:%02X\n",
socket_address.sll_addr[0],socket_address.sll_addr[1],socket_address.sll_addr[2],
socket_address.sll_addr[3],socket_address.sll_addr[4],socket_address.sll_addr[5]);
/*prepare sockaddr_ll*/
socket_address.sll_family = AF_PACKET;
socket_address.sll_protocol = htons(ETH_P_ARP);
socket_address.sll_ifindex = ifindex;
socket_address.sll_hatype = htons(ARPHRD_ETHER);
socket_address.sll_pkttype = (PACKET_BROADCAST);
socket_address.sll_halen = MAC_LENGTH;
socket_address.sll_addr[6] = 0x00;
socket_address.sll_addr[7] = 0x00;
/* Setting protocol of the packet */
send_req->h_proto = htons(ETH_P_ARP);
/* Creating ARP request */
arp_req->hardware_type = htons(HW_TYPE);
arp_req->protocol_type = htons(ETH_P_IP);
arp_req->hardware_len = MAC_LENGTH;
arp_req->protocol_len =IPV4_LENGTH;
arp_req->opcode = htons(ARP_REQUEST);
for(index=0;index<5;index++)
{
arp_req->sender_ip[index]=(unsigned char)source_ip[index];
arp_req->target_ip[index]=(unsigned char)target_ip[index];
}
// Submit request for a raw socket descriptor.
if ((sd = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0) {
perror ("socket() failed ");
exit (EXIT_FAILURE);
}
buffer[32]=0x00;
ret = sendto(sd, buffer, 42, 0, (struct sockaddr*)&socket_address, sizeof(socket_address));
if (ret == -1)
{
perror("sendto():");
exit(1);
}
else
{
printf(" Sent the ARP REQ \n\t");
for(index=0;index<42;index++)
{
printf("%02X ",buffer[index]);
if(index % 16 ==0 && index !=0)
{printf("\n\t");}
}
}
printf("\n\t");
memset(buffer,0x00,60);
while(1)
{
length = recvfrom(sd, buffer, BUF_SIZE, 0, NULL, NULL);
if (length == -1)
{
perror("recvfrom():");
exit(1);
}
if(htons(rcv_resp->h_proto) == PROTO_ARP)
{
//if( arp_resp->opcode == ARP_REPLY )
printf(" RECEIVED ARP RESP len=%d \n",length);
printf(" Sender IP :");
for(index=0;index<4;index++)
printf("%u.",(unsigned int)arp_resp->sender_ip[index]);
printf("\n Sender MAC :");
for(index=0;index<6;index++)
printf(" %02X:",arp_resp->sender_mac[index]);
printf("\nReceiver IP :");
for(index=0;index<4;index++)
printf(" %u.",arp_resp->target_ip[index]);
printf("\n Self MAC :");
for(index=0;index<6;index++)
printf(" %02X:",arp_resp->target_mac[index]);
printf("\n :");
break;
}
}
return 0;
}
もう一度ありがとうございましたArun Kumar P