Пример #1
0
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;
	}
}
Пример #2
0
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];
		}
	}
}
Пример #3
0
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;
	}
Пример #4
0
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;
}