/*
 * hostapd / IEEE 802.11F-2003 Inter-Access Point Protocol (IAPP)
 * Copyright (c) 2002-2007, Jouni Malinen <j@w1.fi>
 *
 * This software may be distributed under the terms of the BSD license.
 * See README for more details.
 *
 * Note: IEEE 802.11F-2003 was a experimental use specification. It has expired
 * and IEEE has withdrawn it. In other words, it is likely better to look at
 * using some other mechanism for AP-to-AP communication than extending the
 * implementation here.
 */

/* TODO:
 * Level 1: no administrative or security support
 *	(e.g., static BSSID to IP address mapping in each AP)
 * Level 2: support for dynamic mapping of BSSID to IP address
 * Level 3: support for encryption and authentication of IAPP messages
 * - add support for MOVE-notify and MOVE-response (this requires support for
 *   finding out IP address for previous AP using RADIUS)
 * - add support for Send- and ACK-Security-Block to speedup IEEE 802.1X during
 *   reassociation to another AP
 * - implement counters etc. for IAPP MIB
 * - verify endianness of fields in IAPP messages; are they big-endian as
 *   used here?
 * - RADIUS connection for AP registration and BSSID to IP address mapping
 * - TCP connection for IAPP MOVE, CACHE
 * - broadcast ESP for IAPP ADD-notify
 * - ESP for IAPP MOVE messages
 * - security block sending/processing
 * - IEEE 802.11 context transfer
 */

#include "utils/includes.h"
#include <net/if.h>
#include <sys/ioctl.h>
#ifdef USE_KERNEL_HEADERS
#include <linux/if_packet.h>
#else /* USE_KERNEL_HEADERS */
#include <netpacket/packet.h>
#endif /* USE_KERNEL_HEADERS */

#include "utils/common.h"
#include "utils/eloop.h"
#include "common/ieee802_11_defs.h"
#include "hostapd.h"
#include "ap_config.h"
#include "ieee802_11.h"
#include "sta_info.h"
#include "iapp.h"


#define IAPP_MULTICAST "224.0.1.178"
#define IAPP_UDP_PORT 3517
#define IAPP_TCP_PORT 3517

struct iapp_hdr {
	u8 version;
	u8 command;
	be16 identifier;
	be16 length;
	/* followed by length-6 octets of data */
} __attribute__ ((packed));

#define IAPP_VERSION 0

enum IAPP_COMMAND {
	IAPP_CMD_ADD_notify = 0,
	IAPP_CMD_MOVE_notify = 1,
	IAPP_CMD_MOVE_response = 2,
	IAPP_CMD_Send_Security_Block = 3,
	IAPP_CMD_ACK_Security_Block = 4,
	IAPP_CMD_CACHE_notify = 5,
	IAPP_CMD_CACHE_response = 6,
};


/* ADD-notify - multicast UDP on the local LAN */
struct iapp_add_notify {
	u8 addr_len; /* ETH_ALEN */
	u8 reserved;
	u8 mac_addr[ETH_ALEN];
	be16 seq_num;
} __attribute__ ((packed));


/* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */
struct iapp_layer2_update {
	u8 da[ETH_ALEN]; /* broadcast */
	u8 sa[ETH_ALEN]; /* STA addr */
	be16 len; /* 6 */
	u8 dsap; /* null DSAP address */
	u8 ssap; /* null SSAP address, CR=Response */
	u8 control;
	u8 xid_info[3];
} __attribute__ ((packed));


/* MOVE-notify - unicast TCP */
struct iapp_move_notify {
	u8 addr_len; /* ETH_ALEN */
	u8 reserved;
	u8 mac_addr[ETH_ALEN];
	u16 seq_num;
	u16 ctx_block_len;
	/* followed by ctx_block_len bytes */
} __attribute__ ((packed));


/* MOVE-response - unicast TCP */
struct iapp_move_response {
	u8 addr_len; /* ETH_ALEN */
	u8 status;
	u8 mac_addr[ETH_ALEN];
	u16 seq_num;
	u16 ctx_block_len;
	/* followed by ctx_block_len bytes */
} __attribute__ ((packed));

