예제 #1
0
파일: bsc_api.c 프로젝트: YBouzid/openbsc
static void handle_ass_fail(struct gsm_subscriber_connection *conn,
			    struct msgb *msg)
{
	struct bsc_api *api = conn->bts->network->bsc_api;
	uint8_t *rr_failure;
	struct gsm48_hdr *gh;


	if (conn->lchan != msg->lchan) {
		LOGP(DMSC, LOGL_ERROR, "Assignment failure should occur on primary lchan.\n");
		return;
	}

	/* stop the timer and release it */
	osmo_timer_del(&conn->T10);
	lchan_release(conn->secondary_lchan, 0, 1);
	conn->secondary_lchan = NULL;

	gh = msgb_l3(msg);
	if (msgb_l3len(msg) - sizeof(*gh) != 1) {
		LOGP(DMSC, LOGL_ERROR, "assignemnt failure unhandled: %lu\n",
		     msgb_l3len(msg) - sizeof(*gh));
		rr_failure = NULL;
	} else {
		rr_failure = &gh->data[0];
	}

	api->assign_fail(conn,
			 GSM0808_CAUSE_RADIO_INTERFACE_MESSAGE_FAILURE,
			 rr_failure);
}
예제 #2
0
/**
 * Messages coming back from the MSC.
 */
int bsc_scan_msc_msg(struct gsm_subscriber_connection *conn, struct msgb *msg)
{
	struct osmo_msc_data *msc;
	struct gsm_network *net;
	struct gsm48_loc_area_id *lai;
	struct gsm48_hdr *gh;
	uint8_t mtype;

	if (msgb_l3len(msg) < sizeof(*gh)) {
		LOGP(DMSC, LOGL_ERROR, "GSM48 header does not fit.\n");
		return -1;
	}

	gh = (struct gsm48_hdr *) msgb_l3(msg);
	mtype = gh->msg_type & 0xbf;
	net = conn->bts->network;
	msc = conn->sccp_con->msc;

	if (mtype == GSM48_MT_MM_LOC_UPD_ACCEPT) {
		if (msc->core_ncc != -1 || msc->core_mcc != -1) {
			if (msgb_l3len(msg) >= sizeof(*gh) + sizeof(*lai)) {
				lai = (struct gsm48_loc_area_id *) &gh->data[0];
				gsm48_generate_lai(lai, net->country_code,
						   net->network_code,
						   conn->bts->location_area_code);
			}
		}

		if (conn->sccp_con->new_subscriber)
			send_welcome_ussd(conn);
	}

	return 0;
}
예제 #3
0
static void handle_lu_request(struct gsm_subscriber_connection *conn,
			      struct msgb *msg)
{
	struct gsm48_hdr *gh;
	struct gsm48_loc_upd_req *lu;
	struct gsm48_loc_area_id lai;
	struct gsm_network *net;

	if (msgb_l3len(msg) < sizeof(*gh) + sizeof(*lu)) {
		LOGP(DMSC, LOGL_ERROR, "LU too small to look at: %u\n", msgb_l3len(msg));
		return;
	}

	net = conn->bts->network;

	gh = msgb_l3(msg);
	lu = (struct gsm48_loc_upd_req *) gh->data;

	gsm48_generate_lai(&lai, net->country_code, net->network_code,
			   conn->bts->location_area_code);

	if (memcmp(&lai, &lu->lai, sizeof(lai)) != 0) {
		LOGP(DMSC, LOGL_DEBUG, "Marking con for welcome USSD.\n");
		conn->sccp_con->new_subscriber = 1;
	}
}
/* receive BCCH at RR layer */
static int bcch(struct osmocom_ms *ms, struct msgb *msg)
{
	struct gsm48_system_information_type_header *sih = msgb_l3(msg);
	struct gsm48_sysinfo *s = &g_sysinfo;

	if (msgb_l3len(msg) != 23) {
		LOGP(DRR, LOGL_NOTICE, "Invalid BCCH message length\n");
		return -EINVAL;
	}
	switch (sih->system_information) {
	case GSM48_MT_RR_SYSINFO_1:
		LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 1\n");
		gsm48_decode_sysinfo1(s,
			(struct gsm48_system_information_type_1 *) sih,
			msgb_l3len(msg));
		return try_cbch(ms, s);
	case GSM48_MT_RR_SYSINFO_4:
		LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 4\n");
		gsm48_decode_sysinfo4(s,
			(struct gsm48_system_information_type_4 *) sih,
			msgb_l3len(msg));
		return try_cbch(ms, s);
	default:
		return 0;
	}
}
예제 #5
0
파일: bsc_api.c 프로젝트: YBouzid/openbsc
static void handle_ass_compl(struct gsm_subscriber_connection *conn,
			     struct msgb *msg)
{
	struct gsm48_hdr *gh;
	struct bsc_api *api = conn->bts->network->bsc_api;

