Example #1
0
/* frees all the expired entries until either there are no more of them
 *  or the total memory used is <= target (to free all of them use -1 for
 *  targer)
 *  params:   target  - free expired entries until no more then taget memory
 *                      is used  (use 0 to free all of them)
 *            delta   - consider an entry expired if it expires after delta
 *                      ticks from now
 *            timeout - exit after timeout ticks
 *
 *  returns: number of deleted entries
 *  This function should be called periodically from a timer
 */
inline static int dst_blacklist_clean_expired(unsigned int target,
									  ticks_t delta,
									  ticks_t timeout)
{
	static unsigned int start=0;
	unsigned int h;
	struct dst_blst_entry** crt;
	struct dst_blst_entry** tmp;
	struct dst_blst_entry* e;
	ticks_t start_time;
	ticks_t now;
	int no=0;
	int i;

	now=start_time=get_ticks_raw();
	for(h=start; h!=(start+DST_BLST_HASH_SIZE); h++){
		i=h%DST_BLST_HASH_SIZE;
		if (dst_blst_hash[i].first){
			LOCK_BLST(i);
			for (crt=&dst_blst_hash[i].first, tmp=&(*crt)->next;
					*crt; crt=tmp, tmp=&(*crt)->next){
				e=*crt;
				prefetch_loc_r((*crt)->next, 1);
				if ((s_ticks_t)(now+delta-(*crt)->expire)>=0){
					*crt=(*crt)->next;
					tmp=crt;
					*blst_mem_used-=DST_BLST_ENTRY_SIZE(*e);
					blst_destroy_entry(e);
					BLST_HASH_STATS_DEC(i);
					no++;
					if (*blst_mem_used<=target){
						UNLOCK_BLST(i);
						goto skip;
					}
				}
			}
			UNLOCK_BLST(i);
			/* check for timeout only "between" hash cells */
			now=get_ticks_raw();
			if ((now-start_time)>=timeout){
				DBG("_dst_blacklist_clean_expired_unsafe: timeout: %d > %d\n",
						TICKS_TO_MS(now-start_time), TICKS_TO_MS(timeout));
				goto skip;
			}
		}
	}
skip:
	start=h; /* next time we start where we left */
	if (no){
		DBG("dst_blacklist_clean_expired, %d entries removed\n", no);
	}
	return no;
}
Example #2
0
/* must be called with the lock held
 * returns 1 if a matching entry was deleted, 0 otherwise
 * it also deletes expired elements (expire<=now) as it searches
 * proto==PROTO_NONE = wildcard */
inline static int _dst_blacklist_del(
												unsigned short hash,
												struct ip_addr* ip,
												unsigned char proto,
												unsigned short port,
												ticks_t now)
{
	struct dst_blst_entry** crt;
	struct dst_blst_entry** tmp;
	struct dst_blst_entry* e;
	struct dst_blst_entry** head;
	unsigned char type;
	
	head=&dst_blst_hash[hash].first;
#ifdef USE_IPV6
	type=(ip->af==AF_INET6)*BLST_IS_IPV6;
#else  /* USE_IPV6 */
	if (unlikely(ip->af!=AF_INET)) return 0;
	type=0;
#endif /* USE_IPV6 */
	for (crt=head, tmp=&(*head)->next; *crt; crt=tmp, tmp=&(*crt)->next){
		e=*crt;
		prefetch_loc_r((*crt)->next, 1);
		/* remove old expired entries */
		if ((s_ticks_t)(now-(*crt)->expire)>=0){
			*crt=(*crt)->next;
			tmp=crt;
			*blst_mem_used-=DST_BLST_ENTRY_SIZE(*e);
			BLST_HASH_STATS_DEC(hash);
			blst_destroy_entry(e);
		}else if ((e->port==port) && ((e->flags & BLST_IS_IPV6)==type) &&
				((e->proto==PROTO_NONE) || (proto==PROTO_NONE) ||
					(e->proto==proto)) && 
					(memcmp(ip->u.addr, e->ip, ip->len)==0)){
			*crt=(*crt)->next;
			tmp=crt;
			*blst_mem_used-=DST_BLST_ENTRY_SIZE(*e);
			BLST_HASH_STATS_DEC(hash);
			blst_destroy_entry(e);
			return 1;
		}
	}
	return 0;
}
Example #3
0
/* deletes all the entries from the blacklist except the permanent ones
 * (which are marked with BLST_PERMANENT)
 */
