dect
/
libnl
Archived
13
0
Fork 0

libnl: import DECT support

Signed-off-by: Patrick McHardy <kaber@trash.net>
This commit is contained in:
Patrick McHardy 2009-05-06 18:55:44 +02:00
parent b24d4fa5db
commit be93d3d46c
35 changed files with 4024 additions and 4 deletions

View File

@ -31,6 +31,7 @@ install:
mkdir -p $(DESTDIR)$(includedir)/netlink/genl/
mkdir -p $(DESTDIR)$(includedir)/netlink/fib_lookup/
mkdir -p $(DESTDIR)$(includedir)/netlink/netfilter
mkdir -p $(DESTDIR)$(includedir)/netlink/dect
install -m 0644 netlink/*.h $(DESTDIR)$(includedir)/netlink/
install -m 0644 netlink/route/*.h $(DESTDIR)$(includedir)/netlink/route/
install -m 0644 netlink/route/sch/*.h $(DESTDIR)$(includedir)/netlink/route/sch/
@ -39,4 +40,4 @@ install:
install -m 0644 netlink/genl/*.h $(DESTDIR)$(includedir)/netlink/genl/
install -m 0644 netlink/fib_lookup/*.h $(DESTDIR)$(includedir)/netlink/fib_lookup/
install -m 0644 netlink/netfilter/*.h $(DESTDIR)$(includedir)/netlink/netfilter/
install -m 0644 netlink/dect/*.h $(DESTDIR)$(includedir)/netlink/dect

View File

@ -0,0 +1,255 @@
#ifndef _LINUX_DECT_NETLINK_H
#define _LINUX_DECT_NETLINK_H
struct dectmsg {
int dm_index;
};
enum dect_nlgroups {
DECTNLGRP_NONE,
DECTNLGRP_TRANSCEIVER,
DECTNLGRP_CELL,
DECTNLGRP_CLUSTER,
DECTNLGRP_LLME,
__DECTNLGRP_MAX
};
#define DECTNLGRP_MAX (__DECTNLGRP_MAX - 1)
enum dect_netlink_msg_types {
DECT_MSG_BASE = 0x10,
DECT_NEW_TRANSCEIVER,
DECT_DEL_TRANSCEIVER,
DECT_GET_TRANSCEIVER,
DECT_NEW_CELL,
DECT_DEL_CELL,
DECT_GET_CELL,
DECT_NEW_CLUSTER,
DECT_DEL_CLUSTER,
DECT_GET_CLUSTER,
DECT_LLME_MSG,
__DECT_MSG_MAX
};
#define DECT_MSG_MAX (__DECT_MSG_MAX - 1)
#define DECT_NR_MSGTYPES (DECT_MSG_MAX + 1 - DECT_MSG_BASE)
enum dect_list_attrs {
DECTA_LIST_UNSPEC,
DECTA_LIST_ELEM,
__DECTA_LIST_MAX
};
#define DECTA_LIST_MAX (__DECTA_LIST_MAX - 1)
enum dect_slot_states {
DECT_SLOT_IDLE,
DECT_SLOT_SCANNING,
DECT_SLOT_RX,
DECT_SLOT_TX,
};
enum dect_slot_attrs {
DECTA_SLOT_UNSPEC,
DECTA_SLOT_NUM,
DECTA_SLOT_STATE,
DECTA_SLOT_CARRIER,
DECTA_SLOT_FREQUENCY,
DECTA_SLOT_RSSI,
DECTA_SLOT_RX_PACKETS,
DECTA_SLOT_RX_BYTES,
DECTA_SLOT_TX_PACKETS,
DECTA_SLOT_TX_BYTES,
__DECTA_SLOT_MAX
};
#define DECTA_SLOT_MAX (__DECTA_SLOT_MAX - 1)
enum dect_transceiver_stats_attrs {
DECTA_TRANSCEIVER_STATS_UNSPEC,
DECTA_TRANSCEIVER_STATS_EVENT_BUSY,
DECTA_TRANSCEIVER_STATS_EVENT_LATE,
__DECTA_TRANSCEIVER_STATS_MAX
};
#define DECTA_TRANSCEIVER_STATS_MAX (__DECTA_TRANSCEIVER_STATS_MAX - 1)
enum dect_transceiver_attrs {
DECTA_TRANSCEIVER_UNSPEC,
DECTA_TRANSCEIVER_NAME,
DECTA_TRANSCEIVER_TYPE,
DECTA_TRANSCEIVER_LINK,
DECTA_TRANSCEIVER_STATS,
DECTA_TRANSCEIVER_BAND,
DECTA_TRANSCEIVER_SLOTS,
__DECTA_TRANSCEIVER_MAX
};
#define DECTA_TRANSCEIVER_MAX (__DECTA_TRANSCEIVER_MAX - 1)
enum dect_cell_flags {
DECT_CELL_CCP = (1 << 0),
};
enum dect_cell_attrs {
DECTA_CELL_UNSPEC,
DECTA_CELL_NAME,
DECTA_CELL_FLAGS,
DECTA_CELL_TRANSCEIVERS,
DECTA_CELL_CLUSTER,
__DECTA_CELL_MAX
};
#define DECTA_CELL_MAX (__DECTA_CELL_MAX - 1)
enum dect_cluster_attrs {
DECTA_CLUSTER_UNSPEC,
DECTA_CLUSTER_NAME,
DECTA_CLUSTER_MODE,
DECTA_CLUSTER_PARI,
DECTA_CLUSTER_CELLS,
__DECTA_CLUSTER_MAX
};
#define DECTA_CLUSTER_MAX (__DECTA_CLUSTER_MAX - 1)
enum dect_cluster_modes {
DECT_MODE_FP,
DECT_MODE_PP,
DECT_MODE_MONITOR,
};
/**
* DECT ARI classes
*
* @DECT_ARC_A: Residential and private (PBX) single- and small multiple cell systems
* @DECT_ARC_B: Private (PABXs) multiple cell
* @DECT_ARC_C: Public single and multiple cell systems
* @DECT_ARC_D: Public DECT access to a GSM network
* @DECT_ARC_E: PP to PP direct communication (private)
*/
enum dect_ari_classes {
DECT_ARC_A,
DECT_ARC_B,
DECT_ARC_C,
DECT_ARC_D,
DECT_ARC_E,
};
enum dect_ari_attrs {
DECTA_ARI_UNSPEC,
DECTA_ARI_CLASS,
DECTA_ARI_FPN,
DECTA_ARI_FPS,
DECTA_ARI_EMC,
DECTA_ARI_EIC,
DECTA_ARI_POC,
DECTA_ARI_GOP,
DECTA_ARI_FIL,
__DECTA_ARI_MAX
};
#define DECTA_ARI_MAX (__DECTA_ARI_MAX - 1)
enum decta_sari_attrs {
DECTA_SARI_UNSPEC,
DECTA_SARI_ARI,
DECTA_SARI_BLACK,
DECTA_SARI_TARI,
__DECTA_SARI_MAX
};
#define DECTA_SARI_MAX (__DECTA_SARI_MAX - 1)
enum dect_fixed_part_capabilities {
DECT_FPC_EXTENDED_FP_INFO = 0x80000,
DECT_FPC_DOUBLE_DUPLEX_BEARER_CONNECTION= 0x40000,
DECT_FPC_RESERVED = 0x20000,
DECT_FPC_DOUBLE_SLOT = 0x10000,
DECT_FPC_HALF_SLOT = 0x8000,
DECT_FPC_FULL_SLOT = 0x4000,
DECT_FPC_FREQ_CONTROL = 0x2000,
DECT_FPC_PAGE_REPETITION = 0x1000,
DECT_FPC_CO_SETUP_ON_DUMMY = 0x800,
DECT_FPC_CL_UPLINK = 0x400,
DECT_FPC_CL_DOWNLINK = 0x200,
DECT_FPC_BASIC_A_FIELD_SETUP = 0x100,
DECT_FPC_ADV_A_FIELD_SETUP = 0x80,
DECT_FPC_B_FIELD_SETUP = 0x40,
DECT_FPC_CF_MESSAGES = 0x20,
DECT_FPC_IN_MIN_DELAY = 0x10,
DECT_FPC_IN_NORM_DELAY = 0x8,
DECT_FPC_IP_ERROR_DETECTION = 0x4,
DECT_FPC_IP_ERROR_CORRECTION = 0x2,
DECT_FPC_MULTIBEARER_CONNECTIONS = 0x1,
};
enum dect_higher_layer_capabilities {
DECT_HLC_ADPCM_G721_VOICE = 0x8000,
DECT_HLC_GAP_PAP_BASIC_SPEECH = 0x4000,
DECT_HLC_NON_VOICE_CIRCUIT_SWITCHED = 0x2000,
DECT_HLC_NON_VOICE_PACKET_SWITCHED = 0x1000,
DECT_HLC_STANDARD_AUTHENTICATION = 0x800,
DECT_HLC_STANDARD_CIPHERING = 0x400,
DECT_HLC_LOCATION_REGISTRATION = 0x200,
DECT_HLC_SIM_SERVICES = 0x100,
DECT_HLC_NON_STATIC_FIXED_PART = 0x80,
DECT_HLC_CISS_SERVICE = 0x40,
DECT_HLC_CLMS_SERVICE = 0x20,
DECT_HLC_COMS_SERVICE = 0x10,
DECT_HLC_ACCESS_RIGHT_REQUESTS = 0x8,
DECT_HLC_EXTERNAL_HANDOVER = 0x4,
DECT_HLC_CONNECTION_HANDOVER = 0x2,
DECT_HLC_RESERVED = 0x1,
};
enum dect_extended_higher_layer_capabilities {
DECT_EHLC_ISDN_DATA_SERVICE = 0x1,
DECT_EHLC_DATA_SERVICE_PROFILE_A_B = 0x2,
DECT_EHLC_DATA_SERVICE_PROFILE_C = 0x4,
DECT_EHLC_DATA_SERVICE_PROFILE_D = 0x8,
DECT_EHLC_DATA_SERVICE_PROFILE_E = 0x10,
DECT_EHLC_DATA_SERVICE_PROFILE_F = 0x20,
DECT_EHLC_ASYMETRIC_BEARERS = 0x40,
DECT_EHLC_TPUI_LOCATION_REGISTRATION = 0x100,
};
enum dect_efpc_attrs {
DECTA_EFPC_UNSPEC,
DECTA_EFPC_CRFP_HOPS,
DECTA_EFPC_CRFP_ENCRYPTION,
DECTA_EFPC_REP_HOPS,
DECTA_EFPC_REP_INTERLACING,
DECTA_EFPC_EHLC,
__DECTA_EFPC_MAX
};
#define DECTA_EFPC_MAX (__DECTA_EFPC_MAX - 1)
enum dect_mac_info_attrs {
DECTA_MAC_INFO_UNSPEC,
DECTA_MAC_INFO_PARI,
DECTA_MAC_INFO_RPN,
DECTA_MAC_INFO_RSSI,
DECTA_MAC_INFO_SARI_LIST,
DECTA_MAC_INFO_FPC,
DECTA_MAC_INFO_HLC,
DECTA_MAC_INFO_EFPC,
__DECTA_MAC_INFO_MAX
};
#define DECTA_MAC_INFO_MAX (__DECTA_MAC_INFO_MAX - 1)
enum dect_llme_ops {
DECT_LLME_REQUEST,
DECT_LLME_INDICATE,
DECT_LLME_RESPONSE,
DECT_LLME_CONFIRM,
};
enum dect_llme_msg_types {
DECT_LLME_SCAN,
DECT_LLME_MAC_INFO,
__DECT_LLME_MAX
};
#define DECT_LLME_MAX (__DECT_LLME_MAX - 1)
enum dect_llme_msg_attrs {
DECTA_LLME_UNSPEC,
DECTA_LLME_OP,
DECTA_LLME_TYPE,
DECTA_LLME_DATA,
__DECTA_LLME_MAX
};
#define DECTA_LLME_MAX (__DECTA_LLME_MAX - 1)
#endif /* _LINUX_DECT_NETLINK_H */

View File

@ -24,6 +24,7 @@
/* leave room for NETLINK_DM (DM Events) */
#define NETLINK_SCSITRANSPORT 18 /* SCSI Transports */
#define NETLINK_ECRYPTFS 19
#define NETLINK_DECT 20 /* DECT */
#define MAX_LINKS 32

View File

@ -799,4 +799,102 @@ struct nfnl_queue_msg {
uint32_t queue_msg_verdict;
};
struct nl_dect_transceiver_slot {
uint8_t dts_valid;
uint8_t dts_state;
uint8_t dts_carrier;
uint8_t dts_rssi;
uint32_t dts_frequency;
uint32_t dts_rx_bytes;
uint32_t dts_rx_packets;
uint32_t dts_tx_bytes;
uint32_t dts_tx_packets;
};
struct nl_dect_transceiver_stats {
uint32_t trx_event_busy;
uint32_t trx_event_late;
};
struct nl_dect_transceiver {
NLHDR_COMMON
char *trx_name;
char *trx_type;
uint8_t trx_index;
uint8_t trx_link;
uint8_t trx_band;
struct nl_dect_transceiver_stats trx_stats;
struct nl_dect_transceiver_slot trx_slots[24];
};
struct nl_dect_ari {
uint32_t ari_flags;
uint8_t ari_class;
uint32_t ari_fpn;
uint32_t ari_fps;
union {
uint16_t emc;
uint16_t eic;
uint16_t poc;
uint32_t gop;
uint16_t fil;
} ari_u;
};
struct nl_dect_cluster {
NLHDR_COMMON
int cl_index;
char *cl_name;
uint8_t cl_mode;
struct nl_dect_ari cl_pari;
uint8_t cells[8];
};
struct nl_dect_cell {
NLHDR_COMMON
int c_index;
char * c_name;
uint32_t c_flags;
char *c_transceiver[16];
int c_link;
};
struct nl_dect_llme_mac_info {
NLHDR_COMMON
struct nl_dect_ari mi_pari;
uint8_t mi_rpn;
uint8_t mi_rssi;
uint32_t mi_fpc;
uint16_t mi_hlc;
uint16_t mi_ehlc;
};
struct nl_dect_llme_mac_con {
NLHDR_COMMON
uint32_t mc_mcei;
struct nl_dect_ari mc_ari;
uint32_t mc_pmid;
uint8_t mc_type;
uint8_t mc_ecn;
uint8_t mc_service;
};
struct nl_dect_llme_msg {
NLHDR_COMMON
int lm_index;
uint8_t lm_type;
uint8_t lm_op;
union {
struct nl_dect_llme_mac_info lm_mi;
struct nl_dect_llme_mac_con lm_mc;
};
};
#endif

View File

@ -0,0 +1,35 @@
#ifndef NETLINK_DECT_ARI_H
#define NETLINK_DECT_ARI_H
#include <stdbool.h>
struct nl_dect_ari;
extern int nl_dect_parse_ari(struct nl_dect_ari *,
struct nlattr *);
extern int nl_dect_fill_ari(struct nl_msg *,
const struct nl_dect_ari *,
int);
extern void nl_dect_dump_ari(const struct nl_dect_ari *,
struct nl_dump_params *);
extern void nl_dect_ari_set_class(struct nl_dect_ari *,
enum dect_ari_classes);
extern enum dect_ari_classes nl_dect_ari_get_class(const struct nl_dect_ari *);
extern void nl_dect_ari_set_fpn(struct nl_dect_ari *, uint32_t);
extern uint32_t nl_dect_ari_get_fpn(const struct nl_dect_ari *);
extern void nl_dect_ari_set_fps(struct nl_dect_ari *, uint32_t);
extern uint32_t nl_dect_ari_get_fps(const struct nl_dect_ari *);
extern void nl_dect_ari_set_emc(struct nl_dect_ari *, uint16_t);
extern uint16_t nl_dect_ari_get_emc(const struct nl_dect_ari *);
extern void nl_dect_ari_set_eic(struct nl_dect_ari *, uint16_t);
extern uint16_t nl_dect_ari_get_eic(const struct nl_dect_ari *);
extern void nl_dect_ari_set_poc(struct nl_dect_ari *, uint16_t);
extern uint16_t nl_dect_ari_get_poc(const struct nl_dect_ari *);
extern void nl_dect_ari_set_gop(struct nl_dect_ari *, uint32_t);
extern uint32_t nl_dect_ari_get_gop(const struct nl_dect_ari *);
extern void nl_dect_ari_set_fil(struct nl_dect_ari *, uint16_t);
extern uint16_t nl_dect_ari_get_fil(const struct nl_dect_ari *);
#endif /* NETLINK_DECT_ARI_H */

View File

@ -0,0 +1,61 @@
#ifndef NETLINK_DECT_CELL_H
#define NETLINK_DECT_CELL_H
#include <stdbool.h>
struct nl_dect_cell;
struct nl_dect_ari;
extern struct nl_object_ops nl_dect_cell_obj_ops;
extern struct nl_dect_cell * nl_dect_cell_alloc(void);
extern void nl_dect_cell_get(struct nl_dect_cell *);
extern void nl_dect_cell_put(struct nl_dect_cell *);
extern void nl_dect_cell_set_index(struct nl_dect_cell *, int);
extern bool nl_dect_cell_test_index(const struct nl_dect_cell *);
extern int nl_dect_cell_get_index(const struct nl_dect_cell *);
extern void nl_dect_cell_set_name(struct nl_dect_cell *, const char *);
extern bool nl_dect_cell_test_name(const struct nl_dect_cell *);
extern const char * nl_dect_cell_get_name(const struct nl_dect_cell *);
extern void nl_dect_cell_set_flags(struct nl_dect_cell *, uint32_t);
extern bool nl_dect_cell_test_flags(const struct nl_dect_cell *);
extern uint32_t nl_dect_cell_get_flags(const struct nl_dect_cell *);
extern void nl_dect_cell_set_transceiver(struct nl_dect_cell *,
unsigned int,
const char *);
extern bool nl_dect_cell_test_transceiver(const struct nl_dect_cell *);
extern const char * nl_dect_cell_get_transceiver(const struct nl_dect_cell *,
unsigned int);
extern void nl_dect_cell_set_link(struct nl_dect_cell *, int);
extern bool nl_dect_cell_test_link(const struct nl_dect_cell *);
extern int nl_dect_cell_get_link(const struct nl_dect_cell *);
extern int nl_dect_cell_alloc_cache(struct nl_sock *,
struct nl_cache **);
extern int nl_dect_cell_build_msg(struct nl_msg *,
struct nl_dect_cell *);
extern int nl_dect_cell_build_add_request(struct nl_dect_cell *,
int, struct nl_msg **);
extern int nl_dect_cell_add(struct nl_sock *,
struct nl_dect_cell *, int);
extern int nl_dect_cell_build_del_request(struct nl_dect_cell *,
int, struct nl_msg **);
extern int nl_dect_cell_delete(struct nl_sock *,
struct nl_dect_cell *, int);
extern char * nl_dect_cell_i2name(struct nl_cache *, int, char *,
size_t);
extern int nl_dect_cell_name2i(struct nl_cache *, const char *);
extern char * nl_dect_cell_flags2str(uint32_t, char *, size_t);
extern uint32_t nl_dect_cell_str2flags(const char *);
#endif /* NETLINK_DECT_CELL_H */

