summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2013-03-09 15:30:42 +0100
committerMatthias Schiffer <mschiffer@universe-factory.net>2013-03-09 15:30:42 +0100
commitc78b87e29df0217d6f277d58559b0d6926508948 (patch)
treebe6213fdb6b6e90459243cf5fa657f26a51d308f
downloadethersend-c78b87e29df0217d6f277d58559b0d6926508948.tar
ethersend-c78b87e29df0217d6f277d58559b0d6926508948.zip
Initial commitHEADmaster
-rw-r--r--.gitignore2
-rw-r--r--Makefile8
-rw-r--r--ethersend.c118
3 files changed, 128 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..07e611d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+*~
+/ethersend
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..08a9322
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,8 @@
+CFLAGS = -Wall
+
+all: ethersend
+
+clean:
+ rm -f ethersend
+
+.PHONY: clean
diff --git a/ethersend.c b/ethersend.c
new file mode 100644
index 0000000..f210401
--- /dev/null
+++ b/ethersend.c
@@ -0,0 +1,118 @@
+/*
+ Copyright (c) 2013, Matthias Schiffer <mschiffer@universe-factory.net>
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <arpa/inet.h>
+
+#include <linux/if_ether.h>
+
+#include <net/if.h>
+
+#include <netpacket/packet.h>
+
+#include <sys/socket.h>
+#include <sys/types.h>
+
+
+static void usage(const char *name) {
+ fprintf(stderr, "Usage: %s interface dest ethertype\n", name);
+}
+
+int main(int argc, char *argv[]) {
+ if (argc != 4) {
+ usage(argv[0]);
+ return 1;
+ }
+
+ unsigned int ifindex;
+ uint8_t d[ETH_ALEN];
+ uint16_t ethertype;
+
+ ifindex = if_nametoindex(argv[1]);
+ if (!ifindex) {
+ fprintf(stderr, "Error: invalid interface\n");
+ usage(argv[0]);
+ return 1;
+ }
+
+ if (sscanf(argv[2], "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &d[0], &d[1], &d[2], &d[3], &d[4], &d[5]) != 6) {
+ fprintf(stderr, "Error: invalid destination address\n");
+ usage(argv[0]);
+ return 1;
+ }
+
+ if (sscanf(argv[3], "%hx", &ethertype) != 1) {
+ fprintf(stderr, "Error: invalid ethertype\n");
+ usage(argv[0]);
+ return 1;
+ }
+
+ int fd = socket(AF_PACKET, SOCK_DGRAM, htons(ethertype));
+ if (fd < 0) {
+ fprintf(stderr, "Error: socket: %m\n");
+ return 1;
+ }
+
+ const size_t buf_len = 65536;
+ uint8_t buf[buf_len];
+ size_t pos = 0;
+
+ while (!feof(stdin) && !ferror(stdin)) {
+ int read = fread(buf+pos, 1, buf_len-pos, stdin);
+
+ if (read <= 0)
+ break;
+
+ pos += read;
+ }
+
+ if (pos < 46) {
+ /* don't send invalid short frames */
+ memset(buf+pos, 0, 46-pos);
+ pos = 46;
+ }
+
+ struct sockaddr_ll sa;
+ memset(&sa, 0, sizeof(sa));
+ sa.sll_family = AF_PACKET;
+ sa.sll_protocol = htons(ethertype);
+ sa.sll_ifindex = ifindex;
+ sa.sll_halen = ETH_ALEN;
+ memcpy(sa.sll_addr, d, ETH_ALEN);
+
+ if (sendto(fd, buf, pos, 0, (struct sockaddr*)&sa, sizeof(sa)) < 0) {
+ fprintf(stderr, "Error: sendto: %m\n");
+ return 1;
+ }
+
+ close(fd);
+
+ return 0;
+}