enum {
	IAPP_MOVE_SUCCESSFUL = 0,
	IAPP_MOVE_DENIED = 1,
	IAPP_MOVE_STALE_MOVE = 2,
};


/* CACHE-notify */
struct iapp_cache_notify {
	u8 addr_len; /* ETH_ALEN */
	u8 reserved;
	u8 mac_addr[ETH_ALEN];
	u16 seq_num;
	u8 current_ap[ETH_ALEN];
	u16 ctx_block_len;
	/* ctx_block_len bytes of context block followed by 16-bit context
	 * timeout */
} __attribute__ ((packed));


/* CACHE-response - unicast TCP */
struct iapp_cache_response {
	u8 addr_len; /* ETH_ALEN */
	u8 status;
	u8 mac_addr[ETH_ALEN];
	u16 seq_num;
} __attribute__ ((packed));

enum {
	IAPP_CACHE_SUCCESSFUL = 0,
	IAPP_CACHE_STALE_CACHE = 1,
};


/* Send-Security-Block - unicast TCP */
struct iapp_send_security_block {
	u8 iv[8];
	u16 sec_block_len;
	/* followed by sec_block_len bytes of security block */
} __attribute__ ((packed));


/* ACK-Security-Block - unicast TCP */
struct iapp_ack_security_block {
	u8 iv[8];
	u8 new_ap_ack_authenticator[48];
} __attribute__ ((packed));


struct iapp_data {
	struct hostapd_data *hapd;
	u16 identifier; /* next IAPP identifier */
	struct in_addr own, multicast;
	int udp_sock;
	int packet_sock;
};


static void iapp_send_add(struct iapp_data *iapp, u8 *mac_addr, u16 seq_num)
{
	char buf[128];
	struct iapp_hdr *hdr;
	struct iapp_add_notify *add;
	struct sockaddr_in addr;

	/* Send IAPP ADD-notify to remove possible association from other APs
	 */

	hdr = (struct iapp_hdr *) buf;
	hdr->version = IAPP_VERSION;
	hdr->command = IAPP_CMD_ADD_notify;
	hdr->identifier = host_to_be16(iapp->identifier++);
	hdr->length = host_to_be16(sizeof(*hdr) + sizeof(*add));

	add = (struct iapp_add_notify *) (hdr + 1);
	add->addr_len = ETH_ALEN;
	add->reserved = 0;
	os_memcpy(add->mac_addr, mac_addr, ETH_ALEN);

	add->seq_num = host_to_be16(seq_num);
	
	os_memset(&addr, 0, sizeof(addr));
	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = iapp->multicast.s_addr;
	addr.sin_port = htons(IAPP_UDP_PORT);
	if (sendto(iapp->udp_sock, buf, (char *) (add + 1) - buf, 0,
		   (struct sockaddr *) &addr, sizeof(addr)) < 0)
		wpa_printf(MSG_INFO, "sendto[IAPP-ADD]: %s", strerror(errno));
}


static void iapp_send_layer2_update(struct iapp_data *iapp, u8 *addr)
{
	struct iapp_layer2_update msg;

	/* Send Level 2 Update Frame to update forwarding tables in layer 2
	 * bridge devices */

	/* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID)
	 * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */

	os_memset(msg.da, 0xff, ETH_ALEN);
	os_memcpy(msg.sa, addr, ETH_ALEN);
	msg.len = host_to_be16(6);
	msg.dsap = 0; /* NULL DSAP address */
	msg.ssap = 0x01; /* NULL SSAP address, CR Bit: Response */
	msg.control = 0xaf; /* XID response lsb.1111F101.
			     * F=0 (no poll command; unsolicited frame) */
	msg.xid_info[0] = 0x81; /* XID format identifier */
	msg.xid_info[1] = 1; /* LLC types/classes: Type 1 LLC */
	msg.xid_info[2] = 1 << 1; /* XID sender's receive window size (RW)
				   * FIX: what is correct RW with 802.11? */

	if (send(iapp->packet_sock, &msg, sizeof(msg), 0) < 0)
		wpa_printf(MSG_INFO, "send[L2 Update]: %s", strerror(errno));
}