View File

@ -0,0 +1,61 @@
#ifndef NETLINK_DECT_CLUSTER_H
#define NETLINK_DECT_CLUSTER_H
#include <stdbool.h>
struct nl_dect_cluster;
struct nl_dect_ari;
extern struct nl_object_ops nl_dect_cluster_obj_ops;
extern struct nl_dect_cluster * nl_dect_cluster_alloc(void);
extern void nl_dect_cluster_get(struct nl_dect_cluster *);
extern void nl_dect_cluster_put(struct nl_dect_cluster *);
extern unsigned int nl_dect_cluster_get_index(const struct nl_dect_cluster *);
extern void nl_dect_cluster_set_name(struct nl_dect_cluster *,
const char *);
extern bool nl_dect_cluster_test_name(const struct nl_dect_cluster *);
extern const char * nl_dect_cluster_get_name(const struct nl_dect_cluster *);
extern void nl_dect_cluster_set_mode(struct nl_dect_cluster *,
uint8_t mode);
extern bool nl_dect_cluster_test_mode(const struct nl_dect_cluster *);
extern uint8_t nl_dect_cluster_get_mode(const struct nl_dect_cluster *);
extern void nl_dect_cluster_set_pari(struct nl_dect_cluster *,
const struct nl_dect_ari *);
extern bool nl_dect_cluster_test_pari(const struct nl_dect_cluster *);
extern const struct nl_dect_ari *nl_dect_cluster_get_pari(const struct nl_dect_cluster *);
extern char * nl_dect_cluster_mode2str(enum dect_cluster_modes,
char *, size_t);
extern enum dect_cluster_modes nl_dect_cluster_str2mode(const char *);
extern int nl_dect_cluster_alloc_cache(struct nl_sock *,
struct nl_cache **);
extern int nl_dect_cluster_build_msg(struct nl_msg *,
struct nl_dect_cluster *);
extern int nl_dect_cluster_build_add_request(struct nl_dect_cluster *,
int, struct nl_msg **);
extern int nl_dect_cluster_add(struct nl_sock *,
struct nl_dect_cluster *, int);
extern int nl_dect_cluster_build_del_request(struct nl_dect_cluster *,
int, struct nl_msg **);
extern int nl_dect_cluster_delete(struct nl_sock *,
struct nl_dect_cluster *, int);
extern int nl_dect_cluster_build_query_request(struct nl_dect_cluster *,
int, struct nl_msg **);
extern int nl_dect_cluster_query(struct nl_sock *,
struct nl_dect_cluster *, int);
extern char * nl_dect_cluster_i2name(struct nl_cache *, int, char *,
size_t);
extern int nl_dect_cluster_name2i(struct nl_cache *, const char *);
#endif /* NETLINK_DECT_CLUSTER_H */

View File

@ -0,0 +1,6 @@
#ifndef _NETLINK_DECT_H
#define _NETLINK_DECT_H
extern double nl_dect_rssi_to_dbm(uint8_t);
#endif /* _NETLINK_DECT_H */

106
include/netlink/dect/llme.h Normal file
View File

@ -0,0 +1,106 @@
#ifndef NETLINK_DECT_LLME_H
#define NETLINK_DECT_LLME_H
#include <stdbool.h>
struct nl_dect_llme_msg;
struct nl_dect_ari;
extern struct nl_dect_llme_msg *nl_dect_llme_msg_alloc(void);
extern void nl_dect_llme_msg_get(struct nl_dect_llme_msg *);
extern void nl_dect_llme_msg_put(struct nl_dect_llme_msg *);
extern int nl_dect_llme_build_request(struct nl_dect_llme_msg *,
struct nl_msg **);
extern int nl_dect_llme_request(struct nl_sock *,
struct nl_dect_llme_msg *);
extern int nl_dect_llme_build_response(struct nl_dect_llme_msg *,
struct nl_msg **);
extern int nl_dect_llme_respond(struct nl_sock *, struct nl_dect_llme_msg *);
extern void nl_dect_llme_msg_set_index(struct nl_dect_llme_msg *, int);
extern void nl_dect_llme_msg_set_type(struct nl_dect_llme_msg *,
enum dect_llme_msg_types);
extern enum dect_llme_msg_types nl_dect_llme_msg_get_type(const struct nl_dect_llme_msg *);
extern void nl_dect_llme_msg_set_op(struct nl_dect_llme_msg *,
enum dect_llme_ops);
extern enum dect_llme_ops nl_dect_llme_msg_get_op(const struct nl_dect_llme_msg *);
extern char * nl_dect_llme_msgtype2str(enum dect_llme_msg_types,
char *, size_t);
extern enum dect_llme_msg_types nl_dect_llme_str2msgtype(const char *);
extern char * nl_dect_llme_op2str(enum dect_llme_ops,
char *, size_t);
extern enum dect_llme_ops nl_dect_llme_str2op(const char *);
extern void nl_dect_llme_mac_info_set_pari(struct nl_dect_llme_msg *lmsg,
const struct nl_dect_ari *);
extern const struct nl_dect_ari *nl_dect_llme_mac_info_get_pari(const struct nl_dect_llme_msg *);
extern void nl_dect_llme_mac_info_set_rpn(struct nl_dect_llme_msg *,
uint8_t);
extern uint8_t nl_dect_llme_mac_info_get_rpn(const struct nl_dect_llme_msg *);
extern void nl_dect_llme_mac_info_set_rssi(struct nl_dect_llme_msg *,
uint8_t);
extern uint8_t nl_dect_llme_mac_info_get_rssi(const struct nl_dect_llme_msg *);
extern void nl_dect_llme_mac_info_set_fpc(struct nl_dect_llme_msg *,
uint32_t);
extern uint32_t nl_dect_llme_mac_info_get_fpc(const struct nl_dect_llme_msg *);
extern void nl_dect_llme_mac_info_set_hlc(struct nl_dect_llme_msg *,
uint16_t);
extern uint16_t nl_dect_llme_mac_info_get_hlc(const struct nl_dect_llme_msg *);
extern void nl_dect_llme_mac_info_set_ehlc(struct nl_dect_llme_msg *,
uint16_t);
extern uint16_t nl_dect_llme_mac_info_get_ehlc(const struct nl_dect_llme_msg *);
extern char * nl_dect_llme_fpc2str(uint32_t, char *, size_t);
extern uint32_t nl_dect_llme_str2fpc(const char *);
extern char * nl_dect_llme_hlc2str(uint16_t, char *, size_t);
extern uint16_t nl_dect_llme_str2hlc(const char *);
extern char * nl_dect_llme_ehlc2str(uint16_t, char *, size_t);
extern uint16_t nl_dect_llme_str2ehlc(const char *);
#if 0
extern void nl_dect_llme_mac_con_set_mcei(struct nl_dect_llme_msg *,
uint32_t);
extern uint32_t nl_dect_llme_mac_con_get_mcei(const struct nl_dect_llme_msg *);
extern void nl_dect_llme_mac_con_set_ari(struct nl_dect_llme_msg *,
const struct nl_dect_ari *);
extern const struct nl_dect_ari * nl_dect_llme_mac_con_get_ari(const struct nl_dect_llme_msg *);
extern void nl_dect_llme_mac_con_set_pmid(struct nl_dect_llme_msg *,
uint32_t);
extern uint32_t nl_dect_llme_mac_con_get_pmid(const struct nl_dect_llme_msg *);
extern void nl_dect_llme_mac_con_set_type(struct nl_dect_llme_msg *,
enum nl_dect_mac_con_types);
extern enum nl_dect_mac_con_types nl_dect_llme_mac_con_get_type(const struct nl_dect_llme_msg *);
extern void nl_dect_llme_mac_con_set_ecn(struct nl_dect_llme_msg *,
uint8_t);
extern uint8_t nl_dect_llme_mac_con_get_ecn(const struct nl_dect_llme_msg *);
extern void nl_dect_llme_mac_con_set_service(struct nl_dect_llme_msg *,
enum nl_dect_mac_con_service_types);
extern enum nl_dect_mac_con_service_types nl_dect_llme_mac_con_get_service(const struct nl_dect_llme_msg *);
extern char * nl_dect_llme_contype2str(enum nl_dect_mac_con_types,
char *, size_t);
extern enum nl_dect_mac_con_types nl_dect_llme_str2contype(const char *);
extern char * nl_dect_llme_service2str(enum nl_dect_mac_con_service_types,
char *, size_t);
extern enum nl_dect_mac_con_service_types nl_dect_llme_str2service(const char *);
#endif
#endif /* NETLINK_DECT_LLME_H */

View File

@ -0,0 +1,47 @@
#ifndef NETLINK_DECT_TRANSCEIVER_H
#define NETLINK_DECT_TRANSCEIVER_H
#include <stdbool.h>
struct nl_dect_transceiver;
extern struct nl_object_ops nl_dect_transceiver_obj_ops;
extern struct nl_dect_transceiver *nl_dect_transceiver_alloc(void);
extern void nl_dect_transceiver_get(struct nl_dect_transceiver *);
extern void nl_dect_transceiver_put(struct nl_dect_transceiver *);
extern void nl_dect_transceiver_set_name(struct nl_dect_transceiver *,
const char *);
extern bool nl_dect_transceiver_test_name(const struct nl_dect_transceiver *);
extern const char * nl_dect_transceiver_get_name(const struct nl_dect_transceiver *);
extern void nl_dect_transceiver_set_type(struct nl_dect_transceiver *,
const char *);
extern bool nl_dect_transceiver_test_type(const struct nl_dect_transceiver *);
extern const char * nl_dect_transceiver_get_type(const struct nl_dect_transceiver *);
extern void nl_dect_transceiver_set_index(struct nl_dect_transceiver *,
int);
extern void nl_dect_transceiver_set_link(struct nl_dect_transceiver *,
uint8_t);
extern void nl_dect_transceiver_set_band(struct nl_dect_transceiver *,
uint8_t);
extern bool nl_dect_transceiver_test_band(const struct nl_dect_transceiver *);
extern uint8_t nl_dect_transceiver_get_band(const struct nl_dect_transceiver *);
extern int nl_dect_transceiver_build_msg(struct nl_msg *,
struct nl_dect_transceiver *);
extern int nl_dect_transceiver_build_change_request(struct nl_dect_transceiver *,
int, struct nl_msg **);
extern int nl_dect_transceiver_change(struct nl_sock *,
struct nl_dect_transceiver *, int flags);
extern char * nl_dect_slot_state2str(uint8_t, char *, size_t);
extern uint8_t nl_dect_slot_str2state(const char *);
extern int nl_dect_transceiver_alloc_cache(struct nl_sock *,
struct nl_cache **);
#endif /* NETLINK_DECT_TRANSCEIVER_H */

View File

@ -26,6 +26,7 @@
#include <linux/rtnetlink.h>
#include <linux/genetlink.h>
#include <linux/netfilter/nfnetlink.h>
#include <linux/dect_netlink.h>
#include <netlink/version.h>
#include <netlink/errno.h>
#include <netlink/types.h>

View File