	if (conn->secondary_lchan != msg->lchan) {
		LOGP(DMSC, LOGL_ERROR, "Assignment Compl should occur on second lchan.\n");
		return;
	}

	gh = msgb_l3(msg);
	if (msgb_l3len(msg) - sizeof(*gh) != 1) {
		LOGP(DMSC, LOGL_ERROR, "Assignment Compl invalid: %lu\n",
		     msgb_l3len(msg) - sizeof(*gh));
		return;
	}

	/* swap channels */
	osmo_timer_del(&conn->T10);

	lchan_release(conn->lchan, 0, 1);
	conn->lchan = conn->secondary_lchan;
	conn->secondary_lchan = NULL;

	if (is_ipaccess_bts(conn->bts) && conn->lchan->tch_mode != GSM48_CMODE_SIGN)
		rsl_ipacc_crcx(conn->lchan);

	api->assign_compl(conn, gh->data[0],
			  lchan_to_chosen_channel(conn->lchan),
			  conn->lchan->encr.alg_id,
			  chan_mode_to_speech(conn->lchan));
}
예제 #6
0
/*
 * I get called from the LAPDm code when something was sent my way...
 */
static int bts_to_ms_tx_cb(struct msgb *in_msg, struct lapdm_entity *le, void *_ctx)
{
	struct lapdm_polling_state *state = _ctx;


	printf("%s: MS->BTS(us) message %d\n", __func__, msgb_length(in_msg));


	if (state->bts_read == 0) {
		printf("BTS: Verifying CM request.\n");
		ASSERT(msgb_l3len(in_msg) == ARRAY_SIZE(cm_padded));
		ASSERT(memcmp(in_msg->l3h, cm_padded, ARRAY_SIZE(cm_padded)) == 0);
	} else if (state->bts_read == 1) {
		printf("BTS: Verifying dummy message.\n");
		ASSERT(msgb_l3len(in_msg) == ARRAY_SIZE(dummy1));
		ASSERT(memcmp(in_msg->l3h, dummy1, ARRAY_SIZE(dummy1)) == 0);
	} else {
		printf("BTS: Do not know to verify: %d\n", state->bts_read);
	}

	state->bts_read += 1;
	msgb_free(in_msg);

	return 0;
}
예제 #7
0
static int ms_to_bts_tx_cb(struct msgb *msg, struct lapdm_entity *le, void *_ctx)
{
	struct lapdm_polling_state *state = _ctx;

	printf("%s: BTS->MS(us) message %d\n", __func__, msgb_length(msg));

	if (state->ms_read == 0) {
		struct abis_rsl_rll_hdr hdr;

		printf("MS: Verifying incoming primitive.\n");
		ASSERT(msg->len == sizeof(struct abis_rsl_rll_hdr) + 3);

		/* verify the header */
		memset(&hdr, 0, sizeof(hdr));
		rsl_init_rll_hdr(&hdr, RSL_MT_EST_CONF);
		hdr.c.msg_discr |= ABIS_RSL_MDISC_TRANSP;
		ASSERT(memcmp(msg->data, &hdr, sizeof(hdr)) == 0);

		/* Verify the added RSL_IE_L3_INFO but we have a bug here */
		ASSERT(msg->data[6] == RSL_IE_L3_INFO);
		#warning "RSL_IE_L3_INFO 16 bit length is wrong"
		/* ASSERT(msg->data[7] == 0x0 && msg->data[8] == 0x9c); */
		/* this should be 0x0 and 0x0... but we have a bug */
	} else if (state->ms_read == 1) {
		printf("MS: Verifying incoming MM message: %d\n", msgb_l3len(msg));
		ASSERT(msgb_l3len(msg) == 3);
		ASSERT(memcmp(msg->l3h, &mm[12], msgb_l3len(msg)) == 0);
	} else {
		printf("MS: Do not know to verify: %d\n", state->ms_read);
	}

	state->ms_read += 1;
	msgb_free(msg);
	return 0;
}
예제 #8
0
/* string tokenizer for the poor */
static int find_msg_pointers(struct msgb *msg, struct mgcp_msg_ptr *ptrs, int ptrs_length)
{
    int i, found = 0;

    int whitespace = 1;
    for (i = 0; i < msgb_l3len(msg) && ptrs_length > 0; ++i) {
        /* if we have a space we found an end */
        if (msg->l3h[i]	== ' ' || msg->l3h[i] == '\r' || msg->l3h[i] == '\n') {
            if (!whitespace) {
                ++found;
                whitespace = 1;
                ptrs->length = i - ptrs->start - 1;
                ++ptrs;
                --ptrs_length;
            } else {
                /* skip any number of whitespace */
            }

            /* line end... stop */
            if (msg->l3h[i] == '\r' || msg->l3h[i] == '\n')
                break;
        } else if (msg->l3h[i] == '\r' || msg->l3h[i] == '\n') {
            /* line end, be done */
            break;
        } else if (whitespace) {
            whitespace = 0;
            ptrs->start = i;
        }
    }

    if (ptrs_length == 0)
        return -1;
    return found;
}
예제 #9
0
static struct msgb *create_empty_msg(void)
{
	struct msgb *msg;

