diff options
Diffstat (limited to 'net/bridge')
-rw-r--r-- | net/bridge/br.c | 10 | ||||
-rw-r--r-- | net/bridge/br_fdb.c | 45 | ||||
-rw-r--r-- | net/bridge/br_netfilter.c | 33 | ||||
-rw-r--r-- | net/bridge/br_private.h | 12 | ||||
-rw-r--r-- | net/bridge/br_sysfs_br.c | 3 | ||||
-rw-r--r-- | net/bridge/br_sysfs_if.c | 3 | ||||
-rw-r--r-- | net/bridge/netfilter/ebtables.c | 18 |
7 files changed, 65 insertions, 59 deletions
diff --git a/net/bridge/br.c b/net/bridge/br.c index 4d2c1f1cb524..9aac5213105a 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c | |||
@@ -65,8 +65,9 @@ static int __init br_init(void) | |||
65 | brioctl_set(br_ioctl_deviceless_stub); | 65 | brioctl_set(br_ioctl_deviceless_stub); |
66 | br_handle_frame_hook = br_handle_frame; | 66 | br_handle_frame_hook = br_handle_frame; |
67 | 67 | ||
68 | br_fdb_get_hook = br_fdb_get; | 68 | #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) |
69 | br_fdb_put_hook = br_fdb_put; | 69 | br_fdb_test_addr_hook = br_fdb_test_addr; |
70 | #endif | ||
70 | 71 | ||
71 | return 0; | 72 | return 0; |
72 | err_out4: | 73 | err_out4: |
@@ -95,8 +96,9 @@ static void __exit br_deinit(void) | |||
95 | synchronize_net(); | 96 | synchronize_net(); |
96 | 97 | ||
97 | br_netfilter_fini(); | 98 | br_netfilter_fini(); |
98 | br_fdb_get_hook = NULL; | 99 | #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) |
99 | br_fdb_put_hook = NULL; | 100 | br_fdb_test_addr_hook = NULL; |
101 | #endif | ||
100 | 102 | ||
101 | br_handle_frame_hook = NULL; | 103 | br_handle_frame_hook = NULL; |
102 | br_fdb_fini(); | 104 | br_fdb_fini(); |
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index a48f5efdb6bf..57bf05c353bc 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c | |||
@@ -71,10 +71,17 @@ static inline int br_mac_hash(const unsigned char *mac) | |||
71 | return jhash_1word(key, fdb_salt) & (BR_HASH_SIZE - 1); | 71 | return jhash_1word(key, fdb_salt) & (BR_HASH_SIZE - 1); |
72 | } | 72 | } |
73 | 73 | ||
74 | static void fdb_rcu_free(struct rcu_head *head) | ||
75 | { | ||
76 | struct net_bridge_fdb_entry *ent | ||
77 | = container_of(head, struct net_bridge_fdb_entry, rcu); | ||
78 | kmem_cache_free(br_fdb_cache, ent); | ||
79 | } | ||
80 | |||
74 | static inline void fdb_delete(struct net_bridge_fdb_entry *f) | 81 | static inline void fdb_delete(struct net_bridge_fdb_entry *f) |
75 | { | 82 | { |
76 | hlist_del_rcu(&f->hlist); | 83 | hlist_del_rcu(&f->hlist); |
77 | br_fdb_put(f); | 84 | call_rcu(&f->rcu, fdb_rcu_free); |
78 | } | 85 | } |
79 | 86 | ||
80 | void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr) | 87 | void br_fdb_changeaddr(struct net_bridge_port *p, const unsigned char *newaddr) |
@@ -226,33 +233,26 @@ struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br, | |||
226 | return NULL; | 233 | return NULL; |
227 | } | 234 | } |
228 | 235 | ||
229 | /* Interface used by ATM hook that keeps a ref count */ | 236 | #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) |
230 | struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br, | 237 | /* Interface used by ATM LANE hook to test |
231 | unsigned char *addr) | 238 | * if an addr is on some other bridge port */ |
239 | int br_fdb_test_addr(struct net_device *dev, unsigned char *addr) | ||
232 | { | 240 | { |
233 | struct net_bridge_fdb_entry *fdb; | 241 | struct net_bridge_fdb_entry *fdb; |
242 | int ret; | ||
243 | |||
244 | if (!dev->br_port) | ||
245 | return 0; | ||
234 | 246 | ||
235 | rcu_read_lock(); | 247 | rcu_read_lock(); |
236 | fdb = __br_fdb_get(br, addr); | 248 | fdb = __br_fdb_get(dev->br_port->br, addr); |
237 | if (fdb && !atomic_inc_not_zero(&fdb->use_count)) | 249 | ret = fdb && fdb->dst->dev != dev && |
238 | fdb = NULL; | 250 | fdb->dst->state == BR_STATE_FORWARDING; |
239 | rcu_read_unlock(); | 251 | rcu_read_unlock(); |
240 | return fdb; | ||
241 | } | ||
242 | |||
243 | static void fdb_rcu_free(struct rcu_head *head) | ||
244 | { | ||
245 | struct net_bridge_fdb_entry *ent | ||
246 | = container_of(head, struct net_bridge_fdb_entry, rcu); | ||
247 | kmem_cache_free(br_fdb_cache, ent); | ||
248 | } | ||
249 | 252 | ||
250 | /* Set entry up for deletion with RCU */ | 253 | return ret; |
251 | void br_fdb_put(struct net_bridge_fdb_entry *ent) | ||
252 | { | ||
253 | if (atomic_dec_and_test(&ent->use_count)) | ||
254 | call_rcu(&ent->rcu, fdb_rcu_free); | ||
255 | } | 254 | } |
255 | #endif /* CONFIG_ATM_LANE */ | ||
256 | 256 | ||
257 | /* | 257 | /* |
258 | * Fill buffer with forwarding table records in | 258 | * Fill buffer with forwarding table records in |
@@ -326,7 +326,6 @@ static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head, | |||
326 | fdb = kmem_cache_alloc(br_fdb_cache, GFP_ATOMIC); | 326 | fdb = kmem_cache_alloc(br_fdb_cache, GFP_ATOMIC); |
327 | if (fdb) { | 327 | if (fdb) { |
328 | memcpy(fdb->addr.addr, addr, ETH_ALEN); | 328 | memcpy(fdb->addr.addr, addr, ETH_ALEN); |
329 | atomic_set(&fdb->use_count, 1); | ||
330 | hlist_add_head_rcu(&fdb->hlist, head); | 329 | hlist_add_head_rcu(&fdb->hlist, head); |
331 | 330 | ||
332 | fdb->dst = source; | 331 | fdb->dst = source; |
@@ -398,7 +397,7 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, | |||
398 | if (unlikely(fdb->is_local)) { | 397 | if (unlikely(fdb->is_local)) { |
399 | if (net_ratelimit()) | 398 | if (net_ratelimit()) |
400 | printk(KERN_WARNING "%s: received packet with " | 399 | printk(KERN_WARNING "%s: received packet with " |
401 | " own address as source address\n", | 400 | "own address as source address\n", |
402 | source->dev->name); | 401 | source->dev->name); |
403 | } else { | 402 | } else { |
404 | /* fastpath: update of existing entry */ | 403 | /* fastpath: update of existing entry */ |
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index e4a418fcb35b..d22f611e4004 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
@@ -228,6 +228,7 @@ int nf_bridge_copy_header(struct sk_buff *skb) | |||
228 | static int br_nf_pre_routing_finish_ipv6(struct sk_buff *skb) | 228 | static int br_nf_pre_routing_finish_ipv6(struct sk_buff *skb) |
229 | { | 229 | { |
230 | struct nf_bridge_info *nf_bridge = skb->nf_bridge; | 230 | struct nf_bridge_info *nf_bridge = skb->nf_bridge; |
231 | struct rtable *rt; | ||
231 | 232 | ||
232 | if (nf_bridge->mask & BRNF_PKT_TYPE) { | 233 | if (nf_bridge->mask & BRNF_PKT_TYPE) { |
233 | skb->pkt_type = PACKET_OTHERHOST; | 234 | skb->pkt_type = PACKET_OTHERHOST; |
@@ -235,12 +236,13 @@ static int br_nf_pre_routing_finish_ipv6(struct sk_buff *skb) | |||
235 | } | 236 | } |
236 | nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING; | 237 | nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING; |
237 | 238 | ||
238 | skb->rtable = bridge_parent_rtable(nf_bridge->physindev); | 239 | rt = bridge_parent_rtable(nf_bridge->physindev); |
239 | if (!skb->rtable) { | 240 | if (!rt) { |
240 | kfree_skb(skb); | 241 | kfree_skb(skb); |
241 | return 0; | 242 | return 0; |
242 | } | 243 | } |
243 | dst_hold(&skb->rtable->u.dst); | 244 | dst_hold(&rt->u.dst); |
245 | skb_dst_set(skb, &rt->u.dst); | ||
244 | 246 | ||
245 | skb->dev = nf_bridge->physindev; | 247 | skb->dev = nf_bridge->physindev; |
246 | nf_bridge_push_encap_header(skb); | 248 | nf_bridge_push_encap_header(skb); |
@@ -320,7 +322,7 @@ static int br_nf_pre_routing_finish_bridge(struct sk_buff *skb) | |||
320 | 322 | ||
321 | skb->dev = bridge_parent(skb->dev); | 323 | skb->dev = bridge_parent(skb->dev); |
322 | if (skb->dev) { | 324 | if (skb->dev) { |
323 | struct dst_entry *dst = skb->dst; | 325 | struct dst_entry *dst = skb_dst(skb); |
324 | 326 | ||
325 | nf_bridge_pull_encap_header(skb); | 327 | nf_bridge_pull_encap_header(skb); |
326 | 328 | ||
@@ -338,6 +340,7 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb) | |||
338 | struct net_device *dev = skb->dev; | 340 | struct net_device *dev = skb->dev; |
339 | struct iphdr *iph = ip_hdr(skb); | 341 | struct iphdr *iph = ip_hdr(skb); |
340 | struct nf_bridge_info *nf_bridge = skb->nf_bridge; | 342 | struct nf_bridge_info *nf_bridge = skb->nf_bridge; |
343 | struct rtable *rt; | ||
341 | int err; | 344 | int err; |
342 | 345 | ||
343 | if (nf_bridge->mask & BRNF_PKT_TYPE) { | 346 | if (nf_bridge->mask & BRNF_PKT_TYPE) { |
@@ -347,7 +350,6 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb) | |||
347 | nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING; | 350 | nf_bridge->mask ^= BRNF_NF_BRIDGE_PREROUTING; |
348 | if (dnat_took_place(skb)) { | 351 | if (dnat_took_place(skb)) { |
349 | if ((err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev))) { | 352 | if ((err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, dev))) { |
350 | struct rtable *rt; | ||
351 | struct flowi fl = { | 353 | struct flowi fl = { |
352 | .nl_u = { | 354 | .nl_u = { |
353 | .ip4_u = { | 355 | .ip4_u = { |
@@ -373,7 +375,7 @@ static int br_nf_pre_routing_finish(struct sk_buff *skb) | |||
373 | /* - Bridged-and-DNAT'ed traffic doesn't | 375 | /* - Bridged-and-DNAT'ed traffic doesn't |
374 | * require ip_forwarding. */ | 376 | * require ip_forwarding. */ |
375 | if (((struct dst_entry *)rt)->dev == dev) { | 377 | if (((struct dst_entry *)rt)->dev == dev) { |
376 | skb->dst = (struct dst_entry *)rt; | 378 | skb_dst_set(skb, (struct dst_entry *)rt); |
377 | goto bridged_dnat; | 379 | goto bridged_dnat; |
378 | } | 380 | } |
379 | /* we are sure that forwarding is disabled, so printing | 381 | /* we are sure that forwarding is disabled, so printing |
@@ -387,7 +389,7 @@ free_skb: | |||
387 | kfree_skb(skb); | 389 | kfree_skb(skb); |
388 | return 0; | 390 | return 0; |
389 | } else { | 391 | } else { |
390 | if (skb->dst->dev == dev) { | 392 | if (skb_dst(skb)->dev == dev) { |
391 | bridged_dnat: | 393 | bridged_dnat: |
392 | /* Tell br_nf_local_out this is a | 394 | /* Tell br_nf_local_out this is a |
393 | * bridged frame */ | 395 | * bridged frame */ |
@@ -404,12 +406,13 @@ bridged_dnat: | |||
404 | skb->pkt_type = PACKET_HOST; | 406 | skb->pkt_type = PACKET_HOST; |
405 | } | 407 | } |
406 | } else { | 408 | } else { |
407 | skb->rtable = bridge_parent_rtable(nf_bridge->physindev); | 409 | rt = bridge_parent_rtable(nf_bridge->physindev); |
408 | if (!skb->rtable) { | 410 | if (!rt) { |
409 | kfree_skb(skb); | 411 | kfree_skb(skb); |
410 | return 0; | 412 | return 0; |
411 | } | 413 | } |
412 | dst_hold(&skb->rtable->u.dst); | 414 | dst_hold(&rt->u.dst); |
415 | skb_dst_set(skb, &rt->u.dst); | ||
413 | } | 416 | } |
414 | 417 | ||
415 | skb->dev = nf_bridge->physindev; | 418 | skb->dev = nf_bridge->physindev; |
@@ -628,10 +631,10 @@ static unsigned int br_nf_local_in(unsigned int hook, struct sk_buff *skb, | |||
628 | const struct net_device *out, | 631 | const struct net_device *out, |
629 | int (*okfn)(struct sk_buff *)) | 632 | int (*okfn)(struct sk_buff *)) |
630 | { | 633 | { |
631 | if (skb->rtable && skb->rtable == bridge_parent_rtable(in)) { | 634 | struct rtable *rt = skb_rtable(skb); |
632 | dst_release(&skb->rtable->u.dst); | 635 | |
633 | skb->rtable = NULL; | 636 | if (rt && rt == bridge_parent_rtable(in)) |
634 | } | 637 | skb_dst_drop(skb); |
635 | 638 | ||
636 | return NF_ACCEPT; | 639 | return NF_ACCEPT; |
637 | } | 640 | } |
@@ -846,7 +849,7 @@ static unsigned int br_nf_post_routing(unsigned int hook, struct sk_buff *skb, | |||
846 | return NF_ACCEPT; | 849 | return NF_ACCEPT; |
847 | 850 | ||
848 | #ifdef CONFIG_NETFILTER_DEBUG | 851 | #ifdef CONFIG_NETFILTER_DEBUG |
849 | if (skb->dst == NULL) { | 852 | if (skb_dst(skb) == NULL) { |
850 | printk(KERN_INFO "br_netfilter post_routing: skb->dst == NULL\n"); | 853 | printk(KERN_INFO "br_netfilter post_routing: skb->dst == NULL\n"); |
851 | goto print_error; | 854 | goto print_error; |
852 | } | 855 | } |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index b6c3b71974dc..d5b5537272b4 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
@@ -51,7 +51,6 @@ struct net_bridge_fdb_entry | |||
51 | struct net_bridge_port *dst; | 51 | struct net_bridge_port *dst; |
52 | 52 | ||
53 | struct rcu_head rcu; | 53 | struct rcu_head rcu; |
54 | atomic_t use_count; | ||
55 | unsigned long ageing_timer; | 54 | unsigned long ageing_timer; |
56 | mac_addr addr; | 55 | mac_addr addr; |
57 | unsigned char is_local; | 56 | unsigned char is_local; |
@@ -154,9 +153,7 @@ extern void br_fdb_delete_by_port(struct net_bridge *br, | |||
154 | const struct net_bridge_port *p, int do_all); | 153 | const struct net_bridge_port *p, int do_all); |
155 | extern struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br, | 154 | extern struct net_bridge_fdb_entry *__br_fdb_get(struct net_bridge *br, |
156 | const unsigned char *addr); | 155 | const unsigned char *addr); |
157 | extern struct net_bridge_fdb_entry *br_fdb_get(struct net_bridge *br, | 156 | extern int br_fdb_test_addr(struct net_device *dev, unsigned char *addr); |
158 | unsigned char *addr); | ||
159 | extern void br_fdb_put(struct net_bridge_fdb_entry *ent); | ||
160 | extern int br_fdb_fillbuf(struct net_bridge *br, void *buf, | 157 | extern int br_fdb_fillbuf(struct net_bridge *br, void *buf, |
161 | unsigned long count, unsigned long off); | 158 | unsigned long count, unsigned long off); |
162 | extern int br_fdb_insert(struct net_bridge *br, | 159 | extern int br_fdb_insert(struct net_bridge *br, |
@@ -242,10 +239,9 @@ extern void br_stp_port_timer_init(struct net_bridge_port *p); | |||
242 | extern unsigned long br_timer_value(const struct timer_list *timer); | 239 | extern unsigned long br_timer_value(const struct timer_list *timer); |
243 | 240 | ||
244 | /* br.c */ | 241 | /* br.c */ |
245 | extern struct net_bridge_fdb_entry *(*br_fdb_get_hook)(struct net_bridge *br, | 242 | #if defined(CONFIG_ATM_LANE) || defined(CONFIG_ATM_LANE_MODULE) |
246 | unsigned char *addr); | 243 | extern int (*br_fdb_test_addr_hook)(struct net_device *dev, unsigned char *addr); |
247 | extern void (*br_fdb_put_hook)(struct net_bridge_fdb_entry *ent); | 244 | #endif |
248 | |||
249 | 245 | ||
250 | /* br_netlink.c */ | 246 | /* br_netlink.c */ |
251 | extern int br_netlink_init(void); | 247 | extern int br_netlink_init(void); |
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index 603d89248e71..ee4820aa1843 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c | |||
@@ -172,7 +172,8 @@ static ssize_t store_stp_state(struct device *d, | |||
172 | if (endp == buf) | 172 | if (endp == buf) |
173 | return -EINVAL; | 173 | return -EINVAL; |
174 | 174 | ||
175 | rtnl_lock(); | 175 | if (!rtnl_trylock()) |
176 | return restart_syscall(); | ||
176 | br_stp_set_enabled(br, val); | 177 | br_stp_set_enabled(br, val); |
177 | rtnl_unlock(); | 178 | rtnl_unlock(); |
178 | 179 | ||
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c index 02b2d50cce4d..4a3cdf8f3813 100644 --- a/net/bridge/br_sysfs_if.c +++ b/net/bridge/br_sysfs_if.c | |||
@@ -189,7 +189,8 @@ static ssize_t brport_store(struct kobject * kobj, | |||
189 | 189 | ||
190 | val = simple_strtoul(buf, &endp, 0); | 190 | val = simple_strtoul(buf, &endp, 0); |
191 | if (endp != buf) { | 191 | if (endp != buf) { |
192 | rtnl_lock(); | 192 | if (!rtnl_trylock()) |
193 | return restart_syscall(); | ||
193 | if (p->dev && p->br && brport_attr->store) { | 194 | if (p->dev && p->br && brport_attr->store) { |
194 | spin_lock_bh(&p->br->lock); | 195 | spin_lock_bh(&p->br->lock); |
195 | ret = brport_attr->store(p, val); | 196 | ret = brport_attr->store(p, val); |
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 820252aee81f..37928d5f2840 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c | |||
@@ -142,6 +142,12 @@ static inline int ebt_basic_match(struct ebt_entry *e, struct ethhdr *h, | |||
142 | return 0; | 142 | return 0; |
143 | } | 143 | } |
144 | 144 | ||
145 | static inline __pure | ||
146 | struct ebt_entry *ebt_next_entry(const struct ebt_entry *entry) | ||
147 | { | ||
148 | return (void *)entry + entry->next_offset; | ||
149 | } | ||
150 | |||
145 | /* Do some firewalling */ | 151 | /* Do some firewalling */ |
146 | unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb, | 152 | unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb, |
147 | const struct net_device *in, const struct net_device *out, | 153 | const struct net_device *in, const struct net_device *out, |
@@ -164,7 +170,7 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb, | |||
164 | mtpar.in = tgpar.in = in; | 170 | mtpar.in = tgpar.in = in; |
165 | mtpar.out = tgpar.out = out; | 171 | mtpar.out = tgpar.out = out; |
166 | mtpar.hotdrop = &hotdrop; | 172 | mtpar.hotdrop = &hotdrop; |
167 | tgpar.hooknum = hook; | 173 | mtpar.hooknum = tgpar.hooknum = hook; |
168 | 174 | ||
169 | read_lock_bh(&table->lock); | 175 | read_lock_bh(&table->lock); |
170 | private = table->private; | 176 | private = table->private; |
@@ -249,8 +255,7 @@ letsreturn: | |||
249 | /* jump to a udc */ | 255 | /* jump to a udc */ |
250 | cs[sp].n = i + 1; | 256 | cs[sp].n = i + 1; |
251 | cs[sp].chaininfo = chaininfo; | 257 | cs[sp].chaininfo = chaininfo; |
252 | cs[sp].e = (struct ebt_entry *) | 258 | cs[sp].e = ebt_next_entry(point); |
253 | (((char *)point) + point->next_offset); | ||
254 | i = 0; | 259 | i = 0; |
255 | chaininfo = (struct ebt_entries *) (base + verdict); | 260 | chaininfo = (struct ebt_entries *) (base + verdict); |
256 | #ifdef CONFIG_NETFILTER_DEBUG | 261 | #ifdef CONFIG_NETFILTER_DEBUG |
@@ -266,8 +271,7 @@ letsreturn: | |||
266 | sp++; | 271 | sp++; |
267 | continue; | 272 | continue; |
268 | letscontinue: | 273 | letscontinue: |
269 | point = (struct ebt_entry *) | 274 | point = ebt_next_entry(point); |
270 | (((char *)point) + point->next_offset); | ||
271 | i++; | 275 | i++; |
272 | } | 276 | } |
273 | 277 | ||
@@ -787,7 +791,7 @@ static int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s | |||
787 | /* this can't be 0, so the loop test is correct */ | 791 | /* this can't be 0, so the loop test is correct */ |
788 | cl_s[i].cs.n = pos + 1; | 792 | cl_s[i].cs.n = pos + 1; |
789 | pos = 0; | 793 | pos = 0; |
790 | cl_s[i].cs.e = ((void *)e + e->next_offset); | 794 | cl_s[i].cs.e = ebt_next_entry(e); |
791 | e = (struct ebt_entry *)(hlp2->data); | 795 | e = (struct ebt_entry *)(hlp2->data); |
792 | nentries = hlp2->nentries; | 796 | nentries = hlp2->nentries; |
793 | cl_s[i].from = chain_nr; | 797 | cl_s[i].from = chain_nr; |
@@ -797,7 +801,7 @@ static int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s | |||
797 | continue; | 801 | continue; |
798 | } | 802 | } |
799 | letscontinue: | 803 | letscontinue: |
800 | e = (void *)e + e->next_offset; | 804 | e = ebt_next_entry(e); |
801 | pos++; | 805 | pos++; |
802 | } | 806 | } |
803 | return 0; | 807 | return 0; |