/*******************************************/ /*Title: sclc.c */ /*Descr: SCCP Connectionless Control */ /*Author: Liang Hanxi */ /*Create: 2002-2-19 */ /*******************************************/ #include "./include/sccp.h" /*===========export================*/ int scrc2sclc ( Intra_Msg * pIntraMsg ); int sclc_rf ( Intra_Msg * pIntraMsg ); /* by simon at 23/9/26 */ extern SCCP_CSTA SccpCsta[96]; extern DWORD SccpCstaInd; extern LOCAL_SSN LocalSSN[256]; SCCP_SegMsgBuf sccp_segmsgbuf[MAX_SEGMSG_BUF]; extern struct sccp_msg_statistic { DWORD msg_mtp_scoc; DWORD msg_scoc_up; DWORD mnp_send; DWORD mnp_route; } sccpmsg_st; extern SCCP_Capture_Buf SCCPCapBuf; extern LOCAL_SSN LocalSSN[256]; extern int RelatedSSNNum; extern RL_SSN RelatedSSN[SCCP_RLSSN_NUM]; extern SCOC_BUF ScocBuf; extern SCCP_ROUTE RouteList[SCCP_ROUTE_NUM]; extern SCCP_OPT SCCP_Param; extern u8 MNP_Flag[2]; /*===========import================*/ extern int sclc2scmg ( Intra_Msg * intramsg ); //scmg.c extern int scrc_route ( Intra_Msg * pIntraMsg, BOOL ForceAnsi ); //scrc.c extern int scrc_mnp_route ( Intra_Msg * pIntraMsg, BOOL ForceAnsi ); //scrc.c extern int send_msg ( Intra_Msg * pIntraMsg ); //scrc.c extern void spLogDebug ( DWORD mask, const char *fmt, ... ); extern void spShowBCD(DWORD mask, BYTE *buf, int len); extern void spShowMsg(DWORD mask, const char *pDesc, Intra_Msg *pIntraMsg); extern void spLog ( char *info ); static SCLC_BUF SCLC_OutBuf; static SCLC_BUF SCLC_InBuf[MAX_SCLC_BUF]; /* buffer changed from 3 to 4, Pierre , 11-07 */ int RecvXUDTMsg ( Intra_Msg * pIntraMsg, BYTE nbuf ); int CheckSegUnID ( Intra_Msg * pIntraMsg ); int RsmRegMsg ( SCLC_MSG * pmsg, SCCP_SegMsgBuf * pSegMsgbuf, Intra_Msg * pIntraMsg ); extern void spLogSeg ( SCCP_SegMsgBuf * pSegMsgbuf ); int scrc2sclc ( Intra_Msg * pIntraMsg ) { SCLC_MSG *pmsg; short writesub, readsub; BYTE nbuf; SccpCsta[SccpCstaInd].utilization[4 - 3]++; if( pIntraMsg->msgMNP ) { nbuf = 1; sccpmsg_st.mnp_route++; if(pIntraMsg->msgsource == FROM_MTP) { pIntraMsg->SLS = LocalSSN[pIntraMsg->CDA.SSN].local+1; } } /* added by pierre for MNP , 2005-11-07 */ else { nbuf = LocalSSN[pIntraMsg->CDA.SSN].nbuf % 4; } switch ( pIntraMsg->msgtype ) { case UDT_MSG: break; case XUDT_MSG: switch ( RecvXUDTMsg ( pIntraMsg, nbuf ) ) { case 0: break; case 1: break; case 2: break; case 3: break; } return 0; case LUDT_MSG: spLogDebug ( SCCPDB_UDT | SCCPDB_ERR, "<005>LUDT/XUDT message is not supported" ); return 0; case UDTS_MSG: break; case XUDTS_MSG: case LUDTS_MSG: spLogDebug ( SCCPDB_UDT | SCCPDB_ERR, "<005>LUDTS/XUDTS message is not supported" ); return 0; } if( pIntraMsg->CDA.SSN == SSN_SCMG ) return sclc2scmg ( pIntraMsg ); else { writesub = SCLC_InBuf[nbuf].writesub; readsub = SCLC_InBuf[nbuf].readsub; pmsg = &SCLC_InBuf[nbuf].msglist[writesub]; pmsg->msglen = pIntraMsg->msglen % SCCP_MSG_MAXLEN; memcpy ( pmsg->msg, pIntraMsg->data, pmsg->msglen ); memcpy ( &( pmsg->src_addr ), &( pIntraMsg->CGA ), sizeof ( SCCP_ADDR ) ); memcpy ( &( pmsg->dst_addr ), &( pIntraMsg->CDA ), sizeof ( SCCP_ADDR ) ); pmsg->sls = pIntraMsg->SLS; if( ( SCLC_InBuf[nbuf].writesub + 1 ) == SCLC_InBuf[nbuf].readsub ) spShowMsg ( SCCPDB_UDT, "USER <== SCCP: buf overflow!!!!!!!", pIntraMsg ); SCLC_InBuf[nbuf].writesub = ( writesub + 1 ) % SS_MSG_NUM; if( SCLC_InBuf[nbuf].writesub == readsub ) SCLC_InBuf[nbuf].readsub = ( readsub + 1 ) % SS_MSG_NUM; if (pIntraMsg->msgtype == UDTS_MSG) { pmsg->primitive = N_NOTICE_IND; spShowMsg ( SCCPDB_UDT, "USER <== SCCP: N-NOTICE", pIntraMsg ); } else { pmsg->primitive = N_UNITDATA_IND; spShowMsg ( SCCPDB_UDT, "USER <== SCCP: UDT Message", pIntraMsg ); } } return 1; } int sclc_rf ( Intra_Msg * pIntraMsg ) { SCCP_ADDR swapaddr; spShowMsg ( SCCPDB_UDT | SCCPDB_ERR, "<006>Route Failure", pIntraMsg ); switch ( pIntraMsg->msgtype ) { case UDT_MSG: if( pIntraMsg->msgsource == FROM_MTP || pIntraMsg->msgsource == FROM_SCLC ) { memcpy ( &swapaddr, &( pIntraMsg->CDA ), sizeof ( SCCP_ADDR ) ); memcpy ( &( pIntraMsg->CDA ), &( pIntraMsg->CGA ), sizeof ( SCCP_ADDR ) ); memcpy ( &( pIntraMsg->CGA ), &swapaddr, sizeof ( SCCP_ADDR ) ); pIntraMsg->CDA.ip = 0xFFFFFFFF; if( pIntraMsg->CDA.RI == RI_SSN ) { if( pIntraMsg->CDA.DPC == 0 ) pIntraMsg->CDA.DPC = pIntraMsg->CGA.DPC; } pIntraMsg->msgsource = FROM_SCLC; pIntraMsg->msgtype = UDTS_MSG; return scrc_route ( pIntraMsg, 0 ); } break; case XUDT_MSG: case LUDT_MSG: //unsupported now break; case UDTS_MSG: break; case XUDTS_MSG: case LUDTS_MSG: //unsupported now break; } return -1; } int scmg2sclc ( Intra_Msg * pIntraMsg ) { return scrc_route ( pIntraMsg, 0 ); } /******************************************************************/ /*================== User Interface-----> ================*/ /******************************************************************/ int sclc_send ( SCLC_MSG * pmsg ) { if( pmsg->msglen > 256 ) { spLogDebug ( SCCPDB_ERR | SCCPDB_UDT, "<007>User ==> SCCP: Message's Length exceed 256" ); spShowBCD ( SCCPDB_ERR, pmsg->msg, pmsg->msglen % 256 ); return 0; } SccpCsta[SccpCstaInd].utilization[0]++; memcpy ( &SCLC_OutBuf.msglist[SCLC_OutBuf.writesub], pmsg, sizeof ( SCLC_MSG ) ); SCLC_OutBuf.writesub = ( SCLC_OutBuf.writesub + 1 ) % SS_MSG_NUM; if( SCLC_OutBuf.writesub == SCLC_OutBuf.readsub ) { spLogDebug ( SCCPDB_ERR | SCCPDB_UDT, "<008>SCLC Out Buffer Overflow" ); SCLC_OutBuf.readsub = ( SCLC_OutBuf.readsub + 1 ) % SS_MSG_NUM; } return 1; } int sclc_receive ( SCLC_MSG * pmsg, BYTE usertype ) { short readsub; usertype %= MAX_SCLC_BUF; /* revised by pierre */ readsub = SCLC_InBuf[usertype].readsub % SS_MSG_NUM; if( SCLC_InBuf[usertype].writesub == readsub ) return 0; memcpy ( pmsg, &SCLC_InBuf[usertype].msglist[readsub], sizeof ( SCLC_MSG ) ); SCLC_InBuf[usertype].readsub = ( readsub + 1 ) % SS_MSG_NUM; return 1; } void sclc_timer ( ) { Intra_Msg outmsg; SCLC_MSG *pmsg; int loop = 128; short readsub; int SegMsgIndex; for ( SegMsgIndex = 0; SegMsgIndex < MAX_SEGMSG_BUF; SegMsgIndex++ ) { if( sccp_segmsgbuf[SegMsgIndex].SegMsgTimer && sccp_segmsgbuf[SegMsgIndex].SegMsgTimer++ > MAX_SEGMSG_TIMER ) { spLogDebug ( SCCPDB_ERR, "SCCP XUDT Msg Timer Out. " ); spLogSeg ( &sccp_segmsgbuf[SegMsgIndex] ); memset ( &sccp_segmsgbuf[SegMsgIndex], 0, sizeof ( SCCP_SegMsgBuf ) ); } } while ( loop-- > 0 ) { if( SCLC_OutBuf.readsub == SCLC_OutBuf.writesub ) return; readsub = SCLC_OutBuf.readsub % SS_MSG_NUM; pmsg = &SCLC_OutBuf.msglist[readsub]; SCLC_OutBuf.readsub = ( readsub + 1 ) % SS_MSG_NUM; outmsg.msgsource = FROM_SCLC; outmsg.msgtype = UDT_MSG; outmsg.msgclass = 0; outmsg.SLS = pmsg->sls; outmsg.sequenceFlag = pmsg->sequence_control; memcpy ( &( outmsg.CDA ), &pmsg->dst_addr, sizeof ( SCCP_ADDR ) ); memcpy ( &( outmsg.CGA ), &pmsg->src_addr, sizeof ( SCCP_ADDR ) ); outmsg.NetID = outmsg.CGA.NetID = outmsg.CDA.NetID; // outmsg.CDA.TT = 0; outmsg.CDA.ip = 0xFFFFFFFF; outmsg.msglen = pmsg->msglen % 256; memcpy ( outmsg.data, pmsg->msg, pmsg->msglen % 256 ); if( MNP_Flag[0] != 0 && outmsg.CDA.NP == 1 && outmsg.CDA.SSN == 6 && pmsg->msg[0] == 0x62 ) { /* MNP supported */ if( MNP_Flag[1] != 2 ) /* Direct routing */ { if( MNP_Flag[0] == 1 && outmsg.CDA.TT != 0 ) { /* IN_based call related message */ spLogDebug ( SCCPDB_UDT, "User ==> SCCP: IN_based MNP and Call_related message, routed to HLR" ); //spShowMsg(SCCPDB_USER, "User ==> SCCP: UDT Message", &outmsg); //scrc_route(&outmsg); } else if( outmsg.CGA.SSN != 10 ) { spShowMsg ( SCCPDB_USER, "User ==> SCCP ==> MNP_SRF : UDT Message", &outmsg ); outmsg.msgMNP = 1; scrc2sclc ( &outmsg ); continue; } } } spShowMsg ( SCCPDB_USER, "User ==> SCCP: UDT Message", &outmsg ); scrc_route ( &outmsg, 0 ); } return; } /* added by Pierre for MNP, 2005-11-07 */ int sclc_mnp_send ( SCLC_MSG * pmsg ) { Intra_Msg outmsg; if( pmsg->msglen > 256 ) { spLogDebug ( SCCPDB_ERR | SCCPDB_UDT, "<007>User ==> SCCP: Message's Length exceed 256" ); spShowBCD ( SCCPDB_ERR, pmsg->msg, pmsg->msglen % 256 ); return 0; } SccpCsta[SccpCstaInd].utilization[0]++; sccpmsg_st.mnp_send++; outmsg.msgsource = FROM_SCLC; outmsg.msgtype = UDT_MSG; outmsg.msgclass = 0; outmsg.SLS = pmsg->sls; memcpy ( &( outmsg.CDA ), &pmsg->dst_addr, sizeof ( SCCP_ADDR ) ); memcpy ( &( outmsg.CGA ), &pmsg->src_addr, sizeof ( SCCP_ADDR ) ); outmsg.NetID = outmsg.CGA.NetID = outmsg.CDA.NetID; //outmsg.CDA.TT = 0; outmsg.CDA.ip = 0xFFFFFFFF; outmsg.msglen = pmsg->msglen % 256; memcpy ( outmsg.data, pmsg->msg, pmsg->msglen % 256 ); spShowMsg ( SCCPDB_USER, "User ==> SCCP: UDT Message", &outmsg ); return scrc_mnp_route ( &outmsg, 0 ); } //add for UDT SegmentingMsg to XUDT --lw 2007/03/20 int SegmentingMsg ( Intra_Msg * pIntraMsg ) { Intra_Msg pIntraMsgSeg1, pIntraMsgSeg2; int ret1, ret2; BYTE sSegLR[4]; ret1 = ret2 = 0; memcpy ( &pIntraMsgSeg1, pIntraMsg, sizeof ( Intra_Msg ) ); memcpy ( &pIntraMsgSeg2, pIntraMsg, sizeof ( Intra_Msg ) ); pIntraMsgSeg1.msglen = pIntraMsg->msglen / 2; pIntraMsgSeg2.msglen = pIntraMsg->msglen - pIntraMsgSeg1.msglen; memset ( &pIntraMsgSeg1.data[pIntraMsgSeg1.msglen], 0, SCCP_MSG_MAXLEN - pIntraMsgSeg1.msglen ); memcpy ( &pIntraMsgSeg2.data[0], &pIntraMsg->data[pIntraMsgSeg1.msglen], pIntraMsgSeg2.msglen ); memset ( &pIntraMsgSeg2.data[pIntraMsgSeg2.msglen], 0, SCCP_MSG_MAXLEN - pIntraMsgSeg2.msglen ); pIntraMsgSeg1.msgtype = pIntraMsgSeg2.msgtype = XUDT_MSG; pIntraMsgSeg1.SegPresent = pIntraMsgSeg2.SegPresent = 1; pIntraMsgSeg1.Segmnt.CBit = pIntraMsgSeg2.Segmnt.CBit = 1; //sequence pIntraMsgSeg1.Segmnt.FBit = 1; pIntraMsgSeg2.Segmnt.FBit = 0; pIntraMsgSeg1.Segmnt.RSBits = 1; pIntraMsgSeg2.Segmnt.RSBits = 0; pIntraMsgSeg1.Hop = pIntraMsgSeg1.Hop = 0; sSegLR[0] = ( SCCP_Param.ip >> 16 ) & 0x0001; //plant number sSegLR[1] = pIntraMsg->SLS; sSegLR[2] = SCCPCapBuf.watch_dog[128]++; memcpy ( pIntraMsgSeg1.Segmnt.SegLR, sSegLR, SEG_RS_LEN ); memcpy ( pIntraMsgSeg2.Segmnt.SegLR, sSegLR, SEG_RS_LEN ); spLogDebug ( SCCPDB_UDT, "SCCP =>SCCP_RegProc=> SCCP : Length [%d Bytes] [%d Bytes]\r\n", pIntraMsgSeg1.msglen, pIntraMsgSeg2.msglen ); ret1 = send_msg ( &pIntraMsgSeg1 ); ret2 = send_msg ( &pIntraMsgSeg2 ); return ( ret1 > 0 && ret2 > 0 ); } int RecvXUDTMsg ( Intra_Msg * pIntraMsg, BYTE nbuf ) { SCLC_MSG *pmsg; short writesub, readsub; int SegMsgIndex; if( !pIntraMsg->SegPresent ) //Not Include Segmentation Paramenters { return -1; } if( pIntraMsg->Segmnt.FBit == 1 && pIntraMsg->Segmnt.RSBits == 0 ) //Single Segmetaion { return -1; } SegMsgIndex = CheckSegUnID ( pIntraMsg ); if( SegMsgIndex == MAX_SEGMSG_BUF + 1 ) //check CGA SLR MTP3 routing lable is idle { return 0; } else if( SegMsgIndex == MAX_SEGMSG_BUF ) //first Segmentation { if( pIntraMsg->Segmnt.FBit != 1 ) { spLogDebug ( SCCPDB_ERR, "SCCP Recv new XUDT Msg but the Fbit is not 1." ); return 0; } for ( SegMsgIndex = 0; SegMsgIndex < MAX_SEGMSG_BUF; SegMsgIndex++ ) { if( sccp_segmsgbuf[SegMsgIndex].MsgState == SEGSTREAM_IDLE ) { int SegBlockIndex; SCCP_SegStream *pSegStream; SCCP_SegMsgBuf *pSegMsgbuf = &sccp_segmsgbuf[SegMsgIndex]; pSegMsgbuf->MsgClass = pIntraMsg->Segmnt.CBit; pSegMsgbuf->MsgTotal = pIntraMsg->Segmnt.RSBits + 1; pSegMsgbuf->RSE = pIntraMsg->Segmnt.RSBits - 1; pSegMsgbuf->SegID.DPC = pIntraMsg->DPC; pSegMsgbuf->SegID.OPC = pIntraMsg->OPC; pSegMsgbuf->SegID.SLS = pIntraMsg->SLS; memcpy ( &pSegMsgbuf->SegID.CGA, &pIntraMsg->CGA, sizeof ( SCCP_ADDR ) ); memcpy ( &pSegMsgbuf->SegID.SegLR, &pIntraMsg->Segmnt.SegLR, SEG_RS_LEN ); SegBlockIndex = pSegMsgbuf->MsgTotal - ( pIntraMsg->Segmnt.RSBits + 1 ); pSegStream = &pSegMsgbuf->SegStream[SegBlockIndex]; pSegStream->SegDataLen = pIntraMsg->msglen; memcpy ( &pSegStream->SegDataBlock, &pIntraMsg->data, pIntraMsg->msglen ); pSegMsgbuf->SegMsgTimer = 1; pSegMsgbuf->MsgState = SEGSTREAM_BUSY; return 1; } } if( SegMsgIndex == MAX_SEGMSG_BUF ) { spLogDebug ( SCCPDB_ERR, "SCCP Recv new XUDT but SCCP SegMsg buf is not enough" ); return 0; } } else //not first Segmentation { int SegBlockIndex; int i, j, linemax; char info[2560 * 3 + 512], temp_str[128]; SCCP_SegStream *pSegStream; SCCP_SegMsgBuf *pSegMsgbuf = &sccp_segmsgbuf[SegMsgIndex]; if( pIntraMsg->Segmnt.RSBits != pSegMsgbuf->RSE ) { spLogDebug ( SCCPDB_ERR, "SCCP Recv unexpect RS XUDT Msg , discard it" ); return 0; } if( pIntraMsg->Segmnt.FBit == 1 ) { spLogDebug ( SCCPDB_ERR, "SCCP Recv XUDT Msg dupulicate first segment. discard it" ); return 0; } SegBlockIndex = pSegMsgbuf->MsgTotal - ( pIntraMsg->Segmnt.RSBits + 1 ); pSegStream = &pSegMsgbuf->SegStream[SegBlockIndex]; if( pSegStream->SegDataLen ) { spLogDebug ( SCCPDB_ERR, "SCCP Recv XUDT Msg dupulicate segment, discard it[RS :%d]", pIntraMsg->Segmnt.RSBits ); return 0; } pSegStream->SegDataLen = pIntraMsg->msglen; memcpy ( &pSegStream->SegDataBlock, &pIntraMsg->data, pIntraMsg->msglen ); if( pSegMsgbuf->RSE ) { pSegMsgbuf->RSE--; return 1; } //last segment pSegMsgbuf->SegMsgTimer = 0; writesub = SCLC_InBuf[nbuf].writesub; readsub = SCLC_InBuf[nbuf].readsub; pmsg = &SCLC_InBuf[nbuf].msglist[writesub]; if( !RsmRegMsg ( pmsg, pSegMsgbuf, pIntraMsg ) ) { return 0; } if( ( SCLC_InBuf[nbuf].writesub + 1 ) == SCLC_InBuf[nbuf].readsub ) spShowMsg ( SCCPDB_UDT, "USER <== SCCP: buf overflow!!!!!!!", pIntraMsg ); SCLC_InBuf[nbuf].writesub = ( writesub + 1 ) % SS_MSG_NUM; if( SCLC_InBuf[nbuf].writesub == readsub ) SCLC_InBuf[nbuf].readsub = ( readsub + 1 ) % SS_MSG_NUM; spLog ( "\r\n\r\nUser <== SCCP_RegProc. XUDT Message" ); spLogSeg ( pSegMsgbuf ); info[0] = '\0'; sprintf ( temp_str, "Segmentaion Length info: \r\n" ); strcat ( info, temp_str ); for ( i = 0; i < pSegMsgbuf->MsgTotal; i++ ) { sprintf ( temp_str, "[%02d]:%d ", i, pSegMsgbuf->SegStream[i].SegDataLen ); strcat ( info, temp_str ); if( i == 7 ) { strcat ( info, "\r\n" ); } } spLog ( info ); memset ( info, 0, 2560 * 3 + 512 ); i = j = linemax = 0; while ( i * 16 < pmsg->msglen ) { if( ( linemax = pmsg->msglen - 16 * i ) > 16 ) linemax = 16; for ( j = 0; j < linemax; j++ ) { sprintf ( info + 3 * j + ( j > 7 ? 1 : 0 ), "%02X ", pmsg->msg[16 * i + j] ); if( j == 7 ) { sprintf ( info + 3 * 8, " " ); } } spLog ( info ); i++; } memset ( pSegMsgbuf, 0, sizeof ( SCCP_SegMsgBuf ) ); return 1; } return 0; } int CheckSegUnID ( Intra_Msg * pIntraMsg ) { int SegMsgIndex, nCheckFlag; SCCP_SegUnID *pSegId; nCheckFlag = 0; for ( SegMsgIndex = 0; SegMsgIndex < MAX_SEGMSG_BUF; SegMsgIndex++ ) { pSegId = &sccp_segmsgbuf[SegMsgIndex].SegID; if( memcmp ( &pSegId->SegLR, &pIntraMsg->Segmnt.SegLR, SEG_RS_LEN ) ) { continue; } if( pSegId->DPC != pIntraMsg->DPC ) //have routed , equal of course { spLogDebug ( SCCPDB_ERR, "SCCP XUDT Msg check MTP3 routing lable fail , DPC is not matched!" ); nCheckFlag = 1;; } if( pSegId->OPC != pIntraMsg->OPC ) { spLogDebug ( SCCPDB_ERR, "SCCP XUDT Msg check MTP3 routing lable fail , OPC is not matched!" ); nCheckFlag = 1; } if( pSegId->SLS != pIntraMsg->SLS ) { spLogDebug ( SCCPDB_ERR, "SCCP XUDT Msg check MTP3 routing lable fail , SLS is not matched!" ); nCheckFlag = 1; } if( memcmp ( &pSegId->CGA, &pIntraMsg->CGA, sizeof ( SCCP_ADDR ) ) ) { spLogDebug ( SCCPDB_ERR, "SCCP XUDT Msg check MTP3 routing lable fail , CGA is not matched!" ); nCheckFlag = 1; } if( nCheckFlag ) //act as a new segmention start { if( pIntraMsg->Segmnt.FBit == 1 && pIntraMsg->Segmnt.RSBits != 0 ) { return MAX_SEGMSG_BUF; } return MAX_SEGMSG_BUF + 1; } return SegMsgIndex; } return SegMsgIndex; } int RsmRegMsg ( SCLC_MSG * pmsg, SCCP_SegMsgBuf * pSegMsgbuf, Intra_Msg * pIntraMsg ) { int SegBlockIndex, XUDTMsgLen; SCCP_SegStream *pSegStream; XUDTMsgLen = 0; for ( SegBlockIndex = 0; SegBlockIndex < pSegMsgbuf->MsgTotal; SegBlockIndex++ ) { pSegStream = &pSegMsgbuf->SegStream[SegBlockIndex]; XUDTMsgLen += pSegStream->SegDataLen; } if( XUDTMsgLen > MAX_SCLCMSG_LEN ) { spLogDebug ( SCCPDB_ERR, "SCCP Reassemble XUDT Msg is too long ,discard it" ); return 0; } XUDTMsgLen = 0; for ( SegBlockIndex = 0; SegBlockIndex < pSegMsgbuf->MsgTotal; SegBlockIndex++ ) { pSegStream = &pSegMsgbuf->SegStream[SegBlockIndex]; memcpy ( pmsg->msg + XUDTMsgLen, pSegStream->SegDataBlock, pSegStream->SegDataLen ); XUDTMsgLen += pSegStream->SegDataLen; } pmsg->msglen = XUDTMsgLen; memcpy ( &( pmsg->src_addr ), &( pIntraMsg->CGA ), sizeof ( SCCP_ADDR ) ); memcpy ( &( pmsg->dst_addr ), &( pIntraMsg->CDA ), sizeof ( SCCP_ADDR ) ); return 1; }