/*
Copyright (C) 2010- Alexander Chudnovets <[email protected]>
Based on SMS Server Tools 3
Copyright (C) 2006- Keijo Kasvi
http://smstools3.kekekasvi.com/
This program is free software unless you got it under another license directly
from the author. You can redistribute it and/or modify it under the terms of
the GNU General Public License as published by the Free Software Foundation.
Either version 2 of the License, or (at your option) any later version.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <iconv.h>
#include "pdu.h"
// Global constants. FIXME: set correct values
const int max_number = 64;
const int max_number_type = 1024;
const int max_smsc = 64;
const int max_date = 32;
const int max_time = 32;
const int max_udh_data = 512;
const int max_udh_type = 512;
const int max_err = 1024;
const int maxsms_binary = 140;
const int max_message = maxsms_binary * 4;
const int validity_period = 255;
const int max_pdu = 160;
const int udh_data_len=6;
// Utility functions
// Converts an octet to a 8-Bit value
// 把一个8位八位字节转换成8位值
int octet2bin(const char* octet)
{
int result = 0;
if (octet[0] > 57)
result += octet[0] - 55;
else
result += octet[0] - 48;
result = result << 4;
if (octet[1] > 57)
result += octet[1] - 55;
else
result += octet[1] - 48;
// printf("octet:%s\n",octet);
return result;
}
// Converts an octet to a 8bit value, returns < in case of error.
int octet2bin_check(const char *octet)
{
if (octet[0] == 0)
return -1;
if (octet[1] == 0)
return -2;
if (!isxdigit(octet[0]))
return -3;
if (!isxdigit(octet[1]))
return -4;
return octet2bin(octet);
}
// Swap every second character
void swapchars(char* string)
{
char c;
int length = strlen(string);
for (int i = 0; i < length - 1; i += 2)
{
c = string[i];
string[i] = string[i + 1];
string[i + 1] = c;
}
printf("swapchars:%s",string);
}
// Returns a length of udh (including UDHL), -1 if error.
// pdu is 0-terminated ascii(hex) pdu string with
// or without spaces.
int explain_udh(char *udh_type, const char *pdu)
{
int udh_length;
int idx;
char *pdu_ptr;
char *p;
const char *p1 = NULL;
int i;
char tmp[512];
char buffer[1024];
printf("explain_udh:udh_type:%s,pdu:%s",udh_type,pdu);
*udh_type = 0;
if (strlen(pdu) >= sizeof(buffer))
return -1;
strcpy(buffer, pdu);
while ((p = strchr(buffer, ' ')))
memmove(p, p + 1, strlen(p + 1) + 1);
//strcpyo(p, p +1);
if ((udh_length = octet2bin_check(buffer)) < 0)
return -1;
udh_length++;
if ((size_t)(udh_length *2) > strlen(buffer))
return -1;
sprintf(udh_type, "Length=%i", udh_length);
idx = 1;
while (idx < udh_length)
{
pdu_ptr = buffer + idx * 2;
p = NULL;
i = octet2bin_check(pdu_ptr);
switch (i)
{
case -1: return -1;
// 3GPP TS 23.040 version 6.8.1 Release 6 - ETSI TS 123 040 V6.8.1 (2006-10)
case 0x00: p1 = "Concatenated short messages, 8-bit reference number"; break;
case 0x01: p1 = "Special SMS Message Indication"; break;
case 0x02: p1 = "Reserved"; break;
//case 0x03: p = "Value not used to avoid misinterpretation as <LF> character"; break;
case 0x04: p1 = "Application port addressing scheme, 8 bit address"; break;
case 0x05: p1 = "Application port addressing scheme, 16 bit address"; break;
case 0x06: p1 = "SMSC Control Parameters"; break;
case 0x07: p1 = "UDH Source Indicator"; break;
case 0x08: p1 = "Concatenated short message, 16-bit reference number"; break;
case 0x09: p1 = "Wireless Control Message Protocol"; break;
case 0x0A: p1 = "Text Formatting"; break;
case 0x0B: p1 = "Predefined Sound"; break;
case 0x0C: p1 = "User Defined Sound (iMelody max 128 bytes)"; break;
case 0x0D: p1 = "Predefined Animation"; break;
case 0x0E: p1 = "Large Animation (16*16 times 4 = 32*4 =128 bytes)"; break;
case 0x0F: p1 = "Small Animation (8*8 times 4 = 8*4 =32 bytes)"; break;
case 0x10: p1 = "Large Picture (32*32 = 128 bytes)"; break;
case 0x11: p1 = "Small Picture (16*16 = 32 bytes)"; break;
case 0x12: p1 = "Variable Picture"; break;
case 0x13: p1 = "User prompt indicator"; break;
case 0x14: p1 = "Extended Object"; break;
case 0x15: p1 = "Reused Extended Object"; break;
case 0x16: p1 = "Compression Control"; break;
case 0x17: p1 = "Object Distribution Indicator"; break;
case 0x18: p1 = "Standard WVG object"; break;
case 0x19: p1 = "Character Size WVG object"; break;
case 0x1A: p1 = "Extended Object Data Request Command"; break;
case 0x20: p1 = "RFC 822 E-Mail Header"; break;
case 0x21: p1 = "Hyperlink format element"; break;
case 0x22: p1 = "Reply Address Element"; break;
case 0x23: p1 = "Enhanced Voice Mail Information"; break;
}
if (!p1)
{
if (i >= 0x1B && i <= 0x1F)
p1 = "Reserved for future EMS features";
else if (i >= 0x24 && i <= 0x6F)
p1 = "Reserved for future use";
else if (i >= 0x70 && i <= 0x7F)
p1 = "(U)SIM Toolkit Security Headers";
else if (i >= 0x80 && i <= 0x9F)
p1 = "SME to SME specific use";
else if (i >= 0xA0 && i <= 0xBF)
p1 = "Reserved for future use";
else if (i >= 0xC0 && i <= 0xDF)
p1 = "SC specific use";
else if (i >= 0xE0 && i <= 0xFF)
p1 = "Reserved for future use";
}
if (!p1)
p1 = "unknown";
sprintf(tmp, ", [%.2s]%s", pdu_ptr, p1);
if (strlen(udh_type) + strlen(tmp) >= (size_t)max_udh_type)
return -1;
sprintf(strchr(udh_type, 0), "%s", tmp);
// Next octet is length of data:
if ((i = octet2bin_check(pdu_ptr + 2)) < 0)
return -1;
if ((size_t)(i *2) > strlen(pdu_ptr + 4))
return -1;
idx += i + 2;
if (idx > udh_length)
return -1; // Incorrect UDL or length of Information Element.
}
return udh_length;
}
void explain_status(char *dest, size_t size_dest, int status)
{
const char *p = "unknown";
switch (status)
{
case 0: p = "Ok, short message received by the SME"; break;
case 1: p = "Ok, short message forwarded by the SC to the SME but the SC is unable to confirm delivery"; break;
case 2: p = "Ok, short message replaced by the SC"; break;
// Temporary error, SC still trying to transfer SM
case 32: p = "Still trying, congestion"; break;
case 33: p = "Still trying, SME busy"; break;
case 34: p = "Still trying, no response sendr SME"; break;
case 35: p = "Still trying, service rejected"; break;
case 36: p = "Still trying, quality of service not available"; break;
case 37: p = "Still trying, error in SME"; break;
// 38...47: Reserved
// 48...63: Values specific to each SC
// Permanent error, SC is not making any more transfer attempts
case 64: p = "Error, remote procedure error"; break;
case 65: p = "Error, incompatible destination"; break;
case 66: p = "Error, connection rejected by SME"; break;
case 67: p = "Error, not obtainable"; break;
case 68: p = "Error, quality of service not available"; break;
case 69: p = "Error, no interworking available"; break;
case 70: p = "Error, SM validity period expired"; break;
case 71: p = "Error, SM deleted by originating SME"; break;
case 72: p = "Error, SM deleted by SC administration"; break;
case 73: p = "Error, SM does not exist"; break;
// 74...79: Reserved
// 80...95: Values specific to each SC
// Permanent error, SC is not making any