gbproxy: Remove patching, TLLI-tracking and SGSN2 support

Those features were introduced a long time ago for one specific use
case at one specific user, and they are not needed anymore.  They
complicate the code base significantly and are hard to maintain with
all the upcoming modifications regarding SGSN pool supoprt.

Change-Id: Id9cc2e1c63486491ac5bb68876088a615075fde6
diff --git a/src/gbproxy/gb_proxy.c b/src/gbproxy/gb_proxy.c
index 4cf7e41..74f799d 100644
--- a/src/gbproxy/gb_proxy.c
+++ b/src/gbproxy/gb_proxy.c
@@ -82,7 +82,6 @@
 			     uint16_t ns_bvci);
 static int gbprox_relay2sgsn(struct gbproxy_config *cfg, struct msgb *old_msg,
 			     uint16_t ns_bvci, uint16_t sgsn_nsei);
-static void gbproxy_reset_imsi_acquisition(struct gbproxy_link_info* link_info);
 
 static int check_bvc_nsei(struct gbproxy_bvc *bvc, uint16_t nsei)
 {
@@ -106,685 +105,6 @@
 	msgb_pull(msg, strip_len);
 }
 
-/* Transmit Chapter 9.2.10 Identity Request */
-static void gprs_put_identity_req(struct msgb *msg, uint8_t id_type)
-{
-	struct gsm48_hdr *gh;
-
-	id_type &= GSM_MI_TYPE_MASK;
-
-	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
-	gh->proto_discr = GSM48_PDISC_MM_GPRS;
-	gh->msg_type = GSM48_MT_GMM_ID_REQ;
-	gh->data[0] = id_type;
-}
-
-/* Transmit Chapter 9.4.6.2 Detach Accept (mobile originated detach) */
-static void gprs_put_mo_detach_acc(struct msgb *msg)
-{
-	struct gsm48_hdr *gh;
-
-	gh = (struct gsm48_hdr *) msgb_put(msg, sizeof(*gh) + 1);
-	gh->proto_discr = GSM48_PDISC_MM_GPRS;
-	gh->msg_type = GSM48_MT_GMM_DETACH_ACK;
-	gh->data[0] = 0; /* no force to standby */
-}
-
-static void gprs_push_llc_ui(struct msgb *msg,
-			     int is_uplink, unsigned sapi, unsigned nu)
-{
-	const uint8_t e_bit = 0;
-	const uint8_t pm_bit = 1;
-	const uint8_t cr_bit = is_uplink ? 0 : 1;
-	uint8_t *llc;
-	uint8_t *fcs_field;
-	uint32_t fcs;
-
-	nu &= 0x01ff; /* 9 Bit */
-
-	llc = msgb_push(msg, 3);
-	llc[0] = (cr_bit << 6) | (sapi & 0x0f);
-	llc[1] = 0xc0 | (nu >> 6); /* UI frame */
-	llc[2] = (nu << 2) | ((e_bit & 1) << 1) | (pm_bit & 1);
-
-	fcs = gprs_llc_fcs(llc, msgb_length(msg));
-	fcs_field = msgb_put(msg, 3);
-	fcs_field[0] = (uint8_t)(fcs >> 0);
-	fcs_field[1] = (uint8_t)(fcs >> 8);
-	fcs_field[2] = (uint8_t)(fcs >> 16);
-}
-
-static void gprs_push_bssgp_dl_unitdata(struct msgb *msg,
-					uint32_t tlli)
-{
-	struct bssgp_ud_hdr *budh;
-	uint8_t *llc = msgb_data(msg);
-	size_t llc_size = msgb_length(msg);
-	const size_t llc_ie_hdr_size = 3;
-	const uint8_t qos_profile[] = {0x00, 0x50, 0x20}; /* hard-coded */
-	const uint8_t lifetime[] = {0x02, 0x58}; /* 6s hard-coded */
-
-	const size_t bssgp_overhead = sizeof(*budh) +
-		TVLV_GROSS_LEN(sizeof(lifetime)) + llc_ie_hdr_size;
-	uint8_t *ie;
-	uint32_t tlli_be = htonl(tlli);
-
-	budh = (struct bssgp_ud_hdr *)msgb_push(msg, bssgp_overhead);
-
-	budh->pdu_type = BSSGP_PDUT_DL_UNITDATA;
-	memcpy(&budh->tlli, &tlli_be, sizeof(budh->tlli));
-	memcpy(&budh->qos_profile, qos_profile, sizeof(budh->qos_profile));
-
-	ie = budh->data;
-	tvlv_put(ie, BSSGP_IE_PDU_LIFETIME, sizeof(lifetime), lifetime);
-	ie += TVLV_GROSS_LEN(sizeof(lifetime));
-
-	/* Note: Add alignment before the LLC IE if inserting other IE */
-
-	*(ie++) = BSSGP_IE_LLC_PDU;
-	*(ie++) = llc_size / 256;
-	*(ie++) = llc_size % 256;
-
-	OSMO_ASSERT(ie == llc);
-
-	msgb_bssgph(msg) = (uint8_t *)budh;
-	msgb_tlli(msg) = tlli;
-}
-
-/* update bvc according to the BSS message */
-static void gbprox_update_current_raid(uint8_t *raid_enc,
-				       struct gbproxy_bvc *bvc,
-				       const char *log_text)
-{
-	struct gbproxy_patch_state *state = &bvc->patch_state;
-	const struct osmo_plmn_id old_plmn = state->local_plmn;
-	struct gprs_ra_id raid;
-	OSMO_ASSERT(bvc->nse);
-	struct gbproxy_config *cfg = bvc->nse->cfg;
-	OSMO_ASSERT(cfg);
-
-	if (!raid_enc)
-		return;
-
-	gsm48_parse_ra(&raid, raid_enc);
-
-	/* save source side MCC/MNC */
-	if (!cfg->core_plmn.mcc || raid.mcc == cfg->core_plmn.mcc) {
-		state->local_plmn.mcc = 0;
-	} else {
-		state->local_plmn.mcc = raid.mcc;
-	}
-
-	if (!cfg->core_plmn.mnc
-	    || !osmo_mnc_cmp(raid.mnc, raid.mnc_3_digits,
-			     cfg->core_plmn.mnc, cfg->core_plmn.mnc_3_digits)) {
-		state->local_plmn.mnc = 0;
-		state->local_plmn.mnc_3_digits = false;
-	} else {
-		state->local_plmn.mnc = raid.mnc;
-		state->local_plmn.mnc_3_digits = raid.mnc_3_digits;
-	}
-
-	if (osmo_plmn_cmp(&old_plmn, &state->local_plmn))
-		LOGPBVC(bvc, LOGL_NOTICE,
-		     "Patching RAID %sactivated, msg: %s, "
-		     "local: %s, core: %s\n",
-		     state->local_plmn.mcc || state->local_plmn.mnc ?
-		     "" : "de",
-		     log_text,
-		     osmo_plmn_name(&state->local_plmn),
-		     osmo_plmn_name2(&cfg->core_plmn));
-}
-
-uint32_t gbproxy_make_bss_ptmsi(struct gbproxy_bvc *bvc,
-				uint32_t sgsn_ptmsi)
-{
-	uint32_t bss_ptmsi;
-	int max_retries = 23, rc = 0;
-	if (!bvc->nse->cfg->patch_ptmsi) {
-		bss_ptmsi = sgsn_ptmsi;
-	} else {
-		do {
-			rc = osmo_get_rand_id((uint8_t *) &bss_ptmsi, sizeof(bss_ptmsi));
-			if (rc < 0) {
-				bss_ptmsi = GSM_RESERVED_TMSI;
-				break;
-			}
-
-			bss_ptmsi = bss_ptmsi | GSM23003_TMSI_SGSN_MASK;
-
-			if (gbproxy_link_info_by_ptmsi(bvc, bss_ptmsi))
-				bss_ptmsi = GSM_RESERVED_TMSI;
-		} while (bss_ptmsi == GSM_RESERVED_TMSI && max_retries--);
-	}
-
-	if (bss_ptmsi == GSM_RESERVED_TMSI)
-		LOGPBVC(bvc, LOGL_ERROR, "Failed to allocate a BSS P-TMSI: %d (%s)\n", rc, strerror(-rc));
-
-	return bss_ptmsi;
-}
-
-uint32_t gbproxy_make_sgsn_tlli(struct gbproxy_bvc *bvc,
-				struct gbproxy_link_info *link_info,
-				uint32_t bss_tlli)
-{
-	uint32_t sgsn_tlli;
-	int max_retries = 23, rc = 0;
-	if (!bvc->nse->cfg->patch_ptmsi) {
-		sgsn_tlli = bss_tlli;
-	} else if (link_info->sgsn_tlli.ptmsi != GSM_RESERVED_TMSI &&
-		   gprs_tlli_type(bss_tlli) == TLLI_FOREIGN) {
-		sgsn_tlli = gprs_tmsi2tlli(link_info->sgsn_tlli.ptmsi,
-					   TLLI_FOREIGN);
-	} else if (link_info->sgsn_tlli.ptmsi != GSM_RESERVED_TMSI &&
-		   gprs_tlli_type(bss_tlli) == TLLI_LOCAL) {
-		sgsn_tlli = gprs_tmsi2tlli(link_info->sgsn_tlli.ptmsi,
-					   TLLI_LOCAL);
-	} else {
-		do {
-			/* create random TLLI, 0b01111xxx... */
-			rc = osmo_get_rand_id((uint8_t *) &sgsn_tlli, sizeof(sgsn_tlli));
-			if (rc < 0) {
-				sgsn_tlli = 0;
-				break;
-			}
-
-			sgsn_tlli = (sgsn_tlli & 0x7fffffff) | 0x78000000;
-
-			if (gbproxy_link_info_by_any_sgsn_tlli(bvc, sgsn_tlli))
-				sgsn_tlli = 0;
-		} while (!sgsn_tlli && max_retries--);
-	}
-
-	if (!sgsn_tlli)
-		LOGPBVC(bvc, LOGL_ERROR, "Failed to allocate an SGSN TLLI: %d (%s)\n", rc, strerror(-rc));
-
-	return sgsn_tlli;
-}
-
-void gbproxy_reset_link(struct gbproxy_link_info *link_info)
-{
-	gbproxy_reset_imsi_acquisition(link_info);
-}
-
-/* Returns != 0 iff IMSI acquisition was in progress */
-static int gbproxy_restart_imsi_acquisition(struct gbproxy_link_info* link_info)
-{
-	int in_progress = 0;
-	if (!link_info)
-		return 0;
-
-	if (link_info->imsi_acq_pending)
-		in_progress = 1;
-
-	gbproxy_link_info_discard_messages(link_info);
-	link_info->imsi_acq_pending = false;
-
-	return in_progress;
-}
-
-static void gbproxy_reset_imsi_acquisition(struct gbproxy_link_info* link_info)
-{
-	gbproxy_restart_imsi_acquisition(link_info);
-	link_info->vu_gen_tx_bss = GBPROXY_INIT_VU_GEN_TX;
-}
-
-/* Got identity response with IMSI, assuming the request had
- * been generated by the gbproxy */
-static int gbproxy_flush_stored_messages(struct gbproxy_bvc *bvc,
-					  time_t now,
-					  struct gbproxy_link_info* link_info)
-{
-	int rc;
-	struct msgb *stored_msg;
-	OSMO_ASSERT(bvc);
-	OSMO_ASSERT(bvc->nse);
-	struct gbproxy_config *cfg = bvc->nse->cfg;
-	OSMO_ASSERT(cfg);
-
-	/* Patch and flush stored messages towards the SGSN */
-	while ((stored_msg = msgb_dequeue_count(&link_info->stored_msgs,
-						&link_info->stored_msgs_len))) {
-		struct gprs_gb_parse_context tmp_parse_ctx = {0};
-		tmp_parse_ctx.to_bss = 0;
-		tmp_parse_ctx.peer_nsei = msgb_nsei(stored_msg);
-		int len_change = 0;
-
-		gprs_gb_parse_bssgp(msgb_bssgph(stored_msg),
-				    msgb_bssgp_len(stored_msg),
-				    &tmp_parse_ctx);
-		gbproxy_patch_bssgp(stored_msg, msgb_bssgph(stored_msg),
-				    msgb_bssgp_len(stored_msg),
-				    bvc, link_info, &len_change,
-				    &tmp_parse_ctx);
-
-		rc = gbproxy_update_link_state_after(bvc, link_info, now,
-				&tmp_parse_ctx);
-		if (rc == 1) {
-			LOGPBVC_CAT(bvc, DLLC, LOGL_NOTICE, "link_info deleted while flushing stored messages\n");
-			msgb_free(stored_msg);
-			return -1;
-		}
-
-		rc = gbprox_relay2sgsn(cfg, stored_msg,
-				       msgb_bvci(stored_msg), link_info->sgsn_nsei);
-
-		if (rc < 0)
-			LOGPBVC_CAT(bvc, DLLC, LOGL_ERROR,
-			     "failed to send stored message "
-			     "(%s)\n",
-			     tmp_parse_ctx.llc_msg_name ?
-			     tmp_parse_ctx.llc_msg_name : "BSSGP");
-		msgb_free(stored_msg);
-	}
-
-	return 0;
-}
-
-static int gbproxy_gsm48_to_bvc(struct gbproxy_bvc *bvc,
-				 struct gbproxy_link_info* link_info,
-				 uint16_t bvci,
-				 struct msgb *msg /* Takes msg ownership */)
-{
-	int rc;
-
-	/* Workaround to avoid N(U) collisions and to enable a restart
-	 * of the IMSI acquisition procedure. This will work unless the
-	 * SGSN has an initial V(UT) within [256-32, 256+n_retries]
-	 * (see GSM 04.64, 8.4.2). */
-	gprs_push_llc_ui(msg, 0, GPRS_SAPI_GMM, link_info->vu_gen_tx_bss);
-	link_info->vu_gen_tx_bss = (link_info->vu_gen_tx_bss + 1) % 512;
-
-	gprs_push_bssgp_dl_unitdata(msg, link_info->tlli.current);
-	msg->l3h = msg->data;
-
-	rc = gbprox_relay2peer(msg, bvc, bvci);
-	msgb_free(msg);
-	return rc;
-}
-
-static void gbproxy_acquire_imsi(struct gbproxy_bvc *bvc,
-				 struct gbproxy_link_info* link_info,
-				 uint16_t bvci)
-{
-	struct msgb *idreq_msg;
-
-	/* Send IDENT REQ */
-	idreq_msg = gsm48_msgb_alloc_name("GSM 04.08 ACQ IMSI");
-	gprs_put_identity_req(idreq_msg, GSM_MI_TYPE_IMSI);
-	gbproxy_gsm48_to_bvc(bvc, link_info, bvci, idreq_msg);
-}
-
-static void gbproxy_tx_detach_acc(struct gbproxy_bvc *bvc,
-				  struct gbproxy_link_info* link_info,
-				  uint16_t bvci)
-{
-	struct msgb *detacc_msg;
-
-	/* Send DETACH ACC */
-	detacc_msg = gsm48_msgb_alloc_name("GSM 04.08 DET ACC");
-	gprs_put_mo_detach_acc(detacc_msg);
-	gbproxy_gsm48_to_bvc(bvc, link_info, bvci, detacc_msg);
-}
-
-/* Return != 0 iff msg still needs to be processed */
-static int gbproxy_imsi_acquisition(struct gbproxy_bvc *bvc,
-				    struct msgb *msg,
-				    time_t now,
-				    struct gbproxy_link_info* link_info,
-				    struct gprs_gb_parse_context *parse_ctx)
-{
-	struct msgb *stored_msg;
-	OSMO_ASSERT(bvc);
-	OSMO_ASSERT(bvc->nse);
-	struct gbproxy_config *cfg = bvc->nse->cfg;
-	OSMO_ASSERT(cfg);
-
-	if (!link_info)
-		return 1;
-
-	if (!link_info->imsi_acq_pending && link_info->imsi_len > 0)
-		return 1;
-
-	if (parse_ctx->g48_hdr)
-		switch (parse_ctx->g48_hdr->msg_type)
-		{
-		case GSM48_MT_GMM_RA_UPD_REQ:
-		case GSM48_MT_GMM_ATTACH_REQ:
-			if (gbproxy_restart_imsi_acquisition(link_info)) {
-				LOGPBVC_CAT(bvc, DLLC, LOGL_INFO,
-				     " IMSI acquisition was in progress "
-				     "when receiving an %s.\n",
-				     parse_ctx->llc_msg_name);
-			}
-			break;
-		case GSM48_MT_GMM_DETACH_REQ:
-			/* Nothing has been sent to the SGSN yet */
-			if (link_info->imsi_acq_pending) {
-				LOGPBVC_CAT(bvc, DLLC, LOGL_INFO,
-				     "IMSI acquisition was in progress "
-				     "when receiving a DETACH_REQ.\n");
-			}
-			if (!parse_ctx->invalidate_tlli) {
-				LOGPBVC_CAT(bvc, DLLC, LOGL_INFO,
-				     "IMSI not yet acquired, "
-				     "faking a DETACH_ACC.\n");
-				gbproxy_tx_detach_acc(bvc, link_info, msgb_bvci(msg));
-				parse_ctx->invalidate_tlli = 1;
-			}
-			gbproxy_reset_imsi_acquisition(link_info);
-			gbproxy_update_link_state_after(bvc, link_info, now,
-							parse_ctx);
-			return 0;
-		}
-
-	if (link_info->imsi_acq_pending && link_info->imsi_len > 0) {
-		int is_ident_resp =
-			parse_ctx->g48_hdr &&
-			gsm48_hdr_pdisc(parse_ctx->g48_hdr) == GSM48_PDISC_MM_GPRS &&
-			gsm48_hdr_msg_type(parse_ctx->g48_hdr) == GSM48_MT_GMM_ID_RESP;
-
-		LOGPBVC_CAT(bvc, DLLC, LOGL_DEBUG,
-		     "IMSI acquisition succeeded, "
-		     "flushing stored messages\n");
-		/* The IMSI is now available. If flushing the messages fails,
-		 * then link_info has been deleted and we should return
-		 * immediately. */
-		if (gbproxy_flush_stored_messages(bvc, now, link_info) < 0)
-			return 0;
-
-		gbproxy_reset_imsi_acquisition(link_info);
-
-		/* This message is most probably the response to the ident
-		 * request sent by gbproxy_acquire_imsi(). Don't forward it to
-		 * the SGSN. */
-		return !is_ident_resp;
-	}
-
-	/* The message cannot be processed since the IMSI is still missing */
-
-	/* If queue is getting too large, drop oldest msgb before adding new one */
-	if (cfg->stored_msgs_max_len > 0) {
-		int exceeded_max_len = link_info->stored_msgs_len
-				   + 1 - cfg->stored_msgs_max_len;
-
-		for (; exceeded_max_len > 0; exceeded_max_len--) {
-			struct msgb *msgb_drop;
-			msgb_drop = msgb_dequeue_count(&link_info->stored_msgs,
-						       &link_info->stored_msgs_len);
-			LOGPBVC_CAT(bvc, DLLC, LOGL_INFO,
-			     "Dropping stored msgb from list "
-			     "(!acq imsi, length %d, max_len exceeded)\n",
-			     link_info->stored_msgs_len);
-
-			msgb_free(msgb_drop);
-		}
-	}
-
-	/* Enqueue unpatched messages */
-	LOGPBVC_CAT(bvc, DLLC, LOGL_INFO,
-	     "IMSI acquisition in progress, "
-	     "storing message (%s)\n",
-	     parse_ctx->llc_msg_name ? parse_ctx->llc_msg_name : "BSSGP");
-
-	stored_msg = bssgp_msgb_copy(msg, "process_bssgp_ul");
-	msgb_enqueue_count(&link_info->stored_msgs, stored_msg,
-			   &link_info->stored_msgs_len);
-
-	if (!link_info->imsi_acq_pending) {
-		LOGPBVC_CAT(bvc, DLLC, LOGL_INFO,
-		     "IMSI is required but not available, "
-		     "initiating identification procedure (%s)\n",
-		     parse_ctx->llc_msg_name ? parse_ctx->llc_msg_name : "BSSGP");
-
-		gbproxy_acquire_imsi(bvc, link_info, msgb_bvci(msg));
-
-		/* There is no explicit retransmission handling, the
-		 * implementation relies on the MS doing proper retransmissions
-		 * of the triggering message instead */
-
-		link_info->imsi_acq_pending = true;
-	}
-
-	return 0;
-}
-
-struct gbproxy_bvc *gbproxy_find_bvc(struct gbproxy_config *cfg,
-				       struct msgb *msg,
-				       struct gprs_gb_parse_context *parse_ctx)
-{
-	struct gbproxy_bvc *bvc = NULL;
-
-	if (msgb_bvci(msg) >= 2)
-		bvc = gbproxy_bvc_by_bvci(cfg, msgb_bvci(msg));
-
-	if (!bvc && !parse_ctx->to_bss)
-		bvc = gbproxy_bvc_by_nsei(cfg, msgb_nsei(msg));
-
-	if (!bvc)
-		bvc = gbproxy_bvc_by_bssgp_tlv(cfg, &parse_ctx->bssgp_tp);
-
-	if (!bvc) {
-		LOGP(DLLC, LOGL_INFO,
-		     "NSE(%05u/%s) patching: didn't find bvc for message, "
-		     "PDU %d\n",
-		     msgb_nsei(msg), parse_ctx->to_bss ? "BSS" : "SGSN",
-		     parse_ctx->pdu_type);
-		/* Increment counter */
-		rate_ctr_inc(&cfg->ctrg->ctr[GBPROX_GLOB_CTR_PATCH_PEER_ERR]);
-	}
-	return bvc;
-}
-
-/* patch BSSGP message */
-static int gbprox_process_bssgp_ul(struct gbproxy_config *cfg,
-				   struct msgb *msg,
-				   struct gbproxy_bvc *bvc)
-{
-	struct gprs_gb_parse_context parse_ctx = {0};
-	int rc;
-	int len_change = 0;
-	time_t now;
-	struct timespec ts = {0,};
-	struct gbproxy_link_info *link_info = NULL;
-	uint32_t sgsn_nsei = cfg->nsip_sgsn_nsei;
-
-	if (!cfg->core_plmn.mcc && !cfg->core_plmn.mnc && !cfg->core_apn &&
-	    !cfg->acquire_imsi && !cfg->patch_ptmsi && !cfg->route_to_sgsn2)
-		return 1;
-
-	parse_ctx.to_bss = 0;
-	parse_ctx.peer_nsei = msgb_nsei(msg);
-
-	/* Parse BSSGP/LLC */
-	rc = gprs_gb_parse_bssgp(msgb_bssgph(msg), msgb_bssgp_len(msg),
-				 &parse_ctx);
-
-	if (!rc && !parse_ctx.need_decryption) {
-		LOGP(DGPRS, LOGL_ERROR,
-		     "NSE(%05u/BSS) patching: failed to parse invalid %s message\n",
-		     msgb_nsei(msg), gprs_gb_message_name(&parse_ctx, "NS_UNITDATA"));
-		gprs_gb_log_parse_context(LOGL_NOTICE, &parse_ctx, "NS_UNITDATA");
-		LOGP(DGPRS, LOGL_NOTICE,
-		     "NSE(%05u/BSS) invalid message was: %s\n",
-		     msgb_nsei(msg), msgb_hexdump(msg));
-		return 0;
-	}
-
-	/* Get bvc */
-	if (!bvc)
-		bvc = gbproxy_find_bvc(cfg, msg, &parse_ctx);
-
-	if (!bvc)
-		return 0;
-
-
-	osmo_clock_gettime(CLOCK_MONOTONIC, &ts);
-	now = ts.tv_sec;
-
-	gbprox_update_current_raid(parse_ctx.bssgp_raid_enc, bvc,
-				   parse_ctx.llc_msg_name);
-
-	gprs_gb_log_parse_context(LOGL_DEBUG, &parse_ctx, "NS_UNITDATA");
-
-	link_info = gbproxy_update_link_state_ul(bvc, now, &parse_ctx);
-
-	if (parse_ctx.g48_hdr) {
-		switch (parse_ctx.g48_hdr->msg_type) {
-		case GSM48_MT_GMM_ATTACH_REQ:
-			rate_ctr_inc(&bvc->ctrg->ctr[GBPROX_PEER_CTR_ATTACH_REQS]);
-			break;
-		case GSM48_MT_GMM_DETACH_REQ:
-			rate_ctr_inc(&bvc->ctrg->ctr[GBPROX_PEER_CTR_DETACH_REQS]);
-			break;
-		case GSM48_MT_GMM_ATTACH_COMPL:
-			rate_ctr_inc(&bvc->ctrg->ctr[GBPROX_PEER_CTR_ATTACH_COMPLS]);
-			break;
-		case GSM48_MT_GMM_RA_UPD_REQ:
-			rate_ctr_inc(&bvc->ctrg->ctr[GBPROX_PEER_CTR_RA_UPD_REQS]);
-			break;
-		case GSM48_MT_GMM_RA_UPD_COMPL:
-			rate_ctr_inc(&bvc->ctrg->ctr[GBPROX_PEER_CTR_RA_UPD_COMPLS]);
-			break;
-		case GSM48_MT_GMM_STATUS:
-			rate_ctr_inc(&bvc->ctrg->ctr[GBPROX_PEER_CTR_GMM_STATUS_BSS]);
-			break;
-		case GSM48_MT_GSM_ACT_PDP_REQ:
-			rate_ctr_inc(&bvc->ctrg->ctr[GBPROX_PEER_CTR_PDP_ACT_REQS]);
-			break;
-		case GSM48_MT_GSM_DEACT_PDP_REQ:
-			rate_ctr_inc(&bvc->ctrg->ctr[GBPROX_PEER_CTR_PDP_DEACT_REQS]);
-			break;
-
-		default:
-			break;
-		}
-	}
-
-	if (link_info && cfg->route_to_sgsn2) {
-		if (cfg->acquire_imsi && link_info->imsi_len == 0)
-			sgsn_nsei = 0xffff;
-		else if (gbproxy_imsi_matches(cfg, GBPROX_MATCH_ROUTING,
-					      link_info))
-			sgsn_nsei = cfg->nsip_sgsn2_nsei;
-	}
-
-	if (link_info)
-		link_info->sgsn_nsei = sgsn_nsei;
-
-	/* Handle IMSI acquisition */
-	if (cfg->acquire_imsi) {
-		rc = gbproxy_imsi_acquisition(bvc, msg, now, link_info,
-					      &parse_ctx);
-		if (rc <= 0)
-			return rc;
-	}
-
-	gbproxy_patch_bssgp(msg, msgb_bssgph(msg), msgb_bssgp_len(msg),
-			    bvc, link_info, &len_change, &parse_ctx);
-
-	gbproxy_update_link_state_after(bvc, link_info, now, &parse_ctx);
-
-	if (sgsn_nsei != cfg->nsip_sgsn_nsei) {
-		/* Send message directly to the selected SGSN */
-		rc = gbprox_relay2sgsn(cfg, msg, msgb_bvci(msg), sgsn_nsei);
-		/* Don't let the calling code handle the transmission */
-		return 0;
-	}
-
-	return 1;
-}
-
-/* patch BSSGP message to use core_plmn.mcc/mnc on the SGSN side */
-static void gbprox_process_bssgp_dl(struct gbproxy_config *cfg,
-				    struct msgb *msg,
-				    struct gbproxy_bvc *bvc)
-{
-	struct gprs_gb_parse_context parse_ctx = {0};
-	int rc;
-	int len_change = 0;
-	time_t now;
-	struct timespec ts = {0,};
-	struct gbproxy_link_info *link_info = NULL;
-
-	if (!cfg->core_plmn.mcc && !cfg->core_plmn.mnc && !cfg->core_apn &&
-	    !cfg->acquire_imsi && !cfg->patch_ptmsi && !cfg->route_to_sgsn2)
-		return;
-
-	parse_ctx.to_bss = 1;
-	parse_ctx.peer_nsei = msgb_nsei(msg);
-
-	rc = gprs_gb_parse_bssgp(msgb_bssgph(msg), msgb_bssgp_len(msg),
-				 &parse_ctx);
-
-	if (!rc && !parse_ctx.need_decryption) {
-		LOGP(DGPRS, LOGL_ERROR,
-		     "NSE(%05u/SGSN) patching: failed to parse invalid %s message\n",
-		     msgb_nsei(msg), gprs_gb_message_name(&parse_ctx, "NS_UNITDATA"));
-		gprs_gb_log_parse_context(LOGL_NOTICE, &parse_ctx, "NS_UNITDATA");
-		LOGP(DGPRS, LOGL_NOTICE,
-		     "NSE(%05u/SGSN) invalid message was: %s\n",
-		     msgb_nsei(msg), msgb_hexdump(msg));
-		return;
-	}
-
-	/* Get bvc */
-	if (!bvc)
-		bvc = gbproxy_find_bvc(cfg, msg, &parse_ctx);
-
-	if (!bvc)
-		return;
-
-	osmo_clock_gettime(CLOCK_MONOTONIC, &ts);
-	now = ts.tv_sec;
-
-	if (parse_ctx.g48_hdr) {
-		switch (parse_ctx.g48_hdr->msg_type) {
-		case GSM48_MT_GMM_ATTACH_ACK:
-			rate_ctr_inc(&bvc->ctrg->ctr[GBPROX_PEER_CTR_ATTACH_ACKS]);
-			break;
-		case GSM48_MT_GMM_ATTACH_REJ:
-			rate_ctr_inc(&bvc->ctrg->ctr[GBPROX_PEER_CTR_ATTACH_REJS]);
-			break;
-		case GSM48_MT_GMM_DETACH_ACK:
-			rate_ctr_inc(&bvc->ctrg->ctr[GBPROX_PEER_CTR_DETACH_ACKS]);
-			break;
-		case GSM48_MT_GMM_RA_UPD_ACK:
-			rate_ctr_inc(&bvc->ctrg->ctr[GBPROX_PEER_CTR_RA_UPD_ACKS]);
-			break;
-		case GSM48_MT_GMM_RA_UPD_REJ:
-			rate_ctr_inc(&bvc->ctrg->ctr[GBPROX_PEER_CTR_RA_UPD_REJS]);
-			break;
-		case GSM48_MT_GMM_STATUS:
-			rate_ctr_inc(&bvc->ctrg->ctr[GBPROX_PEER_CTR_GMM_STATUS_SGSN]);
-			break;
-		case GSM48_MT_GSM_ACT_PDP_ACK:
-			rate_ctr_inc(&bvc->ctrg->ctr[GBPROX_PEER_CTR_PDP_ACT_ACKS]);
-			break;
-		case GSM48_MT_GSM_ACT_PDP_REJ:
-			rate_ctr_inc(&bvc->ctrg->ctr[GBPROX_PEER_CTR_PDP_ACT_REJS]);
-			break;
-		case GSM48_MT_GSM_DEACT_PDP_ACK:
-			rate_ctr_inc(&bvc->ctrg->ctr[GBPROX_PEER_CTR_PDP_DEACT_ACKS]);
-			break;
-
-		default:
-			break;
-		}
-	}
-
-	gprs_gb_log_parse_context(LOGL_DEBUG, &parse_ctx, "NS_UNITDATA");
-
-	link_info = gbproxy_update_link_state_dl(bvc, now, &parse_ctx);
-
-	gbproxy_patch_bssgp(msg, msgb_bssgph(msg), msgb_bssgp_len(msg),
-			    bvc, link_info, &len_change, &parse_ctx);
-
-	gbproxy_update_link_state_after(bvc, link_info, now, &parse_ctx);
-
-	return;
-}
-
 /* feed a message down the NS-VC associated with the specified bvc */
 static int gbprox_relay2sgsn(struct gbproxy_config *cfg, struct msgb *old_msg,
 			     uint16_t ns_bvci, uint16_t sgsn_nsei)
