Use pf_packet and sock_raw to send custom type Ethernet packets

Source: Internet
Author: User
Tags htons

This article describes how to use pf_packet and sock_raw to send custom type Ethernet data packets, and use wireshare to capture packets to pave the way for adding network protocols to the Linux kernel.

First 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 socket (), 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_ton () and inet_ntop ()
# Include <sys/IOCTL. h> // macro IOCTL is defined
# Include <bits/IOCTLs. h> // defines values for argument "request" of 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 man 7 packet)
# Include <net/Ethernet. h>

# Include <errno. h> // errno, perror ()
# Define eth_p_dean 0x8874 // custom 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 first time a socket is created to obtain information about the local Nic
Perror ("socket () failed to get socket descriptor for using IOCTL ()");
Exit (exit_failure );
}

// Use IOCTL () to look up interface name and get its 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 will be 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 the 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 );

// The length of the data to be sent can be arbitrary, but the minimum length of the data to be captured is 46. This is the minimum size of the Ethernet frame data domain to 46 bytes, which is not automatically zero-enable.
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 + 14, Data, datalen );

// Submit request for a raw socket descriptor.
If (SD = socket (pf_packet, sock_raw, htons (eth_p_all) <0) {// create a socket that is actually sent
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 );
}

Packet Capture:


In the next chapter, we use dev_add_pack in Linux to add the protocol test for this type.

Thanks to the reference code provided by David Buchan:

Http://www.pdbuchan.com/rawsock/rawsock.html


Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.