void handle_mi(struct session_info *s, uint8_t *data, uint8_t len, uint8_t new_tmsi) { char tmsi_str[9]; uint8_t mi_type; if (len > GSM48_MI_SIZE) { SET_MSG_INFO(s, "FAILED SANITY CHECKS (MI_LEN)"); return; } mi_type = data[0] & GSM_MI_TYPE_MASK; switch (mi_type) { case GSM_MI_TYPE_NONE: break; case GSM_MI_TYPE_IMSI: bcd2str(data, s->imsi, len*2, 1); APPEND_MSG_INFO(s, ", IMSI %s", s->imsi); s->use_imsi = 1; break; case GSM_MI_TYPE_IMEI: case GSM_MI_TYPE_IMEISV: bcd2str(data, s->imei, 15, 1); APPEND_MSG_INFO(s, ", IMEI %s", s->imei); break; case GSM_MI_TYPE_TMSI: hex_bin2str(&data[1], tmsi_str, 4); tmsi_str[8] = 0; assert(s->new_msg); APPEND_MSG_INFO(s, ", TMSI %s", tmsi_str); if (new_tmsi) { if (!not_zero(s->new_tmsi, 4)) { memcpy(s->new_tmsi, &data[1], 4); } } else { if (!not_zero(s->old_tmsi, 4)) { memcpy(s->old_tmsi, &data[1], 4); s->use_tmsi = 1; } } break; default: SET_MSG_INFO(s, "FAILED SANITY CHECKS (MI_TYPE)"); return; } }
void lp_min_lin_rat(int degen, FLOAT cw_vec[2], FLOAT ccw_vec[2], FLOAT n_vec[2], FLOAT d_vec[2], FLOAT opt[2]) { FLOAT d_cw, d_ccw, n_cw, n_ccw; /* linear rational function case */ d_cw = dot2(cw_vec,d_vec); d_ccw = dot2(ccw_vec,d_vec); n_cw = dot2(cw_vec,n_vec); n_ccw = dot2(ccw_vec,n_vec); if(degen) { /* if degenerate simply compare values */ if(n_cw/d_cw < n_ccw/d_ccw) { opt[0] = cw_vec[0]; opt[1] = cw_vec[1]; } else { opt[0] = ccw_vec[0]; opt[1] = ccw_vec[1]; } /* check that the clock-wise and counter clockwise bounds are not near a poles */ } else if(not_zero(d_cw) && not_zero(d_ccw)) { /* the valid region does not contain a poles */ if(d_cw*d_ccw > 0.0) { /* find which end has the minimum value */ if(n_cw/d_cw < n_ccw/d_ccw) { opt[0] = cw_vec[0]; opt[1] = cw_vec[1]; } else { opt[0] = ccw_vec[0]; opt[1] = ccw_vec[1]; } } else { /* the valid region does contain a poles */ if(d_cw > 0.0) { opt[0] = -d_vec[1]; opt[1] = d_vec[0]; } else { opt[0] = d_vec[1]; opt[1] = -d_vec[0]; } } } else if(not_zero(d_cw)) { /* the counter clockwise bound is near a pole */ if(n_ccw*d_cw > 0.0) { /* counter clockwise bound is a positive pole */ opt[0] = cw_vec[0]; opt[1] = cw_vec[1]; } else { /* counter clockwise bound is a negative pole */ opt[0] = ccw_vec[0]; opt[1] = ccw_vec[1]; } } else if(not_zero(d_ccw)) { /* the clockwise bound is near a pole */ if(n_cw*d_ccw > 2*EPS) { /* clockwise bound is at a positive pole */ opt[0] = ccw_vec[0]; opt[1] = ccw_vec[1]; } else { /* clockwise bound is at a negative pole */ opt[0] = cw_vec[0]; opt[1] = cw_vec[1]; } } else { /* both bounds are near poles */ if(cross2(d_vec,n_vec) > 0.0) { opt[0] = cw_vec[0]; opt[1] = cw_vec[1]; } else { opt[0] = ccw_vec[0]; opt[1] = ccw_vec[1]; } } }
void handle_rr(struct session_info *s, struct gsm48_hdr *dtap, unsigned len, uint32_t fn) { struct gsm48_system_information_type_6 *si6; struct tlv_parsed tp; s->rat = RAT_GSM; assert(s->new_msg); if (!len) { return; } switch (dtap->msg_type) { case GSM48_MT_RR_SYSINFO_1: SET_MSG_INFO(s, "SYSTEM INFO 1"); handle_sysinfo(s, dtap, len); break; case GSM48_MT_RR_SYSINFO_2: SET_MSG_INFO(s, "SYSTEM INFO 2"); handle_sysinfo(s, dtap, len); break; case GSM48_MT_RR_SYSINFO_2bis: SET_MSG_INFO(s, "SYSTEM INFO 2bis"); handle_sysinfo(s, dtap, len); break; case GSM48_MT_RR_SYSINFO_2ter: SET_MSG_INFO(s, "SYSTEM INFO 2ter"); handle_sysinfo(s, dtap, len); break; case GSM48_MT_RR_SYSINFO_2quater: SET_MSG_INFO(s, "SYSTEM INFO 2quater"); handle_sysinfo(s, dtap, len); break; case GSM48_MT_RR_SYSINFO_3: SET_MSG_INFO(s, "SYSTEM INFO 3"); handle_sysinfo(s, dtap, len); break; case GSM48_MT_RR_SYSINFO_4: SET_MSG_INFO(s, "SYSTEM INFO 4"); handle_sysinfo(s, dtap, len); break; case GSM48_MT_RR_SYSINFO_5: SET_MSG_INFO(s, "SYSTEM INFO 5"); rand_check((uint8_t *)dtap, 18, &s->si5, s->cipher); handle_sysinfo(s, dtap, len); break; case GSM48_MT_RR_SYSINFO_5bis: SET_MSG_INFO(s, "SYSTEM INFO 5bis"); rand_check((uint8_t *)dtap, 18, &s->si5bis, s->cipher); handle_sysinfo(s, dtap, len); break; case GSM48_MT_RR_SYSINFO_5ter: SET_MSG_INFO(s, "SYSTEM INFO 5ter"); rand_check((uint8_t *)dtap, 18, &s->si5ter, s->cipher); handle_sysinfo(s, dtap, len); break; case GSM48_MT_RR_SYSINFO_6: SET_MSG_INFO(s, "SYSTEM INFO 6"); rand_check((uint8_t *)dtap, 18, &s->si6, s->cipher); si6 = (struct gsm48_system_information_type_6 *) dtap; handle_lai(s, (uint8_t*)&si6->lai, htons(si6->cell_identity)); handle_sysinfo(s, dtap, len); break; case GSM48_MT_RR_SYSINFO_13: SET_MSG_INFO(s, "SYSTEM INFO 13"); handle_sysinfo(s, dtap, len); break; case GSM48_MT_RR_CHAN_REL: SET_MSG_INFO(s, "CHANNEL RELEASE"); if (s->cipher && !s->fc.enc_rand) s->fc.predict++; s->release = 1; s->rr_cause = dtap->data[0]; if ((len > 3) && ((dtap->data[1] & 0xf0) == 0xc0)) s->have_gprs = 1; session_reset(&s[0], 0); if (auto_reset) { s[1].new_msg = NULL; } break; case GSM48_MT_RR_CLSM_ENQ: SET_MSG_INFO(s, "CLASSMARK ENQUIRY"); break; case GSM48_MT_RR_MEAS_REP: SET_MSG_INFO(s, "MEASUREMENT REPORT"); break; case GSM48_MT_RR_CLSM_CHG: SET_MSG_INFO(s, "CLASSMARK CHANGE"); handle_classmark(s, &dtap->data[1], 2); break; case GSM48_MT_RR_PAG_REQ_1: SET_MSG_INFO(s, "PAGING REQ 1"); handle_paging1(dtap, len); break; case GSM48_MT_RR_PAG_REQ_2: SET_MSG_INFO(s, "PAGING REQ 2"); handle_paging2(dtap, len); break; case GSM48_MT_RR_PAG_REQ_3: SET_MSG_INFO(s, "PAGING REQ 3"); handle_paging3(); break; case GSM48_MT_RR_IMM_ASS: SET_MSG_INFO(s, "IMM ASSIGNMENT"); break; case GSM48_MT_RR_IMM_ASS_EXT: SET_MSG_INFO(s, "IMM ASSIGNMENT EXT"); break; case GSM48_MT_RR_IMM_ASS_REJ: SET_MSG_INFO(s, "IMM ASSIGNMENT REJECT"); break; case GSM48_MT_RR_PAG_RESP: session_reset(s, 1); SET_MSG_INFO(s, "PAGING RESPONSE"); handle_pag_resp(s, dtap->data); break; case GSM48_MT_RR_HANDO_CMD: SET_MSG_INFO(s, "HANDOVER COMMAND"); parse_assignment(dtap, len, s->cell_arfcns, &s->ga); s->handover = 1; s->use_jump = 2; break; case GSM48_MT_RR_HANDO_COMPL: SET_MSG_INFO(s, "HANDOVER COMPLETE"); break; case GSM48_MT_RR_ASS_CMD: SET_MSG_INFO(s, "ASSIGNMENT COMMAND"); if ((s->fc.enc-s->fc.enc_null-s->fc.enc_si) == 1) s->forced_ho = 1; parse_assignment(dtap, len, s->cell_arfcns, &s->ga); s->assignment = 1; s->use_jump = 1; break; case GSM48_MT_RR_ASS_COMPL: SET_MSG_INFO(s, "ASSIGNMENT COMPLETE"); s->assign_complete = 1; break; case GSM48_MT_RR_CIPH_M_COMPL: SET_MSG_INFO(s, "CIPHER MODE COMPLETE"); if (s->cipher_missing < 0) { s->cipher_missing = 0; } else { s->cipher_missing = 1; } if (!s->cm_comp_first_fn) { if (fn) { s->cm_comp_first_fn = fn; } else { s->cm_comp_first_fn = GSM_MAX_FN; } } if (fn) { s->cm_comp_last_fn = fn; } else { s->cm_comp_last_fn = GSM_MAX_FN; } s->cm_comp_count++; if (dtap->data[0] == 0x2b) return; /* get IMEISV */ tlv_parse(&tp, &gsm48_rr_att_tlvdef, dtap->data, len-2, 0, 0); if (TLVP_PRESENT(&tp, GSM48_IE_MOBILE_ID)) { uint8_t *v = (uint8_t *) TLVP_VAL(&tp, GSM48_IE_MOBILE_ID); handle_mi(s, &v[1], v[0], 0); s->cmc_imeisv = 1; } break; case GSM48_MT_RR_GPRS_SUSP_REQ: SET_MSG_INFO(s, "GPRS SUSPEND"); s->have_gprs = 1; //tlli //rai (lai+rac) break; case GSM48_MT_RR_CIPH_M_CMD: if (!s->cm_cmd_fn) { if (fn) { s->cm_cmd_fn = fn; } else { s->cm_cmd_fn = GSM_MAX_FN; } } if (dtap->data[0] & 1) { s->cipher = 1 + ((dtap->data[0]>>1) & 7); if (!not_zero(s->key, 8)) s->decoded = 0; } SET_MSG_INFO(s, "CIPHER MODE COMMAND, A5/%u", s->cipher); if (dtap->data[0] & 0x10) { s->cmc_imeisv = 1; if (s->cipher && !s->fc.enc_rand) s->fc.predict++; } s->cipher_missing = -1; break; case 0x60: SET_MSG_INFO(s, "UTRAN CLASSMARK"); break; default: SET_MSG_INFO(s, "UNKNOWN RR (%02x)", dtap->msg_type); s->unknown = 1; }
int process_tch(struct session_info *s, struct l1ctl_burst_ind *bi, uint8_t *msg) { int ret, ul; uint16_t arfcn; uint32_t fn; uint8_t conv_data[CONV_SIZE]; struct burst_buf *bb; arfcn = ntohs(bi->band_arfcn); ul = !!(arfcn & ARFCN_UPLINK); fn = ntohl(bi->frame_nr); bb = &s->facch[ul]; /* append data to message buffer */ expand_msb(bi->bits, bb->data + bb->count * 114, 114); if(not_zero(s->key, 8)) { int i; uint8_t ks[114]; if (ul) osmo_a5(1, s->key, fn, 0, ks); else osmo_a5(1, s->key, fn, ks, 0); for (i=0; i<114; i++) { bb->data[bb->count * 114 + i] ^= ks[i]; } } // not used bb->sbit[bb->count * 2 + 0] = !!(bi->bits[14] & 0x10); bb->sbit[bb->count * 2 + 1] = !!(bi->bits[14] & 0x20); bb->snr[bb->count] = bi->snr; bb->rxl[bb->count] = bi->rx_level; /* check burst flags */ switch (bi->bits[14] & 0x30) { case 0x00: /* TCH + TCH */ //printf("TCH\n"); /* voice blocks or flags corrupted */ if (bb->count) { /* already had errors? */ if (bb->errors < 2) { /* give a try and record error */ bb->count++; bb->errors++; } else { /* discard all bursts in buffer */ bb->count = 0; bb->errors = 0; return 0; } } else { /* process voice */ return 0; } break; case 0x20: /* FACCH + TCH */ //printf("FACCH+TCH\n"); if (bb->count == 0) { /* start burst buffering */ bb->count = 1; } else { /* check how many bursts in buffer */ if (bb->count < 4) { /* all ok, append */ bb->count++; } else { /* severely errored burst, other errors? */ if (bb->errors < 2) { /* give a try and record error */ bb->count++; bb->errors++; } else { /* discard all bursts in buffer */ bb->count = 0; bb->errors = 0; return 0; } } } break; case 0x10: /* TCH + FACCH */ //printf("TCH+FACCH\n"); if (bb->count > 3) { /* all ok, append */ bb->count++; } else { /* severely errored burst, other errors? */ if (bb->errors < 2) { /* give a try and record error */ bb->count++; bb->errors++; } else { /* discard all bursts in buffer */ bb->count = 0; bb->errors = 0; return 0; } } break; case 0x30: /* FACCH + FACCH (or GPRS) */ //printf("FACCH\n"); if (bb->count > 3) { /* probably overlapping FACCHs */ bb->count++; //record a & b facch separately } else { /* overlapping and misaligned? */ bb->count++; bb->errors++; } } /* Return if not enough bursts for a full gsm message */ if (bb->count == 8) { struct radio_message *m; /* try to decode FACCH */ /* de-interleaving */ gsm_deinter_facch(bb->data, conv_data); ret = decode_signalling(conv_data, msg); if (!ret) { /* skip one burst and wait next */ // some circular buffer needed memcpy(bb->data, bb->data + 114, 7 * 114); memcpy(bb->sbit, bb->sbit + 2, 7 * 2); bb->count = 7; bb->errors /= 2; // approximated value return 0; } m = malloc(sizeof(struct radio_message)); memcpy(&m->bb, bb, sizeof(*bb)); m->chan_nr = bi->chan_nr; m->flags = MSG_FACCH|MSG_DECODED; if (s->have_key) m->flags |= MSG_CIPHERED; memcpy(m->msg, msg, 23); m->msg_len = 23; handle_lapdm(s, &s->chan_facch[ul], m->msg, m->msg_len, m->bb.fn[0], ul); net_send_msg(m); /* check overlapping status */ if ((bi->bits[14] & 0x30) == 0x30) { /* start subsequent message processing */ memcpy(bb->data, bb->data + 4 * 114, 4 * 114); memcpy(bb->sbit, bb->sbit + 4 * 2, 4 * 2); bb->count = 4; bb->errors /= 2; // approximated value memset(bb->data + bb->count*114, 0, sizeof(bb->data)/2); } else { /* nothing else in the buffer, reset */ bb->count = 0; bb->errors = 0; memset(bb->data, 0, sizeof(bb->data)); } return 23; } return 0; }