@ -29,7 +29,10 @@ GENL_OBJ := $(GENL_C:%.c=%.o)
NF_C := $(wildcard netfilter/*.c)
NF_OBJ := $(NF_C:%.c=%.o)
ALL_C := $(CORE_C) $(ROUTE_C) $(GENL_C) $(NF_C)
DECT_C := $(wildcard dect/*.c)
DECT_OBJ := $(DECT_C:%.c=%.o)
ALL_C := $(CORE_C) $(ROUTE_C) $(GENL_C) $(NF_C) $(DECT_C)
ALL_OBJ := $(ALL_C:%.c=%.o)
DEPS := $(ALL_C:%.c=%.d)
@ -39,7 +42,8 @@ CORE_LIB := $(PACKAGE_NAME).so
ROUTE_LIB := $(PACKAGE_NAME)-route.so
GENL_LIB := $(PACKAGE_NAME)-genl.so
NF_LIB := $(PACKAGE_NAME)-nf.so
LIBS := $(CORE_LIB) $(ROUTE_LIB) $(GENL_LIB) $(NF_LIB)
DECT_LIB := $(PACKAGE_NAME)-dect.so
LIBS := $(CORE_LIB) $(ROUTE_LIB) $(GENL_LIB) $(NF_LIB) $(DECT_LIB)
LIBS_V := $(LIBS:%.so=%.so.$(PACKAGE_VERSION))
export
@ -82,6 +86,14 @@ $(NF_LIB): $(NF_LIB).$(PACKAGE_VERSION)
@echo " LN $@ -> $<"; \
$(RM) -f $@; $(LN) $< -s $@
$(DECT_LIB).$(PACKAGE_VERSION): $(DECT_OBJ)
@echo " LD $@"; \
$(CC) -shared -Wl,-soname=$@ -o $@ $^ $(LIBNL_LIB) -lnl
$(DECT_LIB): $(DECT_LIB).$(PACKAGE_VERSION)
@echo " LN $@ -> $<"; \
$(RM) -f $@; $(LN) $< -s $@
clean:
@echo " CLEAN lib"; \
$(RM) -f $(ALL_OBJ) $(LIBS) $(DEPS) *.so.*
@ -97,6 +109,7 @@ install:
$(LN) -sf $(ROUTE_LIB:%.so=%.so.$(PACKAGE_VERSION)) $(DESTDIR)$(libdir)/$(ROUTE_LIB)
$(LN) -sf $(GENL_LIB:%.so=%.so.$(PACKAGE_VERSION)) $(DESTDIR)$(libdir)/$(GENL_LIB)
$(LN) -sf $(NF_LIB:%.so=%.so.$(PACKAGE_VERSION)) $(DESTDIR)$(libdir)/$(NF_LIB)
$(LN) -sf $(DECT_LIB:%.so=%.so.$(PACKAGE_VERSION)) $(DESTDIR)$(libdir)/$(DECT_LIB)
$(DEPS): ../Makefile.opts

227
lib/dect/ari.c Normal file
View File

@ -0,0 +1,227 @@
#include <netlink-local.h>
#include <netlink/netlink.h>
#include <netlink/utils.h>
#include <netlink/dect/ari.h>
#include <linux/dect_netlink.h>
#define ARI_ATTR_CLASS 0x01
#define ARI_ATTR_FPN 0x02
#define ARI_ATTR_FPS 0x03
#define ARI_ATTR_EMC 0x04
#define ARI_ATTR_EIC 0x05
#define ARI_ATTR_POC 0x06
#define ARI_ATTR_GOP 0x07
#define ARI_ATTR_FIL 0x08
static struct nla_policy nl_dect_ari_policy[DECTA_ARI_MAX + 1] = {
[DECTA_ARI_CLASS] = { .type = NLA_U8 },
[DECTA_ARI_FPN] = { .type = NLA_U32 },
[DECTA_ARI_FPS] = { .type = NLA_U32 },
[DECTA_ARI_EMC] = { .type = NLA_U16 },
[DECTA_ARI_EIC] = { .type = NLA_U16 },
[DECTA_ARI_POC] = { .type = NLA_U16 },
[DECTA_ARI_GOP] = { .type = NLA_U32 },
[DECTA_ARI_FIL] = { .type = NLA_U32 },
};
int nl_dect_parse_ari(struct nl_dect_ari *ari, struct nlattr *nla)
{
struct nlattr *tb[DECTA_ARI_MAX + 1];
int err;
err = nla_parse_nested(tb, DECTA_ARI_MAX, nla, nl_dect_ari_policy);
if (err < 0)
return err;
if (tb[DECTA_ARI_CLASS] == NULL)
return -NLE_INVAL;
memset(ari, 0, sizeof(ari));
ari->ari_class = nla_get_u8(tb[DECTA_ARI_CLASS]);
if (tb[DECTA_ARI_FPN] != NULL)
ari->ari_fpn = nla_get_u32(tb[DECTA_ARI_FPN]);
switch (ari->ari_class) {
case DECT_ARC_A:
if (tb[DECTA_ARI_EMC] != NULL)
ari->ari_u.emc = nla_get_u16(tb[DECTA_ARI_EMC]);
break;
case DECT_ARC_B:
if (tb[DECTA_ARI_EIC] != NULL)
ari->ari_u.eic = nla_get_u16(tb[DECTA_ARI_EIC]);
if (tb[DECTA_ARI_FPS] != NULL)
ari->ari_fps = nla_get_u32(tb[DECTA_ARI_FPS]);
break;
case DECT_ARC_C:
if (tb[DECTA_ARI_POC] != NULL)
ari->ari_u.poc = nla_get_u16(tb[DECTA_ARI_POC]);
if (tb[DECTA_ARI_FPS] != NULL)
ari->ari_fps = nla_get_u32(tb[DECTA_ARI_FPS]);
break;
case DECT_ARC_D:
if (tb[DECTA_ARI_GOP] != NULL)
ari->ari_u.gop = nla_get_u32(tb[DECTA_ARI_GOP]);
break;
case DECT_ARC_E:
if (tb[DECTA_ARI_FIL] != NULL)
ari->ari_u.fil = nla_get_u16(tb[DECTA_ARI_FIL]);
break;
default:
return -NLE_INVAL;
}
return 0;
}
int nl_dect_fill_ari(struct nl_msg *msg, const struct nl_dect_ari *ari, int attr)
{
struct nlattr *nla;
nla = nla_nest_start(msg, attr);
if (nla == NULL)
goto nla_put_failure;
NLA_PUT_U8(msg, DECTA_ARI_CLASS, ari->ari_class);
NLA_PUT_U32(msg, DECTA_ARI_FPN, ari->ari_fpn);
switch (ari->ari_class) {
case DECT_ARC_A:
NLA_PUT_U16(msg, DECTA_ARI_EMC, ari->ari_u.emc);
break;
case DECT_ARC_B:
NLA_PUT_U16(msg, DECTA_ARI_EIC, ari->ari_u.eic);
NLA_PUT_U32(msg, DECTA_ARI_FPS, ari->ari_fps);
break;
case DECT_ARC_C:
NLA_PUT_U16(msg, DECTA_ARI_POC, ari->ari_u.poc);
NLA_PUT_U32(msg, DECTA_ARI_FPS, ari->ari_fps);
break;
case DECT_ARC_D:
NLA_PUT_U32(msg, DECTA_ARI_GOP, ari->ari_u.gop);
break;
case DECT_ARC_E:
NLA_PUT_U16(msg, DECTA_ARI_FIL, ari->ari_u.fil);
break;
}
nla_nest_end(msg, nla);
return 0;
nla_put_failure:
return -NLE_MSGSIZE;
}
void nl_dect_dump_ari(const struct nl_dect_ari *ari, struct nl_dump_params *p)
{
nl_dump(p, "class %c ", 'A' + ari->ari_class);
switch (ari->ari_class) {
case DECT_ARC_A:
nl_dump(p, "(residential) EMC: %.4x FPN: %.5x",
ari->ari_u.emc, ari->ari_fpn);
break;
case DECT_ARC_B:
nl_dump(p, "(private multiple cell) EIC: %.4x FPN: %.2x FPS: %x",
ari->ari_u.eic, ari->ari_fpn, ari->ari_fps);
break;
case DECT_ARC_C:
nl_dump(p, "(public) POC: %.4x FPN: %.2x FPS: %x",
ari->ari_u.poc, ari->ari_fpn, ari->ari_fps);
break;
case DECT_ARC_D:
nl_dump(p, "(public GSM) GOP: %.5x FPN: %.2x",
ari->ari_u.gop, ari->ari_fpn);
break;
case DECT_ARC_E:
nl_dump(p, "(PP to PP) FIL: %.4x FPN: %.3x",
ari->ari_u.fil, ari->ari_fpn);
}
}
void nl_dect_ari_set_class(struct nl_dect_ari *ari, enum dect_ari_classes class)
{
ari->ari_flags |= ARI_ATTR_CLASS;
ari->ari_class = class;
}
enum dect_ari_classes nl_dect_ari_get_class(const struct nl_dect_ari *ari)
{
return ari->ari_class;
}
void nl_dect_ari_set_fpn(struct nl_dect_ari *ari, uint32_t fpn)
{
ari->ari_flags |= ARI_ATTR_FPN;
ari->ari_fpn = fpn;
}
uint32_t nl_dect_ari_get_fpn(const struct nl_dect_ari *ari)
{
return ari->ari_fpn;
}
void nl_dect_ari_set_fps(struct nl_dect_ari *ari, uint32_t fps)
{
ari->ari_flags |= ARI_ATTR_FPS;
ari->ari_fps = fps;
}
uint32_t nl_dect_ari_get_fps(const struct nl_dect_ari *ari)
{
return ari->ari_fps;
}
void nl_dect_ari_set_emc(struct nl_dect_ari *ari, uint16_t emc)
{
ari->ari_flags |= ARI_ATTR_EMC;
ari->ari_u.emc = emc;
}
uint16_t nl_dect_ari_get_emc(const struct nl_dect_ari *ari)
{
return ari->ari_u.emc;
}
void nl_dect_ari_set_eic(struct nl_dect_ari *ari, uint16_t eic)
{
ari->ari_flags |= ARI_ATTR_EIC;
ari->ari_u.eic = eic;
}
uint16_t nl_dect_ari_get_eic(const struct nl_dect_ari *ari)
{
return ari->ari_u.eic;
}
void nl_dect_ari_set_poc(struct nl_dect_ari *ari, uint16_t poc)
{
ari->ari_flags |= ARI_ATTR_POC;
ari->ari_u.poc = poc;
}
uint16_t nl_dect_ari_get_poc(const struct nl_dect_ari *ari)
{
return ari->ari_u.poc;
}
void nl_dect_ari_set_gop(struct nl_dect_ari *ari, uint32_t gop)
{
ari->ari_flags |= ARI_ATTR_GOP;
ari->ari_u.gop = gop;
}
uint32_t nl_dect_ari_get_gop(const struct nl_dect_ari *ari)
{
return ari->ari_u.gop;
}
void nl_dect_ari_set_fil(struct nl_dect_ari *ari, uint16_t fil)
{
ari->ari_flags |= ARI_ATTR_FIL;
ari->ari_u.fil = fil;
}
uint16_t nl_dect_ari_get_fil(const struct nl_dect_ari *ari)
{
return ari->ari_u.fil;
}

267
lib/dect/cell.c Normal file
View File

@ -0,0 +1,267 @@
/*
* lib/nl_dect/cell.c DECT Cell objects
*
* 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 version 2.1
* of the License.
*
* Copyright (c) 2009 Patrick McHardy <kaber@trash.net>
*/
/**
* @ingroup nl_dect
* @defgroup nl_dect Transceivers
* @brief
* @{
*/
#include <netlink-local.h>
#include <netlink/netlink.h>
#include <netlink/utils.h>
#include <netlink/dect/cell.h>
#include <netlink/dect/ari.h>
#include <linux/dect_netlink.h>
/** @cond SKIP */
static struct nl_cache_ops nl_dect_cell_ops;
/** @endcond */
static struct nla_policy cell_policy[DECTA_CELL_MAX + 1] = {
[DECTA_CELL_NAME] = { .type = NLA_STRING, .maxlen = 16 },
[DECTA_CELL_FLAGS] = { .type = NLA_U32 },
[DECTA_CELL_TRANSCEIVERS] = { .type = NLA_NESTED },
[DECTA_CELL_CLUSTER] = { .type = NLA_U8 },
};
static int cell_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
struct nlmsghdr *n, struct nl_parser_param *pp)
{
struct dectmsg *dm = nlmsg_data(n);
struct nl_dect_cell *cell;
struct nlattr *tb[DECTA_CELL_MAX + 1], *nla;
int rem, err;
err = nlmsg_parse(n, sizeof(*dm), tb, DECTA_CELL_MAX, cell_policy);
if (err < 0)
return err;
cell = nl_dect_cell_alloc();
if (cell == NULL) {
err = -NLE_NOMEM;
goto errout;
}
cell->ce_msgtype = n->nlmsg_type;
cell->c_index = dm->dm_index;
if (tb[DECTA_CELL_NAME] != NULL)
nl_dect_cell_set_name(cell, nla_data(tb[DECTA_CELL_NAME]));
if (tb[DECTA_CELL_FLAGS] != NULL)
nl_dect_cell_set_flags(cell, nla_get_u32(tb[DECTA_CELL_FLAGS]));
if (tb[DECTA_CELL_TRANSCEIVERS] != NULL) {
unsigned int i = 0;
nla_for_each_nested(nla, tb[DECTA_CELL_TRANSCEIVERS], rem) {
char *id = nla_strdup(nla);
if (id == NULL) {
err = -NLE_NOMEM;
goto errout;
}
nl_dect_cell_set_transceiver(cell, i++, id);
}
}
if (tb[DECTA_CELL_CLUSTER] != NULL)
nl_dect_cell_set_link(cell, nla_get_u8(tb[DECTA_CELL_CLUSTER]));
err = pp->pp_cb((struct nl_object *)cell, pp);
errout:
nl_dect_cell_put(cell);
return err;
}
static int cell_request_update(struct nl_cache *c, struct nl_sock *h)
{
struct dectmsg dm;
memset(&dm, 0, sizeof(dm));
return nl_send_simple(h, DECT_GET_CELL, NLM_F_DUMP, &dm, sizeof(dm));
}
/**
* @name Cache Management
* @{
*/
int nl_dect_cell_alloc_cache(struct nl_sock *sk, struct nl_cache **result)
{
struct nl_cache *cache;
int err;
cache = nl_cache_alloc(&nl_dect_cell_ops);
if (cache == NULL)
return -NLE_NOMEM;
if (sk && (err = nl_cache_refill(sk, cache)) < 0) {
free(cache);
return err;
}
*result = cache;
return 0;
}
struct nl_dect_cell *nl_dect_cell_get_by_name(struct nl_cache *cache, const char *name)
{
struct nl_dect_cell *cell;
nl_list_for_each_entry(cell, &cache->c_items, ce_list) {
if (!strcmp(cell->c_name, name)) {
nl_object_get((struct nl_object *)cell);
return cell;
}
}
return NULL;
}
struct nl_dect_cell *nl_dect_cell_get_by_index(struct nl_cache *cache, int index)
{
struct nl_dect_cell *cell;
nl_list_for_each_entry(cell, &cache->c_items, ce_list) {
if (cell->c_index == index) {
nl_object_get((struct nl_object *)cell);
return cell;
}
}
return NULL;
}
/** @} */
/**
* @name Device creation
* @{
*/
static int build_cell_msg(struct nl_dect_cell *tmpl, int cmd, int flags,
struct nl_msg **result)
{
struct nl_msg *msg;
int err;
msg = nlmsg_alloc_simple(cmd, flags);
if (msg == NULL)
return -NLE_NOMEM;
err = nl_dect_cell_build_msg(msg, tmpl);
if (err < 0) {
nlmsg_free(msg);
return err;
}
*result = msg;
return 0;
}
int nl_dect_cell_build_add_request(struct nl_dect_cell *tmpl, int flags,
struct nl_msg **result)
{
return build_cell_msg(tmpl, DECT_NEW_CELL, NLM_F_CREATE | flags,
result);
}
int nl_dect_cell_add(struct nl_sock *sk, struct nl_dect_cell *cell, int flags)
{
struct nl_msg *msg;
int err;
err = nl_dect_cell_build_add_request(cell, flags, &msg);
if (err < 0)
return err;
err = nl_send_auto_complete(sk, msg);
nlmsg_free(msg);
if (err < 0)
return err;
return wait_for_ack(sk);
}
int nl_dect_cell_build_del_request(struct nl_dect_cell *tmpl, int flags,
struct nl_msg **result)
{
return build_cell_msg(tmpl, DECT_DEL_CELL, flags, result);
}
int nl_dect_cell_delete(struct nl_sock *sk, struct nl_dect_cell *tmpl, int flags)
{
struct nl_msg *msg;
int err;
err = nl_dect_cell_build_del_request(tmpl, flags, &msg);
if (err < 0)
return err;
err = nl_send_auto_complete(sk, msg);
nlmsg_free(msg);
if (err < 0)
return err;
return wait_for_ack(sk);
}
/** @} */
/**
* @name Name <-> Index Translations
* @{
*/
char *nl_dect_cell_i2name(struct nl_cache *cache, int index, char *buf, size_t len)
{
struct nl_dect_cell *cell = nl_dect_cell_get_by_index(cache, index);
if (cell != NULL) {
strncpy(buf, cell->c_name, len - 1);
buf[len - 1] = 0;
return buf;
}
return NULL;
}
int nl_dect_cell_name2i(struct nl_cache *cache, const char *name)
{
struct nl_dect_cell *cell = nl_dect_cell_get_by_name(cache, name);
if (cell != NULL)
return cell->c_index;
return 0;
}
/** @} */
static struct nl_cache_ops nl_dect_cell_ops = {
.co_name = "nl_dect/cell",
.co_hdrsize = 0,
.co_msgtypes = {
{ DECT_NEW_CELL, NL_ACT_NEW, "new" },
{ DECT_DEL_CELL, NL_ACT_NEW, "del" },
{ DECT_GET_CELL, NL_ACT_GET, "get" },
END_OF_MSGTYPES_LIST
},
.co_protocol = NETLINK_DECT,
.co_request_update = cell_request_update,
.co_msg_parser = cell_msg_parser,
.co_obj_ops = &nl_dect_cell_obj_ops,
};
static void __init cell_init(void)
{
nl_cache_mngt_register(&nl_dect_cell_ops);
}
static void __exit cell_exit(void)
{
nl_cache_mngt_unregister(&nl_dect_cell_ops);
}
/** @} */

232
lib/dect/cell_obj.c Normal file
View File

@ -0,0 +1,232 @@
/*
* lib/dect/cell.c DECT Cell objects
*
* 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 version 2.1
* of the License.
*
* Copyright (c) 2009 Patrick McHardy <kaber@trash.net>
*/
#include <netlink-local.h>
#include <netlink/netlink.h>
#include <netlink/cache.h>
#include <netlink/utils.h>
#include <netlink/data.h>
#include <netlink/dect/cluster.h>
#include <netlink/dect/cell.h>
#include <netlink/dect/ari.h>
#include <linux/dect_netlink.h>
/** @cond SKIP */
#define CELL_ATTR_INDEX 0x0001
#define CELL_ATTR_NAME 0x0002
#define CELL_ATTR_FLAGS 0x0004
#define CELL_ATTR_TRANSCEIVER 0x0008
#define CELL_ATTR_LINK 0x0010
/** @endcond */
static void cell_free_data(struct nl_object *obj)
{
struct nl_dect_cell *cell = nl_object_priv(obj);
unsigned int i;
if (cell == NULL)
return;
for (i = 0; i < 16; i++)
free(cell->c_transceiver[i]);
}
static void cell_dump(struct nl_object *obj, struct nl_dump_params *p)
{
struct nl_dect_cell *cell = nl_object_priv(obj);
struct nl_cache *cluster_cache;
unsigned int i;
char buf[64];
if (cell->ce_mask & CELL_ATTR_NAME)
nl_dump(p, "%u: DECT Cell %s", cell->c_index, cell->c_name);
if (cell->ce_mask & CELL_ATTR_LINK) {
cluster_cache = nl_cache_mngt_require("nl_dect/cluster");
if (cluster_cache != NULL) {
nl_dect_cluster_i2name(cluster_cache, cell->c_link, buf,
sizeof(buf));
nl_dump(p, "@%s", buf);
} else
nl_dump(p, "@%u", cell->c_link);
}
nl_dump(p, ":");
if (cell->ce_mask & CELL_ATTR_FLAGS) {
nl_dect_cell_flags2str(cell->c_flags, buf, sizeof(buf));
nl_dump(p, " <%s>", buf);
}
nl_dump(p, "\n");
if (cell->ce_mask & CELL_ATTR_TRANSCEIVER) {
for (i = 0; i < 16 && cell->c_transceiver[i] != NULL; i++)
nl_dump(p, "\tTransceiver: %s\n",
cell->c_transceiver[i]);
}
}
/**
* @name Allocation/Freeing
* @{
*/
struct nl_dect_cell *nl_dect_cell_alloc(void)
{
return (struct nl_dect_cell *)nl_object_alloc(&nl_dect_cell_obj_ops);
}
void nl_dect_cell_get(struct nl_dect_cell *cell)
{
nl_object_get((struct nl_object *)cell);
}
void nl_dect_cell_put(struct nl_dect_cell *cell)
{
nl_object_put((struct nl_object *)cell);
}
/** @} */
/**
* @name Attributes
* @{
*/
void nl_dect_cell_set_index(struct nl_dect_cell *cell, int index)
{
cell->c_index = index;
cell->ce_mask |= CELL_ATTR_INDEX;
}
bool nl_dect_cell_test_index(const struct nl_dect_cell *cell)
{
return !!(cell->ce_mask & CELL_ATTR_INDEX);
}
int nl_dect_cell_get_index(const struct nl_dect_cell *cell)
{
return cell->c_index;
}
void nl_dect_cell_set_name(struct nl_dect_cell *cell, const char *name)
{
cell->c_name = strdup(name);
cell->ce_mask |= CELL_ATTR_NAME;
}
bool nl_dect_cell_test_name(const struct nl_dect_cell *cell)
{
return !!(cell->ce_mask & CELL_ATTR_NAME);
}
const char *nl_dect_cell_get_name(const struct nl_dect_cell *cell)
{
return cell->c_name;
}
void nl_dect_cell_set_flags(struct nl_dect_cell *cell, uint32_t flags)
{
cell->c_flags = flags;
cell->ce_mask |= CELL_ATTR_FLAGS;
}
bool nl_dect_cell_test_flags(const struct nl_dect_cell *cell)
{
return !!(cell->ce_mask & CELL_ATTR_FLAGS);
}
uint32_t nl_dect_cell_get_flags(const struct nl_dect_cell *cell)
{
return cell->c_flags;
}
void nl_dect_cell_set_transceiver(struct nl_dect_cell *cell, unsigned int i,
const char *id)
{
cell->c_transceiver[i] = strdup(id);
cell->ce_mask |= CELL_ATTR_TRANSCEIVER;
}
bool nl_dect_cell_test_transceiver(const struct nl_dect_cell *cell)
{
return !!(cell->ce_mask & CELL_ATTR_TRANSCEIVER);
}
const char *nl_dect_cell_get_transceiver(const struct nl_dect_cell *cell,
unsigned int i)
{
return cell->c_transceiver[i];
}
void nl_dect_cell_set_link(struct nl_dect_cell *cell, int link)
{
cell->c_link = link;
cell->ce_mask |= CELL_ATTR_LINK;
}
bool nl_dect_cell_test_link(const struct nl_dect_cell *cell)
{
return !!(cell->ce_mask & CELL_ATTR_LINK);
}
int nl_dect_cell_get_link(const struct nl_dect_cell *cell)
{
return cell->c_link;
}
int nl_dect_cell_build_msg(struct nl_msg *msg, struct nl_dect_cell *cell)
{
struct dectmsg dm = {
.dm_index = cell->c_index,
};
if (nlmsg_append(msg, &dm, sizeof(dm), NLMSG_ALIGNTO) < 0)
goto nla_put_failure;
if (cell->ce_mask & CELL_ATTR_NAME)
NLA_PUT_STRING(msg, DECTA_CELL_NAME, cell->c_name);
if (cell->ce_mask & CELL_ATTR_FLAGS)
NLA_PUT_U32(msg, DECTA_CELL_FLAGS, cell->c_flags);
if (cell->ce_mask & CELL_ATTR_LINK)
NLA_PUT_U8(msg, DECTA_CELL_CLUSTER, cell->c_link);
return 0;
nla_put_failure:
return -NLE_MSGSIZE;
}
static struct trans_tbl cell_flags[] = {
__ADD(DECT_CELL_CCP, ccp)
};
char *nl_dect_cell_flags2str(uint32_t flags, char *buf, size_t len)
{
return __flags2str(flags, buf, len, cell_flags, ARRAY_SIZE(cell_flags));
}
uint32_t nl_dect_cell_str2flags(const char *str)
{
return __str2flags(str, cell_flags, ARRAY_SIZE(cell_flags));
}
/** @cond SKIP */
struct nl_object_ops nl_dect_cell_obj_ops = {
.oo_name = "nl_dect/cell",
.oo_size = sizeof(struct nl_dect_cell),
.oo_free_data = cell_free_data,
.oo_dump = {
[NL_DUMP_LINE] = cell_dump,
},
.oo_id_attrs = CELL_ATTR_NAME,
};
/** @endcond */
/** @} */