	msg = msgb_from_array(NULL, 0);
	ASSERT(msgb_l3len(msg) == 0);
	rsl_rll_push_l3(msg, RSL_MT_DATA_REQ, 0, 0, 1);
	return msg;
}
예제 #10
0
/* we will need to stop the paging request */
static int handle_page_resp(struct gsm_subscriber_connection *conn, struct msgb *msg)
{
	uint8_t mi_type;
	char mi_string[GSM48_MI_SIZE];
	struct gsm48_hdr *gh;
	struct gsm48_pag_resp *resp;
	struct gsm_subscriber *subscr;

	if (msgb_l3len(msg) < sizeof(*gh) + sizeof(*resp)) {
		LOGP(DMSC, LOGL_ERROR, "PagingResponse too small: %u\n", msgb_l3len(msg));
		return -1;
	}

	gh = msgb_l3(msg);
	resp = (struct gsm48_pag_resp *) &gh->data[0];

	gsm48_paging_extract_mi(resp, msgb_l3len(msg) - sizeof(*gh),
				mi_string, &mi_type);
	DEBUGP(DRR, "PAGING RESPONSE: mi_type=0x%02x MI(%s)\n",
		mi_type, mi_string);

	switch (mi_type) {
	case GSM_MI_TYPE_TMSI:
		subscr = subscr_active_by_tmsi(conn->bts->network,
					       tmsi_from_string(mi_string));
		break;
	case GSM_MI_TYPE_IMSI:
		subscr = subscr_active_by_imsi(conn->bts->network, mi_string);
		break;
	default:
		subscr = NULL;
		break;
	}

	if (!subscr) {
		LOGP(DMSC, LOGL_ERROR, "Non active subscriber got paged.\n");
		return -1;
	}

	paging_request_stop(conn->bts, subscr, conn, msg);
	subscr_put(subscr);
	return 0;
}
예제 #11
0
static struct msgb *create_mm_id_req(void)
{
	struct msgb *msg;

	msg = msgb_from_array(mm, sizeof(mm));
	msg->l2h = msg->data + 3;
	ASSERT(msgb_l2len(msg) == 12);
	msg->l3h = msg->l2h + 6;
	ASSERT(msgb_l3len(msg) == 6);

	return msg;
}
예제 #12
0
static int check_manuf(struct msgb *msg, struct abis_om_hdr *omh, size_t msg_size)
{
	int type;
	size_t size;

	if (msg_size < 1) {
		LOGP(DL1C, LOGL_ERROR, "No ManId Length Indicator %zu\n",
		     msg_size);
		return -1;
	}

	if (omh->data[0] >= msg_size - 1) {
		LOGP(DL1C, LOGL_ERROR,
		     "Insufficient message space for this ManId Length %d %zu\n",
		     omh->data[0], msg_size - 1);
		return -1;
	}

	if (omh->data[0] == sizeof(abis_nm_ipa_magic) &&
		strncmp(abis_nm_ipa_magic, (const char *)omh->data + 1,
			sizeof(abis_nm_ipa_magic)) == 0) {
		type = OML_MSG_TYPE_IPA;
		size = sizeof(abis_nm_ipa_magic) + 1;
	} else if (omh->data[0] == sizeof(abis_nm_osmo_magic) &&
		strncmp(abis_nm_osmo_magic, (const char *) omh->data + 1,
			sizeof(abis_nm_osmo_magic)) == 0) {
		type = OML_MSG_TYPE_OSMO;
		size = sizeof(abis_nm_osmo_magic) + 1;
	} else {
		LOGP(DL1C, LOGL_ERROR, "Manuf Label Unknown\n");
		return -1;
	}

	/* we have verified that the vendor string fits */
	msg->l3h = omh->data + size;
	if (check_fom(omh, msgb_l3len(msg)) != 0)
		return -1;
	return type;
}
예제 #13
0
/**
 * \brief Verify the structure of the OML message and set l3h
 *
 * This function verifies that the data in \param in msg is a proper
 * OML message. This code assumes that msg->l2h points to the
 * beginning of the OML message. In the successful case the msg->l3h
 * will be set and will point to the FOM header. The value is undefined
 * in all other cases.
 *
 * \param msg The message to analyze starting from msg->l2h.
 * \return In case the structure is correct a positive number will be
 * returned and msg->l3h will point to the FOM. The number is a
 * classification of the vendor type of the message.
 */
