69 #define MIN_SMPP_PDU_LEN    (4*4)    71 #define MAX_SMPP_PDU_LEN    (7424)    73 #define DEFAULT_SMSC_ID "def;ault"   142         if (tmp_dict != NULL)
   149         if (tmp_dict != NULL)
   168         if (tmp_dict != NULL)
   175         if (tmp_dict != NULL)
   202         tlv = gw_malloc(
sizeof(*tlv));
   204             error(0, 
"SMPP: Unable to get name for smpp-tlv.");
   210             error(0, 
"SMPP: Unable to get tag for smpp-tlv.");
   215             error(0, 
"SMPP: Unable to get length for smpp-tlv.");
   220             error(0, 
"SMPP: Unable to get type for smpp-tlv.");
   256             if (tmp_dict == NULL) {
   269             if (tmp_dict == NULL) {
   285                 if (tmp_dict == NULL) {
   339     for (i = 0; i < octets; ++i)
   350     for (i = 0; i < octets; ++i)
   363         warning(0, 
"SMPP: PDU NULL terminated string (%s) has no NULL.", field_name);
   366     if (*pos + max_octets < nul) {
   367         error(0, 
"SMPP: PDU NULL terminated string (%s) longer than allowed.", field_name);
   370     *data = (nul - *pos > 0) ? 
octstr_copy(os, *pos, nul - *pos) : NULL;
   378     #define OPTIONAL_BEGIN   379     #define TLV_INTEGER(name, octets) OCTETS(name, octets)   380     #define TLV_NULTERMINATED(name, max_len) OCTETS(name, max_len)   381     #define TLV_OCTETS(name, min_len, max_len) OCTETS(name, min_len)   383     #define INTEGER(name, octets) OCTETS(name, octets)   384     #define NULTERMINATED(name, max_octets) OCTETS(name, max_octets)   385     #define OCTETS(name, field_giving_octetst) \   386             if (strncmp(#name, field_name, sizeof(#name) - 1) == 0) \   388     #define PDU(name, id, fields) \   404     pdu = gw_malloc(
sizeof(*pdu));
   408     #define OPTIONAL_BEGIN   409     #define TLV_INTEGER(name, octets) p->name = -1;   410     #define TLV_NULTERMINATED(name, max_len) p->name = NULL;   411     #define TLV_OCTETS(name, min_len, max_len) p->name = NULL;   412     #define OPTIONAL_END p->tlv = dict_create(1024, octstr_destroy_item);   413     #define INTEGER(name, octets) p->name = 0;   414     #define NULTERMINATED(name, max_octets) p->name = NULL;   415     #define OCTETS(name, field_giving_octetst) p->name = NULL;   416     #define PDU(name, id, fields) \   418             struct name *p = &pdu->u.name; \   419             pdu->type_name = #name; \   421             p->command_id = type; \   422             p->sequence_number = seq_no; \   426         error(0, 
"Unknown SMPP_PDU type, internal error.");
   440     #define OPTIONAL_BEGIN   441     #define TLV_INTEGER(name, octets) p->name = -1;   442     #define TLV_NULTERMINATED(name, max_octets) octstr_destroy(p->name);   443     #define TLV_OCTETS(name, min_len, max_len) octstr_destroy(p->name);   444     #define OPTIONAL_END dict_destroy(p->tlv);   445     #define INTEGER(name, octets) p->name = 0;    446     #define NULTERMINATED(name, max_octets) octstr_destroy(p->name);   447     #define OCTETS(name, field_giving_octets) octstr_destroy(p->name);   448     #define PDU(name, id, fields) \   449         case id: { struct name *p = &pdu->u.name; fields } break;   452         error(0, 
"Unknown SMPP_PDU type, internal error while destroying.");
   471     #define OPTIONAL_BEGIN   472     #define TLV_INTEGER(name, octets)   473     #define TLV_NULTERMINATED(name, max_len)   474     #define TLV_OCTETS(name, min_len, max_len)   476     #define INTEGER(name, octets) p = *(&p);   477     #define NULTERMINATED(name, max_octets) p = *(&p);   478     #define OCTETS(name, field_giving_octets) \   479         p->field_giving_octets = octstr_len(p->name);   480     #define PDU(name, id, fields) \   481         case id: { struct name *p = &pdu->u.name; fields } break;   484         error(0, 
"Unknown SMPP_PDU type, internal error while packing.");
   488     #define TL(name, octets) \   489         append_encoded_integer(os, SMPP_##name, 2); \   490         append_encoded_integer(os, octets, 2);   491     #define OPTIONAL_BEGIN   492     #define TLV_INTEGER(name, octets) \   493         if (p->name >= 0) { \   495             INTEGER(name, octets) \   497     #define TLV_NULTERMINATED(name, max_len) \   498         if (p->name != NULL) { \   499             TL(name, (octstr_len(p->name) > max_len ? max_len : octstr_len(p->name) + 1)); \   500             NULTERMINATED(name, max_len) \   502     #define TLV_OCTETS(name, min_len, max_len) \   503         if (p->name != NULL) { \   504             unsigned long len = octstr_len(p->name); \   505             if (len > max_len || len < min_len) { \   506                 error(0, "SMPP: Optional field (%s) with invalid length (%ld) (should be %d - %d) dropped.", \   507                     #name, len, min_len, max_len);\   510                 octstr_append(os, p->name); \   513     #define OPTIONAL_END \   514         if (p->tlv != NULL) { \   517             struct smpp_tlv *tlv; \   518             keys = dict_keys(p->tlv); \   519             while(keys != NULL && (key = gwlist_extract_first(keys)) != NULL) { \   520                 tlv = smpp_tlv_get_by_name(smsc_id, key); \   522                     if (!is_defined_field(pdu->type, octstr_get_cstr(key))) \   523                         error(0, "SMPP: Unknown TLV `%s', don't send.", octstr_get_cstr(key)); \   524                     octstr_destroy(key); \   527                 switch(tlv->type) { \   528                 case SMPP_TLV_INTEGER: { \   529                     long val = atol(octstr_get_cstr(dict_get(p->tlv, key))); \   530                     append_encoded_integer(os, tlv->tag, 2); \   531                     append_encoded_integer(os, tlv->length, 2); \   532                     append_encoded_integer(os, val, tlv->length); \   535                 case SMPP_TLV_OCTETS: \   536                 case SMPP_TLV_NULTERMINATED: { \   537                     Octstr *val = dict_get(p->tlv, key); \   538                     unsigned long len = octstr_len(val); \   539                     if (len > tlv->length) { \   540                         error(0, "SMPP: Optional field (%s) with invalid length (%ld) (should be %ld) dropped.", \   541                               octstr_get_cstr(key), len, tlv->length);\   542                         octstr_destroy(key); \   545                     append_encoded_integer(os, tlv->tag, 2); \   546                     if (tlv->type == SMPP_TLV_NULTERMINATED) \   547                         append_encoded_integer(os, len + 1, 2); \   549                         append_encoded_integer(os, len, 2); \   550                     octstr_append(os, val); \   551                     if (tlv->type == SMPP_TLV_NULTERMINATED) \   552                         octstr_append_char(os, '\0'); \   556                     panic(0, "SMPP: Internal error, unknown configured TLV type %d.", tlv->type); \   559                 octstr_destroy(key); \   561             gwlist_destroy(keys, octstr_destroy_item); \   563     #define INTEGER(name, octets) \   564         append_encoded_integer(os, p->name, octets);   565     #define NULTERMINATED(name, max_octets) \   566         if (p->name != NULL) { \   567             if (octstr_len(p->name) >= max_octets) { \   568                 warning(0, "SMPP: PDU element <%s> too long " \   569                         "(length is %ld, should be %d)", \   570                         #name, octstr_len(p->name), max_octets-1); \   571                 temp = octstr_copy(p->name, 0, max_octets-1); \   573                 temp = octstr_duplicate(p->name); \   574             octstr_append(os, temp); \   575             octstr_destroy(temp); \   577         octstr_append_char(os, '\0');   578     #define OCTETS(name, field_giving_octets) \   579         if (p->name) octstr_append(os, p->name);   580     #define PDU(name, id, fields) \   581         case id: { struct name *p = &pdu->u.name; fields } break;   584         error(0, 
