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)