kernels/linux-2.4.0/net/ipv6/netfilter/ip6_tables.c
/* Checks and translates the user-supplied table segment (held in
   newinfo) */
Checks and translates the user-supplied table segment (held in
newinfo)
Checks and translates the user - supplied table segment ( held in newinfo )
static int
translate_table(const char *name,
		unsigned int valid_hooks,
		struct ip6t_table_info *newinfo,
		unsigned int size,
		unsigned int number,
		const unsigned int *hook_entries,
		const unsigned int *underflows)
{
	unsigned int i;
	int ret;
	newinfo->size = size;
	newinfo->number = number;
	for (i = 0; i < NF_IP6_NUMHOOKS; i++) {
		newinfo->hook_entry[i] = 0xFFFFFFFF;
		newinfo->underflow[i] = 0xFFFFFFFF;
	}
	duprintf("translate_table: size %u\n", newinfo->size);
	i = 0;
	ret = IP6T_ENTRY_ITERATE(newinfo->entries, newinfo->size,
				check_entry_size_and_hooks,
				newinfo,
				newinfo->entries,
				newinfo->entries + size,
				hook_entries, underflows, &i);
	if (ret != 0)
		return ret;
	if (i != number) {
		duprintf("translate_table: %u not %u entries\n",
			 i, number);
		return -EINVAL;
	}
	for (i = 0; i < NF_IP6_NUMHOOKS; i++) {
		if (!(valid_hooks & (1 << i)))
			continue;
		if (newinfo->hook_entry[i] == 0xFFFFFFFF) {
			duprintf("Invalid hook entry %u %u\n",
				 i, hook_entries[i]);
			return -EINVAL;
		}
		if (newinfo->underflow[i] == 0xFFFFFFFF) {
			duprintf("Invalid underflow %u %u\n",
				 i, underflows[i]);
			return -EINVAL;
		}
	}
	if (!mark_source_chains(newinfo, valid_hooks))
		return -ELOOP;
	i = 0;
	ret = IP6T_ENTRY_ITERATE(newinfo->entries, newinfo->size,
				check_entry, name, size, &i);
	if (ret != 0) {
		IP6T_ENTRY_ITERATE(newinfo->entries, newinfo->size,
				  cleanup_entry, &i);
		return ret;
	}
	for (i = 1; i < smp_num_cpus; i++) {
		memcpy(newinfo->entries + SMP_ALIGN(newinfo->size*i),
		       newinfo->entries,
		       SMP_ALIGN(newinfo->size));
	}
	return ret;
}
static int translate_table ( const char * name , unsigned int valid_hooks , struct ip6t_table_info * newinfo , unsigned int size , unsigned int number , const unsigned int * hook_entries , const unsigned int * underflows ) { unsigned int i ; int ret ; newinfo -> size = size ; newinfo -> number = number ; for ( i = 0 ; i < NF_IP6_NUMHOOKS ; i ++ ) { newinfo -> hook_entry [ i ] = 0xFFFFFFFF ; newinfo -> underflow [ i ] = 0xFFFFFFFF ; } duprintf ( " \n " , newinfo -> size ) ; i = 0 ; ret = IP6T_ENTRY_ITERATE ( newinfo -> entries , newinfo -> size , check_entry_size_and_hooks , newinfo , newinfo -> entries , newinfo -> entries + size , hook_entries , underflows , & i ) ; if ( ret != 0 ) return ret ; if ( i != number ) { duprintf ( " \n " , i , number ) ; return - EINVAL ; } for ( i = 0 ; i < NF_IP6_NUMHOOKS ; i ++ ) { if ( ! ( valid_hooks & ( 1 << i ) ) ) continue ; if ( newinfo -> hook_entry [ i ] == 0xFFFFFFFF ) { duprintf ( " \n " , i , hook_entries [ i ] ) ; return - EINVAL ; } if ( newinfo -> underflow [ i ] == 0xFFFFFFFF ) { duprintf ( " \n " , i , underflows [ i ] ) ; return - EINVAL ; } } if ( ! mark_source_chains ( newinfo , valid_hooks ) ) return - ELOOP ; i = 0 ; ret = IP6T_ENTRY_ITERATE ( newinfo -> entries , newinfo -> size , check_entry , name , size , & i ) ; if ( ret != 0 ) { IP6T_ENTRY_ITERATE ( newinfo -> entries , newinfo -> size , cleanup_entry , & i ) ; return ret ; } for ( i = 1 ; i < smp_num_cpus ; i ++ ) { memcpy ( newinfo -> entries + SMP_ALIGN ( newinfo -> size * i ) , newinfo -> entries , SMP_ALIGN ( newinfo -> size ) ) ; } return ret ; }
Checks and translates the user-supplied table segment (held in
newinfo)
Checks and translates the user - supplied table segment ( held in newinfo )
/* Init all hooks to impossible value. */ /* Walk through entries, checking offsets. */ /* Check hooks all assigned */ /* Only hooks which are valid */ /* Finally, each sanity check must pass */ /* And one copy for every other CPU */