Blame mesh/cfgmod-server.c

Packit Service 8264ee
/*
Packit Service 8264ee
 *
Packit Service 8264ee
 *  BlueZ - Bluetooth protocol stack for Linux
Packit Service 8264ee
 *
Packit Service 8264ee
 *  Copyright (C) 2018-2019  Intel Corporation. All rights reserved.
Packit Service 8264ee
 *
Packit Service 8264ee
 *
Packit Service 8264ee
 *  This library is free software; you can redistribute it and/or
Packit Service 8264ee
 *  modify it under the terms of the GNU Lesser General Public
Packit Service 8264ee
 *  License as published by the Free Software Foundation; either
Packit Service 8264ee
 *  version 2.1 of the License, or (at your option) any later version.
Packit Service 8264ee
 *
Packit Service 8264ee
 *  This library is distributed in the hope that it will be useful,
Packit Service 8264ee
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 8264ee
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 8264ee
 *  Lesser General Public License for more details.
Packit Service 8264ee
 *
Packit Service 8264ee
 */
Packit Service 8264ee
Packit Service 8264ee
#ifdef HAVE_CONFIG_H
Packit Service 8264ee
#include <config.h>
Packit Service 8264ee
#endif
Packit Service 8264ee
Packit Service 8264ee
#include <sys/time.h>
Packit Service 8264ee
#include <ell/ell.h>
Packit Service 8264ee
Packit Service 8264ee
#include "mesh/mesh-defs.h"
Packit Service 8264ee
#include "mesh/node.h"
Packit Service 8264ee
#include "mesh/net.h"
Packit Service 8264ee
#include "mesh/appkey.h"
Packit Service 8264ee
#include "mesh/model.h"
Packit Service 8264ee
#include "mesh/mesh-config.h"
Packit Service 8264ee
#include "mesh/cfgmod.h"
Packit Service 8264ee
Packit Service 8264ee
#define CFG_MAX_MSG_LEN 380
Packit Service 8264ee
Packit Service 8264ee
static void send_pub_status(struct mesh_node *node, uint16_t net_idx,
Packit Service 8264ee
			uint16_t src, uint16_t dst,
Packit Service 8264ee
			uint8_t status, uint16_t ele_addr, uint16_t pub_addr,
Packit Service 8264ee
			uint32_t mod_id, uint16_t idx, bool cred_flag,
Packit Service 8264ee
			uint8_t ttl, uint8_t period, uint8_t retransmit)