void dst_blst_flush(void)
{
	int h;
	struct dst_blst_entry* e;
	struct dst_blst_entry** crt;
	struct dst_blst_entry** tmp;

	for(h=0; h<DST_BLST_HASH_SIZE; h++){
		LOCK_BLST(h);
		for (crt=&dst_blst_hash[h].first, tmp=&(*crt)->next;
				*crt; crt=tmp, tmp=&(*crt)->next){
			e=*crt;
			prefetch_loc_r((*crt)->next, 1);
			if (!(e->flags &  BLST_PERMANENT)){
				*crt=(*crt)->next;
				tmp=crt;
				*blst_mem_used-=DST_BLST_ENTRY_SIZE(*e);
				blst_destroy_entry(e);
				BLST_HASH_STATS_DEC(h);
			}
		}
		UNLOCK_BLST(h);
	}
}
Example #4
0
/* note: it continues where it previously stopped and goes ahead until
   end is encountered or desired HFs are found; if you call it twice
   for the same HF which is present only once, it will fail the second
   time; if you call it twice and the HF is found on second time too,
   it's not replaced in the well-known HF pointer but just added to
   header list; if you want to use a dumb convenience function which will
   give you the first occurrence of a header you are interested in,
   look at check_transaction_quadruple
*/
int parse_headers(struct sip_msg* const msg, const hdr_flags_t flags, const int next)
{
    struct hdr_field* hf;
    char* tmp;
    char* rest;
    char* end;
    hdr_flags_t orig_flag;

    end=msg->buf+msg->len;
    tmp=msg->unparsed;

    if (unlikely(next)) {
        orig_flag = msg->parsed_flag;
        msg->parsed_flag &= ~flags;
    } else
        orig_flag=0;

#ifdef EXTRA_DEBUG
    DBG("parse_headers: flags=%llx\n", (unsigned long long)flags);
#endif
    while( tmp<end && (flags & msg->parsed_flag) != flags) {
        prefetch_loc_r(tmp+64, 1);
        hf=pkg_malloc(sizeof(struct hdr_field));
        if (unlikely(hf==0)) {
            ser_error=E_OUT_OF_MEM;
            LOG(L_ERR, "ERROR:parse_headers: memory allocation error\n");
            goto error;
        }
        memset(hf,0, sizeof(struct hdr_field));
        hf->type=HDR_ERROR_T;
        rest=get_hdr_field(tmp, end, hf);
        switch (hf->type) {
        case HDR_ERROR_T:
            LOG(L_INFO,"ERROR: bad header field [%.*s]\n",
                (end-tmp>20)?20:(int)(end-tmp), tmp);
            goto  error;
        case HDR_EOH_T:
            msg->eoh=tmp; /* or rest?*/
            msg->parsed_flag|=HDR_EOH_F;
            pkg_free(hf);
            goto skip;
        case HDR_ACCEPTCONTACT_T:
        case HDR_ALLOWEVENTS_T:
        case HDR_CONTENTENCODING_T:
        case HDR_REFERREDBY_T:
        case HDR_REJECTCONTACT_T:
        case HDR_REQUESTDISPOSITION_T:
        case HDR_WWW_AUTHENTICATE_T:
        case HDR_PROXY_AUTHENTICATE_T:
        case HDR_RETRY_AFTER_T:
        case HDR_OTHER_T: /* mark the type as found/parsed*/
            msg->parsed_flag|=HDR_T2F(hf->type);
            break;
        case HDR_CALLID_T:
            if (msg->callid==0) msg->callid=hf;
            msg->parsed_flag|=HDR_CALLID_F;
            break;
        case HDR_SIPIFMATCH_T:
            if (msg->sipifmatch==0) msg->sipifmatch=hf;
            msg->parsed_flag|=HDR_SIPIFMATCH_F;
            break;
        case HDR_TO_T:
            if (msg->to==0) msg->to=hf;
            msg->parsed_flag|=HDR_TO_F;
            break;
        case HDR_CSEQ_T:
            if (msg->cseq==0) msg->cseq=hf;
            msg->parsed_flag|=HDR_CSEQ_F;
            break;
        case HDR_FROM_T:
            if (msg->from==0) msg->from=hf;
            msg->parsed_flag|=HDR_FROM_F;
            break;
        case HDR_CONTACT_T:
            if (msg->contact==0) msg->contact=hf;
            msg->parsed_flag|=HDR_CONTACT_F;
            break;
        case HDR_MAXFORWARDS_T:
            if(msg->maxforwards==0) msg->maxforwards=hf;
            msg->parsed_flag|=HDR_MAXFORWARDS_F;
            break;
        case HDR_ROUTE_T:
            if (msg->route==0) msg->route=hf;
            msg->parsed_flag|=HDR_ROUTE_F;
            break;
        case HDR_RECORDROUTE_T:
            if (msg->record_route==0) msg->record_route = hf;
            msg->parsed_flag|=HDR_RECORDROUTE_F;
            break;
        case HDR_CONTENTTYPE_T:
            if (msg->content_type==0) msg->content_type = hf;
            msg->parsed_flag|=HDR_CONTENTTYPE_F;
            break;
        case HDR_CONTENTLENGTH_T:
            if (msg->content_length==0) msg->content_length = hf;
            msg->parsed_flag|=HDR_CONTENTLENGTH_F;
            break;
        case HDR_AUTHORIZATION_T:
            if (msg->authorization==0) msg->authorization = hf;
            msg->parsed_flag|=HDR_AUTHORIZATION_F;
            break;
        case HDR_EXPIRES_T:
            if (msg->expires==0) msg->expires = hf;
            msg->parsed_flag|=HDR_EXPIRES_F;
            break;
        case HDR_PROXYAUTH_T:
            if (msg->proxy_auth==0) msg->proxy_auth = hf;
            msg->parsed_flag|=HDR_PROXYAUTH_F;
            break;
        case HDR_PROXYREQUIRE_T:
            if (msg->proxy_require==0) msg->proxy_require = hf;
            msg->parsed_flag|=HDR_PROXYREQUIRE_F;
            break;
        case HDR_SUPPORTED_T:
            if (msg->supported==0) msg->supported=hf;
            msg->parsed_flag|=HDR_SUPPORTED_F;
            break;
        case HDR_REQUIRE_T:
            if (msg->require==0) msg->require=hf;
            msg->parsed_flag|=HDR_REQUIRE_F;
            break;
        case HDR_UNSUPPORTED_T:
            if (msg->unsupported==0) msg->unsupported=hf;
            msg->parsed_flag|=HDR_UNSUPPORTED_F;
            break;
        case HDR_ALLOW_T:
            if (msg->allow==0) msg->allow = hf;
            msg->parsed_flag|=HDR_ALLOW_F;
            break;
        case HDR_EVENT_T:
            if (msg->event==0) msg->event = hf;
            msg->parsed_flag|=HDR_EVENT_F;
            break;
        case HDR_ACCEPT_T:
            if (msg->accept==0) msg->accept = hf;
            msg->parsed_flag|=HDR_ACCEPT_F;
            break;
        case HDR_ACCEPTLANGUAGE_T:
            if (msg->accept_language==0) msg->accept_language = hf;
            msg->parsed_flag|=HDR_ACCEPTLANGUAGE_F;
            break;
        case HDR_ORGANIZATION_T:
            if (msg->organization==0) msg->organization = hf;
            msg->parsed_flag|=HDR_ORGANIZATION_F;
            break;
        case HDR_PRIORITY_T:
            if (msg->priority==0) msg->priority = hf;
            msg->parsed_flag|=HDR_PRIORITY_F;
            break;
        case HDR_SUBJECT_T:
            if (msg->subject==0) msg->subject = hf;
            msg->parsed_flag|=HDR_SUBJECT_F;
            break;
        case HDR_USERAGENT_T:
            if (msg->user_agent==0) msg->user_agent = hf;
            msg->parsed_flag|=HDR_USERAGENT_F;
            break;
        case HDR_SERVER_T:
            if (msg->server==0) msg->server = hf;
            msg->parsed_flag|=HDR_SERVER_F;
            break;
        case HDR_CONTENTDISPOSITION_T:
            if (msg->content_disposition==0) msg->content_disposition = hf;
            msg->parsed_flag|=HDR_CONTENTDISPOSITION_F;
            break;
        case HDR_DIVERSION_T:
            if (msg->diversion==0) msg->diversion = hf;
            msg->parsed_flag|=HDR_DIVERSION_F;
            break;
        case HDR_RPID_T:
            if (msg->rpid==0) msg->rpid = hf;
            msg->parsed_flag|=HDR_RPID_F;
            break;
        case HDR_REFER_TO_T:
            if (msg->refer_to==0) msg->refer_to = hf;
            msg->parsed_flag|=HDR_REFER_TO_F;
            break;
        case HDR_SESSIONEXPIRES_T:
            if (msg->session_expires==0) msg->session_expires = hf;
            msg->parsed_flag|=HDR_SESSIONEXPIRES_F;
            break;
        case HDR_MIN_SE_T:
            if (msg->min_se==0) msg->min_se = hf;
            msg->parsed_flag|=HDR_MIN_SE_F;
            break;
        case HDR_SUBSCRIPTION_STATE_T:
            if (msg->subscription_state==0) msg->subscription_state = hf;
            msg->parsed_flag|=HDR_SUBSCRIPTION_STATE_F;
            break;
        case HDR_VIA_T:
            msg->parsed_flag|=HDR_VIA_F;
            DBG("parse_headers: Via found, flags=%llx\n",
                (unsigned long long)flags);
            if (msg->via1==0) {
                DBG("parse_headers: this is the first via\n");
                msg->h_via1=hf;
                msg->via1=hf->parsed;
                if (msg->via1->next) {
                    msg->via2=msg->via1->next;
                    msg->parsed_flag|=HDR_VIA2_F;
                }
            } else if (msg->via2==0) {
                msg->h_via2=hf;
                msg->via2=hf->parsed;
                msg->parsed_flag|=HDR_VIA2_F;
                DBG("parse_headers: this is the second via\n");
            }
            break;
        case HDR_DATE_T:
            if (msg->date==0) msg->date=hf;
            msg->parsed_flag|=HDR_DATE_F;
            break;
        case HDR_IDENTITY_T:
            if (msg->identity==0) msg->identity=hf;
            msg->parsed_flag|=HDR_IDENTITY_F;
            break;
        case HDR_IDENTITY_INFO_T:
            if (msg->identity_info==0) msg->identity_info=hf;
            msg->parsed_flag|=HDR_IDENTITY_INFO_F;
            break;
        case HDR_PATH_T:
            if (msg->path==0) msg->path=hf;
            msg->parsed_flag|=HDR_PATH_F;
            break;
        case HDR_PRIVACY_T:
            if (msg->privacy==0) msg->privacy=hf;
            msg->parsed_flag|=HDR_PRIVACY_F;
            break;
        case HDR_PAI_T:
            if (msg->pai==0) msg->pai=hf;
            msg->parsed_flag|=HDR_PAI_F;
            break;
        case HDR_PPI_T:
            if (msg->ppi==0) msg->ppi=hf;
            msg->parsed_flag|=HDR_PPI_F;
            break;
        case HDR_REASON_T:
            msg->parsed_flag|=HDR_REASON_F;
            break;
        default:
            LOG(L_CRIT, "BUG: parse_headers: unknown header type %d\n",
                hf->type);
            goto error;
        }
        /* add the header to the list*/
        if (msg->last_header==0) {
            msg->headers=hf;
            msg->last_header=hf;
        } else {
            msg->last_header->next=hf;
            msg->last_header=hf;
        }
#ifdef EXTRA_DEBUG
        DBG("header field type %d, name=<%.*s>, body=<%.*s>\n",
            hf->type,
            hf->name.len, ZSW(hf->name.s),
            hf->body.len, ZSW(hf->body.s));
#endif
        tmp=rest;
    }
skip:
    msg->unparsed=tmp;
    /* restore original flags */
    msg->parsed_flag |= orig_flag;
    return 0;

error:
    ser_error=E_BAD_REQ;
    if (hf) pkg_free(hf);
    /* restore original flags */
    msg->parsed_flag |= orig_flag;
    return -1;
}