blob: 01396dd1c899b0cbb61e4a40ad5d69b9c0a2142d [file] [log] [blame]
Per Lidenb97bf3f2006-01-02 19:04:38 +01001/*
2 * net/tipc/name_table.c: TIPC name table code
YOSHIFUJI Hideakic4307282007-02-09 23:25:21 +09003 *
Jon Maloye50e73e2018-03-15 16:48:55 +01004 * Copyright (c) 2000-2006, 2014-2018, Ericsson AB
Ying Xue993bfe52014-12-02 15:00:24 +08005 * Copyright (c) 2004-2008, 2010-2014, Wind River Systems
Jon Maloy998d3902021-03-16 22:06:08 -04006 * Copyright (c) 2020-2021, Red Hat Inc
Per Lidenb97bf3f2006-01-02 19:04:38 +01007 * All rights reserved.
8 *
Per Liden9ea1fd32006-01-11 13:30:43 +01009 * Redistribution and use in source and binary forms, with or without
Per Lidenb97bf3f2006-01-02 19:04:38 +010010 * modification, are permitted provided that the following conditions are met:
11 *
Per Liden9ea1fd32006-01-11 13:30:43 +010012 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the names of the copyright holders nor the names of its
18 * contributors may be used to endorse or promote products derived from
19 * this software without specific prior written permission.
Per Lidenb97bf3f2006-01-02 19:04:38 +010020 *
Per Liden9ea1fd32006-01-11 13:30:43 +010021 * Alternatively, this software may be distributed under the terms of the
22 * GNU General Public License ("GPL") version 2 as published by the Free
23 * Software Foundation.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
Per Lidenb97bf3f2006-01-02 19:04:38 +010035 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
Ying Xue4ac1c8d2015-01-09 15:27:09 +080038#include <net/sock.h>
Tuong Lien41b416f2019-11-21 15:34:58 +070039#include <linux/list_sort.h>
Tuong Liend5162f32019-12-10 15:21:02 +070040#include <linux/rbtree_augmented.h>
Per Lidenb97bf3f2006-01-02 19:04:38 +010041#include "core.h"
Richard Alpe22ae7cf2015-02-09 09:50:18 +010042#include "netlink.h"
Per Lidenb97bf3f2006-01-02 19:04:38 +010043#include "name_table.h"
44#include "name_distr.h"
Per Lidenb97bf3f2006-01-02 19:04:38 +010045#include "subscr.h"
Ying Xue1da46562015-01-09 15:27:07 +080046#include "bcast.h"
Richard Alpe22ae7cf2015-02-09 09:50:18 +010047#include "addr.h"
Jon Paul Maloy1d7e1c22015-11-19 14:30:42 -050048#include "node.h"
Jon Maloy75da2162017-10-13 11:04:23 +020049#include "group.h"
Per Lidenb97bf3f2006-01-02 19:04:38 +010050
51/**
Jon Maloy218527f2018-03-29 23:20:41 +020052 * struct service_range - container for all bindings of a service range
53 * @lower: service range lower bound
54 * @upper: service range upper bound
55 * @tree_node: member of service range RB tree
Tuong Liend5162f32019-12-10 15:21:02 +070056 * @max: largest 'upper' in this node subtree
Jon Maloy218527f2018-03-29 23:20:41 +020057 * @local_publ: list of identical publications made from this node
58 * Used by closest_first lookup and multicast lookup algorithm
59 * @all_publ: all publications identical to this one, whatever node and scope
60 * Used by round-robin lookup algorithm
Per Lidenb97bf3f2006-01-02 19:04:38 +010061 */
Jon Maloy218527f2018-03-29 23:20:41 +020062struct service_range {
63 u32 lower;
64 u32 upper;
65 struct rb_node tree_node;
Tuong Liend5162f32019-12-10 15:21:02 +070066 u32 max;
Jon Maloye50e73e2018-03-15 16:48:55 +010067 struct list_head local_publ;
68 struct list_head all_publ;
Per Lidenb97bf3f2006-01-02 19:04:38 +010069};
70
YOSHIFUJI Hideakic4307282007-02-09 23:25:21 +090071/**
Jon Maloy218527f2018-03-29 23:20:41 +020072 * struct tipc_service - container for all published instances of a service type
73 * @type: 32 bit 'type' value for service
Tuong Lien41b416f2019-11-21 15:34:58 +070074 * @publ_cnt: increasing counter for publications in this service
Jon Maloy218527f2018-03-29 23:20:41 +020075 * @ranges: rb tree containing all service ranges for this service
76 * @service_list: links to adjacent name ranges in hash chain
77 * @subscriptions: list of subscriptions for this service type
78 * @lock: spinlock controlling access to pertaining service ranges/publications
Ying Xue97ede292014-12-02 15:00:30 +080079 * @rcu: RCU callback head used for deferred freeing
Per Lidenb97bf3f2006-01-02 19:04:38 +010080 */
Jon Maloy218527f2018-03-29 23:20:41 +020081struct tipc_service {
Per Lidenb97bf3f2006-01-02 19:04:38 +010082 u32 type;
Tuong Lien41b416f2019-11-21 15:34:58 +070083 u32 publ_cnt;
Jon Maloy218527f2018-03-29 23:20:41 +020084 struct rb_root ranges;
85 struct hlist_node service_list;
Per Lidenb97bf3f2006-01-02 19:04:38 +010086 struct list_head subscriptions;
Jon Maloy218527f2018-03-29 23:20:41 +020087 spinlock_t lock; /* Covers service range list */
Ying Xue97ede292014-12-02 15:00:30 +080088 struct rcu_head rcu;
Per Lidenb97bf3f2006-01-02 19:04:38 +010089};
90
Tuong Liend5162f32019-12-10 15:21:02 +070091#define service_range_upper(sr) ((sr)->upper)
92RB_DECLARE_CALLBACKS_MAX(static, sr_callbacks,
93 struct service_range, tree_node, u32, max,
94 service_range_upper)
95
96#define service_range_entry(rbtree_node) \
97 (container_of(rbtree_node, struct service_range, tree_node))
98
99#define service_range_overlap(sr, start, end) \
100 ((sr)->lower <= (end) && (sr)->upper >= (start))
101
102/**
103 * service_range_foreach_match - iterate over tipc service rbtree for each
104 * range match
105 * @sr: the service range pointer as a loop cursor
106 * @sc: the pointer to tipc service which holds the service range rbtree
Randy Dunlap5c5d6792020-11-29 10:32:46 -0800107 * @start: beginning of the search range (end >= start) for matching
108 * @end: end of the search range (end >= start) for matching
Tuong Liend5162f32019-12-10 15:21:02 +0700109 */
110#define service_range_foreach_match(sr, sc, start, end) \
111 for (sr = service_range_match_first((sc)->ranges.rb_node, \
112 start, \
113 end); \
114 sr; \
115 sr = service_range_match_next(&(sr)->tree_node, \
116 start, \
117 end))
118
119/**
120 * service_range_match_first - find first service range matching a range
121 * @n: the root node of service range rbtree for searching
Randy Dunlap5c5d6792020-11-29 10:32:46 -0800122 * @start: beginning of the search range (end >= start) for matching
123 * @end: end of the search range (end >= start) for matching
Tuong Liend5162f32019-12-10 15:21:02 +0700124 *
125 * Return: the leftmost service range node in the rbtree that overlaps the
126 * specific range if any. Otherwise, returns NULL.
127 */
128static struct service_range *service_range_match_first(struct rb_node *n,
129 u32 start, u32 end)
130{
131 struct service_range *sr;
132 struct rb_node *l, *r;
133
134 /* Non overlaps in tree at all? */
135 if (!n || service_range_entry(n)->max < start)
136 return NULL;
137
138 while (n) {
139 l = n->rb_left;
140 if (l && service_range_entry(l)->max >= start) {
141 /* A leftmost overlap range node must be one in the left
142 * subtree. If not, it has lower > end, then nodes on
143 * the right side cannot satisfy the condition either.
144 */
145 n = l;
146 continue;
147 }
148
149 /* No one in the left subtree can match, return if this node is
150 * an overlap i.e. leftmost.
151 */
152 sr = service_range_entry(n);
153 if (service_range_overlap(sr, start, end))
154 return sr;
155
156 /* Ok, try to lookup on the right side */
157 r = n->rb_right;
158 if (sr->lower <= end &&
159 r && service_range_entry(r)->max >= start) {
160 n = r;
161 continue;
162 }
163 break;
164 }
165
166 return NULL;
167}
168
169/**
170 * service_range_match_next - find next service range matching a range
171 * @n: a node in service range rbtree from which the searching starts
Randy Dunlap5c5d6792020-11-29 10:32:46 -0800172 * @start: beginning of the search range (end >= start) for matching
173 * @end: end of the search range (end >= start) for matching
Tuong Liend5162f32019-12-10 15:21:02 +0700174 *
175 * Return: the next service range node to the given node in the rbtree that
176 * overlaps the specific range if any. Otherwise, returns NULL.
177 */
178static struct service_range *service_range_match_next(struct rb_node *n,
179 u32 start, u32 end)
180{
181 struct service_range *sr;
182 struct rb_node *p, *r;
183
184 while (n) {
185 r = n->rb_right;
186 if (r && service_range_entry(r)->max >= start)
187 /* A next overlap range node must be one in the right
188 * subtree. If not, it has lower > end, then any next
189 * successor (- an ancestor) of this node cannot
190 * satisfy the condition either.
191 */
192 return service_range_match_first(r, start, end);
193
194 /* No one in the right subtree can match, go up to find an
195 * ancestor of this node which is parent of a left-hand child.
196 */
197 while ((p = rb_parent(n)) && n == p->rb_right)
198 n = p;
199 if (!p)
200 break;
201
202 /* Return if this ancestor is an overlap */
203 sr = service_range_entry(p);
204 if (service_range_overlap(sr, start, end))
205 return sr;
206
207 /* Ok, try to lookup more from this ancestor */
208 if (sr->lower <= end) {
209 n = p;
210 continue;
211 }
212 break;
213 }
214
215 return NULL;
216}
217
Sam Ravnborg05790c62006-03-20 22:37:04 -0800218static int hash(int x)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100219{
Ying Xuef046e7d2012-08-16 12:09:11 +0000220 return x & (TIPC_NAMETBL_SIZE - 1);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100221}
222
223/**
Jon Maloy218527f2018-03-29 23:20:41 +0200224 * tipc_publ_create - create a publication structure
Jon Maloya45ffa62021-03-16 22:06:12 -0400225 * @ua: the service range the user is binding to
226 * @sk: the address of the socket that is bound
Randy Dunlap5c5d6792020-11-29 10:32:46 -0800227 * @key: publication key
Per Lidenb97bf3f2006-01-02 19:04:38 +0100228 */
Jon Maloya45ffa62021-03-16 22:06:12 -0400229static struct publication *tipc_publ_create(struct tipc_uaddr *ua,
230 struct tipc_socket_addr *sk,
Jon Maloy218527f2018-03-29 23:20:41 +0200231 u32 key)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100232{
Jon Maloy998d3902021-03-16 22:06:08 -0400233 struct publication *p = kzalloc(sizeof(*p), GFP_ATOMIC);
Jon Maloy218527f2018-03-29 23:20:41 +0200234
Jon Maloy998d3902021-03-16 22:06:08 -0400235 if (!p)
Sam Ravnborg1fc54d82006-03-20 22:36:47 -0800236 return NULL;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100237
Jon Maloya45ffa62021-03-16 22:06:12 -0400238 p->sr = ua->sr;
239 p->sk = *sk;
240 p->scope = ua->scope;
Jon Maloy998d3902021-03-16 22:06:08 -0400241 p->key = key;
242 INIT_LIST_HEAD(&p->binding_sock);
243 INIT_LIST_HEAD(&p->binding_node);
244 INIT_LIST_HEAD(&p->local_publ);
245 INIT_LIST_HEAD(&p->all_publ);
246 INIT_LIST_HEAD(&p->list);
247 return p;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100248}
249
250/**
Jon Maloy218527f2018-03-29 23:20:41 +0200251 * tipc_service_create - create a service structure for the specified 'type'
Jon Maloy6e448672021-03-16 22:06:20 -0400252 * @net: network namespace
253 * @ua: address representing the service to be bound
YOSHIFUJI Hideakic4307282007-02-09 23:25:21 +0900254 *
Jon Maloy218527f2018-03-29 23:20:41 +0200255 * Allocates a single range structure and sets it to all 0's.
Per Lidenb97bf3f2006-01-02 19:04:38 +0100256 */
Jon Maloy6e448672021-03-16 22:06:20 -0400257static struct tipc_service *tipc_service_create(struct net *net,
258 struct tipc_uaddr *ua)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100259{
Jon Maloy6e448672021-03-16 22:06:20 -0400260 struct name_table *nt = tipc_name_table(net);
261 struct tipc_service *service;
262 struct hlist_head *hd;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100263
Jon Maloy6e448672021-03-16 22:06:20 -0400264 service = kzalloc(sizeof(*service), GFP_ATOMIC);
Jon Maloy218527f2018-03-29 23:20:41 +0200265 if (!service) {
266 pr_warn("Service creation failed, no memory\n");
Sam Ravnborg1fc54d82006-03-20 22:36:47 -0800267 return NULL;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100268 }
269
Jon Maloy218527f2018-03-29 23:20:41 +0200270 spin_lock_init(&service->lock);
Jon Maloy6e448672021-03-16 22:06:20 -0400271 service->type = ua->sr.type;
Jon Maloy218527f2018-03-29 23:20:41 +0200272 service->ranges = RB_ROOT;
273 INIT_HLIST_NODE(&service->service_list);
274 INIT_LIST_HEAD(&service->subscriptions);
Jon Maloy6e448672021-03-16 22:06:20 -0400275 hd = &nt->services[hash(ua->sr.type)];
Jon Maloy218527f2018-03-29 23:20:41 +0200276 hlist_add_head_rcu(&service->service_list, hd);
277 return service;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100278}
279
Jon Maloy5f307212018-05-09 02:59:41 +0200280/* tipc_service_find_range - find service range matching publication parameters
281 */
282static struct service_range *tipc_service_find_range(struct tipc_service *sc,
Jon Maloy13c9d232021-03-16 22:06:19 -0400283 struct tipc_uaddr *ua)
Jon Maloy5f307212018-05-09 02:59:41 +0200284{
Jon Maloy5f307212018-05-09 02:59:41 +0200285 struct service_range *sr;
286
Jon Maloy13c9d232021-03-16 22:06:19 -0400287 service_range_foreach_match(sr, sc, ua->sr.lower, ua->sr.upper) {
Tuong Liend5162f32019-12-10 15:21:02 +0700288 /* Look for exact match */
Jon Maloy13c9d232021-03-16 22:06:19 -0400289 if (sr->lower == ua->sr.lower && sr->upper == ua->sr.upper)
Tuong Liend5162f32019-12-10 15:21:02 +0700290 return sr;
Jon Maloy5f307212018-05-09 02:59:41 +0200291 }
Jon Maloy5f307212018-05-09 02:59:41 +0200292
Tuong Liend5162f32019-12-10 15:21:02 +0700293 return NULL;
Jon Maloy5f307212018-05-09 02:59:41 +0200294}
295
Jon Maloy218527f2018-03-29 23:20:41 +0200296static struct service_range *tipc_service_create_range(struct tipc_service *sc,
Jon Maloy13c9d232021-03-16 22:06:19 -0400297 struct publication *p)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100298{
Jon Maloy218527f2018-03-29 23:20:41 +0200299 struct rb_node **n, *parent = NULL;
Tuong Liend5162f32019-12-10 15:21:02 +0700300 struct service_range *sr;
Jon Maloy13c9d232021-03-16 22:06:19 -0400301 u32 lower = p->sr.lower;
302 u32 upper = p->sr.upper;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100303
Jon Maloy218527f2018-03-29 23:20:41 +0200304 n = &sc->ranges.rb_node;
305 while (*n) {
Jon Maloy218527f2018-03-29 23:20:41 +0200306 parent = *n;
Tuong Liend5162f32019-12-10 15:21:02 +0700307 sr = service_range_entry(parent);
308 if (lower == sr->lower && upper == sr->upper)
309 return sr;
310 if (sr->max < upper)
311 sr->max = upper;
312 if (lower <= sr->lower)
313 n = &parent->rb_left;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100314 else
Tuong Liend5162f32019-12-10 15:21:02 +0700315 n = &parent->rb_right;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100316 }
Jon Maloy218527f2018-03-29 23:20:41 +0200317 sr = kzalloc(sizeof(*sr), GFP_ATOMIC);
318 if (!sr)
319 return NULL;
320 sr->lower = lower;
321 sr->upper = upper;
Tuong Liend5162f32019-12-10 15:21:02 +0700322 sr->max = upper;
Jon Maloy218527f2018-03-29 23:20:41 +0200323 INIT_LIST_HEAD(&sr->local_publ);
324 INIT_LIST_HEAD(&sr->all_publ);
325 rb_link_node(&sr->tree_node, parent, n);
Tuong Liend5162f32019-12-10 15:21:02 +0700326 rb_insert_augmented(&sr->tree_node, &sc->ranges, &sr_callbacks);
Jon Maloy218527f2018-03-29 23:20:41 +0200327 return sr;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100328}
329
Jon Maloyb26b5aa2021-03-16 22:06:09 -0400330static bool tipc_service_insert_publ(struct net *net,
331 struct tipc_service *sc,
332 struct publication *p)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100333{
Jon Maloy218527f2018-03-29 23:20:41 +0200334 struct tipc_subscription *sub, *tmp;
335 struct service_range *sr;
Jon Maloyb26b5aa2021-03-16 22:06:09 -0400336 struct publication *_p;
337 u32 node = p->sk.node;
Jon Maloy218527f2018-03-29 23:20:41 +0200338 bool first = false;
Jon Maloyb26b5aa2021-03-16 22:06:09 -0400339 bool res = false;
Jon Maloy5c834952021-03-16 22:06:23 -0400340 u32 key = p->key;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100341
Jon Maloyb26b5aa2021-03-16 22:06:09 -0400342 spin_lock_bh(&sc->lock);
Jon Maloy13c9d232021-03-16 22:06:19 -0400343 sr = tipc_service_create_range(sc, p);
Jon Maloy37922ea2018-03-29 23:20:43 +0200344 if (!sr)
Jon Maloyb26b5aa2021-03-16 22:06:09 -0400345 goto exit;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100346
Jon Maloy37922ea2018-03-29 23:20:43 +0200347 first = list_empty(&sr->all_publ);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100348
Jon Maloy218527f2018-03-29 23:20:41 +0200349 /* Return if the publication already exists */
Jon Maloyb26b5aa2021-03-16 22:06:09 -0400350 list_for_each_entry(_p, &sr->all_publ, all_publ) {
Jon Maloy5c834952021-03-16 22:06:23 -0400351 if (_p->key == key && (!_p->sk.node || _p->sk.node == node)) {
352 pr_debug("Failed to bind duplicate %u,%u,%u/%u:%u/%u\n",
353 p->sr.type, p->sr.lower, p->sr.upper,
354 node, p->sk.ref, key);
Jon Maloyb26b5aa2021-03-16 22:06:09 -0400355 goto exit;
Jon Maloy5c834952021-03-16 22:06:23 -0400356 }
Jon Maloy218527f2018-03-29 23:20:41 +0200357 }
Per Lidenb97bf3f2006-01-02 19:04:38 +0100358
Jon Maloyb26b5aa2021-03-16 22:06:09 -0400359 if (in_own_node(net, p->sk.node))
Jon Maloy218527f2018-03-29 23:20:41 +0200360 list_add(&p->local_publ, &sr->local_publ);
361 list_add(&p->all_publ, &sr->all_publ);
Jon Maloyb26b5aa2021-03-16 22:06:09 -0400362 p->id = sc->publ_cnt++;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100363
Paul Gortmaker617d3c72012-04-30 15:29:02 -0400364 /* Any subscriptions waiting for notification? */
Jon Maloy218527f2018-03-29 23:20:41 +0200365 list_for_each_entry_safe(sub, tmp, &sc->subscriptions, service_list) {
Jon Maloy09f78b82021-03-16 22:06:21 -0400366 tipc_sub_report_overlap(sub, p, TIPC_PUBLISHED, first);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100367 }
Jon Maloyb26b5aa2021-03-16 22:06:09 -0400368 res = true;
369exit:
370 if (!res)
371 pr_warn("Failed to bind to %u,%u,%u\n",
372 p->sr.type, p->sr.lower, p->sr.upper);
373 spin_unlock_bh(&sc->lock);
374 return res;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100375}
376
377/**
Jon Maloy218527f2018-03-29 23:20:41 +0200378 * tipc_service_remove_publ - remove a publication from a service
Jon Maloy2c98da02021-03-16 22:06:13 -0400379 * @r: service_range to remove publication from
380 * @sk: address publishing socket
Randy Dunlap5c5d6792020-11-29 10:32:46 -0800381 * @key: target publication key
Per Lidenb97bf3f2006-01-02 19:04:38 +0100382 */
Jon Maloy2c98da02021-03-16 22:06:13 -0400383static struct publication *tipc_service_remove_publ(struct service_range *r,
384 struct tipc_socket_addr *sk,
385 u32 key)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100386{
Jon Maloy218527f2018-03-29 23:20:41 +0200387 struct publication *p;
Jon Maloy2c98da02021-03-16 22:06:13 -0400388 u32 node = sk->node;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100389
Jon Maloy2c98da02021-03-16 22:06:13 -0400390 list_for_each_entry(p, &r->all_publ, all_publ) {
Jon Maloy998d3902021-03-16 22:06:08 -0400391 if (p->key != key || (node && node != p->sk.node))
Jon Maloy218527f2018-03-29 23:20:41 +0200392 continue;
Jon Maloy5f307212018-05-09 02:59:41 +0200393 list_del(&p->all_publ);
394 list_del(&p->local_publ);
395 return p;
Allan Stephensf6f0a4d2011-05-30 10:48:48 -0400396 }
Jon Maloy5f307212018-05-09 02:59:41 +0200397 return NULL;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100398}
399
Randy Dunlap5c5d6792020-11-29 10:32:46 -0800400/*
Tuong Lien41b416f2019-11-21 15:34:58 +0700401 * Code reused: time_after32() for the same purpose
402 */
403#define publication_after(pa, pb) time_after32((pa)->id, (pb)->id)
Sami Tolvanen4f0f5862021-04-08 11:28:34 -0700404static int tipc_publ_sort(void *priv, const struct list_head *a,
405 const struct list_head *b)
Tuong Lien41b416f2019-11-21 15:34:58 +0700406{
407 struct publication *pa, *pb;
408
409 pa = container_of(a, struct publication, list);
410 pb = container_of(b, struct publication, list);
411 return publication_after(pa, pb);
412}
413
414/**
Jon Maloy218527f2018-03-29 23:20:41 +0200415 * tipc_service_subscribe - attach a subscription, and optionally
416 * issue the prescribed number of events if there is any service
417 * range overlapping with the requested range
Randy Dunlap5c5d6792020-11-29 10:32:46 -0800418 * @service: the tipc_service to attach the @sub to
419 * @sub: the subscription to attach
Per Lidenb97bf3f2006-01-02 19:04:38 +0100420 */
Jon Maloy218527f2018-03-29 23:20:41 +0200421static void tipc_service_subscribe(struct tipc_service *service,
Jon Maloy8985ecc2018-02-15 10:40:46 +0100422 struct tipc_subscription *sub)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100423{
Tuong Lien41b416f2019-11-21 15:34:58 +0700424 struct publication *p, *first, *tmp;
425 struct list_head publ_list;
Jon Maloy218527f2018-03-29 23:20:41 +0200426 struct service_range *sr;
Jon Maloy429189a2021-03-16 22:06:22 -0400427 u32 filter, lower, upper;
Parthasarathy Bhuvaragana4273c72016-02-02 10:52:10 +0100428
Jon Maloy429189a2021-03-16 22:06:22 -0400429 filter = sub->s.filter;
430 lower = sub->s.seq.lower;
431 upper = sub->s.seq.upper;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100432
Jon Maloyda0a75e2018-02-15 10:40:48 +0100433 tipc_sub_get(sub);
Jon Maloy218527f2018-03-29 23:20:41 +0200434 list_add(&sub->service_list, &service->subscriptions);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100435
Tuong Lien41b416f2019-11-21 15:34:58 +0700436 if (filter & TIPC_SUB_NO_STATUS)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100437 return;
438
Tuong Lien41b416f2019-11-21 15:34:58 +0700439 INIT_LIST_HEAD(&publ_list);
Jon Maloy429189a2021-03-16 22:06:22 -0400440 service_range_foreach_match(sr, service, lower, upper) {
Tuong Lien41b416f2019-11-21 15:34:58 +0700441 first = NULL;
Jon Maloy218527f2018-03-29 23:20:41 +0200442 list_for_each_entry(p, &sr->all_publ, all_publ) {
Tuong Lien41b416f2019-11-21 15:34:58 +0700443 if (filter & TIPC_SUB_PORTS)
444 list_add_tail(&p->list, &publ_list);
445 else if (!first || publication_after(first, p))
446 /* Pick this range's *first* publication */
447 first = p;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100448 }
Tuong Lien41b416f2019-11-21 15:34:58 +0700449 if (first)
450 list_add_tail(&first->list, &publ_list);
451 }
452
453 /* Sort the publications before reporting */
454 list_sort(NULL, &publ_list, tipc_publ_sort);
455 list_for_each_entry_safe(p, tmp, &publ_list, list) {
Jon Maloy09f78b82021-03-16 22:06:21 -0400456 tipc_sub_report_overlap(sub, p, TIPC_PUBLISHED, true);
Tuong Lien41b416f2019-11-21 15:34:58 +0700457 list_del_init(&p->list);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100458 }
459}
460
Jon Maloy6e448672021-03-16 22:06:20 -0400461static struct tipc_service *tipc_service_find(struct net *net,
462 struct tipc_uaddr *ua)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100463{
Jon Maloy218527f2018-03-29 23:20:41 +0200464 struct name_table *nt = tipc_name_table(net);
465 struct hlist_head *service_head;
466 struct tipc_service *service;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100467
Jon Maloy6e448672021-03-16 22:06:20 -0400468 service_head = &nt->services[hash(ua->sr.type)];
Jon Maloy218527f2018-03-29 23:20:41 +0200469 hlist_for_each_entry_rcu(service, service_head, service_list) {
Jon Maloy6e448672021-03-16 22:06:20 -0400470 if (service->type == ua->sr.type)
Jon Maloy218527f2018-03-29 23:20:41 +0200471 return service;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100472 }
Sam Ravnborg1fc54d82006-03-20 22:36:47 -0800473 return NULL;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100474};
475
Jon Maloya45ffa62021-03-16 22:06:12 -0400476struct publication *tipc_nametbl_insert_publ(struct net *net,
477 struct tipc_uaddr *ua,
478 struct tipc_socket_addr *sk,
479 u32 key)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100480{
Jon Maloy218527f2018-03-29 23:20:41 +0200481 struct tipc_service *sc;
482 struct publication *p;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100483
Jon Maloya45ffa62021-03-16 22:06:12 -0400484 p = tipc_publ_create(ua, sk, key);
Jon Maloyb26b5aa2021-03-16 22:06:09 -0400485 if (!p)
Sam Ravnborg1fc54d82006-03-20 22:36:47 -0800486 return NULL;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100487
Jon Maloy6e448672021-03-16 22:06:20 -0400488 sc = tipc_service_find(net, ua);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100489 if (!sc)
Jon Maloy6e448672021-03-16 22:06:20 -0400490 sc = tipc_service_create(net, ua);
Jon Maloyb26b5aa2021-03-16 22:06:09 -0400491 if (sc && tipc_service_insert_publ(net, sc, p))
492 return p;
493 kfree(p);
494 return NULL;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100495}
496
Jon Maloy2c98da02021-03-16 22:06:13 -0400497struct publication *tipc_nametbl_remove_publ(struct net *net,
498 struct tipc_uaddr *ua,
499 struct tipc_socket_addr *sk,
500 u32 key)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100501{
Jon Maloy5f307212018-05-09 02:59:41 +0200502 struct tipc_subscription *sub, *tmp;
Jon Maloy218527f2018-03-29 23:20:41 +0200503 struct publication *p = NULL;
Jon Maloy2c98da02021-03-16 22:06:13 -0400504 struct service_range *sr;
505 struct tipc_service *sc;
Jon Maloy5f307212018-05-09 02:59:41 +0200506 bool last;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100507
Jon Maloy6e448672021-03-16 22:06:20 -0400508 sc = tipc_service_find(net, ua);
Jon Maloy218527f2018-03-29 23:20:41 +0200509 if (!sc)
Jon Maloy5c834952021-03-16 22:06:23 -0400510 goto exit;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100511
Jon Maloy218527f2018-03-29 23:20:41 +0200512 spin_lock_bh(&sc->lock);
Jon Maloy13c9d232021-03-16 22:06:19 -0400513 sr = tipc_service_find_range(sc, ua);
Jon Maloy5f307212018-05-09 02:59:41 +0200514 if (!sr)
Jon Maloy5c834952021-03-16 22:06:23 -0400515 goto unlock;
Jon Maloy2c98da02021-03-16 22:06:13 -0400516 p = tipc_service_remove_publ(sr, sk, key);
Jon Maloy5f307212018-05-09 02:59:41 +0200517 if (!p)
Jon Maloy5c834952021-03-16 22:06:23 -0400518 goto unlock;
Jon Maloy5f307212018-05-09 02:59:41 +0200519
520 /* Notify any waiting subscriptions */
521 last = list_empty(&sr->all_publ);
522 list_for_each_entry_safe(sub, tmp, &sc->subscriptions, service_list) {
Jon Maloy09f78b82021-03-16 22:06:21 -0400523 tipc_sub_report_overlap(sub, p, TIPC_WITHDRAWN, last);
Jon Maloy5f307212018-05-09 02:59:41 +0200524 }
Jon Maloybe47e412018-04-17 21:25:42 +0200525
526 /* Remove service range item if this was its last publication */
Jon Maloy5f307212018-05-09 02:59:41 +0200527 if (list_empty(&sr->all_publ)) {
Tuong Liend5162f32019-12-10 15:21:02 +0700528 rb_erase_augmented(&sr->tree_node, &sc->ranges, &sr_callbacks);
Jon Maloybe47e412018-04-17 21:25:42 +0200529 kfree(sr);
530 }
Jon Maloy218527f2018-03-29 23:20:41 +0200531
Jon Maloy09f78b82021-03-16 22:06:21 -0400532 /* Delete service item if no more publications and subscriptions */
Jon Maloy218527f2018-03-29 23:20:41 +0200533 if (RB_EMPTY_ROOT(&sc->ranges) && list_empty(&sc->subscriptions)) {
534 hlist_del_init_rcu(&sc->service_list);
535 kfree_rcu(sc, rcu);
Ying Xuefb9962f2014-12-02 15:00:26 +0800536 }
Jon Maloy5c834952021-03-16 22:06:23 -0400537unlock:
Jon Maloy218527f2018-03-29 23:20:41 +0200538 spin_unlock_bh(&sc->lock);
Jon Maloy5c834952021-03-16 22:06:23 -0400539exit:
540 if (!p) {
541 pr_err("Failed to remove unknown binding: %u,%u,%u/%u:%u/%u\n",
542 ua->sr.type, ua->sr.lower, ua->sr.upper,
543 sk->node, sk->ref, key);
544 }
Jon Maloy218527f2018-03-29 23:20:41 +0200545 return p;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100546}
547
Ben Hutchings2c530402012-07-10 10:55:09 +0000548/**
Jon Maloy66db2392021-03-16 22:06:14 -0400549 * tipc_nametbl_lookup_anycast - perform service instance to socket translation
Randy Dunlap5c5d6792020-11-29 10:32:46 -0800550 * @net: network namespace
Jon Maloy908148b2021-03-16 22:06:15 -0400551 * @ua: service address to look up
552 * @sk: address to socket we want to find
Allan Stephensbc9f8142011-11-07 17:00:54 -0500553 *
Jon Maloy908148b2021-03-16 22:06:15 -0400554 * On entry, a non-zero 'sk->node' indicates the node where we want lookup to be
555 * performed, which may not be this one.
Allan Stephensbc9f8142011-11-07 17:00:54 -0500556 *
557 * On exit:
Wu XiangCheng85d091a2021-04-04 22:23:15 +0800558 *
Jon Maloy908148b2021-03-16 22:06:15 -0400559 * - If lookup is deferred to another node, leave 'sk->node' unchanged and
560 * return 'true'.
561 * - If lookup is successful, set the 'sk->node' and 'sk->ref' (== portid) which
562 * represent the bound socket and return 'true'.
563 * - If lookup fails, return 'false'
Jon Maloyf20889f2018-03-29 23:20:42 +0200564 *
565 * Note that for legacy users (node configured with Z.C.N address format) the
Jon Maloy908148b2021-03-16 22:06:15 -0400566 * 'closest-first' lookup algorithm must be maintained, i.e., if sk.node is 0
Jon Maloyf20889f2018-03-29 23:20:42 +0200567 * we must look in the local binding list first
Per Lidenb97bf3f2006-01-02 19:04:38 +0100568 */
Jon Maloy908148b2021-03-16 22:06:15 -0400569bool tipc_nametbl_lookup_anycast(struct net *net,
570 struct tipc_uaddr *ua,
571 struct tipc_socket_addr *sk)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100572{
Jon Maloyb89afb12018-03-22 20:42:48 +0100573 struct tipc_net *tn = tipc_net(net);
574 bool legacy = tn->legacy_addr_format;
575 u32 self = tipc_own_addr(net);
Jon Maloy908148b2021-03-16 22:06:15 -0400576 u32 inst = ua->sa.instance;
577 struct service_range *r;
Jon Maloy218527f2018-03-29 23:20:41 +0200578 struct tipc_service *sc;
579 struct publication *p;
Jon Maloy908148b2021-03-16 22:06:15 -0400580 struct list_head *l;
581 bool res = false;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100582
Jon Maloy908148b2021-03-16 22:06:15 -0400583 if (!tipc_in_scope(legacy, sk->node, self))
584 return true;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100585
Ying Xue97ede292014-12-02 15:00:30 +0800586 rcu_read_lock();
Jon Maloy6e448672021-03-16 22:06:20 -0400587 sc = tipc_service_find(net, ua);
Jon Maloy218527f2018-03-29 23:20:41 +0200588 if (unlikely(!sc))
Tuong Liend5162f32019-12-10 15:21:02 +0700589 goto exit;
Jon Maloy218527f2018-03-29 23:20:41 +0200590
591 spin_lock_bh(&sc->lock);
Jon Maloy908148b2021-03-16 22:06:15 -0400592 service_range_foreach_match(r, sc, inst, inst) {
Tuong Liend5162f32019-12-10 15:21:02 +0700593 /* Select lookup algo: local, closest-first or round-robin */
Jon Maloy908148b2021-03-16 22:06:15 -0400594 if (sk->node == self) {
595 l = &r->local_publ;
596 if (list_empty(l))
Tuong Liend5162f32019-12-10 15:21:02 +0700597 continue;
Jon Maloy908148b2021-03-16 22:06:15 -0400598 p = list_first_entry(l, struct publication, local_publ);
599 list_move_tail(&p->local_publ, &r->local_publ);
600 } else if (legacy && !sk->node && !list_empty(&r->local_publ)) {
601 l = &r->local_publ;
602 p = list_first_entry(l, struct publication, local_publ);
603 list_move_tail(&p->local_publ, &r->local_publ);
Tuong Liend5162f32019-12-10 15:21:02 +0700604 } else {
Jon Maloy908148b2021-03-16 22:06:15 -0400605 l = &r->all_publ;
606 p = list_first_entry(l, struct publication, all_publ);
607 list_move_tail(&p->all_publ, &r->all_publ);
Tuong Liend5162f32019-12-10 15:21:02 +0700608 }
Jon Maloy908148b2021-03-16 22:06:15 -0400609 *sk = p->sk;
610 res = true;
Tuong Liend5162f32019-12-10 15:21:02 +0700611 /* Todo: as for legacy, pick the first matching range only, a
612 * "true" round-robin will be performed as needed.
613 */
614 break;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100615 }
Jon Maloy218527f2018-03-29 23:20:41 +0200616 spin_unlock_bh(&sc->lock);
Tuong Liend5162f32019-12-10 15:21:02 +0700617
618exit:
Ying Xue97ede292014-12-02 15:00:30 +0800619 rcu_read_unlock();
Jon Maloy908148b2021-03-16 22:06:15 -0400620 return res;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100621}
622
Jon Maloy66db2392021-03-16 22:06:14 -0400623/* tipc_nametbl_lookup_group(): lookup destinaton(s) in a communication group
624 * Returns a list of one (== group anycast) or more (== group multicast)
625 * destination socket/node pairs matching the given address.
626 * The requester may or may not want to exclude himself from the list.
627 */
Jon Maloy006ed142021-03-16 22:06:18 -0400628bool tipc_nametbl_lookup_group(struct net *net, struct tipc_uaddr *ua,
629 struct list_head *dsts, int *dstcnt,
630 u32 exclude, bool mcast)
Jon Maloyee106d72017-10-13 11:04:28 +0200631{
632 u32 self = tipc_own_addr(net);
Jon Maloy006ed142021-03-16 22:06:18 -0400633 u32 inst = ua->sa.instance;
Jon Maloy218527f2018-03-29 23:20:41 +0200634 struct service_range *sr;
635 struct tipc_service *sc;
636 struct publication *p;
Jon Maloyee106d72017-10-13 11:04:28 +0200637
Jon Maloyee106d72017-10-13 11:04:28 +0200638 *dstcnt = 0;
639 rcu_read_lock();
Jon Maloy6e448672021-03-16 22:06:20 -0400640 sc = tipc_service_find(net, ua);
Jon Maloy218527f2018-03-29 23:20:41 +0200641 if (unlikely(!sc))
Jon Maloyee106d72017-10-13 11:04:28 +0200642 goto exit;
Jon Maloy218527f2018-03-29 23:20:41 +0200643
644 spin_lock_bh(&sc->lock);
645
Tuong Liend5162f32019-12-10 15:21:02 +0700646 /* Todo: a full search i.e. service_range_foreach_match() instead? */
Jon Maloy006ed142021-03-16 22:06:18 -0400647 sr = service_range_match_first(sc->ranges.rb_node, inst, inst);
Jon Maloy218527f2018-03-29 23:20:41 +0200648 if (!sr)
649 goto no_match;
650
651 list_for_each_entry(p, &sr->all_publ, all_publ) {
Jon Maloy006ed142021-03-16 22:06:18 -0400652 if (p->scope != ua->scope)
Jon Maloy218527f2018-03-29 23:20:41 +0200653 continue;
Jon Maloy998d3902021-03-16 22:06:08 -0400654 if (p->sk.ref == exclude && p->sk.node == self)
Jon Maloy218527f2018-03-29 23:20:41 +0200655 continue;
Jon Maloy998d3902021-03-16 22:06:08 -0400656 tipc_dest_push(dsts, p->sk.node, p->sk.ref);
Jon Maloy218527f2018-03-29 23:20:41 +0200657 (*dstcnt)++;
Jon Maloy66db2392021-03-16 22:06:14 -0400658 if (mcast)
Jon Maloy218527f2018-03-29 23:20:41 +0200659 continue;
660 list_move_tail(&p->all_publ, &sr->all_publ);
661 break;
Jon Maloyee106d72017-10-13 11:04:28 +0200662 }
Jon Maloy218527f2018-03-29 23:20:41 +0200663no_match:
664 spin_unlock_bh(&sc->lock);
Jon Maloyee106d72017-10-13 11:04:28 +0200665exit:
666 rcu_read_unlock();
667 return !list_empty(dsts);
668}
669
Jon Maloy66db2392021-03-16 22:06:14 -0400670/* tipc_nametbl_lookup_mcast_sockets(): look up node local destinaton sockets
671 * matching the given address
672 * Used on nodes which have received a multicast/broadcast message
673 * Returns a list of local sockets
674 */
Jon Maloy45ceea22021-03-16 22:06:16 -0400675void tipc_nametbl_lookup_mcast_sockets(struct net *net, struct tipc_uaddr *ua,
Jon Maloy5ef21322021-06-02 13:44:26 -0400676 struct list_head *dports)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100677{
Jon Maloy218527f2018-03-29 23:20:41 +0200678 struct service_range *sr;
679 struct tipc_service *sc;
Jon Maloy232d07b2018-01-08 21:03:30 +0100680 struct publication *p;
Jon Maloy5ef21322021-06-02 13:44:26 -0400681 u8 scope = ua->scope;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100682
Ying Xue97ede292014-12-02 15:00:30 +0800683 rcu_read_lock();
Jon Maloy6e448672021-03-16 22:06:20 -0400684 sc = tipc_service_find(net, ua);
Jon Maloy218527f2018-03-29 23:20:41 +0200685 if (!sc)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100686 goto exit;
687
Jon Maloy218527f2018-03-29 23:20:41 +0200688 spin_lock_bh(&sc->lock);
Jon Maloy45ceea22021-03-16 22:06:16 -0400689 service_range_foreach_match(sr, sc, ua->sr.lower, ua->sr.upper) {
Jon Maloy218527f2018-03-29 23:20:41 +0200690 list_for_each_entry(p, &sr->local_publ, local_publ) {
Jon Maloy5ef21322021-06-02 13:44:26 -0400691 if (scope == p->scope || scope == TIPC_ANY_SCOPE)
Jon Maloy998d3902021-03-16 22:06:08 -0400692 tipc_dest_push(dports, 0, p->sk.ref);
Allan Stephens968edbe2008-07-14 22:45:33 -0700693 }
Per Lidenb97bf3f2006-01-02 19:04:38 +0100694 }
Jon Maloy218527f2018-03-29 23:20:41 +0200695 spin_unlock_bh(&sc->lock);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100696exit:
Ying Xue97ede292014-12-02 15:00:30 +0800697 rcu_read_unlock();
Per Lidenb97bf3f2006-01-02 19:04:38 +0100698}
699
Jon Maloy66db2392021-03-16 22:06:14 -0400700/* tipc_nametbl_lookup_mcast_nodes(): look up all destination nodes matching
701 * the given address. Used in sending node.
702 * Used on nodes which are sending out a multicast/broadcast message
703 * Returns a list of nodes, including own node if applicable
Jon Paul Maloy2ae0b8a2017-01-18 13:50:51 -0500704 */
Jon Maloy833f8672021-03-16 22:06:17 -0400705void tipc_nametbl_lookup_mcast_nodes(struct net *net, struct tipc_uaddr *ua,
706 struct tipc_nlist *nodes)
Jon Paul Maloy2ae0b8a2017-01-18 13:50:51 -0500707{
Jon Maloy218527f2018-03-29 23:20:41 +0200708 struct service_range *sr;
709 struct tipc_service *sc;
710 struct publication *p;
Jon Paul Maloy2ae0b8a2017-01-18 13:50:51 -0500711
712 rcu_read_lock();
Jon Maloy6e448672021-03-16 22:06:20 -0400713 sc = tipc_service_find(net, ua);
Jon Maloy218527f2018-03-29 23:20:41 +0200714 if (!sc)
Jon Paul Maloy2ae0b8a2017-01-18 13:50:51 -0500715 goto exit;
716
Jon Maloy218527f2018-03-29 23:20:41 +0200717 spin_lock_bh(&sc->lock);
Jon Maloy833f8672021-03-16 22:06:17 -0400718 service_range_foreach_match(sr, sc, ua->sr.lower, ua->sr.upper) {
Jon Maloy218527f2018-03-29 23:20:41 +0200719 list_for_each_entry(p, &sr->all_publ, all_publ) {
Jon Maloy998d3902021-03-16 22:06:08 -0400720 tipc_nlist_add(nodes, p->sk.node);
Jon Paul Maloy2ae0b8a2017-01-18 13:50:51 -0500721 }
722 }
Jon Maloy218527f2018-03-29 23:20:41 +0200723 spin_unlock_bh(&sc->lock);
Jon Paul Maloy2ae0b8a2017-01-18 13:50:51 -0500724exit:
725 rcu_read_unlock();
726}
727
Jon Maloy75da2162017-10-13 11:04:23 +0200728/* tipc_nametbl_build_group - build list of communication group members
729 */
730void tipc_nametbl_build_group(struct net *net, struct tipc_group *grp,
Jon Maloy6e448672021-03-16 22:06:20 -0400731 struct tipc_uaddr *ua)
Jon Maloy75da2162017-10-13 11:04:23 +0200732{
Jon Maloy218527f2018-03-29 23:20:41 +0200733 struct service_range *sr;
734 struct tipc_service *sc;
Jon Maloy75da2162017-10-13 11:04:23 +0200735 struct publication *p;
Jon Maloy218527f2018-03-29 23:20:41 +0200736 struct rb_node *n;
Jon Maloy75da2162017-10-13 11:04:23 +0200737
738 rcu_read_lock();
Jon Maloy6e448672021-03-16 22:06:20 -0400739 sc = tipc_service_find(net, ua);
Jon Maloy218527f2018-03-29 23:20:41 +0200740 if (!sc)
Jon Maloy75da2162017-10-13 11:04:23 +0200741 goto exit;
742
Jon Maloy218527f2018-03-29 23:20:41 +0200743 spin_lock_bh(&sc->lock);
744 for (n = rb_first(&sc->ranges); n; n = rb_next(n)) {
745 sr = container_of(n, struct service_range, tree_node);
746 list_for_each_entry(p, &sr->all_publ, all_publ) {
Jon Maloy6e448672021-03-16 22:06:20 -0400747 if (p->scope != ua->scope)
Jon Maloy75da2162017-10-13 11:04:23 +0200748 continue;
Jon Maloy6e448672021-03-16 22:06:20 -0400749 tipc_group_add_member(grp, p->sk.node, p->sk.ref,
750 p->sr.lower);
Jon Maloy75da2162017-10-13 11:04:23 +0200751 }
752 }
Jon Maloy218527f2018-03-29 23:20:41 +0200753 spin_unlock_bh(&sc->lock);
Jon Maloy75da2162017-10-13 11:04:23 +0200754exit:
755 rcu_read_unlock();
756}
757
Jon Maloy218527f2018-03-29 23:20:41 +0200758/* tipc_nametbl_publish - add service binding to name table
Per Lidenb97bf3f2006-01-02 19:04:38 +0100759 */
Jon Maloy50a34992021-03-16 22:06:11 -0400760struct publication *tipc_nametbl_publish(struct net *net, struct tipc_uaddr *ua,
761 struct tipc_socket_addr *sk, u32 key)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100762{
Jon Maloy218527f2018-03-29 23:20:41 +0200763 struct name_table *nt = tipc_name_table(net);
764 struct tipc_net *tn = tipc_net(net);
765 struct publication *p = NULL;
766 struct sk_buff *skb = NULL;
Hoang Huu Lecad29292020-06-17 13:56:05 +0700767 u32 rc_dests;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100768
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800769 spin_lock_bh(&tn->nametbl_lock);
Jon Maloy218527f2018-03-29 23:20:41 +0200770
771 if (nt->local_publ_count >= TIPC_MAX_PUBL) {
772 pr_warn("Bind failed, max limit %u reached\n", TIPC_MAX_PUBL);
773 goto exit;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100774 }
Per Lidenb97bf3f2006-01-02 19:04:38 +0100775
Jon Maloya45ffa62021-03-16 22:06:12 -0400776 p = tipc_nametbl_insert_publ(net, ua, sk, key);
Jon Maloy218527f2018-03-29 23:20:41 +0200777 if (p) {
778 nt->local_publ_count++;
779 skb = tipc_named_publish(net, p);
Allan Stephensfd6eced2011-11-09 14:22:52 -0500780 }
Hoang Huu Lecad29292020-06-17 13:56:05 +0700781 rc_dests = nt->rc_dests;
Jon Maloy218527f2018-03-29 23:20:41 +0200782exit:
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800783 spin_unlock_bh(&tn->nametbl_lock);
Ying Xueeab8c0452014-04-28 18:00:10 +0800784
Jon Maloy218527f2018-03-29 23:20:41 +0200785 if (skb)
Hoang Huu Lecad29292020-06-17 13:56:05 +0700786 tipc_node_broadcast(net, skb, rc_dests);
Jon Maloy218527f2018-03-29 23:20:41 +0200787 return p;
Hoang Huu Lecad29292020-06-17 13:56:05 +0700788
Per Lidenb97bf3f2006-01-02 19:04:38 +0100789}
790
791/**
Jon Maloy218527f2018-03-29 23:20:41 +0200792 * tipc_nametbl_withdraw - withdraw a service binding
Randy Dunlap5c5d6792020-11-29 10:32:46 -0800793 * @net: network namespace
Jon Maloy2c98da02021-03-16 22:06:13 -0400794 * @ua: service address/range being unbound
795 * @sk: address of the socket being unbound from
Randy Dunlap5c5d6792020-11-29 10:32:46 -0800796 * @key: target publication key
Per Lidenb97bf3f2006-01-02 19:04:38 +0100797 */
Jon Maloy2c98da02021-03-16 22:06:13 -0400798void tipc_nametbl_withdraw(struct net *net, struct tipc_uaddr *ua,
799 struct tipc_socket_addr *sk, u32 key)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100800{
Jon Maloy218527f2018-03-29 23:20:41 +0200801 struct name_table *nt = tipc_name_table(net);
802 struct tipc_net *tn = tipc_net(net);
Ying Xue54923902014-12-02 15:00:28 +0800803 struct sk_buff *skb = NULL;
Jon Maloy218527f2018-03-29 23:20:41 +0200804 struct publication *p;
Hoang Huu Lecad29292020-06-17 13:56:05 +0700805 u32 rc_dests;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100806
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800807 spin_lock_bh(&tn->nametbl_lock);
Jon Maloy218527f2018-03-29 23:20:41 +0200808
Jon Maloy2c98da02021-03-16 22:06:13 -0400809 p = tipc_nametbl_remove_publ(net, ua, sk, key);
Jon Maloy218527f2018-03-29 23:20:41 +0200810 if (p) {
811 nt->local_publ_count--;
812 skb = tipc_named_withdraw(net, p);
Jon Maloy218527f2018-03-29 23:20:41 +0200813 list_del_init(&p->binding_sock);
814 kfree_rcu(p, rcu);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100815 }
Hoang Huu Lecad29292020-06-17 13:56:05 +0700816 rc_dests = nt->rc_dests;
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800817 spin_unlock_bh(&tn->nametbl_lock);
Ying Xue54923902014-12-02 15:00:28 +0800818
Jon Maloy2c98da02021-03-16 22:06:13 -0400819 if (skb)
Hoang Huu Lecad29292020-06-17 13:56:05 +0700820 tipc_node_broadcast(net, skb, rc_dests);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100821}
822
823/**
Per Liden4323add2006-01-18 00:38:21 +0100824 * tipc_nametbl_subscribe - add a subscription object to the name table
Randy Dunlap5c5d6792020-11-29 10:32:46 -0800825 * @sub: subscription to add
Per Lidenb97bf3f2006-01-02 19:04:38 +0100826 */
Jon Maloyc3317f42018-04-11 22:52:09 +0200827bool tipc_nametbl_subscribe(struct tipc_subscription *sub)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100828{
Jon Maloy5c45ab22018-02-15 10:40:49 +0100829 struct tipc_net *tn = tipc_net(sub->net);
Jon Maloy429189a2021-03-16 22:06:22 -0400830 u32 type = sub->s.seq.type;
Jon Maloy218527f2018-03-29 23:20:41 +0200831 struct tipc_service *sc;
Jon Maloy6e448672021-03-16 22:06:20 -0400832 struct tipc_uaddr ua;
Jon Maloyc3317f42018-04-11 22:52:09 +0200833 bool res = true;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100834
Jon Maloy09f78b82021-03-16 22:06:21 -0400835 tipc_uaddr(&ua, TIPC_SERVICE_RANGE, TIPC_NODE_SCOPE, type,
Jon Maloy429189a2021-03-16 22:06:22 -0400836 sub->s.seq.lower, sub->s.seq.upper);
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800837 spin_lock_bh(&tn->nametbl_lock);
Jon Maloy6e448672021-03-16 22:06:20 -0400838 sc = tipc_service_find(sub->net, &ua);
Jon Maloy218527f2018-03-29 23:20:41 +0200839 if (!sc)
Jon Maloy6e448672021-03-16 22:06:20 -0400840 sc = tipc_service_create(sub->net, &ua);
Jon Maloy218527f2018-03-29 23:20:41 +0200841 if (sc) {
842 spin_lock_bh(&sc->lock);
843 tipc_service_subscribe(sc, sub);
844 spin_unlock_bh(&sc->lock);
YOSHIFUJI Hideakic4307282007-02-09 23:25:21 +0900845 } else {
Jon Maloy429189a2021-03-16 22:06:22 -0400846 pr_warn("Failed to subscribe for {%u,%u,%u}\n",
847 type, sub->s.seq.lower, sub->s.seq.upper);
Jon Maloyc3317f42018-04-11 22:52:09 +0200848 res = false;
YOSHIFUJI Hideakic4307282007-02-09 23:25:21 +0900849 }
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800850 spin_unlock_bh(&tn->nametbl_lock);
Jon Maloyc3317f42018-04-11 22:52:09 +0200851 return res;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100852}
853
854/**
Per Liden4323add2006-01-18 00:38:21 +0100855 * tipc_nametbl_unsubscribe - remove a subscription object from name table
Randy Dunlap5c5d6792020-11-29 10:32:46 -0800856 * @sub: subscription to remove
Per Lidenb97bf3f2006-01-02 19:04:38 +0100857 */
Jon Maloy8985ecc2018-02-15 10:40:46 +0100858void tipc_nametbl_unsubscribe(struct tipc_subscription *sub)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100859{
Jon Maloy5c45ab22018-02-15 10:40:49 +0100860 struct tipc_net *tn = tipc_net(sub->net);
Jon Maloy218527f2018-03-29 23:20:41 +0200861 struct tipc_service *sc;
Jon Maloy6e448672021-03-16 22:06:20 -0400862 struct tipc_uaddr ua;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100863
Jon Maloy429189a2021-03-16 22:06:22 -0400864 tipc_uaddr(&ua, TIPC_SERVICE_RANGE, TIPC_NODE_SCOPE,
865 sub->s.seq.type, sub->s.seq.lower, sub->s.seq.upper);
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800866 spin_lock_bh(&tn->nametbl_lock);
Jon Maloy6e448672021-03-16 22:06:20 -0400867 sc = tipc_service_find(sub->net, &ua);
Jon Maloy218527f2018-03-29 23:20:41 +0200868 if (!sc)
869 goto exit;
870
871 spin_lock_bh(&sc->lock);
872 list_del_init(&sub->service_list);
873 tipc_sub_put(sub);
874
875 /* Delete service item if no more publications and subscriptions */
876 if (RB_EMPTY_ROOT(&sc->ranges) && list_empty(&sc->subscriptions)) {
877 hlist_del_init_rcu(&sc->service_list);
878 kfree_rcu(sc, rcu);
YOSHIFUJI Hideakic4307282007-02-09 23:25:21 +0900879 }
Jon Maloy218527f2018-03-29 23:20:41 +0200880 spin_unlock_bh(&sc->lock);
881exit:
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800882 spin_unlock_bh(&tn->nametbl_lock);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100883}
884
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800885int tipc_nametbl_init(struct net *net)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100886{
Jon Maloy218527f2018-03-29 23:20:41 +0200887 struct tipc_net *tn = tipc_net(net);
888 struct name_table *nt;
Ying Xue993bfe52014-12-02 15:00:24 +0800889 int i;
890
Jia-Ju Bai04b9ce42018-07-27 17:28:25 +0800891 nt = kzalloc(sizeof(*nt), GFP_KERNEL);
Jon Maloy218527f2018-03-29 23:20:41 +0200892 if (!nt)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100893 return -ENOMEM;
894
Ying Xue993bfe52014-12-02 15:00:24 +0800895 for (i = 0; i < TIPC_NAMETBL_SIZE; i++)
Jon Maloy218527f2018-03-29 23:20:41 +0200896 INIT_HLIST_HEAD(&nt->services[i]);
Ying Xue993bfe52014-12-02 15:00:24 +0800897
Jon Maloy218527f2018-03-29 23:20:41 +0200898 INIT_LIST_HEAD(&nt->node_scope);
899 INIT_LIST_HEAD(&nt->cluster_scope);
Jon Maloy988f3f12018-10-19 19:55:40 +0200900 rwlock_init(&nt->cluster_scope_lock);
Jon Maloy218527f2018-03-29 23:20:41 +0200901 tn->nametbl = nt;
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800902 spin_lock_init(&tn->nametbl_lock);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100903 return 0;
904}
905
Erik Hugne1bb8dce2014-03-06 14:40:20 +0100906/**
Randy Dunlap5c5d6792020-11-29 10:32:46 -0800907 * tipc_service_delete - purge all publications for a service and delete it
908 * @net: the associated network namespace
909 * @sc: tipc_service to delete
Erik Hugne1bb8dce2014-03-06 14:40:20 +0100910 */
Jon Maloy218527f2018-03-29 23:20:41 +0200911static void tipc_service_delete(struct net *net, struct tipc_service *sc)
Erik Hugne1bb8dce2014-03-06 14:40:20 +0100912{
Jon Maloy218527f2018-03-29 23:20:41 +0200913 struct service_range *sr, *tmpr;
Jon Maloybe47e412018-04-17 21:25:42 +0200914 struct publication *p, *tmp;
Erik Hugne1bb8dce2014-03-06 14:40:20 +0100915
Jon Maloy218527f2018-03-29 23:20:41 +0200916 spin_lock_bh(&sc->lock);
917 rbtree_postorder_for_each_entry_safe(sr, tmpr, &sc->ranges, tree_node) {
Jon Maloybe47e412018-04-17 21:25:42 +0200918 list_for_each_entry_safe(p, tmp, &sr->all_publ, all_publ) {
Jon Maloy2c98da02021-03-16 22:06:13 -0400919 tipc_service_remove_publ(sr, &p->sk, p->key);
Jon Maloy218527f2018-03-29 23:20:41 +0200920 kfree_rcu(p, rcu);
921 }
Tuong Liend5162f32019-12-10 15:21:02 +0700922 rb_erase_augmented(&sr->tree_node, &sc->ranges, &sr_callbacks);
Jon Maloybe47e412018-04-17 21:25:42 +0200923 kfree(sr);
Erik Hugne1bb8dce2014-03-06 14:40:20 +0100924 }
Jon Maloy218527f2018-03-29 23:20:41 +0200925 hlist_del_init_rcu(&sc->service_list);
926 spin_unlock_bh(&sc->lock);
927 kfree_rcu(sc, rcu);
Erik Hugne1bb8dce2014-03-06 14:40:20 +0100928}
929
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800930void tipc_nametbl_stop(struct net *net)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100931{
Jon Maloy218527f2018-03-29 23:20:41 +0200932 struct name_table *nt = tipc_name_table(net);
933 struct tipc_net *tn = tipc_net(net);
934 struct hlist_head *service_head;
935 struct tipc_service *service;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100936 u32 i;
937
Erik Hugne1bb8dce2014-03-06 14:40:20 +0100938 /* Verify name table is empty and purge any lingering
939 * publications, then release the name table
940 */
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800941 spin_lock_bh(&tn->nametbl_lock);
Ying Xuef046e7d2012-08-16 12:09:11 +0000942 for (i = 0; i < TIPC_NAMETBL_SIZE; i++) {
Jon Maloy218527f2018-03-29 23:20:41 +0200943 if (hlist_empty(&nt->services[i]))
Paul Gortmakerf705ab92012-07-11 17:35:01 -0400944 continue;
Jon Maloy218527f2018-03-29 23:20:41 +0200945 service_head = &nt->services[i];
946 hlist_for_each_entry_rcu(service, service_head, service_list) {
947 tipc_service_delete(net, service);
Erik Hugne1bb8dce2014-03-06 14:40:20 +0100948 }
Per Lidenb97bf3f2006-01-02 19:04:38 +0100949 }
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800950 spin_unlock_bh(&tn->nametbl_lock);
Ying Xue993bfe52014-12-02 15:00:24 +0800951
Ying Xue97ede292014-12-02 15:00:30 +0800952 synchronize_net();
Jon Maloy218527f2018-03-29 23:20:41 +0200953 kfree(nt);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100954}
Richard Alpe15931232014-11-20 10:29:20 +0100955
Richard Alped8182802014-11-24 11:10:29 +0100956static int __tipc_nl_add_nametable_publ(struct tipc_nl_msg *msg,
Jon Maloy218527f2018-03-29 23:20:41 +0200957 struct tipc_service *service,
958 struct service_range *sr,
959 u32 *last_key)
Richard Alpe15931232014-11-20 10:29:20 +0100960{
Richard Alpe15931232014-11-20 10:29:20 +0100961 struct publication *p;
Jon Maloy218527f2018-03-29 23:20:41 +0200962 struct nlattr *attrs;
963 struct nlattr *b;
964 void *hdr;
Richard Alpe15931232014-11-20 10:29:20 +0100965
Jon Maloy218527f2018-03-29 23:20:41 +0200966 if (*last_key) {
967 list_for_each_entry(p, &sr->all_publ, all_publ)
968 if (p->key == *last_key)
Richard Alpe15931232014-11-20 10:29:20 +0100969 break;
Jon Maloy218527f2018-03-29 23:20:41 +0200970 if (p->key != *last_key)
Richard Alpe15931232014-11-20 10:29:20 +0100971 return -EPIPE;
972 } else {
Jon Maloy218527f2018-03-29 23:20:41 +0200973 p = list_first_entry(&sr->all_publ,
974 struct publication,
Jon Maloye50e73e2018-03-15 16:48:55 +0100975 all_publ);
Richard Alpe15931232014-11-20 10:29:20 +0100976 }
977
Jon Maloy218527f2018-03-29 23:20:41 +0200978 list_for_each_entry_from(p, &sr->all_publ, all_publ) {
979 *last_key = p->key;
Richard Alpe15931232014-11-20 10:29:20 +0100980
981 hdr = genlmsg_put(msg->skb, msg->portid, msg->seq,
Richard Alpebfb3e5d2015-02-09 09:50:03 +0100982 &tipc_genl_family, NLM_F_MULTI,
Richard Alpe15931232014-11-20 10:29:20 +0100983 TIPC_NL_NAME_TABLE_GET);
984 if (!hdr)
985 return -EMSGSIZE;
986
Michal Kubecekae0be8d2019-04-26 11:13:06 +0200987 attrs = nla_nest_start_noflag(msg->skb, TIPC_NLA_NAME_TABLE);
Richard Alpe15931232014-11-20 10:29:20 +0100988 if (!attrs)
989 goto msg_full;
990
Michal Kubecekae0be8d2019-04-26 11:13:06 +0200991 b = nla_nest_start_noflag(msg->skb, TIPC_NLA_NAME_TABLE_PUBL);
Jon Maloy218527f2018-03-29 23:20:41 +0200992 if (!b)
Richard Alpe15931232014-11-20 10:29:20 +0100993 goto attr_msg_full;
994
Jon Maloy218527f2018-03-29 23:20:41 +0200995 if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_TYPE, service->type))
Richard Alpe15931232014-11-20 10:29:20 +0100996 goto publ_msg_full;
Jon Maloy218527f2018-03-29 23:20:41 +0200997 if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_LOWER, sr->lower))
Richard Alpe15931232014-11-20 10:29:20 +0100998 goto publ_msg_full;
Jon Maloy218527f2018-03-29 23:20:41 +0200999 if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_UPPER, sr->upper))
Richard Alpe15931232014-11-20 10:29:20 +01001000 goto publ_msg_full;
1001 if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_SCOPE, p->scope))
1002 goto publ_msg_full;
Jon Maloy998d3902021-03-16 22:06:08 -04001003 if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_NODE, p->sk.node))
Richard Alpe15931232014-11-20 10:29:20 +01001004 goto publ_msg_full;
Jon Maloy998d3902021-03-16 22:06:08 -04001005 if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_REF, p->sk.ref))
Richard Alpe15931232014-11-20 10:29:20 +01001006 goto publ_msg_full;
1007 if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_KEY, p->key))
1008 goto publ_msg_full;
1009
Jon Maloy218527f2018-03-29 23:20:41 +02001010 nla_nest_end(msg->skb, b);
Richard Alpe15931232014-11-20 10:29:20 +01001011 nla_nest_end(msg->skb, attrs);
1012 genlmsg_end(msg->skb, hdr);
1013 }
Jon Maloy218527f2018-03-29 23:20:41 +02001014 *last_key = 0;
Richard Alpe15931232014-11-20 10:29:20 +01001015
1016 return 0;
1017
1018publ_msg_full:
Jon Maloy218527f2018-03-29 23:20:41 +02001019 nla_nest_cancel(msg->skb, b);
Richard Alpe15931232014-11-20 10:29:20 +01001020attr_msg_full:
1021 nla_nest_cancel(msg->skb, attrs);
1022msg_full:
1023 genlmsg_cancel(msg->skb, hdr);
1024
1025 return -EMSGSIZE;
1026}
1027
Jon Maloy218527f2018-03-29 23:20:41 +02001028static int __tipc_nl_service_range_list(struct tipc_nl_msg *msg,
1029 struct tipc_service *sc,
1030 u32 *last_lower, u32 *last_key)
Richard Alpe15931232014-11-20 10:29:20 +01001031{
Jon Maloy218527f2018-03-29 23:20:41 +02001032 struct service_range *sr;
1033 struct rb_node *n;
Richard Alpe15931232014-11-20 10:29:20 +01001034 int err;
1035
Jon Maloy218527f2018-03-29 23:20:41 +02001036 for (n = rb_first(&sc->ranges); n; n = rb_next(n)) {
1037 sr = container_of(n, struct service_range, tree_node);
1038 if (sr->lower < *last_lower)
1039 continue;
1040 err = __tipc_nl_add_nametable_publ(msg, sc, sr, last_key);
Richard Alpe15931232014-11-20 10:29:20 +01001041 if (err) {
Jon Maloy218527f2018-03-29 23:20:41 +02001042 *last_lower = sr->lower;
Richard Alpe15931232014-11-20 10:29:20 +01001043 return err;
1044 }
1045 }
1046 *last_lower = 0;
Richard Alpe15931232014-11-20 10:29:20 +01001047 return 0;
1048}
1049
Jon Maloy218527f2018-03-29 23:20:41 +02001050static int tipc_nl_service_list(struct net *net, struct tipc_nl_msg *msg,
1051 u32 *last_type, u32 *last_lower, u32 *last_key)
Richard Alpe15931232014-11-20 10:29:20 +01001052{
Jon Maloy218527f2018-03-29 23:20:41 +02001053 struct tipc_net *tn = tipc_net(net);
1054 struct tipc_service *service = NULL;
1055 struct hlist_head *head;
Jon Maloy6e448672021-03-16 22:06:20 -04001056 struct tipc_uaddr ua;
Richard Alpe15931232014-11-20 10:29:20 +01001057 int err;
1058 int i;
1059
1060 if (*last_type)
1061 i = hash(*last_type);
1062 else
1063 i = 0;
1064
1065 for (; i < TIPC_NAMETBL_SIZE; i++) {
Jon Maloy218527f2018-03-29 23:20:41 +02001066 head = &tn->nametbl->services[i];
Richard Alpe15931232014-11-20 10:29:20 +01001067
Hoang Led1841532019-04-09 14:59:24 +07001068 if (*last_type ||
1069 (!i && *last_key && (*last_lower == *last_key))) {
Jon Maloy6e448672021-03-16 22:06:20 -04001070 tipc_uaddr(&ua, TIPC_SERVICE_RANGE, TIPC_NODE_SCOPE,
1071 *last_type, *last_lower, *last_lower);
1072 service = tipc_service_find(net, &ua);
Jon Maloy218527f2018-03-29 23:20:41 +02001073 if (!service)
Richard Alpe15931232014-11-20 10:29:20 +01001074 return -EPIPE;
1075 } else {
Jon Maloy218527f2018-03-29 23:20:41 +02001076 hlist_for_each_entry_rcu(service, head, service_list)
Ying Xue97ede292014-12-02 15:00:30 +08001077 break;
Jon Maloy218527f2018-03-29 23:20:41 +02001078 if (!service)
Richard Alpe15931232014-11-20 10:29:20 +01001079 continue;
1080 }
1081
Jon Maloy218527f2018-03-29 23:20:41 +02001082 hlist_for_each_entry_from_rcu(service, service_list) {
1083 spin_lock_bh(&service->lock);
1084 err = __tipc_nl_service_range_list(msg, service,
1085 last_lower,
1086 last_key);
Richard Alpe15931232014-11-20 10:29:20 +01001087
1088 if (err) {
Jon Maloy218527f2018-03-29 23:20:41 +02001089 *last_type = service->type;
1090 spin_unlock_bh(&service->lock);
Richard Alpe15931232014-11-20 10:29:20 +01001091 return err;
1092 }
Jon Maloy218527f2018-03-29 23:20:41 +02001093 spin_unlock_bh(&service->lock);
Richard Alpe15931232014-11-20 10:29:20 +01001094 }
1095 *last_type = 0;
1096 }
1097 return 0;
1098}
1099
1100int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb)
1101{
Jon Maloy218527f2018-03-29 23:20:41 +02001102 struct net *net = sock_net(skb->sk);
Richard Alpe15931232014-11-20 10:29:20 +01001103 u32 last_type = cb->args[0];
1104 u32 last_lower = cb->args[1];
Jon Maloy218527f2018-03-29 23:20:41 +02001105 u32 last_key = cb->args[2];
1106 int done = cb->args[3];
Richard Alpe15931232014-11-20 10:29:20 +01001107 struct tipc_nl_msg msg;
Jon Maloy218527f2018-03-29 23:20:41 +02001108 int err;
Richard Alpe15931232014-11-20 10:29:20 +01001109
1110 if (done)
1111 return 0;
1112
1113 msg.skb = skb;
1114 msg.portid = NETLINK_CB(cb->skb).portid;
1115 msg.seq = cb->nlh->nlmsg_seq;
1116
Ying Xue97ede292014-12-02 15:00:30 +08001117 rcu_read_lock();
Jon Maloy218527f2018-03-29 23:20:41 +02001118 err = tipc_nl_service_list(net, &msg, &last_type,
1119 &last_lower, &last_key);
Richard Alpe15931232014-11-20 10:29:20 +01001120 if (!err) {
1121 done = 1;
1122 } else if (err != -EMSGSIZE) {
1123 /* We never set seq or call nl_dump_check_consistent() this
1124 * means that setting prev_seq here will cause the consistence
1125 * check to fail in the netlink callback handler. Resulting in
1126 * the NLMSG_DONE message having the NLM_F_DUMP_INTR flag set if
1127 * we got an error.
1128 */
1129 cb->prev_seq = 1;
1130 }
Ying Xue97ede292014-12-02 15:00:30 +08001131 rcu_read_unlock();
Richard Alpe15931232014-11-20 10:29:20 +01001132
1133 cb->args[0] = last_type;
1134 cb->args[1] = last_lower;
Jon Maloy218527f2018-03-29 23:20:41 +02001135 cb->args[2] = last_key;
Richard Alpe15931232014-11-20 10:29:20 +01001136 cb->args[3] = done;
1137
1138 return skb->len;
1139}
Jon Paul Maloy3c724ac2015-02-05 08:36:43 -05001140
Jon Maloya80ae532017-10-13 11:04:22 +02001141struct tipc_dest *tipc_dest_find(struct list_head *l, u32 node, u32 port)
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001142{
Jon Maloya80ae532017-10-13 11:04:22 +02001143 struct tipc_dest *dst;
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001144
Jon Maloya80ae532017-10-13 11:04:22 +02001145 list_for_each_entry(dst, l, list) {
Haiqing Bai30935192018-08-27 09:32:26 +08001146 if (dst->node == node && dst->port == port)
1147 return dst;
Jon Paul Maloy3c724ac2015-02-05 08:36:43 -05001148 }
Jon Maloya80ae532017-10-13 11:04:22 +02001149 return NULL;
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001150}
1151
Jon Maloya80ae532017-10-13 11:04:22 +02001152bool tipc_dest_push(struct list_head *l, u32 node, u32 port)
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001153{
Jon Maloya80ae532017-10-13 11:04:22 +02001154 struct tipc_dest *dst;
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001155
Jon Maloya80ae532017-10-13 11:04:22 +02001156 if (tipc_dest_find(l, node, port))
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001157 return false;
1158
Jon Maloya80ae532017-10-13 11:04:22 +02001159 dst = kmalloc(sizeof(*dst), GFP_ATOMIC);
1160 if (unlikely(!dst))
1161 return false;
Haiqing Bai30935192018-08-27 09:32:26 +08001162 dst->node = node;
1163 dst->port = port;
Jon Maloya80ae532017-10-13 11:04:22 +02001164 list_add(&dst->list, l);
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001165 return true;
1166}
1167
Jon Maloya80ae532017-10-13 11:04:22 +02001168bool tipc_dest_pop(struct list_head *l, u32 *node, u32 *port)
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001169{
Jon Maloya80ae532017-10-13 11:04:22 +02001170 struct tipc_dest *dst;
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001171
1172 if (list_empty(l))
Jon Maloya80ae532017-10-13 11:04:22 +02001173 return false;
1174 dst = list_first_entry(l, typeof(*dst), list);
1175 if (port)
1176 *port = dst->port;
1177 if (node)
1178 *node = dst->node;
1179 list_del(&dst->list);
1180 kfree(dst);
1181 return true;
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001182}
1183
Jon Maloya80ae532017-10-13 11:04:22 +02001184bool tipc_dest_del(struct list_head *l, u32 node, u32 port)
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001185{
Jon Maloya80ae532017-10-13 11:04:22 +02001186 struct tipc_dest *dst;
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001187
Jon Maloya80ae532017-10-13 11:04:22 +02001188 dst = tipc_dest_find(l, node, port);
1189 if (!dst)
1190 return false;
1191 list_del(&dst->list);
1192 kfree(dst);
1193 return true;
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001194}
1195
Jon Maloya80ae532017-10-13 11:04:22 +02001196void tipc_dest_list_purge(struct list_head *l)
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001197{
Jon Maloya80ae532017-10-13 11:04:22 +02001198 struct tipc_dest *dst, *tmp;
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001199
Jon Maloya80ae532017-10-13 11:04:22 +02001200 list_for_each_entry_safe(dst, tmp, l, list) {
1201 list_del(&dst->list);
1202 kfree(dst);
Jon Paul Maloy3c724ac2015-02-05 08:36:43 -05001203 }
1204}
1205
Jon Maloya80ae532017-10-13 11:04:22 +02001206int tipc_dest_list_len(struct list_head *l)
Jon Paul Maloy3c724ac2015-02-05 08:36:43 -05001207{
Jon Maloya80ae532017-10-13 11:04:22 +02001208 struct tipc_dest *dst;
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001209 int i = 0;
Jon Paul Maloy3c724ac2015-02-05 08:36:43 -05001210
Jon Maloya80ae532017-10-13 11:04:22 +02001211 list_for_each_entry(dst, l, list) {
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001212 i++;
Jon Paul Maloy3c724ac2015-02-05 08:36:43 -05001213 }
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001214 return i;
Jon Paul Maloy3c724ac2015-02-05 08:36:43 -05001215}