297
lib/dect/cluster.c Normal file
View File

@ -0,0 +1,297 @@
/*
* lib/dect/cluster.c DECT Cluster objects
*
* 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 version 2.1
* of the License.
*
* Copyright (c) 2009 Patrick McHardy <kaber@trash.net>
*/
/**
* @ingroup nl_dect
* @defgroup nl_dect Transceivers
* @brief
* @{
*/
#include <netlink-local.h>
#include <netlink/netlink.h>
#include <netlink/utils.h>
#include <netlink/dect/cluster.h>
#include <netlink/dect/ari.h>
#include <linux/dect_netlink.h>
/** @cond SKIP */
static struct nl_cache_ops nl_dect_cluster_ops;
/** @endcond */
static struct nla_policy cluster_policy[DECTA_CLUSTER_MAX + 1] = {
[DECTA_CLUSTER_NAME] = { .type = NLA_STRING, .maxlen = 16 },
[DECTA_CLUSTER_MODE] = { .type = NLA_U8 },
[DECTA_CLUSTER_PARI] = { .type = NLA_NESTED },
[DECTA_CLUSTER_CELLS] = { .type = NLA_NESTED },
};
static int cluster_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
struct nlmsghdr *n, struct nl_parser_param *pp)
{
struct dectmsg *dm = nlmsg_data(n);
struct nl_dect_cluster *cl;
struct nlattr *tb[DECTA_CLUSTER_MAX + 1];
int err;
err = nlmsg_parse(n, sizeof(*dm), tb, DECTA_CLUSTER_MAX, cluster_policy);
if (err < 0)
return err;
cl = nl_dect_cluster_alloc();
if (cl == NULL) {
err = -NLE_NOMEM;
goto errout;
}
cl->ce_msgtype = n->nlmsg_type;
cl->cl_index = dm->dm_index;
if (tb[DECTA_CLUSTER_NAME] != NULL) {
char *name = nla_strdup(tb[DECTA_CLUSTER_NAME]);
if (name == NULL) {
err = -NLE_NOMEM;
goto errout;
}
nl_dect_cluster_set_name(cl, name);
free(name);
}
if (tb[DECTA_CLUSTER_MODE] != NULL)
nl_dect_cluster_set_mode(cl, nla_get_u8(tb[DECTA_CLUSTER_MODE]));
if (tb[DECTA_CLUSTER_PARI] != NULL) {
struct nl_dect_ari pari;
err = nl_dect_parse_ari(&pari, tb[DECTA_CLUSTER_PARI]);
if (err < 0)
goto errout;
nl_dect_cluster_set_pari(cl, &pari);
}
err = pp->pp_cb((struct nl_object *)cl, pp);
errout:
nl_dect_cluster_put(cl);
return err;
}
static int cluster_request_update(struct nl_cache *c, struct nl_sock *h)
{
struct dectmsg dm;
memset(&dm, 0, sizeof(dm));
return nl_send_simple(h, DECT_GET_CLUSTER, NLM_F_DUMP, &dm, sizeof(dm));
}
/**
* @name Cache Management
* @{
*/
int nl_dect_cluster_alloc_cache(struct nl_sock *sk, struct nl_cache **result)
{
struct nl_cache *cache;
int err;
cache = nl_cache_alloc(&nl_dect_cluster_ops);
if (cache == NULL)
return -NLE_NOMEM;
if (sk && (err = nl_cache_refill(sk, cache)) < 0) {
free(cache);
return err;
}
*result = cache;
return 0;
}
struct nl_dect_cluster *nl_dect_cluster_get_by_name(struct nl_cache *cache,
const char *name)
{
struct nl_dect_cluster *cl;
nl_list_for_each_entry(cl, &cache->c_items, ce_list) {
if (!strcmp(cl->cl_name, name)) {
nl_object_get((struct nl_object *)cl);
return cl;
}
}
return NULL;
}
struct nl_dect_cluster *nl_dect_cluster_get_by_index(struct nl_cache *cache, int index)
{
struct nl_dect_cluster *cl;
nl_list_for_each_entry(cl, &cache->c_items, ce_list) {
if (cl->cl_index == index) {
nl_object_get((struct nl_object *)cl);
return cl;
}
}
return NULL;
}
/** @} */
/**
* @name Device creation
* @{
*/
static int build_cluster_msg(struct nl_dect_cluster *tmpl, int cmd, int flags,
struct nl_msg **result)
{
struct nl_msg *msg;
int err;
msg = nlmsg_alloc_simple(cmd, flags);
if (msg == NULL)
return -NLE_NOMEM;
err = nl_dect_cluster_build_msg(msg, tmpl);
if (err < 0) {
nlmsg_free(msg);
return err;
}
*result = msg;
return 0;
}
int nl_dect_cluster_build_add_request(struct nl_dect_cluster *tmpl, int flags,
struct nl_msg **result)
{
return build_cluster_msg(tmpl, DECT_NEW_CLUSTER, NLM_F_CREATE | flags,
result);
}
int nl_dect_cluster_add(struct nl_sock *sk, struct nl_dect_cluster *cl, int flags)
{
struct nl_msg *msg;
int err;
err = nl_dect_cluster_build_add_request(cl, flags, &msg);
if (err < 0)
return err;
err = nl_send_auto_complete(sk, msg);
nlmsg_free(msg);
if (err < 0)
return err;
return wait_for_ack(sk);
}
int nl_dect_cluster_build_del_request(struct nl_dect_cluster *tmpl, int flags,
struct nl_msg **result)
{
return build_cluster_msg(tmpl, DECT_DEL_CLUSTER, flags, result);
}
int nl_dect_cluster_delete(struct nl_sock *sk, struct nl_dect_cluster *tmpl, int flags)
{
struct nl_msg *msg;
int err;
err = nl_dect_cluster_build_del_request(tmpl, flags, &msg);
if (err < 0)
return err;
err = nl_send_auto_complete(sk, msg);
nlmsg_free(msg);
if (err < 0)
return err;
return wait_for_ack(sk);
}
int nl_dect_cluster_build_query_request(struct nl_dect_cluster *tmpl, int flags,
struct nl_msg **result)
{
return build_cluster_msg(tmpl, DECT_GET_CLUSTER, flags, result);
}
int nl_dect_cluster_query(struct nl_sock *sk, struct nl_dect_cluster *cl, int flags)
{
struct nl_msg *msg;
int err;
err = nl_dect_cluster_build_query_request(cl, flags, &msg);
if (err < 0)
return err;
err = nl_send_auto_complete(sk, msg);
nlmsg_free(msg);
if (err < 0)
return err;
return wait_for_ack(sk);
}
/** @} */
/**
* @name Name <-> Index Translations
* @{
*/
char *nl_dect_cluster_i2name(struct nl_cache *cache, int index,
char *buf, size_t len)
{
struct nl_dect_cluster *cl = nl_dect_cluster_get_by_index(cache, index);
if (cl != NULL) {
strncpy(buf, cl->cl_name, len - 1);
buf[len - 1] = 0;
return buf;
}
return NULL;
}
int nl_dect_cluster_name2i(struct nl_cache *cache, const char *name)
{
struct nl_dect_cluster *cl = nl_dect_cluster_get_by_name(cache, name);
if (cl != NULL)
return cl->cl_index;
return 0;
}
/** @} */
static struct nl_cache_ops nl_dect_cluster_ops = {
.co_name = "nl_dect/cluster",
.co_hdrsize = 0,
.co_msgtypes = {
{ DECT_NEW_CLUSTER, NL_ACT_NEW, "new" },
{ DECT_DEL_CLUSTER, NL_ACT_NEW, "del" },
{ DECT_GET_CLUSTER, NL_ACT_GET, "get" },
END_OF_MSGTYPES_LIST
},
.co_protocol = NETLINK_DECT,
.co_request_update = cluster_request_update,
.co_msg_parser = cluster_msg_parser,
.co_obj_ops = &nl_dect_cluster_obj_ops,
};
static void __init cluster_init(void)
{
nl_cache_mngt_register(&nl_dect_cluster_ops);
}
static void __exit cluster_exit(void)
{
nl_cache_mngt_unregister(&nl_dect_cluster_ops);
}
/** @} */

189
lib/dect/cluster_obj.c Normal file
View File

@ -0,0 +1,189 @@
/*
* lib/dect/cluster.c DECT Cluster objects
*
* 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 version 2.1
* of the License.
*
* Copyright (c) 2009 Patrick McHardy <kaber@trash.net>
*/
#include <netlink-local.h>
#include <netlink/netlink.h>
#include <netlink/cache.h>
#include <netlink/utils.h>
#include <netlink/data.h>
#include <netlink/dect/cluster.h>
#include <netlink/dect/ari.h>
#include <linux/dect_netlink.h>
/** @cond SKIP */
#define CL_ATTR_NAME 0x0001
#define CL_ATTR_MODE 0x0002
#define CL_ATTR_PARI 0x0004
/** @endcond */
static void cluster_free_data(struct nl_object *obj)
{
struct nl_dect_cluster *cl = nl_object_priv(obj);
if (cl == NULL)
return;
free(cl->cl_name);
}
static void cluster_dump(struct nl_object *obj, struct nl_dump_params *p)
{
struct nl_dect_cluster *cl = nl_object_priv(obj);
char buf[64];
if (cl->ce_mask & CL_ATTR_NAME)
nl_dump_line(p, "%d: DECT Cluster %s:\n",
cl->cl_index, cl->cl_name);
if (cl->ce_mask & CL_ATTR_MODE)
nl_dump_line(p, "\tMode: %s\n",
nl_dect_cluster_mode2str(cl->cl_mode,
buf, sizeof(buf)));
if (cl->ce_mask & CL_ATTR_PARI) {
nl_dump(p, "\tPARI: ");
nl_dect_dump_ari(&cl->cl_pari, p);
nl_dump(p, "\n");
}
}
/**
* @name Allocation/Freeing
* @{
*/
struct nl_dect_cluster *nl_dect_cluster_alloc(void)
{
return (struct nl_dect_cluster *)nl_object_alloc(&nl_dect_cluster_obj_ops);
}
void nl_dect_cluster_get(struct nl_dect_cluster *cl)
{
nl_object_get((struct nl_object *)cl);
}
void nl_dect_cluster_put(struct nl_dect_cluster *cl)
{
nl_object_put((struct nl_object *)cl);
}
/** @} */
/**
* @name Attributes
* @{
*/
unsigned int nl_dect_cluster_get_index(const struct nl_dect_cluster *cl)
{
return cl->cl_index;
}
void nl_dect_cluster_set_name(struct nl_dect_cluster *cl, const char *name)
{
cl->cl_name = strdup(name);
cl->ce_mask |= CL_ATTR_NAME;
}
bool nl_dect_cluster_test_name(const struct nl_dect_cluster *cl)
{
return !!(cl->ce_mask & CL_ATTR_NAME);
}
const char *nl_dect_cluster_get_name(const struct nl_dect_cluster *cl)
{
return cl->cl_name;
}
void nl_dect_cluster_set_mode(struct nl_dect_cluster *cl, uint8_t mode)
{
cl->cl_mode = mode;
cl->ce_mask |= CL_ATTR_MODE;
}
bool nl_dect_cluster_test_mode(const struct nl_dect_cluster *cl)
{
return !!(cl->ce_mask & CL_ATTR_MODE);
}
uint8_t nl_dect_cluster_get_mode(const struct nl_dect_cluster *cl)
{
return cl->cl_mode;
}
void nl_dect_cluster_set_pari(struct nl_dect_cluster *cl, const struct nl_dect_ari *pari)
{
memcpy(&cl->cl_pari, pari, sizeof(cl->cl_pari));
cl->ce_mask |= CL_ATTR_PARI;
}
bool nl_dect_cluster_test_pari(const struct nl_dect_cluster *cl)
{
return !!(cl->ce_mask & CL_ATTR_PARI);
}
const struct nl_dect_ari *nl_dect_cluster_get_pari(const struct nl_dect_cluster *cl)
{
return &cl->cl_pari;
}
int nl_dect_cluster_build_msg(struct nl_msg *msg, struct nl_dect_cluster *cl)
{
struct dectmsg dm = {
.dm_index = cl->cl_index,
};
if (nlmsg_append(msg, &dm, sizeof(dm), NLMSG_ALIGNTO) < 0)
goto nla_put_failure;
if (cl->ce_mask & CL_ATTR_NAME)
NLA_PUT_STRING(msg, DECTA_CLUSTER_NAME, cl->cl_name);
if (nl_dect_fill_ari(msg, &cl->cl_pari, DECTA_CLUSTER_PARI) < 0)
goto nla_put_failure;
if (cl->ce_mask & CL_ATTR_MODE)
NLA_PUT_U8(msg, DECTA_CLUSTER_MODE, cl->cl_mode);
return 0;
nla_put_failure:
return -NLE_MSGSIZE;
}
static struct trans_tbl cluster_modes[] = {
__ADD(DECT_MODE_FP, FP)
__ADD(DECT_MODE_PP, PP)
__ADD(DECT_MODE_MONITOR, monitor)
};
char *nl_dect_cluster_mode2str(enum dect_cluster_modes mode, char *buf, size_t len)
{
return __type2str(mode, buf, len, cluster_modes,
ARRAY_SIZE(cluster_modes));
}
enum dect_cluster_modes nl_dect_cluster_str2mode(const char *str)
{
return __str2type(str, cluster_modes, ARRAY_SIZE(cluster_modes));
}
/** @cond SKIP */
struct nl_object_ops nl_dect_cluster_obj_ops = {
.oo_name = "nl_dect/cluster",
.oo_size = sizeof(struct nl_dect_cluster),
.oo_free_data = cluster_free_data,
.oo_dump = {
[NL_DUMP_LINE] = cluster_dump,
},
.oo_id_attrs = CL_ATTR_NAME,
};
/** @endcond */
/** @} */

22
lib/dect/dect.c Normal file
View File

@ -0,0 +1,22 @@
/*
* lib/dect/dect.c DECT
*
* 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 version 2.1
* of the License.
*
* Copyright (c) 2009 Patrick McHardy <kaber@trash.net>
*/
#include <netlink-local.h>
#include <netlink/netlink.h>
#include <netlink/utils.h>
#include <netlink/dect/dect.h>
double nl_dect_rssi_to_dbm(uint8_t rssi)
{
if (rssi == 0)
return 0;
return -93 + (rssi * 60.0 / 255);
}

843
lib/dect/llme.c Normal file
View File

