summaryrefslogtreecommitdiff
path: root/mtu1280.c
diff options
context:
space:
mode:
authorJason Fesler <jfesler@guest.gigo.com>2015-02-17 12:11:17 -0800
committerJason Fesler <jfesler@guest.gigo.com>2015-02-17 12:11:17 -0800
commitd6d784cc333cdc1ff496c1fc562ffd2335a39e92 (patch)
tree4c899256e469e3b537750dcb7b59801f907753e8 /mtu1280.c
parent834078a53da95d2261d5f8d042b773d3ed2f04b3 (diff)
downloadmtu1280d-d6d784cc333cdc1ff496c1fc562ffd2335a39e92.tar.gz
mtu1280d-d6d784cc333cdc1ff496c1fc562ffd2335a39e92.zip
Rename to mtu1280d
Diffstat (limited to 'mtu1280.c')
-rw-r--r--mtu1280.c525
1 files changed, 0 insertions, 525 deletions
diff --git a/mtu1280.c b/mtu1280.c
deleted file mode 100644
index 7948af9..0000000
--- a/mtu1280.c
+++ /dev/null
@@ -1,525 +0,0 @@
-// Thanks to Austin Marton
-// https://austinmarton.wordpress.com/2011/09/14/sending-raw-ethernet-packets-from-a-specific-interface-in-c-on-linux/
-// csum() is borrowed from Austin; and csum_3() is derived from csum().
-
-// Portions of this file derived from libnetfilter_queue-1.0.2/utils/nfqnl_test.c
-// (C) 2005 by Harald Welte <laforge@gnumonks.org>
-// Particularly the bits that interface with netfilter (and the trigger for this being GPLv2 instead of MIT license)
-
-// Code not otherwise borrowed is
-// (C) 2015 by Jason Fesler <jfesler@gigo.com>
-// Principally: anything to do with ICMPv6 responses
-// The uglier it looks, the more likely it is mine.
-
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <assert.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <net/if.h>
-#include <netinet/ip.h>
-#include <netinet/udp.h>
-#include <netinet/ether.h>
-#include <linux/if_packet.h>
-#include <linux/sockios.h>
-
-// netfilter - lots of stuff pilfered from nfqnl_test.c
-#include <linux/netfilter.h> /* for NF_ACCEPT */
-#include <libnetfilter_queue/libnetfilter_queue.h>
-
-#define MTU 1280
-#define ETHER_SIZE (6+6+2)
-#define IPV6HDR_SIZE 40
-#define ICMP6_SIZE 8
-#define PAYLOAD_SIZE (MTU-(IPV6HDR_SIZE+ICMP6_SIZE))
-#define ETHER_CRC_SIZE 4
-#define ETHER_TOTAL_SIZE (MTU + ETHER_SIZE)
-
-typedef struct fullframe
-{
- u_int8_t ether_frame[ETHER_SIZE];
- u_int8_t ipv6_header[IPV6HDR_SIZE];
- u_int8_t icmp6_header[ICMP6_SIZE];
- u_int8_t payload[PAYLOAD_SIZE];
-} fullframe;
-
-int
-sockfd (void)
-{
- static sock = 0;
- if (!sock)
- {
- sock = socket (AF_PACKET, SOCK_RAW, IPPROTO_RAW);
- }
- if (sock == -1)
- {
- perror ("socket");
- }
-}
-
-uint8_t *
-macaddr_for_interface (int i)
-{
- static int last_i = 0xfffff;
- static uint8_t buffer[6];
- static uint8_t devname[IF_NAMESIZE];
-
- if (i != last_i)
- {
- int s = sockfd (); // * Need a random socket FD to do ioctl against
- char *interface = NULL;
- memset (buffer, 0, sizeof (buffer));
- interface = if_indextoname (i, devname);
- struct ifreq ifr;
-
- if (interface)
- {
- printf ("Looked up %d, found %s ", i, interface);
-
- // 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 (s, SIOCGIFHWADDR, &ifr) < 0)
- {
- perror ("ioctl() failed to get source MAC address ");
- exit (1);
- }
- memcpy (buffer, ifr.ifr_hwaddr.sa_data, 6);
-
- }
-
- }
- printf ("interface %d mac %02x:%02x:%02x:%02x:%02x:%02x",
- i, buffer[0], buffer[1], buffer[2], buffer[3], buffer[4],
- buffer[5]);
-
- return buffer;
-}
-
-
-void
-hexdump (char *s, uint8_t * p, int n)
-{
- int i;
- printf ("\nHEXDUMP: %s\n", s);
- for (i = 0; i < n; i++)
- {
- if (i % 16 == 0)
- {
- printf ("%04x: ", i);
- }
- printf ("%02x", p[i]);
- if (i % 2 == 1)
- {
- printf (" ");
- }
- if (i % 4 == 3)
- {
- printf (" ");
- }
- if (i % 16 == 15)
- {
- printf ("\n");
- }
- }
- printf ("\n");
-}
-
-
-uint16_t
-csum (uint16_t * buf, int count)
-{
- uint32_t sum;
- for (sum = 0; count > 0; count -= 2)
- sum += *buf++;
- sum = (sum >> 16) + (sum & 0xffff);
- sum += (sum >> 16);
- return (uint16_t) (~sum);
-}
-
-uint16_t
-csum_3 (uint16_t * buf1, int count1, uint16_t * buf2, int count2,
- uint16_t * buf3, int count3)
-{
- uint32_t sum;
- for (sum = 0; count1 > 0; count1 -= 2)
- sum += *buf1++;
- for (; count2 > 0; count2 -= 2)
- sum += *buf2++;
- for (; count3 > 0; count3 -= 2)
- sum += *buf3++;
- sum = (sum >> 16) + (sum & 0xffff);
- sum += (sum >> 16);
- return (uint16_t) (~sum);
-}
-
-
-
-
-/* returns packet id */
-static u_int32_t
-block_pkt (struct nfq_data *tb)
-{
- int id = 0;
- struct nfqnl_msg_packet_hdr *ph;
- struct nfqnl_msg_packet_hw *hwph;
- u_int32_t mark, ifi;
- int ret;
- int data_len;
- int copy_len;
- unsigned char *data;
- uint16_t c;
-
- // Where to address the raw packets - fill this in
- // as we go
- struct sockaddr_ll socket_address;
- memset (&socket_address, 0, sizeof (socket_address));
-
-
- // I'm tired of fighting all the crud,
- // so I'm goingto just use a big block.
- fullframe buffer;
- memset (&buffer, 0, sizeof (buffer));
- assert (sizeof (buffer) == ETHER_TOTAL_SIZE);
-
- // We need
- // Ethernet header
- // IPv6 header
- // IPCMPv6 header
- // As much of the original payload as possible
- // Final ether CRC
-
-
- // Get the packet ID. NEeded for netfilter_queue response.
- fprintf (stdout, "TRACE: %s %i\n", __FILE__, __LINE__);
- ph = nfq_get_msg_packet_hdr (tb);
- if (ph)
- {
- id = ntohl (ph->packet_id);
- printf ("hw_protocol=0x%04x hook=%u id=%u ",
- ntohs (ph->hw_protocol), ph->hook, id);
- }
-
- // Get the data payload from netfilter_queue
- fprintf (stdout, "TRACE: %s %i\n", __FILE__, __LINE__);
- ret = nfq_get_payload (tb, &data);
- if (ret >= 0)
- printf ("payload_len=%d ", ret);
- data_len = ret;
- copy_len = (data_len > PAYLOAD_SIZE) ? PAYLOAD_SIZE : data_len;
- printf ("copy_len=%d ", copy_len);
-
-
-
- // What MAC address sent us this packet?
- // We intend to send the outbound packet
- // back to the same place.
- hwph = nfq_get_packet_hw (tb);
- if (hwph)
- {
- int i, hlen = ntohs (hwph->hw_addrlen);
-
- printf ("hw_src_addr=");
- for (i = 0; i < hlen - 1; i++)
- printf ("%02x:", hwph->hw_addr[i]);
- printf ("%02x ", hwph->hw_addr[hlen - 1]);
-
- // Ethernet frame destination
- memcpy (&buffer.ether_frame[0], hwph->hw_addr, 6);
- memcpy (socket_address.sll_addr, hwph->hw_addr, 6);
- socket_address.sll_halen = ETH_ALEN;
- }
-
- // TODO: Ethernet frame source
-
- // Ethernet frame type
- buffer.ether_frame[12] = ETH_P_IPV6 / 256;
- buffer.ether_frame[13] = ETH_P_IPV6 % 256;
-
- // Show the ethernet frame
- hexdump ("DUMP: ether_frame", buffer.ether_frame,
- sizeof (buffer.ether_frame));
-
-
- // Start creating the IPv6 header
- buffer.ipv6_header[0] = 0x60; // IPv6 "version=6"
-
- // What is the payload length?
- int plength = copy_len + ICMP6_SIZE;
- buffer.ipv6_header[4] = plength / 256;
- buffer.ipv6_header[5] = plength % 256;
-
- // What is the next header?
- buffer.ipv6_header[6] = 0x3a; // ICMPv6
- buffer.ipv6_header[7] = 0xff; // Hop limit
-
- // Source address, Destination Address
- // Just swap from what we saw in our input packet
- memcpy (&buffer.ipv6_header[8], &data[24], 16);
- memcpy (&buffer.ipv6_header[24], &data[8], 16);
-
- hexdump ("IP6 HEADER:", buffer.ipv6_header, sizeof (buffer.ipv6_header));
-
- // ICMPv6 header
- buffer.icmp6_header[0] = 2; // Type 2 Packet Too Big
- buffer.icmp6_header[1] = 0; // Code (not used)
-
- // TODO Checksum
- buffer.icmp6_header[2] = 0; // TODO Checksum
- buffer.icmp6_header[3] = 0; // TODO checksum
-
- // MTU expressed as 32 bits
- buffer.icmp6_header[4] = (MTU >> 24) & 0xff;
- buffer.icmp6_header[5] = (MTU >> 16) & 0xff;
- buffer.icmp6_header[6] = (MTU >> 8) & 0xff;
- buffer.icmp6_header[7] = MTU & 0xff;
-
- memcpy (buffer.payload, data, copy_len);
- hexdump ("ICMP6", buffer.icmp6_header,
- sizeof (buffer.icmp6_header) + copy_len);
-
- u_int8_t pseudoheader[40];
- memcpy (pseudoheader, &buffer.ipv6_header[8], 32);
- pseudoheader[32] = 0; // length never more than 0xffff
- pseudoheader[33] = 0; // length never more than 0xffff
- pseudoheader[34] = (ICMP6_SIZE + copy_len) / 256;
- pseudoheader[35] = (ICMP6_SIZE + copy_len) % 256;
- pseudoheader[36] = 0; // zero
- pseudoheader[37] = 0; // zero
- pseudoheader[38] = 0; // zero
- pseudoheader[39] = 58; // ICMPv6 header code
-
- c = csum_3 ((uint16_t *) pseudoheader, sizeof (pseudoheader),
- (uint16_t *) buffer.icmp6_header, sizeof (buffer.icmp6_header),
- (uint16_t *) buffer.payload, copy_len);
- buffer.icmp6_header[2] = c % 256;
- buffer.icmp6_header[3] = c / 256;
-
- hexdump ("PseudoHeader", pseudoheader, sizeof (pseudoheader));
-
-
- hexdump ("ICMP6", buffer.icmp6_header,
- sizeof (buffer.icmp6_header) + copy_len);
-
-
-
-
-
-
- // Device ID that the packet came from
- fprintf (stdout, "TRACE: %s %i\n", __FILE__, __LINE__);
- ifi = nfq_get_indev (tb);
- if (ifi)
- {
- printf ("indev=%u ", ifi);
- socket_address.sll_ifindex = ifi;
- memcpy (&buffer.ether_frame[6], macaddr_for_interface (ifi), 6);
- }
-
- fputc ('\n', stdout);
- fprintf (stdout, "TRACE: %s %i\n", __FILE__, __LINE__);
-
- int tx_len = ETHER_SIZE + IPV6HDR_SIZE + ICMP6_SIZE + copy_len;
- if (sendto
- (sockfd (), &buffer, tx_len, 0, (struct sockaddr *) &socket_address,
- sizeof (struct sockaddr_ll)) < 0)
- printf ("Send failed\n");
-
-
-
-
- return id;
-}
-
-
-
-/* returns packet id */
-static u_int32_t
-print_pkt (struct nfq_data *tb)
-{
- int id = 0;
- struct nfqnl_msg_packet_hdr *ph;
- struct nfqnl_msg_packet_hw *hwph;
- u_int32_t mark, ifi;
- int ret;
- unsigned char *data;
-
- ph = nfq_get_msg_packet_hdr (tb);
- if (ph)
- {
- id = ntohl (ph->packet_id);
- printf ("hw_protocol=0x%04x hook=%u id=%u ",
- ntohs (ph->hw_protocol), ph->hook, id);
- }
-
- hwph = nfq_get_packet_hw (tb);
- if (hwph)
- {
- int i, hlen = ntohs (hwph->hw_addrlen);
-
- printf ("hw_src_addr=");
- for (i = 0; i < hlen - 1; i++)
- printf ("%02x:", hwph->hw_addr[i]);
- printf ("%02x ", hwph->hw_addr[hlen - 1]);
- }
-
- mark = nfq_get_nfmark (tb);
- if (mark)
- printf ("mark=%u ", mark);
-
- ifi = nfq_get_indev (tb);
- if (ifi)
- printf ("indev=%u ", ifi);
-
- ifi = nfq_get_outdev (tb);
- if (ifi)
- printf ("outdev=%u ", ifi);
- ifi = nfq_get_physindev (tb);
- if (ifi)
- printf ("physindev=%u ", ifi);
-
- ifi = nfq_get_physoutdev (tb);
- if (ifi)
- printf ("physoutdev=%u ", ifi);
-
- ret = nfq_get_payload (tb, &data);
- if (ret >= 0)
- printf ("payload_len=%d ", ret);
-
- fputc ('\n', stdout);
-
- return id;
-}
-
-
-static int
-cb (struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
- struct nfq_data *nfa, void *data)
-{
- static u_int32_t id;
-// id = print_pkt(nfa);
- printf ("entering callback\n");
- id = block_pkt (nfa);
- return nfq_set_verdict (qh, id, NF_DROP, 0, NULL);
-}
-
-
-int
-main (int argc, char **argv)
-{
- struct nfq_handle *h;
- struct nfq_q_handle *qh;
- struct nfnl_handle *nh;
- int fd;
- int rv;
- unsigned int queue = 1280; // -q
- unsigned int do_fork = 0; // -d
- char *interface;
- char buf[4096] __attribute__ ((aligned));
-
-// Getopt
- int c;
- int opterr = 0;
- while ((c = getopt (argc, argv, "dq:")) != -1)
- switch (c)
- {
- case 'd':
- fprintf (stderr, "setting\n");
- do_fork = 1;
- fprintf (stderr, "set!\n");
- break;
- case 'q':
- queue = strtol (optarg, NULL, 10);
- break;
- case '?':
- if (optopt == 'q')
- fprintf (stderr, "Option -%c requires an argument.\n", optopt);
- else if (isprint (optopt))
- fprintf (stderr, "Unknown option `-%c'.\n", optopt);
- else
- fprintf (stderr, "Unknown option character `\\x%x'.\n", optopt);
- return 1;
- default:
- abort ();
- }
-
-
-
-
- printf ("opening library handle\n");
- h = nfq_open ();
- if (!h)
- {
- fprintf (stdout, "error during nfq_open()\n");
- exit (1);
- }
-
- printf ("unbinding existing nf_queue handler for AF_INET6 (if any)\n");
- if (nfq_unbind_pf (h, AF_INET6) < 0)
- {
- fprintf (stdout, "error during nfq_unbind_pf()\n");
- if (getuid () != 0)
- {
- fprintf (stderr, "%s: must be ran as root\n", argv[0]);
- }
- exit (1);
- }
-
- printf ("binding nfnetlink_queue as nf_queue handler for AF_INET6\n");
- if (nfq_bind_pf (h, AF_INET6) < 0)
- {
- fprintf (stdout, "error during nfq_bind_pf()\n");
- exit (1);
- }
-
- printf ("binding this socket to queue '%u'\n", queue);
- qh = nfq_create_queue (h, queue, &cb, NULL);
- if (!qh)
- {
- fprintf (stdout, "error during nfq_create_queue()\n");
- exit (1);
- }
-
-
- printf ("setting copy_packet mode\n");
- if (nfq_set_mode (qh, NFQNL_COPY_PACKET, 0xffff) < 0)
- {
- fprintf (stdout, "can't set packet_copy mode\n");
- exit (1);
- }
-
-
- if (do_fork)
- {
- fprintf (stdout, "forking to background\n");
- daemon (0, 0);
- }
-
-
- fd = nfq_fd (h);
-
- while ((rv = recv (fd, buf, sizeof (buf), 0)) && rv >= 0)
- {
- printf ("pkt received\n");
- nfq_handle_packet (h, buf, rv);
- }
-
- printf ("unbinding from queue 0\n");
- nfq_destroy_queue (qh);
-
-#ifdef INSANE
- /* normally, applications SHOULD NOT issue this command, since
- * it detaches other programs/sockets from AF_INET6, too ! */
- printf ("unbinding from AF_INET6\n");
- nfq_unbind_pf (h, AF_INET6);
-#endif
-
- printf ("closing library handle\n");
- nfq_close (h);
-
- exit (0);
-}