···223223 return (void *)e + e->target_offset;224224}225225226226+#ifndef __KERNEL__226227/* fn returns 0 to continue iteration */227228#define IPT_MATCH_ITERATE(e, fn, args...) \228229 XT_MATCH_ITERATE(struct ipt_entry, e, fn, ## args)···231230/* fn returns 0 to continue iteration */232231#define IPT_ENTRY_ITERATE(entries, size, fn, args...) \233232 XT_ENTRY_ITERATE(struct ipt_entry, entries, size, fn, ## args)233233+#endif234234235235/*236236 * Main firewall chains definitions and global var's definitions.···314312}315313316314#define COMPAT_IPT_ALIGN(s) COMPAT_XT_ALIGN(s)317317-318318-/* fn returns 0 to continue iteration */319319-#define COMPAT_IPT_MATCH_ITERATE(e, fn, args...) \320320- XT_MATCH_ITERATE(struct compat_ipt_entry, e, fn, ## args)321321-322322-/* fn returns 0 to continue iteration */323323-#define COMPAT_IPT_ENTRY_ITERATE(entries, size, fn, args...) \324324- XT_ENTRY_ITERATE(struct compat_ipt_entry, entries, size, fn, ## args)325325-326326-/* fn returns 0 to continue iteration */327327-#define COMPAT_IPT_ENTRY_ITERATE_CONTINUE(entries, size, n, fn, args...) \328328- XT_ENTRY_ITERATE_CONTINUE(struct compat_ipt_entry, entries, size, n, \329329- fn, ## args)330315331316#endif /* CONFIG_COMPAT */332317#endif /*__KERNEL__*/
+2-12
include/linux/netfilter_ipv6/ip6_tables.h
···280280 return (void *)e + e->target_offset;281281}282282283283+#ifndef __KERNEL__283284/* fn returns 0 to continue iteration */284285#define IP6T_MATCH_ITERATE(e, fn, args...) \285286 XT_MATCH_ITERATE(struct ip6t_entry, e, fn, ## args)···288287/* fn returns 0 to continue iteration */289288#define IP6T_ENTRY_ITERATE(entries, size, fn, args...) \290289 XT_ENTRY_ITERATE(struct ip6t_entry, entries, size, fn, ## args)290290+#endif291291292292/*293293 * Main firewall chains definitions and global var's definitions.···342340}343341344342#define COMPAT_IP6T_ALIGN(s) COMPAT_XT_ALIGN(s)345345-346346-/* fn returns 0 to continue iteration */347347-#define COMPAT_IP6T_MATCH_ITERATE(e, fn, args...) \348348- XT_MATCH_ITERATE(struct compat_ip6t_entry, e, fn, ## args)349349-350350-/* fn returns 0 to continue iteration */351351-#define COMPAT_IP6T_ENTRY_ITERATE(entries, size, fn, args...) \352352- XT_ENTRY_ITERATE(struct compat_ip6t_entry, entries, size, fn, ## args)353353-354354-#define COMPAT_IP6T_ENTRY_ITERATE_CONTINUE(entries, size, n, fn, args...) \355355- XT_ENTRY_ITERATE_CONTINUE(struct compat_ip6t_entry, entries, size, n, \356356- fn, ## args)357343358344#endif /* CONFIG_COMPAT */359345#endif /*__KERNEL__*/
+135-166
net/ipv4/netfilter/arp_tables.c
···512512}513513514514static inline int515515-find_check_entry(struct arpt_entry *e, const char *name, unsigned int size,516516- unsigned int *i)515515+find_check_entry(struct arpt_entry *e, const char *name, unsigned int size)517516{518517 struct arpt_entry_target *t;519518 struct xt_target *target;···537538 ret = check_target(e, name);538539 if (ret)539540 goto err;540540-541541- (*i)++;542541 return 0;543542err:544543 module_put(t->u.kernel.target->me);···565568 const unsigned char *limit,566569 const unsigned int *hook_entries,567570 const unsigned int *underflows,568568- unsigned int valid_hooks,569569- unsigned int *i)571571+ unsigned int valid_hooks)570572{571573 unsigned int h;572574···602606 /* Clear counters and comefrom */603607 e->counters = ((struct xt_counters) { 0, 0 });604608 e->comefrom = 0;605605-606606- (*i)++;607609 return 0;608610}609611610610-static inline int cleanup_entry(struct arpt_entry *e, unsigned int *i)612612+static inline void cleanup_entry(struct arpt_entry *e)611613{612614 struct xt_tgdtor_param par;613615 struct arpt_entry_target *t;614614-615615- if (i && (*i)-- == 0)616616- return 1;617616618617 t = arpt_get_target(e);619618 par.target = t->u.kernel.target;···617626 if (par.target->destroy != NULL)618627 par.target->destroy(&par);619628 module_put(par.target->me);620620- return 0;621629}622630623631/* Checks and translates the user-supplied table segment (held in624632 * newinfo).625633 */626626-static int translate_table(const char *name,627627- unsigned int valid_hooks,628628- struct xt_table_info *newinfo,629629- void *entry0,630630- unsigned int size,631631- unsigned int number,632632- const unsigned int *hook_entries,633633- const unsigned int *underflows)634634+static int translate_table(struct xt_table_info *newinfo, void *entry0,635635+ const struct arpt_replace *repl)634636{637637+ struct arpt_entry *iter;635638 unsigned int i;636636- int ret;639639+ int ret = 0;637640638638- newinfo->size = size;639639- newinfo->number = number;641641+ newinfo->size = repl->size;642642+ newinfo->number = repl->num_entries;640643641644 /* Init all hooks to impossible value. */642645 for (i = 0; i < NF_ARP_NUMHOOKS; i++) {···642657 i = 0;643658644659 /* Walk through entries, checking offsets. */645645- ret = ARPT_ENTRY_ITERATE(entry0, newinfo->size,646646- check_entry_size_and_hooks,647647- newinfo,648648- entry0,649649- entry0 + size,650650- hook_entries, underflows, valid_hooks, &i);660660+ xt_entry_foreach(iter, entry0, newinfo->size) {661661+ ret = check_entry_size_and_hooks(iter, newinfo, entry0,662662+ entry0 + repl->size, repl->hook_entry, repl->underflow,663663+ repl->valid_hooks);664664+ if (ret != 0)665665+ break;666666+ ++i;667667+ }651668 duprintf("translate_table: ARPT_ENTRY_ITERATE gives %d\n", ret);652669 if (ret != 0)653670 return ret;654671655655- if (i != number) {672672+ if (i != repl->num_entries) {656673 duprintf("translate_table: %u not %u entries\n",657657- i, number);674674+ i, repl->num_entries);658675 return -EINVAL;659676 }660677661678 /* Check hooks all assigned */662679 for (i = 0; i < NF_ARP_NUMHOOKS; i++) {663680 /* Only hooks which are valid */664664- if (!(valid_hooks & (1 << i)))681681+ if (!(repl->valid_hooks & (1 << i)))665682 continue;666683 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {667684 duprintf("Invalid hook entry %u %u\n",668668- i, hook_entries[i]);685685+ i, repl->hook_entry[i]);669686 return -EINVAL;670687 }671688 if (newinfo->underflow[i] == 0xFFFFFFFF) {672689 duprintf("Invalid underflow %u %u\n",673673- i, underflows[i]);690690+ i, repl->underflow[i]);674691 return -EINVAL;675692 }676693 }677694678678- if (!mark_source_chains(newinfo, valid_hooks, entry0)) {695695+ if (!mark_source_chains(newinfo, repl->valid_hooks, entry0)) {679696 duprintf("Looping hook\n");680697 return -ELOOP;681698 }682699683700 /* Finally, each sanity check must pass */684701 i = 0;685685- ret = ARPT_ENTRY_ITERATE(entry0, newinfo->size,686686- find_check_entry, name, size, &i);702702+ xt_entry_foreach(iter, entry0, newinfo->size) {703703+ ret = find_check_entry(iter, repl->name, repl->size);704704+ if (ret != 0)705705+ break;706706+ ++i;707707+ }687708688709 if (ret != 0) {689689- ARPT_ENTRY_ITERATE(entry0, newinfo->size,690690- cleanup_entry, &i);710710+ xt_entry_foreach(iter, entry0, newinfo->size) {711711+ if (i-- == 0)712712+ break;713713+ cleanup_entry(iter);714714+ }691715 return ret;692716 }693717···709715 return ret;710716}711717712712-/* Gets counters. */713713-static inline int add_entry_to_counter(const struct arpt_entry *e,714714- struct xt_counters total[],715715- unsigned int *i)716716-{717717- ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);718718-719719- (*i)++;720720- return 0;721721-}722722-723723-static inline int set_entry_to_counter(const struct arpt_entry *e,724724- struct xt_counters total[],725725- unsigned int *i)726726-{727727- SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);728728-729729- (*i)++;730730- return 0;731731-}732732-733718static void get_counters(const struct xt_table_info *t,734719 struct xt_counters counters[])735720{721721+ struct arpt_entry *iter;736722 unsigned int cpu;737723 unsigned int i;738724 unsigned int curcpu;···728754 curcpu = smp_processor_id();729755730756 i = 0;731731- ARPT_ENTRY_ITERATE(t->entries[curcpu],732732- t->size,733733- set_entry_to_counter,734734- counters,735735- &i);757757+ xt_entry_foreach(iter, t->entries[curcpu], t->size) {758758+ SET_COUNTER(counters[i], iter->counters.bcnt,759759+ iter->counters.pcnt);760760+ ++i;761761+ }736762737763 for_each_possible_cpu(cpu) {738764 if (cpu == curcpu)739765 continue;740766 i = 0;741767 xt_info_wrlock(cpu);742742- ARPT_ENTRY_ITERATE(t->entries[cpu],743743- t->size,744744- add_entry_to_counter,745745- counters,746746- &i);768768+ xt_entry_foreach(iter, t->entries[cpu], t->size) {769769+ ADD_COUNTER(counters[i], iter->counters.bcnt,770770+ iter->counters.pcnt);771771+ ++i;772772+ }747773 xt_info_wrunlock(cpu);748774 }749775 local_bh_enable();···873899static int compat_table_info(const struct xt_table_info *info,874900 struct xt_table_info *newinfo)875901{902902+ struct arpt_entry *iter;876903 void *loc_cpu_entry;904904+ int ret;877905878906 if (!newinfo || !info)879907 return -EINVAL;···884908 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));885909 newinfo->initial_entries = 0;886910 loc_cpu_entry = info->entries[raw_smp_processor_id()];887887- return ARPT_ENTRY_ITERATE(loc_cpu_entry, info->size,888888- compat_calc_entry, info, loc_cpu_entry,889889- newinfo);911911+ xt_entry_foreach(iter, loc_cpu_entry, info->size) {912912+ ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);913913+ if (ret != 0)914914+ return ret;915915+ }916916+ return 0;890917}891918#endif892919···10041025 struct xt_table_info *oldinfo;10051026 struct xt_counters *counters;10061027 void *loc_cpu_old_entry;10281028+ struct arpt_entry *iter;1007102910081030 ret = 0;10091031 counters = vmalloc_node(num_counters * sizeof(struct xt_counters),···1048106810491069 /* Decrease module usage counts and free resource */10501070 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];10511051- ARPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,10521052- NULL);10711071+ xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size)10721072+ cleanup_entry(iter);1053107310541074 xt_free_table_info(oldinfo);10551075 if (copy_to_user(counters_ptr, counters,···10751095 struct arpt_replace tmp;10761096 struct xt_table_info *newinfo;10771097 void *loc_cpu_entry;10981098+ struct arpt_entry *iter;1078109910791100 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)10801101 return -EFAULT;···10961115 goto free_newinfo;10971116 }1098111710991099- ret = translate_table(tmp.name, tmp.valid_hooks,11001100- newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,11011101- tmp.hook_entry, tmp.underflow);11181118+ ret = translate_table(newinfo, loc_cpu_entry, &tmp);11021119 if (ret != 0)11031120 goto free_newinfo;11041121···11091130 return 0;1110113111111132 free_newinfo_untrans:11121112- ARPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL);11331133+ xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)11341134+ cleanup_entry(iter);11131135 free_newinfo:11141136 xt_free_table_info(newinfo);11151137 return ret;11161116-}11171117-11181118-/* We're lazy, and add to the first CPU; overflow works its fey magic11191119- * and everything is OK. */11201120-static int11211121-add_counter_to_entry(struct arpt_entry *e,11221122- const struct xt_counters addme[],11231123- unsigned int *i)11241124-{11251125- ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);11261126-11271127- (*i)++;11281128- return 0;11291138}1130113911311140static int do_add_counters(struct net *net, const void __user *user,···11301163 const struct xt_table_info *private;11311164 int ret = 0;11321165 void *loc_cpu_entry;11661166+ struct arpt_entry *iter;11331167#ifdef CONFIG_COMPAT11341168 struct compat_xt_counters_info compat_tmp;11351169···11881220 curcpu = smp_processor_id();11891221 loc_cpu_entry = private->entries[curcpu];11901222 xt_info_wrlock(curcpu);11911191- ARPT_ENTRY_ITERATE(loc_cpu_entry,11921192- private->size,11931193- add_counter_to_entry,11941194- paddc,11951195- &i);12231223+ xt_entry_foreach(iter, loc_cpu_entry, private->size) {12241224+ ADD_COUNTER(iter->counters, paddc[i].bcnt, paddc[i].pcnt);12251225+ ++i;12261226+ }11961227 xt_info_wrunlock(curcpu);11971228 unlock_up_free:11981229 local_bh_enable();···12041237}1205123812061239#ifdef CONFIG_COMPAT12071207-static inline int12081208-compat_release_entry(struct compat_arpt_entry *e, unsigned int *i)12401240+static inline void compat_release_entry(struct compat_arpt_entry *e)12091241{12101242 struct arpt_entry_target *t;1211124312121212- if (i && (*i)-- == 0)12131213- return 1;12141214-12151244 t = compat_arpt_get_target(e);12161245 module_put(t->u.kernel.target->me);12171217- return 0;12181246}1219124712201248static inline int···12201258 const unsigned char *limit,12211259 const unsigned int *hook_entries,12221260 const unsigned int *underflows,12231223- unsigned int *i,12241261 const char *name)12251262{12261263 struct arpt_entry_target *t;···12791318 /* Clear counters and comefrom */12801319 memset(&e->counters, 0, sizeof(e->counters));12811320 e->comefrom = 0;12821282-12831283- (*i)++;12841321 return 0;1285132212861323release_target:···13221363 return ret;13231364}1324136513251325-static inline int compat_check_entry(struct arpt_entry *e, const char *name,13261326- unsigned int *i)13271327-{13281328- int ret;13291329-13301330- ret = check_target(e, name);13311331- if (ret)13321332- return ret;13331333-13341334- (*i)++;13351335- return 0;13361336-}13371337-13381366static int translate_compat_table(const char *name,13391367 unsigned int valid_hooks,13401368 struct xt_table_info **pinfo,···13341388 unsigned int i, j;13351389 struct xt_table_info *newinfo, *info;13361390 void *pos, *entry0, *entry1;13911391+ struct compat_arpt_entry *iter0;13921392+ struct arpt_entry *iter1;13371393 unsigned int size;13381338- int ret;13941394+ int ret = 0;1339139513401396 info = *pinfo;13411397 entry0 = *pentry0;···13541406 j = 0;13551407 xt_compat_lock(NFPROTO_ARP);13561408 /* Walk through entries, checking offsets. */13571357- ret = COMPAT_ARPT_ENTRY_ITERATE(entry0, total_size,13581358- check_compat_entry_size_and_hooks,13591359- info, &size, entry0,13601360- entry0 + total_size,13611361- hook_entries, underflows, &j, name);13621362- if (ret != 0)13631363- goto out_unlock;14091409+ xt_entry_foreach(iter0, entry0, total_size) {14101410+ ret = check_compat_entry_size_and_hooks(iter0, info, &size,14111411+ entry0, entry0 + total_size, hook_entries, underflows,14121412+ name);14131413+ if (ret != 0)14141414+ goto out_unlock;14151415+ ++j;14161416+ }1364141713651418 ret = -EINVAL;13661419 if (j != number) {···14001451 entry1 = newinfo->entries[raw_smp_processor_id()];14011452 pos = entry1;14021453 size = total_size;14031403- ret = COMPAT_ARPT_ENTRY_ITERATE(entry0, total_size,14041404- compat_copy_entry_from_user,14051405- &pos, &size, name, newinfo, entry1);14541454+ xt_entry_foreach(iter0, entry0, total_size) {14551455+ ret = compat_copy_entry_from_user(iter0, &pos,14561456+ &size, name, newinfo, entry1);14571457+ if (ret != 0)14581458+ break;14591459+ }14061460 xt_compat_flush_offsets(NFPROTO_ARP);14071461 xt_compat_unlock(NFPROTO_ARP);14081462 if (ret)···14161464 goto free_newinfo;1417146514181466 i = 0;14191419- ret = ARPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry,14201420- name, &i);14671467+ xt_entry_foreach(iter1, entry1, newinfo->size) {14681468+ ret = check_target(iter1, name);14691469+ if (ret != 0)14701470+ break;14711471+ ++i;14721472+ }14211473 if (ret) {14741474+ /*14751475+ * The first i matches need cleanup_entry (calls ->destroy)14761476+ * because they had called ->check already. The other j-i14771477+ * entries need only release.14781478+ */14791479+ int skip = i;14221480 j -= i;14231423- COMPAT_ARPT_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i,14241424- compat_release_entry, &j);14251425- ARPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, &i);14811481+ xt_entry_foreach(iter0, entry0, newinfo->size) {14821482+ if (skip-- > 0)14831483+ continue;14841484+ if (j-- == 0)14851485+ break;14861486+ compat_release_entry(iter0);14871487+ }14881488+ xt_entry_foreach(iter1, entry1, newinfo->size) {14891489+ if (i-- == 0)14901490+ break;14911491+ cleanup_entry(iter1);14921492+ }14261493 xt_free_table_info(newinfo);14271494 return ret;14281495 }···14591488free_newinfo:14601489 xt_free_table_info(newinfo);14611490out:14621462- COMPAT_ARPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j);14911491+ xt_entry_foreach(iter0, entry0, total_size) {14921492+ if (j-- == 0)14931493+ break;14941494+ compat_release_entry(iter0);14951495+ }14631496 return ret;14641497out_unlock:14651498 xt_compat_flush_offsets(NFPROTO_ARP);···14901515 struct compat_arpt_replace tmp;14911516 struct xt_table_info *newinfo;14921517 void *loc_cpu_entry;15181518+ struct arpt_entry *iter;1493151914941520 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)14951521 return -EFAULT;···15281552 return 0;1529155315301554 free_newinfo_untrans:15311531- ARPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL);15551555+ xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)15561556+ cleanup_entry(iter);15321557 free_newinfo:15331558 xt_free_table_info(newinfo);15341559 return ret;···15631586static int compat_copy_entry_to_user(struct arpt_entry *e, void __user **dstptr,15641587 compat_uint_t *size,15651588 struct xt_counters *counters,15661566- unsigned int *i)15891589+ unsigned int i)15671590{15681591 struct arpt_entry_target *t;15691592 struct compat_arpt_entry __user *ce;···15711594 compat_uint_t origsize;15721595 int ret;1573159615741574- ret = -EFAULT;15751597 origsize = *size;15761598 ce = (struct compat_arpt_entry __user *)*dstptr;15771577- if (copy_to_user(ce, e, sizeof(struct arpt_entry)))15781578- goto out;15791579-15801580- if (copy_to_user(&ce->counters, &counters[*i], sizeof(counters[*i])))15811581- goto out;15991599+ if (copy_to_user(ce, e, sizeof(struct arpt_entry)) != 0 ||16001600+ copy_to_user(&ce->counters, &counters[i],16011601+ sizeof(counters[i])) != 0)16021602+ return -EFAULT;1582160315831604 *dstptr += sizeof(struct compat_arpt_entry);15841605 *size -= sizeof(struct arpt_entry) - sizeof(struct compat_arpt_entry);···15861611 t = arpt_get_target(e);15871612 ret = xt_compat_target_to_user(t, dstptr, size);15881613 if (ret)15891589- goto out;15901590- ret = -EFAULT;16141614+ return ret;15911615 next_offset = e->next_offset - (origsize - *size);15921592- if (put_user(target_offset, &ce->target_offset))15931593- goto out;15941594- if (put_user(next_offset, &ce->next_offset))15951595- goto out;15961596-15971597- (*i)++;16161616+ if (put_user(target_offset, &ce->target_offset) != 0 ||16171617+ put_user(next_offset, &ce->next_offset) != 0)16181618+ return -EFAULT;15981619 return 0;15991599-out:16001600- return ret;16011620}1602162116031622static int compat_copy_entries_to_user(unsigned int total_size,···16051636 int ret = 0;16061637 void *loc_cpu_entry;16071638 unsigned int i = 0;16391639+ struct arpt_entry *iter;1608164016091641 counters = alloc_counters(table);16101642 if (IS_ERR(counters))···16151645 loc_cpu_entry = private->entries[raw_smp_processor_id()];16161646 pos = userptr;16171647 size = total_size;16181618- ret = ARPT_ENTRY_ITERATE(loc_cpu_entry, total_size,16191619- compat_copy_entry_to_user,16201620- &pos, &size, counters, &i);16481648+ xt_entry_foreach(iter, loc_cpu_entry, total_size) {16491649+ ret = compat_copy_entry_to_user(iter, &pos,16501650+ &size, counters, i++);16511651+ if (ret != 0)16521652+ break;16531653+ }16211654 vfree(counters);16221655 return ret;16231656}···17881815 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];17891816 memcpy(loc_cpu_entry, repl->entries, repl->size);1790181717911791- ret = translate_table(table->name, table->valid_hooks,17921792- newinfo, loc_cpu_entry, repl->size,17931793- repl->num_entries,17941794- repl->hook_entry,17951795- repl->underflow);17961796-18181818+ ret = translate_table(newinfo, loc_cpu_entry, repl);17971819 duprintf("arpt_register_table: translate table gives %d\n", ret);17981820 if (ret != 0)17991821 goto out_free;···18111843 struct xt_table_info *private;18121844 void *loc_cpu_entry;18131845 struct module *table_owner = table->me;18461846+ struct arpt_entry *iter;1814184718151848 private = xt_unregister_table(table);1816184918171850 /* Decrease module usage counts and free resources */18181851 loc_cpu_entry = private->entries[raw_smp_processor_id()];18191819- ARPT_ENTRY_ITERATE(loc_cpu_entry, private->size,18201820- cleanup_entry, NULL);18521852+ xt_entry_foreach(iter, loc_cpu_entry, private->size)18531853+ cleanup_entry(iter);18211854 if (private->number > private->initial_entries)18221855 module_put(table_owner);18231856 xt_free_table_info(private);
+214-222
net/ipv4/netfilter/ip_tables.c
···288288 const void *table_base;289289 const struct ipt_entry *root;290290 const char *hookname, *chainname, *comment;291291+ const struct ipt_entry *iter;291292 unsigned int rulenum = 0;292293293294 table_base = private->entries[smp_processor_id()];···297296 hookname = chainname = hooknames[hook];298297 comment = comments[NF_IP_TRACE_COMMENT_RULE];299298300300- IPT_ENTRY_ITERATE(root,301301- private->size - private->hook_entry[hook],302302- get_chainname_rulenum,303303- e, hookname, &chainname, &comment, &rulenum);299299+ xt_entry_foreach(iter, root, private->size - private->hook_entry[hook])300300+ if (get_chainname_rulenum(iter, e, hookname,301301+ &chainname, &comment, &rulenum) != 0)302302+ break;304303305304 nf_log_packet(AF_INET, hook, skb, in, out, &trace_loginfo,306305 "TRACE: %s:%s:%s:%u ",···366365367366 do {368367 const struct ipt_entry_target *t;368368+ const struct xt_entry_match *ematch;369369370370 IP_NF_ASSERT(e);371371 IP_NF_ASSERT(back);372372 if (!ip_packet_match(ip, indev, outdev,373373- &e->ip, mtpar.fragoff) ||374374- IPT_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0) {373373+ &e->ip, mtpar.fragoff)) {374374+ no_match:375375 e = ipt_next_entry(e);376376 continue;377377 }378378+379379+ xt_ematch_foreach(ematch, e)380380+ if (do_match(ematch, skb, &mtpar) != 0)381381+ goto no_match;378382379383 ADD_COUNTER(e->counters, ntohs(ip->tot_len), 1);380384···572566 return 1;573567}574568575575-static int576576-cleanup_match(struct ipt_entry_match *m, struct net *net, unsigned int *i)569569+static void cleanup_match(struct ipt_entry_match *m, struct net *net)577570{578571 struct xt_mtdtor_param par;579579-580580- if (i && (*i)-- == 0)581581- return 1;582572583573 par.net = net;584574 par.match = m->u.kernel.match;···583581 if (par.match->destroy != NULL)584582 par.match->destroy(&par);585583 module_put(par.match->me);586586- return 0;587584}588585589586static int···607606}608607609608static int610610-check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,611611- unsigned int *i)609609+check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par)612610{613611 const struct ipt_ip *ip = par->entryinfo;614612 int ret;···622622 par.match->name);623623 return ret;624624 }625625- ++*i;626625 return 0;627626}628627629628static int630630-find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par,631631- unsigned int *i)629629+find_check_match(struct ipt_entry_match *m, struct xt_mtchk_param *par)632630{633631 struct xt_match *match;634632 int ret;···640642 }641643 m->u.kernel.match = match;642644643643- ret = check_match(m, par, i);645645+ ret = check_match(m, par);644646 if (ret)645647 goto err;646648···676678677679static int678680find_check_entry(struct ipt_entry *e, struct net *net, const char *name,679679- unsigned int size, unsigned int *i)681681+ unsigned int size)680682{681683 struct ipt_entry_target *t;682684 struct xt_target *target;683685 int ret;684686 unsigned int j;685687 struct xt_mtchk_param mtpar;688688+ struct xt_entry_match *ematch;686689687690 ret = check_entry(e, name);688691 if (ret)···695696 mtpar.entryinfo = &e->ip;696697 mtpar.hook_mask = e->comefrom;697698 mtpar.family = NFPROTO_IPV4;698698- ret = IPT_MATCH_ITERATE(e, find_check_match, &mtpar, &j);699699- if (ret != 0)700700- goto cleanup_matches;699699+ xt_ematch_foreach(ematch, e) {700700+ ret = find_check_match(ematch, &mtpar);701701+ if (ret != 0)702702+ goto cleanup_matches;703703+ ++j;704704+ }701705702706 t = ipt_get_target(e);703707 target = try_then_request_module(xt_find_target(AF_INET,···717715 ret = check_target(e, net, name);718716 if (ret)719717 goto err;720720-721721- (*i)++;722718 return 0;723719 err:724720 module_put(t->u.kernel.target->me);725721 cleanup_matches:726726- IPT_MATCH_ITERATE(e, cleanup_match, net, &j);722722+ xt_ematch_foreach(ematch, e) {723723+ if (j-- == 0)724724+ break;725725+ cleanup_match(ematch, net);726726+ }727727 return ret;728728}729729···751747 const unsigned char *limit,752748 const unsigned int *hook_entries,753749 const unsigned int *underflows,754754- unsigned int valid_hooks,755755- unsigned int *i)750750+ unsigned int valid_hooks)756751{757752 unsigned int h;758753···788785 /* Clear counters and comefrom */789786 e->counters = ((struct xt_counters) { 0, 0 });790787 e->comefrom = 0;791791-792792- (*i)++;793788 return 0;794789}795790796796-static int797797-cleanup_entry(struct ipt_entry *e, struct net *net, unsigned int *i)791791+static void792792+cleanup_entry(struct ipt_entry *e, struct net *net)798793{799794 struct xt_tgdtor_param par;800795 struct ipt_entry_target *t;801801-802802- if (i && (*i)-- == 0)803803- return 1;796796+ struct xt_entry_match *ematch;804797805798 /* Cleanup all matches */806806- IPT_MATCH_ITERATE(e, cleanup_match, net, NULL);799799+ xt_ematch_foreach(ematch, e)800800+ cleanup_match(ematch, net);807801 t = ipt_get_target(e);808802809803 par.net = net;···810810 if (par.target->destroy != NULL)811811 par.target->destroy(&par);812812 module_put(par.target->me);813813- return 0;814813}815814816815/* Checks and translates the user-supplied table segment (held in817816 newinfo) */818817static int819819-translate_table(struct net *net,820820- const char *name,821821- unsigned int valid_hooks,822822- struct xt_table_info *newinfo,823823- void *entry0,824824- unsigned int size,825825- unsigned int number,826826- const unsigned int *hook_entries,827827- const unsigned int *underflows)818818+translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0,819819+ const struct ipt_replace *repl)828820{821821+ struct ipt_entry *iter;829822 unsigned int i;830830- int ret;823823+ int ret = 0;831824832832- newinfo->size = size;833833- newinfo->number = number;825825+ newinfo->size = repl->size;826826+ newinfo->number = repl->num_entries;834827835828 /* Init all hooks to impossible value. */836829 for (i = 0; i < NF_INET_NUMHOOKS; i++) {···834841 duprintf("translate_table: size %u\n", newinfo->size);835842 i = 0;836843 /* Walk through entries, checking offsets. */837837- ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,838838- check_entry_size_and_hooks,839839- newinfo,840840- entry0,841841- entry0 + size,842842- hook_entries, underflows, valid_hooks, &i);843843- if (ret != 0)844844- return ret;844844+ xt_entry_foreach(iter, entry0, newinfo->size) {845845+ ret = check_entry_size_and_hooks(iter, newinfo, entry0,846846+ entry0 + repl->size, repl->hook_entry, repl->underflow,847847+ repl->valid_hooks);848848+ if (ret != 0)849849+ return ret;850850+ ++i;851851+ }845852846846- if (i != number) {853853+ if (i != repl->num_entries) {847854 duprintf("translate_table: %u not %u entries\n",848848- i, number);855855+ i, repl->num_entries);849856 return -EINVAL;850857 }851858852859 /* Check hooks all assigned */853860 for (i = 0; i < NF_INET_NUMHOOKS; i++) {854861 /* Only hooks which are valid */855855- if (!(valid_hooks & (1 << i)))862862+ if (!(repl->valid_hooks & (1 << i)))856863 continue;857864 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {858865 duprintf("Invalid hook entry %u %u\n",859859- i, hook_entries[i]);866866+ i, repl->hook_entry[i]);860867 return -EINVAL;861868 }862869 if (newinfo->underflow[i] == 0xFFFFFFFF) {863870 duprintf("Invalid underflow %u %u\n",864864- i, underflows[i]);871871+ i, repl->underflow[i]);865872 return -EINVAL;866873 }867874 }868875869869- if (!mark_source_chains(newinfo, valid_hooks, entry0))876876+ if (!mark_source_chains(newinfo, repl->valid_hooks, entry0))870877 return -ELOOP;871878872879 /* Finally, each sanity check must pass */873880 i = 0;874874- ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,875875- find_check_entry, net, name, size, &i);881881+ xt_entry_foreach(iter, entry0, newinfo->size) {882882+ ret = find_check_entry(iter, net, repl->name, repl->size);883883+ if (ret != 0)884884+ break;885885+ ++i;886886+ }876887877888 if (ret != 0) {878878- IPT_ENTRY_ITERATE(entry0, newinfo->size,879879- cleanup_entry, net, &i);889889+ xt_entry_foreach(iter, entry0, newinfo->size) {890890+ if (i-- == 0)891891+ break;892892+ cleanup_entry(iter, net);893893+ }880894 return ret;881895 }882896···896896 return ret;897897}898898899899-/* Gets counters. */900900-static inline int901901-add_entry_to_counter(const struct ipt_entry *e,902902- struct xt_counters total[],903903- unsigned int *i)904904-{905905- ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);906906-907907- (*i)++;908908- return 0;909909-}910910-911911-static inline int912912-set_entry_to_counter(const struct ipt_entry *e,913913- struct ipt_counters total[],914914- unsigned int *i)915915-{916916- SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);917917-918918- (*i)++;919919- return 0;920920-}921921-922899static void923900get_counters(const struct xt_table_info *t,924901 struct xt_counters counters[])925902{903903+ struct ipt_entry *iter;926904 unsigned int cpu;927905 unsigned int i;928906 unsigned int curcpu;···916938 curcpu = smp_processor_id();917939918940 i = 0;919919- IPT_ENTRY_ITERATE(t->entries[curcpu],920920- t->size,921921- set_entry_to_counter,922922- counters,923923- &i);941941+ xt_entry_foreach(iter, t->entries[curcpu], t->size) {942942+ SET_COUNTER(counters[i], iter->counters.bcnt,943943+ iter->counters.pcnt);944944+ ++i;945945+ }924946925947 for_each_possible_cpu(cpu) {926948 if (cpu == curcpu)927949 continue;928950 i = 0;929951 xt_info_wrlock(cpu);930930- IPT_ENTRY_ITERATE(t->entries[cpu],931931- t->size,932932- add_entry_to_counter,933933- counters,934934- &i);952952+ xt_entry_foreach(iter, t->entries[cpu], t->size) {953953+ ADD_COUNTER(counters[i], iter->counters.bcnt,954954+ iter->counters.pcnt);955955+ ++i; /* macro does multi eval of i */956956+ }935957 xt_info_wrunlock(cpu);936958 }937959 local_bh_enable();···10501072 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;10511073}1052107410531053-static inline int10541054-compat_calc_match(const struct ipt_entry_match *m, int *size)10551055-{10561056- *size += xt_compat_match_offset(m->u.kernel.match);10571057- return 0;10581058-}10591059-10601075static int compat_calc_entry(const struct ipt_entry *e,10611076 const struct xt_table_info *info,10621077 const void *base, struct xt_table_info *newinfo)10631078{10791079+ const struct xt_entry_match *ematch;10641080 const struct ipt_entry_target *t;10651081 unsigned int entry_offset;10661082 int off, i, ret;1067108310681084 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);10691085 entry_offset = (void *)e - base;10701070- IPT_MATCH_ITERATE(e, compat_calc_match, &off);10861086+ xt_ematch_foreach(ematch, e)10871087+ off += xt_compat_match_offset(ematch->u.kernel.match);10711088 t = ipt_get_target_c(e);10721089 off += xt_compat_target_offset(t->u.kernel.target);10731090 newinfo->size -= off;···10841111static int compat_table_info(const struct xt_table_info *info,10851112 struct xt_table_info *newinfo)10861113{11141114+ struct ipt_entry *iter;10871115 void *loc_cpu_entry;11161116+ int ret;1088111710891118 if (!newinfo || !info)10901119 return -EINVAL;···10951120 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));10961121 newinfo->initial_entries = 0;10971122 loc_cpu_entry = info->entries[raw_smp_processor_id()];10981098- return IPT_ENTRY_ITERATE(loc_cpu_entry, info->size,10991099- compat_calc_entry, info, loc_cpu_entry,11001100- newinfo);11231123+ xt_entry_foreach(iter, loc_cpu_entry, info->size) {11241124+ ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);11251125+ if (ret != 0)11261126+ return ret;11271127+ }11281128+ return 0;11011129}11021130#endif11031131···12141236 struct xt_table_info *oldinfo;12151237 struct xt_counters *counters;12161238 void *loc_cpu_old_entry;12391239+ struct ipt_entry *iter;1217124012181241 ret = 0;12191242 counters = vmalloc(num_counters * sizeof(struct xt_counters));···1257127812581279 /* Decrease module usage counts and free resource */12591280 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];12601260- IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,12611261- net, NULL);12811281+ xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size)12821282+ cleanup_entry(iter, net);12831283+12621284 xt_free_table_info(oldinfo);12631285 if (copy_to_user(counters_ptr, counters,12641286 sizeof(struct xt_counters) * num_counters) != 0)···12841304 struct ipt_replace tmp;12851305 struct xt_table_info *newinfo;12861306 void *loc_cpu_entry;13071307+ struct ipt_entry *iter;1287130812881309 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)12891310 return -EFAULT;···13051324 goto free_newinfo;13061325 }1307132613081308- ret = translate_table(net, tmp.name, tmp.valid_hooks,13091309- newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,13101310- tmp.hook_entry, tmp.underflow);13271327+ ret = translate_table(net, newinfo, loc_cpu_entry, &tmp);13111328 if (ret != 0)13121329 goto free_newinfo;13131330···13181339 return 0;1319134013201341 free_newinfo_untrans:13211321- IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, net, NULL);13421342+ xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)13431343+ cleanup_entry(iter, net);13221344 free_newinfo:13231345 xt_free_table_info(newinfo);13241346 return ret;13251325-}13261326-13271327-/* We're lazy, and add to the first CPU; overflow works its fey magic13281328- * and everything is OK. */13291329-static int13301330-add_counter_to_entry(struct ipt_entry *e,13311331- const struct xt_counters addme[],13321332- unsigned int *i)13331333-{13341334- ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);13351335-13361336- (*i)++;13371337- return 0;13381347}1339134813401349static int···13401373 const struct xt_table_info *private;13411374 int ret = 0;13421375 void *loc_cpu_entry;13761376+ struct ipt_entry *iter;13431377#ifdef CONFIG_COMPAT13441378 struct compat_xt_counters_info compat_tmp;13451379···13981430 curcpu = smp_processor_id();13991431 loc_cpu_entry = private->entries[curcpu];14001432 xt_info_wrlock(curcpu);14011401- IPT_ENTRY_ITERATE(loc_cpu_entry,14021402- private->size,14031403- add_counter_to_entry,14041404- paddc,14051405- &i);14331433+ xt_entry_foreach(iter, loc_cpu_entry, private->size) {14341434+ ADD_COUNTER(iter->counters, paddc[i].bcnt, paddc[i].pcnt);14351435+ ++i;14361436+ }14061437 xt_info_wrunlock(curcpu);14071438 unlock_up_free:14081439 local_bh_enable();···14291462static int14301463compat_copy_entry_to_user(struct ipt_entry *e, void __user **dstptr,14311464 unsigned int *size, struct xt_counters *counters,14321432- unsigned int *i)14651465+ unsigned int i)14331466{14341467 struct ipt_entry_target *t;14351468 struct compat_ipt_entry __user *ce;14361469 u_int16_t target_offset, next_offset;14371470 compat_uint_t origsize;14381438- int ret;14711471+ const struct xt_entry_match *ematch;14721472+ int ret = 0;1439147314401440- ret = -EFAULT;14411474 origsize = *size;14421475 ce = (struct compat_ipt_entry __user *)*dstptr;14431443- if (copy_to_user(ce, e, sizeof(struct ipt_entry)))14441444- goto out;14451445-14461446- if (copy_to_user(&ce->counters, &counters[*i], sizeof(counters[*i])))14471447- goto out;14761476+ if (copy_to_user(ce, e, sizeof(struct ipt_entry)) != 0 ||14771477+ copy_to_user(&ce->counters, &counters[i],14781478+ sizeof(counters[i])) != 0)14791479+ return -EFAULT;1448148014491481 *dstptr += sizeof(struct compat_ipt_entry);14501482 *size -= sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);1451148314521452- ret = IPT_MATCH_ITERATE(e, xt_compat_match_to_user, dstptr, size);14841484+ xt_ematch_foreach(ematch, e) {14851485+ ret = xt_compat_match_to_user(ematch, dstptr, size);14861486+ if (ret != 0)14871487+ return ret;14881488+ }14531489 target_offset = e->target_offset - (origsize - *size);14541454- if (ret)14551455- goto out;14561490 t = ipt_get_target(e);14571491 ret = xt_compat_target_to_user(t, dstptr, size);14581492 if (ret)14591459- goto out;14601460- ret = -EFAULT;14931493+ return ret;14611494 next_offset = e->next_offset - (origsize - *size);14621462- if (put_user(target_offset, &ce->target_offset))14631463- goto out;14641464- if (put_user(next_offset, &ce->next_offset))14651465- goto out;14661466-14671467- (*i)++;14951495+ if (put_user(target_offset, &ce->target_offset) != 0 ||14961496+ put_user(next_offset, &ce->next_offset) != 0)14971497+ return -EFAULT;14681498 return 0;14691469-out:14701470- return ret;14711499}1472150014731501static int···14701508 const char *name,14711509 const struct ipt_ip *ip,14721510 unsigned int hookmask,14731473- int *size, unsigned int *i)15111511+ int *size)14741512{14751513 struct xt_match *match;14761514···14841522 }14851523 m->u.kernel.match = match;14861524 *size += xt_compat_match_offset(match);14871487-14881488- (*i)++;14891525 return 0;14901526}1491152714921492-static int14931493-compat_release_match(struct ipt_entry_match *m, unsigned int *i)14941494-{14951495- if (i && (*i)-- == 0)14961496- return 1;14971497-14981498- module_put(m->u.kernel.match->me);14991499- return 0;15001500-}15011501-15021502-static int15031503-compat_release_entry(struct compat_ipt_entry *e, unsigned int *i)15281528+static void compat_release_entry(struct compat_ipt_entry *e)15041529{15051530 struct ipt_entry_target *t;15061506-15071507- if (i && (*i)-- == 0)15081508- return 1;15311531+ struct xt_entry_match *ematch;1509153215101533 /* Cleanup all matches */15111511- COMPAT_IPT_MATCH_ITERATE(e, compat_release_match, NULL);15341534+ xt_ematch_foreach(ematch, e)15351535+ module_put(ematch->u.kernel.match->me);15121536 t = compat_ipt_get_target(e);15131537 module_put(t->u.kernel.target->me);15141514- return 0;15151538}1516153915171540static int···15071560 const unsigned char *limit,15081561 const unsigned int *hook_entries,15091562 const unsigned int *underflows,15101510- unsigned int *i,15111563 const char *name)15121564{15651565+ struct xt_entry_match *ematch;15131566 struct ipt_entry_target *t;15141567 struct xt_target *target;15151568 unsigned int entry_offset;···15381591 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);15391592 entry_offset = (void *)e - (void *)base;15401593 j = 0;15411541- ret = COMPAT_IPT_MATCH_ITERATE(e, compat_find_calc_match, name,15421542- &e->ip, e->comefrom, &off, &j);15431543- if (ret != 0)15441544- goto release_matches;15941594+ xt_ematch_foreach(ematch, e) {15951595+ ret = compat_find_calc_match(ematch, name,15961596+ &e->ip, e->comefrom, &off);15971597+ if (ret != 0)15981598+ goto release_matches;15991599+ ++j;16001600+ }1545160115461602 t = compat_ipt_get_target(e);15471603 target = try_then_request_module(xt_find_target(AF_INET,···15761626 /* Clear counters and comefrom */15771627 memset(&e->counters, 0, sizeof(e->counters));15781628 e->comefrom = 0;15791579-15801580- (*i)++;15811629 return 0;1582163015831631out:15841632 module_put(t->u.kernel.target->me);15851633release_matches:15861586- IPT_MATCH_ITERATE(e, compat_release_match, &j);16341634+ xt_ematch_foreach(ematch, e) {16351635+ if (j-- == 0)16361636+ break;16371637+ module_put(ematch->u.kernel.match->me);16381638+ }15871639 return ret;15881640}15891641···15991647 struct ipt_entry *de;16001648 unsigned int origsize;16011649 int ret, h;16501650+ struct xt_entry_match *ematch;1602165116031652 ret = 0;16041653 origsize = *size;···16101657 *dstptr += sizeof(struct ipt_entry);16111658 *size += sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);1612165916131613- ret = COMPAT_IPT_MATCH_ITERATE(e, xt_compat_match_from_user,16141614- dstptr, size);16151615- if (ret)16161616- return ret;16601660+ xt_ematch_foreach(ematch, e) {16611661+ ret = xt_compat_match_from_user(ematch, dstptr, size);16621662+ if (ret != 0)16631663+ return ret;16641664+ }16171665 de->target_offset = e->target_offset - (origsize - *size);16181666 t = compat_ipt_get_target(e);16191667 target = t->u.kernel.target;···16311677}1632167816331679static int16341634-compat_check_entry(struct ipt_entry *e, struct net *net, const char *name,16351635- unsigned int *i)16801680+compat_check_entry(struct ipt_entry *e, struct net *net, const char *name)16361681{16821682+ struct xt_entry_match *ematch;16371683 struct xt_mtchk_param mtpar;16381684 unsigned int j;16391639- int ret;16851685+ int ret = 0;1640168616411687 j = 0;16421688 mtpar.net = net;···16441690 mtpar.entryinfo = &e->ip;16451691 mtpar.hook_mask = e->comefrom;16461692 mtpar.family = NFPROTO_IPV4;16471647- ret = IPT_MATCH_ITERATE(e, check_match, &mtpar, &j);16481648- if (ret)16491649- goto cleanup_matches;16931693+ xt_ematch_foreach(ematch, e) {16941694+ ret = check_match(ematch, &mtpar);16951695+ if (ret != 0)16961696+ goto cleanup_matches;16971697+ ++j;16981698+ }1650169916511700 ret = check_target(e, net, name);16521701 if (ret)16531702 goto cleanup_matches;16541654-16551655- (*i)++;16561703 return 0;1657170416581705 cleanup_matches:16591659- IPT_MATCH_ITERATE(e, cleanup_match, net, &j);17061706+ xt_ematch_foreach(ematch, e) {17071707+ if (j-- == 0)17081708+ break;17091709+ cleanup_match(ematch, net);17101710+ }16601711 return ret;16611712}16621713···16791720 unsigned int i, j;16801721 struct xt_table_info *newinfo, *info;16811722 void *pos, *entry0, *entry1;17231723+ struct compat_ipt_entry *iter0;17241724+ struct ipt_entry *iter1;16821725 unsigned int size;16831726 int ret;16841727···16991738 j = 0;17001739 xt_compat_lock(AF_INET);17011740 /* Walk through entries, checking offsets. */17021702- ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,17031703- check_compat_entry_size_and_hooks,17041704- info, &size, entry0,17051705- entry0 + total_size,17061706- hook_entries, underflows, &j, name);17071707- if (ret != 0)17081708- goto out_unlock;17411741+ xt_entry_foreach(iter0, entry0, total_size) {17421742+ ret = check_compat_entry_size_and_hooks(iter0, info, &size,17431743+ entry0, entry0 + total_size, hook_entries, underflows,17441744+ name);17451745+ if (ret != 0)17461746+ goto out_unlock;17471747+ ++j;17481748+ }1709174917101750 ret = -EINVAL;17111751 if (j != number) {···17451783 entry1 = newinfo->entries[raw_smp_processor_id()];17461784 pos = entry1;17471785 size = total_size;17481748- ret = COMPAT_IPT_ENTRY_ITERATE(entry0, total_size,17491749- compat_copy_entry_from_user,17501750- &pos, &size, name, newinfo, entry1);17861786+ xt_entry_foreach(iter0, entry0, total_size) {17871787+ ret = compat_copy_entry_from_user(iter0, &pos,17881788+ &size, name, newinfo, entry1);17891789+ if (ret != 0)17901790+ break;17911791+ }17511792 xt_compat_flush_offsets(AF_INET);17521793 xt_compat_unlock(AF_INET);17531794 if (ret)···17611796 goto free_newinfo;1762179717631798 i = 0;17641764- ret = IPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry,17651765- net, name, &i);17991799+ xt_entry_foreach(iter1, entry1, newinfo->size) {18001800+ ret = compat_check_entry(iter1, net, name);18011801+ if (ret != 0)18021802+ break;18031803+ ++i;18041804+ }17661805 if (ret) {18061806+ /*18071807+ * The first i matches need cleanup_entry (calls ->destroy)18081808+ * because they had called ->check already. The other j-i18091809+ * entries need only release.18101810+ */18111811+ int skip = i;17671812 j -= i;17681768- COMPAT_IPT_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i,17691769- compat_release_entry, &j);17701770- IPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, net, &i);18131813+ xt_entry_foreach(iter0, entry0, newinfo->size) {18141814+ if (skip-- > 0)18151815+ continue;18161816+ if (j-- == 0)18171817+ break;18181818+ compat_release_entry(iter0);18191819+ }18201820+ xt_entry_foreach(iter1, entry1, newinfo->size) {18211821+ if (i-- == 0)18221822+ break;18231823+ cleanup_entry(iter1, net);18241824+ }17711825 xt_free_table_info(newinfo);17721826 return ret;17731827 }···18041820free_newinfo:18051821 xt_free_table_info(newinfo);18061822out:18071807- COMPAT_IPT_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j);18231823+ xt_entry_foreach(iter0, entry0, total_size) {18241824+ if (j-- == 0)18251825+ break;18261826+ compat_release_entry(iter0);18271827+ }18081828 return ret;18091829out_unlock:18101830 xt_compat_flush_offsets(AF_INET);···18231835 struct compat_ipt_replace tmp;18241836 struct xt_table_info *newinfo;18251837 void *loc_cpu_entry;18381838+ struct ipt_entry *iter;1826183918271840 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)18281841 return -EFAULT;···18621873 return 0;1863187418641875 free_newinfo_untrans:18651865- IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, net, NULL);18761876+ xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)18771877+ cleanup_entry(iter, net);18661878 free_newinfo:18671879 xt_free_table_info(newinfo);18681880 return ret;···19121922 int ret = 0;19131923 const void *loc_cpu_entry;19141924 unsigned int i = 0;19251925+ struct ipt_entry *iter;1915192619161927 counters = alloc_counters(table);19171928 if (IS_ERR(counters))···19251934 loc_cpu_entry = private->entries[raw_smp_processor_id()];19261935 pos = userptr;19271936 size = total_size;19281928- ret = IPT_ENTRY_ITERATE(loc_cpu_entry, total_size,19291929- compat_copy_entry_to_user,19301930- &pos, &size, counters, &i);19371937+ xt_entry_foreach(iter, loc_cpu_entry, total_size) {19381938+ ret = compat_copy_entry_to_user(iter, &pos,19391939+ &size, counters, i++);19401940+ if (ret != 0)19411941+ break;19421942+ }1931194319321944 vfree(counters);19331945 return ret;···21042110 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];21052111 memcpy(loc_cpu_entry, repl->entries, repl->size);2106211221072107- ret = translate_table(net, table->name, table->valid_hooks,21082108- newinfo, loc_cpu_entry, repl->size,21092109- repl->num_entries,21102110- repl->hook_entry,21112111- repl->underflow);21132113+ ret = translate_table(net, newinfo, loc_cpu_entry, repl);21122114 if (ret != 0)21132115 goto out_free;21142116···21272137 struct xt_table_info *private;21282138 void *loc_cpu_entry;21292139 struct module *table_owner = table->me;21402140+ struct ipt_entry *iter;2130214121312142 private = xt_unregister_table(table);2132214321332144 /* Decrease module usage counts and free resources */21342145 loc_cpu_entry = private->entries[raw_smp_processor_id()];21352135- IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, net, NULL);21462146+ xt_entry_foreach(iter, loc_cpu_entry, private->size)21472147+ cleanup_entry(iter, net);21362148 if (private->number > private->initial_entries)21372149 module_put(table_owner);21382150 xt_free_table_info(private);
+214-222
net/ipv6/netfilter/ip6_tables.c
···318318 const void *table_base;319319 const struct ip6t_entry *root;320320 const char *hookname, *chainname, *comment;321321+ const struct ip6t_entry *iter;321322 unsigned int rulenum = 0;322323323324 table_base = private->entries[smp_processor_id()];···327326 hookname = chainname = hooknames[hook];328327 comment = comments[NF_IP6_TRACE_COMMENT_RULE];329328330330- IP6T_ENTRY_ITERATE(root,331331- private->size - private->hook_entry[hook],332332- get_chainname_rulenum,333333- e, hookname, &chainname, &comment, &rulenum);329329+ xt_entry_foreach(iter, root, private->size - private->hook_entry[hook])330330+ if (get_chainname_rulenum(iter, e, hookname,331331+ &chainname, &comment, &rulenum) != 0)332332+ break;334333335334 nf_log_packet(AF_INET6, hook, skb, in, out, &trace_loginfo,336335 "TRACE: %s:%s:%s:%u ",···393392394393 do {395394 const struct ip6t_entry_target *t;395395+ const struct xt_entry_match *ematch;396396397397 IP_NF_ASSERT(e);398398 IP_NF_ASSERT(back);399399 if (!ip6_packet_match(skb, indev, outdev, &e->ipv6,400400- &mtpar.thoff, &mtpar.fragoff, &hotdrop) ||401401- IP6T_MATCH_ITERATE(e, do_match, skb, &mtpar) != 0) {400400+ &mtpar.thoff, &mtpar.fragoff, &hotdrop)) {401401+ no_match:402402 e = ip6t_next_entry(e);403403 continue;404404 }405405+406406+ xt_ematch_foreach(ematch, e)407407+ if (do_match(ematch, skb, &mtpar) != 0)408408+ goto no_match;405409406410 ADD_COUNTER(e->counters,407411 ntohs(ipv6_hdr(skb)->payload_len) +···603597 return 1;604598}605599606606-static int607607-cleanup_match(struct ip6t_entry_match *m, struct net *net, unsigned int *i)600600+static void cleanup_match(struct ip6t_entry_match *m, struct net *net)608601{609602 struct xt_mtdtor_param par;610610-611611- if (i && (*i)-- == 0)612612- return 1;613603614604 par.net = net;615605 par.match = m->u.kernel.match;···614612 if (par.match->destroy != NULL)615613 par.match->destroy(&par);616614 module_put(par.match->me);617617- return 0;618615}619616620617static int···637636 return 0;638637}639638640640-static int check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par,641641- unsigned int *i)639639+static int check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par)642640{643641 const struct ip6t_ip6 *ipv6 = par->entryinfo;644642 int ret;···652652 par.match->name);653653 return ret;654654 }655655- ++*i;656655 return 0;657656}658657659658static int660660-find_check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par,661661- unsigned int *i)659659+find_check_match(struct ip6t_entry_match *m, struct xt_mtchk_param *par)662660{663661 struct xt_match *match;664662 int ret;···670672 }671673 m->u.kernel.match = match;672674673673- ret = check_match(m, par, i);675675+ ret = check_match(m, par);674676 if (ret)675677 goto err;676678···707709708710static int709711find_check_entry(struct ip6t_entry *e, struct net *net, const char *name,710710- unsigned int size, unsigned int *i)712712+ unsigned int size)711713{712714 struct ip6t_entry_target *t;713715 struct xt_target *target;714716 int ret;715717 unsigned int j;716718 struct xt_mtchk_param mtpar;719719+ struct xt_entry_match *ematch;717720718721 ret = check_entry(e, name);719722 if (ret)···726727 mtpar.entryinfo = &e->ipv6;727728 mtpar.hook_mask = e->comefrom;728729 mtpar.family = NFPROTO_IPV6;729729- ret = IP6T_MATCH_ITERATE(e, find_check_match, &mtpar, &j);730730- if (ret != 0)731731- goto cleanup_matches;730730+ xt_ematch_foreach(ematch, e) {731731+ ret = find_check_match(ematch, &mtpar);732732+ if (ret != 0)733733+ goto cleanup_matches;734734+ ++j;735735+ }732736733737 t = ip6t_get_target(e);734738 target = try_then_request_module(xt_find_target(AF_INET6,···748746 ret = check_target(e, net, name);749747 if (ret)750748 goto err;751751-752752- (*i)++;753749 return 0;754750 err:755751 module_put(t->u.kernel.target->me);756752 cleanup_matches:757757- IP6T_MATCH_ITERATE(e, cleanup_match, net, &j);753753+ xt_ematch_foreach(ematch, e) {754754+ if (j-- == 0)755755+ break;756756+ cleanup_match(ematch, net);757757+ }758758 return ret;759759}760760···782778 const unsigned char *limit,783779 const unsigned int *hook_entries,784780 const unsigned int *underflows,785785- unsigned int valid_hooks,786786- unsigned int *i)781781+ unsigned int valid_hooks)787782{788783 unsigned int h;789784···819816 /* Clear counters and comefrom */820817 e->counters = ((struct xt_counters) { 0, 0 });821818 e->comefrom = 0;822822-823823- (*i)++;824819 return 0;825820}826821827827-static int828828-cleanup_entry(struct ip6t_entry *e, struct net *net, unsigned int *i)822822+static void cleanup_entry(struct ip6t_entry *e, struct net *net)829823{830824 struct xt_tgdtor_param par;831825 struct ip6t_entry_target *t;832832-833833- if (i && (*i)-- == 0)834834- return 1;826826+ struct xt_entry_match *ematch;835827836828 /* Cleanup all matches */837837- IP6T_MATCH_ITERATE(e, cleanup_match, net, NULL);829829+ xt_ematch_foreach(ematch, e)830830+ cleanup_match(ematch, net);838831 t = ip6t_get_target(e);839832840833 par.net = net;···840841 if (par.target->destroy != NULL)841842 par.target->destroy(&par);842843 module_put(par.target->me);843843- return 0;844844}845845846846/* Checks and translates the user-supplied table segment (held in847847 newinfo) */848848static int849849-translate_table(struct net *net,850850- const char *name,851851- unsigned int valid_hooks,852852- struct xt_table_info *newinfo,853853- void *entry0,854854- unsigned int size,855855- unsigned int number,856856- const unsigned int *hook_entries,857857- const unsigned int *underflows)849849+translate_table(struct net *net, struct xt_table_info *newinfo, void *entry0,850850+ const struct ip6t_replace *repl)858851{852852+ struct ip6t_entry *iter;859853 unsigned int i;860860- int ret;854854+ int ret = 0;861855862862- newinfo->size = size;863863- newinfo->number = number;856856+ newinfo->size = repl->size;857857+ newinfo->number = repl->num_entries;864858865859 /* Init all hooks to impossible value. */866860 for (i = 0; i < NF_INET_NUMHOOKS; i++) {···864872 duprintf("translate_table: size %u\n", newinfo->size);865873 i = 0;866874 /* Walk through entries, checking offsets. */867867- ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size,868868- check_entry_size_and_hooks,869869- newinfo,870870- entry0,871871- entry0 + size,872872- hook_entries, underflows, valid_hooks, &i);873873- if (ret != 0)874874- return ret;875875+ xt_entry_foreach(iter, entry0, newinfo->size) {876876+ ret = check_entry_size_and_hooks(iter, newinfo, entry0,877877+ entry0 + repl->size, repl->hook_entry, repl->underflow,878878+ repl->valid_hooks);879879+ if (ret != 0)880880+ return ret;881881+ ++i;882882+ }875883876876- if (i != number) {884884+ if (i != repl->num_entries) {877885 duprintf("translate_table: %u not %u entries\n",878878- i, number);886886+ i, repl->num_entries);879887 return -EINVAL;880888 }881889882890 /* Check hooks all assigned */883891 for (i = 0; i < NF_INET_NUMHOOKS; i++) {884892 /* Only hooks which are valid */885885- if (!(valid_hooks & (1 << i)))893893+ if (!(repl->valid_hooks & (1 << i)))886894 continue;887895 if (newinfo->hook_entry[i] == 0xFFFFFFFF) {888896 duprintf("Invalid hook entry %u %u\n",889889- i, hook_entries[i]);897897+ i, repl->hook_entry[i]);890898 return -EINVAL;891899 }892900 if (newinfo->underflow[i] == 0xFFFFFFFF) {893901 duprintf("Invalid underflow %u %u\n",894894- i, underflows[i]);902902+ i, repl->underflow[i]);895903 return -EINVAL;896904 }897905 }898906899899- if (!mark_source_chains(newinfo, valid_hooks, entry0))907907+ if (!mark_source_chains(newinfo, repl->valid_hooks, entry0))900908 return -ELOOP;901909902910 /* Finally, each sanity check must pass */903911 i = 0;904904- ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size,905905- find_check_entry, net, name, size, &i);912912+ xt_entry_foreach(iter, entry0, newinfo->size) {913913+ ret = find_check_entry(iter, net, repl->name, repl->size);914914+ if (ret != 0)915915+ break;916916+ ++i;917917+ }906918907919 if (ret != 0) {908908- IP6T_ENTRY_ITERATE(entry0, newinfo->size,909909- cleanup_entry, net, &i);920920+ xt_entry_foreach(iter, entry0, newinfo->size) {921921+ if (i-- == 0)922922+ break;923923+ cleanup_entry(iter, net);924924+ }910925 return ret;911926 }912927···926927 return ret;927928}928929929929-/* Gets counters. */930930-static inline int931931-add_entry_to_counter(const struct ip6t_entry *e,932932- struct xt_counters total[],933933- unsigned int *i)934934-{935935- ADD_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);936936-937937- (*i)++;938938- return 0;939939-}940940-941941-static inline int942942-set_entry_to_counter(const struct ip6t_entry *e,943943- struct ip6t_counters total[],944944- unsigned int *i)945945-{946946- SET_COUNTER(total[*i], e->counters.bcnt, e->counters.pcnt);947947-948948- (*i)++;949949- return 0;950950-}951951-952930static void953931get_counters(const struct xt_table_info *t,954932 struct xt_counters counters[])955933{934934+ struct ip6t_entry *iter;956935 unsigned int cpu;957936 unsigned int i;958937 unsigned int curcpu;···946969 curcpu = smp_processor_id();947970948971 i = 0;949949- IP6T_ENTRY_ITERATE(t->entries[curcpu],950950- t->size,951951- set_entry_to_counter,952952- counters,953953- &i);972972+ xt_entry_foreach(iter, t->entries[curcpu], t->size) {973973+ SET_COUNTER(counters[i], iter->counters.bcnt,974974+ iter->counters.pcnt);975975+ ++i;976976+ }954977955978 for_each_possible_cpu(cpu) {956979 if (cpu == curcpu)957980 continue;958981 i = 0;959982 xt_info_wrlock(cpu);960960- IP6T_ENTRY_ITERATE(t->entries[cpu],961961- t->size,962962- add_entry_to_counter,963963- counters,964964- &i);983983+ xt_entry_foreach(iter, t->entries[cpu], t->size) {984984+ ADD_COUNTER(counters[i], iter->counters.bcnt,985985+ iter->counters.pcnt);986986+ ++i;987987+ }965988 xt_info_wrunlock(cpu);966989 }967990 local_bh_enable();···10801103 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;10811104}1082110510831083-static inline int10841084-compat_calc_match(const struct ip6t_entry_match *m, int *size)10851085-{10861086- *size += xt_compat_match_offset(m->u.kernel.match);10871087- return 0;10881088-}10891089-10901106static int compat_calc_entry(const struct ip6t_entry *e,10911107 const struct xt_table_info *info,10921108 const void *base, struct xt_table_info *newinfo)10931109{11101110+ const struct xt_entry_match *ematch;10941111 const struct ip6t_entry_target *t;10951112 unsigned int entry_offset;10961113 int off, i, ret;1097111410981115 off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);10991116 entry_offset = (void *)e - base;11001100- IP6T_MATCH_ITERATE(e, compat_calc_match, &off);11171117+ xt_ematch_foreach(ematch, e)11181118+ off += xt_compat_match_offset(ematch->u.kernel.match);11011119 t = ip6t_get_target_c(e);11021120 off += xt_compat_target_offset(t->u.kernel.target);11031121 newinfo->size -= off;···11141142static int compat_table_info(const struct xt_table_info *info,11151143 struct xt_table_info *newinfo)11161144{11451145+ struct ip6t_entry *iter;11171146 void *loc_cpu_entry;11471147+ int ret;1118114811191149 if (!newinfo || !info)11201150 return -EINVAL;···11251151 memcpy(newinfo, info, offsetof(struct xt_table_info, entries));11261152 newinfo->initial_entries = 0;11271153 loc_cpu_entry = info->entries[raw_smp_processor_id()];11281128- return IP6T_ENTRY_ITERATE(loc_cpu_entry, info->size,11291129- compat_calc_entry, info, loc_cpu_entry,11301130- newinfo);11541154+ xt_entry_foreach(iter, loc_cpu_entry, info->size) {11551155+ ret = compat_calc_entry(iter, info, loc_cpu_entry, newinfo);11561156+ if (ret != 0)11571157+ return ret;11581158+ }11591159+ return 0;11311160}11321161#endif11331162···12441267 struct xt_table_info *oldinfo;12451268 struct xt_counters *counters;12461269 const void *loc_cpu_old_entry;12701270+ struct ip6t_entry *iter;1247127112481272 ret = 0;12491273 counters = vmalloc_node(num_counters * sizeof(struct xt_counters),···1288131012891311 /* Decrease module usage counts and free resource */12901312 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];12911291- IP6T_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,12921292- net, NULL);13131313+ xt_entry_foreach(iter, loc_cpu_old_entry, oldinfo->size)13141314+ cleanup_entry(iter, net);13151315+12931316 xt_free_table_info(oldinfo);12941317 if (copy_to_user(counters_ptr, counters,12951318 sizeof(struct xt_counters) * num_counters) != 0)···13151336 struct ip6t_replace tmp;13161337 struct xt_table_info *newinfo;13171338 void *loc_cpu_entry;13391339+ struct ip6t_entry *iter;1318134013191341 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)13201342 return -EFAULT;···13361356 goto free_newinfo;13371357 }1338135813391339- ret = translate_table(net, tmp.name, tmp.valid_hooks,13401340- newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,13411341- tmp.hook_entry, tmp.underflow);13591359+ ret = translate_table(net, newinfo, loc_cpu_entry, &tmp);13421360 if (ret != 0)13431361 goto free_newinfo;13441362···13491371 return 0;1350137213511373 free_newinfo_untrans:13521352- IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, net, NULL);13741374+ xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)13751375+ cleanup_entry(iter, net);13531376 free_newinfo:13541377 xt_free_table_info(newinfo);13551378 return ret;13561356-}13571357-13581358-/* We're lazy, and add to the first CPU; overflow works its fey magic13591359- * and everything is OK. */13601360-static int13611361-add_counter_to_entry(struct ip6t_entry *e,13621362- const struct xt_counters addme[],13631363- unsigned int *i)13641364-{13651365- ADD_COUNTER(e->counters, addme[*i].bcnt, addme[*i].pcnt);13661366-13671367- (*i)++;13681368- return 0;13691379}1370138013711381static int···13711405 const struct xt_table_info *private;13721406 int ret = 0;13731407 const void *loc_cpu_entry;14081408+ struct ip6t_entry *iter;13741409#ifdef CONFIG_COMPAT13751410 struct compat_xt_counters_info compat_tmp;13761411···14301463 curcpu = smp_processor_id();14311464 xt_info_wrlock(curcpu);14321465 loc_cpu_entry = private->entries[curcpu];14331433- IP6T_ENTRY_ITERATE(loc_cpu_entry,14341434- private->size,14351435- add_counter_to_entry,14361436- paddc,14371437- &i);14661466+ xt_entry_foreach(iter, loc_cpu_entry, private->size) {14671467+ ADD_COUNTER(iter->counters, paddc[i].bcnt, paddc[i].pcnt);14681468+ ++i;14691469+ }14381470 xt_info_wrunlock(curcpu);1439147114401472 unlock_up_free:···14621496static int14631497compat_copy_entry_to_user(struct ip6t_entry *e, void __user **dstptr,14641498 unsigned int *size, struct xt_counters *counters,14651465- unsigned int *i)14991499+ unsigned int i)14661500{14671501 struct ip6t_entry_target *t;14681502 struct compat_ip6t_entry __user *ce;14691503 u_int16_t target_offset, next_offset;14701504 compat_uint_t origsize;14711471- int ret;15051505+ const struct xt_entry_match *ematch;15061506+ int ret = 0;1472150714731473- ret = -EFAULT;14741508 origsize = *size;14751509 ce = (struct compat_ip6t_entry __user *)*dstptr;14761476- if (copy_to_user(ce, e, sizeof(struct ip6t_entry)))14771477- goto out;14781478-14791479- if (copy_to_user(&ce->counters, &counters[*i], sizeof(counters[*i])))14801480- goto out;15101510+ if (copy_to_user(ce, e, sizeof(struct ip6t_entry)) != 0 ||15111511+ copy_to_user(&ce->counters, &counters[i],15121512+ sizeof(counters[i])) != 0)15131513+ return -EFAULT;1481151414821515 *dstptr += sizeof(struct compat_ip6t_entry);14831516 *size -= sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);1484151714851485- ret = IP6T_MATCH_ITERATE(e, xt_compat_match_to_user, dstptr, size);15181518+ xt_ematch_foreach(ematch, e) {15191519+ ret = xt_compat_match_to_user(ematch, dstptr, size);15201520+ if (ret != 0)15211521+ return ret;15221522+ }14861523 target_offset = e->target_offset - (origsize - *size);14871487- if (ret)14881488- goto out;14891524 t = ip6t_get_target(e);14901525 ret = xt_compat_target_to_user(t, dstptr, size);14911526 if (ret)14921492- goto out;14931493- ret = -EFAULT;15271527+ return ret;14941528 next_offset = e->next_offset - (origsize - *size);14951495- if (put_user(target_offset, &ce->target_offset))14961496- goto out;14971497- if (put_user(next_offset, &ce->next_offset))14981498- goto out;14991499-15001500- (*i)++;15291529+ if (put_user(target_offset, &ce->target_offset) != 0 ||15301530+ put_user(next_offset, &ce->next_offset) != 0)15311531+ return -EFAULT;15011532 return 0;15021502-out:15031503- return ret;15041533}1505153415061535static int···15031542 const char *name,15041543 const struct ip6t_ip6 *ipv6,15051544 unsigned int hookmask,15061506- int *size, unsigned int *i)15451545+ int *size)15071546{15081547 struct xt_match *match;15091548···15171556 }15181557 m->u.kernel.match = match;15191558 *size += xt_compat_match_offset(match);15201520-15211521- (*i)++;15221559 return 0;15231560}1524156115251525-static int15261526-compat_release_match(struct ip6t_entry_match *m, unsigned int *i)15271527-{15281528- if (i && (*i)-- == 0)15291529- return 1;15301530-15311531- module_put(m->u.kernel.match->me);15321532- return 0;15331533-}15341534-15351535-static int15361536-compat_release_entry(struct compat_ip6t_entry *e, unsigned int *i)15621562+static void compat_release_entry(struct compat_ip6t_entry *e)15371563{15381564 struct ip6t_entry_target *t;15391539-15401540- if (i && (*i)-- == 0)15411541- return 1;15651565+ struct xt_entry_match *ematch;1542156615431567 /* Cleanup all matches */15441544- COMPAT_IP6T_MATCH_ITERATE(e, compat_release_match, NULL);15681568+ xt_ematch_foreach(ematch, e)15691569+ module_put(ematch->u.kernel.match->me);15451570 t = compat_ip6t_get_target(e);15461571 module_put(t->u.kernel.target->me);15471547- return 0;15481572}1549157315501574static int···15401594 const unsigned char *limit,15411595 const unsigned int *hook_entries,15421596 const unsigned int *underflows,15431543- unsigned int *i,15441597 const char *name)15451598{15991599+ struct xt_entry_match *ematch;15461600 struct ip6t_entry_target *t;15471601 struct xt_target *target;15481602 unsigned int entry_offset;···15711625 off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);15721626 entry_offset = (void *)e - (void *)base;15731627 j = 0;15741574- ret = COMPAT_IP6T_MATCH_ITERATE(e, compat_find_calc_match, name,15751575- &e->ipv6, e->comefrom, &off, &j);15761576- if (ret != 0)15771577- goto release_matches;16281628+ xt_ematch_foreach(ematch, e) {16291629+ ret = compat_find_calc_match(ematch, name,16301630+ &e->ipv6, e->comefrom, &off);16311631+ if (ret != 0)16321632+ goto release_matches;16331633+ ++j;16341634+ }1578163515791636 t = compat_ip6t_get_target(e);15801637 target = try_then_request_module(xt_find_target(AF_INET6,···16091660 /* Clear counters and comefrom */16101661 memset(&e->counters, 0, sizeof(e->counters));16111662 e->comefrom = 0;16121612-16131613- (*i)++;16141663 return 0;1615166416161665out:16171666 module_put(t->u.kernel.target->me);16181667release_matches:16191619- IP6T_MATCH_ITERATE(e, compat_release_match, &j);16681668+ xt_ematch_foreach(ematch, e) {16691669+ if (j-- == 0)16701670+ break;16711671+ module_put(ematch->u.kernel.match->me);16721672+ }16201673 return ret;16211674}16221675···16321681 struct ip6t_entry *de;16331682 unsigned int origsize;16341683 int ret, h;16841684+ struct xt_entry_match *ematch;1635168516361686 ret = 0;16371687 origsize = *size;···16431691 *dstptr += sizeof(struct ip6t_entry);16441692 *size += sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);1645169316461646- ret = COMPAT_IP6T_MATCH_ITERATE(e, xt_compat_match_from_user,16471647- dstptr, size);16481648- if (ret)16491649- return ret;16941694+ xt_ematch_foreach(ematch, e) {16951695+ ret = xt_compat_match_from_user(ematch, dstptr, size);16961696+ if (ret != 0)16971697+ return ret;16981698+ }16501699 de->target_offset = e->target_offset - (origsize - *size);16511700 t = compat_ip6t_get_target(e);16521701 target = t->u.kernel.target;···16641711}1665171216661713static int compat_check_entry(struct ip6t_entry *e, struct net *net,16671667- const char *name, unsigned int *i)17141714+ const char *name)16681715{16691716 unsigned int j;16701670- int ret;17171717+ int ret = 0;16711718 struct xt_mtchk_param mtpar;17191719+ struct xt_entry_match *ematch;1672172016731721 j = 0;16741722 mtpar.net = net;···16771723 mtpar.entryinfo = &e->ipv6;16781724 mtpar.hook_mask = e->comefrom;16791725 mtpar.family = NFPROTO_IPV6;16801680- ret = IP6T_MATCH_ITERATE(e, check_match, &mtpar, &j);16811681- if (ret)16821682- goto cleanup_matches;17261726+ xt_ematch_foreach(ematch, e) {17271727+ ret = check_match(ematch, &mtpar);17281728+ if (ret != 0)17291729+ goto cleanup_matches;17301730+ ++j;17311731+ }1683173216841733 ret = check_target(e, net, name);16851734 if (ret)16861735 goto cleanup_matches;16871687-16881688- (*i)++;16891736 return 0;1690173716911738 cleanup_matches:16921692- IP6T_MATCH_ITERATE(e, cleanup_match, net, &j);17391739+ xt_ematch_foreach(ematch, e) {17401740+ if (j-- == 0)17411741+ break;17421742+ cleanup_match(ematch, net);17431743+ }16931744 return ret;16941745}16951746···17121753 unsigned int i, j;17131754 struct xt_table_info *newinfo, *info;17141755 void *pos, *entry0, *entry1;17561756+ struct compat_ip6t_entry *iter0;17571757+ struct ip6t_entry *iter1;17151758 unsigned int size;17161716- int ret;17591759+ int ret = 0;1717176017181761 info = *pinfo;17191762 entry0 = *pentry0;···17321771 j = 0;17331772 xt_compat_lock(AF_INET6);17341773 /* Walk through entries, checking offsets. */17351735- ret = COMPAT_IP6T_ENTRY_ITERATE(entry0, total_size,17361736- check_compat_entry_size_and_hooks,17371737- info, &size, entry0,17381738- entry0 + total_size,17391739- hook_entries, underflows, &j, name);17401740- if (ret != 0)17411741- goto out_unlock;17741774+ xt_entry_foreach(iter0, entry0, total_size) {17751775+ ret = check_compat_entry_size_and_hooks(iter0, info, &size,17761776+ entry0, entry0 + total_size, hook_entries, underflows,17771777+ name);17781778+ if (ret != 0)17791779+ goto out_unlock;17801780+ ++j;17811781+ }1742178217431783 ret = -EINVAL;17441784 if (j != number) {···17781816 entry1 = newinfo->entries[raw_smp_processor_id()];17791817 pos = entry1;17801818 size = total_size;17811781- ret = COMPAT_IP6T_ENTRY_ITERATE(entry0, total_size,17821782- compat_copy_entry_from_user,17831783- &pos, &size, name, newinfo, entry1);18191819+ xt_entry_foreach(iter0, entry0, total_size) {18201820+ ret = compat_copy_entry_from_user(iter0, &pos,18211821+ &size, name, newinfo, entry1);18221822+ if (ret != 0)18231823+ break;18241824+ }17841825 xt_compat_flush_offsets(AF_INET6);17851826 xt_compat_unlock(AF_INET6);17861827 if (ret)···17941829 goto free_newinfo;1795183017961831 i = 0;17971797- ret = IP6T_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry,17981798- net, name, &i);18321832+ xt_entry_foreach(iter1, entry1, newinfo->size) {18331833+ ret = compat_check_entry(iter1, net, name);18341834+ if (ret != 0)18351835+ break;18361836+ ++i;18371837+ }17991838 if (ret) {18391839+ /*18401840+ * The first i matches need cleanup_entry (calls ->destroy)18411841+ * because they had called ->check already. The other j-i18421842+ * entries need only release.18431843+ */18441844+ int skip = i;18001845 j -= i;18011801- COMPAT_IP6T_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i,18021802- compat_release_entry, &j);18031803- IP6T_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, net, &i);18461846+ xt_entry_foreach(iter0, entry0, newinfo->size) {18471847+ if (skip-- > 0)18481848+ continue;18491849+ if (j-- == 0)18501850+ break;18511851+ compat_release_entry(iter0);18521852+ }18531853+ xt_entry_foreach(iter1, entry1, newinfo->size) {18541854+ if (i-- == 0)18551855+ break;18561856+ cleanup_entry(iter1, net);18571857+ }18041858 xt_free_table_info(newinfo);18051859 return ret;18061860 }···18371853free_newinfo:18381854 xt_free_table_info(newinfo);18391855out:18401840- COMPAT_IP6T_ENTRY_ITERATE(entry0, total_size, compat_release_entry, &j);18561856+ xt_entry_foreach(iter0, entry0, total_size) {18571857+ if (j-- == 0)18581858+ break;18591859+ compat_release_entry(iter0);18601860+ }18411861 return ret;18421862out_unlock:18431863 xt_compat_flush_offsets(AF_INET6);···18561868 struct compat_ip6t_replace tmp;18571869 struct xt_table_info *newinfo;18581870 void *loc_cpu_entry;18711871+ struct ip6t_entry *iter;1859187218601873 if (copy_from_user(&tmp, user, sizeof(tmp)) != 0)18611874 return -EFAULT;···18951906 return 0;1896190718971908 free_newinfo_untrans:18981898- IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, net, NULL);19091909+ xt_entry_foreach(iter, loc_cpu_entry, newinfo->size)19101910+ cleanup_entry(iter, net);18991911 free_newinfo:19001912 xt_free_table_info(newinfo);19011913 return ret;···19451955 int ret = 0;19461956 const void *loc_cpu_entry;19471957 unsigned int i = 0;19581958+ struct ip6t_entry *iter;1948195919491960 counters = alloc_counters(table);19501961 if (IS_ERR(counters))···19581967 loc_cpu_entry = private->entries[raw_smp_processor_id()];19591968 pos = userptr;19601969 size = total_size;19611961- ret = IP6T_ENTRY_ITERATE(loc_cpu_entry, total_size,19621962- compat_copy_entry_to_user,19631963- &pos, &size, counters, &i);19701970+ xt_entry_foreach(iter, loc_cpu_entry, total_size) {19711971+ ret = compat_copy_entry_to_user(iter, &pos,19721972+ &size, counters, i++);19731973+ if (ret != 0)19741974+ break;19751975+ }1964197619651977 vfree(counters);19661978 return ret;···21372143 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];21382144 memcpy(loc_cpu_entry, repl->entries, repl->size);2139214521402140- ret = translate_table(net, table->name, table->valid_hooks,21412141- newinfo, loc_cpu_entry, repl->size,21422142- repl->num_entries,21432143- repl->hook_entry,21442144- repl->underflow);21462146+ ret = translate_table(net, newinfo, loc_cpu_entry, repl);21452147 if (ret != 0)21462148 goto out_free;21472149···21592169 struct xt_table_info *private;21602170 void *loc_cpu_entry;21612171 struct module *table_owner = table->me;21722172+ struct ip6t_entry *iter;2162217321632174 private = xt_unregister_table(table);2164217521652176 /* Decrease module usage counts and free resources */21662177 loc_cpu_entry = private->entries[raw_smp_processor_id()];21672167- IP6T_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, net, NULL);21782178+ xt_entry_foreach(iter, loc_cpu_entry, private->size)21792179+ cleanup_entry(iter, net);21682180 if (private->number > private->initial_entries)21692181 module_put(table_owner);21702182 xt_free_table_info(private);
+1-7
net/ipv6/netfilter/nf_conntrack_reasm.c
···469469470470 /* all original skbs are linked into the NFCT_FRAG6_CB(head).orig */471471 fp = skb_shinfo(head)->frag_list;472472- if (NFCT_FRAG6_CB(fp)->orig == NULL)472472+ if (fp && NFCT_FRAG6_CB(fp)->orig == NULL)473473 /* at above code, head skb is divided into two skbs. */474474 fp = fp->next;475475···594594 skb_set_transport_header(clone, fhoff);595595 hdr = ipv6_hdr(clone);596596 fhdr = (struct frag_hdr *)skb_transport_header(clone);597597-598598- if (!(fhdr->frag_off & htons(0xFFF9))) {599599- pr_debug("Invalid fragment offset\n");600600- /* It is not a fragmented frame */601601- goto ret_orig;602602- }603597604598 if (atomic_read(&nf_init_frags.mem) > nf_init_frags.high_thresh)605599 nf_ct_frag6_evictor();
+8-4
net/netfilter/xt_TCPMSS.c
···239239{240240 const struct xt_tcpmss_info *info = par->targinfo;241241 const struct ipt_entry *e = par->entryinfo;242242+ const struct xt_entry_match *ematch;242243243244 if (info->mss == XT_TCPMSS_CLAMP_PMTU &&244245 (par->hook_mask & ~((1 << NF_INET_FORWARD) |···249248 "FORWARD, OUTPUT and POSTROUTING hooks\n");250249 return false;251250 }252252- if (IPT_MATCH_ITERATE(e, find_syn_match))253253- return true;251251+ xt_ematch_foreach(ematch, e)252252+ if (find_syn_match(ematch))253253+ return true;254254 printk("xt_TCPMSS: Only works on TCP SYN packets\n");255255 return false;256256}···261259{262260 const struct xt_tcpmss_info *info = par->targinfo;263261 const struct ip6t_entry *e = par->entryinfo;262262+ const struct xt_entry_match *ematch;264263265264 if (info->mss == XT_TCPMSS_CLAMP_PMTU &&266265 (par->hook_mask & ~((1 << NF_INET_FORWARD) |···271268 "FORWARD, OUTPUT and POSTROUTING hooks\n");272269 return false;273270 }274274- if (IP6T_MATCH_ITERATE(e, find_syn_match))275275- return true;271271+ xt_ematch_foreach(ematch, e)272272+ if (find_syn_match(ematch))273273+ return true;276274 printk("xt_TCPMSS: Only works on TCP SYN packets\n");277275 return false;278276}
+2-2
net/netfilter/xt_recent.c
···177177178178static void recent_entry_update(struct recent_table *t, struct recent_entry *e)179179{180180+ e->index %= ip_pkt_list_tot;180181 e->stamps[e->index++] = jiffies;181182 if (e->index > e->nstamps)182183 e->nstamps = e->index;183183- e->index %= ip_pkt_list_tot;184184 list_move_tail(&e->lru_list, &t->lru_list);185185}186186···267267 for (i = 0; i < e->nstamps; i++) {268268 if (info->seconds && time_after(time, e->stamps[i]))269269 continue;270270- if (++hits >= info->hit_count) {270270+ if (info->hit_count && ++hits >= info->hit_count) {271271 ret = !ret;272272 break;273273 }