@@ -924,9 +244,6 @@
 				  uint16_t ns_bvci)
 {
 	struct gbproxy_bvc *bvc;
-	struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *) msgb_bssgph(msg);
-	uint8_t pdu_type = bgph->pdu_type;
-	int rc;
 
 	bvc = gbproxy_bvc_by_bvci(cfg, ns_bvci);
 	if (!bvc) {
@@ -941,23 +258,6 @@
 	/* TODO: Should we discard this message if the check fails */
 	check_bvc_nsei(bvc, nsei);
 
-	rc = gbprox_process_bssgp_ul(cfg, msg, bvc);
-	if (!rc)
-		return 0;
-
-	switch (pdu_type) {
-	case BSSGP_PDUT_FLOW_CONTROL_BVC:
-		if (!cfg->route_to_sgsn2)
-			break;
-
-		/* Send a copy to the secondary SGSN */
-		gbprox_relay2sgsn(cfg, msg, ns_bvci, cfg->nsip_sgsn2_nsei);
-		break;
-	default:
-		break;
-	}
-
-
 	return gbprox_relay2sgsn(cfg, msg, ns_bvci, cfg->nsip_sgsn_nsei);
 }
 
@@ -967,8 +267,6 @@
 				   uint16_t ns_bvci)
 {
 	struct gbproxy_bvc *bvc;
-	struct bssgp_normal_hdr *bgph = (struct bssgp_normal_hdr *) msgb_bssgph(msg);
-	uint8_t pdu_type = bgph->pdu_type;
 
 	bvc = gbproxy_bvc_by_bvci(cfg, ns_bvci);
 
@@ -991,29 +289,12 @@
 		return bssgp_tx_status(BSSGP_CAUSE_BVCI_BLOCKED, &ns_bvci, msg);
 	}
 
