source: trunk/src/common/sendpacket.c @ 2518

Revision 2518, 27.7 KB checked in by aturner, 18 months ago (diff)

merge r2493 from branches/3.4 to trunk. This is the original TX_RING
support shipped in 3.4.5beta2. refs #435

  • Property svn:keywords set to Id HeadURL Author Rev Date
Line 
1/* $Id$ */
2
3/*
4 *   Copyright (c) 2001-2010 Aaron Turner <aturner at synfin dot net>
5 *
6 *   The Tcpreplay Suite of tools is free software: you can redistribute it
7 *   and/or modify it under the terms of the GNU General Public License as
8 *   published by the Free Software Foundation, either version 3 of the
9 *   License, or with the authors permission any later version.
10 *
11 *   The Tcpreplay Suite is distributed in the hope that it will be useful,
12 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 *   GNU General Public License for more details.
15 *
16 *   You should have received a copy of the GNU General Public License
17 *   along with the Tcpreplay Suite.  If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 /* sendpacket.[ch] is my attempt to write a universal packet injection
21  * API for BPF, libpcap, libdnet, and Linux's PF_PACKET.  I got sick
22  * and tired dealing with libnet bugs and its lack of active maintenence,
23  * but unfortunately, libpcap frame injection support is relatively new
24  * and not everyone uses Linux, so I decided to support all four as
25  * best as possible.  If your platform/OS/hardware supports an additional
26  * injection method, then by all means add it here (and send me a patch).
27  *
28  * Anyways, long story short, for now the order of preference is:
29  * 1. TX_RING
30  * 2. PF_PACKET
31  * 3. BPF
32  * 4. libdnet
33  * 5. pcap_inject()
34  * 6. pcap_sendpacket()
35  *
36  * Right now, one big problem with the pcap_* methods is that libpcap
37  * doesn't provide a reliable method of getting the MAC address of
38  * an interface (required for tcpbridge).
39  * You can use PF_PACKET or BPF to get that, but if your system suports
40  * those, might as well inject directly without going through another
41  * level of indirection.
42  *
43  * Please note that some of this code was copied from Libnet 1.1.3
44  */
45
46#include <string.h>
47#include <errno.h>
48#include <stdarg.h>
49#include <stdio.h>
50#include <sys/types.h>
51#include <sys/time.h>
52#include <sys/ioctl.h>
53#include <sys/file.h>
54#include <sys/socket.h>
55
56#include "config.h"
57#include "defines.h"
58#include "common.h"
59#include "sendpacket.h"
60
61#ifdef FORCE_INJECT_TX_RING
62/* TX_RING uses PF_PACKET API so don't undef it here */
63#undef HAVE_LIBDNET
64#undef HAVE_PCAP_INJECT
65#undef HAVE_PCAP_SENDPACKET
66#undef HAVE_BPF
67#endif
68
69#ifdef FORCE_INJECT_PF_PACKET
70#undef HAVE_TX_RING
71#undef HAVE_LIBDNET
72#undef HAVE_PCAP_INJECT
73#undef HAVE_PCAP_SENDPACKET
74#undef HAVE_BPF
75#endif
76
77#ifdef FORCE_INJECT_LIBDNET
78#undef HAVE_TX_RING
79#undef HAVE_PF_PACKET
80#undef HAVE_PCAP_INJECT
81#undef HAVE_PCAP_SENDPACKET
82#undef HAVE_BPF
83#endif
84
85#ifdef FORCE_INJECT_BPF
86#undef HAVE_TX_RING
87#undef HAVE_LIBDNET
88#undef HAVE_PCAP_INJECT
89#undef HAVE_PCAP_SENDPACKET
90#undef HAVE_PF_PACKET
91#endif
92
93#ifdef FORCE_INJECT_PCAP_INJECT
94#undef HAVE_TX_RING
95#undef HAVE_LIBDNET
96#undef HAVE_PCAP_SENDPACKET
97#undef HAVE_BPF
98#undef HAVE_PF_PACKET
99#endif
100
101#ifdef FORCE_INJECT_PCAP_SENDPACKET
102#undef HAVE_TX_RING
103#undef HAVE_LIBDNET
104#undef HAVE_PCAP_INJECT
105#undef HAVE_BPF
106#undef HAVE_PF_PACKET
107#endif
108
109#if (defined HAVE_WINPCAP && defined HAVE_PCAP_INJECT)
110#undef HAVE_PCAP_INJECT /* configure returns true for some odd reason */
111#endif
112
113#if !defined HAVE_PCAP_INJECT && !defined HAVE_PCAP_SENDPACKET && !defined HAVE_LIBDNET && !defined HAVE_PF_PACKET && !defined HAVE_BPF && !defined TX_RING
114#error You need pcap_inject() or pcap_sendpacket() from libpcap, libdnet, Linux's PF_PACKET/TX_RING or *BSD's BPF
115#endif
116
117
118#ifdef HAVE_SYS_PARAM_H
119#include <sys/param.h>
120#endif
121#ifdef HAVE_SYS_SYSCTL_H
122#include <sys/sysctl.h>
123#endif
124#ifdef HAVE_NET_ROUTE_H
125#include <net/route.h>
126#endif
127#include <stdlib.h>
128#include <unistd.h>
129
130#ifdef HAVE_PF_PACKET
131#undef INJECT_METHOD
132
133/* give priority to TX_RING */
134#ifndef HAVE_TX_RING
135#define INJECT_METHOD "PF_PACKET send()"
136#else
137#define INJECT_METHOD "PF_PACKET / TX_RING"
138#endif
139
140#include <fcntl.h>
141#include <sys/utsname.h>
142#include <net/if.h>
143#include <netinet/in.h>
144//#include <linux/if.h>
145#include <linux/if_ether.h>
146#include <net/if_arp.h>
147#include <netpacket/packet.h>
148
149#ifdef HAVE_TX_RING
150#include "txring.h"
151#endif
152
153#ifndef __GLIBC__
154typedef int socklen_t;
155#endif
156
157static sendpacket_t *sendpacket_open_pf(const char *, char *);
158static struct tcpr_ether_addr *sendpacket_get_hwaddr_pf(sendpacket_t *);
159static int get_iface_index(int fd, const int8_t *device, char *);
160
161#endif /* HAVE_PF_PACKET */
162
163#if defined HAVE_BPF && ! defined INJECT_METHOD
164#undef INJECT_METHOD
165#define INJECT_METHOD "bpf send()"
166
167#include <net/bpf.h>
168#include <sys/sysctl.h>
169#include <net/route.h>
170#include <net/if.h>
171#include <sys/uio.h>
172#include <net/if_dl.h> // used for get_hwaddr_bpf()
173
174static sendpacket_t *sendpacket_open_bpf(const char *, char *) _U_;
175static struct tcpr_ether_addr *sendpacket_get_hwaddr_bpf(sendpacket_t *) _U_;
176
177#endif /* HAVE_BPF */
178
179#if defined HAVE_LIBDNET && ! defined INJECT_METHOD
180#undef INJECT_METHOD
181#define INJECT_METHOD "libdnet eth_send()"
182/* need to undef these which are pulled in via defines.h, prior to importing dnet.h */
183#undef icmp_id
184#undef icmp_seq
185#undef icmp_data
186#undef icmp_mask
187#include <dnet.h>
188
189static sendpacket_t *sendpacket_open_libdnet(const char *, char *) _U_;
190static struct tcpr_ether_addr *sendpacket_get_hwaddr_libdnet(sendpacket_t *) _U_;
191#endif /* HAVE_LIBDNET */
192
193#if (defined HAVE_PCAP_INJECT || defined HAVE_PCAP_SENDPACKET) && ! defined INJECT_METHOD
194static sendpacket_t *sendpacket_open_pcap(const char *, char *) _U_;
195static struct tcpr_ether_addr *sendpacket_get_hwaddr_pcap(sendpacket_t *) _U_;
196#endif /* HAVE_PCAP_INJECT || HAVE_PACKET_SENDPACKET */
197
198#if defined HAVE_PCAP_INJECT && ! defined INJECT_METHOD
199#undef INJECT_METHOD
200#define INJECT_METHOD "pcap_inject()"
201#elif defined HAVE_PCAP_SENDPACKET && ! defined INJECT_METHOD
202#undef INJECT_METHOD
203#define INJECT_METHOD "pcap_sendpacket()"
204#endif
205
206static void sendpacket_seterr(sendpacket_t *sp, const char *fmt, ...);
207
208/**
209 * returns number of bytes sent on success or -1 on error
210 * Note: it is theoretically possible to get a return code >0 and < len
211 * which for most people would be considered an error (the packet wasn't fully sent)
212 * so you may want to test for recode != len too.
213 *
214 * Most socket API's have two interesting errors: ENOBUFS & EAGAIN.  ENOBUFS
215 * is usually due to the kernel buffers being full.  EAGAIN happens when you
216 * try to send traffic faster then the PHY allows.
217 */
218int
219sendpacket(sendpacket_t *sp, const u_char *data, size_t len)
220{
221    int retcode;
222
223    assert(sp);
224    assert(data);
225
226    if (len <= 0)
227        return -1;
228
229TRY_SEND_AGAIN:
230    sp->attempt ++;
231
232#if defined HAVE_PF_PACKET
233#ifdef HAVE_TX_RING
234    retcode = (int)txring_put(sp->tx_ring, data, len);
235#else
236    retcode = (int)send(sp->handle.fd, (void *)data, len, 0);
237#endif
238
239    /*
240     * out of buffers, or hit max PHY speed, silently retry
241     * as long as we're not told to abort
242     */
243    if (retcode < 0 && !sp->abort) {
244        switch (errno) {
245            case EAGAIN:
246                sp->retry_eagain ++;
247                goto TRY_SEND_AGAIN;
248                break;
249            case ENOBUFS:
250                sp->retry_enobufs ++;
251                goto TRY_SEND_AGAIN;
252                break;
253
254            default:
255                sendpacket_seterr(sp, "Error with %s [" COUNTER_SPEC "]: "
256                        "%s (errno = %d)", 
257                        INJECT_METHOD, sp->sent + sp->failed + 1, 
258                        strerror(errno), errno);
259        }
260    }
261
262#elif defined HAVE_BPF
263    retcode = write(sp->handle.fd, (void *)data, len);
264
265    /*
266     * out of buffers, or hit max PHY speed, silently retry
267     * as long as we're not told to abort
268     */
269    if (retcode < 0 && !sp->abort) {
270        switch (errno) {
271            case EAGAIN:
272                sp->retry_eagain ++;
273                goto TRY_SEND_AGAIN;
274                break;
275
276            case ENOBUFS:
277                sp->retry_enobufs ++;
278                goto TRY_SEND_AGAIN;
279                break;
280
281            default:
282                sendpacket_seterr(sp, "Error with %s [" COUNTER_SPEC "]: "
283                        "%s (errno = %d)",
284                        INJECT_METHOD, sp->sent + sp->failed + 1, 
285                        strerror(errno), errno);
286        }
287    }
288
289#elif defined HAVE_LIBDNET
290    retcode = eth_send(sp->handle.ldnet, (void*)data, (size_t)len);
291
292    /*
293     * out of buffers, or hit max PHY speed, silently retry
294     * as long as we're not told to abort
295     */
296    if (retcode < 0 && !sp->abort) {
297        switch (errno) {
298            case EAGAIN:
299                sp->retry_eagain ++;
300                goto TRY_SEND_AGAIN;
301                break;
302
303            case ENOBUFS:
304                sp->retry_enobufs ++;
305                goto TRY_SEND_AGAIN;
306                break;
307
308            default:
309                sendpacket_seterr(sp, "Error with %s [" COUNTER_SPEC "]: "
310                        "%s (errno = %d)",
311                            INJECT_METHOD, sp->sent + sp->failed + 1, 
312                            strerror(errno), errno);
313        }
314    }
315
316#elif defined HAVE_PCAP_INJECT
317    /*
318     * pcap methods don't seem to support ENOBUFS, so we just straight fail
319     * is there a better way???
320     */
321    retcode = pcap_inject(sp->handle.pcap, (void*)data, len);
322    /*
323     * out of buffers, or hit max PHY speed, silently retry
324     * as long as we're not told to abort
325     */
326    if (retcode < 0 && !sp->abort) {
327        switch (errno) {
328            case EAGAIN:
329                sp->retry_eagain ++;
330                goto TRY_SEND_AGAIN;
331                break;
332
333            case ENOBUFS:
334                sp->retry_enobufs ++;
335                goto TRY_SEND_AGAIN;
336                break;
337
338            default:
339                sendpacket_seterr(sp, "Error with %s [" COUNTER_SPEC "]: "
340                        "%s (errno = %d)", 
341                        INJECT_METHOD, sp->sent + sp->failed + 1, 
342                        pcap_geterr(sp->handle.pcap), errno);
343        }
344    }
345
346#elif defined HAVE_PCAP_SENDPACKET
347    retcode = pcap_sendpacket(sp->handle.pcap, data, (int)len);
348    /*
349     * out of buffers, or hit max PHY speed, silently retry
350     * as long as we're not told to abort
351     */
352    if (retcode < 0 && !sp->abort) {
353        switch (errno) {
354            case EAGAIN:
355                sp->retry_eagain ++;
356                goto TRY_SEND_AGAIN;
357                break;
358
359            case ENOBUFS:
360                sp->retry_enobufs ++;
361                goto TRY_SEND_AGAIN;
362                break;
363
364            default:
365                sendpacket_seterr(sp, "Error with %s [" COUNTER_SPEC "]: "
366                        "%s (errno = %d)",
367                        INJECT_METHOD, sp->sent + sp->failed + 1, 
368                        pcap_geterr(sp->handle.pcap), errno);
369            }
370    }
371    /*
372     * pcap_sendpacket returns 0 on success, not the packet length!
373     * hence, we have to fix retcode to be more standard on success
374     */
375    if (retcode == 0)
376        retcode = len;
377
378#endif
379
380    if (retcode < 0) {
381        sp->failed ++;
382    } else if (retcode != (int)len) {
383        sendpacket_seterr(sp, "Only able to write %d bytes out of %u bytes total",
384                          retcode, len);
385    } else {
386        sp->bytes_sent += len;
387        sp->sent ++;
388    }
389    return retcode;
390}
391
392/**
393 * Open the given network device name and returns a sendpacket_t struct
394 * pass the error buffer (in case there's a problem) and the direction
395 * that this interface represents
396 */
397sendpacket_t *
398sendpacket_open(const char *device, char *errbuf, tcpr_dir_t direction)
399{
400    sendpacket_t *sp;
401
402    assert(device);
403    assert(errbuf);
404#if defined HAVE_PF_PACKET
405    sp = sendpacket_open_pf(device, errbuf);
406#elif defined HAVE_BPF
407    sp = sendpacket_open_bpf(device, errbuf);
408#elif defined HAVE_LIBDNET
409    sp = sendpacket_open_libdnet(device, errbuf);
410#elif (defined HAVE_PCAP_INJECT || defined HAVE_PCAP_SENDPACKET)
411    sp = sendpacket_open_pcap(device, errbuf);
412#endif
413    if (sp != NULL) {
414        sp->open = 1;
415        sp->cache_dir = direction;
416    }
417    return sp;
418}
419
420/**
421 * Get packet stats for the given sendpacket_t
422 */
423char *
424sendpacket_getstat(sendpacket_t *sp)
425{
426    static char buf[1024];
427
428    assert(sp);
429
430    memset(buf, 0, sizeof(buf));
431    sprintf(buf, "Statistics for network device: %s\n"
432            "\tAttempted packets:         " COUNTER_SPEC "\n"
433            "\tSuccessful packets:        " COUNTER_SPEC "\n"
434            "\tFailed packets:            " COUNTER_SPEC "\n"
435            "\tRetried packets (ENOBUFS): " COUNTER_SPEC "\n"
436            "\tRetried packets (EAGAIN):  " COUNTER_SPEC "\n",
437            sp->device, sp->attempt, sp->sent, sp->failed, sp->retry_enobufs, sp->retry_eagain);
438    return(buf);
439}
440
441/**
442 * close the given sendpacket
443 */
444int
445sendpacket_close(sendpacket_t *sp)
446{
447    assert(sp);
448    switch(sp->handle_type) {
449    case SP_TYPE_BPF:
450#if (defined HAVE_PCAP_INJECT || defined HAVE_PCAP_SENDPACKET)
451        close(sp->handle.fd);
452#endif
453        break;
454
455    case SP_TYPE_PF_PACKET:
456        case SP_TYPE_TX_RING:
457#ifdef HAVE_PF_PACKET
458        close(sp->handle.fd);
459#endif
460        break;
461
462    case SP_TYPE_LIBPCAP:
463#ifdef HAVE_LIBPCAP
464        pcap_close(sp->handle.pcap);
465#endif
466        break;
467
468    case SP_TYPE_LIBDNET:
469#ifdef HAVE_LIBDNET
470        eth_close(sp->handle.ldnet);
471#endif
472        break;
473
474    case SP_TYPE_LIBNET:
475        err(-1, "Libnet is no longer supported!");
476        break;
477    }
478    safe_free(sp);
479    return 0;
480}
481
482/**
483 * returns the Layer 2 address of the interface current
484 * open.  on error, return NULL
485 */
486struct tcpr_ether_addr *
487sendpacket_get_hwaddr(sendpacket_t *sp)
488{
489    struct tcpr_ether_addr *addr;
490    assert(sp);
491
492    /* if we already have our MAC address stored, just return it */
493    if (memcmp(&sp->ether, "\x00\x00\x00\x00\x00\x00", ETHER_ADDR_LEN) != 0)
494        return &sp->ether;
495
496#if defined HAVE_PF_PACKET
497    addr = sendpacket_get_hwaddr_pf(sp);
498#elif defined HAVE_BPF
499    addr = sendpacket_get_hwaddr_bpf(sp);
500#elif defined HAVE_LIBDNET
501    addr = sendpacket_get_hwaddr_libdnet(sp);
502#elif (defined HAVE_PCAP_INJECT || defined HAVE_PCAP_SENDPACKET)
503    addr = sendpacket_get_hwaddr_pcap(sp);
504#endif
505    return addr;
506}
507
508/**
509 * returns the error string
510 */
511char *
512sendpacket_geterr(sendpacket_t *sp)
513{
514    assert(sp);
515    return sp->errbuf;
516}
517
518/**
519 * Set's the error string
520 */
521static void
522sendpacket_seterr(sendpacket_t *sp, const char *fmt, ...)
523{
524    va_list ap;
525
526    assert(sp);
527
528    va_start(ap, fmt);
529    if (fmt != NULL)
530        (void)vsnprintf(sp->errbuf, SENDPACKET_ERRBUF_SIZE, fmt, ap);
531    va_end(ap);
532
533    sp->errbuf[(SENDPACKET_ERRBUF_SIZE-1)] = '\0'; // be safe
534}
535
536
537#if defined HAVE_PCAP_INJECT || defined HAVE_PCAP_SENDPACKET
538/**
539 * Inner sendpacket_open() method for using libpcap
540 */
541static sendpacket_t *
542sendpacket_open_pcap(const char *device, char *errbuf)
543{
544    pcap_t *pcap;
545    sendpacket_t *sp;
546#ifdef BIOCSHDRCMPLT
547    u_int spoof_eth_src = 1;
548    int fd;
549#endif
550
551    assert(device);
552    assert(errbuf);
553
554    dbg(1, "sendpacket: using Libpcap");
555
556    /* open_pcap_live automatically fills out our errbuf for us */
557    if ((pcap = pcap_open_live(device, 0, 0, 0, errbuf)) == NULL)
558        return NULL;
559
560    sp = (sendpacket_t *)safe_malloc(sizeof(sendpacket_t));
561    strlcpy(sp->device, device, sizeof(sp->device));
562    sp->handle.pcap = pcap;
563
564#ifdef BIOCSHDRCMPLT
565    /*
566     * Only systems using BPF on the backend need this...
567     * other systems don't have ioctl and will get compile errors.
568     */
569    fd = pcap_get_selectable_fd(pcap);
570    if (ioctl(fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1)
571        errx(-1, "Unable to enable source MAC spoof support: %s", strerror(errno));
572#endif
573    sp->handle_type = SP_TYPE_LIBPCAP;
574
575    return sp;
576}
577
578/**
579 * Get the hardware MAC address for the given interface using libpcap
580 */
581static struct tcpr_ether_addr *
582sendpacket_get_hwaddr_pcap(sendpacket_t *sp)
583{
584    assert(sp);
585    sendpacket_seterr(sp, "Error: sendpacket_get_hwaddr() not yet supported for pcap injection");
586    return NULL;
587}
588#endif /* HAVE_PCAP_INJECT || HAVE_PCAP_SENDPACKET */
589
590#if defined HAVE_LIBDNET
591/**
592 * Inner sendpacket_open() method for using libdnet
593 */
594static sendpacket_t *
595sendpacket_open_libdnet(const char *device, char *errbuf)
596{
597    eth_t *ldnet;
598    sendpacket_t *sp;
599
600    assert(device);
601    assert(errbuf);
602
603    dbg(1, "sendpacket: using Libdnet");
604
605    if ((ldnet = eth_open(device)) == NULL)
606        return NULL;
607
608    sp = (sendpacket_t *)safe_malloc(sizeof(sendpacket_t));
609    strlcpy(sp->device, device, sizeof(sp->device));
610    sp->handle.ldnet = ldnet;
611    sp->handle_type = SP_TYPE_LIBDNET;
612    return sp;
613}
614
615/**
616 * Get the hardware MAC address for the given interface using libdnet
617 */
618static struct tcpr_ether_addr *
619sendpacket_get_hwaddr_libdnet(sendpacket_t *sp)
620{
621    struct tcpr_ether_addr *addr;
622    int ret;
623    assert(sp);
624
625    ret = eth_get(sp->handle.ldnet, (eth_addr_t *)addr);
626
627    if (addr == NULL || ret < 0) {
628        sendpacket_seterr(sp, "Error getting hwaddr via libdnet: %s", strerror(errno));
629        return NULL;
630    }
631
632    memcpy(&sp->ether, addr, sizeof(struct tcpr_ether_addr));
633    return(&sp->ether);
634}
635#endif /* HAVE_LIBDNET */
636
637#if defined HAVE_PF_PACKET
638/**
639 * Inner sendpacket_open() method for using Linux's PF_PACKET or TX_RING
640 */
641static sendpacket_t *
642sendpacket_open_pf(const char *device, char *errbuf)
643{
644    int mysocket;
645    sendpacket_t *sp;
646    struct ifreq ifr;
647    struct sockaddr_ll sa;
648    int n = 1, err;
649    socklen_t errlen = sizeof(err);
650    unsigned int mtu=1500;
651
652    assert(device);
653    assert(errbuf);
654
655#if defined TX_RING
656    dbg(1, "sendpacket: using TX_RING");
657#else
658    dbg(1, "sendpacket: using PF_PACKET");
659#endif
660
661   /* open our socket */
662    if ((mysocket = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) < 0) {
663        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "socket: %s", strerror(errno));
664        return NULL;
665    }
666
667
668    /* get the interface id for the device */
669    if ((sa.sll_ifindex = get_iface_index(mysocket, device, errbuf)) < 0) {
670        close(mysocket);
671        return NULL;
672    }
673
674    /* bind socket to our interface id */
675    sa.sll_family = AF_PACKET;
676    sa.sll_protocol = htons(ETH_P_ALL);
677    if (bind(mysocket, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
678        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "bind error: %s", strerror(errno));
679        close(mysocket);
680        return NULL;
681    }
682
683    /* check for errors, network down, etc... */
684    if (getsockopt(mysocket, SOL_SOCKET, SO_ERROR, &err, &errlen) < 0) {
685        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "error opening %s: %s", device,
686                 strerror(errno));
687        close(mysocket);
688        return NULL;
689    }
690
691    if (err > 0) {
692        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "error opening %s: %s", device,
693                 strerror(err));
694        close(mysocket);
695        return NULL;
696    }
697
698    /* get hardware type for our interface */
699    memset(&ifr, 0, sizeof(ifr));
700    strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
701
702    if (ioctl(mysocket, SIOCGIFHWADDR, &ifr) < 0) {
703        close(mysocket);
704        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "Error getting hardware type: %s", 
705                strerror(errno));
706        return NULL;
707    }
708
709    /* make sure it's not loopback (PF_PACKET doesn't support it) */
710    if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER)
711        warnx("Unsupported physical layer type 0x%04x on %s.  Maybe it works, maybe it wont."
712              "  See tickets #123/318", ifr.ifr_hwaddr.sa_family, device);
713
714#ifdef SO_BROADCAST
715    /*
716     * man 7 socket
717     *
718     * Set or get the broadcast flag. When  enabled,  datagram  sockets
719     * receive packets sent to a broadcast address and they are allowed
720     * to send packets to a broadcast  address.   This  option  has no
721     * effect on stream-oriented sockets.
722     */
723    if (setsockopt(mysocket, SOL_SOCKET, SO_BROADCAST, &n, sizeof(n)) == -1) {
724        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE,
725                "SO_BROADCAST: %s", strerror(errno));
726        close(mysocket);
727        return NULL;
728    }
729#endif  /*  SO_BROADCAST  */
730
731    /* prep & return our sp handle */
732    sp = (sendpacket_t *)safe_malloc(sizeof(sendpacket_t));
733    strlcpy(sp->device, device, sizeof(sp->device));
734    sp->handle.fd = mysocket;
735
736#ifdef HAVE_TX_RING
737    /* Look up for MTU */
738    memset(&ifr, 0, sizeof(ifr));
739    strlcpy(ifr.ifr_name, sp->device, sizeof(ifr.ifr_name));
740
741    if (ioctl(mysocket, SIOCGIFMTU, &ifr) < 0) {
742        close(mysocket);
743        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "Error getting MTU: %s", strerror(errno));
744        return NULL;
745    }
746    mtu = ifr.ifr_ifru.ifru_mtu;
747
748    /* Init TX ring for sp->handle.fd socket */
749    if ((sp->tx_ring = txring_init(sp->handle.fd, mtu)) == 0) { 
750        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "txring_init: %s", strerror(errno));
751        close(mysocket);
752        return NULL;
753    }
754    sp->handle_type = SP_TYPE_TX_RING;
755#else
756    sp->handle_type = SP_TYPE_PF_PACKET;
757#endif
758    return sp;
759}
760
761/**
762 * get the interface index (necessary for sending packets w/ PF_PACKET)
763 */
764static int
765get_iface_index(int fd, const int8_t *device, char *errbuf) {
766    struct ifreq ifr;
767
768    memset(&ifr, 0, sizeof(ifr));
769    strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
770
771    if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1) {
772        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "ioctl: %s", strerror(errno));
773        return (-1);
774    }
775
776    return ifr.ifr_ifindex;
777}
778
779/**
780 * get's the hardware address via Linux's PF packet interface
781 */
782struct tcpr_ether_addr *
783sendpacket_get_hwaddr_pf(sendpacket_t *sp)
784{
785    struct ifreq ifr;
786    int fd;
787
788    assert(sp);
789
790    if (!sp->open) {
791        sendpacket_seterr(sp, "Unable to get hardware address on un-opened sendpacket handle");
792        return NULL;
793    }
794
795
796    /* create dummy socket for ioctl */
797    if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
798        sendpacket_seterr(sp, "Unable to open dummy socket for get_hwaddr: %s", strerror(errno));
799        return NULL;
800    }
801
802    memset(&ifr, 0, sizeof(ifr));
803    strlcpy(ifr.ifr_name, sp->device, sizeof(ifr.ifr_name));
804
805    if (ioctl(fd, SIOCGIFHWADDR, (int8_t *)&ifr) < 0) {
806        close(fd);
807        sendpacket_seterr(sp, "Error getting hardware address: %s", strerror(errno));
808        return NULL;
809    }
810
811    memcpy(&sp->ether, &ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
812    close(fd);
813    return(&sp->ether);
814}
815#endif /* HAVE_PF_PACKET */
816
817#if defined HAVE_BPF
818/**
819 * Inner sendpacket_open() method for using BSD's BPF interface
820 */
821static sendpacket_t *
822sendpacket_open_bpf(const char *device, char *errbuf)
823{
824    sendpacket_t *sp;
825    char bpf_dev[10];
826    int dev, mysocket, link_offset, link_type;
827    struct ifreq ifr;
828    struct bpf_version bv;
829    u_int v;
830#if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT)
831    u_int spoof_eth_src = 1;
832#endif
833
834    assert(device);
835    assert(errbuf);
836    memset(&ifr, '\0', sizeof(struct ifreq));
837
838    dbg(1, "sendpacket: using BPF");
839    /* open socket */
840    mysocket = -1;
841    for (dev = 0; dev <= 9; dev ++) {
842        memset(bpf_dev, '\0', sizeof(bpf_dev));
843        snprintf(bpf_dev, sizeof(bpf_dev), "/dev/bpf%d", dev);
844        if ((mysocket = open(bpf_dev, O_RDWR, 0)) > 0) {
845            break;
846        }
847    }
848
849    /* error?? */
850    if (mysocket < 0) {
851        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE,
852                 "Unable to open /dev/bpfX: %s", strerror(errno));
853        errbuf[SENDPACKET_ERRBUF_SIZE -1] = '\0';
854        return NULL;
855    }
856
857    /* get BPF version */
858    if (ioctl(mysocket, BIOCVERSION, (caddr_t)&bv) < 0) {
859        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "Unable to get bpf version: %s", strerror(errno));
860        return NULL;
861    }
862
863    if (bv.bv_major != BPF_MAJOR_VERSION || bv.bv_minor != BPF_MINOR_VERSION) {
864        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "Kernel's bpf version is out of date.");
865        return NULL;
866    }
867
868    /* attach to device */
869    strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
870    if (ioctl(mysocket, BIOCSETIF, (caddr_t)&ifr) < 0) {
871        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "Unable to bind %s to %s: %s",
872                 bpf_dev, device, strerror(errno));
873        return NULL;
874    }
875
876    /* get datalink type */
877    if (ioctl(mysocket, BIOCGDLT, (caddr_t)&v) < 0) {
878        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE, "Unable to get datalink type: %s",
879                 strerror(errno));
880        return NULL;
881    }
882
883    /*
884     *  NetBSD and FreeBSD BPF have an ioctl for enabling/disabling
885     *  automatic filling of the link level source address.
886     */
887#if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT)
888    if (ioctl(mysocket, BIOCSHDRCMPLT, &spoof_eth_src) == -1) {
889        snprintf(errbuf, SENDPACKET_ERRBUF_SIZE,
890                 "Unable to enable spoofing src MAC: %s", strerror(errno));
891        return NULL;
892    }
893#endif
894
895    /* assign link type and offset */
896    switch (v) {
897    case DLT_SLIP:
898        link_offset = 0x10;
899        break;
900    case DLT_RAW:
901        link_offset = 0x0;
902        break;
903    case DLT_PPP:
904        link_offset = 0x04;
905        break;
906    case DLT_EN10MB:
907    default: /* default to Ethernet */
908        link_offset = 0xe;
909        break;
910    }
911#if _BSDI_VERSION - 0 > 199510
912    switch (v) {
913    case DLT_SLIP:
914        v = DLT_SLIP_BSDOS;
915        link_offset = 0x10;
916        break;
917    case DLT_PPP:
918        v = DLT_PPP_BSDOS;
919        link_offset = 0x04;
920        break;
921    }
922#endif
923
924    link_type = v;
925
926    /* allocate our sp handle, and return it */
927    sp = (sendpacket_t *)safe_malloc(sizeof(sendpacket_t));
928    strlcpy(sp->device, device, sizeof(sp->device));
929    sp->handle.fd = mysocket;
930    //sp->link_type = link_type;
931    //sp->link_offset = link_offset;
932    sp->handle_type = SP_TYPE_BPF;
933
934    return sp;
935}
936
937/**
938 * Get the interface hardware MAC address when using BPF
939 */
940struct tcpr_ether_addr *
941sendpacket_get_hwaddr_bpf(sendpacket_t *sp)
942{
943    int mib[6];
944    size_t len;
945    int8_t *buf, *next, *end;
946    struct if_msghdr *ifm;
947    struct sockaddr_dl *sdl;
948
949    assert(sp);
950
951    mib[0] = CTL_NET;
952    mib[1] = AF_ROUTE;
953    mib[2] = 0;
954    mib[3] = AF_LINK;
955    mib[4] = NET_RT_IFLIST;
956    mib[5] = 0;
957
958    if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1) {
959        sendpacket_seterr(sp, "%s(): sysctl(): %s", __func__, strerror(errno));
960        return NULL;
961    }
962
963    buf = (int8_t *)safe_malloc(len);
964
965    if (sysctl(mib, 6, buf, &len, NULL, 0) == -1) {
966        sendpacket_seterr(sp, "%s(): sysctl(): %s", __func__, strerror(errno));
967        safe_free(buf);
968        return NULL;
969    }
970
971    end = buf + len;
972    for (next = buf; next < end; next += ifm->ifm_msglen) {
973        ifm = (struct if_msghdr *)next;
974        if (ifm->ifm_type == RTM_IFINFO) {
975            sdl = (struct sockaddr_dl *)(ifm + 1);
976            if (strncmp(&sdl->sdl_data[0], sp->device, sdl->sdl_len) == 0) {
977                memcpy(&sp->ether, LLADDR(sdl), ETHER_ADDR_LEN);
978                break;
979            }
980        }
981    }
982    safe_free(buf);
983    return(&sp->ether);
984}
985
986#endif /* HAVE_BPF */
987
988/**
989 * Get the DLT type of the opened sendpacket
990 * Return -1 if we can't figure it out, else return the DLT_ value
991 */
992int
993sendpacket_get_dlt(sendpacket_t *sp)
994{
995    int dlt;
996#if defined HAVE_BPF
997    int rcode;
998
999    if ((rcode = ioctl(sp->handle.fd, BIOCGDLT, &dlt)) < 0) {
1000        warnx("Unable to get DLT value for BPF device (%s): %s", sp->device, strerror(errno));
1001        return(-1);
1002    }
1003#elif defined HAVE_PF_PACKET || defined HAVE_LIBDNET
1004    /* use libpcap to get dlt */
1005    pcap_t *pcap;
1006    char errbuf[PCAP_ERRBUF_SIZE];
1007    if ((pcap = pcap_open_live(sp->device, 65535, 0, 0, errbuf)) == NULL) {
1008        warnx("Unable to get DLT value for %s: %s", sp->device, errbuf);
1009        return(-1);
1010    }
1011    dlt = pcap_datalink(pcap);
1012    pcap_close(pcap);
1013#elif defined HAVE_PCAP_SENDPACKET || defined HAVE_PCAP_INJECT
1014    dlt = pcap_datalink(sp->handle.pcap);
1015#endif
1016    return dlt;
1017}
1018
1019/**
1020 * \brief Returns a string of the name of the injection method being used
1021 */
1022const char *
1023sendpacket_get_method()
1024{
1025    return INJECT_METHOD;
1026}
1027
1028/**
1029 * \brief Cause the currently running sendpacket() call
1030 */
1031void
1032sendpacket_abort(sendpacket_t *sp)
1033{
1034    assert(sp);
1035
1036    sp->abort = true;
1037}
Note: See TracBrowser for help on using the repository browser.