tipc: remove source file port.c
[cascardo/linux.git] / net / tipc / socket.c
index 7e6240e..ea33eab 100644 (file)
@@ -57,6 +57,10 @@ static int tipc_release(struct socket *sock);
 static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags);
 static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p);
 static void tipc_sk_timeout(unsigned long ref);
+static int tipc_sk_publish(struct tipc_port *port, uint scope,
+                          struct tipc_name_seq const *seq);
+static int tipc_sk_withdraw(struct tipc_port *port, uint scope,
+                           struct tipc_name_seq const *seq);
 
 static const struct proto_ops packet_ops;
 static const struct proto_ops stream_ops;
@@ -138,6 +142,38 @@ static void reject_rx_queue(struct sock *sk)
        }
 }
 
+/* tipc_sk_peer_msg - verify if message was sent by connected port's peer
+ *
+ * Handles cases where the node's network address has changed from
+ * the default of <0.0.0> to its configured setting.
+ */
+static bool tipc_sk_peer_msg(struct tipc_sock *tsk, struct tipc_msg *msg)
+{
+       u32 peer_port = tipc_port_peerport(&tsk->port);
+       u32 orig_node;
+       u32 peer_node;
+
+       if (unlikely(!tsk->port.connected))
+               return false;
+
+       if (unlikely(msg_origport(msg) != peer_port))
+               return false;
+
+       orig_node = msg_orignode(msg);
+       peer_node = tipc_port_peernode(&tsk->port);
+
+       if (likely(orig_node == peer_node))
+               return true;
+
+       if (!orig_node && (peer_node == tipc_own_addr))
+               return true;
+
+       if (!peer_node && (orig_node == tipc_own_addr))
+               return true;
+
+       return false;
+}
+
 /**
  * tipc_sk_create - create a TIPC socket
  * @net: network namespace (must be default network)
@@ -356,7 +392,7 @@ static int tipc_release(struct socket *sock)
                }
        }
 
-       tipc_withdraw(port, 0, NULL);
+       tipc_sk_withdraw(port, 0, NULL);
        tipc_ref_discard(port->ref);
        k_cancel_timer(&port->timer);
        if (port->connected) {
@@ -407,7 +443,7 @@ static int tipc_bind(struct socket *sock, struct sockaddr *uaddr,
 
        lock_sock(sk);
        if (unlikely(!uaddr_len)) {
-               res = tipc_withdraw(&tsk->port, 0, NULL);
+               res = tipc_sk_withdraw(&tsk->port, 0, NULL);
                goto exit;
        }
 
@@ -435,8 +471,8 @@ static int tipc_bind(struct socket *sock, struct sockaddr *uaddr,
        }
 
        res = (addr->scope > 0) ?
-               tipc_publish(&tsk->port, addr->scope, &addr->addr.nameseq) :
-               tipc_withdraw(&tsk->port, -addr->scope, &addr->addr.nameseq);
+               tipc_sk_publish(&tsk->port, addr->scope, &addr->addr.nameseq) :
+               tipc_sk_withdraw(&tsk->port, -addr->scope, &addr->addr.nameseq);
 exit:
        release_sock(sk);
        return res;
@@ -663,7 +699,7 @@ static int tipc_sk_proto_rcv(struct tipc_sock *tsk, u32 *dnode,
        int conn_cong;
 
        /* Ignore if connection cannot be validated: */
-       if (!port->connected || !tipc_port_peer_msg(port, msg))
+       if (!tipc_sk_peer_msg(tsk, msg))
                goto exit;
 
        port->probing_state = TIPC_CONN_OK;
@@ -1444,7 +1480,7 @@ static int filter_connect(struct tipc_sock *tsk, struct sk_buff **buf)
        switch ((int)sock->state) {
        case SS_CONNECTED:
                /* Accept only connection-based messages sent by peer */
-               if (msg_connected(msg) && tipc_port_peer_msg(port, msg)) {
+               if (tipc_sk_peer_msg(tsk, msg)) {
                        if (unlikely(msg_errcode(msg))) {
                                sock->state = SS_DISCONNECTING;
                                port->connected = 0;
@@ -2027,6 +2063,60 @@ exit:
        tipc_sk_put(tsk);
 }
 
+static int tipc_sk_publish(struct tipc_port *port, uint scope,
+                          struct tipc_name_seq const *seq)
+{
+       struct publication *publ;
+       u32 key;
+
+       if (port->connected)
+               return -EINVAL;
+       key = port->ref + port->pub_count + 1;
+       if (key == port->ref)
+               return -EADDRINUSE;
+
+       publ = tipc_nametbl_publish(seq->type, seq->lower, seq->upper,
+                                   scope, port->ref, key);
+       if (unlikely(!publ))
+               return -EINVAL;
+
+       list_add(&publ->pport_list, &port->publications);
+       port->pub_count++;
+       port->published = 1;
+       return 0;
+}
+
+static int tipc_sk_withdraw(struct tipc_port *port, uint scope,
+                           struct tipc_name_seq const *seq)
+{
+       struct publication *publ;
+       struct publication *safe;
+       int rc = -EINVAL;
+
+       list_for_each_entry_safe(publ, safe, &port->publications, pport_list) {
+               if (seq) {
+                       if (publ->scope != scope)
+                               continue;
+                       if (publ->type != seq->type)
+                               continue;
+                       if (publ->lower != seq->lower)
+                               continue;
+                       if (publ->upper != seq->upper)
+                               break;
+                       tipc_nametbl_withdraw(publ->type, publ->lower,
+                                             publ->ref, publ->key);
+                       rc = 0;
+                       break;
+               }
+               tipc_nametbl_withdraw(publ->type, publ->lower,
+                                     publ->ref, publ->key);
+               rc = 0;
+       }
+       if (list_empty(&port->publications))
+               port->published = 0;
+       return rc;
+}
+
 static int tipc_sk_show(struct tipc_port *port, char *buf,
                        int len, int full_id)
 {