diff options
Diffstat (limited to 'mcast/common/.svn/text-base/ciparser.c.svn-base')
-rw-r--r-- | mcast/common/.svn/text-base/ciparser.c.svn-base | 702 |
1 files changed, 702 insertions, 0 deletions
diff --git a/mcast/common/.svn/text-base/ciparser.c.svn-base b/mcast/common/.svn/text-base/ciparser.c.svn-base new file mode 100644 index 0000000..5ce563d --- /dev/null +++ b/mcast/common/.svn/text-base/ciparser.c.svn-base @@ -0,0 +1,702 @@ +/* + * (c) BayCom GmbH, http://www.baycom.de, info@baycom.de + * + * See the COPYING file for copyright information and + * how to reach the author. + * + */ + +//#define TESTING +#ifdef TESTING +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <netinet/in.h> +#include <stdlib.h> + +#include "ciparser.h" +static unsigned char ll[] = { 0x00, 0x01, 0xA0, 0x28, 0x01, 0x90, 0x02, 0x00, 0x05, 0x9F, 0x80, 0x32, 0x1F, 0x03, 0x32, 0xC9, 0x01, 0x00, 0x0F, 0x01, 0x09, 0x06, 0x17, 0x62, 0xE0, 0x65, 0x00, 0x09, 0x09, 0x04, 0x17, 0x02, 0xE1, 0x2D, 0x02, 0x00, 0xA0, 0x00, 0x00, 0x04, 0x00, 0xA1, 0x00, 0x00 }; +static unsigned char lr[] = { 0x00, 0x01, 0x80, 0x02, 0x01, 0x80 }; +static unsigned char la[] = { 0x00, 0x01, 0xA0, 0x07, 0x01, 0x91, 0x04, 0x00, 0x01, 0x00, 0x41, 0x80, 0x02, 0x01, 0x00 }; +static unsigned char lb[] = { 0x00, 0x01, 0xA0, 0x82, 0x00, 0x17, 0x01, 0x90, 0x02, 0x00, 0x03, 0x9F, 0x80, 0x31, 0x0E, 0x06, 0x02, 0x06, 0x02, 0x17, 0x02, 0x17, 0x62, 0x01, 0x00, 0x05, 0x00, 0x18, 0x00, 0x80, 0x02, 0x01, 0x00 }; +static unsigned char lc[] = { 0x01, 0x02, 0xA0, 0x5F, 0x02, 0x90, 0x02, 0x00, 0x06, 0x9F, 0x80, 0x32, 0x56, 0x03, 0x03, 0x8B, 0x01, 0x00, 0x00, 0x02, 0x00, 0xA3, 0x00, 0x23, 0x01, 0x09, 0x0F, 0x05, 0x00, 0xE2, 0xC3, 0x10, 0x01, 0x00, 0x13, 0x01, 0x20, 0x14, 0x03, 0x00, 0x94, 0x0D, 0x09, 0x0F, 0x05, 0x00, 0xE2, 0xCD, 0x10, 0x01, 0x00, 0x13, 0x01, 0x20, 0x14, 0x03, 0x02, 0x38, 0x08, 0x04, 0x00, 0x5C, 0x00, 0x23, 0x01, 0x09, 0x0F, 0x05, 0x00, 0xE2, 0xC3, 0x10, 0x01, 0x00, 0x13, 0x01, 0x20, 0x14, 0x03, 0x00, 0x94, 0x0D, 0x09, 0x0F, 0x05, 0x00, 0xE2, 0xCD, 0x10, 0x01, 0x00, 0x13, 0x01, 0x20, 0x14, 0x03, 0x02, 0x38, 0x08 }; +static unsigned char ld[] = { 0x00, 0x01, 0xA0, 0x82, 0x00, 0x10, 0x01, 0x90, 0x02, 0x00, 0x03, 0x9F, 0x80, 0x33, 0x07, 0x2D, 0xB9, 0x01, 0x81, 0x00, 0x08, 0x00, 0x80, 0x02, 0x01, 0x00 }; +static unsigned char le[] = { 0x00, 0x01, 0xA0, 0x34, 0x01, 0x90, 0x02, 0x00, 0x03, 0x9F, 0x80, 0x32, 0x2B, 0x03, 0x00, 0x0B, 0x01, 0x00, 0x11, 0x01, 0x09, 0x06, 0x17, 0x22, 0xF0, 0x0B, 0x00, 0x0B, 0x09, 0x06, 0x17, 0x02, 0xF0, 0x0B, 0x00, 0x0B, 0x02, 0x06, 0xFF, 0x00, 0x00, 0x04, 0x07, 0x00, 0x00, 0x00, 0x04, 0x07, 0x01, 0x00, 0x00, 0x00, 0x07, 0x03, 0x00, 0x00}; + +#define dbg(format, arg...) printf("%s:%d " format , __FILE__ , __LINE__ , ## arg) +#define err(format, arg...) {printf("err:%s:%d: %s (%d): " format , __FILE__ , __LINE__ ,strerror(errno), errno, ## arg);print_trace();abort();} +#define info(format, arg...) printf("%s:%d: " format , __FILE__ , __LINE__ ,## arg) +#define warn(format, arg...) printf("%s:%d: " format , __FILE__ , __LINE__ ,## arg) +#define STATIC +#else +//#define DEBUG +#include "headers.h" +#endif + +#define CA_MAX_CAIDS 16 +#define CA_MAX_PIDS 16 +#ifndef CA_MAX_SLOTS +#define CA_MAX_SLOTS 3 +#endif +typedef struct +{ + u_int16_t caid[CA_MAX_CAIDS]; + u_int16_t pid[CA_MAX_PIDS]; + u_int16_t capid[CA_MAX_PIDS]; +} caid_pid_list_t; + +static caid_pid_list_t cpl[CA_MAX_SLOTS]; + +STATIC void dump(u_int8_t *data, int len) +{ +#ifdef DEBUG + int j; + printf("Dump: "); + for(j=0;j<len;j++) { + printf("%02x ",data[j]); + } + printf("\n"); +#endif +} + +STATIC int ci_cpl_find_pid (int slot, int pid) +{ + if (slot < 0 || slot >= CA_MAX_SLOTS) { + return -1; + } + int i; + for (i = 0; i < CA_MAX_PIDS; i++) { + if (pid == cpl[slot].pid[i]) + return 1; + } + return 0; +} + +STATIC int ci_cpl_find_caid (int slot, int caid) +{ + if (slot < 0 || slot >= CA_MAX_SLOTS) { + return -1; + } + int i; + for (i = 0; i < CA_MAX_CAIDS; i++) { + if (caid == cpl[slot].caid[i]) + return 1; + } + return 0; +} + +STATIC int ci_cpl_find_capid (int slot, int pid) +{ + if (slot < 0 || slot >= CA_MAX_SLOTS) { + return -1; + } + int i; + for (i = 0; i < CA_MAX_PIDS; i++) { + if (pid == cpl[slot].capid[i]) + return 1; + } + return 0; +} + +STATIC int ci_cpl_delete_pid (int slot, int pid) +{ + if (slot < 0 || slot >= CA_MAX_SLOTS) { + return -1; + } + int i; + for (i = 0; i < CA_MAX_PIDS; i++) { + if (cpl[slot].pid[i]==pid) { + cpl[slot].pid[i] = 0; + dbg ("-------> Slot: %d Deleted pid: %04x\n", slot, pid); + return 1; + } + } + return 0; +} + +STATIC int ci_cpl_update_pid (int slot, int pid) +{ + if (slot < 0 || slot >= CA_MAX_SLOTS) { + return -1; + } + if (!ci_cpl_find_pid (slot, pid)) { + int i; + for (i = 0; i < CA_MAX_PIDS; i++) { + if (!cpl[slot].pid[i]) { + cpl[slot].pid[i] = pid; + dbg ("-------> Slot: %d Added pid: %04x\n", slot, pid); + return 1; + } + } + } + return 0; +} + +STATIC int ci_cpl_update_caid (int slot, int caid) +{ + if (slot < 0 || slot >= CA_MAX_SLOTS) { + return -1; + } + if (!ci_cpl_find_caid (slot, caid)) { + int i; + for (i = 0; i < CA_MAX_CAIDS; i++) { + if (!cpl[slot].caid[i]) { + cpl[slot].caid[i] = caid; + dbg ("-------> Slot: %d Added caid: %04x\n", slot, caid); + return 1; + } + } + } + return 0; +} + +STATIC int ci_cpl_update_capid (int slot, int capid) +{ + if (slot < 0 || slot >= CA_MAX_SLOTS) { + return -1; + } + if (!ci_cpl_find_capid (slot, capid)) { + int i; + for (i = 0; i < CA_MAX_PIDS; i++) { + if (!cpl[slot].capid[i]) { + cpl[slot].capid[i] = capid; + dbg ("-------> Slot: %d Added capid: %04x\n", slot, capid); + return 1; + } + } + } + return 0; +} + +int ci_cpl_find_caid_by_pid (int pid) +{ + int i; + int slot; + + if(!pid) { + return 0; + } + for (slot = 0; slot < CA_MAX_SLOTS; slot++) { + for (i = 0; i < CA_MAX_PIDS; i++) { + if (pid == cpl[slot].pid[i]) { + return cpl[slot].caid[0]; + } + } + } + return 0; +} + +int ci_cpl_find_slot_by_caid_and_pid (int caid, int pid) +{ + int slot; + for (slot = 0; slot < CA_MAX_SLOTS; slot++) { + if (ci_cpl_find_pid (slot, pid) && ci_cpl_find_caid (slot, caid)) { + return slot; + } + } + return -1; +} + +int ci_cpl_clear (int slot) +{ + if (slot < 0 || slot >= CA_MAX_SLOTS) { + return -1; + } + memset (&cpl[slot], 0, sizeof (caid_pid_list_t)); + return 0; +} + +int ci_cpl_clear_pids (int slot) +{ + if (slot < 0 || slot >= CA_MAX_SLOTS) { + return -1; + } + memset (cpl[slot].pid, 0, sizeof (u_int16_t) * CA_MAX_PIDS); + return 0; +} + +int ci_cpl_clear_caids (int slot) +{ + if (slot < 0 || slot >= CA_MAX_SLOTS) { + return -1; + } + memset (cpl[slot].caid, 0, sizeof (u_int16_t) * CA_MAX_CAIDS); + return 0; +} + +int ci_cpl_clear_capids (int slot) +{ + if (slot < 0 || slot >= CA_MAX_SLOTS) { + return -1; + } + memset (cpl[slot].capid, 0, sizeof (u_int16_t) * CA_MAX_PIDS); + return 0; +} + +STATIC int ci_decode_length (unsigned int *len, u_int8_t * v) +{ + int ret = 0; + + if (*v & LENGTH_SIZE_INDICATOR) { + int l = *v & 0x7f; + if (l > 4) { + return -1; + } + ret = l + 1; + *len = 0; + while (l--) { + v++; + *len <<= 8; + *len |= *v; + } + } else { + *len = *v; + ret = 1; + } + return ret; +} + +#if 0 +STATIC int ci_decode_al_ca_info (ci_al_t * al) +{ + int i = 0; + u_int8_t *data = al->data; + int len = al->length; + + if (len & 1) { + dbg ("ci_decode_al_ca_info: invalid length %d\n", len); + } + + len >>= 1; + + u_int16_t *caid = (u_int16_t *) malloc (sizeof (u_int16_t) * len); + ci_cpl_clear_caids (al->sl->tl->ll->slot); + while (i < len) { + caid[i++] = ntohs16 (data); + data += 2; + ci_cpl_update_caid (al->sl->tl->ll->slot, caid[i - 1]); + dbg ("CAID[%d]: %04x\n", i - 1, caid[i - 1]); + } + if (caid) { + free (caid); + } + return data - al->data; +} +#endif + +STATIC int ca_decode_ca_descr (ca_desc_t ** cadescr, int count, u_int8_t * data, int len, int *magic) +{ + *cadescr = (ca_desc_t *) realloc (*cadescr, sizeof (ca_desc_t *) * (count + 1)); + if (!*cadescr) { + err ("ca_decode_ca_descr: out of memory\n"); + } + ca_desc_t *c = *cadescr + count; + +// u_int8_t descriptor_tag = *data; + data++; + u_int8_t descriptor_length = *data; + data++; + c->ca_id = ntohs16 (data); + data += 2; + c->ca_pid = ntohs16 (data); + data += 2; + dbg ("cadescr: %p %d ca_id: %04x ca_pid: %04x\n", cadescr, count, c->ca_id, c->ca_pid); + if(magic && c->ca_id > 0 && c->ca_id < 3 && c->ca_pid > 0 && c->ca_pid < 3 && c->ca_id == c->ca_pid){ + *magic = c->ca_id; + } + return descriptor_length + 2; +} + + +STATIC int ci_decode_al_ca_pmt (ci_al_t * al) +{ + ca_pmt_t p; + int magic = 0; + int slot = 0; + int cleared = 0; + + memset (&p, 0, sizeof (ca_pmt_t)); + + int ret; + u_int8_t *data = al->data; + int len; + + p.ca_pmt_list_management = *data; + data++; + + p.program_number = ntohs16 (data); + data += 2; + + p.version_number = *data; + data++; + + p.program_info_length = (u_int16_t) ntohs16 (data); + data += 2; + + dbg ("ci_decode_al_ca_pmt: ca_pmt_list_management:%02x program_number:%04x version_number:%02x program_info_length:%04x\n", p.ca_pmt_list_management, p.program_number, p.version_number, p.program_info_length); + if (p.program_info_length) { + int ca_descr_count = 0; + len = p.program_info_length - 1; + p.ca_pmt_cmd_id = *data; + dbg ("p.ca_pmt_cmd_id:%02x\n", p.ca_pmt_cmd_id); + data++; + while (len>0) { + ret = ca_decode_ca_descr (&p.cadescr, ca_descr_count, data, len, &magic); + if (magic) + slot = magic - 1; + else + slot = al->sl->tl->ll->slot; + if (!cleared) { + if(p.ca_pmt_list_management == CPLM_ONLY || p.ca_pmt_list_management == CPLM_FIRST || p.ca_pmt_list_management == CPLM_UPDATE) { + ci_cpl_clear_pids(slot); + ci_cpl_clear_capids(slot); + ci_cpl_clear_caids(slot); + cleared = 1; + } + } + if (ret < 0) { + warn ("error decoding ca_descriptor\n"); + break; + } + if((magic != p.cadescr[ca_descr_count].ca_id) || (magic != p.cadescr[ca_descr_count].ca_pid)){ + ci_cpl_update_caid (slot, p.cadescr[ca_descr_count].ca_id); + ci_cpl_update_capid (slot, p.cadescr[ca_descr_count].ca_pid); + } + ca_descr_count++; + data += ret; + len -= ret; + } + if (p.cadescr) { + free (p.cadescr); + } + } + + len = al->length - (data - al->data); + int pidn = 0; + + while (len>0) { + p.pidinfo = (pidinfo_t *) realloc (p.pidinfo, sizeof (pidinfo_t) * (pidn + 1)); + if (!p.pidinfo) { + err ("ci_decode_al_ca_pmt: out of memory"); + } + memset (&p.pidinfo[pidn], 0, sizeof (pidinfo_t)); + p.pidinfo[pidn].stream_type = *data; + data++; + len--; + p.pidinfo[pidn].pid = ntohs16 (data); + data += 2; + len -= 2; + p.pidinfo[pidn].es_info_length = ntohs16 (data); + data += 2; + len -= 2; + + dbg ("len: %d count: %d, stream_type: %02x, pid: %04x es_info_length: %04x\n", len, pidn, p.pidinfo[pidn].stream_type, p.pidinfo[pidn].pid, p.pidinfo[pidn].es_info_length); + if (p.pidinfo[pidn].es_info_length) { + int pi_len = p.pidinfo[pidn].es_info_length - 1; + p.pidinfo[pidn].ca_pmt_cmd_id = *data; + data++; + len--; + int pid_ca_descr_count = 0; + while (pi_len>0) { + ret = ca_decode_ca_descr (&p.pidinfo[pidn].cadescr, pid_ca_descr_count, data, pi_len, NULL); + if (!cleared) { + if(p.ca_pmt_list_management == CPLM_ONLY || p.ca_pmt_list_management == CPLM_FIRST || p.ca_pmt_list_management == CPLM_UPDATE) { + ci_cpl_clear_pids(slot); + ci_cpl_clear_capids(slot); + ci_cpl_clear_caids(slot); + cleared = 1; + } + } + if (ret < 0) { + warn ("error decoding ca_descriptor\n"); + break; + } + if((magic != p.pidinfo[pidn].cadescr[pid_ca_descr_count].ca_id) || (magic != p.pidinfo[pidn].cadescr[pid_ca_descr_count].ca_pid)){ + ci_cpl_update_pid (slot, p.pidinfo[pidn].pid); + ci_cpl_update_caid (slot, p.pidinfo[pidn].cadescr[pid_ca_descr_count].ca_id); + ci_cpl_update_capid (slot, p.pidinfo[pidn].cadescr[pid_ca_descr_count].ca_pid); + } + pid_ca_descr_count++; + data += ret; + pi_len -= ret; + len -= ret; + } + } + if (p.pidinfo[pidn].cadescr) { + free (p.pidinfo[pidn].cadescr); + } + pidn++; + } + if (p.pidinfo) { + free (p.pidinfo); + } + return 0; +} + +STATIC int ci_decode_al_ca_pmt_reply (ci_al_t * al) +{ + ca_pmt_reply_t p; + + memset (&p, 0, sizeof (ca_pmt_reply_t)); + + u_int8_t *data = al->data; + int len; + + p.program_number = ntohs16 (data); + data += 2; + + p.version_number = *data; + data++; + + p.ca_enable = *data; + data++; + + len = al->length - (data - al->data); + int pidn = 0; + + dbg ("ci_decode_al_ca_pmt_reply: program_number: %04x ca_enable: %02x\n", p.program_number, p.ca_enable); + + while (len>0) { + p.pidcaenable = (pid_ca_enable_t *) realloc (p.pidcaenable, sizeof (pid_ca_enable_t) * (pidn + 1)); + if (!p.pidcaenable) { + err ("ci_decode_al_ca_pmt_reply: out of memory\n"); + } + memset (&p.pidcaenable[pidn], 0, sizeof (pid_ca_enable_t)); + p.pidcaenable[pidn].pid = ntohs16 (data); + data += 2; + p.pidcaenable[pidn].ca_enable = *data; + data++; + len -= 3; + if ((p.pidcaenable[pidn].ca_enable == CPCI_OK_DESCRAMBLING) || (p.pidcaenable[pidn].ca_enable == CPCI_OK_MMI) || (p.pidcaenable[pidn].ca_enable == CPCI_QUERY)) { + ci_cpl_update_pid (al->sl->tl->ll->slot, p.pidcaenable[pidn].pid); + } else { + ci_cpl_delete_pid (al->sl->tl->ll->slot, p.pidcaenable[pidn].pid); + } + dbg ("count: %d pid: %04x pid_ca_enable: %02x\n", pidn, p.pidcaenable[pidn].pid, p.pidcaenable[pidn].ca_enable); + pidn++; + } + if (p.pidcaenable) { + free (p.pidcaenable); + } + return 0; +} + +STATIC int ci_decode_al (ci_sl_t * sl) +{ + int ret = 0; + int done = 0; + int len = 3; + ci_al_t al; + u_int8_t *data = sl->data; + al.sl = sl; + + al.tag = 0; + while (len--) { + al.tag <<= 8; + al.tag |= *data; + data++; + } + done += 3; + ret = ci_decode_length (&al.length, data); + if (ret < 0) { + warn ("ci_decode_al ci_decode_length failed\n"); + return ret; + } + + data += ret; + done += ret; + //Fake + al.data = data; + + dbg ("ci_decode_al: tag:%03x length: %02x data[0]:%02x done: %02x\n", al.tag, al.length, al.data[0], done); + + switch (al.tag) { + case AOT_CA_INFO: +// ci_decode_al_ca_info (&al); + break; + case AOT_CA_PMT: + ci_decode_al_ca_pmt (&al); + break; + case AOT_CA_PMT_REPLY: + ci_decode_al_ca_pmt_reply (&al); + break; + } + + done += al.length; + + dbg ("ci_decode_al: done %02x\n", done); + return done; +} + +STATIC int ci_decode_sl (ci_tl_t * tl) +{ + int ret = 0; + int done = 0; + unsigned int len; + ci_sl_t sl; + u_int8_t *data = tl->data; + sl.tl = tl; + + sl.tag = *data; + data++; + done++; + + if(sl.tag != ST_SESSION_NUMBER) { + return tl->length; + } + + ret = ci_decode_length (&len, data); + if (ret < 0) { + warn ("ci_decode_sl ci_decode_length failed\n"); + return ret; + } + data += ret; + done += ret; + + if (len > 4) { + warn ("invalid length (%d) for session_object_value\n", len); + return -1; + } + + sl.object_value = 0; + while (len--) { + sl.object_value <<= 8; + sl.object_value |= *data; + data++; + done++; + } + + sl.data = data; + sl.length = tl->length - done; + + while (sl.length>0) { + dbg ("ci_decode_sl: object_value:%02x length: %02x done: %02x\n", sl.object_value, sl.length, done); + ret = ci_decode_al (&sl); + if (ret < 0) { + warn ("ci_decode_al failed\n"); + return ret; + } + sl.length -= ret; + sl.data += ret; + done += ret; + } + dbg ("ci_decode_sl: done %02x\n", done); + return done; +} + +STATIC int ci_decode_tl (ci_ll_t * ll) +{ + int ret = 0; + int done = 0; + ci_tl_t tl; + u_int8_t *data = ll->data; + tl.ll = ll; + + tl.c_tpdu_tag = *data; + data++; + done++; + + ret = ci_decode_length (&tl.length, data); + if (ret < 0) { + warn ("ci_decode_tl ci_decode_length failed\n"); + return ret; + } + + data += ret; + done += ret; + + tl.tcid = *data; + data++; + done++; + + if (tl.tcid != ll->tcid) { + warn ("Error: redundant tcid mismatch %02x %02x\n",tl.tcid, ll->tcid); + return -1; + } + + tl.data = data; + + //According to A.4.1.1 + tl.length--; + + while (tl.length>0) { + dbg ("ci_decode_tl: c_tpdu_tag:%02x tcid:%02x length: %02x done: %02x\n", tl.c_tpdu_tag, tl.tcid, tl.length, done); + if (tl.c_tpdu_tag == T_DATA_LAST || tl.c_tpdu_tag == T_DATA_MORE) { + ret = ci_decode_sl (&tl); + if (ret < 0) { + warn ("ci_decode_sl failed\n"); + return ret; + } + } else { + ret = tl.length; + } + tl.length -= ret; + tl.data += ret; + done += ret; + } + dbg ("ci_decode_tl: done %02x\n", done); + return done; +} + +int ci_decode_ll (uint8_t * tpdu, int len) +{ + int ret = 0; + int done = 0; + u_int8_t *data=tpdu; + ci_ll_t ll; + dump(tpdu,len); + + ll.slot = *data; + data++; + + ll.tcid = *data; + data++; + + ll.data = data; + ll.length = len - (data-tpdu); + + while (ll.length) { + + dbg ("ci_decode_ll: slot:%02x tcid:%02x length: %02x\n", ll.slot, ll.tcid, ll.length); + ret = ci_decode_tl (&ll); + if (ret < 0) { + warn ("ci_decode_tl failed\n"); + return ret; + } + ll.length -= ret; + ll.data += ret; + } + dbg ("ci_decode_ll: done %02x\n", len); + return done; +} + +#ifdef TESTING +int main (int argc, char **argv) +{ + int ret; + + printf ("ci_decode_ll len: %02x\n", sizeof (lb)); + ret = ci_decode_ll (lb, sizeof (lb)); + printf ("ci_decode_ll ret: %02x\n", ret); + + printf ("ci_decode_ll len: %02x\n", sizeof (ll)); + ret = ci_decode_ll (ll, sizeof (ll)); + printf ("ci_decode_ll ret: %02x\n", ret); + + + printf ("ci_decode_ll len: %02x\n", sizeof (ld)); + ret = ci_decode_ll (ld, sizeof (ld)); + printf ("ci_decode_ll ret: %02x\n", ret); + + printf ("ci_decode_ll len: %02x\n", sizeof (lc)); + ret = ci_decode_ll (lc, sizeof (lc)); + printf ("ci_decode_ll ret: %02x\n", ret); + + printf ("ci_decode_ll len: %02x\n", sizeof (le)); + ret = ci_decode_ll (le, sizeof (le)); + printf ("ci_decode_ll ret: %02x\n", ret); + +// printf ("caid %04x for pid %04x\n", ci_cpl_find_caid_by_pid (0x5c), 0x5c); + return 0; +} +#endif |