Ejemplo n.º 1
0
void Control::MOSMSController(const L3CMServiceRequest *req, 
						LogicalChannel *LCH)
{
	assert(req);
	assert(LCH);

	LOG(INFO) << "MOSMS, req " << *req;

	// If we got a TMSI, find the IMSI.
	// Note that this is a copy, not a reference.
	L3MobileIdentity mobileIdentity = req->mobileIdentity();
	resolveIMSI(mobileIdentity,LCH);


	// See GSM 04.11 Arrow Diagram A5 for the transaction
	// Step 1	MS->Network	CP-DATA containing RP-DATA
	// Step 2	Network->MS	CP-ACK
	// Step 3	Network->MS	CP-DATA containing RP-ACK
	// Step 4	MS->Network	CP-ACK

	// LAPDm operation, from GSM 04.11, Annex F:
	// """
	// Case A: Mobile originating short message transfer, no parallel call:
	// The mobile station side will initiate SAPI 3 establishment by a SABM command
	// on the SDCCH after the cipher mode has been set. If no hand over occurs, the
	// SAPI 3 link will stay up until the last CP-ACK is received by the MSC, and
	// the clearing procedure is invoked.
	// """

	// FIXME: check provisioning

	// Let the phone know we're going ahead with the transaction.
	LOG(INFO) << "sending CMServiceAccept";
	LCH->send(L3CMServiceAccept());
	// Wait for SAP3 to connect.
	// The first read on SAP3 is the ESTABLISH primitive.
	delete getFrameSMS(LCH,ESTABLISH);

	// Step 1
	// Now get the first message.
	// Should be CP-DATA, containing RP-DATA.
	L3Frame *CM = getFrameSMS(LCH);
	LOG(DEBUG) << "data from MS " << *CM;
	if (CM->MTI()!=CPMessage::DATA) {
		LOG(NOTICE) << "unexpected SMS CP message with TI=" << CM->MTI();
		throw UnexpectedMessage();
	}
	unsigned TI = CM->TIValue();

	// Step 2
	// Respond with CP-ACK.
	// This just means that we got the message.
	LOG(INFO) << "sending CPAck";
	LCH->send(CPAck(1,TI),3);

	// Parse the message in CM and process RP part.
	// This is where we actually parse the message and send it out.
	// FIXME -- We need to set the message ref correctly,
	// even if the parsing fails.
	// The compiler gives a warning here.  Let it.  It will remind someone to fix it.
	unsigned ref;
	bool success = false;
	try {
		CPData data;
		data.parse(*CM);
		delete CM;
		LOG(INFO) << "CPData " << data;
		// Transfer out the RPDU -> TPDU -> delivery.
		ref = data.RPDU().reference();
		// This handler invokes higher-layer parsers, too.
		success = handleRPDU(mobileIdentity,data.RPDU());
	}
	catch (SMSReadError) {
		LOG(WARN) << "SMS parsing failed (above L3)";
		// Cause 95, "semantically incorrect message".
		LCH->send(CPData(1,TI,RPError(95,ref)),3);
		throw UnexpectedMessage();
	}
	catch (L3ReadError) {
		LOG(WARN) << "SMS parsing failed (in L3)";
		throw UnsupportedMessage();
	}

	// Step 3
	// Send CP-DATA containing RP-ACK and message reference.
	if (success) {
		LOG(INFO) << "sending RPAck in CPData";
		LCH->send(CPData(1,TI,RPAck(ref)),3);
	} else {
		LOG(INFO) << "sending RPError in CPData";
		// Cause 127 is "internetworking error, unspecified".
		// See GSM 04.11 Table 8.4.
		LCH->send(CPData(1,TI,RPError(127,ref)),3);
	}

	// Step 4
	// Get CP-ACK from the MS.
	CM = getFrameSMS(LCH);
	if (CM->MTI()!=CPMessage::ACK) {
		LOG(NOTICE) << "unexpected SMS CP message with TI=" << CM->MTI();
		throw UnexpectedMessage();
	}
	LOG(DEBUG) << "ack from MS: " << *CM;
	CPAck ack;
	ack.parse(*CM);
	LOG(INFO) << "CPAck " << ack;

	// RRLP Here if enabled
	if (gConfig.defines("GSM.RRLP") && gConfig.getNum("GSM.RRLP") == 1 &&
		gConfig.defines("RRLP.LocationUpdate") && gConfig.getNum("RRLP.LocationUpdate") == 1 /* RRLP? */)
	{
		Timeval start;
		RRLP::collectMSInfo(mobileIdentity, LCH, true /* DO RRLP */);
		LOG(INFO) << "submitSMS with RRLP took " << start.elapsed() << " for IMSI " << mobileIdentity;
	}

	// Done.
	LOG(INFO) << "closing";
	LCH->send(L3ChannelRelease());
}
Ejemplo n.º 2
0
void Control::MOSMSController(const GSM::L3CMServiceRequest *req, GSM::LogicalChannel *LCH)
{
	assert(req);
	assert(req->serviceType().type() == GSM::L3CMServiceType::ShortMessage);
	assert(LCH);
	assert(LCH->type() != GSM::SACCHType);

	LOG(INFO) << "MOSMS, req " << *req;

	// If we got a TMSI, find the IMSI.
	// Note that this is a copy, not a reference.
	GSM::L3MobileIdentity mobileID = req->mobileID();
	resolveIMSI(mobileID,LCH);

	// Create a transaction record.
	TransactionEntry *transaction = new TransactionEntry(gConfig.getStr("SIP.Proxy.SMS").c_str(),mobileID,LCH);
	gTransactionTable.add(transaction);
	LOG(DEBUG) << "MOSMS: transaction: " << *transaction;

	// See GSM 04.11 Arrow Diagram A5 for the transaction
	// Step 1	MS->Network	CP-DATA containing RP-DATA
	// Step 2	Network->MS	CP-ACK
	// Step 3	Network->MS	CP-DATA containing RP-ACK
	// Step 4	MS->Network	CP-ACK

	// LAPDm operation, from GSM 04.11, Annex F:
	// """
	// Case A: Mobile originating short message transfer, no parallel call:
	// The mobile station side will initiate SAPI 3 establishment by a SABM command
	// on the DCCH after the cipher mode has been set. If no hand over occurs, the
	// SAPI 3 link will stay up until the last CP-ACK is received by the MSC, and
	// the clearing procedure is invoked.
	// """

	// FIXME: check provisioning

	if (gConfig.getNum("GSM.Authentication")||gConfig.getNum("GSM.Encryption")) {
		AuthenticationParameters authParams(mobileID);
		registerIMSI(authParams, LCH);
		authenticate(authParams, LCH);
	}

	// Let the phone know we're going ahead with the transaction.
	if (LCH->isDecrypting()) {
		LOG(INFO) << "Decryption ACTIVE for:" << mobileID << " CMServiceAccept NOT sent, because CipherModeCommand implies it.";
	}
	else {
		LOG(INFO) << "Decryption NOT active for: " << mobileID << " Sending CMServiceAccept";
		LCH->send(GSM::L3CMServiceAccept());
	}


	// Wait for SAP3 to connect.
	// The first read on SAP3 is the ESTABLISH primitive.
	delete getFrameSMS(LCH,GSM::ESTABLISH);

	// Step 1
	// Now get the first message.
	// Should be CP-DATA, containing RP-DATA.
	GSM::L3Frame *CM = getFrameSMS(LCH);
	LOG(DEBUG) << "data from MS " << *CM;
	if (CM->MTI()!=CPMessage::DATA) {
		LOG(NOTICE) << "unexpected SMS CP message with TI=" << CM->MTI();
		delete CM;
		throw UnexpectedMessage();
	}
	unsigned L3TI = CM->TI() | 0x08;
	transaction->L3TI(L3TI);

	// Step 2
	// Respond with CP-ACK.
	// This just means that we got the message.
	LOG(INFO) << "sending CPAck";
	LCH->send(CPAck(L3TI),3);

	// Parse the message in CM and process RP part.
	// This is where we actually parse the message and send it out.
	// FIXME -- We need to set the message ref correctly,
	// even if the parsing fails.
	// The compiler gives a warning here.  Let it.  It will remind someone to fix it.
	unsigned ref;
	bool success = false;
	try {
		CPData data;
		data.parse(*CM);
		LOG(INFO) << "CPData " << data;
		// Transfer out the RPDU -> TPDU -> delivery.
		ref = data.RPDU().reference();
		// This handler invokes higher-layer parsers, too.
		success = handleRPDU(transaction,data.RPDU());
	}
	catch (SMSReadError) {
		LOG(WARNING) << "SMS parsing failed (above L3)";
		// Cause 95, "semantically incorrect message".
		LCH->send(CPData(L3TI,RPError(95,ref)),3);
		delete CM;
		throw UnexpectedMessage();
	}
	catch (GSM::L3ReadError) {
		LOG(WARNING) << "SMS parsing failed (in L3)";
		delete CM;
		throw UnsupportedMessage();
	}
	delete CM;

	// Step 3
	// Send CP-DATA containing RP-ACK and message reference.
	if (success) {
		LOG(INFO) << "sending RPAck in CPData";
		LCH->send(CPData(L3TI,RPAck(ref)),3);
	} else {
		LOG(INFO) << "sending RPError in CPData";
		// Cause 127 is "internetworking error, unspecified".
		// See GSM 04.11 Table 8.4.
		LCH->send(CPData(L3TI,RPError(127,ref)),3);
	}

	// Step 4
	// Get CP-ACK from the MS.
	CM = getFrameSMS(LCH);
	if (CM->MTI()!=CPMessage::ACK) {
		LOG(NOTICE) << "unexpected SMS CP message with TI=" << CM->MTI();
		throw UnexpectedMessage();
	}
	LOG(DEBUG) << "ack from MS: " << *CM;
	CPAck ack;
	ack.parse(*CM);
	delete CM;
	LOG(INFO) << "CPAck " << ack;

	/* MOSMS RLLP request */
	if (gConfig.defines("Control.SMS.QueryRRLP")) {
		// Query for RRLP
		if (!sendRRLP(mobileID, LCH)) {
			LOG(INFO) << "RRLP request failed";
		}
	}

	// Done.
	LCH->send(GSM::L3ChannelRelease());
	gTransactionTable.remove(transaction);
	LOG(INFO) << "closing the Um channel";
}
Ejemplo n.º 3
0
void Control::InCallMOSMSController(const CPData *cpData, TransactionEntry* transaction, GSM::SACCHLogicalChannel *LCH)
{
	LOG(INFO) << *cpData;

	// See GSM 04.11 Arrow Diagram A5 for the transaction
	// Step 1	MS->Network	CP-DATA containing RP-DATA
	// Step 2	Network->MS	CP-ACK
	// Step 3	Network->MS	CP-DATA containing RP-ACK
	// Step 4	MS->Network	CP-ACK

	// LAPDm operation, from GSM 04.11, Annex F:
	// """
	// Case C: Mobile originating short message transfer, parallel call. 
	// The mobile station will send a SABM command on the SACCH when a CM_SERV_ACC
	// message has been received from the network, allowing the short message
	// transfer to start. If no hand over occurs the link will stay up until the
	// MSC orders a explicit release, or the clearing procedure is invoked. If the
	// parallel call is cleared before the short message transfer is finalized, the
	// MSC will delay the clearing procedure toward the BSS, i.e. the channel
	// release procedure is delayed. 
	// """

	// Since there's a parallel call, we will assume correct provisioning.
	// And we know that CM and SABM are established.

	// Step 1 already happened in the SACCH service loop.
	// Just get the L3 TI and set the high bit since it originated in the MS.
	unsigned L3TI = cpData->TI() | 0x08;
	transaction->L3TI(L3TI);

	// Step 2
	// Respond with CP-ACK.
	// This just means that we got the message.
	LOG(INFO) << "sending CPAck";
	LCH->send(CPAck(L3TI),3);

	// Parse the message in CM and process RP part.
	// This is where we actually parse the message and send it out.
	// FIXME -- We need to set the message ref correctly,
	// even if the parsing fails.
	// The compiler gives a warning here.  Let it.  It will remind someone to fix it.
	unsigned ref;
	bool success = false;
	try {
		CPData data;
		data.parse(*cpData);
		LOG(INFO) << "CPData " << data;
		// Transfer out the RPDU -> TPDU -> delivery.
		ref = data.RPDU().reference();
		// This handler invokes higher-layer parsers, too.
		success = handleRPDU(transaction,data.RPDU());
	}
	catch (SMSReadError) {
		LOG(WARNING) << "SMS parsing failed (above L3)";
		// Cause 95, "semantically incorrect message".
		LCH->send(CPData(L3TI,RPError(95,ref)),3);
		throw UnexpectedMessage(transaction->ID());
	}
	catch (GSM::L3ReadError) {
		LOG(WARNING) << "SMS parsing failed (in L3)";
		throw UnsupportedMessage(transaction->ID());
	}

	// Step 3
	// Send CP-DATA containing RP-ACK and message reference.
	if (success) {
		LOG(INFO) << "sending RPAck in CPData";
		LCH->send(CPData(L3TI,RPAck(ref)),3);
	} else {
		LOG(INFO) << "sending RPError in CPData";
		// Cause 127 is "internetworking error, unspecified".
		// See GSM 04.11 Table 8.4.
		LCH->send(CPData(L3TI,RPError(127,ref)),3);
	}

	// Step 4
	// Get CP-ACK from the MS.
	GSM::L3Frame* CM = getFrameSMS(LCH);
	if (CM->MTI()!=CPMessage::ACK) {
		LOG(NOTICE) << "unexpected SMS CP message with MTI=" << CM->MTI() << " " << *CM;
		throw UnexpectedMessage(transaction->ID());
	}
	LOG(DEBUG) << "ack from MS: " << *CM;
	CPAck ack;
	ack.parse(*CM);
	LOG(INFO) << "CPAck " << ack;

	/* I had a hell of a time testing this with my B100
	   I know it went off, that's all. If things fail, look
	   here -kurtis */

	/* MOSMS RLLP request */
	if (gConfig.defines("Control.SMS.QueryRRLP")) {
		// Query for RRLP
		if (!sendRRLP(transaction->subscriber(), LCH)) {
			LOG(INFO) << "RRLP request failed";
		}
	}

	gTransactionTable.remove(transaction);
}
Ejemplo n.º 4
0
void Control::InCallMOSMSController(const CPData *cpData, TransactionEntry* transaction, UMTS::DCCHLogicalChannel *LCH)
{
	LOG(INFO) << *cpData;

	// FIXME -- We know this will be broken in UMTS.

	// Step 1 already happened in the SACCH service loop.
	// Just get the L3 TI and set the high bit since it originated in the MS.
	unsigned L3TI = cpData->TI() | 0x08;
	transaction->L3TI(L3TI);

	// Step 2
	// Respond with CP-ACK.
	// This just means that we got the message.
	LOG(INFO) << "sending CPAck";
	LCH->send(CPAck(L3TI),3);

	// Parse the message in CM and process RP part.
	// This is where we actually parse the message and send it out.
	// FIXME -- We need to set the message ref correctly,
	// even if the parsing fails.
	// The compiler gives a warning here.  Let it.  It will remind someone to fix it.
	unsigned ref;
	bool success = false;
	try {
		CPData data;
		data.parse(*cpData);
		LOG(INFO) << "CPData " << data;
		// Transfer out the RPDU -> TPDU -> delivery.
		ref = data.RPDU().reference();
		// This handler invokes higher-layer parsers, too.
		success = handleRPDU(transaction,data.RPDU());
	}
	catch (SMSReadError) {
		LOG(WARNING) << "SMS parsing failed (above L3)";
		// Cause 95, "semantically incorrect message".
		LCH->send(CPData(L3TI,RPError(95,ref)),3);
		throw UnexpectedMessage(transaction->ID());
	}
	catch (GSM::L3ReadError) {
		LOG(WARNING) << "SMS parsing failed (in L3)";
		throw UnsupportedMessage(transaction->ID());
	}

	// Step 3
	// Send CP-DATA containing RP-ACK and message reference.
	if (success) {
		LOG(INFO) << "sending RPAck in CPData";
		LCH->send(CPData(L3TI,RPAck(ref)),3);
	} else {
		LOG(INFO) << "sending RPError in CPData";
		// Cause 127 is "internetworking error, unspecified".
		// See GSM 04.11 Table 8.4.
		LCH->send(CPData(L3TI,RPError(127,ref)),3);
	}

	// Step 4
	// Get CP-ACK from the MS.
	GSM::L3Frame* CM = getFrameSMS(LCH);
	if (CM->MTI()!=CPMessage::ACK) {
		LOG(NOTICE) << "unexpected SMS CP message with MTI=" << CM->MTI() << " " << *CM;
		throw UnexpectedMessage(transaction->ID());
	}
	LOG(DEBUG) << "ack from MS: " << *CM;
	CPAck ack;
	ack.parse(*CM);
	LOG(INFO) << "CPAck " << ack;

	gTransactionTable.remove(transaction);
}