1 /* (C) 2009,2010 by Holger Hans Peter Freyther <zecke@selfish.org>
2 * (C) 2009,2010 by On-Waves
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include <osmocore/gsm0808.h>
22 #include <osmocore/protocol/gsm_08_08.h>
23 #include <osmocore/gsm48.h>
25 #include <arpa/inet.h>
27 #define BSSMAP_MSG_SIZE 512
28 #define BSSMAP_MSG_HEADROOM 128
30 struct msgb *gsm0808_create_layer3(struct msgb *msg_l3, uint16_t nc, uint16_t cc, int lac, int _ci)
35 struct gsm48_loc_area_id *lai;
37 msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
42 /* create the bssmap header */
43 msg->l3h = msgb_put(msg, 2);
46 /* create layer 3 header */
47 data = msgb_put(msg, 1);
48 data[0] = BSS_MAP_MSG_COMPLETE_LAYER_3;
50 /* create the cell header */
51 data = msgb_put(msg, 3);
52 data[0] = GSM0808_IE_CELL_IDENTIFIER;
53 data[1] = 1 + sizeof(*lai) + 2;
54 data[2] = CELL_IDENT_WHOLE_GLOBAL;
56 lai = (struct gsm48_loc_area_id *) msgb_put(msg, sizeof(*lai));
57 gsm48_generate_lai(lai, cc, nc, lac);
59 ci = (uint16_t *) msgb_put(msg, 2);
62 /* copy the layer3 data */
63 data = msgb_put(msg, msgb_l3len(msg_l3) + 2);
64 data[0] = GSM0808_IE_LAYER_3_INFORMATION;
65 data[1] = msgb_l3len(msg_l3);
66 memcpy(&data[2], msg_l3->l3h, data[1]);
69 msg->l3h[1] = msgb_l3len(msg) - 2;
74 struct msgb *gsm0808_create_reset(void)
76 struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
81 msg->l3h = msgb_put(msg, 6);
82 msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
91 struct msgb *gsm0808_create_clear_complete(void)
93 struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
94 "bssmap: clear complete");
98 msg->l3h = msgb_put(msg, 3);
99 msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
101 msg->l3h[2] = BSS_MAP_MSG_CLEAR_COMPLETE;
106 struct msgb *gsm0808_create_cipher_reject(uint8_t cause)
108 struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
109 "bssmap: clear complete");
113 msg->l3h = msgb_put(msg, 3);
114 msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
116 msg->l3h[2] = BSS_MAP_MSG_CIPHER_MODE_REJECT;
122 struct msgb *gsm0808_create_classmark_update(const uint8_t *classmark_data, u_int8_t length)
124 struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
129 msg->l3h = msgb_put(msg, 3);
130 msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
132 msg->l3h[2] = BSS_MAP_MSG_CLASSMARK_UPDATE;
134 msg->l4h = msgb_put(msg, length);
135 memcpy(msg->l4h, classmark_data, length);
137 /* update the size */
138 msg->l3h[1] = msgb_l3len(msg) - 2;
142 struct msgb *gsm0808_create_sapi_reject(uint8_t link_id)
144 struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
145 "bssmap: sapi 'n' reject");
149 msg->l3h = msgb_put(msg, 5);
150 msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
152 msg->l3h[2] = BSS_MAP_MSG_SAPI_N_REJECT;
153 msg->l3h[3] = link_id;
154 msg->l3h[4] = GSM0808_CAUSE_BSS_NOT_EQUIPPED;
159 struct msgb *gsm0808_create_assignment_failure(uint8_t cause, uint8_t *rr_cause)
162 struct msgb *msg = msgb_alloc_headroom(BSSMAP_MSG_SIZE, BSSMAP_MSG_HEADROOM,
167 msg->l3h = msgb_put(msg, 6);
168 msg->l3h[0] = BSSAP_MSG_BSS_MANAGEMENT;
170 msg->l3h[2] = BSS_MAP_MSG_ASSIGMENT_FAILURE;
171 msg->l3h[3] = GSM0808_IE_CAUSE;
175 /* RR cause 3.2.2.22 */
177 data = msgb_put(msg, 2);
178 data[0] = GSM0808_IE_RR_CAUSE;
182 /* Circuit pool 3.22.45 */
183 /* Circuit pool list 3.2.2.46 */
185 /* update the size */
186 msg->l3h[1] = msgb_l3len(msg) - 2;
190 static const struct tlv_definition bss_att_tlvdef = {
192 [GSM0808_IE_IMSI] = { TLV_TYPE_TLV },
193 [GSM0808_IE_TMSI] = { TLV_TYPE_TLV },
194 [GSM0808_IE_CELL_IDENTIFIER_LIST] = { TLV_TYPE_TLV },
195 [GSM0808_IE_CHANNEL_NEEDED] = { TLV_TYPE_TV },
196 [GSM0808_IE_EMLPP_PRIORITY] = { TLV_TYPE_TV },
197 [GSM0808_IE_CHANNEL_TYPE] = { TLV_TYPE_TLV },
198 [GSM0808_IE_PRIORITY] = { TLV_TYPE_TLV },
199 [GSM0808_IE_CIRCUIT_IDENTITY_CODE] = { TLV_TYPE_TV },
200 [GSM0808_IE_DOWNLINK_DTX_FLAG] = { TLV_TYPE_TV },
201 [GSM0808_IE_INTERFERENCE_BAND_TO_USE] = { TLV_TYPE_TV },
202 [GSM0808_IE_CLASSMARK_INFORMATION_T2] = { TLV_TYPE_TLV },
203 [GSM0808_IE_GROUP_CALL_REFERENCE] = { TLV_TYPE_TLV },
204 [GSM0808_IE_TALKER_FLAG] = { TLV_TYPE_T },
205 [GSM0808_IE_CONFIG_EVO_INDI] = { TLV_TYPE_TV },
206 [GSM0808_IE_LSA_ACCESS_CTRL_SUPPR] = { TLV_TYPE_TV },
207 [GSM0808_IE_SERVICE_HANDOVER] = { TLV_TYPE_TV},
208 [GSM0808_IE_ENCRYPTION_INFORMATION] = { TLV_TYPE_TLV },
209 [GSM0808_IE_CIPHER_RESPONSE_MODE] = { TLV_TYPE_TV },
213 const struct tlv_definition *gsm0808_att_tlvdef()
215 return &bss_att_tlvdef;