123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- #include <stdlib.h>
- #include <stdio.h>
- #include <pcap.h>
- #ifdef _WIN32
- #include <tchar.h>
- BOOL LoadNpcapDlls()
- {
- _TCHAR npcap_dir[512];
- UINT len;
- len = GetSystemDirectory(npcap_dir, 480);
- if (!len) {
- fprintf(stderr, "Error in GetSystemDirectory: %x", GetLastError());
- return FALSE;
- }
- _tcscat_s(npcap_dir, 512, _T("\\Npcap"));
- if (SetDllDirectory(npcap_dir) == 0) {
- fprintf(stderr, "Error in SetDllDirectory: %x", GetLastError());
- return FALSE;
- }
- return TRUE;
- }
- #endif
- /* case-insensitive string comparison that may mix up special characters and numbers */
- int close_enough(char *one, char *two)
- {
- while (*one && *two)
- {
- if ( *one != *two && !(
- (*one >= 'a' && *one - *two == 0x20) ||
- (*two >= 'a' && *two - *one == 0x20)
- ))
- {
- return 0;
- }
- one++;
- two++;
- }
- if (*one || *two)
- {
- return 0;
- }
- return 1;
- }
- #define ORIG_PACKET_LEN 64
- int main(int argc, char **argv)
- {
- pcap_t *fp;
- char errbuf[PCAP_ERRBUF_SIZE] = {0};
- u_char packet[ORIG_PACKET_LEN] =
- /* Ethernet frame header */
- "\xff\xff\xff\xff\xff\xff" /* dst mac */
- "\x02\x02\x02\x02\x02\x02" /* src mac */
- "\x08\x00" /* ethertype IPv4 */
- /* IPv4 packet header */
- "\x45\x00\x00\x00" /* IPv4, minimal header, length TBD */
- "\x12\x34\x00\x00" /* IPID 0x1234, no fragmentation */
- "\x10\x11\x00\x00" /* TTL 0x10, UDP, checksum (not required) */
- "\x00\x00\x00\x00" /* src IP (TBD) */
- "\xff\xff\xff\xff" /* dst IP (broadcast) */
- /* UDP header */
- "\x00\x07\x00\x07" /* src port 7, dst port 7 (echo) */
- "\x00\x00\x00\x00" /* length TBD, cksum 0 (unset) */
- ;
- u_char *sendme = packet;
- size_t packet_len = ORIG_PACKET_LEN;
- pcap_if_t *ifaces = NULL;
- pcap_if_t *dev = NULL;
- pcap_addr_t *addr = NULL;
- #ifdef _WIN32
- /* Load Npcap and its functions. */
- if (!LoadNpcapDlls())
- {
- fprintf(stderr, "Couldn't load Npcap\n");
- exit(1);
- }
- #endif
- /* Check the validity of the command line */
- if (argc != 2)
- {
- printf("usage: %s interface", argv[0]);
- return 1;
- }
-
- if (0 != pcap_init(PCAP_CHAR_ENC_LOCAL, errbuf)) {
- fprintf(stderr, "Failed to initialize pcap lib: %s\n", errbuf);
- return 2;
- }
- /* Find the IPv4 address of the device */
- if (0 != pcap_findalldevs(&ifaces, errbuf)) {
- fprintf(stderr, "Failed to get list of devices: %s\n", errbuf);
- return 2;
- }
- for (dev = ifaces; dev != NULL; dev = dev->next)
- {
- if (close_enough(dev->name, argv[1]))
- {
- break;
- }
- }
- if (dev == NULL) {
- fprintf(stderr, "Could not find %s in the list of devices\n", argv[1]);
- return 3;
- }
- for (addr = dev->addresses; addr != NULL; addr = addr->next)
- {
- if (addr->addr->sa_family == AF_INET)
- {
- break;
- }
- }
- if (addr == NULL) {
- fprintf(stderr, "Could not find IPv4 address for %s\n", argv[1]);
- return 3;
- }
- /* Fill in the length and source addr and calculate checksum */
- packet[14 + 2] = 0xff & ((ORIG_PACKET_LEN - 14) >> 8);
- packet[14 + 3] = 0xff & (ORIG_PACKET_LEN - 14);
- /* UDP length */
- packet[14 + 20 + 4] = 0xff & ((ORIG_PACKET_LEN - 14 - 20) >> 8);
- packet[14 + 20 + 5] = 0xff & (ORIG_PACKET_LEN - 14 - 20);
- *(u_long *)(packet + 14 + 12) = ((struct sockaddr_in *)(addr->addr))->sin_addr.S_un.S_addr;
- uint32_t cksum = 0;
- for (int i=14; i < 14 + 4 * (packet[14] & 0xf); i += 2)
- {
- cksum += *(uint16_t *)(packet + i);
- }
- while (cksum>>16)
- cksum = (cksum & 0xffff) + (cksum >> 16);
- cksum = ~cksum;
- *(uint16_t *)(packet + 14 + 10) = cksum;
- /* Open the adapter */
- if ((fp = pcap_open_live(argv[1], // name of the device
- 0, // portion of the packet to capture. 0 == no capture.
- 0, // non-promiscuous mode
- 1000, // read timeout
- errbuf // error buffer
- )) == NULL)
- {
- fprintf(stderr,"\nUnable to open the adapter. %s is not supported by Npcap\n", argv[1]);
- return 2;
- }
-
- switch(pcap_datalink(fp))
- {
- case DLT_NULL:
- /* Skip Ethernet header, retreat NULL header length */
- #define NULL_VS_ETH_DIFF (14 - 4)
- sendme = packet + NULL_VS_ETH_DIFF;
- packet_len -= NULL_VS_ETH_DIFF;
- // Pretend IPv4
- sendme[0] = 2;
- sendme[1] = 0;
- sendme[2] = 0;
- sendme[3] = 0;
- break;
- case DLT_EN10MB:
- /* Already set up */
- sendme = packet;
- break;
- default:
- fprintf(stderr, "\nError, unknown data-link type %u\n", pcap_datalink(fp));
- return 4;
- }
-
- /* Send down the packet */
- if (pcap_sendpacket(fp, // Adapter
- sendme, // buffer with the packet
- packet_len // size
- ) != 0)
- {
- fprintf(stderr,"\nError sending the packet: %s\n", pcap_geterr(fp));
- return 3;
- }
- pcap_close(fp);
- return 0;
- }
|