capture.c 3.09 KB
Newer Older
1
/* horst - Highly Optimized Radio Scanning Tool
2
 *
3
 * Copyright (C) 2005-2016 Bruno Randolf (br1@einfach.org)
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include <stdio.h>
#include <string.h>
#include <unistd.h>
Bruno Randolf's avatar
Bruno Randolf committed
23
#include <stdlib.h>
24 25 26 27
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netpacket/packet.h>
#include <net/ethernet.h>
28
#include <net/if.h>
29 30 31 32 33
#include <arpa/inet.h>
#include <err.h>

#include "capture.h"
#include "util.h"
34
#include "main.h"
35 36 37 38 39


/*
 *  Get the hardware type of the given interface as ARPHRD_xxx constant.
 */
Bruno Randolf's avatar
Bruno Randolf committed
40
int device_get_hwinfo(int fd, char* ifname, unsigned char* mac)
41 42 43 44
{
	struct ifreq ifr;

	memset(&ifr, 0, sizeof(ifr));
45 46
	strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1);
	ifr.ifr_name[IFNAMSIZ - 1] = '\0';
47

48
	if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0)
Bruno Randolf's avatar
Bruno Randolf committed
49
		err(1, "Could not get arptype");
50
	DEBUG("ARPTYPE %d\n", ifr.ifr_hwaddr.sa_family);
51 52
	memcpy(mac, ifr.ifr_hwaddr.sa_data, 6);
	DEBUG("MY MAC %s\n", ether_sprintf(mac));
53 54 55
	return ifr.ifr_hwaddr.sa_family;
}

Bruno Randolf's avatar
Bruno Randolf committed
56
static void set_receive_buffer(int fd, int sockbufsize)
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
{
	int ret;

	/* the maximum allowed value is set by the rmem_max sysctl */
	FILE* PF = fopen("/proc/sys/net/core/rmem_max", "w");
	fprintf(PF, "%d", sockbufsize);
	fclose(PF);

	ret = setsockopt (fd, SOL_SOCKET, SO_RCVBUF, &sockbufsize, sizeof(sockbufsize));
	if (ret != 0)
		err(1, "setsockopt failed");

#if DO_DEBUG
	socklen_t size = sizeof(sockbufsize);
	sockbufsize = 0;
	ret = getsockopt(fd, SOL_SOCKET, SO_RCVBUF, &sockbufsize, &size);
	if (ret != 0)
		err(1, "getsockopt failed");
	DEBUG("socket receive buffer size %d\n", sockbufsize);
#endif
}

Bruno Randolf's avatar
Bruno Randolf committed
79
int open_packet_socket(char* devname, int recv_buffer_size)
80 81
{
	int ret;
82
	int mon_fd;
83
	int ifindex;
Bruno Randolf's avatar
Bruno Randolf committed
84
	struct sockaddr_ll sall;
85 86

	mon_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
Bruno Randolf's avatar
Bruno Randolf committed
87
	if (mon_fd < 0) {
88
		printlog("Could not create packet socket! Please run horst as root!");
Bruno Randolf's avatar
Bruno Randolf committed
89 90
		exit(1);
	}
91 92

	/* bind only to one interface */
93
	ifindex = if_nametoindex(devname);
94

95
	memset(&sall, 0, sizeof(struct sockaddr_ll));
96 97 98 99 100 101 102 103
	sall.sll_ifindex = ifindex;
	sall.sll_family = AF_PACKET;
	sall.sll_protocol = htons(ETH_P_ALL);

	ret = bind(mon_fd, (struct sockaddr*)&sall, sizeof(sall));
	if (ret != 0)
		err(1, "bind failed");

104 105
	if (recv_buffer_size)
		set_receive_buffer(mon_fd, recv_buffer_size);
106

107
	return mon_fd;
108 109
}

Bruno Randolf's avatar
Bruno Randolf committed
110
inline int recv_packet(int fd, unsigned char* buffer, size_t bufsize)
111
{
112
	return recv(fd, buffer, bufsize, MSG_DONTWAIT);
113 114
}

Bruno Randolf's avatar
Bruno Randolf committed
115
void close_packet_socket(int fd)
116
{
117
	if (fd > 0)
118
		close(fd);
119
}