"Unknown SMPP_PDU type 0x%08lx, internal error while packing.", pdu->
type);
   606         error(0, 
"SMPP: PDU was too short (%ld bytes).",
   623     #define OPTIONAL_BEGIN  \   625             while (pos + 4 <= len) { \   626                 struct smpp_tlv *tlv; \   627                 unsigned long opt_tag, opt_len; \   628                 opt_tag = decode_integer(data_without_len, pos, 2); pos += 2; \   629                 debug("sms.smpp", 0, "Optional parameter tag (0x%04lx)", opt_tag);  \   630                 opt_len = decode_integer(data_without_len, pos, 2); pos += 2;  \   631                 debug("sms.smpp", 0, "Optional parameter length read as %ld", opt_len); \   633                 tlv = smpp_tlv_get_by_tag(smsc_id, opt_tag); \   634                 if (tlv != NULL) debug("sms.smpp", 0, "Found configured optional parameter `%s'", octstr_get_cstr(tlv->name));   635     #define TLV_INTEGER(mname, octets) \   636                 if (SMPP_##mname == opt_tag) { \   638                     if (opt_len > octets) { \   639                         error(0, "SMPP: Optional field (%s) with invalid length (%ld) dropped.", #mname, opt_len); \   643                     INTEGER(mname, opt_len); \   644                     if (tlv != NULL) dict_put(p->tlv, tlv->name, octstr_format("%ld", p->mname)); \   646     #define TLV_NULTERMINATED(mname, max_len) \   647                 if (SMPP_##mname == opt_tag) { \   649                     if (opt_len > max_len || pos+opt_len > len) { \   650                         error(0, "SMPP: Optional field (%s) with invalid length (%ld) dropped.", #mname, opt_len);  \   654                     if(p->mname != NULL) { \   655                         warning(0, "SMPP: Optional field (%s) was sent more than once, overwriting", #mname); \   656                         octstr_destroy(p->mname); \   659                     copy_until_nul(#mname, data_without_len, &pos, opt_len, &p->mname); \   660                     if (tlv != NULL) dict_put(p->tlv, tlv->name, octstr_duplicate(p->mname)); \   662     #define TLV_OCTETS(mname, min_len, max_len) \   663                 if (SMPP_##mname == opt_tag) { \   665                     if (opt_len < min_len || opt_len > max_len || pos + opt_len > len) { \   666                         error(0, "SMPP: Optional field (%s) with invalid length (%ld) (should be %d - %d) dropped.", \   667                             #mname, opt_len, min_len, max_len);  \   671                     if(p->mname != NULL) { \   672                         warning(0, "SMPP: Optional field (%s) was sent more than once, overwriting", #mname); \   673                         octstr_destroy(p->mname); \   676                     p->mname = octstr_copy(data_without_len, pos, opt_len); \   678                     if (tlv != NULL) dict_put(p->tlv, tlv->name, octstr_duplicate(p->mname)); \   680     #define OPTIONAL_END \   682                     Octstr *val = NULL; \   686                         if (opt_len > tlv->length) { \   687                             error(0, "SMPP: Optional field (%s) with invalid length (%ld) (should be %ld) dropped.", \   688                                   octstr_get_cstr(tlv->name), opt_len, tlv->length); \   692                         switch (tlv->type) { \   693                         case SMPP_TLV_INTEGER: { \   695                             if ((val_i = decode_integer(data_without_len, pos, opt_len)) == -1) \   697                             val = octstr_format("%ld", val_i); \   698                             dict_put(p->tlv, tlv->name, val); \   702                         case SMPP_TLV_OCTETS: { \   703                             val = octstr_copy(data_without_len, pos, opt_len); \   704                             dict_put(p->tlv, tlv->name, val); \   708                         case SMPP_TLV_NULTERMINATED: { \   709                             if (copy_until_nul(octstr_get_cstr(tlv->name), data_without_len, &pos, opt_len, &val) == 0) \   710                                 dict_put(p->tlv, tlv->name, val); \   714                             panic(0, "SMPP: Internal error, unknown configured TLV type %d.", tlv->type); \   718                         val = octstr_copy(data_without_len, pos, opt_len); \   720                             octstr_binary_to_hex(val, 0); \   722                             val = octstr_create(""); \   723                         warning(0, "SMPP: Unknown TLV(0x%04lx,0x%04lx,%s) for PDU type (%s) received!", \   724                             opt_tag, opt_len, octstr_get_cstr(val), pdu->type_name); \   725                         octstr_destroy(val); \   731     #define INTEGER(name, octets) \   732         if ((p->name = decode_integer(data_without_len, pos, octets)) == -1) \   735     #define NULTERMINATED(name, max_octets) \   737         copy_until_nul(#name, data_without_len, &pos, max_octets, &p->name);   738     #define OCTETS(name, field_giving_octets) \   739         p->name = octstr_copy(data_without_len, pos, \   740                           p->field_giving_octets); \   741         if (p->field_giving_octets != (unsigned long) octstr_len(p->name)) { \   742             error(0, "smpp_pdu: error while unpacking '" #name "', " \   743                      "len is %ld but should have been %ld, dropping.", \   744                      octstr_len(p->name), p->field_giving_octets); \   747             pos += p->field_giving_octets; \   749     #define PDU(name, id, fields) \   750         case id: { struct name *p = &pdu->u.name; fields } break;   753         error(0, 
"Unknown SMPP_PDU type 0x%08lx, internal error while unpacking.", 
type);
   768     debug(
"sms.smpp", 0, 
"SMPP PDU %p dump:", (
void *) pdu);
   769     debug(
"sms.smpp", 0, 
"  type_name: %s", pdu->type_name);
   771     #define OPTIONAL_BEGIN   772     #define TLV_INTEGER(name, max_len) \   773         if (p->name != -1)  { \   774             INTEGER(name, max_len) \   776     #define TLV_NULTERMINATED(name, max_len) \   777         if (p->name != NULL) { \   778             NULTERMINATED(name, max_len) \   780     #define TLV_OCTETS(name, min_len, max_len) \   781         if (p->name != NULL) { \   782             OCTETS(name, max_len) \   784     #define OPTIONAL_END \   785         if (p->tlv != NULL) { \   788             struct smpp_tlv *tlv; \   789             keys = dict_keys(p->tlv); \   790             while(keys != NULL && (key = gwlist_extract_first(keys)) != NULL) { \   791                 tlv = smpp_tlv_get_by_name(smsc_id, key); \   793                     octstr_dump_short(dict_get(p->tlv, key), 2, octstr_get_cstr(key)); \   795                 octstr_destroy(key); \   797             gwlist_destroy(keys, octstr_destroy_item); \   799     #define INTEGER(name, octets) \   800         debug("sms.smpp", 0, "  %s: %lu = 0x%08lx", #name, p->name, p->name);   801     #define NULTERMINATED(name, max_octets) \   802         octstr_dump_short(p->name, 2, #name);   803     #define OCTETS(name, field_giving_octets) \   804         octstr_dump_short(p->name, 2, #name);   805     #define PDU(name, id, fields) \   806         case id: { struct name *p = &pdu->u.name; fields } break;   809         error(0, 