-	switch (pdu_type) {
-	case BSSGP_PDUT_FLOW_CONTROL_BVC_ACK:
-	case BSSGP_PDUT_BVC_BLOCK_ACK:
-	case BSSGP_PDUT_BVC_UNBLOCK_ACK:
-		if (cfg->route_to_sgsn2 && nsei == cfg->nsip_sgsn2_nsei)
-			/* Hide ACKs from the secondary SGSN, the primary SGSN
-			 * is responsible to send them. */
-			return 0;
-		break;
-	default:
-		break;
-	}
-
-	/* Optionally patch the message */
-	gbprox_process_bssgp_dl(cfg, msg, bvc);
-
 	return gbprox_relay2peer(msg, bvc, ns_bvci);
 }
 
 /* process a BVC-RESET message from the BSS side */
 static int gbprox_rx_bvc_reset_from_bss(struct gbproxy_config *cfg, struct msgb *msg,
-					uint16_t nsei, struct tlv_parsed *tp,
-					int *copy_to_sgsn2)
+					uint16_t nsei, struct tlv_parsed *tp)
 {
 	struct gbproxy_bvc *from_bvc = NULL;
 	uint16_t bvci;
@@ -1087,8 +368,6 @@
 			gsm48_parse_ra(&raid, from_bvc->ra);
 			LOGPBVC(from_bvc, LOGL_INFO, "Cell ID %s\n", osmo_rai_name(&raid));
 		}
