func: struct xt_table *ipt_register_table(struct net const struct xt_table const struct ipt_replace *repl) struct xt_table_info * newinfo ; void * loc_cpu_entry ; newinfo = xt_alloc_table_info ( repl -> size ); if ( ! newinfo )  loc_cpu_entry = newinfo -> entries; memcpy ( loc_cpu_entry , repl -> entries , repl -> size ); ret = translate_table ( net , newinfo , loc_cpu_entry , repl ); static translate_table(struct net *net, struct xt_table_info *newinfo, void const struct ipt_replace *repl) newinfo -> size = repl -> size; newinfo -> number = repl -> num_entries; newinfo -> hook_entry [ i ] = 0xFFFFFFFF; newinfo -> underflow [ i ] = 0xFFFFFFFF; duprintf ( "translate_table: size %u\n" , newinfo -> size ); xt_entry_foreach ( iter , entry0 , newinfo -> size ) ret = check_entry_size_and_hooks ( iter , newinfo , entry0 , entry0 + repl -> size , repl -> hook_entry , repl -> underflow , repl -> valid_hooks ); static check_entry_size_and_hooks(struct ipt_entry struct xt_table_info const unsigned char const unsigned char const unsigned int const unsigned int unsigned int valid_hooks) if ( ( unsigned long ) e % __alignof__ ( struct ipt_entry ) != 0 ( unsigned char * ) e + sizeof ( struct ipt_entry ) >= limit ) duprintf ( "Bad offset %p\n" , e ); if ( e -> next_offset < sizeof ( struct ipt_entry ) + sizeof ( struct xt_entry_target ) )  duprintf ( "checking: element %p size %u\n" , e , e -> next_offset ); if ( ! ( valid_hooks & ( 1 << h ) ) )  if ( ( unsigned char * ) e - base == hook_entries [ h ] )  newinfo -> hook_entry [ h ] = hook_entries [ h ]; if ( ( unsigned char * ) e - base == underflows [ h ] )  if ( ! check_underflow ( e ) )  static bool check_underflow(const struct ipt_entry *e) if ( ! unconditional ( & e -> ip ) )  static inline bool unconditional(const struct ipt_ip *ip) return memcmp ( ip , & uncond , sizeof ( uncond ) ) == 0 ; t = ipt_get_target_c ( e ); static inline const struct xt_entry_target ipt_get_target_c(const struct ipt_entry *e) return ipt_get_target ( ( struct ipt_entry * ) e ) ; if ( strcmp ( t -> u . user . name , XT_STANDARD_TARGET ) != 0 )  verdict = ( ( struct xt_standard_target * ) t ) -> verdict; verdict = - verdict - 1; return verdict == NF_DROP || verdict == NF_ACCEPT ; newinfo -> underflow [ h ] = underflows [ h ]; e -> counters = ( ( struct xt_counters ) 0 , 0 ) e -> comefrom = 0; if ( ret != 0 )  return ret ; ++ newinfo -> stacksize; if ( i != repl -> num_entries )  duprintf ( "translate_table: %u not %u entries\n" , i , repl -> num_entries ); for (i = 0; i < NF_INET_NUMHOOKS; i++) if ( ! ( repl -> valid_hooks & ( 1 << i ) ) )  if ( newinfo -> hook_entry [ i ] == 0xFFFFFFFF )  duprintf ( "Invalid hook entry %u %u\n" , i , repl -> hook_entry [ i ] ); if ( newinfo -> underflow [ i ] == 0xFFFFFFFF )  duprintf ( "Invalid underflow %u %u\n" , i , repl -> underflow [ i ] ); if ( ! mark_source_chains ( newinfo , repl -> valid_hooks , entry0 ) )  static mark_source_chains(const struct xt_table_info unsigned int valid_hooks, void *entry0) unsigned int pos = newinfo -> hook_entry [ hook ] ; struct ipt_entry * e = ( struct ipt_entry * ) ( entry0 + pos ) ; if ( ! ( valid_hooks & ( 1 << hook ) ) )  e -> counters . pcnt = pos; const struct xt_standard_target * t = ( void * ) ipt_get_target_c ( e ) ; static inline const struct xt_entry_target ipt_get_target_c(const struct ipt_entry *e) return ipt_get_target ( ( struct ipt_entry * ) e ) ; int visited = e -> comefrom & ( 1 << hook ) ; if ( e -> comefrom & ( 1 << NF_INET_NUMHOOKS ) )  pr_err ( "iptables: loop hook %u pos %u %08X.\n" , hook , pos , e -> comefrom ); e -> comefrom |= ( ( 1 << hook ) | ( 1 << NF_INET_NUMHOOKS ) ); if ( ( e -> target_offset == sizeof ( struct ipt_entry ) && ( strcmp ( t -> target . u . user . name , XT_STANDARD_TARGET ) == 0 ) && t -> verdict < 0 && unconditional ( & e -> ip ) ) || visited )  static inline bool unconditional(const struct ipt_ip *ip) return memcmp ( ip , & uncond , sizeof ( uncond ) ) == 0 ; if ( ( strcmp ( t -> target . u . user . name , XT_STANDARD_TARGET ) == 0 ) && t -> verdict < - NF_MAX_VERDICT - 1 )  e -> comefrom ^= ( 1 << NF_INET_NUMHOOKS ); if ( e -> comefrom & ( 1 << NF_INET_NUMHOOKS ) )  oldpos = pos; pos = e -> counters . pcnt; e -> counters . pcnt = 0; if ( pos == oldpos )  e = ( struct ipt_entry * ) ( entry0 + pos ); while ( oldpos == pos + e -> next_offset )  size = e -> next_offset; e = ( struct ipt_entry * ) ( entry0 + pos + size ); e -> counters . pcnt = pos; pos += size; int newpos = t -> verdict ; if ( strcmp ( t -> target . u . user . name , XT_STANDARD_TARGET ) == 0 && newpos >= 0 )  if ( newpos > newinfo -> size - sizeof ( struct ipt_entry ) )  duprintf ( "Jump rule %u -> %u\n" , pos , newpos ); newpos = pos + e -> next_offset; e = ( struct ipt_entry * ) ( entry0 + newpos ); e -> counters . pcnt = pos; pos = newpos; xt_entry_foreach ( iter , entry0 , newinfo -> size ) ret = find_check_entry ( iter , net , repl -> name , repl -> size ); static find_check_entry(struct ipt_entry *e, struct net *net, const char unsigned int size) ret = check_entry ( e , name ); static check_entry(const struct ipt_entry *e, const char *name) if ( ! ip_checkentry ( & e -> ip ) )  static ip_checkentry(const struct ipt_ip *ip) if ( ip -> flags & ~IPT_F_MASK )  duprintf ( "Unknown flag bits set: %08X\n" , ip -> flags & ~IPT_F_MASK ); if ( ip -> invflags & ~IPT_INV_MASK )  duprintf ( "Unknown invflag bits set: %08X\n" , ip -> invflags & ~IPT_INV_MASK ); duprintf ( "ip check failed %p %s.\n" , e , name ); if ( e -> target_offset + sizeof ( struct xt_entry_target ) > e -> next_offset )  t = ipt_get_target_c ( e ); static inline const struct xt_entry_target ipt_get_target_c(const struct ipt_entry *e) return ipt_get_target ( ( struct ipt_entry * ) e ) ; if ( e -> target_offset + t -> u . target_size > e -> next_offset )  if ( ret )  return ret ; e -> counters . pcnt = xt_percpu_counter_alloc ( ); if ( IS_ERR_VALUE ( e -> counters . pcnt ) )  mtpar . net = net; mtpar . table = name; mtpar . entryinfo = & e -> ip; mtpar . hook_mask = e -> comefrom; mtpar . family = NFPROTO_IPV4; xt_ematch_foreach ( ematch , e ) ret = find_check_match ( ematch , & mtpar ); static find_check_match(struct xt_entry_match *m, struct xt_mtchk_param *par) match = xt_request_find_match ( NFPROTO_IPV4 , m -> u . user . name , m -> u . user . revision ); if ( IS_ERR ( match ) )  duprintf ( "find_check_match: `%s' not found\n" , m -> u . user . name ); return PTR_ERR ( match ) ; m -> u . kernel . match = match; ret = check_match ( m , par ); static check_match(struct xt_entry_match *m, struct xt_mtchk_param *par) const struct ipt_ip * ip = par -> entryinfo ; par -> match = m -> u . kernel . match; par -> matchinfo = m -> data; ret = xt_check_match ( par , m -> u . match_size - sizeof ( * m ) , ip -> proto , ip -> invflags & IPT_INV_PROTO ); if ( ret < 0 )  duprintf ( "check failed for `%s'.\n" , par -> match -> name ); return ret ; if ( ret )  module_put ( m -> u . kernel . match -> me ); return ret ; if ( ret != 0 )  t = ipt_get_target ( e ); target = xt_request_find_target ( NFPROTO_IPV4 , t -> u . user . name , t -> u . user . revision ); if ( IS_ERR ( target ) )  duprintf ( "find_check_entry: `%s' not found\n" , t -> u . user . name ); ret = PTR_ERR ( target ); t -> u . kernel . target = target; ret = check_target ( e , net , name ); static int check_target(struct ipt_entry *e, struct net *net, const char *name) struct xt_entry_target * t = ipt_get_target ( e ) ; struct xt_tgchk_param par . net = net . table = name . entryinfo = e . target = t -> u . kernel . target . targinfo = t -> data . hook_mask = e -> comefrom . family = NFPROTO_IPV4 , ret = xt_check_target ( & par , t -> u . target_size - sizeof ( * t ) , e -> ip . proto , e -> ip . invflags & IPT_INV_PROTO ); if ( ret < 0 )  duprintf ( "check failed for `%s'.\n" , t -> u . kernel . target -> name ); return ret ; if ( ret )  module_put ( t -> u . kernel . target -> me ); xt_ematch_foreach ( ematch , e ) cleanup_match ( ematch , net ); static void cleanup_match(struct xt_entry_match *m, struct net *net) par . net = net; par . match = m -> u . kernel . match; par . matchinfo = m -> data; par . family = NFPROTO_IPV4; if ( par . match -> destroy != NULL )  par . match -> destroy ( & par ); module_put ( par . match -> me ); xt_percpu_counter_free ( e -> counters . pcnt ); return ret ; if ( ret != 0 )  if ( ret != 0 )  xt_entry_foreach ( iter , entry0 , newinfo -> size ) if ( i -- == 0 )  cleanup_entry ( iter , net ); static cleanup_entry(struct ipt_entry *e, struct net *net) xt_ematch_foreach ( ematch , e ) cleanup_match ( ematch , net ); static void cleanup_match(struct xt_entry_match *m, struct net *net) par . net = net; par . match = m -> u . kernel . match; par . matchinfo = m -> data; par . family = NFPROTO_IPV4; if ( par . match -> destroy != NULL )  par . match -> destroy ( & par ); module_put ( par . match -> me ); t = ipt_get_target ( e ); par . net = net; par . target = t -> u . kernel . target; par . targinfo = t -> data; par . family = NFPROTO_IPV4; if ( par . target -> destroy != NULL )  par . target -> destroy ( & par ); module_put ( par . target -> me ); xt_percpu_counter_free ( e -> counters . pcnt ); return ret ; return ret ; if ( ret != 0 )  return ERR_PTR ( ret ) ; 