@ -0,0 +1,843 @@
/*
* lib/dect/llme.c DECT Lower Layer Management Entity Objects
*
* 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 version 2.1
* of the License.
*
* Copyright (c) 2009 Patrick McHardy <kaber@trash.net>
*/
/**
* @ingroup dect
* @defgroup dect LLME
* @brief
* @{
*/
#include <netlink-local.h>
#include <netlink/netlink.h>
#include <netlink/utils.h>
#include <netlink/dect/dect.h>
#include <netlink/dect/ari.h>
#include <netlink/dect/llme.h>
#include <linux/dect_netlink.h>
/** @cond SKIP */
static struct nl_object_ops llme_msg_obj_ops;
/** @endcond */
#define MAC_INFO_ATTR_PARI 0x010000
#define MAC_INFO_ATTR_RPN 0x020000
#define MAC_INFO_ATTR_RSSI 0x040000
#define MAC_INFO_ATTR_FPC 0x080000
#define MAC_INFO_ATTR_HLC 0x100000
#define MAC_INFO_ATTR_EHLC 0x200000
static inline struct nl_dect_llme_mac_info *mac_info(const struct nl_dect_llme_msg *lmsg)
{
return (void *)&lmsg->lm_mi;
}
void nl_dect_llme_mac_info_set_pari(struct nl_dect_llme_msg *lmsg,
const struct nl_dect_ari *pari)
{
struct nl_dect_llme_mac_info *mi = mac_info(lmsg);
memcpy(&mi->mi_pari, pari, sizeof(mi->mi_pari));
lmsg->ce_mask |= MAC_INFO_ATTR_PARI;
}
const struct nl_dect_ari *nl_dect_llme_mac_info_get_pari(const struct nl_dect_llme_msg *lmsg)
{
return &mac_info(lmsg)->mi_pari;
}
void nl_dect_llme_mac_info_set_rpn(struct nl_dect_llme_msg *lmsg, uint8_t rpn)
{
mac_info(lmsg)->mi_rpn = rpn;
lmsg->ce_mask |= MAC_INFO_ATTR_RPN;
}
uint8_t nl_dect_llme_mac_info_get_rpn(const struct nl_dect_llme_msg *lmsg)
{
return mac_info(lmsg)->mi_rpn;
}
void nl_dect_llme_mac_info_set_rssi(struct nl_dect_llme_msg *lmsg, uint8_t rssi)
{
mac_info(lmsg)->mi_rssi = rssi;
lmsg->ce_mask |= MAC_INFO_ATTR_RSSI;
}
uint8_t nl_dect_llme_mac_info_get_rssi(const struct nl_dect_llme_msg *lmsg)
{
return mac_info(lmsg)->mi_rssi;
}
void nl_dect_llme_mac_info_set_fpc(struct nl_dect_llme_msg *lmsg, uint32_t fpc)
{
mac_info(lmsg)->mi_fpc = fpc;
lmsg->ce_mask |= MAC_INFO_ATTR_FPC;
}
uint32_t nl_dect_llme_mac_info_get_fpc(const struct nl_dect_llme_msg *lmsg)
{
return mac_info(lmsg)->mi_fpc;
}
void nl_dect_llme_mac_info_set_hlc(struct nl_dect_llme_msg *lmsg, uint16_t hlc)
{
mac_info(lmsg)->mi_hlc = hlc;
lmsg->ce_mask |= MAC_INFO_ATTR_HLC;
}
uint16_t nl_dect_llme_mac_info_get_hlc(const struct nl_dect_llme_msg *lmsg)
{
return mac_info(lmsg)->mi_hlc;
}
void nl_dect_llme_mac_info_set_ehlc(struct nl_dect_llme_msg *lmsg, uint16_t ehlc)
{
mac_info(lmsg)->mi_ehlc = ehlc;
lmsg->ce_mask |= MAC_INFO_ATTR_EHLC;
}
uint16_t nl_dect_llme_mac_info_get_ehlc(const struct nl_dect_llme_msg *lmsg)
{
return mac_info(lmsg)->mi_ehlc;
}
static struct trans_tbl fixed_part_capabilities[] = {
__ADD(DECT_FPC_EXTENDED_FP_INFO, extended_fp_info)
__ADD(DECT_FPC_DOUBLE_DUPLEX_BEARER_CONNECTION, double_duplex_bearer_connection)
__ADD(DECT_FPC_RESERVED, reserved)
__ADD(DECT_FPC_DOUBLE_SLOT, double_slot)
__ADD(DECT_FPC_HALF_SLOT, half_slot)
__ADD(DECT_FPC_FULL_SLOT, full_slot)
__ADD(DECT_FPC_FREQ_CONTROL, frequency_control)
__ADD(DECT_FPC_PAGE_REPETITION, page_repetition)
__ADD(DECT_FPC_CO_SETUP_ON_DUMMY, co_setup_on_dummy)
__ADD(DECT_FPC_CL_UPLINK, cl_uplink)
__ADD(DECT_FPC_CL_DOWNLINK, cl_downlink)
__ADD(DECT_FPC_BASIC_A_FIELD_SETUP, basic_a_field_setup)
__ADD(DECT_FPC_ADV_A_FIELD_SETUP, advanced_a_field_setup)
__ADD(DECT_FPC_B_FIELD_SETUP, b_field_setup)
__ADD(DECT_FPC_CF_MESSAGES, cf_messages)
__ADD(DECT_FPC_IN_MIN_DELAY, in_min_delay)
__ADD(DECT_FPC_IN_NORM_DELAY, in_normal_delay)
__ADD(DECT_FPC_IP_ERROR_DETECTION, ip_error_detection)
__ADD(DECT_FPC_IP_ERROR_CORRECTION, ip_error_correction)
__ADD(DECT_FPC_MULTIBEARER_CONNECTIONS, multibearer_connections)
};
char *nl_dect_llme_fpc2str(uint32_t fpc, char *buf, size_t len)
{
return __flags2str(fpc, buf, len, fixed_part_capabilities,
ARRAY_SIZE(fixed_part_capabilities));
}
uint32_t nl_dect_llme_str2fpc(const char *str)
{
return __str2flags(str, fixed_part_capabilities,
ARRAY_SIZE(fixed_part_capabilities));
}
static struct trans_tbl higher_layer_capabilities[] = {
__ADD(DECT_HLC_ADPCM_G721_VOICE, adpcm_g721_voice)
__ADD(DECT_HLC_GAP_PAP_BASIC_SPEECH, gap_pap_basic_speech)
__ADD(DECT_HLC_NON_VOICE_CIRCUIT_SWITCHED, non_voice_circuit_switched_service)
__ADD(DECT_HLC_NON_VOICE_PACKET_SWITCHED, non_voice_packet_switched_service)
__ADD(DECT_HLC_STANDARD_AUTHENTICATION, standard_authentication)
__ADD(DECT_HLC_STANDARD_CIPHERING, standard_ciphering)
__ADD(DECT_HLC_LOCATION_REGISTRATION, location_registration)
__ADD(DECT_HLC_SIM_SERVICES, sim_services)
__ADD(DECT_HLC_NON_STATIC_FIXED_PART, non_static_fixed_part)
__ADD(DECT_HLC_CISS_SERVICE, ciss_service)
__ADD(DECT_HLC_CLMS_SERVICE, clms_service)
__ADD(DECT_HLC_COMS_SERVICE, coms_service)
__ADD(DECT_HLC_ACCESS_RIGHT_REQUESTS, access_right_requests)
__ADD(DECT_HLC_EXTERNAL_HANDOVER, external_handover)
__ADD(DECT_HLC_CONNECTION_HANDOVER, connection_handover)
__ADD(DECT_HLC_RESERVED, reserved)
};
char *nl_dect_llme_hlc2str(uint16_t hlc, char *buf, size_t len)
{
return __flags2str(hlc, buf, len, higher_layer_capabilities,
ARRAY_SIZE(higher_layer_capabilities));
}
uint16_t nl_dect_llme_str2hlc(const char *str)
{
return __str2flags(str, higher_layer_capabilities,
ARRAY_SIZE(higher_layer_capabilities));
}
static struct trans_tbl extended_higher_layer_capabilities[] = {
__ADD(DECT_EHLC_ISDN_DATA_SERVICE, isdn_data_service)
__ADD(DECT_EHLC_DATA_SERVICE_PROFILE_A_B, data_service_profile_a_b)
__ADD(DECT_EHLC_DATA_SERVICE_PROFILE_C, data_service_profile_c)
__ADD(DECT_EHLC_DATA_SERVICE_PROFILE_D, data_service_profile_d)
__ADD(DECT_EHLC_DATA_SERVICE_PROFILE_E, data_service_profile_e)
__ADD(DECT_EHLC_DATA_SERVICE_PROFILE_F, data_service_profile_f)
__ADD(DECT_EHLC_ASYMETRIC_BEARERS, asymetric_bearers)
__ADD(DECT_EHLC_TPUI_LOCATION_REGISTRATION, tpui_location_registration)
};
char *nl_dect_llme_ehlc2str(uint16_t ehlc, char *buf, size_t len)
{
return __flags2str(ehlc, buf, len, extended_higher_layer_capabilities,
ARRAY_SIZE(extended_higher_layer_capabilities));
}
uint16_t nl_dect_llme_str2ehlc(const char *str)
{
return __str2flags(str, extended_higher_layer_capabilities,
ARRAY_SIZE(extended_higher_layer_capabilities));
}
static void nl_dect_llme_mac_info_dump(const struct nl_dect_llme_msg *lmsg,
struct nl_dump_params *p)
{
const struct nl_dect_llme_mac_info *mi = mac_info(lmsg);
char buf[256];
if (lmsg->ce_mask & MAC_INFO_ATTR_PARI) {
nl_dump(p, "\tARI: ");
nl_dect_dump_ari(&mi->mi_pari, p);
}
if (lmsg->ce_mask & MAC_INFO_ATTR_RPN)
nl_dump(p, " RPN: %x", mi->mi_rpn);
if (lmsg->ce_mask & MAC_INFO_ATTR_RSSI)
nl_dump(p, " signal level: %.2fdBm", nl_dect_rssi_to_dbm(mi->mi_rssi));
if (lmsg->ce_mask & MAC_INFO_ATTR_FPC) {
nl_dect_llme_fpc2str(mi->mi_fpc, buf, sizeof(buf));
nl_dump(p, "\n\tCapabilities: %s", buf);
}
if (lmsg->ce_mask & MAC_INFO_ATTR_HLC) {
nl_dect_llme_hlc2str(mi->mi_hlc, buf, sizeof(buf));
nl_dump(p, "\n\tHigher layer capabilities: %s", buf);
}
if (lmsg->ce_mask & MAC_INFO_ATTR_EHLC) {
nl_dect_llme_ehlc2str(mi->mi_ehlc, buf, sizeof(buf));
nl_dump(p, "\n\tExtended higher layer capabilities: %s", buf);
}
nl_dump(p, "\n");
}
static struct nla_policy nl_dect_efpc_policy[DECTA_EFPC_MAX + 1] = {
[DECTA_EFPC_CRFP_HOPS] = { .type = NLA_U8 },
[DECTA_EFPC_CRFP_ENCRYPTION] = { },
[DECTA_EFPC_REP_HOPS] = { .type = NLA_U8 },
[DECTA_EFPC_REP_INTERLACING] = { },
[DECTA_EFPC_EHLC] = { .type = NLA_U16 },
};
static struct nla_policy nl_dect_mac_info_policy[DECTA_MAC_INFO_MAX + 1] = {
[DECTA_MAC_INFO_PARI] = { .type = NLA_NESTED },
[DECTA_MAC_INFO_RPN] = { .type = NLA_U8 },
[DECTA_MAC_INFO_RSSI] = { .type = NLA_U8 },
[DECTA_MAC_INFO_SARI_LIST] = { .type = NLA_NESTED },
[DECTA_MAC_INFO_FPC] = { .type = NLA_U32 },
[DECTA_MAC_INFO_HLC] = { .type = NLA_U16 },
[DECTA_MAC_INFO_EFPC] = { .type = NLA_NESTED },
};
static int nl_dect_llme_mac_info_parse(struct nl_dect_llme_msg *lmsg,
struct nlattr *tb[])
{
struct nl_dect_ari pari;
int err;
if (tb[DECTA_MAC_INFO_PARI] != NULL) {
err = nl_dect_parse_ari(&pari, tb[DECTA_MAC_INFO_PARI]);
if (err < 0)
return err;
nl_dect_llme_mac_info_set_pari(lmsg, &pari);
}
if (tb[DECTA_MAC_INFO_RPN] != NULL)
nl_dect_llme_mac_info_set_rpn(lmsg, nla_get_u8(tb[DECTA_MAC_INFO_RPN]));
if (tb[DECTA_MAC_INFO_RSSI] != NULL)
nl_dect_llme_mac_info_set_rssi(lmsg, nla_get_u8(tb[DECTA_MAC_INFO_RSSI]));
if (tb[DECTA_MAC_INFO_FPC] != NULL)
nl_dect_llme_mac_info_set_fpc(lmsg, nla_get_u32(tb[DECTA_MAC_INFO_FPC]));
if (tb[DECTA_MAC_INFO_HLC] != NULL)
nl_dect_llme_mac_info_set_hlc(lmsg, nla_get_u16(tb[DECTA_MAC_INFO_HLC]));
if (tb[DECTA_MAC_INFO_EFPC] != NULL) {
struct nlattr *nla[DECTA_EFPC_MAX + 1];
err = nla_parse_nested(nla, DECTA_EFPC_MAX, tb[DECTA_MAC_INFO_EFPC],
nl_dect_efpc_policy);
if (err < 0)
return err;
nl_dect_llme_mac_info_set_ehlc(lmsg, nla_get_u16(nla[DECTA_EFPC_EHLC]));
}
return 0;
}
static int nl_dect_llme_mac_info_build(struct nl_msg *msg,
struct nl_dect_llme_msg *lmsg)
{
struct nl_dect_llme_mac_info *mi = mac_info(lmsg);
int err;
if (lmsg->ce_mask & MAC_INFO_ATTR_PARI) {
err = nl_dect_fill_ari(msg, &mi->mi_pari, DECTA_MAC_INFO_PARI);
if (err < 0)
return err;
}
if (lmsg->ce_mask & MAC_INFO_ATTR_RPN)
NLA_PUT_U8(msg, DECTA_MAC_INFO_RPN, mi->mi_rpn);
if (lmsg->ce_mask & MAC_INFO_ATTR_FPC)
NLA_PUT_U32(msg, DECTA_MAC_INFO_FPC, mi->mi_fpc);
#ifdef FIXME
if (lmsg->ce_mask & MAC_INFO_ATTR_EHLC)
NLA_PUT_U16(msg, DECTA_MAC_INFO_EHLC, mi->mi_ehlc);
#endif
return 0;
nla_put_failure:
return -NLE_MSGSIZE;
}
#if 0
#define MAC_CON_ATTR_MCEI 0x010000
#define MAC_CON_ATTR_ARI 0x020000
#define MAC_CON_ATTR_PMID 0x040000
#define MAC_CON_ATTR_TYPE 0x080000
#define MAC_CON_ATTR_ECN 0x100000
#define MAC_CON_ATTR_SERVICE 0x200000
static inline struct nl_dect_llme_mac_con *mac_con(const struct nl_dect_llme_msg *lmsg)
{
return (void *)&lmsg->lm_mc;
}
void nl_dect_llme_mac_con_set_mcei(struct nl_dect_llme_msg *lmsg, uint32_t mcei)
{
mac_con(lmsg)->mc_mcei = mcei;
lmsg->ce_mask |= MAC_CON_ATTR_MCEI;
}
uint32_t nl_dect_llme_mac_con_get_mcei(const struct nl_dect_llme_msg *lmsg)
{
return mac_con(lmsg)->mc_mcei;
}
void nl_dect_llme_mac_con_set_ari(struct nl_dect_llme_msg *lmsg, const struct nl_dect_ari *ari)
{
struct nl_dect_llme_mac_con *mc = mac_con(lmsg);
memcpy(&mc->mc_ari, ari, sizeof(mc->mc_ari));
lmsg->ce_mask |= MAC_CON_ATTR_ARI;
}
const struct nl_dect_ari *nl_dect_llme_mac_con_get_ari(const struct nl_dect_llme_msg *lmsg)
{
return &mac_con(lmsg)->mc_ari;
}
void nl_dect_llme_mac_con_set_pmid(struct nl_dect_llme_msg *lmsg, uint32_t pmid)
{
mac_con(lmsg)->mc_pmid = pmid;
lmsg->ce_mask |= MAC_CON_ATTR_PMID;
}
uint32_t nl_dect_llme_mac_con_get_pmid(const struct nl_dect_llme_msg *lmsg)
{
return mac_con(lmsg)->mc_pmid;
}
void nl_dect_llme_mac_con_set_type(struct nl_dect_llme_msg *lmsg,
enum nl_dect_mac_con_types type)
{
mac_con(lmsg)->mc_type = type;
lmsg->ce_mask |= MAC_CON_ATTR_TYPE;
}
enum nl_dect_mac_con_types nl_dect_llme_mac_con_get_type(const struct nl_dect_llme_msg *lmsg)
{
return mac_con(lmsg)->mc_type;
}
void nl_dect_llme_mac_con_set_ecn(struct nl_dect_llme_msg *lmsg, uint8_t ecn)
{
mac_con(lmsg)->mc_ecn = ecn;
lmsg->ce_mask |= MAC_CON_ATTR_ECN;
}
uint8_t nl_dect_llme_mac_con_get_ecn(const struct nl_dect_llme_msg *lmsg)
{
return mac_con(lmsg)->mc_ecn;
}
void nl_dect_llme_mac_con_set_service(struct nl_dect_llme_msg *lmsg,
enum nl_dect_mac_con_service_types service)
{
mac_con(lmsg)->mc_service = service;
lmsg->ce_mask |= MAC_CON_ATTR_SERVICE;
}
enum nl_dect_mac_con_service_types
nl_dect_llme_mac_con_get_service(const struct nl_dect_llme_msg *lmsg)
{
return mac_con(lmsg)->mc_service;
}
static struct trans_tbl con_types[] = {
__ADD(DECT_MAC_CON_BASIC, basic)
__ADD(DECT_MAC_CON_ADVANCED, advanced)
};
char *nl_dect_llme_contype2str(enum nl_dect_mac_con_types type, char *buf, size_t len)
{
return __type2str(type, buf, len, con_types, ARRAY_SIZE(con_types));
}
enum nl_dect_mac_con_types nl_dect_llme_str2contype(const char *str)
{
return __str2type(str, con_types, ARRAY_SIZE(con_types));
}
static struct trans_tbl service_types[] = {
__ADD(DECT_MAC_CON_IN_MIN_DELAY, I_N_minimal_delay)
__ADD(DECT_MAC_CON_IN_NORM_DELAY, I_N_normal_delay)
__ADD(DECT_MAC_CON_IP_ERROR_DETECTION, I_P_error_detection)
__ADD(DECT_MAC_CON_IP_ERROR_CORRECTION, I_P_error_correction)
__ADD(DECT_MAC_CON_UNKNOWN, unknown)
__ADD(DECT_MAC_CON_C_ONLY, C_only)
};
char *nl_dect_llme_service2str(enum nl_dect_mac_con_service_types service,
char *buf, size_t len)
{
return __type2str(service, buf, len, service_types,
ARRAY_SIZE(service_types));
}
enum nl_dect_mac_con_service_types nl_dect_llme_str2service(const char *str)
{
return __str2type(str, service_types, ARRAY_SIZE(service_types));
}
static void nl_dect_llme_mac_con_dump(const struct nl_dect_llme_msg *lmsg,
struct nl_dump_params *p)
{
const struct nl_dect_llme_mac_con *mc = mac_con(lmsg);
char buf[256];
nl_dump(p, "\t");
if (lmsg->ce_mask & MAC_CON_ATTR_MCEI)
nl_dump(p, "MCEI %x: ", mc->mc_mcei);
if (lmsg->ce_mask & MAC_CON_ATTR_PMID)
nl_dump(p, "PMID: %x ", mc->mc_pmid);
if (lmsg->ce_mask & MAC_CON_ATTR_ARI) {
nl_dump(p, "=> ");
nl_dect_dump_ari(&mc->mc_ari, p);
nl_dump(p, " ");
}
if (lmsg->ce_mask & MAC_CON_ATTR_ECN)
nl_dump(p, "ECN: %x ", mc->mc_ecn);
nl_dump(p, "\n");
if (lmsg->ce_mask & MAC_CON_ATTR_TYPE) {
nl_dect_llme_contype2str(mc->mc_type, buf, sizeof(buf));
nl_dump(p, "\tType: %s\n", buf);
}
if (lmsg->ce_mask & MAC_CON_ATTR_SERVICE) {
nl_dect_llme_service2str(mc->mc_service, buf, sizeof(buf));
nl_dump(p, "\tService: %s\n", buf);
}
nl_dump(p, "\n");
}
static struct nla_policy nl_dect_mac_con_policy[DECTA_MAC_CON_MAX + 1] = {
[DECTA_MAC_CON_MCEI] = { .type = NLA_U32 },
[DECTA_MAC_CON_ARI] = { .type = NLA_NESTED },
[DECTA_MAC_CON_PMID] = { .type = NLA_U32 },
[DECTA_MAC_CON_TYPE] = { .type = NLA_U8 },
[DECTA_MAC_CON_ECN] = { .type = NLA_U8 },
[DECTA_MAC_CON_SERVICE] = { .type = NLA_U8 },
};
static int nl_dect_llme_mac_con_parse(struct nl_dect_llme_msg *lmsg,
struct nlattr *tb[])
{
struct nl_dect_ari ari;
int err;
if (tb[DECTA_MAC_CON_MCEI] != NULL)
nl_dect_llme_mac_con_set_mcei(lmsg, nla_get_u32(tb[DECTA_MAC_CON_MCEI]));
if (tb[DECTA_MAC_CON_ARI] != NULL) {
err = nl_dect_parse_ari(&ari, tb[DECTA_MAC_CON_ARI]);
if (err < 0)
return err;
nl_dect_llme_mac_con_set_ari(lmsg, &ari);
}
if (tb[DECTA_MAC_CON_PMID] != NULL)
nl_dect_llme_mac_con_set_pmid(lmsg, nla_get_u32(tb[DECTA_MAC_CON_PMID]));
if (tb[DECTA_MAC_CON_TYPE] != NULL)
nl_dect_llme_mac_con_set_type(lmsg, nla_get_u8(tb[DECTA_MAC_CON_TYPE]));
if (tb[DECTA_MAC_CON_ECN] != NULL)
nl_dect_llme_mac_con_set_ecn(lmsg, nla_get_u8(tb[DECTA_MAC_CON_ECN]));
if (tb[DECTA_MAC_CON_SERVICE] != NULL)
nl_dect_llme_mac_con_set_service(lmsg, nla_get_u8(tb[DECTA_MAC_CON_SERVICE]));
return 0;
}
static int nl_dect_llme_mac_con_build(struct nl_msg *msg,
struct nl_dect_llme_msg *lmsg)
{
struct nl_dect_llme_mac_con *mc = mac_con(lmsg);
int err;
if (lmsg->ce_mask & MAC_CON_ATTR_MCEI)
NLA_PUT_U32(msg, DECTA_MAC_CON_MCEI, mc->mc_mcei);
if (lmsg->ce_mask & MAC_CON_ATTR_ARI) {
err = nl_dect_fill_ari(msg, &mc->mc_ari, DECTA_MAC_CON_ARI);
if (err < 0)
goto nla_put_failure;
}
if (lmsg->ce_mask & MAC_CON_ATTR_PMID)
NLA_PUT_U32(msg, DECTA_MAC_CON_PMID, mc->mc_pmid);
if (lmsg->ce_mask & MAC_CON_ATTR_TYPE)
NLA_PUT_U8(msg, DECTA_MAC_CON_TYPE, mc->mc_type);
if (lmsg->ce_mask & MAC_CON_ATTR_ECN)
NLA_PUT_U8(msg, DECTA_MAC_CON_ECN, mc->mc_ecn);
if (lmsg->ce_mask & MAC_CON_ATTR_SERVICE)
NLA_PUT_U8(msg, DECTA_MAC_CON_SERVICE, mc->mc_service);
return 0;
nla_put_failure:
return -NLE_MSGSIZE;
}
#endif
static const struct nl_dect_llme_link {
int (*parse)(struct nl_dect_llme_msg *, struct nlattr *[]);
int (*build)(struct nl_msg *, struct nl_dect_llme_msg *);
void (*dump)(const struct nl_dect_llme_msg *, struct nl_dump_params *);
struct nla_policy *policy;
unsigned int maxtype;
} nl_dect_llme_dispatch[DECT_LLME_MAX + 1] = {
[DECT_LLME_SCAN] = {
.policy = nl_dect_mac_info_policy,
.maxtype = DECTA_MAC_INFO_MAX,
.parse = nl_dect_llme_mac_info_parse,
.build = nl_dect_llme_mac_info_build,
.dump = nl_dect_llme_mac_info_dump,
},
[DECT_LLME_MAC_INFO] = {
.policy = nl_dect_mac_info_policy,
.maxtype = DECTA_MAC_INFO_MAX,
.parse = nl_dect_llme_mac_info_parse,
.build = nl_dect_llme_mac_info_build,
.dump = nl_dect_llme_mac_info_dump,
},
#if 0
[DECT_LLME_MAC_CON] = {
.policy = nl_dect_mac_con_policy,
.maxtype = DECTA_MAC_CON_MAX,
.parse = nl_dect_llme_mac_con_parse,
.build = nl_dect_llme_mac_con_build,
.dump = nl_dect_llme_mac_con_dump,
},
#endif
};
static void llme_msg_dump(struct nl_object *obj, struct nl_dump_params *p)
{
struct nl_dect_llme_msg *lmsg = nl_object_priv(obj);
const struct nl_dect_llme_link *link;
char buf1[64], buf2[64];
nl_dect_llme_msgtype2str(lmsg->lm_type, buf1, sizeof(buf1));
nl_dect_llme_op2str(lmsg->lm_op, buf2, sizeof(buf2));
nl_dump(p, "%s-%s:\n", buf1, buf2);
link = &nl_dect_llme_dispatch[lmsg->lm_type];
link->dump(lmsg, p);
}
static struct nla_policy nl_dect_llme_policy[DECTA_LLME_MAX + 1] = {
[DECTA_LLME_OP] = { .type = NLA_U8 },
[DECTA_LLME_TYPE] = { .type = NLA_U8 },
[DECTA_LLME_DATA] = { .type = NLA_NESTED },
};
static int llme_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
struct nlmsghdr *n, struct nl_parser_param *pp)
{
const struct nl_dect_llme_link *link;
struct dectmsg *dm = nlmsg_data(n);
struct nlattr *tb[DECTA_LLME_MAX + 1];
struct nl_dect_llme_msg *lmsg;
uint8_t op, type;
int err;
err = nlmsg_parse(n, sizeof(*dm), tb, DECTA_LLME_MAX, nl_dect_llme_policy);
if (err < 0)
return err;
if (tb[DECTA_LLME_OP] == NULL ||
tb[DECTA_LLME_TYPE] == NULL ||
tb[DECTA_LLME_DATA] == NULL)
return -NLE_INVAL;
type = nla_get_u8(tb[DECTA_LLME_TYPE]);
if (type > DECT_LLME_MAX)
return -NLE_INVAL;
link = &nl_dect_llme_dispatch[type];
op = nla_get_u8(tb[DECTA_LLME_OP]);
switch (op) {
case DECT_LLME_REQUEST:
case DECT_LLME_INDICATE:
case DECT_LLME_RESPONSE:
case DECT_LLME_CONFIRM:
if (link->parse == NULL)
return -NLE_OPNOTSUPP;
break;
default:
return -NLE_INVAL;
}
lmsg = nl_dect_llme_msg_alloc();
lmsg->ce_msgtype = n->nlmsg_type;
lmsg->lm_index = dm->dm_index;
nl_dect_llme_msg_set_type(lmsg, type);
nl_dect_llme_msg_set_op(lmsg, op);
if (1) {
struct nlattr *nla[link->maxtype + 1];
err = nla_parse_nested(nla, link->maxtype, tb[DECTA_LLME_DATA],
link->policy);
if (err < 0)
goto errout;
err = link->parse(lmsg, nla);
if (err < 0)
goto errout;
}
err = pp->pp_cb((struct nl_object *)lmsg, pp);
errout:
nl_dect_llme_msg_put(lmsg);
return err;
}
/**
* @name message creation
* @{
*/
static int nl_dect_llme_build_msg(struct nl_msg *msg, struct nl_dect_llme_msg *lmsg,
enum dect_llme_ops op)
{
const struct nl_dect_llme_link *link;
struct nlattr *nest;
struct dectmsg dm = {
.dm_index = lmsg->lm_index,
};
if (nlmsg_append(msg, &dm, sizeof(dm), NLMSG_ALIGNTO) < 0)
goto nla_put_failure;
NLA_PUT_U8(msg, DECTA_LLME_OP, op);
NLA_PUT_U8(msg, DECTA_LLME_TYPE, lmsg->lm_type);
link = &nl_dect_llme_dispatch[lmsg->lm_type];
nest = nla_nest_start(msg, DECTA_LLME_DATA);
if (nest == NULL)
goto nla_put_failure;
if (link->build(msg, lmsg) < 0)
goto nla_put_failure;
nla_nest_end(msg, nest);
return 0;
nla_put_failure:
return -NLE_MSGSIZE;
}
static int build_llme_msg(struct nl_dect_llme_msg *tmpl, enum dect_llme_ops op,
struct nl_msg **result)
{
struct nl_msg *msg;
int err;
if (!(msg = nlmsg_alloc_simple(DECT_LLME_MSG, 0)))
return -NLE_NOMEM;
if ((err = nl_dect_llme_build_msg(msg, tmpl, op)) < 0) {
nlmsg_free(msg);
return err;
}
*result = msg;
return 0;
}
int nl_dect_llme_build_request(struct nl_dect_llme_msg *tmpl,
struct nl_msg **result)
{
return build_llme_msg(tmpl, DECT_LLME_REQUEST, result);
}
int nl_dect_llme_request(struct nl_sock *sk, struct nl_dect_llme_msg *lmsg)
{
struct nl_msg *msg;
int err;
if ((err = nl_dect_llme_build_request(lmsg, &msg)) < 0)
return err;
err = nl_send_auto_complete(sk, msg);
nlmsg_free(msg);
if (err < 0)
return err;
return wait_for_ack(sk);
}
int nl_dect_llme_build_response(struct nl_dect_llme_msg *tmpl,
struct nl_msg **result)
{
return build_llme_msg(tmpl, DECT_LLME_RESPONSE, result);
}
int nl_dect_llme_respond(struct nl_sock *sk, struct nl_dect_llme_msg *tmpl)
{
struct nl_msg *msg;
int err;
if ((err = nl_dect_llme_build_response(tmpl, &msg)) < 0)
return err;
err = nl_send_auto_complete(sk, msg);
nlmsg_free(msg);
if (err < 0)
return err;
return wait_for_ack(sk);
}
void nl_dect_llme_msg_set_index(struct nl_dect_llme_msg *lmsg, int index)
{
lmsg->lm_index = index;
}
void nl_dect_llme_msg_set_type(struct nl_dect_llme_msg *lmsg,
enum dect_llme_msg_types type)
{
lmsg->lm_type = type;
}
enum dect_llme_msg_types nl_dect_llme_msg_get_type(const struct nl_dect_llme_msg *lmsg)
{
return lmsg->lm_type;
}
enum dect_llme_ops nl_dect_llme_msg_get_op(const struct nl_dect_llme_msg *lmsg)
{
return lmsg->lm_op;
}
void nl_dect_llme_msg_set_op(struct nl_dect_llme_msg *lmsg, enum dect_llme_ops op)
{
lmsg->lm_op = op;
}
/** @} */
/**
* @name Allocation/Freeing
* @{
*/
struct nl_dect_llme_msg *nl_dect_llme_msg_alloc(void)
{
return (struct nl_dect_llme_msg *)nl_object_alloc(&llme_msg_obj_ops);
}
void nl_dect_llme_msg_get(struct nl_dect_llme_msg *lmsg)
{
nl_object_get((struct nl_object *)lmsg);
}
void nl_dect_llme_msg_put(struct nl_dect_llme_msg *lmsg)
{
nl_object_put((struct nl_object *)lmsg);
}
/** @} */
static struct trans_tbl llme_types[] = {
__ADD(DECT_LLME_SCAN, SCAN)
__ADD(DECT_LLME_MAC_INFO, MAC_INFO)
#if 0
__ADD(DECT_LLME_MAC_CON, MAC_CON)
#endif
};
char *nl_dect_llme_msgtype2str(enum dect_llme_msg_types type, char *buf, size_t len)
{
return __type2str(type, buf, len, llme_types, ARRAY_SIZE(llme_types));
}
enum dect_llme_msg_types nl_dect_llme_str2msgtype(const char *str)
{
return __str2type(str, llme_types, ARRAY_SIZE(llme_types));
}
static struct trans_tbl llme_ops[] = {
__ADD(DECT_LLME_REQUEST, req)
__ADD(DECT_LLME_INDICATE, ind)
__ADD(DECT_LLME_RESPONSE, res)
__ADD(DECT_LLME_CONFIRM, cfm)
};
char *nl_dect_llme_op2str(enum dect_llme_ops op, char *buf, size_t len)
{
return __type2str(op, buf, len, llme_ops, ARRAY_SIZE(llme_ops));
}
enum dect_llme_ops nl_dect_llme_str2op(const char *str)
{
return __str2type(str, llme_ops, ARRAY_SIZE(llme_ops));
}
/** @cond SKIP */
static struct nl_object_ops llme_msg_obj_ops = {
.oo_name = "nl_dect/llme_msg",
.oo_size = sizeof(struct nl_dect_llme_msg),
.oo_dump = {
[NL_DUMP_LINE] = llme_msg_dump,
},
};
static struct nl_cache_ops nl_dect_llme_msg_ops = {
.co_name = "nl_dect/llme_msg",
.co_protocol = NETLINK_DECT,
.co_msgtypes = {
{ DECT_LLME_MSG, NL_ACT_NEW, "new" },
END_OF_MSGTYPES_LIST,
},
.co_msg_parser = llme_msg_parser,
.co_obj_ops = &llme_msg_obj_ops,
};
/** @endcond */
static void __init llme_init(void)
{
nl_cache_mngt_register(&nl_dect_llme_msg_ops);
}
static void __exit llme_exit(void)
{
nl_cache_mngt_unregister(&nl_dect_llme_msg_ops);
}
/** @} */