int msg_verify_oml_structure(struct msgb *msg)
{
	struct abis_om_hdr *omh;

	if (msgb_l2len(msg) < sizeof(*omh)) {
		LOGP(DL1C, LOGL_ERROR, "Om header insufficient space %d %d\n",
		     msgb_l2len(msg), sizeof(*omh));
		return -1;
	}

	omh = (struct abis_om_hdr *) msg->l2h;
	if (omh->mdisc != ABIS_OM_MDISC_FOM &&
	    omh->mdisc != ABIS_OM_MDISC_MANUF) {
		LOGP(DL1C, LOGL_ERROR, "Incorrect om mdisc value %x\n",
		     omh->mdisc);
		return -1;
	}

	if (omh->placement != ABIS_OM_PLACEMENT_ONLY) {
		LOGP(DL1C, LOGL_ERROR, "Incorrect om placement value %x %x\n",
		     omh->placement, ABIS_OM_PLACEMENT_ONLY);
		return -1;
	}

	if (omh->sequence != 0) {
		LOGP(DL1C, LOGL_ERROR, "Incorrect om sequence value %d\n",
		     omh->sequence);
		return -1;
	}

	if (omh->mdisc == ABIS_OM_MDISC_MANUF)
		return check_manuf(msg, omh, msgb_l2len(msg) - sizeof(*omh));

	msg->l3h = omh->data;
	if (check_fom(omh, msgb_l3len(msg)) != 0)
		return -1;
	return OML_MSG_TYPE_ETSI;
}
예제 #14
0
파일: bsc_api.c 프로젝트: YBouzid/openbsc
static void handle_classmark_chg(struct gsm_subscriber_connection *conn,
				 struct msgb *msg)
{
	struct bsc_api *api = msg->lchan->ts->trx->bts->network->bsc_api;
	struct gsm48_hdr *gh = msgb_l3(msg);
	unsigned int payload_len = msgb_l3len(msg) - sizeof(*gh);
	uint8_t cm2_len, cm3_len = 0;
	uint8_t *cm2, *cm3 = NULL;

	DEBUGP(DRR, "CLASSMARK CHANGE ");

	/* classmark 2 */
	cm2_len = gh->data[0];
	cm2 = &gh->data[1];
	DEBUGPC(DRR, "CM2(len=%u) ", cm2_len);

	if (payload_len > cm2_len + 1) {
		/* we must have a classmark3 */
		if (gh->data[cm2_len+1] != 0x20) {
			DEBUGPC(DRR, "ERR CM3 TAG\n");
			return;
		}
		if (cm2_len > 3) {
			DEBUGPC(DRR, "CM2 too long!\n");
			return;
		}

		cm3_len = gh->data[cm2_len+2];
		cm3 = &gh->data[cm2_len+3];
		if (cm3_len > 14) {
			DEBUGPC(DRR, "CM3 len %u too long!\n", cm3_len);
			return;
		}
		DEBUGPC(DRR, "CM3(len=%u)\n", cm3_len);
	}
	api->classmark_chg(conn, cm2, cm2_len, cm3, cm3_len);
}
예제 #15
0
static struct msgb *handle_create_con(struct mgcp_config *cfg, struct msgb *msg)
{
    struct mgcp_msg_ptr data_ptrs[6];
    int found, i, line_start;
    const char *trans_id;
    struct mgcp_trunk_config *tcfg;
    struct mgcp_endpoint *endp;
    int error_code = 400;

    found = mgcp_analyze_header(cfg, msg, data_ptrs, ARRAY_SIZE(data_ptrs), &trans_id, &endp);
    if (found != 0)
        return create_err_response(510, "CRCX", trans_id);

    tcfg = endp->tcfg;

    if (endp->allocated) {
        if (tcfg->force_realloc) {
            LOGP(DMGCP, LOGL_NOTICE, "Endpoint 0x%x already allocated. Forcing realloc.\n",
                 ENDPOINT_NUMBER(endp));
            mgcp_free_endp(endp);
            if (cfg->realloc_cb)
                cfg->realloc_cb(tcfg, ENDPOINT_NUMBER(endp));
        } else {
            LOGP(DMGCP, LOGL_ERROR, "Endpoint is already used. 0x%x\n",
                 ENDPOINT_NUMBER(endp));
            return create_err_response(400, "CRCX", trans_id);
        }
    }

