This article describes the use of Pf_packet and Sock_raw to send themselves a defined type Ethernet packet, using the Wireshare capture packet to get to the packet and pave the line for adding a network protocol to the Linux kernel.
First on the code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>//close ()
#include <string.h>//strcpy, memset (), and memcpy ()
#include <netdb.h>//struct ADDRINFO
#include <sys/types.h>//needed for sockets (), uint8_t, uint16_t, uint32_t
#include <sys/socket.h>//needed for socket ()
#include <netinet/in.h>//ipproto_icmp, Inet_addrstrlen
#include <netinet/ip.h>//struct IP and Ip_maxpacket (which is 65535)
#include <netinet/ip_icmp.h>//struct ICMP, Icmp_echo
#include <arpa/inet.h>//Inet_pton () and Inet_ntop ()
#include <sys/ioctl.h>//macro IOCTL is defined
#include <bits/ioctls.h>//Defines values for argument "request" of the IOCTL.
#include <net/if.h>//struct IFREQ
#include <linux/if_ether.h>//eth_p_ip = 0x0800, Eth_p_ipv6 = 0X86DD
#include <linux/if_packet.h>//struct SOCKADDR_LL (see Mans 7 packet)
#include <net/ethernet.h>
#include <errno.h>//errno, perror ()
#define Eth_p_dean 0x8874//self-defined Ethernet protocol type
int main (int argc, char **argv)
{
int i, datalen,frame_length, SD, bytes;
Char *interface= "eth1";;
uint8_t Data[ip_maxpacket];
uint8_t Src_mac[6];
uint8_t dst_mac[6];;
uint8_t Ether_frame[ip_maxpacket];
struct SOCKADDR_LL device;
struct Ifreq IFR;
Submit request for a socket descriptor-to-look up interface.
if (SD = socket (Pf_packet, Sock_raw, htons (Eth_p_all))) < 0) {//The socket was created for the first time to obtain local NIC information
Perror ("socket () failed to get socket descriptor for using IOCTL ()");
Exit (Exit_failure);
}
Use the IOCTL () to look up interface name and get their MAC address.
memset (&IFR, 0, sizeof (IFR));
snprintf (ifr.ifr_name, sizeof (Ifr.ifr_name), "%s", interface);
if (IOCTL (SD, SIOCGIFHWADDR, &IFR) < 0) {
Perror ("IOCTL () failed to get source MAC address");
return (exit_failure);
}
Close (SD);
Copy source MAC address.
memcpy (Src_mac, Ifr.ifr_hwaddr.sa_data, 6);
Report source MAC address to stdout.
printf ("MAC address for interface%s is", interface);
for (i=0; i<5; i++) {
printf ("%02x:", Src_mac[i]);
}
printf ("%02x\n", src_mac[5]);
Find interface index from Interface name and store index in
struct SOCKADDR_LL device, which is used as an argument of SendTo ().
memset (&device, 0, sizeof (device));
if ((Device.sll_ifindex = If_nametoindex (interface)) = = 0) {
Perror ("If_nametoindex () failed to obtain interface index");
Exit (Exit_failure);
}
printf ("Index for interface%s is%i\n", interface, Device.sll_ifindex);
Set destination MAC address:you need to fill these out
Dst_mac[0] = 0x10;//set destination NIC address
DST_MAC[1] = 0x78;
DST_MAC[2] = 0xd2;
DST_MAC[3] = 0xc6;
DST_MAC[4] = 0x2f;
DST_MAC[5] = 0x89;
Fill out Sockaddr_ll.
device.sll_family = Af_packet;
memcpy (Device.sll_addr, Src_mac, 6);
Device.sll_halen = htons (6);
Send the data, the length can be arbitrary, but when the packet caught see the minimum data length of 46, which is the Ethernet protocol provisionsEthernet frame Data domain portion minimum of 46 bytes, insufficient self-active 0 processing
Datalen = 12;
Data[0] = ' h ';
DATA[1] = ' e ';
DATA[2] = ' l ';
DATA[3] = ' l ';
Data[4] = ' o ';
DATA[5] = ";
DATA[6] = ' W ';
Data[7] = ' o ';
DATA[8] = ' R ';
DATA[9] = ' l ';
DATA[10] = ' d ';
DATA[11] = '! ';
Fill out Ethernet frame header.
Frame_length = 6 + 6 + 2 + datalen;
Destination and Source MAC addresses
memcpy (Ether_frame, Dst_mac, 6);
memcpy (Ether_frame + 6, Src_mac, 6);
ETHER_FRAME[12] = eth_p_dean/256;
ETHER_FRAME[13] = eth_p_dean% 256;
Data
memcpy (Ether_frame +, data, datalen);
Submit request for a raw socket descriptor.
if (SD = socket (Pf_packet, Sock_raw, htons (Eth_p_all))) < 0) {//Create a true-send socket
Perror ("socket () failed");
Exit (Exit_failure);
}
Send Ethernet frame to socket.
if (bytes = sendto (SD, Ether_frame, Frame_length, 0, (struct sockaddr *) &device, sizeof (device))) <= 0) {
Perror ("SendTo () failed");
Exit (Exit_failure);
}
printf ("Send Num=%d,read num=%d\n", frame_length,bytes);
Close socket Descriptor.
Close (SD);
return (exit_success);
}
Grab bag Get:
watermark/2/text/ahr0cdovl2jsb2cuy3nkbi5uzxqvzgvhbl9nzha=/font/5a6l5l2t/fontsize/400/fill/i0jbqkfcma==/ Dissolve/70/gravity/southeast ">
In the next chapter, we use Dev_add_pack in Linux to add this type of protocol probe.
Thanks to David Buchan's webpage for reference code:
Http://www.pdbuchan.com/rawsock/rawsock.html
Use Pf_packet and Sock_raw to send yourself a defined type Ethernet packet