Octstr *radius_pdu_pack(RADIUS_PDU *pdu) { Octstr *os,*oos; Octstr *temp; os = octstr_create(""); gw_assert(pdu != NULL); /* switch (pdu->type) { #define INTEGER(name, octets) p = *(&p); #define NULTERMINATED(name, max_octets) p = *(&p); #define OCTETS(name, field_giving_octets) \ p->field_giving_octets = octstr_len(p->name); #define PDU(name, id, fields) \ case id: { struct name *p = &pdu->u.name; fields } break; #include "radius_pdu.def" default: error(0, "Unknown RADIUS_PDU type, internal error while packing."); } */ switch (pdu->type) { #define INTEGER(name, octets) \ append_encoded_integer(os, p->name, octets); #define OCTETS(name, field_giving_octets) \ octstr_append(os, p->name); #define PDU(name, id, fields) \ case id: { struct name *p = &pdu->u.name; fields; oos = radius_attr_pack(pdu); \ octstr_append(os, oos);octstr_destroy(oos); } break; #include "radius_pdu.def" default: error(0, "Unknown RADIUS_PDU type, internal error while packing."); } /* now set PDU length */ temp = octstr_create(""); append_encoded_integer(temp, octstr_len(os), 2); octstr_delete(os, 2, 2); octstr_insert(os, temp, 2); octstr_destroy(temp); return os; }
Octstr *smpp_pdu_pack(SMPP_PDU *pdu) { Octstr *os; Octstr *temp; os = octstr_create(""); gw_assert(pdu != NULL); /* * Fix lengths of octet string fields. */ switch (pdu->type) { #define OPTIONAL_BEGIN #define TLV_INTEGER(name, octets) #define TLV_NULTERMINATED(name, max_len) #define TLV_OCTETS(name, min_len, max_len) #define OPTIONAL_END #define INTEGER(name, octets) p = *(&p); #define NULTERMINATED(name, max_octets) p = *(&p); #define OCTETS(name, field_giving_octets) \ p->field_giving_octets = octstr_len(p->name); #define PDU(name, id, fields) \ case id: { struct name *p = &pdu->u.name; fields } break; #include "smpp_pdu.def" default: error(0, "Unknown SMPP_PDU type, internal error while packing."); } switch (pdu->type) { #define TL(name, octets) \ append_encoded_integer(os, SMPP_##name, 2); \ append_encoded_integer(os, octets, 2); #define OPTIONAL_BEGIN #define TLV_INTEGER(name, octets) \ if (p->name != -1) { \ TL(name, octets); \ INTEGER(name, octets) \ } #define TLV_NULTERMINATED(name, max_len) \ if (p->name != NULL) { \ TL(name, (octstr_len(p->name) > max_len ? max_len : octstr_len(p->name))); \ NULTERMINATED(name, max_len) \ } #define TLV_OCTETS(name, min_len, max_len) \ if (p->name != NULL) { \ unsigned long len = octstr_len(p->name); \ if (len > max_len || len < min_len) { \ error(0, "SMPP: Optional field (%s) with invalid length (%ld) (should be %d - %d) dropped.", \ #name, len, min_len, max_len);\ } else { \ TL(name, len); \ octstr_append(os, p->name); \ } \ } #define OPTIONAL_END #define INTEGER(name, octets) \ append_encoded_integer(os, p->name, octets); #define NULTERMINATED(name, max_octets) \ if (p->name != NULL) { \ if (octstr_len(p->name) >= max_octets) { \ warning(0, "SMPP: PDU element <%s> too long " \ "(length is %ld, should be %d)", \ #name, octstr_len(p->name), max_octets-1); \ temp = octstr_copy(p->name, 0, max_octets-1); \ } else \ temp = octstr_duplicate(p->name); \ octstr_append(os, temp); \ octstr_destroy(temp); \ } \ octstr_append_char(os, '\0'); #define OCTETS(name, field_giving_octets) \ if (p->name) octstr_append(os, p->name); #define PDU(name, id, fields) \ case id: { struct name *p = &pdu->u.name; fields } break; #include "smpp_pdu.def" default: error(0, "Unknown SMPP_PDU type, internal error while packing."); } temp = octstr_create(""); append_encoded_integer(temp, octstr_len(os) + 4, 4); octstr_insert(os, temp, 0); octstr_destroy(temp); return os; }
Octstr *smpp_pdu_pack(Octstr *smsc_id, SMPP_PDU *pdu) { Octstr *os; Octstr *temp; os = octstr_create(""); gw_assert(pdu != NULL); /* * Fix lengths of octet string fields. */ switch (pdu->type) { #define OPTIONAL_BEGIN #define TLV_INTEGER(name, octets) #define TLV_NULTERMINATED(name, max_len) #define TLV_OCTETS(name, min_len, max_len) #define OPTIONAL_END #define INTEGER(name, octets) p = *(&p); #define NULTERMINATED(name, max_octets) p = *(&p); #define OCTETS(name, field_giving_octets) \ p->field_giving_octets = octstr_len(p->name); #define PDU(name, id, fields) \ case id: { struct name *p = &pdu->u.name; fields } break; #include "smpp_pdu.def" default: error(0, "Unknown SMPP_PDU type, internal error while packing."); } switch (pdu->type) { #define TL(name, octets) \ append_encoded_integer(os, SMPP_##name, 2); \ append_encoded_integer(os, octets, 2); #define OPTIONAL_BEGIN #define TLV_INTEGER(name, octets) \ if (p->name >= 0) { \ TL(name, octets); \ INTEGER(name, octets) \ } #define TLV_NULTERMINATED(name, max_len) \ if (p->name != NULL) { \ TL(name, (octstr_len(p->name) > max_len ? max_len : octstr_len(p->name) + 1)); \ NULTERMINATED(name, max_len) \ } #define TLV_OCTETS(name, min_len, max_len) \ if (p->name != NULL) { \ unsigned long len = octstr_len(p->name); \ if (len > max_len || len < min_len) { \ error(0, "SMPP: Optional field (%s) with invalid length (%ld) (should be %d - %d) dropped.", \ #name, len, min_len, max_len);\ } else { \ TL(name, len); \ octstr_append(os, p->name); \ } \ } #define OPTIONAL_END \ if (p->tlv != NULL) { \ Octstr *key; \ List *keys; \ struct smpp_tlv *tlv; \ keys = dict_keys(p->tlv); \ while(keys != NULL && (key = gwlist_extract_first(keys)) != NULL) { \ tlv = smpp_tlv_get_by_name(smsc_id, key); \ if (tlv == NULL) { \ error(0, "SMPP: Unknown TLV `%s', don't send.", octstr_get_cstr(key)); \ octstr_destroy(key); \ continue; \ } \ switch(tlv->type) { \ case SMPP_TLV_INTEGER: { \ long val = atol(octstr_get_cstr(dict_get(p->tlv, key))); \ append_encoded_integer(os, tlv->tag, 2); \ append_encoded_integer(os, tlv->length, 2); \ append_encoded_integer(os, val, tlv->length); \ break; \ } \ case SMPP_TLV_OCTETS: \ case SMPP_TLV_NULTERMINATED: { \ Octstr *val = dict_get(p->tlv, key); \ unsigned long len = octstr_len(val); \ if (len > tlv->length) { \ error(0, "SMPP: Optional field (%s) with invalid length (%ld) (should be %ld) dropped.", \ octstr_get_cstr(key), len, tlv->length);\ octstr_destroy(key); \ continue; \ } \ append_encoded_integer(os, tlv->tag, 2); \ if (tlv->type == SMPP_TLV_NULTERMINATED) \ append_encoded_integer(os, len + 1, 2); \ else \ append_encoded_integer(os, len, 2); \ octstr_append(os, val); \ if (tlv->type == SMPP_TLV_NULTERMINATED) \ octstr_append_char(os, '\0'); \ break; \ } \ default: \ panic(0, "SMPP: Internal error, unknown configured TLV type %d.", tlv->type); \ break; \ } \ octstr_destroy(key); \ } \ gwlist_destroy(keys, octstr_destroy_item); \ } #define INTEGER(name, octets) \ append_encoded_integer(os, p->name, octets); #define NULTERMINATED(name, max_octets) \ if (p->name != NULL) { \ if (octstr_len(p->name) >= max_octets) { \ warning(0, "SMPP: PDU element <%s> too long " \ "(length is %ld, should be %d)", \ #name, octstr_len(p->name), max_octets-1); \ temp = octstr_copy(p->name, 0, max_octets-1); \ } else \ temp = octstr_duplicate(p->name); \ octstr_append(os, temp); \ octstr_destroy(temp); \ } \ octstr_append_char(os, '\0'); #define OCTETS(name, field_giving_octets) \ if (p->name) octstr_append(os, p->name); #define PDU(name, id, fields) \ case id: { struct name *p = &pdu->u.name; fields } break; #include "smpp_pdu.def" default: error(0, "Unknown SMPP_PDU type 0x%08lx, internal error while packing.", pdu->type); break; } temp = octstr_create(""); append_encoded_integer(temp, octstr_len(os) + 4, 4); octstr_insert(os, temp, 0); octstr_destroy(temp); return os; }