-		if (cfg->route_to_sgsn2)
-			*copy_to_sgsn2 = 1;
 	}
 	/* continue processing / relaying to SGSN[s] */
 	return 1;
@@ -1105,7 +384,6 @@
 	int data_len = msgb_bssgp_len(msg) - sizeof(*bgph);
 	struct gbproxy_bvc *from_bvc = NULL;
 	struct gprs_ra_id raid;
-	int copy_to_sgsn2 = 0;
 	int rc;
 
 	if (ns_bvci != 0 && ns_bvci != 1) {
@@ -1147,22 +425,13 @@
 		/* FIXME: This only supports one BSS per RA */
 		break;
 	case BSSGP_PDUT_BVC_RESET:
-		rc = gbprox_rx_bvc_reset_from_bss(cfg, msg, nsei, &tp, &copy_to_sgsn2);
+		rc = gbprox_rx_bvc_reset_from_bss(cfg, msg, nsei, &tp);
 		/* if function retruns 0, we terminate processing here */
 		if (rc == 0)
 			return 0;
 		break;
 	}
 
-	/* Normally, we can simply pass on all signalling messages from BSS to
-	 * SGSN */
-	rc = gbprox_process_bssgp_ul(cfg, msg, from_bvc);
-	if (!rc)
-		return 0;
-
-	if (copy_to_sgsn2)
-		gbprox_relay2sgsn(cfg, msg, ns_bvci, cfg->nsip_sgsn2_nsei);
-
 	return gbprox_relay2sgsn(cfg, msg, ns_bvci, cfg->nsip_sgsn_nsei);
 err_no_bvc:
 	LOGP(DGPRS, LOGL_ERROR, "NSE(%05u/BSS) cannot find bvc based on NSEI\n",
@@ -1337,7 +606,6 @@
 	}
 
 	msg = bssgp_msgb_copy(orig_msg, "rx_sig_from_sgsn");