284
lib/dect/transceiver.c Normal file
View File

@ -0,0 +1,284 @@
/*
* lib/dect/transceiver.c DECT Transceiver objects
*
* 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 version 2.1
* of the License.
*
* Copyright (c) 2009 Patrick McHardy <kaber@trash.net>
*/
/**
* @ingroup dect
* @defgroup dect Transceivers
* @brief
* @{
*/
#include <netlink-local.h>
#include <netlink/netlink.h>
#include <netlink/utils.h>
#include <netlink/dect/transceiver.h>
/** @cond SKIP */
static struct nl_cache_ops nl_dect_transceiver_ops;
/** @endcond */
#define DECTNAMSIZ 16
static struct nla_policy transceiver_policy[DECTA_TRANSCEIVER_MAX + 1] = {
[DECTA_TRANSCEIVER_NAME] = { .type = NLA_STRING, .maxlen = DECTNAMSIZ },
[DECTA_TRANSCEIVER_TYPE] = { .type = NLA_STRING },
[DECTA_TRANSCEIVER_LINK] = { .type = NLA_U8 },
[DECTA_TRANSCEIVER_STATS] = { .type = NLA_NESTED },
[DECTA_TRANSCEIVER_BAND] = { .type = NLA_U8 },
[DECTA_TRANSCEIVER_SLOTS] = { .type = NLA_NESTED },
};
static struct nla_policy stats_policy[DECTA_TRANSCEIVER_STATS_MAX + 1] = {
[DECTA_TRANSCEIVER_STATS_EVENT_BUSY] = { .type = NLA_U32 },
[DECTA_TRANSCEIVER_STATS_EVENT_LATE] = { .type = NLA_U32 },
};
static struct nla_policy slot_policy[DECTA_SLOT_MAX + 1] = {
[DECTA_SLOT_NUM] = { .type = NLA_U8 },
[DECTA_SLOT_STATE] = { .type = NLA_U8 },
[DECTA_SLOT_CARRIER] = { .type = NLA_U8 },
[DECTA_SLOT_FREQUENCY] = { .type = NLA_U32 },
[DECTA_SLOT_RSSI] = { .type = NLA_U8 },
[DECTA_SLOT_RX_BYTES] = { .type = NLA_U32 },
[DECTA_SLOT_RX_PACKETS] = { .type = NLA_U32 },
[DECTA_SLOT_TX_BYTES] = { .type = NLA_U32 },
[DECTA_SLOT_TX_PACKETS] = { .type = NLA_U32 },
};
static int slot_parser(struct nl_dect_transceiver *trx, struct nlattr *nla)
{
struct nlattr *tb[DECTA_SLOT_MAX + 1];
struct nl_dect_transceiver_slot *dts;
uint8_t slot;
int err;
err = nla_parse_nested(tb, DECTA_SLOT_MAX, nla, slot_policy);
if (err < 0)
return err;
if (tb[DECTA_SLOT_NUM] == NULL)
return -NLE_INVAL;
slot = nla_get_u8(tb[DECTA_SLOT_NUM]);
dts = &trx->trx_slots[slot];
dts->dts_valid = 1;
if (tb[DECTA_SLOT_STATE] != NULL)
dts->dts_state = nla_get_u8(tb[DECTA_SLOT_STATE]);
if (tb[DECTA_SLOT_CARRIER] != NULL)
dts->dts_carrier = nla_get_u8(tb[DECTA_SLOT_CARRIER]);
if (tb[DECTA_SLOT_FREQUENCY] != NULL)
dts->dts_frequency = nla_get_u32(tb[DECTA_SLOT_FREQUENCY]);
if (tb[DECTA_SLOT_RSSI] != NULL)
dts->dts_rssi = nla_get_u8(tb[DECTA_SLOT_RSSI]);
if (tb[DECTA_SLOT_RX_BYTES] != NULL)
dts->dts_rx_bytes = nla_get_u32(tb[DECTA_SLOT_RX_BYTES]);
if (tb[DECTA_SLOT_RX_PACKETS] != NULL)
dts->dts_rx_packets = nla_get_u32(tb[DECTA_SLOT_RX_PACKETS]);
if (tb[DECTA_SLOT_TX_BYTES] != NULL)
dts->dts_tx_bytes = nla_get_u32(tb[DECTA_SLOT_TX_BYTES]);
if (tb[DECTA_SLOT_TX_PACKETS] != NULL)
dts->dts_tx_packets = nla_get_u32(tb[DECTA_SLOT_TX_PACKETS]);
return 0;
}
static int stats_parser(struct nl_dect_transceiver *trx, struct nlattr *nla)
{
struct nlattr *tb[DECTA_TRANSCEIVER_STATS_MAX + 1];
struct nl_dect_transceiver_stats *stats = &trx->trx_stats;
int err;
err = nla_parse_nested(tb, DECTA_TRANSCEIVER_STATS_MAX, nla, stats_policy);
if (err < 0)
return err;
if (tb[DECTA_TRANSCEIVER_STATS_EVENT_BUSY] != NULL)
stats->trx_event_busy =
nla_get_u32(tb[DECTA_TRANSCEIVER_STATS_EVENT_BUSY]);
if (tb[DECTA_TRANSCEIVER_STATS_EVENT_LATE] != NULL)
stats->trx_event_late =
nla_get_u32(tb[DECTA_TRANSCEIVER_STATS_EVENT_LATE]);
return 0;
}
static int transceiver_msg_parser(struct nl_cache_ops *ops,
struct sockaddr_nl *who,
struct nlmsghdr *n,
struct nl_parser_param *pp)
{
struct nlattr *tb[DECTA_TRANSCEIVER_MAX + 1], *nla;
struct nl_dect_transceiver *trx;
int err;
trx = nl_dect_transceiver_alloc();
if (trx == NULL) {
err = -NLE_NOMEM;
goto errout;
}
trx->ce_msgtype = n->nlmsg_type;
err = nlmsg_parse(n, sizeof(struct dectmsg), tb, DECTA_TRANSCEIVER_MAX,
transceiver_policy);
if (err < 0)
goto errout;
if (tb[DECTA_TRANSCEIVER_NAME] != NULL) {
char name[DECTNAMSIZ];
nla_strlcpy(name, tb[DECTA_TRANSCEIVER_NAME], sizeof(name));
nl_dect_transceiver_set_name(trx, name);
}
if (tb[DECTA_TRANSCEIVER_TYPE] != NULL) {
char *type = nla_strdup(tb[DECTA_TRANSCEIVER_TYPE]);
if (type == NULL) {
err = -NLE_NOMEM;
goto errout;
}
nl_dect_transceiver_set_type(trx, type);
free(type);
}
if (tb[DECTA_TRANSCEIVER_LINK] != NULL)
nl_dect_transceiver_set_link(trx, nla_get_u8(tb[DECTA_TRANSCEIVER_LINK]));
if (tb[DECTA_TRANSCEIVER_STATS] != NULL) {
err = stats_parser(trx, tb[DECTA_TRANSCEIVER_STATS]);
if (err < 0)
goto errout;
}
if (tb[DECTA_TRANSCEIVER_BAND] != NULL)
nl_dect_transceiver_set_band(trx, nla_get_u8(tb[DECTA_TRANSCEIVER_BAND]));
if (tb[DECTA_TRANSCEIVER_SLOTS] != NULL) {
int rem;
nla_for_each_nested(nla, tb[DECTA_TRANSCEIVER_SLOTS], rem) {
if (nla_type(nla) != DECTA_LIST_ELEM)
continue;
err = slot_parser(trx, nla);
if (err < 0)
goto errout;
}
}
err = pp->pp_cb((struct nl_object *)trx, pp);
errout:
nl_dect_transceiver_put(trx);
return err;
}
static int transceiver_request_update(struct nl_cache *c, struct nl_sock *h)
{
struct dectmsg dm;
memset(&dm, 0, sizeof(dm));
return nl_send_simple(h, DECT_GET_TRANSCEIVER, NLM_F_DUMP,
&dm, sizeof(dm));
}
/**
* @name Cache Management
* @{
*/
int nl_dect_transceiver_alloc_cache(struct nl_sock *sk, struct nl_cache **result)
{
struct nl_cache *cache;
int err;
cache = nl_cache_alloc(&nl_dect_transceiver_ops);
if (cache == NULL)
return -NLE_NOMEM;
if (sk && (err = nl_cache_refill(sk, cache)) < 0) {
free(cache);
return err;
}
*result = cache;
return 0;
}
/** @} */
/**
* @name Transceiver creation
* @{
*/
static int build_transceiver_msg(struct nl_dect_transceiver *tmpl, int cmd,
int flags, struct nl_msg **result)
{
struct nl_msg *msg;
int err;
msg = nlmsg_alloc_simple(cmd, flags);
if (msg == NULL)
return -NLE_NOMEM;
err = nl_dect_transceiver_build_msg(msg, tmpl);
if (err < 0) {
nlmsg_free(msg);
return err;
}
*result = msg;
return 0;
}
int nl_dect_transceiver_build_change_request(struct nl_dect_transceiver *tmpl,
int flags, struct nl_msg **result)
{
return build_transceiver_msg(tmpl, DECT_NEW_TRANSCEIVER, flags, result);
}
int nl_dect_transceiver_change(struct nl_sock *sk, struct nl_dect_transceiver *trx,
int flags)
{
struct nl_msg *msg;
int err;
err = nl_dect_transceiver_build_change_request(trx, flags, &msg);
if (err < 0)
return err;
err = nl_send_auto_complete(sk, msg);
nlmsg_free(msg);
if (err < 0)
return err;
return wait_for_ack(sk);
}
static struct nl_cache_ops nl_dect_transceiver_ops = {
.co_name = "nl_dect/transceiver",
.co_hdrsize = 0,
.co_msgtypes = {
{ DECT_NEW_TRANSCEIVER, NL_ACT_NEW, "new" },
{ DECT_GET_TRANSCEIVER, NL_ACT_GET, "get" },
END_OF_MSGTYPES_LIST
},
.co_protocol = NETLINK_DECT,
.co_request_update = transceiver_request_update,
.co_msg_parser = transceiver_msg_parser,
.co_obj_ops = &nl_dect_transceiver_obj_ops,
};
static void __init transceiver_init(void)
{
nl_cache_mngt_register(&nl_dect_transceiver_ops);
}
static void __exit transceiver_exit(void)
{
nl_cache_mngt_unregister(&nl_dect_transceiver_ops);
}
/** @} */

