pespin has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/osmo-upf/+/41482?usp=email )


Change subject: Validate session remote CP F-SEID and use it to transmit 
session requests
......................................................................

Validate session remote CP F-SEID and use it to transmit session requests

Change-Id: Ifccd4d2b8d500c9928778400bb096baaa12c9a31
---
M include/osmocom/upf/pfcp_entity_peer.h
M src/osmo-upf/pfcp_entity_peer.c
M src/osmo-upf/up_endpoint.c
M src/osmo-upf/up_session.c
4 files changed, 155 insertions(+), 34 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/osmo-upf refs/changes/82/41482/1

diff --git a/include/osmocom/upf/pfcp_entity_peer.h 
b/include/osmocom/upf/pfcp_entity_peer.h
index d2727e5..ae771eb 100644
--- a/include/osmocom/upf/pfcp_entity_peer.h
+++ b/include/osmocom/upf/pfcp_entity_peer.h
@@ -73,9 +73,12 @@

 char *pfcp_entity_peer_remote_addr_str(struct pfcp_entity_peer *entity_peer);

-struct osmo_pfcp_msg *pfcp_entity_peer_init_tx(struct pfcp_entity_peer 
*entity_peer,
-                                              struct osmo_pfcp_msg 
*in_reply_to,
-                                              enum osmo_pfcp_message_type 
message_type);
+struct osmo_pfcp_msg *pfcp_entity_peer_init_tx_req(struct pfcp_entity_peer 
*peer,
+                                                  const struct osmo_sockaddr 
*dst_addr,
+                                                  enum osmo_pfcp_message_type 
message_type);
+struct osmo_pfcp_msg *pfcp_entity_peer_init_tx_resp(struct pfcp_entity_peer 
*peer,
+                                                   struct osmo_pfcp_msg 
*in_reply_to,
+                                                   enum osmo_pfcp_message_type 
message_type);

 struct up_session *pfcp_entity_peer_find_up_session_by_up_seid(struct 
pfcp_entity_peer *entity_peer, uint64_t up_seid);
 struct up_session *pfcp_entity_peer_find_up_session_by_cp_f_seid(struct 
pfcp_entity_peer *entity_peer, const struct osmo_pfcp_ie_f_seid *cp_f_seid);
diff --git a/src/osmo-upf/pfcp_entity_peer.c b/src/osmo-upf/pfcp_entity_peer.c
index db02f78..7b8c28d 100644
--- a/src/osmo-upf/pfcp_entity_peer.c
+++ b/src/osmo-upf/pfcp_entity_peer.c
@@ -194,15 +194,22 @@
        m->ctx.peer_use_token = NULL;
 }

-struct osmo_pfcp_msg *pfcp_entity_peer_init_tx(struct pfcp_entity_peer *peer,
-                                              struct osmo_pfcp_msg 
*in_reply_to,
-                                              enum osmo_pfcp_message_type 
message_type)
+struct osmo_pfcp_msg *pfcp_entity_peer_init_tx_req(struct pfcp_entity_peer 
*peer,
+                                                  const struct osmo_sockaddr 
*dst_addr,
+                                                  enum osmo_pfcp_message_type 
message_type)
 {
        struct osmo_pfcp_msg *tx;
-       if (in_reply_to)
-               tx = osmo_pfcp_msg_alloc_tx_resp(OTC_SELECT, in_reply_to, 
message_type);
-       else
-               tx = osmo_pfcp_msg_alloc_tx_req(OTC_SELECT, &peer->remote_addr, 
message_type);
+       tx = osmo_pfcp_msg_alloc_tx_req(OTC_SELECT, dst_addr, message_type);
+       pfcp_entity_peer_set_msg_ctx(peer, tx);
+       return tx;
+}
+
+struct osmo_pfcp_msg *pfcp_entity_peer_init_tx_resp(struct pfcp_entity_peer 
*peer,
+                                                   struct osmo_pfcp_msg 
*in_reply_to,
+                                                   enum osmo_pfcp_message_type 
message_type)
+{
+       struct osmo_pfcp_msg *tx;
+       tx = osmo_pfcp_msg_alloc_tx_resp(OTC_SELECT, in_reply_to, message_type);
        pfcp_entity_peer_set_msg_ctx(peer, tx);
        return tx;
 }