"Unknown SMPP_PDU type, internal error.");
   812     debug(
"sms.smpp", 0, 
"SMPP PDU dump ends.");
   822     #define OPTIONAL_BEGIN   823     #define TLV_INTEGER(name, max_len) \   824         if (p->name != -1)  { \   825             INTEGER(name, max_len) \   827     #define TLV_NULTERMINATED(name, max_len) \   828         if (p->name != NULL) { \   829             NULTERMINATED(name, max_len) \   831     #define TLV_OCTETS(name, min_len, max_len) \   832         if (p->name != NULL) { \   833             OCTETS(name, max_len) \   835     #define OPTIONAL_END \   836         if (p->tlv != NULL) { \   839             struct smpp_tlv *tlv; \   840             keys = dict_keys(p->tlv); \   841             while(keys != NULL && (key = gwlist_extract_first(keys)) != NULL) { \   842                 tlv = smpp_tlv_get_by_name(smsc_id, key); \   844                     Octstr *val = dict_get(p->tlv, key); \   845                     octstr_format_append(str, " [%E:%d:%E]", key, octstr_len(val), val); \   847                 octstr_destroy(key); \   849             gwlist_destroy(keys, octstr_destroy_item); \   851     #define INTEGER(name, octets) \   852         octstr_format_append(str, " [%s:0:0x%08lx]", #name, p->name);   853     #define NULTERMINATED(name, max_octets) \   854         octstr_format_append(str, " [%s:%d:%E]", #name, octstr_len(p->name), (p->name != NULL ? p->name : octstr_imm("NULL")));   855     #define OCTETS(name, field_giving_octets) \   856         octstr_format_append(str, " [%s:%d:%E]", #name, octstr_len(p->name), (p->name != NULL ? p->name : octstr_imm("NULL")));   857     #define PDU(name, id, fields) \   858         case id: { struct name *p = &pdu->u.name; fields } break;   861         error(0, 
