#define MODULE_LOG_PREFIX "config" #include "globals.h" #include "oscam-array.h" #include "oscam-conf-chk.h" #include "oscam-garbage.h" #include "oscam-net.h" #include "oscam-string.h" void chk_iprange(char *value, struct s_ip **base) { int32_t i = 0; char *ptr1, *ptr2, *saveptr1 = NULL; struct s_ip *fip, *lip, *cip; if(!cs_malloc(&cip, sizeof(struct s_ip))) { return; } fip = cip; for(ptr1 = strtok_r(value, ",", &saveptr1); ptr1; ptr1 = strtok_r(NULL, ",", &saveptr1)) { if(i == 0) { ++i; } else { if(!cs_malloc(&cip, sizeof(struct s_ip))) { break; } lip->next = cip; } if((ptr2 = strchr(trim(ptr1), '-'))) { *ptr2++ = '\0'; cs_inet_addr(trim(ptr1), &cip->ip[0]); cs_inet_addr(trim(ptr2), &cip->ip[1]); } else { cs_inet_addr(ptr1, &cip->ip[0]); IP_ASSIGN(cip->ip[1], cip->ip[0]); } lip = cip; } lip = *base; *base = fip; clear_sip(&lip); } void chk_caidtab(char *value, CAIDTAB *caidtab) { caidtab_clear(caidtab); char *ptr, *saveptr1 = NULL; for(ptr = strtok_r(value, ",", &saveptr1); ptr; ptr = strtok_r(NULL, ",", &saveptr1)) { CAIDTAB_DATA d; memset(&d, 0, sizeof(d)); d.mask = 0xffff; char *caid_end_ptr = strchr(ptr, ':'); // caid_end_ptr + 1 -> cmap if(caid_end_ptr) { *caid_end_ptr++ = '\0'; d.cmap = a2i(caid_end_ptr, 2); if (errno == EINVAL) continue; } char *mask_start_ptr = strchr(ptr, '&'); // mask_start_ptr + 1 -> mask errno = 0; if(mask_start_ptr) { // Mask is optional *mask_start_ptr++ = '\0'; d.mask = a2i(mask_start_ptr, 2); if (errno == EINVAL) continue; } d.caid = a2i(ptr, 2); if (errno == EINVAL) continue; if (d.caid || d.cmap) caidtab_add(caidtab, &d); } } void chk_caidvaluetab(char *value, CAIDVALUETAB *caidvaluetab) { caidvaluetab_clear(caidvaluetab); char *ptr, *saveptr1 = NULL; for(ptr = strtok_r(value, ",", &saveptr1); ptr; ptr = strtok_r(NULL, ",", &saveptr1)) { CAIDVALUETAB_DATA d; memset(&d, 0, sizeof(d)); char *caid_end_ptr = strchr(ptr, ':'); // caid_end_ptr + 1 -> value if(!caid_end_ptr) continue; *caid_end_ptr++ = '\0'; errno = 0; d.caid = a2i(ptr, 2); if (errno == EINVAL) continue; d.value = atoi(caid_end_ptr); if (d.caid && d.value < 10000) caidvaluetab_add(caidvaluetab, &d); } } void chk_cacheex_valuetab(char *lbrlt, CECSPVALUETAB *tab) { //[caid][&mask][@provid][$servid][:awtime][:]dwtime char *ptr = NULL, *saveptr1 = NULL; cecspvaluetab_clear(tab); int32_t i; for(i = 0, ptr = strtok_r(lbrlt, ",", &saveptr1); (ptr); ptr = strtok_r(NULL, ",", &saveptr1), i++) { CECSPVALUETAB_DATA d; memset(&d, 0, sizeof(d)); int32_t caid = -1, cmask = -1, srvid = -1; int32_t j, provid = -1; int16_t awtime = -1, dwtime = -1; char *ptr1 = NULL, *ptr2 = NULL, *ptr3 = NULL, *ptr4 = NULL, *ptr5 = NULL, *saveptr2 = NULL; if((ptr4 = strchr(trim(ptr), ':'))) { //awtime & dwtime *ptr4++ = '\0'; for(j = 0, ptr5 = strtok_r(ptr4, ":", &saveptr2); (j < 2) && ptr5; ptr5 = strtok_r(NULL, ":", &saveptr2), j++) { if(!j) { dwtime = atoi(ptr5); } if(j) { awtime = dwtime; dwtime = atoi(ptr5); } } } if((ptr3 = strchr(trim(ptr), '$'))) { *ptr3++ = '\0'; srvid = a2i(ptr3, 4); } if((ptr2 = strchr(trim(ptr), '@'))) { *ptr2++ = '\0'; provid = a2i(ptr2, 6); } if((ptr1 = strchr(ptr, '&'))) { *ptr1++ = '\0'; cmask = a2i(ptr1, -2); } if(!ptr1 && !ptr2 && !ptr3 && !ptr4) //only dwtime { dwtime = atoi(ptr); } else { caid = a2i(ptr, 2); } if((i == 0 && (caid <= 0)) || (caid > 0)) { d.caid = caid; d.cmask = cmask; d.prid = provid; d.srvid = srvid; d.awtime = awtime; d.dwtime = dwtime; cecspvaluetab_add(tab, &d); } } } void chk_cacheex_cwcheck_valuetab(char *lbrlt, CWCHECKTAB *tab) { //caid[&mask][@provid][$servid]:mode:counter int32_t i; char *ptr = NULL, *saveptr1 = NULL; cwcheckvaluetab_clear(tab); for(i = 0, ptr = strtok_r(lbrlt, ",", &saveptr1); (ptr); ptr = strtok_r(NULL, ",", &saveptr1), i++) { CWCHECKTAB_DATA d; memset(&d, 0, sizeof(d)); int32_t caid = -1, cmask = -1, provid = -1, srvid = -1; int16_t mode = -1, counter = -1; char *ptr1 = NULL, *ptr2 = NULL, *ptr3 = NULL, *ptr4 = NULL, *ptr5 = NULL, *saveptr2 = NULL; if((ptr4 = strchr(trim(ptr), ':'))) { *ptr4++ = '\0'; ptr5 = strtok_r(ptr4, ":", &saveptr2); if(ptr5) mode = atoi(ptr5); ptr5 = strtok_r(NULL, ":", &saveptr2); if(ptr5) counter = atoi(ptr5); } if((ptr3 = strchr(trim(ptr), '$'))) { *ptr3++ = '\0'; srvid = a2i(ptr3, 4); } if((ptr2 = strchr(trim(ptr), '@'))) { *ptr2++ = '\0'; provid = a2i(ptr2, 6); } if((ptr1 = strchr(ptr, '&'))) { *ptr1++ = '\0'; cmask = a2i(ptr1, -2); } caid = a2i(ptr, 2); if((i == 0 && (caid <= 0)) || (caid > 0)) { d.caid = caid; d.cmask = cmask; d.prid = provid; d.srvid = srvid; d.mode = mode; d.counter = counter; cwcheckvaluetab_add(tab, &d); } } } void chk_cacheex_hitvaluetab(char *lbrlt, CECSPVALUETAB *tab) { //[caid][&mask][@provid][$servid] char *ptr = NULL, *saveptr1 = NULL; cecspvaluetab_clear(tab); for(ptr = strtok_r(lbrlt, ",", &saveptr1); (ptr); ptr = strtok_r(NULL, ",", &saveptr1)) { CECSPVALUETAB_DATA d; memset(&d, 0, sizeof(d)); int32_t caid = -1, cmask = -1, srvid = -1; int32_t provid = -1; char *ptr1 = NULL, *ptr2 = NULL, *ptr3 = NULL; if((ptr3 = strchr(trim(ptr), '$'))) { *ptr3++ = '\0'; srvid = a2i(ptr3, 4); } if((ptr2 = strchr(trim(ptr), '@'))) { *ptr2++ = '\0'; provid = a2i(ptr2, 6); } if((ptr1 = strchr(ptr, '&'))) { *ptr1++ = '\0'; cmask = a2i(ptr1, -2); } caid = a2i(ptr, 2); if(caid > 0) { d.caid = caid; d.cmask = cmask; d.prid = provid; d.srvid = srvid; cecspvaluetab_add(tab, &d); } } } void chk_tuntab(char *tunasc, TUNTAB *ttab) { tuntab_clear(ttab); errno = 0; char *caid_ptr, *savecaid_ptr = NULL; for(caid_ptr = strtok_r(tunasc, ",", &savecaid_ptr); (caid_ptr); caid_ptr = strtok_r(NULL, ",", &savecaid_ptr)) { TUNTAB_DATA d; char *srvid_ptr = strchr(trim(caid_ptr), '.'); char *caidto_ptr = strchr(trim(caid_ptr), ':'); if (!srvid_ptr) continue; *srvid_ptr++ = '\0'; if (caidto_ptr) *caidto_ptr++ = '\0'; d.bt_caidfrom = a2i(caid_ptr, 2); d.bt_srvid = a2i(srvid_ptr, 2); d.bt_caidto = 0; if (caidto_ptr) d.bt_caidto = a2i(caidto_ptr, 2); if (errno == EINVAL) continue; if (d.bt_caidfrom | d.bt_srvid | d.bt_caidto) tuntab_add(ttab, &d); } } void chk_services(char *labels, SIDTABS *sidtabs) { int32_t i; char *ptr, *saveptr1 = NULL; SIDTAB *sidtab; SIDTABBITS newsidok, newsidno; newsidok = newsidno = 0; for(ptr = strtok_r(labels, ",", &saveptr1); ptr; ptr = strtok_r(NULL, ",", &saveptr1)) { for(trim(ptr), i = 0, sidtab = cfg.sidtab; sidtab; sidtab = sidtab->next, i++) { if(!strcmp(sidtab->label, ptr)) { newsidok |= ((SIDTABBITS)1 << i); } if((ptr[0] == '!') && (!strcmp(sidtab->label, ptr + 1))) { newsidno |= ((SIDTABBITS)1 << i); } } } sidtabs->ok = newsidok; sidtabs->no = newsidno; } void chk_ftab(char *value, FTAB *ftab) { ftab_clear(ftab); char *ptr1, *saveptr1 = NULL; errno = 0; for(ptr1 = strtok_r(value, ";", &saveptr1); (ptr1); ptr1 = strtok_r(NULL, ";", &saveptr1)) { FILTER d; memset(&d, 0, sizeof(d)); char *caid_end_ptr = strchr(ptr1, ':'); // caid_end_ptr + 1 -> headers if(!caid_end_ptr) continue; caid_end_ptr[0] = '\0'; d.caid = a2i(ptr1, 4); if (!d.caid || errno == EINVAL) { errno = 0; continue; } ptr1 = caid_end_ptr + 1; // -> headers char *ident_ptr, *saveident_ptr = NULL; for(ident_ptr = strtok_r(ptr1, ",", &saveident_ptr); ident_ptr && d.nprids < ARRAY_SIZE(d.prids); ident_ptr = strtok_r(NULL, ",", &saveident_ptr)) { uint32_t ident = a2i(ident_ptr, 4); if (errno == EINVAL) { errno = 0; continue; } d.prids[d.nprids++] = ident; } if (d.nprids) ftab_add(ftab, &d); } } void chk_cltab(char *classasc, CLASSTAB *clstab) { int32_t max_an = 0, max_bn = 0; char *ptr1, *saveptr1 = NULL, *classasc_org; CLASSTAB newclstab, oldclstab; memset(&newclstab, 0, sizeof(newclstab)); newclstab.an = newclstab.bn = 0; if(!cs_malloc(&classasc_org, sizeof(char)*cs_strlen(classasc)+1)) { return; } cs_strncpy(classasc_org, classasc, sizeof(char)*cs_strlen(classasc)+1); for(ptr1 = strtok_r(classasc, ",", &saveptr1); ptr1; ptr1 = strtok_r(NULL, ",", &saveptr1)) { ptr1 = trim(ptr1); if(ptr1[0] == '!') { max_bn++; } else { max_an++; } } if(max_an && !cs_malloc(&newclstab.aclass, sizeof(uint8_t) * max_an)) { NULLFREE(classasc_org); return; } if(max_bn && !cs_malloc(&newclstab.bclass, sizeof(uint8_t) * max_bn)) { NULLFREE(newclstab.aclass); NULLFREE(classasc_org); return; } classasc = classasc_org; for(ptr1 = strtok_r(classasc, ",", &saveptr1); ptr1; ptr1 = strtok_r(NULL, ",", &saveptr1)) { ptr1 = trim(ptr1); if(ptr1[0] == '!' && newclstab.bclass != NULL) { newclstab.bclass[newclstab.bn++] = (uint8_t)a2i(ptr1 + 1, 2); } else if(newclstab.aclass != NULL) { newclstab.aclass[newclstab.an++] = (uint8_t)a2i(ptr1, 2); } } NULLFREE(classasc_org); memcpy(&oldclstab, clstab, sizeof(CLASSTAB)); memcpy(clstab, &newclstab, sizeof(CLASSTAB)); NULLFREE(oldclstab.aclass); NULLFREE(oldclstab.bclass); } void chk_port_tab(char *portasc, PTAB *ptab) { int32_t i, j, nfilts, ifilt, iport; PTAB *newptab; char *ptr1, *ptr2, *ptr3, *saveptr1 = NULL; char *ptr[CS_MAXPORTS] = {0}; int32_t port[CS_MAXPORTS] = {0}; if(!cs_malloc(&newptab, sizeof(PTAB))) { return; } for(nfilts = i = 0, ptr1 = strtok_r(portasc, ";", &saveptr1); (i < CS_MAXPORTS) && (ptr1); ptr1 = strtok_r(NULL, ";", &saveptr1), i++) { ptr[i] = ptr1; if(!newptab->ports[i].ncd && !cs_malloc(&newptab->ports[i].ncd, sizeof(struct ncd_port))) { break; } if((ptr2 = strchr(trim(ptr1), '@'))) { *ptr2++ = '\0'; newptab->ports[i].s_port = atoi(ptr1); //checking for des key for port newptab->ports[i].ncd->ncd_key_is_set = false; if((ptr3 = strchr(trim(ptr1), '{'))) { *ptr3++ = '\0'; if(key_atob_l(ptr3, newptab->ports[i].ncd->ncd_key, sizeof(newptab->ports[i].ncd->ncd_key) * 2)) { fprintf(stderr, "newcamd: error in DES Key for port %s -> ignored\n", ptr1); } else { newptab->ports[i].ncd->ncd_key_is_set = true; } } ptr[i] = ptr2; port[i] = newptab->ports[i].s_port; newptab->nports++; } nfilts++; } if(nfilts == 1 && cs_strlen(portasc) < 6 && newptab->ports[0].s_port == 0) { newptab->ports[0].s_port = atoi(portasc); newptab->nports = 1; } iport = ifilt = 0; for(i = 0; i < nfilts; i++) { if(port[i] != 0) { iport = i; } for(j = 0, ptr3 = strtok_r(ptr[i], ",", &saveptr1); (j < CS_MAXPROV) && (ptr3); ptr3 = strtok_r(NULL, ",", &saveptr1), j++) { if((ptr2 = strchr(trim(ptr3), ':'))) { *ptr2++ = '\0'; ifilt = newptab->ports[iport].ncd->ncd_ftab.nfilts++; j = 0; newptab->ports[iport].ncd->ncd_ftab.filts[ifilt].caid = (uint16_t)a2i(ptr3, 4); newptab->ports[iport].ncd->ncd_ftab.filts[ifilt].prids[j] = a2i(ptr2, 6); } else { newptab->ports[iport].ncd->ncd_ftab.filts[ifilt].prids[j] = a2i(ptr3, 6); } newptab->ports[iport].ncd->ncd_ftab.filts[ifilt].nprids++; } } memcpy(ptab, newptab, sizeof(PTAB)); NULLFREE(newptab); } void chk_port_camd35_tab(char *portasc, PTAB *ptab) { int32_t i, j; PTAB *newptab; char *ptr1, *ptr2, *ptr4, *provids, *saveptr1 = NULL, *saveptr2 = NULL; if(!cs_malloc(&newptab, sizeof(PTAB))) { return; } for(i = 0, ptr1 = strtok_r(portasc, ";", &saveptr1); (i < CS_MAXPORTS) && (ptr1); ptr1 = strtok_r(NULL, ";", &saveptr1), i++) { if(!newptab->ports[newptab->nports].ncd && !cs_malloc(&newptab->ports[i].ncd, sizeof(struct ncd_port))) { break; } newptab->ports[newptab->nports].s_port = atoi(ptr1); if((ptr2 = strchr(trim(ptr1), '@'))) { *ptr2++ = '\0'; // clean up @ symbol newptab->ports[newptab->nports].s_port = atoi(ptr1); if((provids = strchr(trim(ptr2), ':'))) { *provids++ = '\0'; // clean up : symbol for(j = 0, ptr4 = strtok_r(provids, ",", &saveptr2); (i < CS_MAXPORTS) && (ptr4); ptr4 = strtok_r(NULL, ",", &saveptr2), j++) { newptab->ports[newptab->nports].ncd->ncd_ftab.filts[0].prids[j] = a2i(ptr4, 6); } newptab->ports[newptab->nports].ncd->ncd_ftab.filts[0].nprids=j; } newptab->ports[newptab->nports].ncd->ncd_ftab.filts[0].caid = (uint16_t)a2i(ptr2, sizeof(ptr2)); newptab->nports++; } else { newptab->ports[newptab->nports].s_port = atoi(ptr1); if (newptab->ports[newptab->nports].s_port) { newptab->nports++; }; } } memcpy(ptab, newptab, sizeof(PTAB)); NULLFREE(newptab); } void chk_ecm_whitelist(char *value, ECM_WHITELIST *ecm_whitelist) { ecm_whitelist_clear(ecm_whitelist); char *ptr, *saveptr1 = NULL; for(ptr = strtok_r(value, ";", &saveptr1); ptr; ptr = strtok_r(NULL, ";", &saveptr1)) { ECM_WHITELIST_DATA d; memset(&d, 0, sizeof(d)); char *caid_end_ptr = strchr(ptr, ':'); // caid_end_ptr + 1 -> headers char *provid_ptr = strchr(ptr, '@'); // provid_ptr + 1 -> provid char *headers = ptr; if(caid_end_ptr) { caid_end_ptr[0] = '\0'; if (provid_ptr) { provid_ptr[0] = '\0'; provid_ptr++; d.ident = a2i(provid_ptr, 6); } d.caid = dyn_word_atob(ptr); headers = caid_end_ptr + 1; // -> headers } else if(provid_ptr) { provid_ptr[0] = '\0'; d.ident = a2i(provid_ptr, 6); } if (d.caid == 0xffff) d.caid = 0; if (d.ident == 0xffff) d.ident = 0; char *len_ptr, *savelen_ptr = NULL; for(len_ptr = strtok_r(headers, ",", &savelen_ptr); len_ptr; len_ptr = strtok_r(NULL, ",", &savelen_ptr)) { d.len = dyn_word_atob(len_ptr); if (d.len == 0xffff) continue; ecm_whitelist_add(ecm_whitelist, &d); } } } void chk_ecm_hdr_whitelist(char *value, ECM_HDR_WHITELIST *ecm_hdr_whitelist) { ecm_hdr_whitelist_clear(ecm_hdr_whitelist); char *ptr, *saveptr = NULL; for(ptr = strtok_r(value, ";", &saveptr); ptr; ptr = strtok_r(NULL, ";", &saveptr)) { ECM_HDR_WHITELIST_DATA d; memset(&d, 0, sizeof(d)); char *caid_end_ptr = strchr(ptr, ':'); // caid_end_ptr + 1 -> headers char *provid_ptr = strchr(ptr, '@'); // provid_ptr + 1 -> provid char *headers = ptr; if(caid_end_ptr) { caid_end_ptr[0] = '\0'; if (provid_ptr) { provid_ptr[0] = '\0'; provid_ptr++; d.provid = a2i(provid_ptr, 6); } d.caid = dyn_word_atob(ptr); headers = caid_end_ptr + 1; // -> headers } else if(provid_ptr) { provid_ptr[0] = '\0'; d.provid = a2i(provid_ptr, 6); } if (d.caid == 0xffff) d.caid = 0; if (d.provid == 0xffff) d.provid = 0; char *hdr_ptr, *savehdr_ptr = NULL; for(hdr_ptr = strtok_r(headers, ",", &savehdr_ptr); hdr_ptr; hdr_ptr = strtok_r(NULL, ",", &savehdr_ptr)) { hdr_ptr = trim(hdr_ptr); d.len = cs_strlen(hdr_ptr); if (d.len / 2 > sizeof(d.header)) d.len = sizeof(d.header) * 2; if (d.len > 1) { key_atob_l(hdr_ptr, d.header, d.len); ecm_hdr_whitelist_add(ecm_hdr_whitelist, &d); } } } } /* Clears the s_ip structure provided. The pointer will be set to NULL so everything is cleared.*/ void clear_sip(struct s_ip **sip) { struct s_ip *cip = *sip; for(*sip = NULL; cip != NULL; cip = cip->next) { add_garbage(cip); } } /* Clears the s_ptab struct provided by setting nfilts and nprids to zero. */ void clear_ptab(struct s_ptab *ptab) { int32_t i; ptab->nports = 0; for(i = 0; i < CS_MAXPORTS; i++) { if(ptab->ports[i].ncd) { ptab->ports[i].ncd->ncd_ftab.nfilts = 0; ptab->ports[i].ncd->ncd_ftab.filts[0].nprids = 0; NULLFREE(ptab->ports[i].ncd); ptab->ports[i].ncd = NULL; } } } /* Clears given csptab */ void clear_cacheextab(CECSPVALUETAB *ctab) { ctab->cevnum = 0; NULLFREE(ctab->cevdata); } void cwvote_caidtab_clear(CW_VOTE_CAID_TAB *cwvote_caid_table) { if (cwvote_caid_table->cvcdata) { NULLFREE(cwvote_caid_table->cvcdata); } cwvote_caid_table->cvcnum = 0; } void chk_cwvote_caidtab(char *value, CW_VOTE_CAID_TAB *cwvote_caid_table) { char *ptr1, *saveptr1 = NULL; int32_t i; uint16_t caid; cwvote_caidtab_clear(cwvote_caid_table); for (i = 0, ptr1 = strtok_r(value, ",", &saveptr1); ptr1; ptr1 = strtok_r(NULL, ",", &saveptr1)) { if (i >= CS_MAXPROV) { cs_log("WARNING: Too many CW Vote CAIDs defined, max %d allowed!", CS_MAXPROV); break; } errno = 0; // Reset errno before calling strtoul caid = (uint16_t)strtoul(ptr1, NULL, 16); if (errno != 0) { cs_log("WARNING: Invalid CAID format '%s' in cwvote_caids, ignoring.", ptr1); continue; } if (caid > 0) { if (!cs_realloc(&cwvote_caid_table->cvcdata, sizeof(CW_VOTE_CAID_DATA) * (i + 1))) { cwvote_caid_table->cvcnum = 0; return; } cwvote_caid_table->cvcdata[i].caid = caid; i++; } } cwvote_caid_table->cvcnum = i; }