1 /* GSM Mobile Radio Interface Layer 3 messages
2 * 3GPP TS 04.08 version 7.21.0 Release 1998 / ETSI TS 100 940 V7.21.0 */
4 /* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
5 * (C) 2008, 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 #include <arpa/inet.h>
31 #include <osmocore/utils.h>
32 #include <osmocore/tlv.h>
33 #include <osmocore/gsm48.h>
35 #include <osmocore/protocol/gsm_04_08.h>
37 const struct tlv_definition gsm48_att_tlvdef
= {
39 [GSM48_IE_MOBILE_ID
] = { TLV_TYPE_TLV
},
40 [GSM48_IE_NAME_LONG
] = { TLV_TYPE_TLV
},
41 [GSM48_IE_NAME_SHORT
] = { TLV_TYPE_TLV
},
42 [GSM48_IE_UTC
] = { TLV_TYPE_TV
},
43 [GSM48_IE_NET_TIME_TZ
] = { TLV_TYPE_FIXED
, 7 },
44 [GSM48_IE_LSA_IDENT
] = { TLV_TYPE_TLV
},
46 [GSM48_IE_BEARER_CAP
] = { TLV_TYPE_TLV
},
47 [GSM48_IE_CAUSE
] = { TLV_TYPE_TLV
},
48 [GSM48_IE_CC_CAP
] = { TLV_TYPE_TLV
},
49 [GSM48_IE_ALERT
] = { TLV_TYPE_TLV
},
50 [GSM48_IE_FACILITY
] = { TLV_TYPE_TLV
},
51 [GSM48_IE_PROGR_IND
] = { TLV_TYPE_TLV
},
52 [GSM48_IE_AUX_STATUS
] = { TLV_TYPE_TLV
},
53 [GSM48_IE_NOTIFY
] = { TLV_TYPE_TV
},
54 [GSM48_IE_KPD_FACILITY
] = { TLV_TYPE_TV
},
55 [GSM48_IE_SIGNAL
] = { TLV_TYPE_TV
},
56 [GSM48_IE_CONN_BCD
] = { TLV_TYPE_TLV
},
57 [GSM48_IE_CONN_SUB
] = { TLV_TYPE_TLV
},
58 [GSM48_IE_CALLING_BCD
] = { TLV_TYPE_TLV
},
59 [GSM48_IE_CALLING_SUB
] = { TLV_TYPE_TLV
},
60 [GSM48_IE_CALLED_BCD
] = { TLV_TYPE_TLV
},
61 [GSM48_IE_CALLED_SUB
] = { TLV_TYPE_TLV
},
62 [GSM48_IE_REDIR_BCD
] = { TLV_TYPE_TLV
},
63 [GSM48_IE_REDIR_SUB
] = { TLV_TYPE_TLV
},
64 [GSM48_IE_LOWL_COMPAT
] = { TLV_TYPE_TLV
},
65 [GSM48_IE_HIGHL_COMPAT
] = { TLV_TYPE_TLV
},
66 [GSM48_IE_USER_USER
] = { TLV_TYPE_TLV
},
67 [GSM48_IE_SS_VERS
] = { TLV_TYPE_TLV
},
68 [GSM48_IE_MORE_DATA
] = { TLV_TYPE_T
},
69 [GSM48_IE_CLIR_SUPP
] = { TLV_TYPE_T
},
70 [GSM48_IE_CLIR_INVOC
] = { TLV_TYPE_T
},
71 [GSM48_IE_REV_C_SETUP
] = { TLV_TYPE_T
},
72 [GSM48_IE_REPEAT_CIR
] = { TLV_TYPE_T
},
73 [GSM48_IE_REPEAT_SEQ
] = { TLV_TYPE_T
},
74 /* FIXME: more elements */
78 static const struct value_string rr_cause_names
[] = {
79 { GSM48_RR_CAUSE_NORMAL
, "Normal event" },
80 { GSM48_RR_CAUSE_ABNORMAL_UNSPEC
, "Abnormal release, unspecified" },
81 { GSM48_RR_CAUSE_ABNORMAL_UNACCT
, "Abnormal release, channel unacceptable" },
82 { GSM48_RR_CAUSE_ABNORMAL_TIMER
, "Abnormal release, timer expired" },
83 { GSM48_RR_CAUSE_ABNORMAL_NOACT
, "Abnormal release, no activity on radio path" },
84 { GSM48_RR_CAUSE_PREMPTIVE_REL
, "Preemptive release" },
85 { GSM48_RR_CAUSE_HNDOVER_IMP
, "Handover impossible, timing advance out of range" },
86 { GSM48_RR_CAUSE_CHAN_MODE_UNACCT
, "Channel mode unacceptable" },
87 { GSM48_RR_CAUSE_FREQ_NOT_IMPL
, "Frequency not implemented" },
88 { GSM48_RR_CAUSE_CALL_CLEARED
, "Call already cleared" },
89 { GSM48_RR_CAUSE_SEMANT_INCORR
, "Semantically incorrect message" },
90 { GSM48_RR_CAUSE_INVALID_MAND_INF
, "Invalid mandatory information" },
91 { GSM48_RR_CAUSE_MSG_TYPE_N
, "Message type non-existant or not implemented" },
92 { GSM48_RR_CAUSE_MSG_TYPE_N_COMPAT
, "Message type not compatible with protocol state" },
93 { GSM48_RR_CAUSE_COND_IE_ERROR
, "Conditional IE error" },
94 { GSM48_RR_CAUSE_NO_CELL_ALLOC_A
, "No cell allocation available" },
95 { GSM48_RR_CAUSE_PROT_ERROR_UNSPC
, "Protocol error unspecified" },
99 const char *cc_state_names
[32] = {
134 const char *gsm48_cc_msg_names
[0x40] = {
201 static char strbuf
[64];
203 const char *rr_cause_name(uint8_t cause
)
205 return get_value_string(rr_cause_names
, cause
);
208 static void to_bcd(uint8_t *bcd
, uint16_t val
)
218 void gsm48_generate_lai(struct gsm48_loc_area_id
*lai48
, uint16_t mcc
,
219 uint16_t mnc
, uint16_t lac
)
224 lai48
->digits
[0] = bcd
[0] | (bcd
[1] << 4);
225 lai48
->digits
[1] = bcd
[2];
228 /* FIXME: do we need three-digit MNC? See Table 10.5.3 */
230 lai48
->digits
[1] |= bcd
[2] << 4;
231 lai48
->digits
[2] = bcd
[0] | (bcd
[1] << 4);
233 lai48
->digits
[1] |= 0xf << 4;
234 lai48
->digits
[2] = bcd
[1] | (bcd
[2] << 4);
237 lai48
->lac
= htons(lac
);
240 int gsm48_generate_mid_from_tmsi(uint8_t *buf
, uint32_t tmsi
)
242 uint32_t *tptr
= (uint32_t *) &buf
[3];
244 buf
[0] = GSM48_IE_MOBILE_ID
;
245 buf
[1] = GSM48_TMSI_LEN
;
246 buf
[2] = 0xf0 | GSM_MI_TYPE_TMSI
;
252 int gsm48_generate_mid_from_imsi(uint8_t *buf
, const char *imsi
)
254 unsigned int length
= strlen(imsi
), i
, off
= 0;
255 uint8_t odd
= (length
& 0x1) == 1;
257 buf
[0] = GSM48_IE_MOBILE_ID
;
258 buf
[2] = char2bcd(imsi
[0]) << 4 | GSM_MI_TYPE_IMSI
| (odd
<< 3);
260 /* if the length is even we will fill half of the last octet */
262 buf
[1] = (length
+ 1) >> 1;
264 buf
[1] = (length
+ 2) >> 1;
266 for (i
= 1; i
< buf
[1]; ++i
) {
267 uint8_t lower
, upper
;
269 lower
= char2bcd(imsi
[++off
]);
270 if (!odd
&& off
+ 1 == length
)
273 upper
= char2bcd(imsi
[++off
]) & 0x0f;
275 buf
[2 + i
] = (upper
<< 4) | lower
;