@@ -211,7 +218,7 @@
 {
        struct osmo_pfcp_msg *resp;

-       resp = pfcp_entity_peer_init_tx(entity_peer, m, 
OSMO_PFCP_MSGT_ASSOC_SETUP_RESP);
+       resp = pfcp_entity_peer_init_tx_resp(entity_peer, m, 
OSMO_PFCP_MSGT_ASSOC_SETUP_RESP);

        resp->ies.assoc_setup_resp = (struct osmo_pfcp_msg_assoc_setup_resp) {
                .cause = cause,
@@ -232,7 +239,7 @@
 {
        struct osmo_pfcp_msg *resp;

-       resp = pfcp_entity_peer_init_tx(peer, m, 
OSMO_PFCP_MSGT_ASSOC_RELEASE_RESP);
+       resp = pfcp_entity_peer_init_tx_resp(peer, m, 
OSMO_PFCP_MSGT_ASSOC_RELEASE_RESP);

        resp->ies.assoc_release_resp = (struct 
osmo_pfcp_msg_assoc_release_resp) {
                .cause = cause,
@@ -307,7 +314,9 @@
 {
        enum osmo_pfcp_cause cause = OSMO_PFCP_CAUSE_REQUEST_ACCEPTED;
        struct osmo_pfcp_msg *resp;
-       struct up_session *session = 
pfcp_entity_peer_find_up_session_by_cp_f_seid(peer, 
&m->ies.session_est_req.cp_f_seid);
+       struct up_session *session;
+
+       session = pfcp_entity_peer_find_up_session_by_cp_f_seid(peer, 
&m->ies.session_est_req.cp_f_seid);
        if (!session)
                session = up_session_alloc(peer, 
&m->ies.session_est_req.cp_f_seid);
        if (!session) {
@@ -324,7 +333,7 @@
        return;

 nack_response:
-       resp = pfcp_entity_peer_init_tx(peer, m, 
OSMO_PFCP_MSGT_SESSION_EST_RESP);
+       resp = pfcp_entity_peer_init_tx_resp(peer, m, 
OSMO_PFCP_MSGT_SESSION_EST_RESP);
        resp->h.seid = m->ies.session_est_req.cp_f_seid.seid;
        resp->h.seid_present = true;
        resp->ies.session_est_resp = (struct osmo_pfcp_msg_session_est_resp){
diff --git a/src/osmo-upf/up_endpoint.c b/src/osmo-upf/up_endpoint.c
index f53dc50..8161042 100644
--- a/src/osmo-upf/up_endpoint.c
+++ b/src/osmo-upf/up_endpoint.c
@@ -166,61 +166,137 @@
                              OSMO_PFCP_CAUSE_SERVICE_NOT_SUPPORTED);
 }

+/* Validate received F-SEID IP address */
+static enum osmo_pfcp_cause up_ep_validate_cp_f_seid_addr(const struct 
up_endpoint *up_ep,
+                                                         const struct 
osmo_pfcp_ie_f_seid *f_seid)
+{
+       const struct osmo_sockaddr *local_addr;
+
+       OSMO_ASSERT(up_ep);
+       OSMO_ASSERT(f_seid)
+
+       /* Validate the F-SEID contains an IP address we can send requests to 
later on: */
+       local_addr = osmo_pfcp_endpoint_get_local_addr(up_ep->pfcp_ep);
+       OSMO_ASSERT(local_addr);
+       switch (local_addr->u.sa.sa_family) {
+       case AF_INET:
+               if (!f_seid->ip_addr.v4_present)
+                       return OSMO_PFCP_CAUSE_MANDATORY_IE_INCORRECT;
+               break;
+       case AF_INET6:
+               if (!f_seid->ip_addr.v4_present &&
+                   !f_seid->ip_addr.v6_present)
+                       return OSMO_PFCP_CAUSE_MANDATORY_IE_INCORRECT;
+               break;
+       default:
+               OSMO_ASSERT(0);
+       }
+       return OSMO_PFCP_CAUSE_REQUEST_ACCEPTED;
+}
+
 static void up_ep_rx_session_est_req(struct up_endpoint *up_ep, const struct 
osmo_pfcp_msg *m)
 {
-       if (!m->ctx.peer_fi) {
-               struct osmo_pfcp_msg *tx;
-               OSMO_LOG_PFCP_MSG(m, LOGL_ERROR, "Peer is not associated, 
cannot establish session\n");
-               tx = osmo_pfcp_msg_alloc_tx_resp(OTC_SELECT, m, 
OSMO_PFCP_MSGT_SESSION_EST_RESP);
-               tx->ies.session_est_resp.cause = 
OSMO_PFCP_CAUSE_NO_ESTABLISHED_PFCP_ASSOC;
-               osmo_pfcp_endpoint_tx(up_ep->pfcp_ep, tx);
-               return;
+       struct osmo_pfcp_msg *resp;
+       enum osmo_pfcp_cause cause;
+
+       cause = up_ep_validate_cp_f_seid_addr(up_ep, 
&m->ies.session_est_req.cp_f_seid);
+       if (cause != OSMO_PFCP_CAUSE_REQUEST_ACCEPTED) {
+               OSMO_LOG_PFCP_MSG(m, LOGL_ERROR, "Remote CP F-SEID IP address 
invalid\n");
+               goto nack_response;
        }
+
+       if (!m->ctx.peer_fi) {
+               OSMO_LOG_PFCP_MSG(m, LOGL_ERROR, "Peer is not associated, 
cannot establish session\n");
+               cause = OSMO_PFCP_CAUSE_NO_ESTABLISHED_PFCP_ASSOC;
+               goto nack_response;
+       }
+
        osmo_fsm_inst_dispatch(m->ctx.peer_fi, 
PFCP_ENTITY_PEER_EV_RX_SESSION_EST_REQ, (void *)m);
+       return;
+
+nack_response:
+       resp = osmo_pfcp_msg_alloc_tx_resp(OTC_SELECT, m, 
OSMO_PFCP_MSGT_SESSION_EST_RESP);
+       resp->ies.session_est_resp.cause = cause;
+       osmo_pfcp_endpoint_tx(up_ep->pfcp_ep, resp);
 }

 static void up_ep_rx_session_mod_req(struct up_endpoint *up_ep, const struct 
osmo_pfcp_msg *m)
 {
+       struct osmo_pfcp_msg *resp;
+       enum osmo_pfcp_cause cause;
+
+       if (m->ies.session_mod_req.cp_f_seid_present) {
+               cause = up_ep_validate_cp_f_seid_addr(up_ep, 
&m->ies.session_mod_req.cp_f_seid);
+               if (cause != OSMO_PFCP_CAUSE_REQUEST_ACCEPTED) {
+                       OSMO_LOG_PFCP_MSG(m, LOGL_ERROR, "Remote CP F-SEID IP 
address invalid\n");
+                       goto nack_response;
+               }
+       }
+
        if (!m->ctx.session_fi) {
                /* Session not found. */
-               struct osmo_pfcp_msg *tx;
-               tx = osmo_pfcp_msg_alloc_tx_resp(OTC_SELECT, m, 
OSMO_PFCP_MSGT_SESSION_MOD_RESP);
                if (!m->ctx.peer_fi) {
                        /* Not even the peer is associated. */
                        OSMO_LOG_PFCP_MSG(m, LOGL_ERROR, "Peer is not 
associated, cannot modify session\n");
-                       tx->ies.session_mod_resp.cause = 
OSMO_PFCP_CAUSE_NO_ESTABLISHED_PFCP_ASSOC;
+                       cause = OSMO_PFCP_CAUSE_NO_ESTABLISHED_PFCP_ASSOC;
+                       goto nack_response;
                } else {
                        OSMO_LOG_PFCP_MSG(m, LOGL_ERROR,
                                          "No established session with 
SEID=0x%"PRIx64", cannot modify\n",
                                          m->h.seid);
-                       tx->ies.session_mod_resp.cause = 
OSMO_PFCP_CAUSE_SESSION_CTX_NOT_FOUND;
+                       cause = OSMO_PFCP_CAUSE_SESSION_CTX_NOT_FOUND;
+                       goto nack_response;
                }
-               osmo_pfcp_endpoint_tx(up_ep->pfcp_ep, tx);
-               return;
        }
+
        osmo_fsm_inst_dispatch(m->ctx.session_fi, 
UP_SESSION_EV_RX_SESSION_MOD_REQ, (void *)m);
+       return;
+
+nack_response:
+       resp = osmo_pfcp_msg_alloc_tx_resp(OTC_SELECT, m, 
OSMO_PFCP_MSGT_SESSION_MOD_RESP);
+       resp->ies.session_mod_resp.cause = cause;
+       osmo_pfcp_endpoint_tx(up_ep->pfcp_ep, resp);
 }

 static void up_ep_rx_session_del_req(struct up_endpoint *up_ep, const struct 
osmo_pfcp_msg *m)
 {
+       struct osmo_pfcp_msg *resp;
+       enum osmo_pfcp_cause cause;
+
+#if 0
+       /* Can be enabled once libosmo-pfcp struct 
osmo_pfcp_msg_session_del_req supports the IE: */
+       if (m->ies.session_del_req.cp_f_seid_present) {
+               cause = up_ep_validate_cp_f_seid_addr(up_ep, 
&m->ies.session_mod_req.cp_f_seid);
+               if (cause != OSMO_PFCP_CAUSE_REQUEST_ACCEPTED) {
+                       OSMO_LOG_PFCP_MSG(m, LOGL_ERROR, "Remote CP F-SEID IP 
address invalid\n");
+                       goto nack_response;
+               }
+       }
+#endif
+
        if (!m->ctx.session_fi) {
                /* Session not found. */
-               struct osmo_pfcp_msg *tx;
-               tx = osmo_pfcp_msg_alloc_tx_resp(OTC_SELECT, m, 
OSMO_PFCP_MSGT_SESSION_DEL_RESP);
                if (!m->ctx.peer_fi) {
                        /* Not even the peer is associated. */
                        OSMO_LOG_PFCP_MSG(m, LOGL_ERROR, "Peer is not 
associated, cannot delete session\n");
-                       tx->ies.session_del_resp.cause = 
OSMO_PFCP_CAUSE_NO_ESTABLISHED_PFCP_ASSOC;
+                       cause = OSMO_PFCP_CAUSE_NO_ESTABLISHED_PFCP_ASSOC;
+                       goto nack_response;
                } else {
                        OSMO_LOG_PFCP_MSG(m, LOGL_ERROR,
                                          "No established session with 
SEID=0x%"PRIx64", cannot delete\n",
                                          m->h.seid);
-                       tx->ies.session_del_resp.cause = 
OSMO_PFCP_CAUSE_SESSION_CTX_NOT_FOUND;
+                       cause = OSMO_PFCP_CAUSE_SESSION_CTX_NOT_FOUND;
+                       goto nack_response;
                }
-               osmo_pfcp_endpoint_tx(up_ep->pfcp_ep, tx);
-               return;
        }
+
        osmo_fsm_inst_dispatch(m->ctx.session_fi, 
UP_SESSION_EV_RX_SESSION_DEL_REQ, (void *)m);
+       return;
+
+nack_response:
+       resp = osmo_pfcp_msg_alloc_tx_resp(OTC_SELECT, m, 
OSMO_PFCP_MSGT_SESSION_DEL_RESP);
+       resp->ies.session_del_resp.cause = cause;
+       osmo_pfcp_endpoint_tx(up_ep->pfcp_ep, resp);
 }

 static void up_ep_rx_session_rep_req(struct up_endpoint *up_ep, const struct 
osmo_pfcp_msg *m)
diff --git a/src/osmo-upf/up_session.c b/src/osmo-upf/up_session.c
index 5f406d5..9693745 100644
--- a/src/osmo-upf/up_session.c
+++ b/src/osmo-upf/up_session.c
@@ -90,10 +90,43 @@
        return 1;
 }

+/* Return as dst IP address the IP address from remote's CP F-SEID that matches
+ * our local endpoint configuration.
+ * Asserts regarding cp_f_seid are validated during session 
establishment/modification/deletion,
+ * see pfcp_entityt_peer_validate_cp_f_seid(). */
+static const struct osmo_sockaddr *up_session_req_dst_addr(const struct 
up_session *session)
+{
+       const struct osmo_sockaddr *src_addr = 
osmo_pfcp_endpoint_get_local_addr(session->entity_peer->node_peer->up_endpoint->pfcp_ep);
+       switch (src_addr->u.sa.sa_family) {
+       case AF_INET:
+               OSMO_ASSERT(session->cp_f_seid.ip_addr.v4_present);
+               return &session->cp_f_seid.ip_addr.v4;
+       case AF_INET6:
+               if (session->cp_f_seid.ip_addr.v6_present)
+                       return &session->cp_f_seid.ip_addr.v6;
+               if (session->cp_f_seid.ip_addr.v4_present)
+                       return &session->cp_f_seid.ip_addr.v4;
+               OSMO_ASSERT(0);
+               break;
+       default:
+               OSMO_ASSERT(0);
+               break;
+       }
+       return NULL;
+}
+
 struct osmo_pfcp_msg *up_session_init_tx(struct up_session *session, struct 
osmo_pfcp_msg *in_reply_to,
                                         enum osmo_pfcp_message_type 
message_type)
 {
-       struct osmo_pfcp_msg *tx = 
pfcp_entity_peer_init_tx(session->entity_peer, in_reply_to, message_type);
+       struct osmo_pfcp_msg *tx;
+       if (in_reply_to) {
+               /* Use req src IP address as resp dst IP address: */
+               tx = pfcp_entity_peer_init_tx_resp(session->entity_peer, 
in_reply_to, message_type);
+       } else {
+               const struct osmo_sockaddr *dst_addr = 
up_session_req_dst_addr(session);
+               /* Use IP address from remote's CP F-SEID as dst IP address: */
+               tx = pfcp_entity_peer_init_tx_req(session->entity_peer, 
dst_addr, message_type);
+       }
        tx->h.seid = session->cp_f_seid.seid;
        tx->h.seid_present = true;
        up_session_set_msg_ctx(session, tx);

--
To view, visit https://gerrit.osmocom.org/c/osmo-upf/+/41482?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings?usp=email

Gerrit-MessageType: newchange
Gerrit-Project: osmo-upf
Gerrit-Branch: master
Gerrit-Change-Id: Ifccd4d2b8d500c9928778400bb096baaa12c9a31
Gerrit-Change-Number: 41482
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <[email protected]>

Reply via email to