"Unknown SMPP_PDU type, internal error.");
   872     unsigned char buf[4];    
   882     error(0, 
"SMPP: PDU length was too small (%ld, minimum is %ld).",
   887     error(0, 
"SMPP: PDU length was too large (%ld, maximum is %ld).",
   917             return "Message Length is invalid";
   919             return "Command Length is invalid";
   921             return "Invalid Command ID";
   923             return "Incorrect BIND Status for given command";
   925             return "ESME Already in Bound State";
   927             return "Invalid Priority Flag";
   929             return "Invalid Registered Delivery Flag";
   931             return "System Error";
   933             return "Invalid Source Address";
   935             return "Invalid Destination Address";
   937             return "Bind Failed";
   939             return "Invalid Password";
   941             return "Invalid System ID";
   943             return "Cancel SM Failed";
   945             return "Replace SM Failed";
   947             return "Message Queue Full";
   949             return "Invalid Service Type";
   951             return "Invalid number of destinations";
   953             return "Invalid Distribution List Name";
   955             return "Destination flag is invalid";
   957             return "Submit w/replace not supported/allowed";
   959             return "Invalid esm_class field data";
   961             return "Cannot Submit to Distribution List";
   963             return "Submit failed";
   965             return "Invalid Source address TON"; 
   967             return "Invalid Source address NPI";
   969             return "Invalid Destination address TON";
   971             return "Invalid Destination address NPI";
   973             return "Invalid system_type field";
   975             return "Invalid replace_if_present flag";
   977             return "Invalid number of messages";
   979             return "Throttling error";
   981             return "Invalid Scheduled Delivery Time";
   983             return "Invalid message validity period";
   985             return "Predefined Message ID is Invalid or specific predefined message was not found";
   987             return "ESME Receiver Temporary App Error Code";
   989             return "ESME Receiver Permanent App Error Code";
   991             return "ESME Receiver Reject Message Error Code";
   993             return "query_sm request failed";
   995             return "Error in optional part of the PDU Body";
   997             return "TLV not allowed";
   999             return "Invalid Parameter Length";
  1001             return "Expected TLV missing";
  1003             return "Invalid TLV value";
  1005             return "Transaction Delivery Failure";
  1007             return "Unknown Error";
  1009             return "ESME Not authorized to use specified service_type";
  1011             return "ESME Prohibited from using specified operation";
  1013             return "Specified service_type is unavailable";
  1015             return "Specified service_type is denied";
  1017             return "Invalid Data Coding Scheme";
  1019             return "Source Address Sub unit is invalid";
  1021             return "Destination Address Sub unit is invalid";
  1023             return "Broadcast Frequency Interval is invalid";
  1025             return "Broadcast Alias Name is invalid";
  1027             return "Broadcast Area Format is invalid";
  1029             return "Number of Broadcast Areas is invalid";
  1031             return "Broadcast Content Type is invalid";
  1033             return "Broadcast Message Class is invalid";
  1035             return "broadcast_sm operation failed";
  1037             return "broadcast_query_sm operation failed";
  1039             return "broadcast_cancel_sm operation failed";
  1041             return "Number of Repeated Broadcasts is invalid";
  1043             return "Broadcast Service Group is invalid";
  1045             return "Broadcast Channel Indicator is invalid";
  1050                 return "Vendor-specific error, please refer to your SMPP provider";
  1052                 return "Unknown/Reserved";
 Dict * dict_create(long size_hint, void(*destroy_value)(void *))
 
const char * smpp_error_to_string(enum SMPP_ERROR_MESSAGES error)
 
void smpp_pdu_destroy(SMPP_PDU *pdu)
 
void error(int err, const char *fmt,...)
 
int octstr_str_case_compare(const Octstr *ostr, const char *str)
 
gw_assert(wtls_machine->packet_to_send !=NULL)
 
void dict_put(Dict *dict, Octstr *key, void *value)
 
void gwlist_produce(List *list, void *item)
 
void smpp_tlv_add_constant(Octstr *smsc_id, Dict **tlvs)
 
void octstr_append_char(Octstr *ostr, int ch)
 
#define cfg_get(grp, varname)
 
static Dict * tlvs_by_name
 
long smpp_pdu_read_len(Connection *conn)
 
static void smpp_tlv_destroy(struct smpp_tlv *tlv)
 
#define octstr_get_cstr(ostr)
 
#define octstr_copy(ostr, from, len)
 
long octstr_search_char(const Octstr *ostr, int ch, long pos)
 
static Dict * tlvs_by_tag
 
static int copy_until_nul(const char *field_name, Octstr *os, long *pos, long max_octets, Octstr **data)
 
int smpp_pdu_shutdown(void)
 
Octstr * octstr_imm(const char *cstr)
 
void octstr_insert(Octstr *ostr1, const Octstr *ostr2, long pos)
 
void * gwlist_extract_first(List *list)
 
void * dict_get(Dict *dict, Octstr *key)
 
#define octstr_duplicate(ostr)
 
#define octstr_dump(ostr, level,...)
 
List * cfg_get_multi_group(Cfg *cfg, Octstr *name)
 
Octstr * smpp_pdu_pack(Octstr *smsc_id, SMPP_PDU *pdu)
 
SMPP_PDU * smpp_pdu_unpack(Octstr *smsc_id, Octstr *data_without_len)
 
void warning(int err, const char *fmt,...)
 
Octstr * octstr_format(const char *fmt,...)
 
void octstr_destroy(Octstr *ostr)
 
#define octstr_create(cstr)
 
void octstr_destroy_item(void *os)
 
void smpp_pdu_dump(Octstr *smsc_id, SMPP_PDU *pdu)
 
Octstr * smpp_pdu_read_data(Connection *conn, long len)
 
static struct smpp_tlv * smpp_tlv_get_by_tag(Octstr *smsc_id, long tag)
 
long octstr_len(const Octstr *ostr)
 
void dict_destroy(Dict *dict)
 
long decode_network_long(unsigned char *data)
 
static Dict * tlvs_by_const
 
void debug(const char *place, int err, const char *fmt,...)
 
static struct smpp_tlv * smpp_tlv_get_by_name(Octstr *smsc_id, Octstr *name)
 
int cfg_get_integer(long *n, CfgGroup *grp, Octstr *varname)
 
void octstr_format_append(Octstr *os, const char *fmt,...)
 
int smpp_pdu_init(Cfg *cfg)
 
static void append_encoded_integer(Octstr *os, unsigned long u, long octets)
 
List * dict_keys(Dict *dict)
 
Octstr * conn_read_fixed(Connection *conn, long length)
 
int dict_put_once(Dict *dict, Octstr *key, void *value)
 
void octstr_get_many_chars(char *buf, Octstr *ostr, long pos, long len)
 
int octstr_get_char(const Octstr *ostr, long pos)
 
List * octstr_split(const Octstr *os, const Octstr *sep)
 
SMPP_PDU * smpp_pdu_create(unsigned long type, unsigned long seq_no)
 
void smpp_pdu_dump_line(Octstr *smsc_id, SMPP_PDU *pdu)
 
static long decode_integer(Octstr *os, long pos, int octets)
 
static int is_defined_field(long type, const char *field_name)
 
void gwlist_destroy(List *list, gwlist_item_destructor_t *destructor)