252
lib/dect/transceiver_obj.c Normal file
View File

@ -0,0 +1,252 @@
/*
* lib/dect/transceiver_obj.c DECT Transceiver objects
*
* 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 version 2.1
* of the License.
*
* Copyright (c) 2009 Patrick McHardy <kaber@trash.net>
*/
#include <netlink-local.h>
#include <netlink/netlink.h>
#include <netlink/cache.h>
#include <netlink/utils.h>
#include <netlink/data.h>
#include <netlink/dect/dect.h>
#include <netlink/dect/cell.h>
#include <netlink/dect/transceiver.h>
/** @cond SKIP */
#define TRANSCEIVER_ATTR_NAME 0x0001
#define TRANSCEIVER_ATTR_TYPE 0x0002
#define TRANSCEIVER_ATTR_INDEX 0x0004
#define TRANSCEIVER_ATTR_LINK 0x0008
#define TRANSCEIVER_ATTR_BAND 0x0010
/** @endtsond */
static void transceiver_free_data(struct nl_object *obj)
{
struct nl_dect_transceiver *trx = nl_object_priv(obj);
if (trx == NULL)
return;
free(trx->trx_name);
free(trx->trx_type);
}
static void slot_dump(struct nl_dect_transceiver_slot *dts, unsigned int n,
struct nl_dump_params *p)
{
char buf[64];
nl_dump(p, "\tslot %u: <%s> carrier: %u (%u.%3u MHz)", n,
nl_dect_slot_state2str(dts->dts_state, buf, sizeof(buf)),
dts->dts_carrier,
dts->dts_frequency / 1000, dts->dts_frequency % 1000);
if (dts->dts_state == DECT_SLOT_RX)
nl_dump(p, " signal level: %.2fdBm",
nl_dect_rssi_to_dbm(dts->dts_rssi));
nl_dump(p, "\n");
nl_dump(p, "\t RX: bytes %u packets %u\n",
dts->dts_rx_bytes, dts->dts_rx_packets);
nl_dump(p, "\t TX: bytes %u packets %u\n",
dts->dts_tx_bytes, dts->dts_tx_packets);
}
static void transceiver_dump(struct nl_object *obj, struct nl_dump_params *p)
{
struct nl_dect_transceiver *trx = nl_object_priv(obj);
struct nl_dect_transceiver_stats *stats = &trx->trx_stats;
struct nl_dect_transceiver_slot *dts;
struct nl_cache *cell_cache;
char buf[64];
unsigned int n;
nl_dump(p, "DECT Transceiver ");
if (trx->trx_name != NULL)
nl_dump_line(p, "%s", trx->trx_name);
if (trx->trx_link) {
cell_cache = nl_cache_mngt_require("nl_dect/cell");
if (cell_cache != NULL) {
nl_dump(p, "@%s",
nl_dect_cell_i2name(cell_cache, trx->trx_link,
buf, sizeof(buf)));
} else
nl_dump(p, "@%d", trx->trx_link);
}
nl_dump(p, ":\n");
if (trx->trx_type != NULL)
nl_dump_line(p, "\tType: %s\n", trx->trx_type);
nl_dump(p, "\tEvents: busy: %u late: %u\n",
stats->trx_event_busy, stats->trx_event_late);
nl_dump(p, "\tRF-band: %u\n", trx->trx_band);
nl_dump(p, "\n");
for (n = 0; n < 24; n++) {
dts = &trx->trx_slots[n];
if (!dts->dts_valid)
continue;
slot_dump(dts, n, p);
}
}
static int nl_dect_transceiver_compare(struct nl_object *_a, struct nl_object *_b,
uint32_t attrs, int flags)
{
struct nl_dect_transceiver *a = (struct nl_dect_transceiver *)_a;
struct nl_dect_transceiver *b = (struct nl_dect_transceiver *)_b;
int diff = 0;
#define TRX_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, TRANSCEIVER_ATTR_##ATTR, a, b, EXPR)
diff |= TRX_DIFF(NAME, strcmp(a->trx_name, b->trx_name));
diff |= TRX_DIFF(LINK, a->trx_link != b->trx_link);
#undef TRX_DIFF
return diff;
}
/**
* @name Allocation/Freeing
* @{
*/
struct nl_dect_transceiver *nl_dect_transceiver_alloc(void)
{
return (struct nl_dect_transceiver *)nl_object_alloc(&nl_dect_transceiver_obj_ops);
}
void nl_dect_transceiver_get(struct nl_dect_transceiver *trx)
{
nl_object_get((struct nl_object *)trx);
}
void nl_dect_transceiver_put(struct nl_dect_transceiver *trx)
{
nl_object_put((struct nl_object *)trx);
}
/** @} */
/**
* @name Attributes
* @{
*/
void nl_dect_transceiver_set_name(struct nl_dect_transceiver *trx, const char *name)
{
trx->trx_name = strdup(name);
trx->ce_mask |= TRANSCEIVER_ATTR_NAME;
}
bool nl_dect_transceiver_test_name(const struct nl_dect_transceiver *trx)
{
return !!(trx->ce_mask & TRANSCEIVER_ATTR_NAME);
}
const char *nl_dect_transceiver_get_name(const struct nl_dect_transceiver *trx)
{
return trx->trx_name;
}
void nl_dect_transceiver_set_type(struct nl_dect_transceiver *trx, const char *type)
{
trx->trx_type = strdup(type);
trx->ce_mask |= TRANSCEIVER_ATTR_TYPE;
}
bool nl_dect_transceiver_test_type(const struct nl_dect_transceiver *trx)
{
return !!(trx->ce_mask & TRANSCEIVER_ATTR_TYPE);
}
const char *nl_dect_transceiver_get_type(const struct nl_dect_transceiver *trx)
{
return trx->trx_type;
}
void nl_dect_transceiver_set_index(struct nl_dect_transceiver *trx, int index)
{
trx->trx_index = index;
trx->ce_mask |= TRANSCEIVER_ATTR_INDEX;
}
void nl_dect_transceiver_set_link(struct nl_dect_transceiver *trx, uint8_t link)
{
trx->trx_link = link;
trx->ce_mask |= TRANSCEIVER_ATTR_LINK;
}
static struct trans_tbl slot_states[] = {
__ADD(DECT_SLOT_IDLE, idle)
__ADD(DECT_SLOT_SCANNING, scanning)
__ADD(DECT_SLOT_RX, rx)
__ADD(DECT_SLOT_TX, tx)
};
void nl_dect_transceiver_set_band(struct nl_dect_transceiver *trx, uint8_t band)
{
trx->trx_band = band;
trx->ce_mask |= TRANSCEIVER_ATTR_BAND;
}
bool nl_dect_transceiver_test_band(const struct nl_dect_transceiver *trx)
{
return !!(trx->ce_mask & TRANSCEIVER_ATTR_BAND);
}
uint8_t nl_dect_transceiver_get_band(const struct nl_dect_transceiver *trx)
{
return trx->trx_band;
}
char *nl_dect_slot_state2str(uint8_t state, char *buf, size_t len)
{
return __type2str(state, buf, len, slot_states,
ARRAY_SIZE(slot_states));
}
uint8_t nl_dect_slot_str2state(const char *str)
{
return __str2type(str, slot_states, ARRAY_SIZE(slot_states));
}
int nl_dect_transceiver_build_msg(struct nl_msg *msg, struct nl_dect_transceiver *trx)
{
struct dectmsg dm = {
.dm_index = trx->trx_index,
};
if (nlmsg_append(msg, &dm, sizeof(dm), NLMSG_ALIGNTO) < 0)
goto nla_put_failure;
if (trx->ce_mask & TRANSCEIVER_ATTR_NAME)
NLA_PUT_STRING(msg, DECTA_TRANSCEIVER_NAME, trx->trx_name);
if (trx->ce_mask & TRANSCEIVER_ATTR_LINK)
NLA_PUT_U8(msg, DECTA_TRANSCEIVER_LINK, trx->trx_link);
return 0;
nla_put_failure:
return -NLE_MSGSIZE;
}
/** @cond SKIP */
struct nl_object_ops nl_dect_transceiver_obj_ops = {
.oo_name = "nl_dect/transceiver",
.oo_size = sizeof(struct nl_dect_transceiver),
.oo_free_data = transceiver_free_data,
.oo_dump = {
[NL_DUMP_LINE] = transceiver_dump,
},
.oo_compare = nl_dect_transceiver_compare,
.oo_id_attrs = TRANSCEIVER_ATTR_NAME,
};
/** @endcond */
/** @} */

9
src/.gitignore vendored
View File

@ -29,3 +29,12 @@ nl-rule-list
nl-tctree-list
nl-util-addr
nf-queue
dect-transceiver-list
dect-transceiver-bind
dect-cell-add
dect-cell-delete
dect-cell-list
dect-cluster-add
dect-cluster-delete
dect-cluster-list
dect-llme-scan

View File

@ -14,7 +14,7 @@ ifeq ($(shell [ ! -r ../Makefile.opts ] && echo 1),)
endif
LDFLAGS += -L../lib -lnl
CIN := $(wildcard nl-*.c) $(wildcard genl-*.c) $(wildcard nf-*.c)
CIN := $(wildcard nl-*.c) $(wildcard genl-*.c) $(wildcard nf-*.c) $(wildcard dect-*.c)
TOOLS := $(CIN:%.c=%)
all: $(TOOLS)
@ -50,6 +50,10 @@ nf-%: nf-%.o
@echo " LD $@"; \
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) -lnl-nf -lnl-route
dect-%: dect-%.c
@echo " LD $@"; \
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) -lnl-dect
clean:
@echo " CLEAN src"; \
rm -f $(TOOLS) *.o

67
src/dect-cell-add.c Normal file
View File

@ -0,0 +1,67 @@
#include "utils.h"
int main(int argc, char *argv[])
{
struct nl_sock *sock;
struct nl_dect_cell *cell;
struct nl_cache *cluster_cache;
struct nl_dump_params params = {
.dp_type = NL_DUMP_LINE,
.dp_fd = stdout,
};
uint8_t cli;
int err;
sock = nlt_alloc_socket();
nlt_connect(sock, NETLINK_DECT);
if (nl_dect_cluster_alloc_cache(sock, &cluster_cache))
exit(1);
nl_cache_mngt_provide(cluster_cache);
cell = nl_dect_cell_alloc();
for (;;) {
int c, optidx = 0;
enum {
ARG_NAME = 256,
ARG_FLAGS,
ARG_CLUSTER,
};
static struct option long_opts[] = {
{ "name", 1, 0, ARG_NAME },
{ "flags", 1, 0, ARG_FLAGS },
{ "cluster", 1, 0, ARG_CLUSTER },
{ 0, 0, 0, 0 }
};
c = getopt_long(argc, argv, "qhvd:n:t:", long_opts, &optidx);
if (c == -1)
break;
switch (c) {
case 'v': nlt_print_version(); break;
case ARG_NAME:
nl_dect_cell_set_name(cell, optarg);
break;
case ARG_FLAGS:
nl_dect_cell_set_flags(cell, nl_dect_cell_str2flags(optarg));
break;
case ARG_CLUSTER:
if (isdigit(*optarg))
cli = strtoul(optarg, NULL, 0);
else
cli = nl_dect_cluster_name2i(cluster_cache, optarg);
nl_dect_cell_set_link(cell, cli);
break;
}
}
err = nl_dect_cell_add(sock, cell, 0);
if (err < 0)
fatal(err, "Unable to add cell: %s", nl_geterror(err));
printf("Added: ");
nl_object_dump(OBJ_CAST(cell), &params);
return 0;
}

59
src/dect-cell-delete.c Normal file
View File

@ -0,0 +1,59 @@
#include "utils.h"
int main(int argc, char *argv[])
{
struct nl_sock *sock;
struct nl_dect_cell *cell;
struct nl_cache *cluster_cache;
struct nl_dump_params params = {
.dp_type = NL_DUMP_LINE,
.dp_fd = stdout,
};
int err;
sock = nlt_alloc_socket();
nlt_connect(sock, NETLINK_DECT);
if (nl_dect_cluster_alloc_cache(sock, &cluster_cache))
exit(1);
nl_cache_mngt_provide(cluster_cache);
cell = nl_dect_cell_alloc();
for (;;) {
int c, optidx = 0;
enum {
ARG_CELL = 257,
ARG_CLUSTER,
ARG_TRANSCEIVER,
};
static struct option long_opts[] = {
{ "cell", 1, 0, ARG_CELL },
{ "cluster", 1, 0, ARG_CLUSTER },
{ 0, 0, 0, 0 }
};
c = getopt_long(argc, argv, "qhvd:n:t:", long_opts, &optidx);
if (c == -1)
break;
switch (c) {
case 'v': nlt_print_version(); break;
case ARG_CELL:
nl_dect_cell_set_name(cell, optarg);
break;
case ARG_CLUSTER:
nl_dect_cell_set_link(cell,
nl_dect_cluster_name2i(cluster_cache, optarg));
break;
}
}
err = nl_dect_cell_delete(sock, cell, 0);
if (err < 0)
fatal(err, "Unable to delete cell: %s", nl_geterror(err));
printf("Deleted: ");
nl_object_dump(OBJ_CAST(cell), &params);
return 0;
}

