pts rule name              description
 ---- ---------------------- --------------------------------------------------
  2.7 DNS_FROM_AHBL_RHSBL    RBL: Envelope sender listed in dnsbl.ahbl.org
 -0.0 SPF_PASS               SPF: sender matches SPF record
 -1.9 BAYES_00               BODY: Bayes spam probability is 0 to 1%
                             [score: 0.0000]
Status: RO
X-Status: F
Content-Length: 1800

Signed-off-by: Andreas Schultz <[email protected]>
---
 gtp.c | 35 ++++++++++++++++++++++++++++-------
 1 file changed, 28 insertions(+), 7 deletions(-)

diff --git a/gtp.c b/gtp.c
index f569d62..e46638a 100644
--- a/gtp.c
+++ b/gtp.c
@@ -1178,24 +1178,45 @@ static int ipv4_pdp_add(struct net_device *dev, struct 
genl_info *info)
        }

        if (found) {
+               struct pdp_ctx *repl_pctx;
+
                if (info->nlhdr->nlmsg_flags & NLM_F_EXCL)
                        return -EEXIST;
-               if (info->nlhdr->nlmsg_flags & NLM_F_REPLACE)
-                       return -EOPNOTSUPP;

-               ipv4_pdp_fill(pctx, info);
+               repl_pctx = kmemdup(pctx, sizeof(struct pdp_ctx), GFP_KERNEL);
+               if (repl_pctx == NULL)
+                       return -ENOMEM;
+
+               ipv4_pdp_fill(repl_pctx, info);
+
+               /* only the SGSN can be changed */
+               if (pctx->af != repl_pctx->af ||
+                   pctx->gtp_version != repl_pctx->gtp_version ||
+                   memcpy(&pctx->u, &repl_pctx->u, sizeof(pctx->u) != 0)) {
+                       kfree(repl_pctx);
+                       return -EINVAL;
+               }
+
+               hlist_replace_rcu(&pctx->hlist_addr, &repl_pctx->hlist_addr);
+               hlist_replace_rcu(&pctx->hlist_tid, &repl_pctx->hlist_tid);

-               if (pctx->gtp_version == GTP_V0)
+               kfree_rcu(pctx, rcu_head);
+
+               if (repl_pctx->gtp_version == GTP_V0)
                        netdev_dbg(dev, "GTPv0-U: update tunnel id = %llx (pdp 
%p)\n",
-                                  pctx->u.v0.tid, pctx);
-               else if (pctx->gtp_version == GTP_V1)
+                                  repl_pctx->u.v0.tid, repl_pctx);
+               else if (repl_pctx->gtp_version == GTP_V1)
                        netdev_dbg(dev, "GTPv1-U: update tunnel id = %x/%x (pdp 
%p)\n",
-                                  pctx->u.v1.i_tei, pctx->u.v1.o_tei, pctx);
+                                  repl_pctx->u.v1.i_tei,
+                                  repl_pctx->u.v1.o_tei, repl_pctx);

                return 0;

        }

+       if (info->nlhdr->nlmsg_flags & NLM_F_REPLACE)
+               return -ENXIO;
+
        pctx = kmalloc(sizeof(struct pdp_ctx), GFP_KERNEL);
        if (pctx == NULL)
                return -ENOMEM;
-- 
2.7.4

Reply via email to