FreeBSD/sys/netpfil/ipfw/ip_fw_sockopt.c
/*
 * Delete rules matching range @rt.
 * Saves number of deleted rules in @ndel.
 *
 * Returns 0 on success.
 */
Delete rules matching range @rt.
Saves number of deleted rules in @ndel.

Returns 0 on success.
Delete rules matching range @rt . Saves number of deleted rules in @ndel . Returns 0 on success .
static int
delete_range(struct ip_fw_chain *chain, ipfw_range_tlv *rt, int *ndel)
{
	struct ip_fw *reap, *rule, **map;
	int end, start;
	int i, n, ndyn, ofs;
	reap = NULL;
	IPFW_UH_WLOCK(chain);	
	start = 0;
	end = chain->n_rules - 1;
	if ((rt->flags & IPFW_RCFLAG_RANGE) != 0) {
		start = ipfw_find_rule(chain, rt->start_rule, 0);
		end = ipfw_find_rule(chain, rt->end_rule, 0);
		if (rt->end_rule != IPFW_DEFAULT_RULE)
			while (chain->map[end]->rulenum == rt->end_rule)
				end++;
	}
	map = get_map(chain, 0, 1 );
	if (map == NULL) {
		IPFW_UH_WUNLOCK(chain);
		return (ENOMEM);
	}
	n = 0;
	ndyn = 0;
	ofs = start;
	if (start > 0)
		bcopy(chain->map, map, start * sizeof(struct ip_fw *));
	for (i = start; i < end; i++) {
		rule = chain->map[i];
		if (ipfw_match_range(rule, rt) == 0) {
			map[ofs++] = rule;
			continue;
		}
		n++;
		if (ipfw_is_dyn_rule(rule) != 0)
			ndyn++;
	}
	bcopy(chain->map + end, map + ofs,
		(chain->n_rules - end) * sizeof(struct ip_fw *));
	update_skipto_cache(chain, map);
	map = swap_map(chain, map, chain->n_rules - n);
	if (ndyn > 0)
		ipfw_expire_dyn_rules(chain, rt);
	for (i = start; i < end; i++) {
		rule = map[i];
		if (ipfw_match_range(rule, rt) == 0)
			continue;
		chain->static_len -= RULEUSIZE0(rule);
		ipfw_reap_add(chain, &reap, rule);
	}
	IPFW_UH_WUNLOCK(chain);
	ipfw_reap_rules(reap);
	if (map != NULL)
		free(map, M_IPFW);
	*ndel = n;
	return (0);
}
static int delete_range ( struct ip_fw_chain * chain , ipfw_range_tlv * rt , int * ndel ) { struct ip_fw * reap , * rule , * * map ; int end , start ; int i , n , ndyn , ofs ; reap = NULL ; IPFW_UH_WLOCK ( chain ) ; start = 0 ; end = chain -> n_rules - 1 ; if ( ( rt -> flags & IPFW_RCFLAG_RANGE ) != 0 ) { start = ipfw_find_rule ( chain , rt -> start_rule , 0 ) ; end = ipfw_find_rule ( chain , rt -> end_rule , 0 ) ; if ( rt -> end_rule != IPFW_DEFAULT_RULE ) while ( chain -> map [ end ] -> rulenum == rt -> end_rule ) end ++ ; } map = get_map ( chain , 0 , 1 ) ; if ( map == NULL ) { IPFW_UH_WUNLOCK ( chain ) ; return ( ENOMEM ) ; } n = 0 ; ndyn = 0 ; ofs = start ; if ( start > 0 ) bcopy ( chain -> map , map , start * sizeof ( struct ip_fw * ) ) ; for ( i = start ; i < end ; i ++ ) { rule = chain -> map [ i ] ; if ( ipfw_match_range ( rule , rt ) == 0 ) { map [ ofs ++ ] = rule ; continue ; } n ++ ; if ( ipfw_is_dyn_rule ( rule ) != 0 ) ndyn ++ ; } bcopy ( chain -> map + end , map + ofs , ( chain -> n_rules - end ) * sizeof ( struct ip_fw * ) ) ; update_skipto_cache ( chain , map ) ; map = swap_map ( chain , map , chain -> n_rules - n ) ; if ( ndyn > 0 ) ipfw_expire_dyn_rules ( chain , rt ) ; for ( i = start ; i < end ; i ++ ) { rule = map [ i ] ; if ( ipfw_match_range ( rule , rt ) == 0 ) continue ; chain -> static_len -= RULEUSIZE0 ( rule ) ; ipfw_reap_add ( chain , & reap , rule ) ; } IPFW_UH_WUNLOCK ( chain ) ; ipfw_reap_rules ( reap ) ; if ( map != NULL ) free ( map , M_IPFW ) ; * ndel = n ; return ( 0 ) ; }
Delete rules matching range @rt.
Delete rules matching range @rt .
/* arbitrate writers */ /*
	 * Stage 1: Determine range to inspect.
	 * Range is half-inclusive, e.g [start, end).
	 */ /* Allocate new map of the same size */ /* locked */ /* 1. bcopy the initial part of the map */ /* 2. copy active rules between start and end */ /* 3. copy the final part of the map */ /* 4. recalculate skipto cache */ /* 5. swap the maps (under UH_WLOCK + WHLOCK) */ /* 6. Remove all dynamic states originated by deleted rules */ /* 7. now remove the rules deleted from the old map */