24
src/dect-cell-list.c Normal file
View File

@ -0,0 +1,24 @@
#include "utils.h"
int main(int argc, char *argv[])
{
struct nl_sock *sock;
struct nl_cache *cell_cache;
struct nl_cache *cluster_cache;
struct nl_dump_params params = {
.dp_type = NL_DUMP_LINE,
.dp_fd = stdout,
};
sock = nlt_alloc_socket();
nlt_connect(sock, NETLINK_DECT);
if (nl_dect_cluster_alloc_cache(sock, &cluster_cache))
exit(1);
nl_cache_mngt_provide(cluster_cache);
if (nl_dect_cell_alloc_cache(sock, &cell_cache))
exit(1);
nl_cache_dump(cell_cache, &params);
return 0;
}

65
src/dect-cluster-add.c Normal file
View File

@ -0,0 +1,65 @@
#include "utils.h"
int main(int argc, char *argv[])
{
struct nl_sock *sock;
struct nl_dect_cluster *cl;
struct nl_dect_ari *pari;
struct nl_dump_params params = {
.dp_type = NL_DUMP_LINE,
.dp_fd = stdout,
};
int err;
sock = nlt_alloc_socket();
nlt_connect(sock, NETLINK_DECT);
cl = nl_dect_cluster_alloc();
pari = (void *)nl_dect_cluster_get_pari(cl);
for (;;) {
int c, optidx = 0;
enum {
ARG_NAME = 257,
ARG_MODE,
ARG_EMC,
ARG_FPN,
};
static struct option long_opts[] = {
{ "name", 1, 0, ARG_NAME },
{ "mode", 1, 0, ARG_MODE },
{ "emc", 1, 0, ARG_EMC },
{ "fpn", 1, 0, ARG_FPN },
{ 0, 0, 0, 0 }
};
c = getopt_long(argc, argv, "qhvd:n:t:", long_opts, &optidx);
if (c == -1)
break;
switch (c) {
case 'v': nlt_print_version(); break;
case ARG_NAME:
nl_dect_cluster_set_name(cl, strdup(optarg));
break;
case ARG_MODE:
nl_dect_cluster_set_mode(cl, nl_dect_cluster_str2mode(optarg));
break;
case ARG_EMC:
nl_dect_ari_set_emc(pari, strtoul(optarg, NULL, 16));
break;
case ARG_FPN:
nl_dect_ari_set_fpn(pari, strtoul(optarg, NULL, 16));
break;
}
}
nl_dect_cluster_set_pari(cl, pari);
err = nl_dect_cluster_add(sock, cl, 0);
if (err < 0)
fatal(err, "Unable to add cluster: %s", nl_geterror(err));
printf("Added: ");
nl_object_dump(OBJ_CAST(cl), &params);
return 0;
}

64
src/dect-cluster-delete.c Normal file
View File

@ -0,0 +1,64 @@
#include "utils.h"
int main(int argc, char *argv[])
{
struct nl_sock *sock;
struct nl_dect_cluster *cl;
struct nl_dect_ari *pari;
struct nl_dump_params params = {
.dp_type = NL_DUMP_LINE,
.dp_fd = stdout,
};
int err;
sock = nlt_alloc_socket();
nlt_connect(sock, NETLINK_DECT);
cl = nl_dect_cluster_alloc();
pari = (void *)nl_dect_cluster_get_pari(cl);
for (;;) {
int c, optidx = 0;
enum {
ARG_NAME = 257,
ARG_MODE,
ARG_EMC,
ARG_FPN,
};
static struct option long_opts[] = {
{ "name", 1, 0, ARG_NAME },
{ "mode", 1, 0, ARG_MODE },
{ "emc", 1, 0, ARG_EMC },
{ "fpn", 1, 0, ARG_FPN },
{ 0, 0, 0, 0 }
};
c = getopt_long(argc, argv, "qhvd:n:t:", long_opts, &optidx);
if (c == -1)
break;
switch (c) {
case 'v': nlt_print_version(); break;
case ARG_NAME:
nl_dect_cluster_set_name(cl, strdup(optarg));
break;
case ARG_MODE:
nl_dect_cluster_set_mode(cl, atoi(optarg));
break;
case ARG_EMC:
nl_dect_ari_set_emc(pari, strtoul(optarg, NULL, 16));
break;
case ARG_FPN:
nl_dect_ari_set_fpn(pari, strtoul(optarg, NULL, 16));
break;
}
}
err = nl_dect_cluster_delete(sock, cl, 0);
if (err < 0)
fatal(err, "Unable to delete cluster: %s", nl_geterror(err));
printf("Deleted: ");
nl_object_dump(OBJ_CAST(cl), &params);
return 0;
}

20
src/dect-cluster-list.c Normal file
View File

@ -0,0 +1,20 @@
#include "utils.h"
int main(int argc, char *argv[])
{
struct nl_sock *sock;
struct nl_cache *cluster_cache;
struct nl_dump_params params = {
.dp_type = NL_DUMP_LINE,
.dp_fd = stdout,
};
sock = nlt_alloc_socket();
nlt_connect(sock, NETLINK_DECT);
if (nl_dect_cluster_alloc_cache(sock, &cluster_cache))
exit(1);
nl_cache_dump(cluster_cache, &params);
return 0;
}

111
src/dect-llme-mac-con.c Normal file
View File

@ -0,0 +1,111 @@
#if 0
#include "utils.h"
static void obj_input(struct nl_object *obj, void *arg)
{
struct nl_dump_params dp = {
.dp_type = NL_DUMP_LINE,
.dp_fd = stdout,
};
printf("MAC Connection: ");
nl_object_dump(obj, &dp);
printf("\n");
}
static int event_input(struct nl_msg *msg, void *arg)
{
if (nl_msg_parse(msg, &obj_input, NULL) < 0)
fprintf(stderr, "Unknown message type\n");
return NL_STOP;
}
int main(int argc, char *argv[])
{
struct nl_sock *sock;
struct nl_cache *cluster_cache;
struct dect_llme_msg *lmsg;
struct dect_ari *ari;
struct nl_dump_params params = {
.dp_type = NL_DUMP_LINE,
.dp_fd = stdout,
};
int index;
int err;
sock = nlt_alloc_socket();
nlt_connect(sock, NETLINK_DECT);
if (dect_cluster_alloc_cache(sock, &cluster_cache))
exit(1);
nl_cache_mngt_provide(cluster_cache);
lmsg = dect_llme_msg_alloc();
dect_llme_msg_set_type(lmsg, DECT_LLME_MAC_CON);
ari = (void *)dect_llme_mac_con_get_ari(lmsg);
for (;;) {
int c, optidx = 0;
enum {
ARG_CLUSTER = 257,
ARG_MCEI,
ARG_PMID,
ARG_EMC,
ARG_FPN,
ARG_FPC,
};
static struct option long_opts[] = {
{ "cluster", 1, 0, ARG_CLUSTER },
{ "mcei", 1, 0, ARG_MCEI },
{ "pmid", 1, 0, ARG_PMID },
{ "emc", 1, 0, ARG_EMC },
{ "fpn", 1, 0, ARG_FPN },
{ "fpc", 0, 0, ARG_FPC },
{ 0, 0, 0, 0 }
};
c = getopt_long(argc, argv, "qhvd:n:t:", long_opts, &optidx);
if (c == -1)
break;
switch (c) {
case 'v': nlt_print_version(); break;
case ARG_CLUSTER:
index = dect_cluster_name2i(cluster_cache, optarg);
dect_llme_msg_set_index(lmsg, index);
break;
case ARG_MCEI:
dect_llme_mac_con_set_mcei(lmsg, strtoul(optarg, NULL, 16));
break;
case ARG_PMID:
dect_llme_mac_con_set_pmid(lmsg, strtoul(optarg, NULL, 16));
break;
case ARG_EMC:
dect_ari_set_emc(ari, strtoul(optarg, NULL, 16));
break;
case ARG_FPN:
dect_ari_set_fpn(ari, strtoul(optarg, NULL, 16));
break;
case ARG_FPC:
dect_llme_mac_info_set_fpc(lmsg, 0);
dect_llme_mac_info_set_ehlc(lmsg, 0);
break;
}
}
//dect_llme_mac_con_set_ari(lmsg, ari);
if ((err = dect_llme_request(sock, lmsg)) < 0)
fatal(err, "Unable to send request: %s", nl_geterror(err));
printf("Requested: ");
nl_object_dump(OBJ_CAST(lmsg), &params);
nl_socket_add_membership(sock, DECTNLGRP_LLME);
nl_socket_disable_seq_check(sock);
nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, event_input, NULL);
while (1)
nl_recvmsgs_default(sock);
return 0;
}
#endif
int main() {}

37
src/dect-llme-monitor.c Normal file
View File

@ -0,0 +1,37 @@
#include "utils.h"
static void obj_input(struct nl_object *obj, void *arg)
{
struct nl_dump_params dp = {
.dp_type = NL_DUMP_LINE,
.dp_fd = stdout,
};
nl_object_dump(obj, &dp);
}
static int event_input(struct nl_msg *msg, void *arg)
{
if (nl_msg_parse(msg, &obj_input, NULL) < 0)
fprintf(stderr, "Unknown message type\n");
return NL_STOP;
}
int main(int argc, char *argv[])
{
struct nl_sock *sock;
struct nl_cache *cluster_cache;
sock = nlt_alloc_socket();
nlt_connect(sock, NETLINK_DECT);
if (nl_dect_cluster_alloc_cache(sock, &cluster_cache))
exit(1);
nl_cache_mngt_provide(cluster_cache);
nl_socket_add_membership(sock, DECTNLGRP_LLME);
nl_socket_disable_seq_check(sock);
nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, event_input, NULL);
while (1)
nl_recvmsgs_default(sock);
return 0;
}

139
src/dect-llme-scan.c Normal file
View File

@ -0,0 +1,139 @@
#include "utils.h"
#define CACHE_SIZE 64
static struct {
unsigned int index;
unsigned int used;
struct {
uint16_t emc;
uint32_t fpn;
uint8_t rpn;
} ids[CACHE_SIZE];
} cache;
static void add_ari(const struct nl_dect_llme_msg *lmsg)
{
const struct nl_dect_ari *ari = nl_dect_llme_mac_info_get_pari(lmsg);
unsigned int index = cache.index;
cache.ids[index].emc = nl_dect_ari_get_emc(ari);
cache.ids[index].fpn = nl_dect_ari_get_fpn(ari);
cache.ids[index].rpn = nl_dect_llme_mac_info_get_rpn(lmsg);
if (++cache.used > CACHE_SIZE)
cache.used = CACHE_SIZE;
if (++cache.index == CACHE_SIZE)
cache.index = 0;
}
static bool lookup_ari(const struct nl_dect_llme_msg *lmsg)
{
const struct nl_dect_ari *ari = nl_dect_llme_mac_info_get_pari(lmsg);
unsigned int index;
for (index = 0; index < cache.used; index++) {
if (cache.ids[index].emc == nl_dect_ari_get_emc(ari) &&
cache.ids[index].fpn == nl_dect_ari_get_fpn(ari) &&
cache.ids[index].rpn == nl_dect_llme_mac_info_get_rpn(lmsg))
return true;
}
return false;
}
static void obj_input(struct nl_object *obj, void *arg)
{
struct nl_dect_llme_msg *lmsg = nl_object_priv(obj);
struct nl_dump_params dp = {
.dp_type = NL_DUMP_LINE,
.dp_fd = stdout,
};
static unsigned int n;
if (lookup_ari(lmsg))
return;
add_ari(lmsg);
printf("%u: Station: ", ++n);
nl_object_dump(obj, &dp);
printf("\n");
}
static int event_input(struct nl_msg *msg, void *arg)
{
if (nl_msg_parse(msg, &obj_input, NULL) < 0)
fprintf(stderr, "Unknown message type\n");
return NL_STOP;
}
int main(int argc, char *argv[])
{
struct nl_sock *sock;
struct nl_cache *cluster_cache;
struct nl_dect_llme_msg *lmsg;
struct nl_dect_ari *pari;
struct nl_dump_params params = {
.dp_type = NL_DUMP_LINE,
.dp_fd = stdout,
};
int index;
int err;
sock = nlt_alloc_socket();
nlt_connect(sock, NETLINK_DECT);
if (nl_dect_cluster_alloc_cache(sock, &cluster_cache))
exit(1);
nl_cache_mngt_provide(cluster_cache);
lmsg = nl_dect_llme_msg_alloc();
nl_dect_llme_msg_set_type(lmsg, DECT_LLME_SCAN);
pari = (void *)nl_dect_llme_mac_info_get_pari(lmsg);
for (;;) {
int c, optidx = 0;
enum {
ARG_CLUSTER = 257,
ARG_EMC,
ARG_FPN,
};
static struct option long_opts[] = {
{ "cluster", 1, 0, ARG_CLUSTER },
{ "emc", 1, 0, ARG_EMC },
{ "fpn", 1, 0, ARG_FPN },
{ 0, 0, 0, 0 }
};
c = getopt_long(argc, argv, "qhvd:n:t:", long_opts, &optidx);
if (c == -1)
break;
switch (c) {
case 'v': nlt_print_version(); break;
case ARG_CLUSTER:
index = nl_dect_cluster_name2i(cluster_cache, optarg);
nl_dect_llme_msg_set_index(lmsg, index);
break;
case ARG_EMC:
nl_dect_ari_set_emc(pari, strtoul(optarg, NULL, 16));
break;
case ARG_FPN:
nl_dect_ari_set_fpn(pari, strtoul(optarg, NULL, 16));
break;
}
}
//nl_dect_llme_mac_info_set_pari(lmsg, pari);
if ((err = nl_dect_llme_request(sock, lmsg)) < 0)
fatal(err, "Unable to send request: %s", nl_geterror(err));
printf("Requested: ");
nl_object_dump(OBJ_CAST(lmsg), &params);
nl_socket_disable_seq_check(sock);
nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, event_input, NULL);
while (1)
nl_recvmsgs_default(sock);
return 0;
}

View File

@ -0,0 +1,57 @@
#include "utils.h"
int main(int argc, char *argv[])
{
struct nl_sock *sock;
struct nl_dect_transceiver *trx;
struct nl_cache *cell_cache;
struct nl_dump_params params = {
.dp_type = NL_DUMP_LINE,
.dp_fd = stdout,
};
int err;
sock = nlt_alloc_socket();
nlt_connect(sock, NETLINK_DECT);
if (nl_dect_cell_alloc_cache(sock, &cell_cache))
exit(1);
nl_cache_mngt_provide(cell_cache);
trx = nl_dect_transceiver_alloc();
for (;;) {
int c, optidx = 0;
enum {
ARG_TRANSCEIVER = 257,
ARG_CELL,
};
static struct option long_opts[] = {
{ "transceiver", 1, 0, ARG_TRANSCEIVER },
{ "cell", 1, 0, ARG_CELL },
{ 0, 0, 0, 0 }
};
c = getopt_long(argc, argv, "qhvd:n:t:", long_opts, &optidx);
if (c == -1)
break;
switch (c) {
case 'v': nlt_print_version(); break;
case ARG_TRANSCEIVER:
nl_dect_transceiver_set_name(trx, strdup(optarg));
break;
case ARG_CELL:
nl_dect_transceiver_set_link(trx, nl_dect_cell_name2i(cell_cache, optarg));
break;
}
}
err = nl_dect_transceiver_change(sock, trx, 0);
if (err < 0)
fatal(err, "Unable to bind cell: %s", nl_geterror(err));
printf("Bound: ");
nl_object_dump(OBJ_CAST(trx), &params);
return 0;
}

View File

@ -0,0 +1,60 @@
#include "utils.h"
int main(int argc, char *argv[])
{
struct nl_sock *sock;
struct nl_cache *cell_cache;
struct nl_cache *transceiver_cache;
struct nl_dect_transceiver *trx;
struct nl_dump_params params = {
.dp_type = NL_DUMP_LINE,
.dp_fd = stdout,
};
sock = nlt_alloc_socket();
nlt_connect(sock, NETLINK_DECT);
if (nl_dect_cell_alloc_cache(sock, &cell_cache))
exit(1);
nl_cache_mngt_provide(cell_cache);
if (nl_dect_transceiver_alloc_cache(sock, &transceiver_cache))
exit(1);
trx = nl_dect_transceiver_alloc();
if (trx == NULL)
exit(1);
for (;;) {
int c, optidx = 0, cidx;
enum {
ARG_NAME = 257,
ARG_CELL,
};
static struct option long_ops[] = {
{ "name", 1, 0, ARG_NAME },
{ "cell", 1, 0, ARG_CELL },
{}
};
c = getopt_long(argc, argv, "n:c:", long_ops, &optidx);
if (c == -1)
break;
switch (c) {
case ARG_NAME:
nl_dect_transceiver_set_name(trx, optarg);
break;
case ARG_CELL:
cidx = nl_dect_cell_name2i(cell_cache, optarg);
if (cidx == 0) {
fprintf(stderr, "cell %s does not exist\n", optarg);
exit(1);
}
nl_dect_transceiver_set_link(trx, cidx);
break;
}
}
nl_cache_dump_filter(transceiver_cache, &params, OBJ_CAST(trx));
return 0;
}

View File

@ -20,6 +20,7 @@
#include <stdint.h>
#include <ctype.h>
#include <getopt.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/socket.h>
@ -42,6 +43,11 @@
#include <netlink/genl/ctrl.h>
#include <netlink/genl/mngt.h>
#include <netlink/netfilter/ct.h>
#include <netlink/dect/transceiver.h>
#include <netlink/dect/cell.h>
#include <netlink/dect/cluster.h>
#include <netlink/dect/llme.h>
#include <netlink/dect/ari.h>
extern uint32_t parse_u32(const char *);