/*
 * Linux packet socket monitor
 * Copyright (c) 2010, Jouni Malinen <j@w1.fi>
 *
 * This software may be distributed under the terms of the BSD license.
 * See README for more details.
 */

#include "utils/includes.h"
#include <net/if.h>
#include <netpacket/packet.h>

#include "utils/common.h"
#include "utils/eloop.h"
#include "wlantest.h"


static void monitor_read(int sock, void *eloop_ctx, void *sock_ctx)
{
	struct wlantest *wt = eloop_ctx;
	u8 buf[3000];
	int len;

	len = recv(sock, buf, sizeof(buf), 0);
	if (len < 0) {
		wpa_printf(MSG_INFO, "recv(PACKET): %s", strerror(errno));
		return;
	}

	write_pcap_captured(wt, buf, len);
	wlantest_process(wt, buf, len);
}


static void monitor_read_wired(int sock, void *eloop_ctx, void *sock_ctx)
{
	struct wlantest *wt = eloop_ctx;
	u8 buf[3000];
	int len;

	len = recv(sock, buf, sizeof(buf), 0);
	if (len < 0) {
		wpa_printf(MSG_INFO, "recv(PACKET): %s", strerror(errno));
		return;
	}

	wlantest_process_wired(wt, buf, len);
}


int monitor_init(struct wlantest *wt, const char *ifname)
{
	struct sockaddr_ll ll;

	os_memset(&ll, 0, sizeof(ll));
	ll.sll_family = AF_PACKET;
	ll.sll_ifindex = if_nametoindex(ifname);
	if (ll.sll_ifindex == 0) {
		wpa_printf(MSG_ERROR, "Monitor interface '%s' does not exist",
			   ifname);
		return -1;
	}

	wt->monitor_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
	if (wt->monitor_sock < 0) {
		wpa_printf(MSG_ERROR, "socket(PF_PACKET,SOCK_RAW): %s",
			   strerror(errno));
		return -1;
	}

	if (bind(wt->monitor_sock, (struct sockaddr *) &ll, sizeof(ll)) < 0) {
		wpa_printf(MSG_ERROR, "bind(PACKET): %s", strerror(errno));
		close(wt->monitor_sock);
		wt->monitor_sock = -1;
		return -1;
	}

	if (eloop_register_read_sock(wt->monitor_sock, monitor_read, wt, NULL))
	{
		wpa_printf(MSG_ERROR, "Could not register monitor read "
			   "socket");
		close(wt->monitor_sock);
		wt->monitor_sock = -1;
		return -1;
	}

	return 0;
}


int monitor_init_wired(struct wlantest *wt, const char *ifname)
{
	struct sockaddr_ll ll;

	os_memset(&ll, 0, sizeof(ll));
	ll.sll_family = AF_PACKET;
	ll.sll_ifindex = if_nametoindex(ifname);
	if (ll.sll_ifindex == 0) {
		wpa_printf(MSG_ERROR, "Monitor interface '%s' does not exist",
			   ifname);
		return -1;
	}

	wt->monitor_wired = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
	if (wt->monitor_wired < 0) {
		wpa_printf(MSG_ERROR, "socket(PF_PACKET,SOCK_RAW): %s",
			   strerror(errno));
		return -1;
	}

	if (bind(wt->monitor_wired, (struct sockaddr *) &ll, sizeof(ll)) < 0) {
		wpa_printf(MSG_ERROR, "bind(PACKET): %s", strerror(errno));
		close(wt->monitor_wired);
		wt->monitor_wired = -1;
		return -1;
	}

	if (eloop_register_read_sock(wt->monitor_wired, monitor_read_wired,
				     wt, NULL)) {
		wpa_printf(MSG_ERROR, "Could not register monitor read "
			   "socket");
		close(wt->monitor_wired);
		wt->monitor_wired = -1;
		return -1;
	}

	return 0;
}


void monitor_deinit(struct wlantest *wt)
{
	if (wt->monitor_sock >= 0) {
		eloop_unregister_read_sock(wt->monitor_sock);
		close(wt->monitor_sock);
		wt->monitor_sock = -1;
	}

	if (wt->monitor_wired >= 0) {
		eloop_unregister_read_sock(wt->monitor_wired);
		close(wt->monitor_wired);
		wt->monitor_wired = -1;
	}
}