-	gbprox_process_bssgp_dl(cfg, msg, NULL);
 	/* Update message info */
 	bgph = (struct bssgp_normal_hdr *) msgb_bssgph(msg);
 	data_len = msgb_bssgp_len(orig_msg) - sizeof(*bgph);
@@ -1348,8 +616,6 @@
 		rc = rx_reset_from_sgsn(cfg, msg, orig_msg, &tp, nsei, ns_bvci);
 		break;
 	case BSSGP_PDUT_BVC_RESET_ACK:
-		if (cfg->route_to_sgsn2 && nsei == cfg->nsip_sgsn2_nsei)
-			break;
 		/* simple case: BVCI IE is mandatory */
 		if (!TLVP_PRES_LEN(&tp, BSSGP_IE_BVCI, 2))
 			goto err_mand_ie;
@@ -1462,8 +728,7 @@
 
 static int gbproxy_is_sgsn_nsei(struct gbproxy_config *cfg, uint16_t nsei)
 {
-	return nsei == cfg->nsip_sgsn_nsei ||
-		(cfg->route_to_sgsn2 && nsei == cfg->nsip_sgsn2_nsei);
+	return nsei == cfg->nsip_sgsn_nsei;
 }
 
 int gbprox_bssgp_send_cb(void *ctx, struct msgb *msg)