mirror of
https://git.kernel.org/pub/scm/bluetooth/bluez.git
synced 2024-11-15 16:24:28 +08:00
386 lines
12 KiB
C
386 lines
12 KiB
C
/*
|
|
*
|
|
* BlueZ - Bluetooth protocol stack for Linux
|
|
*
|
|
* Copyright (C) 2018-2019 Intel Corporation. All rights reserved.
|
|
*
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
*/
|
|
|
|
#ifndef __packed
|
|
#define __packed __attribute__((packed))
|
|
#endif
|
|
|
|
struct mesh_io;
|
|
struct mesh_node;
|
|
|
|
#define DEV_ID 0
|
|
|
|
#define UNUSED_KEY_IDX 0xffff
|
|
|
|
#define APP_AID_DEV 0x00
|
|
|
|
#define CTL 0x80
|
|
|
|
#define CREDFLAG_MASK 0x1000
|
|
|
|
#define KEY_CACHE_SIZE 64
|
|
#define FRND_CACHE_MAX 32
|
|
|
|
#define MAX_UNSEG_LEN 15 /* msg_len == 11 + sizeof(MIC) */
|
|
#define MAX_SEG_LEN 12 /* UnSeg length - 3 octets overhead */
|
|
#define SEG_MAX(seg, len) ((!seg && len <= MAX_UNSEG_LEN) ? 0 : \
|
|
(((len) - 1) / MAX_SEG_LEN))
|
|
|
|
#define SEG_OFF(seg) ((seg) * MAX_SEG_LEN)
|
|
#define MAX_SEG_TO_LEN(seg) ((seg) ? SEG_OFF((seg) + 1) : MAX_UNSEG_LEN)
|
|
|
|
#define SEGMENTED 0x80
|
|
#define UNSEGMENTED 0x00
|
|
#define SEG_HDR_SHIFT 31
|
|
#define IS_SEGMENTED(hdr) (!!((hdr) & (true << SEG_HDR_SHIFT)))
|
|
|
|
#define KEY_ID_MASK 0x7f
|
|
#define KEY_AID_MASK 0x3f
|
|
#define KEY_ID_AKF 0x40
|
|
#define KEY_AID_SHIFT 0
|
|
#define AKF_HDR_SHIFT 30
|
|
#define KEY_HDR_SHIFT 24
|
|
#define HAS_APP_KEY(hdr) (!!((hdr) & (true << AKF_HDR_SHIFT)))
|
|
|
|
#define OPCODE_MASK 0x7f
|
|
#define OPCODE_HDR_SHIFT 24
|
|
#define RELAY 0x80
|
|
#define RELAY_HDR_SHIFT 23
|
|
#define SZMIC 0x80
|
|
#define SZMIC_HDR_SHIFT 23
|
|
#define SEQ_ZERO_MASK 0x1fff
|
|
#define SEQ_ZERO_HDR_SHIFT 10
|
|
#define IS_RELAYED(hdr) (!!((hdr) & (true << RELAY_HDR_SHIFT)))
|
|
#define HAS_MIC64(hdr) (!!((hdr) & (true << SZMIC_HDR_SHIFT)))
|
|
|
|
#define SEG_MASK 0x1f
|
|
#define SEGO_HDR_SHIFT 5
|
|
#define SEGN_HDR_SHIFT 0
|
|
#define SEG_TOTAL(hdr) (((hdr) >> SEGN_HDR_SHIFT) & SEG_MASK)
|
|
|
|
/* Mask of Hdr bits which must be constant over entire incoming SAR message */
|
|
/* (SEG || AKF || AID || SZMIC || SeqZero || SegN) */
|
|
#define HDR_KEY_MASK ((true << SEG_HDR_SHIFT) | \
|
|
(KEY_ID_MASK << KEY_HDR_SHIFT) | \
|
|
(true << SZMIC_HDR_SHIFT) | \
|
|
(SEQ_ZERO_MASK << SEQ_ZERO_HDR_SHIFT) | \
|
|
(SEG_MASK << SEGN_HDR_SHIFT))
|
|
|
|
#define HDR_ACK_MASK ((OPCODE_MASK << OPCODE_HDR_SHIFT) | \
|
|
(SEQ_ZERO_MASK << SEQ_ZERO_HDR_SHIFT))
|
|
|
|
|
|
|
|
#define MSG_CACHE_SIZE 70
|
|
#define REPLAY_CACHE_SIZE 10
|
|
|
|
/* Proxy Configuration Opcodes */
|
|
#define PROXY_OP_SET_FILTER_TYPE 0x00
|
|
#define PROXY_OP_FILTER_ADD 0x01
|
|
#define PROXY_OP_FILTER_DEL 0x02
|
|
#define PROXY_OP_FILTER_STATUS 0x03
|
|
|
|
/* Proxy Filter Defines */
|
|
#define PROXY_FILTER_WHITELIST 0x00
|
|
#define PROXY_FILTER_BLACKLIST 0x01
|
|
|
|
/* Network Tranport Opcodes */
|
|
#define NET_OP_SEG_ACKNOWLEDGE 0x00
|
|
#define NET_OP_FRND_POLL 0x01
|
|
#define NET_OP_FRND_UPDATE 0x02
|
|
#define NET_OP_FRND_REQUEST 0x03
|
|
#define NET_OP_FRND_OFFER 0x04
|
|
#define NET_OP_FRND_CLEAR 0x05
|
|
#define NET_OP_FRND_CLEAR_CONFIRM 0x06
|
|
|
|
#define NET_OP_PROXY_SUB_ADD 0x07
|
|
#define NET_OP_PROXY_SUB_REMOVE 0x08
|
|
#define NET_OP_PROXY_SUB_CONFIRM 0x09
|
|
#define NET_OP_HEARTBEAT 0x0a
|
|
|
|
#define FRND_OPCODE(x) \
|
|
((x) >= NET_OP_FRND_POLL && (x) <= NET_OP_FRND_CLEAR_CONFIRM)
|
|
|
|
#define DEFAULT_MIN_DELAY 0
|
|
#define DEFAULT_MAX_DELAY 25
|
|
|
|
struct mesh_net_addr_range {
|
|
uint16_t low;
|
|
uint16_t high;
|
|
uint16_t next;
|
|
};
|
|
|
|
struct mesh_net_prov_caps {
|
|
uint8_t num_ele;
|
|
uint16_t algorithms;
|
|
uint8_t pub_type;
|
|
uint8_t static_type;
|
|
uint8_t output_size;
|
|
uint16_t output_action;
|
|
uint8_t input_size;
|
|
uint16_t input_action;
|
|
} __packed;
|
|
|
|
struct mesh_net_heartbeat {
|
|
struct l_timeout *pub_timer;
|
|
struct l_timeout *sub_timer;
|
|
struct timeval sub_time;
|
|
bool sub_enabled;
|
|
uint32_t pub_period;
|
|
uint32_t sub_period;
|
|
uint32_t sub_start;
|
|
uint16_t pub_dst;
|
|
uint16_t pub_count;
|
|
uint16_t pub_features;
|
|
uint16_t features;
|
|
uint16_t pub_net_idx;
|
|
uint16_t sub_src;
|
|
uint16_t sub_dst;
|
|
uint16_t sub_count;
|
|
uint8_t pub_ttl;
|
|
uint8_t sub_min_hops;
|
|
uint8_t sub_max_hops;
|
|
};
|
|
|
|
struct mesh_key_set {
|
|
bool frnd;
|
|
uint8_t nid;
|
|
uint8_t enc_key[16];
|
|
uint8_t privacy_key[16];
|
|
};
|
|
|
|
struct friend_neg {
|
|
int8_t rssi;
|
|
bool clearing;
|
|
};
|
|
|
|
struct friend_act {
|
|
uint16_t *grp_list;
|
|
uint32_t last_hdr;
|
|
int16_t grp_cnt;
|
|
bool seq;
|
|
bool last;
|
|
};
|
|
|
|
struct mesh_friend {
|
|
struct mesh_net *net;
|
|
struct l_timeout *timeout;
|
|
struct l_queue *pkt_cache;
|
|
void *pkt;
|
|
uint32_t poll_timeout;
|
|
uint32_t net_key_cur;
|
|
uint32_t net_key_upd;
|
|
uint16_t old_friend;
|
|
uint16_t net_idx;
|
|
uint16_t lp_addr;/* dst; * Primary Element unicast addr */
|
|
uint16_t fn_cnt;
|
|
uint16_t lp_cnt;
|
|
uint8_t receive_delay;
|
|
uint8_t ele_cnt;
|
|
uint8_t frd;
|
|
uint8_t frw;
|
|
union {
|
|
struct friend_neg negotiate;
|
|
struct friend_act active;
|
|
} u;
|
|
};
|
|
|
|
struct mesh_frnd_pkt {
|
|
uint32_t iv_index;
|
|
uint32_t seq;
|
|
uint16_t src;
|
|
uint16_t dst;
|
|
uint16_t size;
|
|
uint8_t segN;
|
|
uint8_t segO;
|
|
uint8_t ttl;
|
|
uint8_t tc;
|
|
bool szmict;
|
|
union {
|
|
struct {
|
|
uint8_t key_id;
|
|
} m;
|
|
struct {
|
|
uint16_t seq0;
|
|
} a;
|
|
struct {
|
|
uint8_t opcode;
|
|
} c;
|
|
} u;
|
|
uint8_t data[];
|
|
};
|
|
|
|
struct mesh_friend_seg_one {
|
|
uint32_t hdr;
|
|
uint32_t seq;
|
|
bool sent;
|
|
bool md;
|
|
uint8_t data[15];
|
|
};
|
|
|
|
struct mesh_friend_seg_12 {
|
|
uint32_t hdr;
|
|
uint32_t seq;
|
|
bool sent;
|
|
bool md;
|
|
uint8_t data[12];
|
|
};
|
|
|
|
struct mesh_friend_msg {
|
|
uint32_t iv_index;
|
|
uint32_t flags;
|
|
uint16_t src;
|
|
uint16_t dst;
|
|
uint8_t ttl;
|
|
uint8_t cnt_in;
|
|
uint8_t cnt_out;
|
|
uint8_t last_len;
|
|
bool done;
|
|
bool ctl;
|
|
union {
|
|
struct mesh_friend_seg_one one[1]; /* Single segment */
|
|
struct mesh_friend_seg_12 s12[0]; /* Array of segments */
|
|
} u;
|
|
};
|
|
|
|
typedef void (*mesh_status_func_t)(void *user_data, bool result);
|
|
typedef void (*mesh_net_status_func_t)(uint16_t remote, uint8_t status,
|
|
void *data, uint16_t size,
|
|
void *user_data);
|
|
|
|
struct mesh_net *mesh_net_new(struct mesh_node *node);
|
|
void mesh_net_free(struct mesh_net *net);
|
|
void mesh_net_flush_msg_queues(struct mesh_net *net);
|
|
void mesh_net_set_iv_index(struct mesh_net *net, uint32_t index, bool update);
|
|
bool mesh_net_iv_index_update(struct mesh_net *net);
|
|
bool mesh_net_set_seq_num(struct mesh_net *net, uint32_t number);
|
|
uint32_t mesh_net_get_seq_num(struct mesh_net *net);
|
|
uint32_t mesh_net_next_seq_num(struct mesh_net *net);
|
|
bool mesh_net_set_default_ttl(struct mesh_net *net, uint8_t ttl);
|
|
uint8_t mesh_net_get_default_ttl(struct mesh_net *net);
|
|
bool mesh_net_get_frnd_seq(struct mesh_net *net);
|
|
void mesh_net_set_frnd_seq(struct mesh_net *net, bool seq);
|
|
uint16_t mesh_net_get_address(struct mesh_net *net);
|
|
bool mesh_net_register_unicast(struct mesh_net *net,
|
|
uint16_t unicast, uint8_t num_ele);
|
|
uint8_t mesh_net_get_num_ele(struct mesh_net *net);
|
|
void net_local_beacon(uint32_t key_id, uint8_t *beacon);
|
|
bool mesh_net_set_beacon_mode(struct mesh_net *net, bool enable);
|
|
bool mesh_net_set_proxy_mode(struct mesh_net *net, bool enable);
|
|
bool mesh_net_set_relay_mode(struct mesh_net *net, bool enable, uint8_t cnt,
|
|
uint8_t interval);
|
|
bool mesh_net_set_friend_mode(struct mesh_net *net, bool enable);
|
|
int mesh_net_del_key(struct mesh_net *net, uint16_t net_idx);
|
|
int mesh_net_add_key(struct mesh_net *net, uint16_t net_idx,
|
|
const uint8_t *key);
|
|
int mesh_net_update_key(struct mesh_net *net, uint16_t net_idx,
|
|
const uint8_t *key);
|
|
bool mesh_net_set_key(struct mesh_net *net, uint16_t idx, const uint8_t *key,
|
|
const uint8_t *new_key, uint8_t phase);
|
|
uint32_t mesh_net_get_iv_index(struct mesh_net *net);
|
|
void mesh_net_get_snb_state(struct mesh_net *net,
|
|
uint8_t *flags, uint32_t *iv_index);
|
|
bool mesh_net_get_key(struct mesh_net *net, bool new_key, uint16_t idx,
|
|
uint32_t *key_id);
|
|
bool mesh_net_attach(struct mesh_net *net, struct mesh_io *io);
|
|
struct mesh_io *mesh_net_detach(struct mesh_net *net);
|
|
struct l_queue *mesh_net_get_app_keys(struct mesh_net *net);
|
|
|
|
bool mesh_net_flush(struct mesh_net *net);
|
|
void mesh_net_transport_send(struct mesh_net *net, uint32_t key_id,
|
|
uint16_t net_idx, uint32_t iv_index,
|
|
uint8_t ttl, uint32_t seq, uint16_t src,
|
|
uint16_t dst, const uint8_t *msg,
|
|
uint16_t msg_len);
|
|
|
|
bool mesh_net_app_send(struct mesh_net *net, bool frnd_cred, uint16_t src,
|
|
uint16_t dst, uint8_t key_id, uint16_t net_idx,
|
|
uint8_t ttl, uint32_t seq, uint32_t iv_index,
|
|
bool segmented, bool szmic,
|
|
const void *msg, uint16_t msg_len,
|
|
mesh_net_status_func_t status_func,
|
|
void *user_data);
|
|
void mesh_net_ack_send(struct mesh_net *net, uint32_t key_id,
|
|
uint32_t iv_index, uint8_t ttl, uint32_t seq,
|
|
uint16_t src, uint16_t dst, bool rly,
|
|
uint16_t seqZero, uint32_t ack_flags);
|
|
struct mesh_net_prov_caps *mesh_net_prov_caps_get(struct mesh_net *net);
|
|
uint8_t *mesh_net_priv_key_get(struct mesh_net *net);
|
|
bool mesh_net_priv_key_set(struct mesh_net *net, uint8_t key[32]);
|
|
uint8_t *mesh_net_prov_rand(struct mesh_net *net);
|
|
uint16_t mesh_net_prov_uni(struct mesh_net *net, uint8_t ele_cnt);
|
|
bool mesh_net_id_uuid_set(struct mesh_net *net, uint8_t uuid[16]);
|
|
uint8_t *mesh_net_test_addr(struct mesh_net *net);
|
|
int mesh_net_get_identity_mode(struct mesh_net *net, uint16_t idx,
|
|
uint8_t *mode);
|
|
char *mesh_net_id_name(struct mesh_net *net);
|
|
bool mesh_net_test_mode(struct mesh_net *net);
|
|
bool mesh_net_dst_reg(struct mesh_net *net, uint16_t dst);
|
|
bool mesh_net_dst_unreg(struct mesh_net *net, uint16_t dst);
|
|
struct mesh_friend *mesh_friend_new(struct mesh_net *net, uint16_t dst,
|
|
uint8_t ele_cnt, uint8_t frd,
|
|
uint8_t frw, uint32_t fpt,
|
|
uint16_t fn_cnt, uint16_t lp_cnt);
|
|
void mesh_friend_free(void *frnd);
|
|
bool mesh_friend_clear(struct mesh_net *net, struct mesh_friend *frnd);
|
|
void mesh_friend_sub_add(struct mesh_net *net, uint16_t lpn, uint8_t ele_cnt,
|
|
uint8_t grp_cnt,
|
|
const uint8_t *list);
|
|
void mesh_friend_sub_del(struct mesh_net *net, uint16_t lpn, uint8_t cnt,
|
|
const uint8_t *del_list);
|
|
uint8_t mesh_net_key_refresh_phase_set(struct mesh_net *net, uint16_t net_idx,
|
|
uint8_t transition);
|
|
uint8_t mesh_net_key_refresh_phase_get(struct mesh_net *net, uint16_t net_idx,
|
|
uint8_t *phase);
|
|
void mesh_net_send_seg(struct mesh_net *net, uint32_t key_id,
|
|
uint32_t iv_index, uint8_t ttl, uint32_t seq,
|
|
uint16_t src, uint16_t dst, uint32_t hdr,
|
|
const void *seg, uint16_t seg_len);
|
|
uint16_t mesh_net_get_features(struct mesh_net *net);
|
|
struct mesh_net_heartbeat *mesh_net_heartbeat_get(struct mesh_net *net);
|
|
void mesh_net_heartbeat_init(struct mesh_net *net);
|
|
void mesh_net_heartbeat_send(struct mesh_net *net);
|
|
void mesh_net_uni_range_set(struct mesh_net *net,
|
|
struct mesh_net_addr_range *range);
|
|
struct mesh_net_addr_range mesh_net_uni_range_get(struct mesh_net *net);
|
|
void mesh_net_provisioner_mode_set(struct mesh_net *net, bool mode);
|
|
bool mesh_net_provisioner_mode_get(struct mesh_net *net);
|
|
bool mesh_net_key_list_get(struct mesh_net *net, uint8_t *buf, uint16_t *count);
|
|
uint16_t mesh_net_get_primary_idx(struct mesh_net *net);
|
|
uint32_t mesh_net_friend_timeout(struct mesh_net *net, uint16_t addr);
|
|
struct mesh_io *mesh_net_get_io(struct mesh_net *net);
|
|
struct mesh_node *mesh_net_node_get(struct mesh_net *net);
|
|
bool mesh_net_have_key(struct mesh_net *net, uint16_t net_idx);
|
|
bool mesh_net_is_local_address(struct mesh_net *net, uint16_t src,
|
|
uint16_t count);
|
|
void mesh_net_set_window_accuracy(struct mesh_net *net, uint8_t accuracy);
|
|
void mesh_net_transmit_params_set(struct mesh_net *net, uint8_t count,
|
|
uint16_t interval);
|
|
void mesh_net_transmit_params_get(struct mesh_net *net, uint8_t *count,
|
|
uint16_t *interval);
|
|
struct mesh_prov *mesh_net_get_prov(struct mesh_net *net);
|
|
void mesh_net_set_prov(struct mesh_net *net, struct mesh_prov *prov);
|
|
uint32_t mesh_net_get_instant(struct mesh_net *net);
|
|
struct l_queue *mesh_net_get_friends(struct mesh_net *net);
|
|
struct l_queue *mesh_net_get_negotiations(struct mesh_net *net);
|
|
bool net_msg_check_replay_cache(struct mesh_net *net, uint16_t src,
|
|
uint16_t crpl, uint32_t seq, uint32_t iv_index);
|
|
void net_msg_add_replay_cache(struct mesh_net *net, uint16_t src, uint32_t seq,
|
|
uint32_t iv_index);
|