Packit Service 8264ee
{
Packit Service 8264ee
	uint8_t msg[16];
Packit Service 8264ee
	size_t n;
Packit Service 8264ee
Packit Service 8264ee
	n = mesh_model_opcode_set(OP_CONFIG_MODEL_PUB_STATUS, msg);
Packit Service 8264ee
	msg[n++] = status;
Packit Service 8264ee
	l_put_le16(ele_addr, msg + n);
Packit Service 8264ee
	n += 2;
Packit Service 8264ee
	l_put_le16(pub_addr, msg + n);
Packit Service 8264ee
	n += 2;
Packit Service 8264ee
	idx |= cred_flag ? CREDFLAG_MASK : 0;
Packit Service 8264ee
	l_put_le16(idx, msg + n);
Packit Service 8264ee
	n += 2;
Packit Service 8264ee
	msg[n++] = ttl;
Packit Service 8264ee
	msg[n++] = period;
Packit Service 8264ee
	msg[n++] = retransmit;
Packit Service 8264ee
Packit Service 8264ee
	if (mod_id < 0x10000 || mod_id > VENDOR_ID_MASK) {
Packit Service 8264ee
		l_put_le16(mod_id, msg + n);
Packit Service 8264ee
		n += 2;
Packit Service 8264ee
	} else {
Packit Service 8264ee
		l_put_le16(mod_id >> 16, msg + n);
Packit Service 8264ee
		n += 2;
Packit Service 8264ee
		l_put_le16(mod_id, msg + n);
Packit Service 8264ee
		n += 2;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	mesh_model_send(node, dst, src, APP_IDX_DEV_LOCAL, net_idx, DEFAULT_TTL,
Packit Service 8264ee
								msg, n);
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static bool config_pub_get(struct mesh_node *node, uint16_t net_idx,
Packit Service 8264ee
					uint16_t src, uint16_t dst,
Packit Service 8264ee
					const uint8_t *pkt, uint16_t size)
Packit Service 8264ee
{
Packit Service 8264ee
	uint32_t mod_id;
Packit Service 8264ee
	uint16_t ele_addr;
Packit Service 8264ee
	int ele_idx;
Packit Service 8264ee
	struct mesh_model_pub *pub = NULL;
Packit Service 8264ee
	int status;
Packit Service 8264ee
Packit Service 8264ee
	if (size == 4) {
Packit Service 8264ee
		mod_id = l_get_le16(pkt + 2);
Packit Service 8264ee
		mod_id |= VENDOR_ID_MASK;
Packit Service 8264ee
	} else if (size == 6) {
Packit Service 8264ee
		mod_id = l_get_le16(pkt + 2) << 16;
Packit Service 8264ee
		mod_id |= l_get_le16(pkt + 4);
Packit Service 8264ee
	} else
Packit Service 8264ee
		return false;
Packit Service 8264ee
Packit Service 8264ee
	ele_addr = l_get_le16(pkt);
Packit Service 8264ee
	ele_idx = node_get_element_idx(node, ele_addr);
Packit Service 8264ee
Packit Service 8264ee
	if (ele_idx >= 0)
Packit Service 8264ee
		pub = mesh_model_pub_get(node, ele_addr, mod_id, &status);
Packit Service 8264ee
	else
Packit Service 8264ee
		status = MESH_STATUS_INVALID_ADDRESS;
Packit Service 8264ee
Packit Service 8264ee
	if (pub && status == MESH_STATUS_SUCCESS)
Packit Service 8264ee
		send_pub_status(node, net_idx, src, dst, status, ele_addr,
Packit Service 8264ee
				pub->addr, mod_id, pub->idx, pub->credential,
Packit Service 8264ee
				pub->ttl, pub->period, pub->retransmit);
Packit Service 8264ee
	else
Packit Service 8264ee
		send_pub_status(node, net_idx, src, dst, status, ele_addr, 0,
Packit Service 8264ee
							mod_id, 0, 0, 0, 0, 0);
Packit Service 8264ee
	return true;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static bool config_pub_set(struct mesh_node *node, uint16_t net_idx,
Packit Service 8264ee
					uint16_t src, uint16_t dst,
Packit Service 8264ee
					const uint8_t *pkt, uint16_t size,
Packit Service 8264ee
					bool unreliable)
Packit Service 8264ee
{
Packit Service 8264ee
	uint32_t mod_id;
Packit Service 8264ee
	uint16_t ele_addr, idx, ota = 0;
Packit Service 8264ee
	const uint8_t *pub_addr;
Packit Service 8264ee
	uint16_t test_addr;
Packit Service 8264ee
	uint8_t ttl, period;
Packit Service 8264ee
	uint8_t retransmit;
Packit Service 8264ee
	int status;
Packit Service 8264ee
	bool cred_flag, b_virt = false;
Packit Service 8264ee
	bool vendor = false;
Packit Service 8264ee
Packit Service 8264ee
	switch (size) {
Packit Service 8264ee
	default:
Packit Service 8264ee
		return false;
Packit Service 8264ee
Packit Service 8264ee
	case 11:
Packit Service 8264ee
		idx = l_get_le16(pkt + 4);
Packit Service 8264ee
		ttl = pkt[6];
Packit Service 8264ee
		period = pkt[7];
Packit Service 8264ee
		retransmit = pkt[8];
Packit Service 8264ee
		mod_id = l_get_le16(pkt + 9);
Packit Service 8264ee
		mod_id |= VENDOR_ID_MASK;
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case 13:
Packit Service 8264ee
		idx = l_get_le16(pkt + 4);
Packit Service 8264ee
		ttl = pkt[6];
Packit Service 8264ee
		period = pkt[7];
Packit Service 8264ee
		retransmit = pkt[8];
Packit Service 8264ee
		mod_id = l_get_le16(pkt + 9) << 16;
Packit Service 8264ee
		mod_id |= l_get_le16(pkt + 11);
Packit Service 8264ee
		vendor = true;
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case 25:
Packit Service 8264ee
		b_virt = true;
Packit Service 8264ee
		idx = l_get_le16(pkt + 18);
Packit Service 8264ee
		ttl = pkt[20];
Packit Service 8264ee
		period = pkt[21];
Packit Service 8264ee
		retransmit = pkt[22];
Packit Service 8264ee
		mod_id = l_get_le16(pkt + 23);
Packit Service 8264ee
		mod_id |= VENDOR_ID_MASK;
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case 27:
Packit Service 8264ee
		b_virt = true;
Packit Service 8264ee
		idx = l_get_le16(pkt + 18);
Packit Service 8264ee
		ttl = pkt[20];
Packit Service 8264ee
		period = pkt[21];
Packit Service 8264ee
		retransmit = pkt[22];
Packit Service 8264ee
		mod_id = l_get_le16(pkt + 23) << 16;
Packit Service 8264ee
		mod_id |= l_get_le16(pkt + 25);
Packit Service 8264ee
		vendor = true;
Packit Service 8264ee
		break;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	ele_addr = l_get_le16(pkt);
Packit Service 8264ee
	pub_addr = pkt + 2;
Packit Service 8264ee
Packit Service 8264ee
	/* Doesn't accept out-of-range TTLs */
Packit Service 8264ee
	if (ttl > TTL_MASK && ttl != DEFAULT_TTL)
Packit Service 8264ee
		return false;
Packit Service 8264ee
Packit Service 8264ee
	/* Get cred_flag */
Packit Service 8264ee
	cred_flag = !!(CREDFLAG_MASK & idx);
Packit Service 8264ee
Packit Service 8264ee
	/* Ignore non-IDX bits */
Packit Service 8264ee
	idx &= APP_IDX_MASK;
Packit Service 8264ee
Packit Service 8264ee
	/* Doesn't accept virtual seeming addresses */
Packit Service 8264ee
	test_addr = l_get_le16(pub_addr);
Packit Service 8264ee
	if (!b_virt && test_addr > 0x7fff && test_addr < 0xc000)
Packit Service 8264ee
		return false;
Packit Service 8264ee
Packit Service 8264ee
	status = mesh_model_pub_set(node, ele_addr, mod_id, pub_addr, idx,
Packit Service 8264ee
					cred_flag, ttl, period, retransmit,
Packit Service 8264ee
					b_virt, &ota;;
Packit Service 8264ee
Packit Service 8264ee
	l_debug("pub_set: status %d, ea %4.4x, ota: %4.4x, mod: %x, idx: %3.3x",
Packit Service 8264ee
					status, ele_addr, ota, mod_id, idx);
Packit Service 8264ee
Packit Service 8264ee
	if (IS_UNASSIGNED(ota) && !b_virt) {
Packit Service 8264ee
		ttl = period = idx = 0;
Packit Service 8264ee
Packit Service 8264ee
		/* Remove model publication from config file */
Packit Service 8264ee
		if (status == MESH_STATUS_SUCCESS)
Packit Service 8264ee
			mesh_config_model_pub_del(node_config_get(node),
Packit Service 8264ee
				ele_addr, vendor ? mod_id : mod_id & 0x0000ffff,
Packit Service 8264ee
									vendor);
Packit Service 8264ee
		goto done;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	if (status == MESH_STATUS_SUCCESS) {
Packit Service 8264ee
		struct mesh_config_pub db_pub = {
Packit Service 8264ee
			.virt = b_virt,
Packit Service 8264ee
			.addr = ota,
Packit Service 8264ee
			.idx = idx,
Packit Service 8264ee
			.ttl = ttl,
Packit Service 8264ee
			.credential = cred_flag,
Packit Service 8264ee
			.period = period,
Packit Service 8264ee
			.count = retransmit >> 5,
Packit Service 8264ee
			.interval = ((0x1f & retransmit) + 1) * 50
Packit Service 8264ee
		};
Packit Service 8264ee
Packit Service 8264ee
		if (b_virt)
Packit Service 8264ee
			memcpy(db_pub.virt_addr, pub_addr, 16);
Packit Service 8264ee
Packit Service 8264ee
		/* Save model publication to config file */
Packit Service 8264ee
		if (!mesh_config_model_pub_add(node_config_get(node), ele_addr,
Packit Service 8264ee
					vendor ? mod_id : mod_id & 0x0000ffff,
Packit Service 8264ee
					vendor, &db_pub))
Packit Service 8264ee
			status = MESH_STATUS_STORAGE_FAIL;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
done:
Packit Service 8264ee
	if (!unreliable)
Packit Service 8264ee
		send_pub_status(node, net_idx, src, dst, status, ele_addr, ota,
Packit Service 8264ee
			mod_id, idx, cred_flag, ttl, period, retransmit);
Packit Service 8264ee
	return true;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static void send_sub_status(struct mesh_node *node, uint16_t net_idx,
Packit Service 8264ee
					uint16_t src, uint16_t dst,
Packit Service 8264ee
					uint8_t status, uint16_t ele_addr,
Packit Service 8264ee
					uint16_t addr, uint32_t mod)
Packit Service 8264ee
{
Packit Service 8264ee
	uint8_t msg[12];
Packit Service 8264ee
	int n = mesh_model_opcode_set(OP_CONFIG_MODEL_SUB_STATUS, msg);
Packit Service 8264ee
Packit Service 8264ee
	msg[n++] = status;
Packit Service 8264ee
	l_put_le16(ele_addr, msg + n);
Packit Service 8264ee
	n += 2;
Packit Service 8264ee
	l_put_le16(addr, msg + n);
Packit Service 8264ee
	n += 2;
Packit Service 8264ee
	if (mod >= 0x10000 && mod < VENDOR_ID_MASK) {
Packit Service 8264ee
		l_put_le16(mod >> 16, msg + n);
Packit Service 8264ee
		l_put_le16(mod, msg + n + 2);
Packit Service 8264ee
		n += 4;
Packit Service 8264ee
	} else {
Packit Service 8264ee
		l_put_le16(mod, msg + n);
Packit Service 8264ee
		n += 2;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	mesh_model_send(node, dst, src, APP_IDX_DEV_LOCAL, net_idx,
Packit Service 8264ee
							DEFAULT_TTL, msg, n);
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static bool config_sub_get(struct mesh_node *node, uint16_t net_idx,
Packit Service 8264ee
					uint16_t src, uint16_t dst,
Packit Service 8264ee
					const uint8_t *pkt, uint16_t size)
Packit Service 8264ee
{
Packit Service 8264ee
	uint16_t ele_addr;
Packit Service 8264ee
	uint32_t mod_id;
Packit Service 8264ee
	uint16_t n = 0;
Packit Service 8264ee
	int status;
Packit Service 8264ee
	uint8_t *msg_status;
Packit Service 8264ee
	uint16_t buf_size;
Packit Service 8264ee
	uint8_t msg[5 + sizeof(uint16_t) * MAX_GRP_PER_MOD];
Packit Service 8264ee
Packit Service 8264ee
	/* Incoming message has already been size-checked */
Packit Service 8264ee
	ele_addr = l_get_le16(pkt);
Packit Service 8264ee
Packit Service 8264ee
	switch (size) {
Packit Service 8264ee
	default:
Packit Service 8264ee
		l_debug("Bad Len Cfg_Pub_Set: %d", size);
Packit Service 8264ee
		return false;
Packit Service 8264ee
Packit Service 8264ee
	case 4:
Packit Service 8264ee
		mod_id = l_get_le16(pkt + 2);
Packit Service 8264ee
		n = mesh_model_opcode_set(OP_CONFIG_MODEL_SUB_LIST, msg);
Packit Service 8264ee
		msg_status = msg + n;
Packit Service 8264ee
		msg[n++] = 0;
Packit Service 8264ee
		l_put_le16(ele_addr, msg + n);
Packit Service 8264ee
		n += 2;
Packit Service 8264ee
		l_put_le16(mod_id, msg + n);
Packit Service 8264ee
		n += 2;
Packit Service 8264ee
		mod_id |= VENDOR_ID_MASK;
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case 6:
Packit Service 8264ee
		mod_id = l_get_le16(pkt + 2) << 16;
Packit Service 8264ee
		mod_id |= l_get_le16(pkt + 4);
Packit Service 8264ee
		n = mesh_model_opcode_set(OP_CONFIG_VEND_MODEL_SUB_LIST, msg);
Packit Service 8264ee
		msg_status = msg + n;
Packit Service 8264ee
		msg[n++] = 0;
Packit Service 8264ee
		l_put_le16(ele_addr, msg + n);
Packit Service 8264ee
		n += 2;
Packit Service 8264ee
		l_put_le16(mod_id >> 16, msg + n);
Packit Service 8264ee
		n += 2;
Packit Service 8264ee
		l_put_le16(mod_id, msg + n);
Packit Service 8264ee
		n += 2;
Packit Service 8264ee
		break;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	buf_size = sizeof(uint16_t) * MAX_GRP_PER_MOD;
Packit Service 8264ee
	status = mesh_model_sub_get(node, ele_addr, mod_id, msg + n, buf_size,
Packit Service 8264ee
									&size);
Packit Service 8264ee
Packit Service 8264ee
	if (status == MESH_STATUS_SUCCESS)
Packit Service 8264ee
		n += size;
Packit Service 8264ee
Packit Service 8264ee
	*msg_status = (uint8_t) status;
Packit Service 8264ee
Packit Service 8264ee
	mesh_model_send(node, dst, src, APP_IDX_DEV_LOCAL, net_idx, DEFAULT_TTL,
Packit Service 8264ee
									msg, n);
Packit Service 8264ee
	return true;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static bool save_config_sub(struct mesh_node *node, uint16_t ele_addr,
Packit Service 8264ee
					uint32_t mod_id, bool vendor,
Packit Service 8264ee
					const uint8_t *addr, bool virt,
Packit Service 8264ee
					uint16_t grp, uint32_t opcode)
Packit Service 8264ee
{
Packit Service 8264ee
	struct mesh_config_sub db_sub = {
Packit Service 8264ee
				.virt = virt,
Packit Service 8264ee
				.src.addr = grp
Packit Service 8264ee
				};
Packit Service 8264ee
Packit Service 8264ee
	if (virt)
Packit Service 8264ee
		memcpy(db_sub.src.virt_addr, addr, 16);
Packit Service 8264ee
Packit Service 8264ee
	if (opcode == OP_CONFIG_MODEL_SUB_VIRT_OVERWRITE ||
Packit Service 8264ee
					opcode == OP_CONFIG_MODEL_SUB_OVERWRITE)
Packit Service 8264ee
		mesh_config_model_sub_del_all(node_config_get(node),
Packit Service 8264ee
				ele_addr, vendor ? mod_id : mod_id & 0x0000ffff,
Packit Service 8264ee
									vendor);
Packit Service 8264ee
Packit Service 8264ee
	if (opcode != OP_CONFIG_MODEL_SUB_VIRT_DELETE &&
Packit Service 8264ee
			opcode != OP_CONFIG_MODEL_SUB_DELETE)
Packit Service 8264ee
		return mesh_config_model_sub_add(node_config_get(node),
Packit Service 8264ee
					ele_addr,
Packit Service 8264ee
					vendor ? mod_id : mod_id & 0x0000ffff,
Packit Service 8264ee
					vendor, &db_sub);
Packit Service 8264ee
	else
Packit Service 8264ee
		return mesh_config_model_sub_del(node_config_get(node),
Packit Service 8264ee
					ele_addr,
Packit Service 8264ee
					vendor ? mod_id : mod_id & 0x0000ffff,
Packit Service 8264ee
					vendor, &db_sub);
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static void config_sub_set(struct mesh_node *node, uint16_t net_idx,
Packit Service 8264ee
					uint16_t src, uint16_t dst,
Packit Service 8264ee
					const uint8_t *pkt, uint16_t size,
Packit Service 8264ee
					bool virt, uint32_t opcode)
Packit Service 8264ee
{
Packit Service 8264ee
	uint16_t grp, ele_addr;
Packit Service 8264ee
	bool unreliable = !!(opcode & OP_UNRELIABLE);
Packit Service 8264ee
	uint32_t mod_id;
Packit Service 8264ee
	const uint8_t *addr = NULL;
Packit Service 8264ee
	int status = MESH_STATUS_SUCCESS;
Packit Service 8264ee
	bool vendor = false;
Packit Service 8264ee
Packit Service 8264ee
	switch (size) {
Packit Service 8264ee
	default:
Packit Service 8264ee
		l_error("Bad Len Cfg_Sub_Set: %d", size);
Packit Service 8264ee
		return;
Packit Service 8264ee
	case 4:
Packit Service 8264ee
		if (opcode != OP_CONFIG_MODEL_SUB_DELETE_ALL)
Packit Service 8264ee
			return;
Packit Service 8264ee
		mod_id = l_get_le16(pkt + 2);
Packit Service 8264ee
		mod_id |= VENDOR_ID_MASK;
Packit Service 8264ee
		break;
Packit Service 8264ee
	case 6:
Packit Service 8264ee
		if (virt)
Packit Service 8264ee
			return;
Packit Service 8264ee
		if (opcode != OP_CONFIG_MODEL_SUB_DELETE_ALL) {
Packit Service 8264ee
			mod_id = l_get_le16(pkt + 4);
Packit Service 8264ee
			mod_id |= VENDOR_ID_MASK;
Packit Service 8264ee
		} else {
Packit Service 8264ee
			mod_id = l_get_le16(pkt + 2) << 16;
Packit Service 8264ee
			mod_id |= l_get_le16(pkt + 4);
Packit Service 8264ee
			vendor = true;
Packit Service 8264ee
		}
Packit Service 8264ee
		break;
Packit Service 8264ee
	case 8:
Packit Service 8264ee
		if (virt)
Packit Service 8264ee
			return;
Packit Service 8264ee
		mod_id = l_get_le16(pkt + 4) << 16;
Packit Service 8264ee
		mod_id |= l_get_le16(pkt + 6);
Packit Service 8264ee
		vendor = true;
Packit Service 8264ee
		break;
Packit Service 8264ee
	case 20:
Packit Service 8264ee
		if (!virt)
Packit Service 8264ee
			return;
Packit Service 8264ee
		mod_id = l_get_le16(pkt + 18);
Packit Service 8264ee
		mod_id |= VENDOR_ID_MASK;
Packit Service 8264ee
		break;
Packit Service 8264ee
	case 22:
Packit Service 8264ee
		if (!virt)
Packit Service 8264ee
			return;
Packit Service 8264ee
		mod_id = l_get_le16(pkt + 18) << 16;
Packit Service 8264ee
		mod_id |= l_get_le16(pkt + 20);
Packit Service 8264ee
		break;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	ele_addr = l_get_le16(pkt);
Packit Service 8264ee
Packit Service 8264ee
	if (opcode != OP_CONFIG_MODEL_SUB_DELETE_ALL) {
Packit Service 8264ee
		addr = pkt + 2;
Packit Service 8264ee
		grp = l_get_le16(addr);
Packit Service 8264ee
	} else
Packit Service 8264ee
		grp = UNASSIGNED_ADDRESS;
Packit Service 8264ee
Packit Service 8264ee
	switch (opcode & ~OP_UNRELIABLE) {
Packit Service 8264ee
	default:
Packit Service 8264ee
		l_debug("Bad opcode: %x", opcode);
Packit Service 8264ee
		return;
Packit Service 8264ee
Packit Service 8264ee
	case OP_CONFIG_MODEL_SUB_DELETE_ALL:
Packit Service 8264ee
		status = mesh_model_sub_del_all(node, ele_addr, mod_id);
Packit Service 8264ee
Packit Service 8264ee
		if (status == MESH_STATUS_SUCCESS)
Packit Service 8264ee
			mesh_config_model_sub_del_all(node_config_get(node),
Packit Service 8264ee
				ele_addr, vendor ? mod_id : mod_id & 0x0000ffff,
Packit Service 8264ee
									vendor);
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case OP_CONFIG_MODEL_SUB_VIRT_OVERWRITE:
Packit Service 8264ee
		grp = UNASSIGNED_ADDRESS;
Packit Service 8264ee
		/* Fall Through */
Packit Service 8264ee
	case OP_CONFIG_MODEL_SUB_OVERWRITE:
Packit Service 8264ee
		status = mesh_model_sub_ovr(node, ele_addr, mod_id,
Packit Service 8264ee
							addr, virt, &grp;;
Packit Service 8264ee
Packit Service 8264ee
		if (status == MESH_STATUS_SUCCESS)
Packit Service 8264ee
			save_config_sub(node, ele_addr, mod_id, vendor, addr,
Packit Service 8264ee
							virt, grp, opcode);
Packit Service 8264ee
		break;
Packit Service 8264ee
	case OP_CONFIG_MODEL_SUB_VIRT_ADD:
Packit Service 8264ee
		grp = UNASSIGNED_ADDRESS;
Packit Service 8264ee
		/* Fall Through */
Packit Service 8264ee
	case OP_CONFIG_MODEL_SUB_ADD:
Packit Service 8264ee
		status = mesh_model_sub_add(node, ele_addr, mod_id,
Packit Service 8264ee
							addr, virt, &grp;;
Packit Service 8264ee
Packit Service 8264ee
		if (status == MESH_STATUS_SUCCESS &&
Packit Service 8264ee
				!save_config_sub(node, ele_addr, mod_id, vendor,
Packit Service 8264ee
						addr, virt, grp, opcode))
Packit Service 8264ee
			status = MESH_STATUS_STORAGE_FAIL;
Packit Service 8264ee
Packit Service 8264ee
		break;
Packit Service 8264ee
	case OP_CONFIG_MODEL_SUB_VIRT_DELETE:
Packit Service 8264ee
		grp = UNASSIGNED_ADDRESS;
Packit Service 8264ee
		/* Fall Through */
Packit Service 8264ee
	case OP_CONFIG_MODEL_SUB_DELETE:
Packit Service 8264ee
		status = mesh_model_sub_del(node, ele_addr, mod_id,
Packit Service 8264ee
							addr, virt, &grp;;
Packit Service 8264ee
Packit Service 8264ee
		if (status == MESH_STATUS_SUCCESS)
Packit Service 8264ee
			save_config_sub(node, ele_addr, mod_id, vendor, addr,
Packit Service 8264ee
							virt, grp, opcode);
Packit Service 8264ee
Packit Service 8264ee
		break;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	if (!unreliable)
Packit Service 8264ee
		send_sub_status(node, net_idx, src, dst, status, ele_addr,
Packit Service 8264ee
								grp, mod_id);
Packit Service 8264ee
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static void send_model_app_status(struct mesh_node *node, uint16_t net_idx,
Packit Service 8264ee
					uint16_t src, uint16_t dst,
Packit Service 8264ee
					uint8_t status, uint16_t addr,
Packit Service 8264ee
					uint32_t id, uint16_t idx)
Packit Service 8264ee
{
Packit Service 8264ee
	uint8_t msg[12];
Packit Service 8264ee
	size_t n = mesh_model_opcode_set(OP_MODEL_APP_STATUS, msg);
Packit Service 8264ee
Packit Service 8264ee
	msg[n++] = status;
Packit Service 8264ee
	l_put_le16(addr, msg + n);
Packit Service 8264ee
	n += 2;
Packit Service 8264ee
	l_put_le16(idx, msg + n);
Packit Service 8264ee
	n += 2;
Packit Service 8264ee
	if (id >= 0x10000 && id < VENDOR_ID_MASK) {
Packit Service 8264ee
		l_put_le16(id >> 16, msg + n);
Packit Service 8264ee
		n += 2;
Packit Service 8264ee
	}
Packit Service 8264ee
	l_put_le16(id, msg + n);
Packit Service 8264ee
	n += 2;
Packit Service 8264ee
Packit Service 8264ee
	mesh_model_send(node, dst, src, APP_IDX_DEV_LOCAL, net_idx, DEFAULT_TTL,
Packit Service 8264ee
									msg, n);
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static void model_app_list(struct mesh_node *node, uint16_t net_idx,
Packit Service 8264ee
					uint16_t src, uint16_t dst,
Packit Service 8264ee
					const uint8_t *pkt, uint16_t size)
Packit Service 8264ee
{
Packit Service 8264ee
	uint16_t ele_addr;
Packit Service 8264ee
	uint32_t mod_id = 0xffff;
Packit Service 8264ee
	uint8_t *msg = NULL;
Packit Service 8264ee
	uint8_t *status;
Packit Service 8264ee
	uint16_t n, buf_size;
Packit Service 8264ee
	int result;
Packit Service 8264ee
Packit Service 8264ee
	buf_size = MAX_BINDINGS * sizeof(uint16_t);
Packit Service 8264ee
	msg = l_malloc(7 + buf_size);
Packit Service 8264ee
	if (!msg)
Packit Service 8264ee
		return;
Packit Service 8264ee
Packit Service 8264ee
	ele_addr = l_get_le16(pkt);
Packit Service 8264ee
Packit Service 8264ee
	switch (size) {
Packit Service 8264ee
	default:
Packit Service 8264ee
		l_free(msg);
Packit Service 8264ee
		return;
Packit Service 8264ee
	case 4:
Packit Service 8264ee
		n = mesh_model_opcode_set(OP_MODEL_APP_LIST, msg);
Packit Service 8264ee
		status = msg + n;
Packit Service 8264ee
		mod_id = l_get_le16(pkt + 2);
Packit Service 8264ee
		l_put_le16(ele_addr, msg + 1 + n);
Packit Service 8264ee
		l_put_le16(mod_id, msg + 3 + n);
Packit Service 8264ee
		mod_id |= VENDOR_ID_MASK;
Packit Service 8264ee
		n += 5;
Packit Service 8264ee
		break;
Packit Service 8264ee
	case 6:
Packit Service 8264ee
		n = mesh_model_opcode_set(OP_VEND_MODEL_APP_LIST, msg);
Packit Service 8264ee
		status = msg + n;
Packit Service 8264ee
		mod_id = l_get_le16(pkt + 2) << 16;
Packit Service 8264ee
		mod_id |= l_get_le16(pkt + 4);
Packit Service 8264ee
Packit Service 8264ee
		l_put_le16(ele_addr, msg + 1 + n);
Packit Service 8264ee
		l_put_le16(mod_id >> 16, msg + 3 + n);
Packit Service 8264ee
		l_put_le16(mod_id, msg + 5 + n);
Packit Service 8264ee
		n += 7;
Packit Service 8264ee
		break;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
Packit Service 8264ee
	result = mesh_model_get_bindings(node, ele_addr, mod_id, msg + n,
Packit Service 8264ee
							buf_size, &size);
Packit Service 8264ee
	n += size;
Packit Service 8264ee
Packit Service 8264ee
	if (result >= 0) {
Packit Service 8264ee
		*status = result;
Packit Service 8264ee
		mesh_model_send(node, dst, src, APP_IDX_DEV_LOCAL, net_idx,
Packit Service 8264ee
							DEFAULT_TTL, msg, n);
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	l_free(msg);
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static bool model_app_bind(struct mesh_node *node, uint16_t net_idx,
Packit Service 8264ee
					uint16_t src, uint16_t dst,
Packit Service 8264ee
					const uint8_t *pkt, uint16_t size,
Packit Service 8264ee
					bool unbind)
Packit Service 8264ee
{
Packit Service 8264ee
	uint16_t ele_addr;
Packit Service 8264ee
	uint32_t mod_id;
Packit Service 8264ee
	uint16_t idx;
Packit Service 8264ee
	int result;
Packit Service 8264ee
Packit Service 8264ee
	switch (size) {
Packit Service 8264ee
	default:
Packit Service 8264ee
		return false;
Packit Service 8264ee
Packit Service 8264ee
	case 6:
Packit Service 8264ee
		mod_id = l_get_le16(pkt + 4);
Packit Service 8264ee
		mod_id |= VENDOR_ID_MASK;
Packit Service 8264ee
		break;
Packit Service 8264ee
	case 8:
Packit Service 8264ee
		mod_id = l_get_le16(pkt + 4) << 16;
Packit Service 8264ee
		mod_id |= l_get_le16(pkt + 6);
Packit Service 8264ee
		break;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	ele_addr = l_get_le16(pkt);
Packit Service 8264ee
	idx = l_get_le16(pkt + 2);
Packit Service 8264ee
Packit Service 8264ee
	if (idx > 0xfff)
Packit Service 8264ee
		return false;
Packit Service 8264ee
Packit Service 8264ee
	if (unbind)
Packit Service 8264ee
		result = mesh_model_binding_del(node, ele_addr, mod_id, idx);
Packit Service 8264ee
	else
Packit Service 8264ee
		result = mesh_model_binding_add(node, ele_addr, mod_id, idx);
Packit Service 8264ee
Packit Service 8264ee
	send_model_app_status(node, net_idx, src, dst, result, ele_addr,
Packit Service 8264ee
								mod_id, idx);
Packit Service 8264ee
Packit Service 8264ee
	return true;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static void hb_pub_timeout_func(struct l_timeout *timeout, void *user_data)
Packit Service 8264ee
{
Packit Service 8264ee
	struct mesh_net *net = user_data;
Packit Service 8264ee
	struct mesh_net_heartbeat *hb = mesh_net_heartbeat_get(net);
Packit Service 8264ee
Packit Service 8264ee
	mesh_net_heartbeat_send(net);
Packit Service 8264ee
Packit Service 8264ee
	if (hb->pub_count != 0xffff)
Packit Service 8264ee
		hb->pub_count--;
Packit Service 8264ee
	if (hb->pub_count > 0)
Packit Service 8264ee
		l_timeout_modify(hb->pub_timer, hb->pub_period);
Packit Service 8264ee
	else {
Packit Service 8264ee
		l_timeout_remove(hb->pub_timer);
Packit Service 8264ee
		hb->pub_timer = NULL;
Packit Service 8264ee
	}
Packit Service 8264ee
	l_debug("%d left", hb->pub_count);
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static void update_hb_pub_timer(struct mesh_net *net,
Packit Service 8264ee
						struct mesh_net_heartbeat *hb)
Packit Service 8264ee
{
Packit Service 8264ee
	if (IS_UNASSIGNED(hb->pub_dst) || hb->pub_count == 0) {
Packit Service 8264ee
		l_timeout_remove(hb->pub_timer);
Packit Service 8264ee
		hb->pub_timer = NULL;
Packit Service 8264ee
		return;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	if (!hb->pub_timer)
Packit Service 8264ee
		hb->pub_timer = l_timeout_create(hb->pub_period,
Packit Service 8264ee
					hb_pub_timeout_func, net, NULL);
Packit Service 8264ee
	else
Packit Service 8264ee
		l_timeout_modify(hb->pub_timer, hb->pub_period);
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static void hb_sub_timeout_func(struct l_timeout *timeout, void *user_data)
Packit Service 8264ee
{
Packit Service 8264ee
	struct mesh_net *net = user_data;
Packit Service 8264ee
	struct mesh_net_heartbeat *hb = mesh_net_heartbeat_get(net);
Packit Service 8264ee
Packit Service 8264ee
	l_debug("HB Subscription Ended");
Packit Service 8264ee
	l_timeout_remove(hb->sub_timer);
Packit Service 8264ee
	hb->sub_timer = NULL;
Packit Service 8264ee
	hb->sub_enabled = false;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static uint8_t uint32_to_log(uint32_t value)
Packit Service 8264ee
{
Packit Service 8264ee
	uint32_t val = 1;
Packit Service 8264ee
	uint8_t ret = 1;
Packit Service 8264ee
Packit Service 8264ee
	if (!value)
Packit Service 8264ee
		return 0;
Packit Service 8264ee
	else if (value > 0x10000)
Packit Service 8264ee
		return 0xff;
Packit Service 8264ee
Packit Service 8264ee
	while (val < value) {
Packit Service 8264ee
		val <<= 1;
Packit Service 8264ee
		ret++;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	return ret;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static uint32_t log_to_uint32(uint8_t log, uint8_t offset)
Packit Service 8264ee
{
Packit Service 8264ee
	if (!log)
Packit Service 8264ee
		return 0x0000;
Packit Service 8264ee
	else if (log > 0x11)
Packit Service 8264ee
		return 0xffff;
Packit Service 8264ee
	else
Packit Service 8264ee
		return (1 << (log - offset));
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
Packit Service 8264ee
static int hb_subscription_set(struct mesh_net *net, uint16_t src,
Packit Service 8264ee
					uint16_t dst, uint8_t period_log)
Packit Service 8264ee
{
Packit Service 8264ee
	struct mesh_net_heartbeat *hb = mesh_net_heartbeat_get(net);
Packit Service 8264ee
	struct timeval time_now;
Packit Service 8264ee
Packit Service 8264ee
	/* SRC must be Unicast, DST can be any legal address except Virtual */
Packit Service 8264ee
	if ((!IS_UNASSIGNED(src) && !IS_UNICAST(src)) || IS_VIRTUAL(dst))
Packit Service 8264ee
		return -1;
Packit Service 8264ee
Packit Service 8264ee
	/* Check if the subscription should be disabled */
Packit Service 8264ee
	if (IS_UNASSIGNED(src) || IS_UNASSIGNED(dst)) {
Packit Service 8264ee
		if (IS_GROUP(hb->sub_dst))
Packit Service 8264ee
			mesh_net_dst_unreg(net, hb->sub_dst);
Packit Service 8264ee
Packit Service 8264ee
		l_timeout_remove(hb->sub_timer);
Packit Service 8264ee
		hb->sub_timer = NULL;
Packit Service 8264ee
		hb->sub_enabled = false;
Packit Service 8264ee
		hb->sub_dst = UNASSIGNED_ADDRESS;
Packit Service 8264ee
		hb->sub_src = UNASSIGNED_ADDRESS;
Packit Service 8264ee
		hb->sub_count = 0;
Packit Service 8264ee
		hb->sub_period = 0;
Packit Service 8264ee
		hb->sub_min_hops = 0;
Packit Service 8264ee
		hb->sub_max_hops = 0;
Packit Service 8264ee
		return MESH_STATUS_SUCCESS;
Packit Service 8264ee
	} else if (!period_log && src == hb->sub_src && dst == hb->sub_dst) {
Packit Service 8264ee
		/* Preserve collected data, but disable */
Packit Service 8264ee
		l_timeout_remove(hb->sub_timer);
Packit Service 8264ee
		hb->sub_timer = NULL;
Packit Service 8264ee
		hb->sub_enabled = false;
Packit Service 8264ee
		hb->sub_period = 0;
Packit Service 8264ee
		return MESH_STATUS_SUCCESS;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	if (hb->sub_dst != dst) {
Packit Service 8264ee
		if (IS_GROUP(hb->sub_dst))
Packit Service 8264ee
			mesh_net_dst_unreg(net, hb->sub_dst);
Packit Service 8264ee
		if (IS_GROUP(dst))
Packit Service 8264ee
			mesh_net_dst_reg(net, dst);
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	hb->sub_enabled = !!period_log;
Packit Service 8264ee
	hb->sub_src = src;
Packit Service 8264ee
	hb->sub_dst = dst;
Packit Service 8264ee
	hb->sub_count = 0;
Packit Service 8264ee
	hb->sub_period = log_to_uint32(period_log, 1);
Packit Service 8264ee
	hb->sub_min_hops = 0x00;
Packit Service 8264ee
	hb->sub_max_hops = 0x00;
Packit Service 8264ee
Packit Service 8264ee
	gettimeofday(&time_now, NULL);
Packit Service 8264ee
	hb->sub_start = time_now.tv_sec;
Packit Service 8264ee
Packit Service 8264ee
	if (!hb->sub_enabled) {
Packit Service 8264ee
		l_timeout_remove(hb->sub_timer);
Packit Service 8264ee
		hb->sub_timer = NULL;
Packit Service 8264ee
		return MESH_STATUS_SUCCESS;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	hb->sub_min_hops = 0xff;
Packit Service 8264ee
Packit Service 8264ee
	if (!hb->sub_timer)
Packit Service 8264ee
		hb->sub_timer = l_timeout_create(hb->sub_period,
Packit Service 8264ee
						hb_sub_timeout_func, net, NULL);
Packit Service 8264ee
	else
Packit Service 8264ee
		l_timeout_modify(hb->sub_timer, hb->sub_period);
Packit Service 8264ee
Packit Service 8264ee
	return MESH_STATUS_SUCCESS;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static void node_reset(struct l_timeout *timeout, void *user_data)
Packit Service 8264ee
{
Packit Service 8264ee
	l_debug("Node Reset");
Packit Service 8264ee
	l_timeout_remove(timeout);
Packit Service 8264ee
	l_main_quit();
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static bool cfg_srv_pkt(uint16_t src, uint32_t dst, uint16_t unicast,
Packit Service 8264ee
				uint16_t app_idx, uint16_t net_idx,
Packit Service 8264ee
				const uint8_t *data, uint16_t size,
Packit Service 8264ee
				uint8_t ttl, const void *user_data)
Packit Service 8264ee
{
Packit Service 8264ee
	struct mesh_node *node = (struct mesh_node *) user_data;
Packit Service 8264ee
	struct mesh_net *net;
Packit Service 8264ee
	const uint8_t *pkt = data;
Packit Service 8264ee
	struct timeval time_now;
Packit Service 8264ee
	uint32_t opcode, tmp32;
Packit Service 8264ee
	int b_res = MESH_STATUS_SUCCESS;
Packit Service 8264ee
	uint8_t msg[11];
Packit Service 8264ee
	uint8_t *long_msg = NULL;
Packit Service 8264ee
	struct mesh_net_heartbeat *hb;
Packit Service 8264ee
	uint16_t n_idx, a_idx;
Packit Service 8264ee
	uint8_t state, status;
Packit Service 8264ee
	uint8_t phase;
Packit Service 8264ee
	bool virt = false;
Packit Service 8264ee
	uint8_t count;
Packit Service 8264ee
	uint16_t interval;
Packit Service 8264ee
	uint16_t n;
Packit Service 8264ee
Packit Service 8264ee
	if (app_idx != APP_IDX_DEV_LOCAL)
Packit Service 8264ee
		return false;
Packit Service 8264ee
Packit Service 8264ee
	if (mesh_model_opcode_get(pkt, size, &opcode, &n)) {
Packit Service 8264ee
		size -= n;
Packit Service 8264ee
		pkt += n;
Packit Service 8264ee
	} else
Packit Service 8264ee
		return false;
Packit Service 8264ee
Packit Service 8264ee
	net = node_get_net(node);
Packit Service 8264ee
	hb = mesh_net_heartbeat_get(net);
Packit Service 8264ee
	l_debug("CONFIG-SRV-opcode 0x%x size %u idx %3.3x", opcode, size,
Packit Service 8264ee
								net_idx);
Packit Service 8264ee
Packit Service 8264ee
	n = 0;
Packit Service 8264ee
Packit Service 8264ee
	switch (opcode) {
Packit Service 8264ee
	default:
Packit Service 8264ee
		return false;
Packit Service 8264ee
Packit Service 8264ee
	case OP_DEV_COMP_GET:
Packit Service 8264ee
		if (size != 1)
Packit Service 8264ee
			return false;
Packit Service 8264ee
Packit Service 8264ee
		/* Only page 0 is currently supported */
Packit Service 8264ee
		if (pkt[0] != 0) {
Packit Service 8264ee
			l_debug("Unsupported page number %d", pkt[0]);
Packit Service 8264ee
			l_debug("Returning page number 0");
Packit Service 8264ee
		}
Packit Service 8264ee
		long_msg = l_malloc(CFG_MAX_MSG_LEN);
Packit Service 8264ee
		n = mesh_model_opcode_set(OP_DEV_COMP_STATUS, long_msg);
Packit Service 8264ee
		long_msg[n++] = 0;
Packit Service 8264ee
		n += node_generate_comp(node, long_msg + n,
Packit Service 8264ee
							CFG_MAX_MSG_LEN - n);
Packit Service 8264ee
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case OP_CONFIG_DEFAULT_TTL_SET:
Packit Service 8264ee
		if (size != 1 || pkt[0] > TTL_MASK || pkt[0] == 1)
Packit Service 8264ee
			return true;
Packit Service 8264ee
Packit Service 8264ee
		if (pkt[0] <= TTL_MASK)
Packit Service 8264ee
			node_default_ttl_set(node, pkt[0]);
Packit Service 8264ee
		/* Fall Through */
Packit Service 8264ee
Packit Service 8264ee
	case OP_CONFIG_DEFAULT_TTL_GET:
Packit Service 8264ee
		l_debug("Get/Set Default TTL");
Packit Service 8264ee
Packit Service 8264ee
		n = mesh_model_opcode_set(OP_CONFIG_DEFAULT_TTL_STATUS, msg);
Packit Service 8264ee
		msg[n++] = node_default_ttl_get(node);
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case OP_CONFIG_MODEL_PUB_VIRT_SET:
Packit Service 8264ee
		if (size != 25 && size != 27)
Packit Service 8264ee
			return true;
Packit Service 8264ee
Packit Service 8264ee
		config_pub_set(node, net_idx, src, unicast, pkt, size,
Packit Service 8264ee
				!!(opcode & OP_UNRELIABLE));
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case OP_CONFIG_MODEL_PUB_SET:
Packit Service 8264ee
		if (size != 11 && size != 13)
Packit Service 8264ee
			return true;
Packit Service 8264ee
Packit Service 8264ee
		config_pub_set(node, net_idx, src, unicast, pkt, size,
Packit Service 8264ee
				!!(opcode & OP_UNRELIABLE));
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case OP_CONFIG_MODEL_PUB_GET:
Packit Service 8264ee
		config_pub_get(node, net_idx, src, unicast, pkt, size);
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case OP_CONFIG_VEND_MODEL_SUB_GET:
Packit Service 8264ee
		if (size != 6)
Packit Service 8264ee
			return true;
Packit Service 8264ee
Packit Service 8264ee
		config_sub_get(node, net_idx, src, unicast, pkt, size);
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case OP_CONFIG_MODEL_SUB_GET:
Packit Service 8264ee
		if (size != 4)
Packit Service 8264ee
			return true;
Packit Service 8264ee
Packit Service 8264ee
		config_sub_get(node, net_idx, src, unicast, pkt, size);
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case OP_CONFIG_MODEL_SUB_VIRT_OVERWRITE:
Packit Service 8264ee
	case OP_CONFIG_MODEL_SUB_VIRT_DELETE:
Packit Service 8264ee
	case OP_CONFIG_MODEL_SUB_VIRT_ADD:
Packit Service 8264ee
		virt = true;
Packit Service 8264ee
		/* Fall Through */
Packit Service 8264ee
	case OP_CONFIG_MODEL_SUB_OVERWRITE:
Packit Service 8264ee
	case OP_CONFIG_MODEL_SUB_DELETE:
Packit Service 8264ee
	case OP_CONFIG_MODEL_SUB_ADD:
Packit Service 8264ee
	case OP_CONFIG_MODEL_SUB_DELETE_ALL:
Packit Service 8264ee
		config_sub_set(node, net_idx, src, unicast, pkt, size, virt,
Packit Service 8264ee
									opcode);
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case OP_CONFIG_RELAY_SET:
Packit Service 8264ee
		if (size != 2 || pkt[0] > 0x01)
Packit Service 8264ee
			return true;
Packit Service 8264ee
Packit Service 8264ee
		count = (pkt[1] >> 5) + 1;
Packit Service 8264ee
		interval = ((pkt[1] & 0x1f) + 1) * 10;
Packit Service 8264ee
		node_relay_mode_set(node, !!pkt[0], count, interval);
Packit Service 8264ee
		/* Fall Through */
Packit Service 8264ee
Packit Service 8264ee
	case OP_CONFIG_RELAY_GET:
Packit Service 8264ee
		n = mesh_model_opcode_set(OP_CONFIG_RELAY_STATUS, msg);
Packit Service 8264ee
Packit Service 8264ee
		msg[n++] = node_relay_mode_get(node, &count, &interval);
Packit Service 8264ee
		msg[n++] = ((count - 1) << 5) + ((interval/10 - 1) & 0x1f);
Packit Service 8264ee
Packit Service 8264ee
		l_debug("Get/Set Relay Config (%d)", msg[n-1]);
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case OP_CONFIG_NETWORK_TRANSMIT_SET:
Packit Service 8264ee
		if (size != 1)
Packit Service 8264ee
			return true;
Packit Service 8264ee
Packit Service 8264ee
		count = (pkt[0] >> 5) + 1;
Packit Service 8264ee
		interval = ((pkt[0] & 0x1f) + 1) * 10;
Packit Service 8264ee
Packit Service 8264ee
		if (mesh_config_write_net_transmit(node_config_get(node), count,
Packit Service 8264ee
								interval))
Packit Service 8264ee
			mesh_net_transmit_params_set(net, count, interval);
Packit Service 8264ee
		/* Fall Through */
Packit Service 8264ee
Packit Service 8264ee
	case OP_CONFIG_NETWORK_TRANSMIT_GET:
Packit Service 8264ee
		n = mesh_model_opcode_set(OP_CONFIG_NETWORK_TRANSMIT_STATUS,
Packit Service 8264ee
									msg);
Packit Service 8264ee
		mesh_net_transmit_params_get(net, &count, &interval);
Packit Service 8264ee
		msg[n++] = ((count - 1) << 5) + ((interval/10 - 1) & 0x1f);
Packit Service 8264ee
Packit Service 8264ee
		l_debug("Get/Set Network Transmit Config");
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case OP_CONFIG_PROXY_SET:
Packit Service 8264ee
		if (size != 1 || pkt[0] > 0x01)
Packit Service 8264ee
			return true;
Packit Service 8264ee
Packit Service 8264ee
		node_proxy_mode_set(node, !!pkt[0]);
Packit Service 8264ee
		/* Fall Through */
Packit Service 8264ee
Packit Service 8264ee
	case OP_CONFIG_PROXY_GET:
Packit Service 8264ee
		n = mesh_model_opcode_set(OP_CONFIG_PROXY_STATUS, msg);
Packit Service 8264ee
Packit Service 8264ee
		msg[n++] = node_proxy_mode_get(node);
Packit Service 8264ee
		l_debug("Get/Set Config Proxy (%d)", msg[n-1]);
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case OP_NODE_IDENTITY_SET:
Packit Service 8264ee
		if (size != 3 || pkt[2] > 0x01)
Packit Service 8264ee
			return true;
Packit Service 8264ee
Packit Service 8264ee
		n_idx = l_get_le16(pkt);
Packit Service 8264ee
		if (n_idx > 0xfff)
Packit Service 8264ee
			return true;
Packit Service 8264ee
Packit Service 8264ee
		/*
Packit Service 8264ee
		 * Currently no support for proxy: node identity not supported
Packit Service 8264ee
		 */
Packit Service 8264ee
Packit Service 8264ee
		/* Fall Through */
Packit Service 8264ee
Packit Service 8264ee
	case OP_NODE_IDENTITY_GET:
Packit Service 8264ee
		if (size < 2)
Packit Service 8264ee
			return true;
Packit Service 8264ee
Packit Service 8264ee
		n_idx = l_get_le16(pkt);
Packit Service 8264ee
		if (n_idx > 0xfff)
Packit Service 8264ee
			return true;
Packit Service 8264ee
Packit Service 8264ee
		n = mesh_model_opcode_set(OP_NODE_IDENTITY_STATUS, msg);
Packit Service 8264ee
Packit Service 8264ee
		status = mesh_net_get_identity_mode(net, n_idx, &state);
Packit Service 8264ee
Packit Service 8264ee
		msg[n++] = status;
Packit Service 8264ee
Packit Service 8264ee
		l_put_le16(n_idx, msg + n);
Packit Service 8264ee
		n += 2;
Packit Service 8264ee
Packit Service 8264ee
		msg[n++] = state;
Packit Service 8264ee
		l_debug("Get/Set Config Identity (%d)", state);
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case OP_CONFIG_BEACON_SET:
Packit Service 8264ee
		if (size != 1 || pkt[0] > 0x01)
Packit Service 8264ee
			return true;
Packit Service 8264ee
Packit Service 8264ee
		node_beacon_mode_set(node, !!pkt[0]);
Packit Service 8264ee
		/* Fall Through */
Packit Service 8264ee
Packit Service 8264ee
	case OP_CONFIG_BEACON_GET:
Packit Service 8264ee
		n = mesh_model_opcode_set(OP_CONFIG_BEACON_STATUS, msg);
Packit Service 8264ee
Packit Service 8264ee
		msg[n++] = node_beacon_mode_get(node);
Packit Service 8264ee
		l_debug("Get/Set Config Beacon (%d)", msg[n-1]);
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case OP_CONFIG_FRIEND_SET:
Packit Service 8264ee
		if (size != 1 || pkt[0] > 0x01)
Packit Service 8264ee
			return true;
Packit Service 8264ee
Packit Service 8264ee
		node_friend_mode_set(node, !!pkt[0]);
Packit Service 8264ee
		/* Fall Through */
Packit Service 8264ee
Packit Service 8264ee
	case OP_CONFIG_FRIEND_GET:
Packit Service 8264ee
Packit Service 8264ee
		n = mesh_model_opcode_set(OP_CONFIG_FRIEND_STATUS, msg);
Packit Service 8264ee
Packit Service 8264ee
		msg[n++] = node_friend_mode_get(node);
Packit Service 8264ee
		l_debug("Get/Set Friend (%d)", msg[n-1]);
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case OP_CONFIG_KEY_REFRESH_PHASE_SET:
Packit Service 8264ee
		if (size != 3 || pkt[2] > 0x03)
Packit Service 8264ee
			return true;
Packit Service 8264ee
Packit Service 8264ee
		b_res = mesh_net_key_refresh_phase_set(net, l_get_le16(pkt),
Packit Service 8264ee
							pkt[2]);
Packit Service 8264ee
		size = 2;
Packit Service 8264ee
		/* Fall Through */
Packit Service 8264ee
Packit Service 8264ee
	case OP_CONFIG_KEY_REFRESH_PHASE_GET:
Packit Service 8264ee
		if (size != 2)
Packit Service 8264ee
			return true;
Packit Service 8264ee
Packit Service 8264ee
		n_idx = l_get_le16(pkt);
Packit Service 8264ee
Packit Service 8264ee
		n = mesh_model_opcode_set(OP_CONFIG_KEY_REFRESH_PHASE_STATUS,
Packit Service 8264ee
						msg);
Packit Service 8264ee
Packit Service 8264ee
		/* State: 0x00-0x03 phase of key refresh */
Packit Service 8264ee
		status = mesh_net_key_refresh_phase_get(net, n_idx,
Packit Service 8264ee
							&phase);
Packit Service 8264ee
		if (status != MESH_STATUS_SUCCESS) {
Packit Service 8264ee
			b_res = status;
Packit Service 8264ee
			phase = KEY_REFRESH_PHASE_NONE;
Packit Service 8264ee
		}
Packit Service 8264ee
Packit Service 8264ee
		msg[n++] = b_res;
Packit Service 8264ee
		l_put_le16(n_idx, msg + n);
Packit Service 8264ee
		n += 2;
Packit Service 8264ee
		msg[n++] = phase;
Packit Service 8264ee
Packit Service 8264ee
		l_debug("Get/Set Key Refresh State (%d)", msg[n-1]);
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case OP_APPKEY_ADD:
Packit Service 8264ee
	case OP_APPKEY_UPDATE:
Packit Service 8264ee
		if (size != 19)
Packit Service 8264ee
			return true;
Packit Service 8264ee
Packit Service 8264ee
		n_idx = l_get_le16(pkt) & 0xfff;
Packit Service 8264ee
		a_idx = l_get_le16(pkt + 1) >> 4;
Packit Service 8264ee
Packit Service 8264ee
		if (opcode == OP_APPKEY_ADD)
Packit Service 8264ee
			b_res = appkey_key_add(net, n_idx, a_idx, pkt + 3);
Packit Service 8264ee
		else
Packit Service 8264ee
			b_res = appkey_key_update(net, n_idx, a_idx,
Packit Service 8264ee
								pkt + 3);
Packit Service 8264ee
Packit Service 8264ee
		l_debug("Add/Update AppKey %s: Net_Idx %3.3x, App_Idx %3.3x",
Packit Service 8264ee
			(b_res == MESH_STATUS_SUCCESS) ? "success" : "fail",
Packit Service 8264ee
							n_idx, a_idx);
Packit Service 8264ee
Packit Service 8264ee
Packit Service 8264ee
		n = mesh_model_opcode_set(OP_APPKEY_STATUS, msg);
Packit Service 8264ee
Packit Service 8264ee
		msg[n++] = b_res;
Packit Service 8264ee
		msg[n++] = pkt[0];
Packit Service 8264ee
		msg[n++] = pkt[1];
Packit Service 8264ee
		msg[n++] = pkt[2];
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case OP_APPKEY_DELETE:
Packit Service 8264ee
		if (size != 3)
Packit Service 8264ee
			return true;
Packit Service 8264ee
Packit Service 8264ee
		n_idx = l_get_le16(pkt) & 0xfff;
Packit Service 8264ee
		a_idx = l_get_le16(pkt + 1) >> 4;
Packit Service 8264ee
		b_res = appkey_key_delete(net, n_idx, a_idx);
Packit Service 8264ee
		l_debug("Delete AppKey %s Net_Idx %3.3x to App_Idx %3.3x",
Packit Service 8264ee
			(b_res == MESH_STATUS_SUCCESS) ? "success" : "fail",
Packit Service 8264ee
							n_idx, a_idx);
Packit Service 8264ee
Packit Service 8264ee
		n = mesh_model_opcode_set(OP_APPKEY_STATUS, msg);
Packit Service 8264ee
		msg[n++] = b_res;
Packit Service 8264ee
		msg[n++] = pkt[0];
Packit Service 8264ee
		msg[n++] = pkt[1];
Packit Service 8264ee
		msg[n++] = pkt[2];
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case OP_APPKEY_GET:
Packit Service 8264ee
		if (size != 2)
Packit Service 8264ee
			return true;
Packit Service 8264ee
Packit Service 8264ee
		n_idx = l_get_le16(pkt);
Packit Service 8264ee
Packit Service 8264ee
		long_msg = l_malloc(CFG_MAX_MSG_LEN);
Packit Service 8264ee
		n = mesh_model_opcode_set(OP_APPKEY_LIST, long_msg);
Packit Service 8264ee
Packit Service 8264ee
		status = appkey_list(net, n_idx, long_msg + n + 3,
Packit Service 8264ee
						CFG_MAX_MSG_LEN - n - 3, &size);
Packit Service 8264ee
Packit Service 8264ee
		long_msg[n] = status;
Packit Service 8264ee
		l_put_le16(n_idx, long_msg + n + 1);
Packit Service 8264ee
		n += (size + 3);
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case OP_NETKEY_ADD:
Packit Service 8264ee
	case OP_NETKEY_UPDATE:
Packit Service 8264ee
		if (size != 18)
Packit Service 8264ee
			return true;
Packit Service 8264ee
Packit Service 8264ee
		n_idx = l_get_le16(pkt);
Packit Service 8264ee
Packit Service 8264ee
		if (opcode == OP_NETKEY_ADD)
Packit Service 8264ee
			b_res = mesh_net_add_key(net, n_idx, pkt + 2);
Packit Service 8264ee
		else
Packit Service 8264ee
			b_res = mesh_net_update_key(net, n_idx, pkt + 2);
Packit Service 8264ee
Packit Service 8264ee
		l_debug("NetKey Add/Update %s",
Packit Service 8264ee
			(b_res == MESH_STATUS_SUCCESS) ? "success" : "fail");
Packit Service 8264ee
Packit Service 8264ee
		n = mesh_model_opcode_set(OP_NETKEY_STATUS, msg);
Packit Service 8264ee
		msg[n++] = b_res;
Packit Service 8264ee
		l_put_le16(l_get_le16(pkt), msg + n);
Packit Service 8264ee
		n += 2;
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case OP_NETKEY_DELETE:
Packit Service 8264ee
		if (size != 2)
Packit Service 8264ee
			return true;
Packit Service 8264ee
Packit Service 8264ee
		b_res = mesh_net_del_key(net, l_get_le16(pkt));
Packit Service 8264ee
Packit Service 8264ee
		l_debug("NetKey delete %s",
Packit Service 8264ee
			(b_res == MESH_STATUS_SUCCESS) ? "success" : "fail");
Packit Service 8264ee
Packit Service 8264ee
		n = mesh_model_opcode_set(OP_NETKEY_STATUS, msg);
Packit Service 8264ee
		msg[n++] = b_res;
Packit Service 8264ee
		l_put_le16(l_get_le16(pkt), msg + n);
Packit Service 8264ee
		n += 2;
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case OP_NETKEY_GET:
Packit Service 8264ee
		long_msg = l_malloc(CFG_MAX_MSG_LEN);
Packit Service 8264ee
		n = mesh_model_opcode_set(OP_NETKEY_LIST, long_msg);
Packit Service 8264ee
		size = CFG_MAX_MSG_LEN - n;
Packit Service 8264ee
Packit Service 8264ee
		if (mesh_net_key_list_get(net, long_msg + n, &size))
Packit Service 8264ee
			n += size;
Packit Service 8264ee
		else
Packit Service 8264ee
			n = 0;
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case OP_MODEL_APP_BIND:
Packit Service 8264ee
	case OP_MODEL_APP_UNBIND:
Packit Service 8264ee
		model_app_bind(node, net_idx, src, unicast, pkt, size,
Packit Service 8264ee
				opcode != OP_MODEL_APP_BIND);
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case OP_VEND_MODEL_APP_GET:
Packit Service 8264ee
		if (size != 6)
Packit Service 8264ee
			return true;
Packit Service 8264ee
		model_app_list(node, net_idx, src, unicast, pkt, size);
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case OP_MODEL_APP_GET:
Packit Service 8264ee
		if (size != 4)
Packit Service 8264ee
			return true;
Packit Service 8264ee
		model_app_list(node, net_idx, src, unicast, pkt, size);
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case OP_CONFIG_HEARTBEAT_PUB_SET:
Packit Service 8264ee
		l_debug("OP_CONFIG_HEARTBEAT_PUB_SET");
Packit Service 8264ee
		if (size != 9) {
Packit Service 8264ee
			l_debug("bad size %d", size);
Packit Service 8264ee
			return true;
Packit Service 8264ee
		}
Packit Service 8264ee
		if (pkt[2] > 0x11 || pkt[3] > 0x10 || pkt[4] > 0x7f)
Packit Service 8264ee
			return true;
Packit Service 8264ee
		else if (IS_VIRTUAL(l_get_le16(pkt)))
Packit Service 8264ee
			b_res = MESH_STATUS_INVALID_ADDRESS;
Packit Service 8264ee
		else if (l_get_le16(pkt + 7) != mesh_net_get_primary_idx(net))
Packit Service 8264ee
			/* Future work: check for valid subnets */
Packit Service 8264ee
			b_res = MESH_STATUS_INVALID_NETKEY;
Packit Service 8264ee
Packit Service 8264ee
		n = mesh_model_opcode_set(OP_CONFIG_HEARTBEAT_PUB_STATUS,
Packit Service 8264ee
						msg);
Packit Service 8264ee
		msg[n++] = b_res;
Packit Service 8264ee
Packit Service 8264ee
		memcpy(&msg[n], pkt, 9);
Packit Service 8264ee
Packit Service 8264ee
		/* Ignore RFU bits in features */
Packit Service 8264ee
		l_put_le16(l_get_le16(pkt + 5) & 0xf, &msg[n + 5]);
Packit Service 8264ee
Packit Service 8264ee
		/* Add octet count to status */
Packit Service 8264ee
		n += 9;
Packit Service 8264ee
Packit Service 8264ee
		if (b_res != MESH_STATUS_SUCCESS)
Packit Service 8264ee
			break;
Packit Service 8264ee
Packit Service 8264ee
		hb->pub_dst = l_get_le16(pkt);
Packit Service 8264ee
		if (hb->pub_dst == UNASSIGNED_ADDRESS ||
Packit Service 8264ee
				pkt[2] == 0 || pkt[3] == 0) {
Packit Service 8264ee
			/*
Packit Service 8264ee
			 * We might still have a pub_dst here in case
Packit Service 8264ee
			 * we need it for State Change heartbeat
Packit Service 8264ee
			 */
Packit Service 8264ee
			hb->pub_count = 0;
Packit Service 8264ee
			hb->pub_period = 0;
Packit Service 8264ee
		} else {
Packit Service 8264ee
			hb->pub_count = (pkt[2] != 0xff) ?
Packit Service 8264ee
				log_to_uint32(pkt[2], 1) : 0xffff;
Packit Service 8264ee
			hb->pub_period = log_to_uint32(pkt[3], 1);
Packit Service 8264ee
		}
Packit Service 8264ee
Packit Service 8264ee
		hb->pub_ttl = pkt[4];
Packit Service 8264ee
		hb->pub_features = l_get_le16(pkt + 5) & 0xf;
Packit Service 8264ee
		hb->pub_net_idx = l_get_le16(pkt + 7);
Packit Service 8264ee
		update_hb_pub_timer(net, hb);
Packit Service 8264ee
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case OP_CONFIG_HEARTBEAT_PUB_GET:
Packit Service 8264ee
		n = mesh_model_opcode_set(OP_CONFIG_HEARTBEAT_PUB_STATUS, msg);
Packit Service 8264ee
		msg[n++] = b_res;
Packit Service 8264ee
		l_put_le16(hb->pub_dst, msg + n);
Packit Service 8264ee
		n += 2;
Packit Service 8264ee
		msg[n++] = uint32_to_log(hb->pub_count);
Packit Service 8264ee
		msg[n++] = uint32_to_log(hb->pub_period);
Packit Service 8264ee
		msg[n++] = hb->pub_ttl;
Packit Service 8264ee
		l_put_le16(hb->pub_features, msg + n);
Packit Service 8264ee
		n += 2;
Packit Service 8264ee
		l_put_le16(hb->pub_net_idx, msg + n);
Packit Service 8264ee
		n += 2;
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case OP_CONFIG_HEARTBEAT_SUB_SET:
Packit Service 8264ee
		if (size != 5)
Packit Service 8264ee
			return true;
Packit Service 8264ee
Packit Service 8264ee
		l_debug("Set Sub Period (Log %2.2x) %d sec",
Packit Service 8264ee
				pkt[4], log_to_uint32(pkt[4], 1));
Packit Service 8264ee
Packit Service 8264ee
		b_res = hb_subscription_set(net, l_get_le16(pkt),
Packit Service 8264ee
						l_get_le16(pkt + 2),
Packit Service 8264ee
						pkt[4]);
Packit Service 8264ee
		if (b_res < 0)
Packit Service 8264ee
			return true;
Packit Service 8264ee
Packit Service 8264ee
		/* Fall through */
Packit Service 8264ee
Packit Service 8264ee
	case OP_CONFIG_HEARTBEAT_SUB_GET:
Packit Service 8264ee
		gettimeofday(&time_now, NULL);
Packit Service 8264ee
		time_now.tv_sec -= hb->sub_start;
Packit Service 8264ee
Packit Service 8264ee
		if (time_now.tv_sec >= (long int) hb->sub_period)
Packit Service 8264ee
			time_now.tv_sec = 0;
Packit Service 8264ee
		else
Packit Service 8264ee
			time_now.tv_sec = hb->sub_period - time_now.tv_sec;
Packit Service 8264ee
Packit Service 8264ee
		l_debug("Sub Period (Log %2.2x) %d sec",
Packit Service 8264ee
				uint32_to_log(time_now.tv_sec),
Packit Service 8264ee
				(int) time_now.tv_sec);
Packit Service 8264ee
Packit Service 8264ee
		n = mesh_model_opcode_set(OP_CONFIG_HEARTBEAT_SUB_STATUS, msg);
Packit Service 8264ee
		msg[n++] = b_res;
Packit Service 8264ee
		l_put_le16(hb->sub_src, msg + n);
Packit Service 8264ee
		n += 2;
Packit Service 8264ee
		l_put_le16(hb->sub_dst, msg + n);
Packit Service 8264ee
		n += 2;
Packit Service 8264ee
		msg[n++] = uint32_to_log(time_now.tv_sec);
Packit Service 8264ee
		msg[n++] = uint32_to_log(hb->sub_count);
Packit Service 8264ee
		msg[n++] = hb->sub_count ? hb->sub_min_hops : 0;
Packit Service 8264ee
		msg[n++] = hb->sub_max_hops;
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case OP_CONFIG_POLL_TIMEOUT_LIST:
Packit Service 8264ee
		if (size != 2 || l_get_le16(pkt) == 0 ||
Packit Service 8264ee
						l_get_le16(pkt) > 0x7fff)
Packit Service 8264ee
			return true;
Packit Service 8264ee
Packit Service 8264ee
		n = mesh_model_opcode_set(OP_CONFIG_POLL_TIMEOUT_STATUS, msg);
Packit Service 8264ee
		l_put_le16(l_get_le16(pkt), msg + n);
Packit Service 8264ee
		n += 2;
Packit Service 8264ee
		tmp32 = mesh_net_friend_timeout(net, l_get_le16(pkt));
Packit Service 8264ee
		msg[n++] = tmp32;
Packit Service 8264ee
		msg[n++] = tmp32 >> 8;
Packit Service 8264ee
		msg[n++] = tmp32 >> 16;
Packit Service 8264ee
		break;
Packit Service 8264ee
Packit Service 8264ee
	case OP_NODE_RESET:
Packit Service 8264ee
		n = mesh_model_opcode_set(OP_NODE_RESET_STATUS, msg);
Packit Service 8264ee
		l_timeout_create(1, node_reset, net, NULL);
Packit Service 8264ee
		break;
Packit Service 8264ee
	}
Packit Service 8264ee
Packit Service 8264ee
	if (n) {
Packit Service 8264ee
		/* print_packet("App Tx", long_msg ? long_msg : msg, n); */
Packit Service 8264ee
		mesh_model_send(node, unicast, src,
Packit Service 8264ee
				APP_IDX_DEV_LOCAL, net_idx, DEFAULT_TTL,
Packit Service 8264ee
				long_msg ? long_msg : msg, n);
Packit Service 8264ee
	}
Packit Service 8264ee
	l_free(long_msg);
Packit Service 8264ee
Packit Service 8264ee
	return true;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static void cfgmod_srv_unregister(void *user_data)
Packit Service 8264ee
{
Packit Service 8264ee
	struct mesh_node *node = user_data;
Packit Service 8264ee
	struct mesh_net *net = node_get_net(node);
Packit Service 8264ee
	struct mesh_net_heartbeat *hb = mesh_net_heartbeat_get(net);
Packit Service 8264ee
Packit Service 8264ee
	l_timeout_remove(hb->pub_timer);
Packit Service 8264ee
	l_timeout_remove(hb->sub_timer);
Packit Service 8264ee
	hb->pub_timer = hb->sub_timer = NULL;
Packit Service 8264ee
}
Packit Service 8264ee
Packit Service 8264ee
static const struct mesh_model_ops ops = {
Packit Service 8264ee
	.unregister = cfgmod_srv_unregister,
Packit Service 8264ee
	.recv = cfg_srv_pkt,
Packit Service 8264ee
	.bind = NULL,
Packit Service 8264ee
	.sub = NULL,
Packit Service 8264ee
	.pub = NULL
Packit Service 8264ee
};
Packit Service 8264ee
Packit Service 8264ee
void cfgmod_server_init(struct mesh_node *node, uint8_t ele_idx)
Packit Service 8264ee
{
Packit Service 8264ee
	l_debug("%2.2x", ele_idx);
Packit Service 8264ee
	mesh_model_register(node, ele_idx, CONFIG_SRV_MODEL, &ops, node);
Packit Service 8264ee
}