aboutsummaryrefslogtreecommitdiffstats
path: root/src/hnbgw_hnbap.c
blob: ce4122257b20d3f33a16ba99138be050cc157748 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#include <osmocom/core/msgb.h>

#include "hnbgw.h"
#include "hnbap_const.h"

static int hnbgw_hnbap_tx(struct HNBAP_PDU *pdu)
{
	/* FIXME */
}

static int hnbgw_tx_hnb_register_acc()
{
	/* FIXME */
	/* Single required response IE: RNC-ID */
}

static int hnbgw_tx_ue_register_acc()
{
	/* FIXME */
	/* Single required response IE: RNC-ID */
}

struct ProtocolIE_Field_1 *find_ie(const struct ProtocolIE_Container_1 *cont, ProtocolIE_ID id)
{
	for (i = 0; i < cont->count; i++) {
		if (cont->tab[i].id == id)
			return &cont->tab[i];
	}
	return NULL;
}

static inline uint16_t asn1str_to_u16(ASN1String *as)
{
	if (as->len < 2)
		return 0;
	else
		return *(uint16_t *)as->buf;
}

static inline uint8_t asn1str_to_u8(ASN1String *as)
{
	if (as->len < 1)
		return 0;
	else
		return *(uint8_t *)as->buf;
}

static inline uint8_t asn1bitstr_to_u32(ASN1BitString *as)
{
	if (as->len < 25)
		return 0;
	else
		return *(uint32_t *)as->buf;
}

static int hnbgw_rx_hnb_register_req(struct hnb_context *ctx, struct HNBRegisterRequest *req)
{
	HNB_Identity *identity =
		FIND_IE(req->protocolIEs, HNBAP_IEI_HNB_Identity);
	HNB_Location_Information *loc =
		FIND_IE(req->protocolIEs, HNBAP_IEI_HNB_Location_Information);
	PLMNidentity *plmn_id =
		FIND_IE(req->protocolIEs, HNBAP_IEI_PLMNidentity);
	CellIdentity *cell_id =
		FIND_IE(req->protocolIEs, HNBAP_IEI_CellIdentity);
	LAC *lac = FIND_IE(req->protocolIEs, HNBAP_IEI_LAC);
	RAC *rac = FIND_IE(req->protocolIEs, HNBAP_IEI_RAC);
	SAC *sac = FIND_IE(req->protocolIEs, HNBAP_IEI_SAC);
	/* Optional: CSG-ID */

	if(!identity || !loc || !plmn_id || !cell_id || !lac || !rac || !sac)
		return -1;

	/* copy all identity parameters from the message to ctx */
	strncpy(ctx->identity_info, sizeof(ctx->identity_info, identity_info->buf);
	ctx->id.lac = asn1str_to_u16(lac);
	ctx->id.sac = asn1str_to_u16(sac);
	ctx->id.rac = asn1str_to_u8(rac);
	ctx->id.cid = asn1bitstr_to_u32(cell_id);
	ctx->id.mcc FIXME
	ctx->id.mnc FIXME

	/* FIXME: Send HNBRegisterAccept */
}

static int hnbgw_rx_ue_register_req(struct hnb_context *ctx, struct UERegisterRequest *req)
{
	UE_Identity *id =
		FIND_IE(req->protocolIEs, HNBAP_IEI_UE_Identity);
	Registration_Cause *reg_cause =
		FIND_IE(req->protocolIEs, HNBAP_IEI_RegistrationCause);
	UE_Capabilities *ue_cap =
		FIND_IE(req->protocolIEs, HNBAP_IEI_UE_Capabilities);

	if (!id || !reg_cause || !ue_cap)
		return -1;

	/* FIXME: Send UERegisterAccept */
}

static int hnbgw_rx_initiating_msg(struct hnb_context *hnb, struct InitiatingMessage *msg)
{
	int rc;

	switch (msg->procedureCode) {
	case HNBAP_PC_HNBRegister:	/* 8.2 */
		if (msg->value.type != asn1_type_HNBRegisterRequest)
			return -1;
		rc = hnbgw_rx_hnb_register_req(hnb, FIXME);
		break;
	case HNBAP_PC_HNBDe_Register:	/* 8.3 */
		break;
	case HNBAP_PC_UERegister: 	/* 8.4 */
		if (msg->value.type != asn1_type_UERegisterRequest)
			return -1;
		rc = hnbgw_rx_ue_register_req(hnb, FIXME);
		break;
	case HNBAP_PC_UEDe_Register:	/* 8.5 */
		break;
	case HNBAP_PC_ErrorIndication:	/* 8.6 */
	case HNBAP_PC_TNLUpdate:	/* 8.9 */
	case HNBAP_PC_HNBConfigTransfer:	/* 8.10 */
	case HNBAP_PC_RelocationComplete:	/* 8.11 */
	case HNBAP_PC_U_RNTIQuery:	/* 8.12 */
	case HNBAP_PC_privateMessage:
		break;
	default:
		break;
	}
}

static int hnbgw_rx_successful_outcome_msg(struct SuccessfulOutcome *msg)
{

}

static int hnbgw_rx_unsuccessful_outcome_msg(struct UnsuccessfulOutcome *msg)
{

}


static int _hnbgw_hnbap_rx(struct hnb_context *hnb, struct HNBAP_PDU *pdu)
{
	/* it's a bit odd that we can't dispatch on procedure code, but
	 * that's not possible */
	switch (pdu->choice) {
	case HNBAP_PDU_initiatingMessage:
		rc = hnbgw_rx_initiating_msg(&pdu->u.initiatingMessage);
		break;
	case HNBAP_PDU_successfulOutcome:
		rc = hnbgw_rx_successful_outcome_msg(&pdu->u.successfulOutcome);
		break;
	case HNBAP_PDU_unsuccessfulOutcome:
		rc = hnbgw_rx_unsuccessful_outcome_msg(&pdu->u.unsuccessfulOutcome);
		break;
	default:
		return -1;
	}
}

int hnbgw_hnbap_rx(struct hnb_context *hnb, struct msgb *msg)
{
	/* FIXME: decode and handle to _hnbgw_hnbap_rx() */
}


int hnbgw_hnbap_init(void)
{

}