sockbpf.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. #include <netinet/in.h>
  2. #include <net/if.h>
  3. #include <net/ethernet.h>
  4. #include <net/bpf.h>
  5. #include <sys/ioctl.h>
  6. #include <string.h>
  7. #include <unistd.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <getopt.h>
  11. #include <fcntl.h>
  12. #include <errno.h>
  13. #include <err.h>
  14. #define DEVICE_BPF "/dev/bpf"
  15. static int verbose;
  16. static const char *out_net = "tap0";
  17. struct ether_addr *daddr;
  18. #define PAYLOAD_LEN 64
  19. union __attribute__((packed)) frame {
  20. struct {
  21. struct ether_header header;
  22. unsigned char payload[PAYLOAD_LEN];
  23. } frame;
  24. unsigned char buffer[ETHER_MAX_LEN];
  25. } out_buffer ;
  26. /* bpf */
  27. int bpf = -1;
  28. static const char *fake_dest = "6:66:6:66:6:66";
  29. #define VPRINTF(...) if(verbose) {printf(__VA_ARGS__);};
  30. #define EPRINTF(...) do {fprintf(stderr, __VA_ARGS__); } while(0);
  31. static void __attribute__((__noreturn__)) usage(void)
  32. {
  33. fputs("\nUsage:\n", stderr);
  34. fputs("sockraw [--if net][--mac mac][--packets samples][--verbose]\n", stderr);
  35. fputs(" --if : interface\n", stderr);
  36. fputs(" --mac : destination MAC address\n", stderr);
  37. fputs(" --packets: packets samples to sent\n", stderr);
  38. fputs(" --verbose: verbose\n", stderr);
  39. exit(EXIT_SUCCESS);
  40. }
  41. /* open BPF interface */
  42. static int get_first_bpf(void)
  43. {
  44. size_t i = 0;
  45. char buf[16] = {0};
  46. for(; i < 99; ) {
  47. sprintf(buf, "%s%zu", DEVICE_BPF, i++);
  48. bpf = open(buf, O_RDWR);
  49. if (bpf != -1)
  50. break;
  51. /* must have root access*/
  52. if (errno == EACCES)
  53. break;
  54. }
  55. return bpf;
  56. }
  57. static void sender(size_t nb)
  58. {
  59. static unsigned char dummy;
  60. size_t total = nb + 1;
  61. printf("Prepare to send %zu packets to %s.\n", nb, out_net);
  62. out_buffer.frame.header.ether_type = htons(PAYLOAD_LEN);
  63. memcpy(out_buffer.frame.header.ether_dhost, daddr, ETHER_ADDR_LEN);
  64. while (nb) {
  65. memset(out_buffer.frame.payload, ++dummy, sizeof out_buffer.frame.payload);
  66. ssize_t r = write(bpf, out_buffer.buffer,
  67. sizeof out_buffer.frame.payload + sizeof(struct ether_header));
  68. if (r == -1)
  69. warn("Unable to send packet #%zu.\n", nb);
  70. else
  71. VPRINTF("Packet #%zu sent.\n", total - nb);
  72. --nb;
  73. }
  74. printf("Done.\n");
  75. }
  76. int main(int argc, char *argv[])
  77. {
  78. size_t packets = 10;
  79. struct ifreq out_if = {0};
  80. const char *mac_address = fake_dest;
  81. /* options */
  82. int ch;
  83. static struct option longopts[] = {
  84. { "if" , required_argument, NULL, 'i' },
  85. { "verbose", no_argument , NULL, 'v' },
  86. { "mac" , required_argument, NULL, 'm' },
  87. { "packets", required_argument, NULL, 'p' },
  88. { NULL, 0, NULL, 0 }
  89. };
  90. while ((ch = getopt_long(argc, argv, "vi:o:p:m:", longopts, NULL)) != -1) {
  91. switch (ch) {
  92. case 'v':
  93. verbose = 1;
  94. break;
  95. case 'i':
  96. out_net = optarg;
  97. break;
  98. case 'p':
  99. packets = strtoul(optarg, NULL, 10);
  100. break;
  101. case 'm':
  102. mac_address = optarg;
  103. break;
  104. case 0:
  105. /* long option */
  106. break;
  107. default:
  108. usage();
  109. }
  110. }
  111. if (argc - optind != 0)
  112. usage();
  113. /* sanity checks */
  114. daddr = ether_aton(mac_address);
  115. if (daddr == NULL)
  116. err(EXIT_FAILURE, "Cannot get mac destination");
  117. if (strlcpy(out_if.ifr_name, out_net, sizeof(out_if.ifr_name)) >= sizeof(out_if.ifr_name))
  118. errx(EXIT_FAILURE, "%s is not a valid interface name.\n", out_net);
  119. /* man 4 BPF */
  120. if (get_first_bpf() < 0)
  121. err(EXIT_FAILURE, "Cannot open bpf interface");
  122. /* Get net device index */
  123. if (ioctl(bpf, BIOCSETIF, &out_if) == -1) {
  124. warn("Cannot open %s interface.\n", out_net);
  125. goto last;
  126. }
  127. /*
  128. * pointless until we do not read _from_ interface
  129. * static int dummy_true = 1;
  130. * if( ioctl( bpf, BIOCIMMEDIATE, &dummy_true ) == -1 ) {
  131. * warn("Can not activate immediate mode.\n");
  132. * }
  133. * if( ioctl( bpf, BIOCGBLEN, &buf_len ) == -1 ) {
  134. * warn("Can not request buffer length\n");
  135. * exit(1);
  136. * }
  137. */
  138. sender(packets);
  139. last:
  140. close(bpf);
  141. return EXIT_SUCCESS;
  142. }