/**
 * iapp_new_station - IAPP processing for a new STA
 * @iapp: IAPP data
 * @sta: The associated station
 */
void iapp_new_station(struct iapp_data *iapp, struct sta_info *sta)
{
	u16 seq = 0; /* TODO */

	if (iapp == NULL)
		return;

	/* IAPP-ADD.request(MAC Address, Sequence Number, Timeout) */
	hostapd_logger(iapp->hapd, sta->addr, HOSTAPD_MODULE_IAPP,
		       HOSTAPD_LEVEL_DEBUG, "IAPP-ADD.request(seq=%d)", seq);
	iapp_send_layer2_update(iapp, sta->addr);
	iapp_send_add(iapp, sta->addr, seq);

	/* TODO: If this was reassociation:
	 * IAPP-MOVE.request(MAC Address, Sequence Number, Old AP,
	 *                   Context Block, Timeout)
	 * TODO: Send IAPP-MOVE to the old AP; Map Old AP BSSID to
	 * IP address */
}


static void iapp_process_add_notify(struct iapp_data *iapp,
				    struct sockaddr_in *from,
				    struct iapp_hdr *hdr, int len)
{
	struct iapp_add_notify *add = (struct iapp_add_notify *) (hdr + 1);
	struct sta_info *sta;

	if (len != sizeof(*add)) {
		wpa_printf(MSG_INFO, "Invalid IAPP-ADD packet length %d (expected %lu)",
			   len, (unsigned long) sizeof(*add));
		return;
	}

	sta = ap_get_sta(iapp->hapd, add->mac_addr);

	/* IAPP-ADD.indication(MAC Address, Sequence Number) */
	hostapd_logger(iapp->hapd, add->mac_addr, HOSTAPD_MODULE_IAPP,
		       HOSTAPD_LEVEL_INFO,
		       "Received IAPP ADD-notify (seq# %d) from %s:%d%s",
		       be_to_host16(add->seq_num),
		       inet_ntoa(from->sin_addr), ntohs(from->sin_port),
		       sta ? "" : " (STA not found)");

	if (!sta)
		return;

	/* TODO: could use seq_num to try to determine whether last association
	 * to this AP is newer than the one advertised in IAPP-ADD. Although,
	 * this is not really a reliable verification. */

	hostapd_logger(iapp->hapd, add->mac_addr, HOSTAPD_MODULE_IAPP,
		       HOSTAPD_LEVEL_INFO,
		       "Removing STA due to IAPP ADD-notify");
	ap_sta_disconnect(iapp->hapd, sta, NULL, 0);
}


/**
 * iapp_receive_udp - Process IAPP UDP frames
 * @sock: File descriptor for the socket
 * @eloop_ctx: IAPP data (struct iapp_data *)
 * @sock_ctx: Not used
 */
