/* 10.3.4 */ static int gsm_plmnsel_decode(struct osim_decoded_data *dd, const struct osim_file_desc *desc, int len, uint8_t *data) { int i, n_plmn = len / 3; if (n_plmn < 1) return -EINVAL; for (i = 0; i < n_plmn; i++) { uint8_t *cur = data + 3*i; struct osim_decoded_element *elem, *mcc, *mnc; uint8_t ra_buf[6]; struct gprs_ra_id ra_id; memset(ra_buf, 0, sizeof(ra_buf)); memcpy(ra_buf, cur, 3); gsm48_parse_ra(&ra_id, ra_buf); elem = element_alloc(dd, "PLMN", ELEM_T_GROUP, ELEM_REPR_NONE); mcc = element_alloc_sub(elem, "MCC", ELEM_T_UINT16, ELEM_REPR_DEC); mcc->u.u16 = ra_id.mcc; mnc = element_alloc_sub(elem, "MNC", ELEM_T_UINT16, ELEM_REPR_DEC); mnc->u.u16 = ra_id.mnc; } return 0; }
static inline void check_ra(const struct gprs_ra_id *raid) { struct gsm48_ra_id ra; struct gprs_ra_id raid0 = { .mnc = 0, .mcc = 0, .lac = 0, .rac = 0, }; gsm48_encode_ra(&ra, raid); printf("Constructed RA:\n"); gsm48_parse_ra(&raid0, (const uint8_t *)&ra); dump_ra(raid); printf("MCC+MNC in BCD: %s\n", osmo_hexdump(ra.digits, sizeof(ra.digits))); dump_ra(&raid0); printf("RA test..."); if (raid->mnc != raid0.mnc || raid->mcc != raid0.mcc || raid->lac != raid0.lac || raid->rac != raid0.rac || (raid->mnc_3_digits || raid->mnc > 99) != raid0.mnc_3_digits) printf("FAIL\n"); else printf("passed\n"); } static inline void check_lai(const struct gprs_ra_id *raid) { int rc; struct gsm48_loc_area_id lai = {}; struct gprs_ra_id decoded = {}; struct gprs_ra_id _laid = *raid; struct gprs_ra_id *laid = &_laid; laid->rac = 0; printf("- gsm48_generate_lai() from "); dump_ra(laid); gsm48_generate_lai(&lai, laid->mcc, laid->mnc, laid->lac); printf(" Encoded %s\n", osmo_hexdump((unsigned char*)&lai, sizeof(lai))); rc = gsm48_decode_lai(&lai, &decoded.mcc, &decoded.mnc, &decoded.lac); if (rc) { printf(" gsm48_decode_lai() returned %d --> FAIL\n", rc); return; } printf(" gsm48_decode_lai() gives "); dump_ra(&decoded); if (decoded.mcc == laid->mcc && decoded.mnc == laid->mnc && decoded.lac == laid->lac) printf(" passed\n"); else printf(" FAIL\n"); }
static void gbprox_vty_print_peer(struct vty *vty, struct gbproxy_peer *peer) { struct gprs_ra_id raid; gsm48_parse_ra(&raid, peer->ra); vty_out(vty, "NSEI %5u, PTP-BVCI %5u, " "RAI %u-%u-%u-%u", peer->nsei, peer->bvci, raid.mcc, raid.mnc, raid.lac, raid.rac); if (peer->blocked) vty_out(vty, " [BVC-BLOCKED]"); vty_out(vty, "%s", VTY_NEWLINE); }
void gprs_gb_log_parse_context(struct gprs_gb_parse_context *parse_ctx, const char *default_msg_name) { const char *msg_name = default_msg_name; const char *sep = ""; if (!parse_ctx->tlli_enc && !parse_ctx->ptmsi_enc && !parse_ctx->new_ptmsi_enc && !parse_ctx->imsi) return; if (parse_ctx->llc_msg_name) msg_name = parse_ctx->llc_msg_name; LOGP(DGPRS, LOGL_DEBUG, "%s: Got", msg_name); if (parse_ctx->tlli_enc) { LOGP(DGPRS, LOGL_DEBUG, "%s TLLI %08x", sep, parse_ctx->tlli); sep = ","; } if (parse_ctx->old_tlli_enc) { LOGP(DGPRS, LOGL_DEBUG, "%s old TLLI %02x%02x%02x%02x", sep, parse_ctx->old_tlli_enc[0], parse_ctx->old_tlli_enc[1], parse_ctx->old_tlli_enc[2], parse_ctx->old_tlli_enc[3]); sep = ","; } if (parse_ctx->bssgp_raid_enc) { struct gprs_ra_id raid; gsm48_parse_ra(&raid, parse_ctx->bssgp_raid_enc); LOGP(DGPRS, LOGL_DEBUG, "%s BSSGP RAID %u-%u-%u-%u", sep, raid.mcc, raid.mnc, raid.lac, raid.rac); sep = ","; } if (parse_ctx->raid_enc) { struct gprs_ra_id raid; gsm48_parse_ra(&raid, parse_ctx->raid_enc); LOGP(DGPRS, LOGL_DEBUG, "%s RAID %u-%u-%u-%u", sep, raid.mcc, raid.mnc, raid.lac, raid.rac); sep = ","; } if (parse_ctx->old_raid_enc) { struct gprs_ra_id raid; gsm48_parse_ra(&raid, parse_ctx->old_raid_enc); LOGP(DGPRS, LOGL_DEBUG, "%s old RAID %u-%u-%u-%u", sep, raid.mcc, raid.mnc, raid.lac, raid.rac); sep = ","; } if (parse_ctx->ptmsi_enc) { uint32_t ptmsi = GSM_RESERVED_TMSI; int ok; ok = gprs_parse_mi_tmsi(parse_ctx->ptmsi_enc, GSM48_TMSI_LEN, &ptmsi); LOGP(DGPRS, LOGL_DEBUG, "%s PTMSI %08x%s", sep, ptmsi, ok ? "" : " (parse error)"); sep = ","; } if (parse_ctx->new_ptmsi_enc) { uint32_t new_ptmsi = GSM_RESERVED_TMSI; int ok; ok = gprs_parse_mi_tmsi(parse_ctx->new_ptmsi_enc, GSM48_TMSI_LEN, &new_ptmsi); LOGP(DGPRS, LOGL_DEBUG, "%s new PTMSI %08x%s", sep, new_ptmsi, ok ? "" : " (parse error)"); sep = ","; } if (parse_ctx->imsi) { char mi_buf[200]; mi_buf[0] = '\0'; gsm48_mi_to_string(mi_buf, sizeof(mi_buf), parse_ctx->imsi, parse_ctx->imsi_len); LOGP(DGPRS, LOGL_DEBUG, "%s IMSI %s", sep, mi_buf); sep = ","; } if (parse_ctx->invalidate_tlli) { LOGP(DGPRS, LOGL_DEBUG, "%s invalidate", sep); sep = ","; } LOGP(DGPRS, LOGL_DEBUG, "\n"); }
/* Parse a single GMM-PAGING.req to a given NSEI/NS-BVCI */ int bssgp_rx_paging(struct bssgp_paging_info *pinfo, struct msgb *msg) { struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *) msgb_bssgph(msg); struct tlv_parsed tp; uint8_t ra[6]; int rc, data_len; memset(ra, 0, sizeof(ra)); data_len = msgb_bssgp_len(msg) - sizeof(*bgph); rc = bssgp_tlv_parse(&tp, bgph->data, data_len); if (rc < 0) goto err_mand_ie; switch (bgph->pdu_type) { case BSSGP_PDUT_PAGING_PS: pinfo->mode = BSSGP_PAGING_PS; break; case BSSGP_PDUT_PAGING_CS: pinfo->mode = BSSGP_PAGING_CS; break; default: return -EINVAL; } /* IMSI */ if (!TLVP_PRESENT(&tp, BSSGP_IE_IMSI)) goto err_mand_ie; if (!pinfo->imsi) pinfo->imsi = talloc_zero_size(pinfo, GSM_IMSI_LENGTH); gsm48_mi_to_string(pinfo->imsi, GSM_IMSI_LENGTH, TLVP_VAL(&tp, BSSGP_IE_IMSI), TLVP_LEN(&tp, BSSGP_IE_IMSI)); /* DRX Parameters */ if (!TLVP_PRESENT(&tp, BSSGP_IE_DRX_PARAMS)) goto err_mand_ie; pinfo->drx_params = ntohs(*(uint16_t *)TLVP_VAL(&tp, BSSGP_IE_DRX_PARAMS)); /* Scope */ if (TLVP_PRESENT(&tp, BSSGP_IE_BSS_AREA_ID)) { pinfo->scope = BSSGP_PAGING_BSS_AREA; } else if (TLVP_PRESENT(&tp, BSSGP_IE_LOCATION_AREA)) { pinfo->scope = BSSGP_PAGING_LOCATION_AREA; memcpy(ra, TLVP_VAL(&tp, BSSGP_IE_LOCATION_AREA), TLVP_LEN(&tp, BSSGP_IE_LOCATION_AREA)); gsm48_parse_ra(&pinfo->raid, ra); } else if (TLVP_PRESENT(&tp, BSSGP_IE_ROUTEING_AREA)) { pinfo->scope = BSSGP_PAGING_ROUTEING_AREA; memcpy(ra, TLVP_VAL(&tp, BSSGP_IE_ROUTEING_AREA), TLVP_LEN(&tp, BSSGP_IE_ROUTEING_AREA)); gsm48_parse_ra(&pinfo->raid, ra); } else if (TLVP_PRESENT(&tp, BSSGP_IE_BVCI)) { pinfo->scope = BSSGP_PAGING_BVCI; pinfo->bvci = ntohs(*(uint16_t *)TLVP_VAL(&tp, BSSGP_IE_BVCI)); } else return -EINVAL; /* QoS profile mandatory for PS */ if (pinfo->mode == BSSGP_PAGING_PS) { if (!TLVP_PRESENT(&tp, BSSGP_IE_QOS_PROFILE)) goto err_cond_ie; if (TLVP_LEN(&tp, BSSGP_IE_QOS_PROFILE) < 3) goto err; memcpy(&pinfo->qos, TLVP_VAL(&tp, BSSGP_IE_QOS_PROFILE), 3); } /* Optional (P-)TMSI */ if (TLVP_PRESENT(&tp, BSSGP_IE_TMSI) && TLVP_LEN(&tp, BSSGP_IE_TMSI) >= 4) if (!pinfo->ptmsi) pinfo->ptmsi = talloc_zero_size(pinfo, sizeof(uint32_t)); *(pinfo->ptmsi) = ntohl(*(uint32_t *) TLVP_VAL(&tp, BSSGP_IE_TMSI)); return 0; err_mand_ie: err_cond_ie: err: /* FIXME */ return 0; }
void gprs_gb_log_parse_context(int log_level, struct gprs_gb_parse_context *parse_ctx, const char *default_msg_name) { const char *msg_name; const char *sep = ""; if (!parse_ctx->tlli_enc && !parse_ctx->ptmsi_enc && !parse_ctx->new_ptmsi_enc && !parse_ctx->bssgp_ptmsi_enc && !parse_ctx->imsi) return; msg_name = gprs_gb_message_name(parse_ctx, default_msg_name); if (parse_ctx->llc_msg_name) msg_name = parse_ctx->llc_msg_name; LOGP(DGPRS, log_level, "%s: Got", msg_name); if (parse_ctx->tlli_enc) { LOGPC(DGPRS, log_level, "%s TLLI %08x", sep, parse_ctx->tlli); sep = ","; } if (parse_ctx->old_tlli_enc) { LOGPC(DGPRS, log_level, "%s old TLLI %02x%02x%02x%02x", sep, parse_ctx->old_tlli_enc[0], parse_ctx->old_tlli_enc[1], parse_ctx->old_tlli_enc[2], parse_ctx->old_tlli_enc[3]); sep = ","; } if (parse_ctx->bssgp_raid_enc) { struct gprs_ra_id raid; gsm48_parse_ra(&raid, parse_ctx->bssgp_raid_enc); LOGPC(DGPRS, log_level, "%s BSSGP RAID %u-%u-%u-%u", sep, raid.mcc, raid.mnc, raid.lac, raid.rac); sep = ","; } if (parse_ctx->raid_enc) { struct gprs_ra_id raid; gsm48_parse_ra(&raid, parse_ctx->raid_enc); LOGPC(DGPRS, log_level, "%s RAID %u-%u-%u-%u", sep, raid.mcc, raid.mnc, raid.lac, raid.rac); sep = ","; } if (parse_ctx->old_raid_enc) { struct gprs_ra_id raid; gsm48_parse_ra(&raid, parse_ctx->old_raid_enc); LOGPC(DGPRS, log_level, "%s old RAID %u-%u-%u-%u", sep, raid.mcc, raid.mnc, raid.lac, raid.rac); sep = ","; } if (parse_ctx->bssgp_ptmsi_enc) { uint32_t ptmsi = GSM_RESERVED_TMSI; gprs_parse_tmsi(parse_ctx->bssgp_ptmsi_enc, &ptmsi); LOGPC(DGPRS, log_level, "%s BSSGP PTMSI %08x", sep, ptmsi); sep = ","; } if (parse_ctx->ptmsi_enc) { uint32_t ptmsi = GSM_RESERVED_TMSI; gprs_parse_tmsi(parse_ctx->ptmsi_enc, &ptmsi); LOGPC(DGPRS, log_level, "%s PTMSI %08x", sep, ptmsi); sep = ","; } if (parse_ctx->new_ptmsi_enc) { uint32_t new_ptmsi = GSM_RESERVED_TMSI; gprs_parse_tmsi(parse_ctx->new_ptmsi_enc, &new_ptmsi); LOGPC(DGPRS, log_level, "%s new PTMSI %08x", sep, new_ptmsi); sep = ","; } if (parse_ctx->imsi) { char mi_buf[200]; mi_buf[0] = '\0'; gsm48_mi_to_string(mi_buf, sizeof(mi_buf), parse_ctx->imsi, parse_ctx->imsi_len); LOGPC(DGPRS, log_level, "%s IMSI %s", sep, mi_buf); sep = ","; } if (parse_ctx->invalidate_tlli) { LOGPC(DGPRS, log_level, "%s invalidate", sep); sep = ","; } if (parse_ctx->await_reattach) { LOGPC(DGPRS, log_level, "%s re-attach", sep); sep = ","; } LOGPC(DGPRS, log_level, "\n"); }