    /* parse CallID C: and LocalParameters L: */
    MSG_TOKENIZE_START
    switch (msg->l3h[line_start]) {
    case 'L':
        endp->local_options = talloc_strdup(tcfg->endpoints,
                                            (const char *)&msg->l3h[line_start + 3]);
        break;
    case 'C':
        endp->callid = talloc_strdup(tcfg->endpoints,
                                     (const char *)&msg->l3h[line_start + 3]);
        break;
    case 'M':
        if (parse_conn_mode((const char *)&msg->l3h[line_start + 3],
                            &endp->conn_mode) != 0) {
            error_code = 517;
            goto error2;
        }

        endp->orig_mode = endp->conn_mode;
        break;
    default:
        LOGP(DMGCP, LOGL_NOTICE, "Unhandled option: '%c'/%d on 0x%x\n",
             msg->l3h[line_start], msg->l3h[line_start],
             ENDPOINT_NUMBER(endp));
        break;
    }
    MSG_TOKENIZE_END

    /* initialize */
    endp->net_end.rtp_port = endp->net_end.rtcp_port = endp->bts_end.rtp_port = endp->bts_end.rtcp_port = 0;

    /* set to zero until we get the info */
    memset(&endp->net_end.addr, 0, sizeof(endp->net_end.addr));

    /* bind to the port now */
    if (allocate_ports(endp) != 0)
        goto error2;

    /* assign a local call identifier or fail */
    endp->ci = generate_call_id(cfg);
    if (endp->ci == CI_UNUSED)
        goto error2;

    endp->allocated = 1;
    endp->bts_end.payload_type = tcfg->audio_payload;

    /* policy CB */
    if (cfg->policy_cb) {
        switch (cfg->policy_cb(tcfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_CRCX, trans_id)) {
        case MGCP_POLICY_REJECT:
            LOGP(DMGCP, LOGL_NOTICE, "CRCX rejected by policy on 0x%x\n",
                 ENDPOINT_NUMBER(endp));
            mgcp_free_endp(endp);
            return create_err_response(400, "CRCX", trans_id);
            break;
        case MGCP_POLICY_DEFER:
            /* stop processing */
            create_transcoder(endp);
            return NULL;
            break;
        case MGCP_POLICY_CONT:
            /* just continue */
            break;
        }
    }

    LOGP(DMGCP, LOGL_DEBUG, "Creating endpoint on: 0x%x CI: %u port: %u/%u\n",
         ENDPOINT_NUMBER(endp), endp->ci,
         endp->net_end.local_port, endp->bts_end.local_port);
    if (cfg->change_cb)
        cfg->change_cb(tcfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_CRCX);

    create_transcoder(endp);
    return create_response_with_sdp(endp, "CRCX", trans_id);
error:
    LOGP(DMGCP, LOGL_ERROR, "Malformed line: %s on 0x%x with: line_start: %d %d\n",
         osmo_hexdump(msg->l3h, msgb_l3len(msg)),
         ENDPOINT_NUMBER(endp), line_start, i);
    return create_err_response(error_code, "CRCX", trans_id);

error2:
    mgcp_free_endp(endp);
    LOGP(DMGCP, LOGL_NOTICE, "Resource error on 0x%x\n", ENDPOINT_NUMBER(endp));
    return create_err_response(error_code, "CRCX", trans_id);
}
예제 #16
0
static struct msgb *handle_modify_con(struct mgcp_config *cfg, struct msgb *msg)
{
    struct mgcp_msg_ptr data_ptrs[6];
    int found, i, line_start;
    const char *trans_id;
    struct mgcp_endpoint *endp;
    int error_code = 500;
    int silent = 0;

    found = mgcp_analyze_header(cfg, msg, data_ptrs, ARRAY_SIZE(data_ptrs), &trans_id, &endp);
    if (found != 0)
        return create_err_response(510, "MDCX", trans_id);

    if (endp->ci == CI_UNUSED) {
        LOGP(DMGCP, LOGL_ERROR, "Endpoint is not holding a connection. 0x%x\n", ENDPOINT_NUMBER(endp));
        return create_err_response(400, "MDCX", trans_id);
    }

