| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- #include <netinet/in.h>
- #include <net/if.h>
- #include <net/ethernet.h>
- #include <net/bpf.h>
- #include <sys/ioctl.h>
- #include <string.h>
- #include <unistd.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <getopt.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <err.h>
- #define DEVICE_BPF "/dev/bpf"
- static int verbose;
- static const char *out_net = "epair0a";
- static const char *dest_net = NULL;
- struct ether_addr *daddr;
- #define PAYLOAD_LEN 64
- union __attribute__((packed)) frame {
- struct {
- struct ether_header header;
- unsigned char payload[PAYLOAD_LEN];
- } frame;
- unsigned char buffer[ETHER_MAX_LEN];
- } out_buffer ;
- /* bpf */
- int bpf = -1;
- static const char *fake_dest = "6:66:6:66:6:66";
- #define VPRINTF(...) if(verbose) {printf(__VA_ARGS__);};
- #define EPRINTF(...) do {fprintf(stderr, __VA_ARGS__); } while(0);
- static void __attribute__((__noreturn__)) usage(void)
- {
- fputs("\nUsage:\n", stderr);
- fputs("sockraw [--if iface][--mac maca[-to iface]][--packets samples][--verbose]\n", stderr);
- fputs(" --if : interface\n", stderr);
- fputs(" --mac : destination MAC address\n", stderr);
- fputs(" --to : destination MAC address from interface name\n", stderr);
- fputs(" --packets: packets samples to sent\n", stderr);
- fputs(" --verbose: verbose\n", stderr);
- exit(EXIT_SUCCESS);
- }
- /* open BPF interface
- *
- * Setup global variable bpf
- *
- * return pbf value on success, -1 on error
- */
- static int get_first_bpf(void)
- {
- size_t i = 0;
- char buf[16] = {0};
- for(; i < 99; ) {
- sprintf(buf, "%s%zu", DEVICE_BPF, i++);
- bpf = open(buf, O_RDWR);
- if (bpf != -1)
- break;
- /* must have root access*/
- if (errno == EACCES)
- break;
- }
- return bpf;
- }
- /*
- * send packets
- *
- * @ifr: destination interface
- * @nb: packets number
- *
- */
- static void sender(struct ifreq *ifr, size_t nb)
- {
- static unsigned char dummy;
- size_t total = nb + 1;
- printf("Prepare to send %zu packets to %s.\n", nb, out_net);
- out_buffer.frame.header.ether_type = htons(PAYLOAD_LEN);
- memcpy(out_buffer.frame.header.ether_dhost, ifr->ifr_addr.sa_data, ETHER_ADDR_LEN);
- while (nb) {
- memset(out_buffer.frame.payload, ++dummy, sizeof out_buffer.frame.payload);
- ssize_t r = write(bpf, out_buffer.buffer,
- sizeof out_buffer.frame.payload + sizeof(struct ether_header));
- if (r == -1)
- warn("Unable to send packet #%zu.\n", nb);
- else
- VPRINTF("Packet #%zu sent.\n", total - nb);
- --nb;
- }
- printf("Done.\n");
- }
- /*
- * Return MAC address
- *
- * @iface: Interface name
- *
- * @return -1 on error, 0 on success
- */
- static int get_hwaddr(const char *iface, struct ifreq *dest_ifr)
- {
- int shw;
- strncpy(dest_ifr->ifr_name, iface, sizeof dest_ifr->ifr_name);
- dest_ifr->ifr_addr.sa_family = AF_LINK;
- if ((shw = socket(AF_INET, SOCK_RAW, 0)) < 0) {
- return -1;
- }
- ioctl(shw, SIOCGHWADDR, dest_ifr);
- close(shw);
- VPRINTF("Destination %s, HW address: %s.\n", iface, ether_ntoa((const struct ether_addr *)dest_ifr->ifr_addr.sa_data));
- return 0;
- }
- int main(int argc, char *argv[])
- {
- size_t packets = 10;
- struct ifreq out_if = {0};
- const char *mac_address = fake_dest;
- struct ifreq dest_ifr = {0};
- int rc;
- /* options */
- int ch;
- static struct option longopts[] = {
- { "if" , required_argument, NULL, 'i' },
- { "to" , required_argument, NULL, 't' },
- { "verbose", no_argument , NULL, 'v' },
- { "mac" , required_argument, NULL, 'm' },
- { "packets", required_argument, NULL, 'p' },
- { NULL, 0, NULL, 0 }
- };
- while ((ch = getopt_long(argc, argv, "vi:t:p:m:", longopts, NULL)) != -1) {
- switch (ch) {
- case 'v':
- verbose = 1;
- break;
- case 't':
- dest_net = optarg;
- break;
- case 'i':
- out_net = optarg;
- break;
- case 'p':
- packets = strtoul(optarg, NULL, 10);
- break;
- case 'm':
- mac_address = optarg;
- break;
- case 0:
- /* long option */
- break;
- default:
- usage();
- }
- }
- if (argc - optind != 0)
- usage();
- /* sanity checks */
- daddr = ether_aton(mac_address);
- if (daddr == NULL)
- err(EXIT_FAILURE, "Cannot get mac destination");
- if (strlcpy(out_if.ifr_name, out_net, sizeof(out_if.ifr_name)) >= sizeof(out_if.ifr_name))
- errx(EXIT_FAILURE, "%s is not a valid interface name.\n", out_net);
- /* man 4 BPF */
- if (get_first_bpf() < 0)
- err(EXIT_FAILURE, "Cannot open bpf interface");
- /* Get net device index */
- if (ioctl(bpf, BIOCSETIF, &out_if) == -1) {
- warn("Cannot open %s interface.\n", out_net);
- goto last;
- }
- rc = dest_net == NULL;
- if (!rc)
- rc = get_hwaddr(dest_net, &dest_ifr);
- if (rc)
- memcpy(dest_ifr.ifr_addr.sa_data, daddr, ETHER_ADDR_LEN);
- /*
- * pointless until we do not read _from_ interface
- * static int dummy_true = 1;
- * if( ioctl( bpf, BIOCIMMEDIATE, &dummy_true ) == -1 ) {
- * warn("Can not activate immediate mode.\n");
- * }
- * if( ioctl( bpf, BIOCGBLEN, &buf_len ) == -1 ) {
- * warn("Can not request buffer length\n");
- * exit(1);
- * }
- */
- sender(&dest_ifr, packets);
- last:
- close(bpf);
- return EXIT_SUCCESS;
- }
|