static void iapp_receive_udp(int sock, void *eloop_ctx, void *sock_ctx)
{
	struct iapp_data *iapp = eloop_ctx;
	int len, hlen;
	unsigned char buf[128];
	struct sockaddr_in from;
	socklen_t fromlen;
	struct iapp_hdr *hdr;

	/* Handle incoming IAPP frames (over UDP/IP) */

	fromlen = sizeof(from);
	len = recvfrom(iapp->udp_sock, buf, sizeof(buf), 0,
		       (struct sockaddr *) &from, &fromlen);
	if (len < 0) {
		wpa_printf(MSG_INFO, "iapp_receive_udp - recvfrom: %s",
			   strerror(errno));
		return;
	}

	if (from.sin_addr.s_addr == iapp->own.s_addr)
		return; /* ignore own IAPP messages */

	hostapd_logger(iapp->hapd, NULL, HOSTAPD_MODULE_IAPP,
		       HOSTAPD_LEVEL_DEBUG,
		       "Received %d byte IAPP frame from %s%s\n",
		       len, inet_ntoa(from.sin_addr),
		       len < (int) sizeof(*hdr) ? " (too short)" : "");

	if (len < (int) sizeof(*hdr))
		return;

	hdr = (struct iapp_hdr *) buf;
	hlen = be_to_host16(hdr->length);
	hostapd_logger(iapp->hapd, NULL, HOSTAPD_MODULE_IAPP,
		       HOSTAPD_LEVEL_DEBUG,
		       "RX: version=%d command=%d id=%d len=%d\n",
		       hdr->version, hdr->command,
		       be_to_host16(hdr->identifier), hlen);
	if (hdr->version != IAPP_VERSION) {
		wpa_printf(MSG_INFO, "Dropping IAPP frame with unknown version %d",
			   hdr->version);
		return;
	}
	if (hlen > len) {
		wpa_printf(MSG_INFO, "Underflow IAPP frame (hlen=%d len=%d)",
			   hlen, len);
		return;
	}
	if (hlen < len) {
		wpa_printf(MSG_INFO, "Ignoring %d extra bytes from IAPP frame",
			   len - hlen);
		len = hlen;
	}

	switch (hdr->command) {
	case IAPP_CMD_ADD_notify:
		iapp_process_add_notify(iapp, &from, hdr, len - sizeof(*hdr));
		break;
	case IAPP_CMD_MOVE_notify:
		/* TODO: MOVE is using TCP; so move this to TCP handler once it
		 * is implemented.. */
		/* IAPP-MOVE.indication(MAC Address, New BSSID,
		 * Sequence Number, AP Address, Context Block) */
		/* TODO: process */
		break;
	default:
		wpa_printf(MSG_INFO, "Unknown IAPP command %d", hdr->command);
		break;
	}
}


struct iapp_data * iapp_init(struct hostapd_data *hapd, const char *iface)
{
	struct ifreq ifr;
	struct sockaddr_ll addr;
	int ifindex;
	struct sockaddr_in *paddr, uaddr;
	struct iapp_data *iapp;
	struct ip_mreqn mreq;

	iapp = os_zalloc(sizeof(*iapp));
	if (iapp == NULL)
		return NULL;
	iapp->hapd = hapd;
	iapp->udp_sock = iapp->packet_sock = -1;

	/* TODO:
	 * open socket for sending and receiving IAPP frames over TCP
	 */

	iapp->udp_sock = socket(PF_INET, SOCK_DGRAM, 0);
	if (iapp->udp_sock < 0) {
		wpa_printf(MSG_INFO, "iapp_init - socket[PF_INET,SOCK_DGRAM]: %s",
			   strerror(errno));
		iapp_deinit(iapp);
		return NULL;
	}

	os_memset(&ifr, 0, sizeof(ifr));
	os_strlcpy(ifr.ifr_name, iface, sizeof(ifr.ifr_name));
	if (ioctl(iapp->udp_sock, SIOCGIFINDEX, &ifr) != 0) {
		wpa_printf(MSG_INFO, "iapp_init - ioctl(SIOCGIFINDEX): %s",
			   strerror(errno));
		iapp_deinit(iapp);
		return NULL;
	}
	ifindex = ifr.ifr_ifindex;

	if (ioctl(iapp->udp_sock, SIOCGIFADDR, &ifr) != 0) {
		wpa_printf(MSG_INFO, "iapp_init - ioctl(SIOCGIFADDR): %s",
			   strerror(errno));
		iapp_deinit(iapp);
		return NULL;
	}
	paddr = (struct sockaddr_in *) &ifr.ifr_addr;
	if (paddr->sin_family != AF_INET) {
		wpa_printf(MSG_INFO, "IAPP: Invalid address family %i (SIOCGIFADDR)",
			   paddr->sin_family);
		iapp_deinit(iapp);
		return NULL;
	}
	iapp->own.s_addr = paddr->sin_addr.s_addr;