    MSG_TOKENIZE_START
    switch (msg->l3h[line_start]) {
    case 'C': {
        if (verify_call_id(endp, (const char *)&msg->l3h[line_start + 3]) != 0)
            goto error3;
        break;
    }
    case 'I': {
        if (verify_ci(endp, (const char *)&msg->l3h[line_start + 3]) != 0)
            goto error3;
        break;
    }
    case 'L':
        /* skip */
        break;
    case 'M':
        if (parse_conn_mode((const char *)&msg->l3h[line_start + 3],
                            &endp->conn_mode) != 0) {
            error_code = 517;
            goto error3;
        }
        endp->orig_mode = endp->conn_mode;
        break;
    case 'Z':
        silent = strcmp("noanswer", (const char *)&msg->l3h[line_start + 3]) == 0;
        break;
    case '\0':
        /* SDP file begins */
        break;
    case 'a':
    case 'o':
    case 's':
    case 't':
    case 'v':
        /* skip these SDP attributes */
        break;
    case 'm': {
        int port;
        int payload;
        const char *param = (const char *)&msg->l3h[line_start];

        if (sscanf(param, "m=audio %d RTP/AVP %d", &port, &payload) == 2) {
            endp->net_end.rtp_port = htons(port);
            endp->net_end.rtcp_port = htons(port + 1);
            endp->net_end.payload_type = payload;
        }
        break;
    }
    case 'c': {
        char ipv4[16];
        const char *param = (const char *)&msg->l3h[line_start];

        if (sscanf(param, "c=IN IP4 %15s", ipv4) == 1) {
            inet_aton(ipv4, &endp->net_end.addr);
        }
        break;
    }
    default:
        LOGP(DMGCP, LOGL_NOTICE, "Unhandled option: '%c'/%d on 0x%x\n",
             msg->l3h[line_start], msg->l3h[line_start],
             ENDPOINT_NUMBER(endp));
        break;
    }
    MSG_TOKENIZE_END

    /* policy CB */
    if (cfg->policy_cb) {
        switch (cfg->policy_cb(endp->tcfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_MDCX, trans_id)) {
        case MGCP_POLICY_REJECT:
            LOGP(DMGCP, LOGL_NOTICE, "MDCX rejected by policy on 0x%x\n",
                 ENDPOINT_NUMBER(endp));
            if (silent)
                goto out_silent;
            return create_err_response(400, "MDCX", trans_id);
            break;
        case MGCP_POLICY_DEFER:
            /* stop processing */
            return NULL;
            break;
        case MGCP_POLICY_CONT:
            /* just continue */
            break;
        }
    }

    /* modify */
    LOGP(DMGCP, LOGL_DEBUG, "Modified endpoint on: 0x%x Server: %s:%u\n",
         ENDPOINT_NUMBER(endp), inet_ntoa(endp->net_end.addr), ntohs(endp->net_end.rtp_port));
    if (cfg->change_cb)
        cfg->change_cb(endp->tcfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_MDCX);
    if (silent)
        goto out_silent;

    return create_response_with_sdp(endp, "MDCX", trans_id);

error:
    LOGP(DMGCP, LOGL_ERROR, "Malformed line: %s on 0x%x with: line_start: %d %d %d\n",
         osmo_hexdump(msg->l3h, msgb_l3len(msg)),
         ENDPOINT_NUMBER(endp), line_start, i, msg->l3h[line_start]);
    return create_err_response(error_code, "MDCX", trans_id);

error3:
    return create_err_response(error_code, "MDCX", trans_id);


out_silent:
    return NULL;
}
예제 #17
0
static struct msgb *handle_delete_con(struct mgcp_config *cfg, struct msgb *msg)
{
    struct mgcp_msg_ptr data_ptrs[6];
    int found, i, line_start;
    const char *trans_id;
    struct mgcp_endpoint *endp;
    int error_code = 400;
    int silent = 0;

    found = mgcp_analyze_header(cfg, msg, data_ptrs, ARRAY_SIZE(data_ptrs), &trans_id, &endp);
    if (found != 0)
        return create_err_response(error_code, "DLCX", trans_id);

    if (!endp->allocated) {
        LOGP(DMGCP, LOGL_ERROR, "Endpoint is not used. 0x%x\n", ENDPOINT_NUMBER(endp));
        return create_err_response(400, "DLCX", trans_id);
    }

    MSG_TOKENIZE_START
    switch (msg->l3h[line_start]) {
    case 'C': {
        if (verify_call_id(endp, (const char *)&msg->l3h[line_start + 3]) != 0)
            goto error3;
        break;
    }
    case 'I': {
        if (verify_ci(endp, (const char *)&msg->l3h[line_start + 3]) != 0)
            goto error3;
        break;
        case 'Z':
            silent = strcmp("noanswer", (const char *)&msg->l3h[line_start + 3]) == 0;
            break;
        }
    default:
        LOGP(DMGCP, LOGL_NOTICE, "Unhandled option: '%c'/%d on 0x%x\n",
             msg->l3h[line_start], msg->l3h[line_start],
             ENDPOINT_NUMBER(endp));
        break;
    }
    MSG_TOKENIZE_END

