···232232 __be16 dport = 0; /* destination port to forward */233233 unsigned int flags;234234 struct ip_vs_conn_param param;235235+ const union nf_inet_addr fwmark = { .ip = htonl(svc->fwmark) };235236 union nf_inet_addr snet; /* source network of the client,236237 after masking */237238···268267 {269268 int protocol = iph.protocol;270269 const union nf_inet_addr *vaddr = &iph.daddr;271271- const union nf_inet_addr fwmark = { .ip = htonl(svc->fwmark) };272270 __be16 vport = 0;273271274272 if (dst_port == svc->port) {
+16-27
net/netfilter/nf_conntrack_netlink.c
···13671367 nf_ct_protonum(ct));13681368 if (helper == NULL) {13691369 rcu_read_unlock();13701370- spin_unlock_bh(&nf_conntrack_lock);13711370#ifdef CONFIG_MODULES13721371 if (request_module("nfct-helper-%s", helpname) < 0) {13731373- spin_lock_bh(&nf_conntrack_lock);13741372 err = -EOPNOTSUPP;13751373 goto err1;13761374 }1377137513781378- spin_lock_bh(&nf_conntrack_lock);13791376 rcu_read_lock();13801377 helper = __nf_conntrack_helper_find(helpname,13811378 nf_ct_l3num(ct),···14661469 tstamp->start = ktime_to_ns(ktime_get_real());1467147014681471 add_timer(&ct->timeout);14721472+ spin_lock_bh(&nf_conntrack_lock);14691473 nf_conntrack_hash_insert(ct);14741474+ nf_conntrack_get(&ct->ct_general);14751475+ spin_unlock_bh(&nf_conntrack_lock);14701476 rcu_read_unlock();1471147714721478 return ct;···14901490 struct nf_conntrack_tuple otuple, rtuple;14911491 struct nf_conntrack_tuple_hash *h = NULL;14921492 struct nfgenmsg *nfmsg = nlmsg_data(nlh);14931493+ struct nf_conn *ct;14931494 u_int8_t u3 = nfmsg->nfgen_family;14941495 u16 zone;14951496 int err;···1513151215141513 spin_lock_bh(&nf_conntrack_lock);15151514 if (cda[CTA_TUPLE_ORIG])15161516- h = __nf_conntrack_find(net, zone, &otuple);15151515+ h = nf_conntrack_find_get(net, zone, &otuple);15171516 else if (cda[CTA_TUPLE_REPLY])15181518- h = __nf_conntrack_find(net, zone, &rtuple);15171517+ h = nf_conntrack_find_get(net, zone, &rtuple);15181518+ spin_unlock_bh(&nf_conntrack_lock);1519151915201520 if (h == NULL) {15211521 err = -ENOENT;15221522 if (nlh->nlmsg_flags & NLM_F_CREATE) {15231523- struct nf_conn *ct;15241523 enum ip_conntrack_events events;1525152415261525 ct = ctnetlink_create_conntrack(net, zone, cda, &otuple,15271526 &rtuple, u3);15281528- if (IS_ERR(ct)) {15291529- err = PTR_ERR(ct);15301530- goto out_unlock;15311531- }15271527+ if (IS_ERR(ct))15281528+ return PTR_ERR(ct);15291529+15321530 err = 0;15331533- nf_conntrack_get(&ct->ct_general);15341534- spin_unlock_bh(&nf_conntrack_lock);15351531 if (test_bit(IPS_EXPECTED_BIT, &ct->status))15361532 events = IPCT_RELATED;15371533 else···15431545 ct, NETLINK_CB(skb).pid,15441546 nlmsg_report(nlh));15451547 nf_ct_put(ct);15461546- } else15471547- spin_unlock_bh(&nf_conntrack_lock);15481548+ }1548154915491550 return err;15501551 }15511552 /* implicit 'else' */1552155315531553- /* We manipulate the conntrack inside the global conntrack table lock,15541554- * so there's no need to increase the refcount */15551554 err = -EEXIST;15551555+ ct = nf_ct_tuplehash_to_ctrack(h);15561556 if (!(nlh->nlmsg_flags & NLM_F_EXCL)) {15571557- struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);15581558-15571557+ spin_lock_bh(&nf_conntrack_lock);15591558 err = ctnetlink_change_conntrack(ct, cda);15591559+ spin_unlock_bh(&nf_conntrack_lock);15601560 if (err == 0) {15611561- nf_conntrack_get(&ct->ct_general);15621562- spin_unlock_bh(&nf_conntrack_lock);15631561 nf_conntrack_eventmask_report((1 << IPCT_REPLY) |15641562 (1 << IPCT_ASSURED) |15651563 (1 << IPCT_HELPER) |···15641570 (1 << IPCT_MARK),15651571 ct, NETLINK_CB(skb).pid,15661572 nlmsg_report(nlh));15671567- nf_ct_put(ct);15681568- } else15691569- spin_unlock_bh(&nf_conntrack_lock);15701570-15711571- return err;15731573+ }15721574 }1573157515741574-out_unlock:15751575- spin_unlock_bh(&nf_conntrack_lock);15761576+ nf_ct_put(ct);15761577 return err;15771578}15781579
+32-8
net/netfilter/nf_queue.c
···203203 return status;204204}205205206206+#ifdef CONFIG_BRIDGE_NETFILTER207207+/* When called from bridge netfilter, skb->data must point to MAC header208208+ * before calling skb_gso_segment(). Else, original MAC header is lost209209+ * and segmented skbs will be sent to wrong destination.210210+ */211211+static void nf_bridge_adjust_skb_data(struct sk_buff *skb)212212+{213213+ if (skb->nf_bridge)214214+ __skb_push(skb, skb->network_header - skb->mac_header);215215+}216216+217217+static void nf_bridge_adjust_segmented_data(struct sk_buff *skb)218218+{219219+ if (skb->nf_bridge)220220+ __skb_pull(skb, skb->network_header - skb->mac_header);221221+}222222+#else223223+#define nf_bridge_adjust_skb_data(s) do {} while (0)224224+#define nf_bridge_adjust_segmented_data(s) do {} while (0)225225+#endif226226+206227int nf_queue(struct sk_buff *skb,207228 struct list_head *elem,208229 u_int8_t pf, unsigned int hook,···233212 unsigned int queuenum)234213{235214 struct sk_buff *segs;236236- int err;215215+ int err = -EINVAL;237216 unsigned int queued;238217239218 if (!skb_is_gso(skb))···249228 break;250229 }251230231231+ nf_bridge_adjust_skb_data(skb);252232 segs = skb_gso_segment(skb, 0);253233 /* Does not use PTR_ERR to limit the number of error codes that can be254234 * returned by nf_queue. For instance, callers rely on -ECANCELED to mean255235 * 'ignore this hook'.256236 */257237 if (IS_ERR(segs))258258- return -EINVAL;259259-238238+ goto out_err;260239 queued = 0;261240 err = 0;262241 do {263242 struct sk_buff *nskb = segs->next;264243265244 segs->next = NULL;266266- if (err == 0)245245+ if (err == 0) {246246+ nf_bridge_adjust_segmented_data(segs);267247 err = __nf_queue(segs, elem, pf, hook, indev,268248 outdev, okfn, queuenum);249249+ }269250 if (err == 0)270251 queued++;271252 else···275252 segs = nskb;276253 } while (segs);277254278278- /* also free orig skb if only some segments were queued */279279- if (unlikely(err && queued))280280- err = 0;281281- if (err == 0)255255+ if (queued) {282256 kfree_skb(skb);257257+ return 0;258258+ }259259+ out_err:260260+ nf_bridge_adjust_segmented_data(skb);283261 return err;284262}285263