	if (ioctl(iapp->udp_sock, SIOCGIFBRDADDR, &ifr) != 0) {
		wpa_printf(MSG_INFO, "iapp_init - ioctl(SIOCGIFBRDADDR): %s",
			   strerror(errno));
		iapp_deinit(iapp);
		return NULL;
	}
	paddr = (struct sockaddr_in *) &ifr.ifr_addr;
	if (paddr->sin_family != AF_INET) {
		wpa_printf(MSG_INFO, "Invalid address family %i (SIOCGIFBRDADDR)",
			   paddr->sin_family);
		iapp_deinit(iapp);
		return NULL;
	}
	inet_aton(IAPP_MULTICAST, &iapp->multicast);

	os_memset(&uaddr, 0, sizeof(uaddr));
	uaddr.sin_family = AF_INET;
	uaddr.sin_port = htons(IAPP_UDP_PORT);
	if (bind(iapp->udp_sock, (struct sockaddr *) &uaddr,
		 sizeof(uaddr)) < 0) {
		wpa_printf(MSG_INFO, "iapp_init - bind[UDP]: %s",
			   strerror(errno));
		iapp_deinit(iapp);
		return NULL;
	}

	os_memset(&mreq, 0, sizeof(mreq));
	mreq.imr_multiaddr = iapp->multicast;
	mreq.imr_address.s_addr = INADDR_ANY;
	mreq.imr_ifindex = 0;
	if (setsockopt(iapp->udp_sock, SOL_IP, IP_ADD_MEMBERSHIP, &mreq,
		       sizeof(mreq)) < 0) {
		wpa_printf(MSG_INFO, "iapp_init - setsockopt[UDP,IP_ADD_MEMBERSHIP]: %s",
			   strerror(errno));
		iapp_deinit(iapp);
		return NULL;
	}

	iapp->packet_sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
	if (iapp->packet_sock < 0) {
		wpa_printf(MSG_INFO, "iapp_init - socket[PF_PACKET,SOCK_RAW]: %s",
			   strerror(errno));
		iapp_deinit(iapp);
		return NULL;
	}

	os_memset(&addr, 0, sizeof(addr));
	addr.sll_family = AF_PACKET;
	addr.sll_ifindex = ifindex;
	if (bind(iapp->packet_sock, (struct sockaddr *) &addr,
		 sizeof(addr)) < 0) {
		wpa_printf(MSG_INFO, "iapp_init - bind[PACKET]: %s",
			   strerror(errno));
		iapp_deinit(iapp);
		return NULL;
	}

	if (eloop_register_read_sock(iapp->udp_sock, iapp_receive_udp,
				     iapp, NULL)) {
		wpa_printf(MSG_INFO, "Could not register read socket for IAPP");
		iapp_deinit(iapp);
		return NULL;
	}

	wpa_printf(MSG_INFO, "IEEE 802.11F (IAPP) using interface %s", iface);

	/* TODO: For levels 2 and 3: send RADIUS Initiate-Request, receive
	 * RADIUS Initiate-Accept or Initiate-Reject. IAPP port should actually
	 * be openned only after receiving Initiate-Accept. If Initiate-Reject
	 * is received, IAPP is not started. */

	return iapp;
}


void iapp_deinit(struct iapp_data *iapp)
{
	struct ip_mreqn mreq;

	if (iapp == NULL)
		return;

	if (iapp->udp_sock >= 0) {
		os_memset(&mreq, 0, sizeof(mreq));
		mreq.imr_multiaddr = iapp->multicast;
		mreq.imr_address.s_addr = INADDR_ANY;
		mreq.imr_ifindex = 0;
		if (setsockopt(iapp->udp_sock, SOL_IP, IP_DROP_MEMBERSHIP,
			       &mreq, sizeof(mreq)) < 0) {
			wpa_printf(MSG_INFO, "iapp_deinit - setsockopt[UDP,IP_DEL_MEMBERSHIP]: %s",
				   strerror(errno));
		}

		eloop_unregister_read_sock(iapp->udp_sock);
		close(iapp->udp_sock);
	}
	if (iapp->packet_sock >= 0) {
		eloop_unregister_read_sock(iapp->packet_sock);
		close(iapp->packet_sock);
	}
	os_free(iapp);
}