    /* policy CB */
    if (cfg->policy_cb) {
        switch (cfg->policy_cb(endp->tcfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_DLCX, trans_id)) {
        case MGCP_POLICY_REJECT:
            LOGP(DMGCP, LOGL_NOTICE, "DLCX rejected by policy on 0x%x\n",
                 ENDPOINT_NUMBER(endp));
            if (silent)
                goto out_silent;
            return create_err_response(400, "DLCX", trans_id);
            break;
        case MGCP_POLICY_DEFER:
            /* stop processing */
            delete_transcoder(endp);
            return NULL;
            break;
        case MGCP_POLICY_CONT:
            /* just continue */
            break;
        }
    }

    /* free the connection */
    LOGP(DMGCP, LOGL_DEBUG, "Deleted endpoint on: 0x%x Server: %s:%u\n",
         ENDPOINT_NUMBER(endp), inet_ntoa(endp->net_end.addr), ntohs(endp->net_end.rtp_port));

    delete_transcoder(endp);
    mgcp_free_endp(endp);
    if (cfg->change_cb)
        cfg->change_cb(endp->tcfg, ENDPOINT_NUMBER(endp), MGCP_ENDP_DLCX);

    if (silent)
        goto out_silent;
    return create_ok_response(250, "DLCX", trans_id);

error:
    LOGP(DMGCP, LOGL_ERROR, "Malformed line: %s on 0x%x with: line_start: %d %d\n",
         osmo_hexdump(msg->l3h, msgb_l3len(msg)),
         ENDPOINT_NUMBER(endp), line_start, i);
    return create_err_response(error_code, "DLCX", trans_id);

error3:
    return create_err_response(error_code, "DLCX", trans_id);

out_silent:
    return NULL;
}
예제 #18
0
/* receive BCCH at RR layer */
static int bcch(struct osmocom_ms *ms, struct msgb *msg)
{
	struct gsm48_sysinfo *s = &sysinfo;
	struct gsm48_system_information_type_header *sih = msgb_l3(msg);
	uint8_t ccch_mode;

	if (msgb_l3len(msg) != 23) {
		LOGP(DRR, LOGL_NOTICE, "Invalid BCCH message length\n");
		return -EINVAL;
	}
	switch (sih->system_information) {
	case GSM48_MT_RR_SYSINFO_1:
		if (!memcmp(sih, s->si1_msg, sizeof(s->si1_msg)))
			return 0;
		LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 1\n");
		gsm48_decode_sysinfo1(s,
			(struct gsm48_system_information_type_1 *) sih,
			msgb_l3len(msg));
		return new_sysinfo();
	case GSM48_MT_RR_SYSINFO_2:
		if (!memcmp(sih, s->si2_msg, sizeof(s->si2_msg)))
			return 0;
		LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 2\n");
		gsm48_decode_sysinfo2(s,
			(struct gsm48_system_information_type_2 *) sih,
			msgb_l3len(msg));
		return new_sysinfo();
	case GSM48_MT_RR_SYSINFO_2bis:
		if (!memcmp(sih, s->si2b_msg, sizeof(s->si2b_msg)))
			return 0;
		LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 2bis\n");
		gsm48_decode_sysinfo2bis(s,
			(struct gsm48_system_information_type_2bis *) sih,
			msgb_l3len(msg));
		return new_sysinfo();
	case GSM48_MT_RR_SYSINFO_2ter:
		if (!memcmp(sih, s->si2t_msg, sizeof(s->si2t_msg)))
			return 0;
		LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 2ter\n");
		gsm48_decode_sysinfo2ter(s,
			(struct gsm48_system_information_type_2ter *) sih,
			msgb_l3len(msg));
		return new_sysinfo();
	case GSM48_MT_RR_SYSINFO_3:
		if (!memcmp(sih, s->si3_msg, sizeof(s->si3_msg)))
			return 0;
		LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 3\n");
		gsm48_decode_sysinfo3(s,
			(struct gsm48_system_information_type_3 *) sih,
			msgb_l3len(msg));
		ccch_mode = (s->ccch_conf == 1) ? CCCH_MODE_COMBINED :
			CCCH_MODE_NON_COMBINED;
		LOGP(DRR, LOGL_INFO, "Changing CCCH_MODE to %d\n", ccch_mode);
		l1ctl_tx_ccch_mode_req(ms, ccch_mode);
		return new_sysinfo();
	case GSM48_MT_RR_SYSINFO_4:
		if (!memcmp(sih, s->si4_msg, sizeof(s->si4_msg)))
			return 0;
		LOGP(DRR, LOGL_INFO, "New SYSTEM INFORMATION 4\n");
		gsm48_decode_sysinfo4(s,
			(struct gsm48_system_information_type_4 *) sih,
			msgb_l3len(msg));
		return new_sysinfo();
	default:
		return -EINVAL;
	}
}
예제 #19
0
파일: bsc_api.c 프로젝트: YBouzid/openbsc
static void dispatch_dtap(struct gsm_subscriber_connection *conn,
			  uint8_t link_id, struct msgb *msg)
{
	struct bsc_api *api = msg->lchan->ts->trx->bts->network->bsc_api;
	struct gsm48_hdr *gh;
	uint8_t pdisc;
	int rc;

	if (msgb_l3len(msg) < sizeof(*gh)) {
		LOGP(DMSC, LOGL_ERROR, "Message too short for a GSM48 header.\n");
		return;
	}

	gh = msgb_l3(msg);
	pdisc = gh->proto_discr & 0x0f;

	/* the idea is to handle all RR messages here, and only hand
	 * MM/CC/SMS-CP/LCS up to the MSC.  Some messages like PAGING
	 * RESPONSE or CM SERVICE REQUEST will not be covered here, as
	 * they are only possible in the first L3 message of each L2
	 * channel, i.e. 'conn' will not exist and gsm0408_rcvmsg()
	 * will call api->compl_l3() for it */
	switch (pdisc) {
	case GSM48_PDISC_RR:
		switch (gh->msg_type) {
		case GSM48_MT_RR_GPRS_SUSP_REQ:
			DEBUGP(DRR, "GRPS SUSPEND REQUEST\n");
			break;
		case GSM48_MT_RR_STATUS:
			LOGP(DRR, LOGL_NOTICE, "RR STATUS (cause: %s)\n",
				rr_cause_name(gh->data[0]));
			break;
		case GSM48_MT_RR_MEAS_REP:
			/* This shouldn't actually end up here, as RSL treats
			* L3 Info of 08.58 MEASUREMENT REPORT different by calling
			* directly into gsm48_parse_meas_rep */
			LOGP(DMEAS, LOGL_ERROR, "DIRECT GSM48 MEASUREMENT REPORT ?!? ");
			break;
		case GSM48_MT_RR_HANDO_COMPL:
			handle_rr_ho_compl(msg);
			break;
		case GSM48_MT_RR_HANDO_FAIL:
			handle_rr_ho_fail(msg);
			break;
		case GSM48_MT_RR_CIPH_M_COMPL:
			if (api->cipher_mode_compl)
				api->cipher_mode_compl(conn, msg,
						conn->lchan->encr.alg_id);
			break;
		case GSM48_MT_RR_ASS_COMPL:
			handle_ass_compl(conn, msg);
			break;
		case GSM48_MT_RR_ASS_FAIL:
			handle_ass_fail(conn, msg);
			break;
		case GSM48_MT_RR_CHAN_MODE_MODIF_ACK:
			osmo_timer_del(&conn->T10);
			rc = gsm48_rx_rr_modif_ack(msg);
			if (rc < 0) {
				api->assign_fail(conn,
						 GSM0808_CAUSE_NO_RADIO_RESOURCE_AVAILABLE,
						 NULL);
			} else if (rc >= 0) {
				api->assign_compl(conn, 0,
						  lchan_to_chosen_channel(conn->lchan),
						  conn->lchan->encr.alg_id,
						  chan_mode_to_speech(conn->lchan));
			}
			break;
		case GSM48_MT_RR_CLSM_CHG:
			handle_classmark_chg(conn, msg);
			break;
		case GSM48_MT_RR_APP_INFO:
			/* Passing RR APP INFO to MSC, not quite
			 * according to spec */
			if (api->dtap)
				api->dtap(conn, link_id, msg);
			break;
		default:
			/* Normally, a MSC should never receive RR
			 * messages, but we'd rather forward what we
			 * don't know than drop it... */
			LOGP(DRR, LOGL_NOTICE, "BSC: Passing unknown 04.08 "
			     "RR message type 0x%02x to MSC\n", gh->msg_type);
			if (api->dtap)
				api->dtap(conn, link_id, msg);
		}
		break;
	default:
		if (api->dtap)
			api->dtap(conn, link_id, msg);
		break;
	}
}