diff options
Diffstat (limited to 'net/tipc/socket.c')
-rw-r--r-- | net/tipc/socket.c | 102 |
1 files changed, 96 insertions, 6 deletions
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 7e6240e41e69..ea33eab4fb9d 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -57,6 +57,10 @@ static int tipc_release(struct socket *sock); | |||
57 | static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags); | 57 | static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags); |
58 | static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p); | 58 | static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p); |
59 | static void tipc_sk_timeout(unsigned long ref); | 59 | static void tipc_sk_timeout(unsigned long ref); |
60 | static int tipc_sk_publish(struct tipc_port *port, uint scope, | ||
61 | struct tipc_name_seq const *seq); | ||
62 | static int tipc_sk_withdraw(struct tipc_port *port, uint scope, | ||
63 | struct tipc_name_seq const *seq); | ||
60 | 64 | ||
61 | static const struct proto_ops packet_ops; | 65 | static const struct proto_ops packet_ops; |
62 | static const struct proto_ops stream_ops; | 66 | static const struct proto_ops stream_ops; |
@@ -138,6 +142,38 @@ static void reject_rx_queue(struct sock *sk) | |||
138 | } | 142 | } |
139 | } | 143 | } |
140 | 144 | ||
145 | /* tipc_sk_peer_msg - verify if message was sent by connected port's peer | ||
146 | * | ||
147 | * Handles cases where the node's network address has changed from | ||
148 | * the default of <0.0.0> to its configured setting. | ||
149 | */ | ||
150 | static bool tipc_sk_peer_msg(struct tipc_sock *tsk, struct tipc_msg *msg) | ||
151 | { | ||
152 | u32 peer_port = tipc_port_peerport(&tsk->port); | ||
153 | u32 orig_node; | ||
154 | u32 peer_node; | ||
155 | |||
156 | if (unlikely(!tsk->port.connected)) | ||
157 | return false; | ||
158 | |||
159 | if (unlikely(msg_origport(msg) != peer_port)) | ||
160 | return false; | ||
161 | |||
162 | orig_node = msg_orignode(msg); | ||
163 | peer_node = tipc_port_peernode(&tsk->port); | ||
164 | |||
165 | if (likely(orig_node == peer_node)) | ||
166 | return true; | ||
167 | |||
168 | if (!orig_node && (peer_node == tipc_own_addr)) | ||
169 | return true; | ||
170 | |||
171 | if (!peer_node && (orig_node == tipc_own_addr)) | ||
172 | return true; | ||
173 | |||
174 | return false; | ||
175 | } | ||
176 | |||
141 | /** | 177 | /** |
142 | * tipc_sk_create - create a TIPC socket | 178 | * tipc_sk_create - create a TIPC socket |
143 | * @net: network namespace (must be default network) | 179 | * @net: network namespace (must be default network) |
@@ -356,7 +392,7 @@ static int tipc_release(struct socket *sock) | |||
356 | } | 392 | } |
357 | } | 393 | } |
358 | 394 | ||
359 | tipc_withdraw(port, 0, NULL); | 395 | tipc_sk_withdraw(port, 0, NULL); |
360 | tipc_ref_discard(port->ref); | 396 | tipc_ref_discard(port->ref); |
361 | k_cancel_timer(&port->timer); | 397 | k_cancel_timer(&port->timer); |
362 | if (port->connected) { | 398 | if (port->connected) { |
@@ -407,7 +443,7 @@ static int tipc_bind(struct socket *sock, struct sockaddr *uaddr, | |||
407 | 443 | ||
408 | lock_sock(sk); | 444 | lock_sock(sk); |
409 | if (unlikely(!uaddr_len)) { | 445 | if (unlikely(!uaddr_len)) { |
410 | res = tipc_withdraw(&tsk->port, 0, NULL); | 446 | res = tipc_sk_withdraw(&tsk->port, 0, NULL); |
411 | goto exit; | 447 | goto exit; |
412 | } | 448 | } |
413 | 449 | ||
@@ -435,8 +471,8 @@ static int tipc_bind(struct socket *sock, struct sockaddr *uaddr, | |||
435 | } | 471 | } |
436 | 472 | ||
437 | res = (addr->scope > 0) ? | 473 | res = (addr->scope > 0) ? |
438 | tipc_publish(&tsk->port, addr->scope, &addr->addr.nameseq) : | 474 | tipc_sk_publish(&tsk->port, addr->scope, &addr->addr.nameseq) : |
439 | tipc_withdraw(&tsk->port, -addr->scope, &addr->addr.nameseq); | 475 | tipc_sk_withdraw(&tsk->port, -addr->scope, &addr->addr.nameseq); |
440 | exit: | 476 | exit: |
441 | release_sock(sk); | 477 | release_sock(sk); |
442 | return res; | 478 | return res; |
@@ -663,7 +699,7 @@ static int tipc_sk_proto_rcv(struct tipc_sock *tsk, u32 *dnode, | |||
663 | int conn_cong; | 699 | int conn_cong; |
664 | 700 | ||
665 | /* Ignore if connection cannot be validated: */ | 701 | /* Ignore if connection cannot be validated: */ |
666 | if (!port->connected || !tipc_port_peer_msg(port, msg)) | 702 | if (!tipc_sk_peer_msg(tsk, msg)) |
667 | goto exit; | 703 | goto exit; |
668 | 704 | ||
669 | port->probing_state = TIPC_CONN_OK; | 705 | port->probing_state = TIPC_CONN_OK; |
@@ -1444,7 +1480,7 @@ static int filter_connect(struct tipc_sock *tsk, struct sk_buff **buf) | |||
1444 | switch ((int)sock->state) { | 1480 | switch ((int)sock->state) { |
1445 | case SS_CONNECTED: | 1481 | case SS_CONNECTED: |
1446 | /* Accept only connection-based messages sent by peer */ | 1482 | /* Accept only connection-based messages sent by peer */ |
1447 | if (msg_connected(msg) && tipc_port_peer_msg(port, msg)) { | 1483 | if (tipc_sk_peer_msg(tsk, msg)) { |
1448 | if (unlikely(msg_errcode(msg))) { | 1484 | if (unlikely(msg_errcode(msg))) { |
1449 | sock->state = SS_DISCONNECTING; | 1485 | sock->state = SS_DISCONNECTING; |
1450 | port->connected = 0; | 1486 | port->connected = 0; |
@@ -2027,6 +2063,60 @@ exit: | |||
2027 | tipc_sk_put(tsk); | 2063 | tipc_sk_put(tsk); |
2028 | } | 2064 | } |
2029 | 2065 | ||
2066 | static int tipc_sk_publish(struct tipc_port *port, uint scope, | ||
2067 | struct tipc_name_seq const *seq) | ||
2068 | { | ||
2069 | struct publication *publ; | ||
2070 | u32 key; | ||
2071 | |||
2072 | if (port->connected) | ||
2073 | return -EINVAL; | ||
2074 | key = port->ref + port->pub_count + 1; | ||
2075 | if (key == port->ref) | ||
2076 | return -EADDRINUSE; | ||
2077 | |||
2078 | publ = tipc_nametbl_publish(seq->type, seq->lower, seq->upper, | ||
2079 | scope, port->ref, key); | ||
2080 | if (unlikely(!publ)) | ||
2081 | return -EINVAL; | ||
2082 | |||
2083 | list_add(&publ->pport_list, &port->publications); | ||
2084 | port->pub_count++; | ||
2085 | port->published = 1; | ||
2086 | return 0; | ||
2087 | } | ||
2088 | |||
2089 | static int tipc_sk_withdraw(struct tipc_port *port, uint scope, | ||
2090 | struct tipc_name_seq const *seq) | ||
2091 | { | ||
2092 | struct publication *publ; | ||
2093 | struct publication *safe; | ||
2094 | int rc = -EINVAL; | ||
2095 | |||
2096 | list_for_each_entry_safe(publ, safe, &port->publications, pport_list) { | ||
2097 | if (seq) { | ||
2098 | if (publ->scope != scope) | ||
2099 | continue; | ||
2100 | if (publ->type != seq->type) | ||
2101 | continue; | ||
2102 | if (publ->lower != seq->lower) | ||
2103 | continue; | ||
2104 | if (publ->upper != seq->upper) | ||
2105 | break; | ||
2106 | tipc_nametbl_withdraw(publ->type, publ->lower, | ||
2107 | publ->ref, publ->key); | ||
2108 | rc = 0; | ||
2109 | break; | ||
2110 | } | ||
2111 | tipc_nametbl_withdraw(publ->type, publ->lower, | ||
2112 | publ->ref, publ->key); | ||
2113 | rc = 0; | ||
2114 | } | ||
2115 | if (list_empty(&port->publications)) | ||
2116 | port->published = 0; | ||
2117 | return rc; | ||
2118 | } | ||
2119 | |||
2030 | static int tipc_sk_show(struct tipc_port *port, char *buf, | 2120 | static int tipc_sk_show(struct tipc_port *port, char *buf, |
2031 | int len, int full_id) | 2121 | int len, int full_id) |
2032 | { | 2122 | { |