コード例 #1
0
ファイル: oscam-conf-chk.c プロジェクト: FFTEAM/oscam
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);
		}
	}
}
コード例 #2
0
ファイル: oscam-conf-chk.c プロジェクト: FFTEAM/oscam
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 = 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);
			}
		}
	}
}
コード例 #3
0
int32_t init_srvid(void)
{
	int8_t new_syntax = 1;
	FILE *fp = open_config_file("oscam.srvid2");
	if(!fp)
	{ 
		fp = open_config_file(cs_srid);
		if(fp)
		{
			new_syntax = 0;
		}
	}

	if(!fp)
	{ 
		fp = create_config_file("oscam.srvid2");
		if(fp)
		{
			flush_config_file(fp, "oscam.srvid2");
		}
		
		return 0;
	}

	int32_t nr = 0, i, j;
	char *payload, *saveptr1 = NULL, *saveptr2 = NULL, *token;
	const char *tmp;
	if(!cs_malloc(&token, MAXLINESIZE))
		{ return 0; }
	struct s_srvid *srvid = NULL, *new_cfg_srvid[16], *last_srvid[16];
	// A cache for strings within srvids. A checksum is calculated which is the start point in the array (some kind of primitive hash algo).
	// From this point, a sequential search is done. This greatly reduces the amount of string comparisons.
	const char **stringcache[1024];
	int32_t allocated[1024] = { 0 };
	int32_t used[1024] = { 0 };
	struct timeb ts, te;
	cs_ftime(&ts);

	memset(last_srvid, 0, sizeof(last_srvid));
	memset(new_cfg_srvid, 0, sizeof(new_cfg_srvid));

	while(fgets(token, MAXLINESIZE, fp))
	{
		int32_t l, len = 0, len2, srvidtmp;
		uint32_t k;
		uint32_t pos;
		char *srvidasc, *prov;
		tmp = trim(token);

		if(tmp[0] == '#') { continue; }
		if((l = strlen(tmp)) < 6) { continue; }
		if(!(srvidasc = strchr(token, ':'))) { continue; }
		if(!(payload = strchr(token, '|'))) { continue; }
		*payload++ = '\0';
		
		if(!cs_malloc(&srvid, sizeof(struct s_srvid)))
		{
			NULLFREE(token);
			fclose(fp);
			return (1);
		}

		char tmptxt[128];

		int32_t offset[4] = { -1, -1, -1, -1 };
		char *ptr1 = NULL, *ptr2 = NULL;
		const char *searchptr[4] = { NULL, NULL, NULL, NULL };
		const char **ptrs[4] = { &srvid->prov, &srvid->name, &srvid->type, &srvid->desc };
		uint32_t max_payload_length = MAXLINESIZE - (payload - token);
		
		if(new_syntax)
		{
			ptrs[0] = &srvid->name;
			ptrs[1] = &srvid->type;
			ptrs[2] = &srvid->desc;
			ptrs[3] = &srvid->prov;
		}
		
		// allow empty strings as "||"
		if(payload[0] == '|' && (strlen(payload)+2 < max_payload_length))
		{
			memmove(payload+1, payload, strlen(payload)+1);
			payload[0] = ' ';
		}
		
		for(k=1; ((k < max_payload_length) && (payload[k] != '\0')); k++)
		{
			if(payload[k-1] == '|' && payload[k] == '|')
			{
				if(strlen(payload+k)+2 < max_payload_length-k)
				{
					memmove(payload+k+1, payload+k, strlen(payload+k)+1);
					payload[k] = ' ';
				}
				else
				{
					break;
				}	
			}
		}
	
		for(i = 0, ptr1 = strtok_r(payload, "|", &saveptr1); ptr1 && (i < 4) ; ptr1 = strtok_r(NULL, "|", &saveptr1), ++i)
		{
			// check if string is in cache
			len2 = strlen(ptr1);
			pos = 0;
			for(j = 0; j < len2; ++j) { pos += (uint8_t)ptr1[j]; }
			pos = pos % 1024;
			for(j = 0; j < used[pos]; ++j)
			{
				if(!strcmp(stringcache[pos][j], ptr1))
				{
					searchptr[i] = stringcache[pos][j];
					break;
				}
			}
			if(searchptr[i]) { continue; }

			offset[i] = len;
			cs_strncpy(tmptxt + len, trim(ptr1), sizeof(tmptxt) - len);
			len += strlen(ptr1) + 1;
		}

		char *tmpptr = NULL;
		if(len > 0 && !cs_malloc(&tmpptr, len))
			{ continue; }

		srvid->data = tmpptr;
		if(len > 0) { memcpy(tmpptr, tmptxt, len); }

		for(i = 0; i < 4; i++)
		{
			if(searchptr[i])
			{
				*ptrs[i] = searchptr[i];
				continue;
			}
			if(offset[i] > -1)
			{
				*ptrs[i] = tmpptr + offset[i];
				// store string in stringcache
				tmp = *ptrs[i];
				len2 = strlen(tmp);
				pos = 0;
				for(j = 0; j < len2; ++j) { pos += (uint8_t)tmp[j]; }
				pos = pos % 1024;
				if(used[pos] >= allocated[pos])
				{
					if(allocated[pos] == 0)
					{
						if(!cs_malloc(&stringcache[pos], 16 * sizeof(char *)))
							{ break; }
					}
					else
					{
						if(!cs_realloc(&stringcache[pos], (allocated[pos] + 16) * sizeof(char *)))
							{ break; }
					}
					allocated[pos] += 16;
				}
				stringcache[pos][used[pos]] = tmp;
				used[pos] += 1;
			}
		}

		*srvidasc++ = '\0';
		if(new_syntax)
			{ srvidtmp = dyn_word_atob(token) & 0xFFFF; }
		else
			{ srvidtmp = dyn_word_atob(srvidasc) & 0xFFFF; }
			
		if(srvidtmp < 0)
		{
			NULLFREE(tmpptr);
			NULLFREE(srvid);
			continue;
		}
		else
		{
			srvid->srvid = srvidtmp;
		}		
		
		srvid->ncaid = 0;
		for(i = 0, ptr1 = strtok_r(new_syntax ? srvidasc : token, ",", &saveptr1); (ptr1); ptr1 = strtok_r(NULL, ",", &saveptr1), i++)
		{
			srvid->ncaid++;
		}
		
		if(!cs_malloc(&srvid->caid, sizeof(struct s_srvid_caid) * srvid->ncaid))
		{
			NULLFREE(tmpptr);
			NULLFREE(srvid);
			return 0;
		}
		
		ptr1 = new_syntax ? srvidasc : token;
		for(i = 0; i < srvid->ncaid; i++)
		{
			prov = strchr(ptr1,'@');
						
			srvid->caid[i].nprovid = 0;
			
			if(prov)
			{
				if(prov[1] != '\0')
				{
					for(j = 0, ptr2 = strtok_r(prov+1, "@", &saveptr2); (ptr2); ptr2 = strtok_r(NULL, "@", &saveptr2), j++)
					{
						srvid->caid[i].nprovid++;
					}
		    		
					if(!cs_malloc(&srvid->caid[i].provid, sizeof(uint32_t) * srvid->caid[i].nprovid))
					{
						for(j = 0; j < i; j++)
							{ NULLFREE(srvid->caid[j].provid); } 
						NULLFREE(srvid->caid);
						NULLFREE(tmpptr);
						NULLFREE(srvid);
						return 0;
					}
					
					ptr2 = prov+1;
					for(j = 0;  j < srvid->caid[i].nprovid; j++)
					{
						srvid->caid[i].provid[j] = dyn_word_atob(ptr2) & 0xFFFFFF;
						ptr2 = ptr2 + strlen(ptr2) + 1;
					}
				}
				else
				{
					ptr2 = prov+2;
				}
				
				prov[0] = '\0';
			}

			srvid->caid[i].caid = dyn_word_atob(ptr1) & 0xFFFF;
			if(prov)
				{ ptr1 = ptr2; }
			else 
				{ ptr1 = ptr1 + strlen(ptr1) + 1; }
		}
			
		nr++;

		if(new_cfg_srvid[srvid->srvid >> 12])
			{ last_srvid[srvid->srvid >> 12]->next = srvid; }
		else
			{ new_cfg_srvid[srvid->srvid >> 12] = srvid; }

		last_srvid[srvid->srvid >> 12] = srvid;
	}
コード例 #4
0
static void ecmwhitelist_fn(const char *token, char *value, void *setting, FILE *f) {
    struct s_reader *rdr = setting;
    if (value) {
        char *ptr, *ptr2, *ptr3, *saveptr1 = NULL;
        struct s_ecmWhitelist *tmp, *last;
        struct s_ecmWhitelistIdent *tmpIdent, *lastIdent;
        struct s_ecmWhitelistLen *tmpLen, *lastLen;
        for(tmp = rdr->ecmWhitelist; tmp; tmp=tmp->next) {
            for(tmpIdent = tmp->idents; tmpIdent; tmpIdent=tmpIdent->next) {
                for(tmpLen = tmpIdent->lengths; tmpLen; tmpLen=tmpLen->next) {
                    add_garbage(tmpLen);
                }
                add_garbage(tmpIdent);
            }
            add_garbage(tmp);
        }
        rdr->ecmWhitelist = NULL;
        if(strlen(value) > 0) {
            saveptr1 = NULL;
            char *saveptr2 = NULL;
            for (ptr = strtok_r(value, ";", &saveptr1); ptr; ptr = strtok_r(NULL, ";", &saveptr1)) {
                int16_t caid = 0, len;
                uint32_t ident = 0;
                ptr2=strchr(ptr,':');
                if(ptr2 != NULL) {
                    ptr2[0] = '\0';
                    ++ptr2;
                    ptr3=strchr(ptr,'@');
                    if(ptr3 != NULL) {
                        ptr3[0] = '\0';
                        ++ptr3;
                        ident = (uint32_t)a2i(ptr3, 6);
                    }
                    caid = (int16_t)dyn_word_atob(ptr);
                } else ptr2 = ptr;
                for (ptr2 = strtok_r(ptr2, ",", &saveptr2); ptr2; ptr2 = strtok_r(NULL, ",", &saveptr2)) {
                    len = (int16_t)dyn_word_atob(ptr2);
                    last = NULL, tmpIdent = NULL, lastIdent = NULL, tmpLen = NULL, lastLen = NULL;
                    for(tmp = rdr->ecmWhitelist; tmp; tmp=tmp->next) {
                        last = tmp;
                        if(tmp->caid == caid) {
                            for(tmpIdent = tmp->idents; tmpIdent; tmpIdent=tmpIdent->next) {
                                lastIdent = tmpIdent;
                                if(tmpIdent->ident == ident) {
                                    for(tmpLen = tmpIdent->lengths; tmpLen; tmpLen=tmpLen->next) {
                                        lastLen = tmpLen;
                                        if(tmpLen->len == len) break;
                                    }
                                    break;
                                }
                            }
                        }
                    }
                    if(tmp == NULL) {
                        if (cs_malloc(&tmp, sizeof(struct s_ecmWhitelist))) {
                            tmp->caid = caid;
                            tmp->idents = NULL;
                            tmp->next = NULL;
                            if(last == NULL) {
                                rdr->ecmWhitelist = tmp;
                            } else {
                                last->next = tmp;
                            }
                        }
                    }
                    if(tmp != NULL && tmpIdent == NULL) {
                        if (cs_malloc(&tmpIdent, sizeof(struct s_ecmWhitelistIdent))) {
                            tmpIdent->ident = ident;
                            tmpIdent->lengths = NULL;
                            tmpIdent->next = NULL;
                            if(lastIdent == NULL) {
                                tmp->idents = tmpIdent;
                            } else {
                                lastIdent->next = tmpIdent;
                            }
                        }
                    }
                    if(tmp != NULL && tmpIdent != NULL && tmpLen == NULL) {
                        if (cs_malloc(&tmpLen, sizeof(struct s_ecmWhitelistLen))) {
                            tmpLen->len = len;
                            tmpLen->next = NULL;
                            if(lastLen == NULL) {
                                tmpIdent->lengths = tmpLen;
                            } else {
                                lastLen->next = tmpLen;
                            }
                        }
                    }
                }
            }
        }
        return;
    }

    value = mk_t_ecmwhitelist(rdr->ecmWhitelist);
    if (strlen(value) > 0 || cfg.http_full_cfg)
        fprintf_conf(f, token, "%s\n", value);
    free_mk_t(value);
}
コード例 #5
0
static void ecmheaderwhitelist_fn(const char *token, char *value, void *setting, FILE *f) {
    struct s_reader *rdr = setting;
    if (value) {
        char *ptr, *ptr2, *ptr3;
        struct s_ecmHeaderwhitelist *tmp, *last = NULL;

        if (strlen(value) == 0) {
            for (tmp = rdr->ecmHeaderwhitelist; tmp; tmp=tmp->next)
                add_garbage(tmp);
            rdr->ecmHeaderwhitelist = NULL;
        } else {
            char *ptr4, *ptr5, *ptr6, *saveptr = NULL, *saveptr4 = NULL, *saveptr5 = NULL, *saveptr6 = NULL;
            uint16_t caid = 0;
            uint32_t provid = 0;
            int16_t len = 0;
            for (ptr = strtok_r(value, ";", &saveptr); ptr; ptr = strtok_r(NULL, ";", &saveptr)) {
                caid = 0;
                provid = 0;
                ptr2 = strchr(ptr, '@');
                ptr3 = strchr(ptr, ':');
                if (ptr2 == NULL && ptr3 == NULL) { //no Caid no Provid
                    for (ptr4 = strtok_r(ptr, ",", &saveptr4); ptr4; ptr4 = strtok_r(NULL, ",", &saveptr4)) {
                        if (cs_malloc(&tmp, sizeof(struct s_ecmHeaderwhitelist))) {
                            ptr4 = trim(ptr4);
                            len = strlen(ptr4);
                            key_atob_l(ptr4, tmp->header, len);
                            tmp->len = len;
                            tmp->caid = 0;
                            tmp->provid = 0;
                            tmp->next = NULL;
                            if (last == NULL) {
                                rdr->ecmHeaderwhitelist = tmp;
                            } else {
                                last->next = tmp;
                            }
                            last = tmp;
                        }
                    }
                }

                if (ptr3 != NULL && ptr2 == NULL) { // only with Caid
                    ptr3[0] = '\0';
                    ++ptr3;
                    caid = (int16_t)dyn_word_atob(ptr);
                    for (ptr5 = strtok_r(ptr3, ",", &saveptr5); ptr5; ptr5 = strtok_r(NULL, ",", &saveptr5)) {
                        if (cs_malloc(&tmp, sizeof(struct s_ecmHeaderwhitelist))) {
                            tmp->caid = caid;
                            tmp->provid = 0;
                            ptr5 = trim(ptr5);
                            len = strlen(ptr5);
                            key_atob_l(ptr5, tmp->header, len);
                            tmp->len = len;
                            tmp->next = NULL;
                            if (last == NULL) {
                                rdr->ecmHeaderwhitelist = tmp;
                            } else {
                                last->next = tmp;
                            }
                            last = tmp;
                        }
                    }
                }

                if (ptr3 != NULL && ptr2 != NULL) { // with Caid & Provid
                    ptr2[0] = '\0';
                    ++ptr2; // -> provid
                    ptr3[0] = '\0';
                    ++ptr3; // -> headers
                    caid = (int16_t)dyn_word_atob(ptr);
                    provid = (uint32_t)a2i(ptr2, 6);
                    for (ptr6 = strtok_r(ptr3, ",", &saveptr6); ptr6; ptr6 = strtok_r(NULL, ",", &saveptr6)) {
                        if (cs_malloc(&tmp, sizeof(struct s_ecmHeaderwhitelist))) {
                            tmp->caid = caid;
                            tmp->provid = provid;
                            ptr6 = trim(ptr6);
                            len = strlen(ptr6);
                            key_atob_l(ptr6, tmp->header, len);
                            tmp->len = len;
                            tmp->next = NULL;
                            if (last == NULL) {
                                rdr->ecmHeaderwhitelist = tmp;
                            } else {
                                last->next = tmp;
                            }
                            last = tmp;
                        }
                    }
                }
            }
        }
        /*	if (rdr->ecmHeaderwhitelist != NULL) { // debug
        		cs_log("**********Begin ECM Header List for Reader: %s **************", rdr->label);

        		struct s_ecmHeaderwhitelist *tmp;
        		for(tmp = rdr->ecmHeaderwhitelist; tmp; tmp=tmp->next){
        			cs_log("Caid: %i Provid: %i Header: %02X Len: %i", tmp->caid, tmp->provid, tmp->header[0], tmp->len);
        		}
        		cs_log("***********End ECM Header List for Reader: %s ***************", rdr->label);
        	} */
        return;
    }

    value = mk_t_ecmheaderwhitelist(rdr->ecmHeaderwhitelist);
    if (strlen(value) > 0 || cfg.http_full_cfg)
        fprintf_conf(f, token, "%s\n", value);
    free_mk_t(value);
}
コード例 #6
0
ファイル: oscam-config.c プロジェクト: TELE-TWIN/oscam
int32_t init_srvid(void)
{
	FILE *fp = open_config_file(cs_srid);
	if (!fp)
		return 0;

	int32_t nr = 0, i;
	char *payload, *tmp, *saveptr1 = NULL, *token;
	if (!cs_malloc(&token, MAXLINESIZE))
		return 0;
	struct s_srvid *srvid=NULL, *new_cfg_srvid[16], *last_srvid[16];
	// A cache for strings within srvids. A checksum is calculated which is the start point in the array (some kind of primitive hash algo).
	// From this point, a sequential search is done. This greatly reduces the amount of string comparisons.
	char **stringcache[1024];
	int32_t allocated[1024] = { 0 };
	int32_t used[1024] = { 0 };
	struct timeb ts, te;
  cs_ftime(&ts);

	memset(last_srvid, 0, sizeof(last_srvid));
	memset(new_cfg_srvid, 0, sizeof(new_cfg_srvid));

	while (fgets(token, MAXLINESIZE, fp)) {
		int32_t l, j, len=0, len2, srvidtmp;
		uint32_t pos;
		char *srvidasc;
		tmp = trim(token);

		if (tmp[0] == '#') continue;
		if ((l=strlen(tmp)) < 6) continue;
		if (!(srvidasc = strchr(token, ':'))) continue;
		if (!(payload=strchr(token, '|'))) continue;
		*payload++ = '\0';

		if (!cs_malloc(&srvid, sizeof(struct s_srvid))) {
			free(token);
			fclose(fp);
			return(1);
		}

		char tmptxt[128];

		int32_t offset[4] = { -1, -1, -1, -1 };
		char *ptr1, *searchptr[4] = { NULL, NULL, NULL, NULL };
		char **ptrs[4] = { &srvid->prov, &srvid->name, &srvid->type, &srvid->desc };

		for (i = 0, ptr1 = strtok_r(payload, "|", &saveptr1); ptr1 && (i < 4) ; ptr1 = strtok_r(NULL, "|", &saveptr1), ++i){
			// check if string is in cache
			len2 = strlen(ptr1);
			pos = 0;
			for(j = 0; j < len2; ++j) pos += (uint8_t)ptr1[j];
			pos = pos%1024;
			for(j = 0; j < used[pos]; ++j){
				if (!strcmp(stringcache[pos][j], ptr1)){
					searchptr[i]=stringcache[pos][j];
					break;
				}
			}
			if (searchptr[i]) continue;

			offset[i]=len;
			cs_strncpy(tmptxt+len, trim(ptr1), sizeof(tmptxt)-len);
			len+=strlen(ptr1)+1;
		}

		char *tmpptr = NULL;
		if (len > 0 && !cs_malloc(&tmpptr, len))
			continue;

		srvid->data=tmpptr;
		if(len > 0) memcpy(tmpptr, tmptxt, len);

		for (i=0;i<4;i++) {
			if (searchptr[i]) {
				*ptrs[i] = searchptr[i];
				continue;
			}
			if (offset[i]>-1){
				*ptrs[i] = tmpptr + offset[i];
				// store string in stringcache
				tmp = *ptrs[i];
				len2 = strlen(tmp);
				pos = 0;
				for(j = 0; j < len2; ++j) pos += (uint8_t)tmp[j];
				pos = pos%1024;
				if(used[pos] >= allocated[pos]){
					if (allocated[pos] == 0) {
						if (!cs_malloc(&stringcache[pos], 16 * sizeof(char *)))
							break;
					} else {
						if (!cs_realloc(&stringcache[pos], (allocated[pos] + 16) * sizeof(char *)))
							break;
					}
					allocated[pos] += 16;
				}
				stringcache[pos][used[pos]] = tmp;
				used[pos] += 1;
			}
		}

		*srvidasc++ = '\0';
		srvidtmp = dyn_word_atob(srvidasc) & 0xFFFF;
		//printf("srvid %s - %d\n",srvidasc,srvid->srvid );

		if (srvidtmp<0) {
			free(tmpptr);
			free(srvid);
			continue;
		} else srvid->srvid = srvidtmp;

		srvid->ncaid = 0;
		for (i = 0, ptr1 = strtok_r(token, ",", &saveptr1); (ptr1) && (i < 10) ; ptr1 = strtok_r(NULL, ",", &saveptr1), i++){
			srvid->caid[i] = dyn_word_atob(ptr1);
			srvid->ncaid = i+1;
			//cs_debug_mask(D_CLIENT, "ld caid: %04X srvid: %04X Prov: %s Chan: %s",srvid->caid[i],srvid->srvid,srvid->prov,srvid->name);
		}
		nr++;

		if (new_cfg_srvid[srvid->srvid>>12])
			last_srvid[srvid->srvid>>12]->next = srvid;
		else
			new_cfg_srvid[srvid->srvid>>12] = srvid;

		last_srvid[srvid->srvid>>12] = srvid;
	}