blob: 22616a943e700b1bbb5da79097af3c9143f19813 [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'
Randy Dunlap5c5d6792020-11-29 10:32:46 -0800252 * @type: service type
253 * @hd: name_table services list
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 Maloy218527f2018-03-29 23:20:41 +0200257static struct tipc_service *tipc_service_create(u32 type, struct hlist_head *hd)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100258{
Jon Maloy218527f2018-03-29 23:20:41 +0200259 struct tipc_service *service = kzalloc(sizeof(*service), GFP_ATOMIC);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100260
Jon Maloy218527f2018-03-29 23:20:41 +0200261 if (!service) {
262 pr_warn("Service creation failed, no memory\n");
Sam Ravnborg1fc54d82006-03-20 22:36:47 -0800263 return NULL;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100264 }
265
Jon Maloy218527f2018-03-29 23:20:41 +0200266 spin_lock_init(&service->lock);
267 service->type = type;
268 service->ranges = RB_ROOT;
269 INIT_HLIST_NODE(&service->service_list);
270 INIT_LIST_HEAD(&service->subscriptions);
271 hlist_add_head_rcu(&service->service_list, hd);
272 return service;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100273}
274
Jon Maloy5f307212018-05-09 02:59:41 +0200275/* tipc_service_find_range - find service range matching publication parameters
276 */
277static struct service_range *tipc_service_find_range(struct tipc_service *sc,
278 u32 lower, u32 upper)
279{
Jon Maloy5f307212018-05-09 02:59:41 +0200280 struct service_range *sr;
281
Tuong Liend5162f32019-12-10 15:21:02 +0700282 service_range_foreach_match(sr, sc, lower, upper) {
283 /* Look for exact match */
284 if (sr->lower == lower && sr->upper == upper)
285 return sr;
Jon Maloy5f307212018-05-09 02:59:41 +0200286 }
Jon Maloy5f307212018-05-09 02:59:41 +0200287
Tuong Liend5162f32019-12-10 15:21:02 +0700288 return NULL;
Jon Maloy5f307212018-05-09 02:59:41 +0200289}
290
Jon Maloy218527f2018-03-29 23:20:41 +0200291static struct service_range *tipc_service_create_range(struct tipc_service *sc,
292 u32 lower, u32 upper)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100293{
Jon Maloy218527f2018-03-29 23:20:41 +0200294 struct rb_node **n, *parent = NULL;
Tuong Liend5162f32019-12-10 15:21:02 +0700295 struct service_range *sr;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100296
Jon Maloy218527f2018-03-29 23:20:41 +0200297 n = &sc->ranges.rb_node;
298 while (*n) {
Jon Maloy218527f2018-03-29 23:20:41 +0200299 parent = *n;
Tuong Liend5162f32019-12-10 15:21:02 +0700300 sr = service_range_entry(parent);
301 if (lower == sr->lower && upper == sr->upper)
302 return sr;
303 if (sr->max < upper)
304 sr->max = upper;
305 if (lower <= sr->lower)
306 n = &parent->rb_left;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100307 else
Tuong Liend5162f32019-12-10 15:21:02 +0700308 n = &parent->rb_right;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100309 }
Jon Maloy218527f2018-03-29 23:20:41 +0200310 sr = kzalloc(sizeof(*sr), GFP_ATOMIC);
311 if (!sr)
312 return NULL;
313 sr->lower = lower;
314 sr->upper = upper;
Tuong Liend5162f32019-12-10 15:21:02 +0700315 sr->max = upper;
Jon Maloy218527f2018-03-29 23:20:41 +0200316 INIT_LIST_HEAD(&sr->local_publ);
317 INIT_LIST_HEAD(&sr->all_publ);
318 rb_link_node(&sr->tree_node, parent, n);
Tuong Liend5162f32019-12-10 15:21:02 +0700319 rb_insert_augmented(&sr->tree_node, &sc->ranges, &sr_callbacks);
Jon Maloy218527f2018-03-29 23:20:41 +0200320 return sr;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100321}
322
Jon Maloyb26b5aa2021-03-16 22:06:09 -0400323static bool tipc_service_insert_publ(struct net *net,
324 struct tipc_service *sc,
325 struct publication *p)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100326{
Jon Maloy218527f2018-03-29 23:20:41 +0200327 struct tipc_subscription *sub, *tmp;
328 struct service_range *sr;
Jon Maloyb26b5aa2021-03-16 22:06:09 -0400329 struct publication *_p;
330 u32 node = p->sk.node;
Jon Maloy218527f2018-03-29 23:20:41 +0200331 bool first = false;
Jon Maloyb26b5aa2021-03-16 22:06:09 -0400332 bool res = false;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100333
Jon Maloyb26b5aa2021-03-16 22:06:09 -0400334 spin_lock_bh(&sc->lock);
335 sr = tipc_service_create_range(sc, p->sr.lower, p->sr.upper);
Jon Maloy37922ea2018-03-29 23:20:43 +0200336 if (!sr)
Jon Maloyb26b5aa2021-03-16 22:06:09 -0400337 goto exit;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100338
Jon Maloy37922ea2018-03-29 23:20:43 +0200339 first = list_empty(&sr->all_publ);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100340
Jon Maloy218527f2018-03-29 23:20:41 +0200341 /* Return if the publication already exists */
Jon Maloyb26b5aa2021-03-16 22:06:09 -0400342 list_for_each_entry(_p, &sr->all_publ, all_publ) {
343 if (_p->key == p->key && (!_p->sk.node || _p->sk.node == node))
344 goto exit;
Jon Maloy218527f2018-03-29 23:20:41 +0200345 }
Per Lidenb97bf3f2006-01-02 19:04:38 +0100346
Jon Maloyb26b5aa2021-03-16 22:06:09 -0400347 if (in_own_node(net, p->sk.node))
Jon Maloy218527f2018-03-29 23:20:41 +0200348 list_add(&p->local_publ, &sr->local_publ);
349 list_add(&p->all_publ, &sr->all_publ);
Jon Maloyb26b5aa2021-03-16 22:06:09 -0400350 p->id = sc->publ_cnt++;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100351
Paul Gortmaker617d3c72012-04-30 15:29:02 -0400352 /* Any subscriptions waiting for notification? */
Jon Maloy218527f2018-03-29 23:20:41 +0200353 list_for_each_entry_safe(sub, tmp, &sc->subscriptions, service_list) {
Jon Maloyb26b5aa2021-03-16 22:06:09 -0400354 tipc_sub_report_overlap(sub, p->sr.lower, p->sr.upper,
355 TIPC_PUBLISHED, p->sk.ref, p->sk.node,
356 p->scope, first);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100357 }
Jon Maloyb26b5aa2021-03-16 22:06:09 -0400358 res = true;
359exit:
360 if (!res)
361 pr_warn("Failed to bind to %u,%u,%u\n",
362 p->sr.type, p->sr.lower, p->sr.upper);
363 spin_unlock_bh(&sc->lock);
364 return res;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100365}
366
367/**
Jon Maloy218527f2018-03-29 23:20:41 +0200368 * tipc_service_remove_publ - remove a publication from a service
Jon Maloy2c98da02021-03-16 22:06:13 -0400369 * @r: service_range to remove publication from
370 * @sk: address publishing socket
Randy Dunlap5c5d6792020-11-29 10:32:46 -0800371 * @key: target publication key
Per Lidenb97bf3f2006-01-02 19:04:38 +0100372 */
Jon Maloy2c98da02021-03-16 22:06:13 -0400373static struct publication *tipc_service_remove_publ(struct service_range *r,
374 struct tipc_socket_addr *sk,
375 u32 key)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100376{
Jon Maloy218527f2018-03-29 23:20:41 +0200377 struct publication *p;
Jon Maloy2c98da02021-03-16 22:06:13 -0400378 u32 node = sk->node;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100379
Jon Maloy2c98da02021-03-16 22:06:13 -0400380 list_for_each_entry(p, &r->all_publ, all_publ) {
Jon Maloy998d3902021-03-16 22:06:08 -0400381 if (p->key != key || (node && node != p->sk.node))
Jon Maloy218527f2018-03-29 23:20:41 +0200382 continue;
Jon Maloy5f307212018-05-09 02:59:41 +0200383 list_del(&p->all_publ);
384 list_del(&p->local_publ);
385 return p;
Allan Stephensf6f0a4d2011-05-30 10:48:48 -0400386 }
Jon Maloy5f307212018-05-09 02:59:41 +0200387 return NULL;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100388}
389
Randy Dunlap5c5d6792020-11-29 10:32:46 -0800390/*
Tuong Lien41b416f2019-11-21 15:34:58 +0700391 * Code reused: time_after32() for the same purpose
392 */
393#define publication_after(pa, pb) time_after32((pa)->id, (pb)->id)
394static int tipc_publ_sort(void *priv, struct list_head *a,
395 struct list_head *b)
396{
397 struct publication *pa, *pb;
398
399 pa = container_of(a, struct publication, list);
400 pb = container_of(b, struct publication, list);
401 return publication_after(pa, pb);
402}
403
404/**
Jon Maloy218527f2018-03-29 23:20:41 +0200405 * tipc_service_subscribe - attach a subscription, and optionally
406 * issue the prescribed number of events if there is any service
407 * range overlapping with the requested range
Randy Dunlap5c5d6792020-11-29 10:32:46 -0800408 * @service: the tipc_service to attach the @sub to
409 * @sub: the subscription to attach
Per Lidenb97bf3f2006-01-02 19:04:38 +0100410 */
Jon Maloy218527f2018-03-29 23:20:41 +0200411static void tipc_service_subscribe(struct tipc_service *service,
Jon Maloy8985ecc2018-02-15 10:40:46 +0100412 struct tipc_subscription *sub)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100413{
Jon Maloy218527f2018-03-29 23:20:41 +0200414 struct tipc_subscr *sb = &sub->evt.s;
Tuong Lien41b416f2019-11-21 15:34:58 +0700415 struct publication *p, *first, *tmp;
416 struct list_head publ_list;
Jon Maloy218527f2018-03-29 23:20:41 +0200417 struct service_range *sr;
Jon Maloyb6f88d92020-11-25 13:29:15 -0500418 struct tipc_service_range r;
Tuong Lien41b416f2019-11-21 15:34:58 +0700419 u32 filter;
Parthasarathy Bhuvaragana4273c72016-02-02 10:52:10 +0100420
Jon Maloyb6f88d92020-11-25 13:29:15 -0500421 r.type = tipc_sub_read(sb, seq.type);
422 r.lower = tipc_sub_read(sb, seq.lower);
423 r.upper = tipc_sub_read(sb, seq.upper);
Tuong Lien41b416f2019-11-21 15:34:58 +0700424 filter = tipc_sub_read(sb, filter);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100425
Jon Maloyda0a75e2018-02-15 10:40:48 +0100426 tipc_sub_get(sub);
Jon Maloy218527f2018-03-29 23:20:41 +0200427 list_add(&sub->service_list, &service->subscriptions);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100428
Tuong Lien41b416f2019-11-21 15:34:58 +0700429 if (filter & TIPC_SUB_NO_STATUS)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100430 return;
431
Tuong Lien41b416f2019-11-21 15:34:58 +0700432 INIT_LIST_HEAD(&publ_list);
Jon Maloyb6f88d92020-11-25 13:29:15 -0500433 service_range_foreach_match(sr, service, r.lower, r.upper) {
Tuong Lien41b416f2019-11-21 15:34:58 +0700434 first = NULL;
Jon Maloy218527f2018-03-29 23:20:41 +0200435 list_for_each_entry(p, &sr->all_publ, all_publ) {
Tuong Lien41b416f2019-11-21 15:34:58 +0700436 if (filter & TIPC_SUB_PORTS)
437 list_add_tail(&p->list, &publ_list);
438 else if (!first || publication_after(first, p))
439 /* Pick this range's *first* publication */
440 first = p;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100441 }
Tuong Lien41b416f2019-11-21 15:34:58 +0700442 if (first)
443 list_add_tail(&first->list, &publ_list);
444 }
445
446 /* Sort the publications before reporting */
447 list_sort(NULL, &publ_list, tipc_publ_sort);
448 list_for_each_entry_safe(p, tmp, &publ_list, list) {
Jon Maloy998d3902021-03-16 22:06:08 -0400449 tipc_sub_report_overlap(sub, p->sr.lower, p->sr.upper,
450 TIPC_PUBLISHED, p->sk.ref, p->sk.node,
Tuong Lien41b416f2019-11-21 15:34:58 +0700451 p->scope, true);
452 list_del_init(&p->list);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100453 }
454}
455
Jon Maloy218527f2018-03-29 23:20:41 +0200456static struct tipc_service *tipc_service_find(struct net *net, u32 type)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100457{
Jon Maloy218527f2018-03-29 23:20:41 +0200458 struct name_table *nt = tipc_name_table(net);
459 struct hlist_head *service_head;
460 struct tipc_service *service;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100461
Jon Maloy218527f2018-03-29 23:20:41 +0200462 service_head = &nt->services[hash(type)];
463 hlist_for_each_entry_rcu(service, service_head, service_list) {
464 if (service->type == type)
465 return service;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100466 }
Sam Ravnborg1fc54d82006-03-20 22:36:47 -0800467 return NULL;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100468};
469
Jon Maloya45ffa62021-03-16 22:06:12 -0400470struct publication *tipc_nametbl_insert_publ(struct net *net,
471 struct tipc_uaddr *ua,
472 struct tipc_socket_addr *sk,
473 u32 key)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100474{
Jon Maloy218527f2018-03-29 23:20:41 +0200475 struct name_table *nt = tipc_name_table(net);
476 struct tipc_service *sc;
477 struct publication *p;
Jon Maloya45ffa62021-03-16 22:06:12 -0400478 u32 type = ua->sr.type;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100479
Jon Maloya45ffa62021-03-16 22:06:12 -0400480 p = tipc_publ_create(ua, sk, key);
Jon Maloyb26b5aa2021-03-16 22:06:09 -0400481 if (!p)
482 return NULL;
483
Jon Maloya45ffa62021-03-16 22:06:12 -0400484 if (ua->sr.lower > ua->sr.upper) {
485 pr_debug("Failed to bind illegal {%u,%u,%u} from node %u\n",
486 type, ua->sr.lower, ua->sr.upper, sk->node);
Sam Ravnborg1fc54d82006-03-20 22:36:47 -0800487 return NULL;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100488 }
Jon Maloy218527f2018-03-29 23:20:41 +0200489 sc = tipc_service_find(net, type);
490 if (!sc)
491 sc = tipc_service_create(type, &nt->services[hash(type)]);
Jon Maloyb26b5aa2021-03-16 22:06:09 -0400492 if (sc && tipc_service_insert_publ(net, sc, p))
493 return p;
494 kfree(p);
495 return NULL;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100496}
497
Jon Maloy2c98da02021-03-16 22:06:13 -0400498struct publication *tipc_nametbl_remove_publ(struct net *net,
499 struct tipc_uaddr *ua,
500 struct tipc_socket_addr *sk,
501 u32 key)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100502{
Jon Maloy5f307212018-05-09 02:59:41 +0200503 struct tipc_subscription *sub, *tmp;
Jon Maloy218527f2018-03-29 23:20:41 +0200504 struct publication *p = NULL;
Jon Maloy2c98da02021-03-16 22:06:13 -0400505 struct service_range *sr;
506 struct tipc_service *sc;
507 u32 upper = ua->sr.upper;
508 u32 lower = ua->sr.lower;
Jon Maloy5f307212018-05-09 02:59:41 +0200509 bool last;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100510
Jon Maloy2c98da02021-03-16 22:06:13 -0400511 sc = tipc_service_find(net, ua->sr.type);
Jon Maloy218527f2018-03-29 23:20:41 +0200512 if (!sc)
Sam Ravnborg1fc54d82006-03-20 22:36:47 -0800513 return NULL;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100514
Jon Maloy218527f2018-03-29 23:20:41 +0200515 spin_lock_bh(&sc->lock);
Jon Maloy5f307212018-05-09 02:59:41 +0200516 sr = tipc_service_find_range(sc, lower, upper);
517 if (!sr)
518 goto exit;
Jon Maloy2c98da02021-03-16 22:06:13 -0400519 p = tipc_service_remove_publ(sr, sk, key);
Jon Maloy5f307212018-05-09 02:59:41 +0200520 if (!p)
521 goto exit;
522
523 /* Notify any waiting subscriptions */
524 last = list_empty(&sr->all_publ);
525 list_for_each_entry_safe(sub, tmp, &sc->subscriptions, service_list) {
526 tipc_sub_report_overlap(sub, lower, upper, TIPC_WITHDRAWN,
Jon Maloy2c98da02021-03-16 22:06:13 -0400527 sk->ref, sk->node, ua->scope, last);
Jon Maloy5f307212018-05-09 02:59:41 +0200528 }
Jon Maloybe47e412018-04-17 21:25:42 +0200529
530 /* Remove service range item if this was its last publication */
Jon Maloy5f307212018-05-09 02:59:41 +0200531 if (list_empty(&sr->all_publ)) {
Tuong Liend5162f32019-12-10 15:21:02 +0700532 rb_erase_augmented(&sr->tree_node, &sc->ranges, &sr_callbacks);
Jon Maloybe47e412018-04-17 21:25:42 +0200533 kfree(sr);
534 }
Jon Maloy218527f2018-03-29 23:20:41 +0200535
536 /* Delete service item if this no more publications and subscriptions */
537 if (RB_EMPTY_ROOT(&sc->ranges) && list_empty(&sc->subscriptions)) {
538 hlist_del_init_rcu(&sc->service_list);
539 kfree_rcu(sc, rcu);
Ying Xuefb9962f2014-12-02 15:00:26 +0800540 }
Jon Maloy5f307212018-05-09 02:59:41 +0200541exit:
Jon Maloy218527f2018-03-29 23:20:41 +0200542 spin_unlock_bh(&sc->lock);
543 return p;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100544}
545
Ben Hutchings2c530402012-07-10 10:55:09 +0000546/**
Jon Maloy66db2392021-03-16 22:06:14 -0400547 * tipc_nametbl_lookup_anycast - perform service instance to socket translation
Randy Dunlap5c5d6792020-11-29 10:32:46 -0800548 * @net: network namespace
549 * @type: message type
550 * @instance: message instance
551 * @dnode: the search domain used during translation
Allan Stephensbc9f8142011-11-07 17:00:54 -0500552 *
Jon Maloy66db2392021-03-16 22:06:14 -0400553 * On entry, 'dnode' is the search domain used during the lookup
554 *
Allan Stephensbc9f8142011-11-07 17:00:54 -0500555 * On exit:
Jon Maloy66db2392021-03-16 22:06:14 -0400556 * - if lookup is deferred to another node, leave 'dnode' unchanged and return 0
557 * - if lookup is attempted and succeeds, set 'dnode' to the publishing node and
558 * return the published (non-zero) port number
559 * - if lookup is attempted and fails, set 'dnode' to 0 and return 0
Jon Maloyf20889f2018-03-29 23:20:42 +0200560 *
561 * Note that for legacy users (node configured with Z.C.N address format) the
562 * 'closest-first' lookup algorithm must be maintained, i.e., if dnode is 0
563 * we must look in the local binding list first
Per Lidenb97bf3f2006-01-02 19:04:38 +0100564 */
Jon Maloy66db2392021-03-16 22:06:14 -0400565u32 tipc_nametbl_lookup_anycast(struct net *net, u32 type,
566 u32 instance, u32 *dnode)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100567{
Jon Maloyb89afb12018-03-22 20:42:48 +0100568 struct tipc_net *tn = tipc_net(net);
569 bool legacy = tn->legacy_addr_format;
570 u32 self = tipc_own_addr(net);
Jon Maloy218527f2018-03-29 23:20:41 +0200571 struct service_range *sr;
572 struct tipc_service *sc;
Jon Maloyf20889f2018-03-29 23:20:42 +0200573 struct list_head *list;
Jon Maloy218527f2018-03-29 23:20:41 +0200574 struct publication *p;
Jon Maloye50e73e2018-03-15 16:48:55 +0100575 u32 port = 0;
Allan Stephensbc9f8142011-11-07 17:00:54 -0500576 u32 node = 0;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100577
Jon Maloyf20889f2018-03-29 23:20:42 +0200578 if (!tipc_in_scope(legacy, *dnode, self))
Per Lidenb97bf3f2006-01-02 19:04:38 +0100579 return 0;
580
Ying Xue97ede292014-12-02 15:00:30 +0800581 rcu_read_lock();
Jon Maloy218527f2018-03-29 23:20:41 +0200582 sc = tipc_service_find(net, type);
583 if (unlikely(!sc))
Tuong Liend5162f32019-12-10 15:21:02 +0700584 goto exit;
Jon Maloy218527f2018-03-29 23:20:41 +0200585
586 spin_lock_bh(&sc->lock);
Tuong Liend5162f32019-12-10 15:21:02 +0700587 service_range_foreach_match(sr, sc, instance, instance) {
588 /* Select lookup algo: local, closest-first or round-robin */
589 if (*dnode == self) {
590 list = &sr->local_publ;
591 if (list_empty(list))
592 continue;
593 p = list_first_entry(list, struct publication,
594 local_publ);
595 list_move_tail(&p->local_publ, &sr->local_publ);
596 } else if (legacy && !*dnode && !list_empty(&sr->local_publ)) {
597 list = &sr->local_publ;
598 p = list_first_entry(list, struct publication,
599 local_publ);
600 list_move_tail(&p->local_publ, &sr->local_publ);
601 } else {
602 list = &sr->all_publ;
603 p = list_first_entry(list, struct publication,
604 all_publ);
605 list_move_tail(&p->all_publ, &sr->all_publ);
606 }
Jon Maloy998d3902021-03-16 22:06:08 -0400607 port = p->sk.ref;
608 node = p->sk.node;
Tuong Liend5162f32019-12-10 15:21:02 +0700609 /* Todo: as for legacy, pick the first matching range only, a
610 * "true" round-robin will be performed as needed.
611 */
612 break;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100613 }
Jon Maloy218527f2018-03-29 23:20:41 +0200614 spin_unlock_bh(&sc->lock);
Tuong Liend5162f32019-12-10 15:21:02 +0700615
616exit:
Ying Xue97ede292014-12-02 15:00:30 +0800617 rcu_read_unlock();
Jon Maloyf20889f2018-03-29 23:20:42 +0200618 *dnode = node;
Jon Maloye50e73e2018-03-15 16:48:55 +0100619 return port;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100620}
621
Jon Maloy66db2392021-03-16 22:06:14 -0400622/* tipc_nametbl_lookup_group(): lookup destinaton(s) in a communication group
623 * Returns a list of one (== group anycast) or more (== group multicast)
624 * destination socket/node pairs matching the given address.
625 * The requester may or may not want to exclude himself from the list.
626 */
627bool tipc_nametbl_lookup_group(struct net *net, u32 type, u32 instance,
628 u32 scope, struct list_head *dsts,
629 int *dstcnt, u32 exclude,
630 bool mcast)
Jon Maloyee106d72017-10-13 11:04:28 +0200631{
632 u32 self = tipc_own_addr(net);
Jon Maloy218527f2018-03-29 23:20:41 +0200633 struct service_range *sr;
634 struct tipc_service *sc;
635 struct publication *p;
Jon Maloyee106d72017-10-13 11:04:28 +0200636
Jon Maloyee106d72017-10-13 11:04:28 +0200637 *dstcnt = 0;
638 rcu_read_lock();
Jon Maloy218527f2018-03-29 23:20:41 +0200639 sc = tipc_service_find(net, type);
640 if (unlikely(!sc))
Jon Maloyee106d72017-10-13 11:04:28 +0200641 goto exit;
Jon Maloy218527f2018-03-29 23:20:41 +0200642
643 spin_lock_bh(&sc->lock);
644
Tuong Liend5162f32019-12-10 15:21:02 +0700645 /* Todo: a full search i.e. service_range_foreach_match() instead? */
646 sr = service_range_match_first(sc->ranges.rb_node, instance, instance);
Jon Maloy218527f2018-03-29 23:20:41 +0200647 if (!sr)
648 goto no_match;
649
650 list_for_each_entry(p, &sr->all_publ, all_publ) {
651 if (p->scope != scope)
652 continue;
Jon Maloy998d3902021-03-16 22:06:08 -0400653 if (p->sk.ref == exclude && p->sk.node == self)
Jon Maloy218527f2018-03-29 23:20:41 +0200654 continue;
Jon Maloy998d3902021-03-16 22:06:08 -0400655 tipc_dest_push(dsts, p->sk.node, p->sk.ref);
Jon Maloy218527f2018-03-29 23:20:41 +0200656 (*dstcnt)++;
Jon Maloy66db2392021-03-16 22:06:14 -0400657 if (mcast)
Jon Maloy218527f2018-03-29 23:20:41 +0200658 continue;
659 list_move_tail(&p->all_publ, &sr->all_publ);
660 break;
Jon Maloyee106d72017-10-13 11:04:28 +0200661 }
Jon Maloy218527f2018-03-29 23:20:41 +0200662no_match:
663 spin_unlock_bh(&sc->lock);
Jon Maloyee106d72017-10-13 11:04:28 +0200664exit:
665 rcu_read_unlock();
666 return !list_empty(dsts);
667}
668
Jon Maloy66db2392021-03-16 22:06:14 -0400669/* tipc_nametbl_lookup_mcast_sockets(): look up node local destinaton sockets
670 * matching the given address
671 * Used on nodes which have received a multicast/broadcast message
672 * Returns a list of local sockets
673 */
674void tipc_nametbl_lookup_mcast_sockets(struct net *net, u32 type, u32 lower,
675 u32 upper, u32 scope, bool exact,
676 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;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100681
Ying Xue97ede292014-12-02 15:00:30 +0800682 rcu_read_lock();
Jon Maloy218527f2018-03-29 23:20:41 +0200683 sc = tipc_service_find(net, type);
684 if (!sc)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100685 goto exit;
686
Jon Maloy218527f2018-03-29 23:20:41 +0200687 spin_lock_bh(&sc->lock);
Tuong Liend5162f32019-12-10 15:21:02 +0700688 service_range_foreach_match(sr, sc, lower, upper) {
Jon Maloy218527f2018-03-29 23:20:41 +0200689 list_for_each_entry(p, &sr->local_publ, local_publ) {
Jon Maloy232d07b2018-01-08 21:03:30 +0100690 if (p->scope == scope || (!exact && p->scope < scope))
Jon Maloy998d3902021-03-16 22:06:08 -0400691 tipc_dest_push(dports, 0, p->sk.ref);
Allan Stephens968edbe2008-07-14 22:45:33 -0700692 }
Per Lidenb97bf3f2006-01-02 19:04:38 +0100693 }
Jon Maloy218527f2018-03-29 23:20:41 +0200694 spin_unlock_bh(&sc->lock);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100695exit:
Ying Xue97ede292014-12-02 15:00:30 +0800696 rcu_read_unlock();
Per Lidenb97bf3f2006-01-02 19:04:38 +0100697}
698
Jon Maloy66db2392021-03-16 22:06:14 -0400699/* tipc_nametbl_lookup_mcast_nodes(): look up all destination nodes matching
700 * the given address. Used in sending node.
701 * Used on nodes which are sending out a multicast/broadcast message
702 * Returns a list of nodes, including own node if applicable
Jon Paul Maloy2ae0b8a2017-01-18 13:50:51 -0500703 */
Jon Maloy66db2392021-03-16 22:06:14 -0400704void tipc_nametbl_lookup_mcast_nodes(struct net *net, u32 type, u32 lower,
705 u32 upper, struct tipc_nlist *nodes)
Jon Paul Maloy2ae0b8a2017-01-18 13:50:51 -0500706{
Jon Maloy218527f2018-03-29 23:20:41 +0200707 struct service_range *sr;
708 struct tipc_service *sc;
709 struct publication *p;
Jon Paul Maloy2ae0b8a2017-01-18 13:50:51 -0500710
711 rcu_read_lock();
Jon Maloy218527f2018-03-29 23:20:41 +0200712 sc = tipc_service_find(net, type);
713 if (!sc)
Jon Paul Maloy2ae0b8a2017-01-18 13:50:51 -0500714 goto exit;
715
Jon Maloy218527f2018-03-29 23:20:41 +0200716 spin_lock_bh(&sc->lock);
Tuong Liend5162f32019-12-10 15:21:02 +0700717 service_range_foreach_match(sr, sc, lower, upper) {
Jon Maloy218527f2018-03-29 23:20:41 +0200718 list_for_each_entry(p, &sr->all_publ, all_publ) {
Jon Maloy998d3902021-03-16 22:06:08 -0400719 tipc_nlist_add(nodes, p->sk.node);
Jon Paul Maloy2ae0b8a2017-01-18 13:50:51 -0500720 }
721 }
Jon Maloy218527f2018-03-29 23:20:41 +0200722 spin_unlock_bh(&sc->lock);
Jon Paul Maloy2ae0b8a2017-01-18 13:50:51 -0500723exit:
724 rcu_read_unlock();
725}
726
Jon Maloy75da2162017-10-13 11:04:23 +0200727/* tipc_nametbl_build_group - build list of communication group members
728 */
729void tipc_nametbl_build_group(struct net *net, struct tipc_group *grp,
Jon Maloy232d07b2018-01-08 21:03:30 +0100730 u32 type, u32 scope)
Jon Maloy75da2162017-10-13 11:04:23 +0200731{
Jon Maloy218527f2018-03-29 23:20:41 +0200732 struct service_range *sr;
733 struct tipc_service *sc;
Jon Maloy75da2162017-10-13 11:04:23 +0200734 struct publication *p;
Jon Maloy218527f2018-03-29 23:20:41 +0200735 struct rb_node *n;
Jon Maloy75da2162017-10-13 11:04:23 +0200736
737 rcu_read_lock();
Jon Maloy218527f2018-03-29 23:20:41 +0200738 sc = tipc_service_find(net, type);
739 if (!sc)
Jon Maloy75da2162017-10-13 11:04:23 +0200740 goto exit;
741
Jon Maloy218527f2018-03-29 23:20:41 +0200742 spin_lock_bh(&sc->lock);
743 for (n = rb_first(&sc->ranges); n; n = rb_next(n)) {
744 sr = container_of(n, struct service_range, tree_node);
745 list_for_each_entry(p, &sr->all_publ, all_publ) {
Jon Maloy232d07b2018-01-08 21:03:30 +0100746 if (p->scope != scope)
Jon Maloy75da2162017-10-13 11:04:23 +0200747 continue;
Jon Maloy998d3902021-03-16 22:06:08 -0400748 tipc_group_add_member(grp, p->sk.node, p->sk.ref, p->sr.lower);
Jon Maloy75da2162017-10-13 11:04:23 +0200749 }
750 }
Jon Maloy218527f2018-03-29 23:20:41 +0200751 spin_unlock_bh(&sc->lock);
Jon Maloy75da2162017-10-13 11:04:23 +0200752exit:
753 rcu_read_unlock();
754}
755
Jon Maloy218527f2018-03-29 23:20:41 +0200756/* tipc_nametbl_publish - add service binding to name table
Per Lidenb97bf3f2006-01-02 19:04:38 +0100757 */
Jon Maloy50a34992021-03-16 22:06:11 -0400758struct publication *tipc_nametbl_publish(struct net *net, struct tipc_uaddr *ua,
759 struct tipc_socket_addr *sk, u32 key)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100760{
Jon Maloy218527f2018-03-29 23:20:41 +0200761 struct name_table *nt = tipc_name_table(net);
762 struct tipc_net *tn = tipc_net(net);
763 struct publication *p = NULL;
764 struct sk_buff *skb = NULL;
Hoang Huu Lecad29292020-06-17 13:56:05 +0700765 u32 rc_dests;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100766
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800767 spin_lock_bh(&tn->nametbl_lock);
Jon Maloy218527f2018-03-29 23:20:41 +0200768
769 if (nt->local_publ_count >= TIPC_MAX_PUBL) {
770 pr_warn("Bind failed, max limit %u reached\n", TIPC_MAX_PUBL);
771 goto exit;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100772 }
Per Lidenb97bf3f2006-01-02 19:04:38 +0100773
Jon Maloya45ffa62021-03-16 22:06:12 -0400774 p = tipc_nametbl_insert_publ(net, ua, sk, key);
Jon Maloy218527f2018-03-29 23:20:41 +0200775 if (p) {
776 nt->local_publ_count++;
777 skb = tipc_named_publish(net, p);
Allan Stephensfd6eced2011-11-09 14:22:52 -0500778 }
Hoang Huu Lecad29292020-06-17 13:56:05 +0700779 rc_dests = nt->rc_dests;
Jon Maloy218527f2018-03-29 23:20:41 +0200780exit:
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800781 spin_unlock_bh(&tn->nametbl_lock);
Ying Xueeab8c0452014-04-28 18:00:10 +0800782
Jon Maloy218527f2018-03-29 23:20:41 +0200783 if (skb)
Hoang Huu Lecad29292020-06-17 13:56:05 +0700784 tipc_node_broadcast(net, skb, rc_dests);
Jon Maloy218527f2018-03-29 23:20:41 +0200785 return p;
Hoang Huu Lecad29292020-06-17 13:56:05 +0700786
Per Lidenb97bf3f2006-01-02 19:04:38 +0100787}
788
789/**
Jon Maloy218527f2018-03-29 23:20:41 +0200790 * tipc_nametbl_withdraw - withdraw a service binding
Randy Dunlap5c5d6792020-11-29 10:32:46 -0800791 * @net: network namespace
Jon Maloy2c98da02021-03-16 22:06:13 -0400792 * @ua: service address/range being unbound
793 * @sk: address of the socket being unbound from
Randy Dunlap5c5d6792020-11-29 10:32:46 -0800794 * @key: target publication key
Per Lidenb97bf3f2006-01-02 19:04:38 +0100795 */
Jon Maloy2c98da02021-03-16 22:06:13 -0400796void tipc_nametbl_withdraw(struct net *net, struct tipc_uaddr *ua,
797 struct tipc_socket_addr *sk, u32 key)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100798{
Jon Maloy218527f2018-03-29 23:20:41 +0200799 struct name_table *nt = tipc_name_table(net);
800 struct tipc_net *tn = tipc_net(net);
Ying Xue54923902014-12-02 15:00:28 +0800801 struct sk_buff *skb = NULL;
Jon Maloy218527f2018-03-29 23:20:41 +0200802 struct publication *p;
Hoang Huu Lecad29292020-06-17 13:56:05 +0700803 u32 rc_dests;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100804
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800805 spin_lock_bh(&tn->nametbl_lock);
Jon Maloy218527f2018-03-29 23:20:41 +0200806
Jon Maloy2c98da02021-03-16 22:06:13 -0400807 p = tipc_nametbl_remove_publ(net, ua, sk, key);
Jon Maloy218527f2018-03-29 23:20:41 +0200808 if (p) {
809 nt->local_publ_count--;
810 skb = tipc_named_withdraw(net, p);
Jon Maloy218527f2018-03-29 23:20:41 +0200811 list_del_init(&p->binding_sock);
812 kfree_rcu(p, rcu);
Ying Xue54923902014-12-02 15:00:28 +0800813 } else {
Jon Maloy218527f2018-03-29 23:20:41 +0200814 pr_err("Failed to remove local publication {%u,%u,%u}/%u\n",
Jon Maloy2c98da02021-03-16 22:06:13 -0400815 ua->sr.type, ua->sr.lower, ua->sr.upper, key);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100816 }
Hoang Huu Lecad29292020-06-17 13:56:05 +0700817 rc_dests = nt->rc_dests;
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800818 spin_unlock_bh(&tn->nametbl_lock);
Ying Xue54923902014-12-02 15:00:28 +0800819
Jon Maloy2c98da02021-03-16 22:06:13 -0400820 if (skb)
Hoang Huu Lecad29292020-06-17 13:56:05 +0700821 tipc_node_broadcast(net, skb, rc_dests);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100822}
823
824/**
Per Liden4323add2006-01-18 00:38:21 +0100825 * tipc_nametbl_subscribe - add a subscription object to the name table
Randy Dunlap5c5d6792020-11-29 10:32:46 -0800826 * @sub: subscription to add
Per Lidenb97bf3f2006-01-02 19:04:38 +0100827 */
Jon Maloyc3317f42018-04-11 22:52:09 +0200828bool tipc_nametbl_subscribe(struct tipc_subscription *sub)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100829{
Jon Maloy218527f2018-03-29 23:20:41 +0200830 struct name_table *nt = tipc_name_table(sub->net);
Jon Maloy5c45ab22018-02-15 10:40:49 +0100831 struct tipc_net *tn = tipc_net(sub->net);
Jon Maloy8985ecc2018-02-15 10:40:46 +0100832 struct tipc_subscr *s = &sub->evt.s;
833 u32 type = tipc_sub_read(s, seq.type);
Jon Maloy218527f2018-03-29 23:20:41 +0200834 struct tipc_service *sc;
Jon Maloyc3317f42018-04-11 22:52:09 +0200835 bool res = true;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100836
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800837 spin_lock_bh(&tn->nametbl_lock);
Jon Maloy218527f2018-03-29 23:20:41 +0200838 sc = tipc_service_find(sub->net, type);
839 if (!sc)
840 sc = tipc_service_create(type, &nt->services[hash(type)]);
841 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 Maloy218527f2018-03-29 23:20:41 +0200846 pr_warn("Failed to subscribe for {%u,%u,%u}\n", type,
847 tipc_sub_read(s, seq.lower),
848 tipc_sub_read(s, seq.upper));
Jon Maloyc3317f42018-04-11 22:52:09 +0200849 res = false;
YOSHIFUJI Hideakic4307282007-02-09 23:25:21 +0900850 }
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800851 spin_unlock_bh(&tn->nametbl_lock);
Jon Maloyc3317f42018-04-11 22:52:09 +0200852 return res;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100853}
854
855/**
Per Liden4323add2006-01-18 00:38:21 +0100856 * tipc_nametbl_unsubscribe - remove a subscription object from name table
Randy Dunlap5c5d6792020-11-29 10:32:46 -0800857 * @sub: subscription to remove
Per Lidenb97bf3f2006-01-02 19:04:38 +0100858 */
Jon Maloy8985ecc2018-02-15 10:40:46 +0100859void tipc_nametbl_unsubscribe(struct tipc_subscription *sub)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100860{
Jon Maloy5c45ab22018-02-15 10:40:49 +0100861 struct tipc_net *tn = tipc_net(sub->net);
Jon Maloy218527f2018-03-29 23:20:41 +0200862 struct tipc_subscr *s = &sub->evt.s;
Jon Maloy8985ecc2018-02-15 10:40:46 +0100863 u32 type = tipc_sub_read(s, seq.type);
Jon Maloy218527f2018-03-29 23:20:41 +0200864 struct tipc_service *sc;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100865
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800866 spin_lock_bh(&tn->nametbl_lock);
Jon Maloy218527f2018-03-29 23:20:41 +0200867 sc = tipc_service_find(sub->net, type);
868 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;
Richard Alpe15931232014-11-20 10:29:20 +01001056 int err;
1057 int i;
1058
1059 if (*last_type)
1060 i = hash(*last_type);
1061 else
1062 i = 0;
1063
1064 for (; i < TIPC_NAMETBL_SIZE; i++) {
Jon Maloy218527f2018-03-29 23:20:41 +02001065 head = &tn->nametbl->services[i];
Richard Alpe15931232014-11-20 10:29:20 +01001066
Hoang Led1841532019-04-09 14:59:24 +07001067 if (*last_type ||
1068 (!i && *last_key && (*last_lower == *last_key))) {
Jon Maloy218527f2018-03-29 23:20:41 +02001069 service = tipc_service_find(net, *last_type);
1070 if (!service)
Richard Alpe15931232014-11-20 10:29:20 +01001071 return -EPIPE;
1072 } else {
Jon Maloy218527f2018-03-29 23:20:41 +02001073 hlist_for_each_entry_rcu(service, head, service_list)
Ying Xue97ede292014-12-02 15:00:30 +08001074 break;
Jon Maloy218527f2018-03-29 23:20:41 +02001075 if (!service)
Richard Alpe15931232014-11-20 10:29:20 +01001076 continue;
1077 }
1078
Jon Maloy218527f2018-03-29 23:20:41 +02001079 hlist_for_each_entry_from_rcu(service, service_list) {
1080 spin_lock_bh(&service->lock);
1081 err = __tipc_nl_service_range_list(msg, service,
1082 last_lower,
1083 last_key);
Richard Alpe15931232014-11-20 10:29:20 +01001084
1085 if (err) {
Jon Maloy218527f2018-03-29 23:20:41 +02001086 *last_type = service->type;
1087 spin_unlock_bh(&service->lock);
Richard Alpe15931232014-11-20 10:29:20 +01001088 return err;
1089 }
Jon Maloy218527f2018-03-29 23:20:41 +02001090 spin_unlock_bh(&service->lock);
Richard Alpe15931232014-11-20 10:29:20 +01001091 }
1092 *last_type = 0;
1093 }
1094 return 0;
1095}
1096
1097int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb)
1098{
Jon Maloy218527f2018-03-29 23:20:41 +02001099 struct net *net = sock_net(skb->sk);
Richard Alpe15931232014-11-20 10:29:20 +01001100 u32 last_type = cb->args[0];
1101 u32 last_lower = cb->args[1];
Jon Maloy218527f2018-03-29 23:20:41 +02001102 u32 last_key = cb->args[2];
1103 int done = cb->args[3];
Richard Alpe15931232014-11-20 10:29:20 +01001104 struct tipc_nl_msg msg;
Jon Maloy218527f2018-03-29 23:20:41 +02001105 int err;
Richard Alpe15931232014-11-20 10:29:20 +01001106
1107 if (done)
1108 return 0;
1109
1110 msg.skb = skb;
1111 msg.portid = NETLINK_CB(cb->skb).portid;
1112 msg.seq = cb->nlh->nlmsg_seq;
1113
Ying Xue97ede292014-12-02 15:00:30 +08001114 rcu_read_lock();
Jon Maloy218527f2018-03-29 23:20:41 +02001115 err = tipc_nl_service_list(net, &msg, &last_type,
1116 &last_lower, &last_key);
Richard Alpe15931232014-11-20 10:29:20 +01001117 if (!err) {
1118 done = 1;
1119 } else if (err != -EMSGSIZE) {
1120 /* We never set seq or call nl_dump_check_consistent() this
1121 * means that setting prev_seq here will cause the consistence
1122 * check to fail in the netlink callback handler. Resulting in
1123 * the NLMSG_DONE message having the NLM_F_DUMP_INTR flag set if
1124 * we got an error.
1125 */
1126 cb->prev_seq = 1;
1127 }
Ying Xue97ede292014-12-02 15:00:30 +08001128 rcu_read_unlock();
Richard Alpe15931232014-11-20 10:29:20 +01001129
1130 cb->args[0] = last_type;
1131 cb->args[1] = last_lower;
Jon Maloy218527f2018-03-29 23:20:41 +02001132 cb->args[2] = last_key;
Richard Alpe15931232014-11-20 10:29:20 +01001133 cb->args[3] = done;
1134
1135 return skb->len;
1136}
Jon Paul Maloy3c724ac2015-02-05 08:36:43 -05001137
Jon Maloya80ae532017-10-13 11:04:22 +02001138struct tipc_dest *tipc_dest_find(struct list_head *l, u32 node, u32 port)
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001139{
Jon Maloya80ae532017-10-13 11:04:22 +02001140 struct tipc_dest *dst;
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001141
Jon Maloya80ae532017-10-13 11:04:22 +02001142 list_for_each_entry(dst, l, list) {
Haiqing Bai30935192018-08-27 09:32:26 +08001143 if (dst->node == node && dst->port == port)
1144 return dst;
Jon Paul Maloy3c724ac2015-02-05 08:36:43 -05001145 }
Jon Maloya80ae532017-10-13 11:04:22 +02001146 return NULL;
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001147}
1148
Jon Maloya80ae532017-10-13 11:04:22 +02001149bool tipc_dest_push(struct list_head *l, u32 node, u32 port)
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001150{
Jon Maloya80ae532017-10-13 11:04:22 +02001151 struct tipc_dest *dst;
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001152
Jon Maloya80ae532017-10-13 11:04:22 +02001153 if (tipc_dest_find(l, node, port))
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001154 return false;
1155
Jon Maloya80ae532017-10-13 11:04:22 +02001156 dst = kmalloc(sizeof(*dst), GFP_ATOMIC);
1157 if (unlikely(!dst))
1158 return false;
Haiqing Bai30935192018-08-27 09:32:26 +08001159 dst->node = node;
1160 dst->port = port;
Jon Maloya80ae532017-10-13 11:04:22 +02001161 list_add(&dst->list, l);
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001162 return true;
1163}
1164
Jon Maloya80ae532017-10-13 11:04:22 +02001165bool tipc_dest_pop(struct list_head *l, u32 *node, u32 *port)
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001166{
Jon Maloya80ae532017-10-13 11:04:22 +02001167 struct tipc_dest *dst;
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001168
1169 if (list_empty(l))
Jon Maloya80ae532017-10-13 11:04:22 +02001170 return false;
1171 dst = list_first_entry(l, typeof(*dst), list);
1172 if (port)
1173 *port = dst->port;
1174 if (node)
1175 *node = dst->node;
1176 list_del(&dst->list);
1177 kfree(dst);
1178 return true;
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001179}
1180
Jon Maloya80ae532017-10-13 11:04:22 +02001181bool tipc_dest_del(struct list_head *l, u32 node, u32 port)
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001182{
Jon Maloya80ae532017-10-13 11:04:22 +02001183 struct tipc_dest *dst;
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001184
Jon Maloya80ae532017-10-13 11:04:22 +02001185 dst = tipc_dest_find(l, node, port);
1186 if (!dst)
1187 return false;
1188 list_del(&dst->list);
1189 kfree(dst);
1190 return true;
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001191}
1192
Jon Maloya80ae532017-10-13 11:04:22 +02001193void tipc_dest_list_purge(struct list_head *l)
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001194{
Jon Maloya80ae532017-10-13 11:04:22 +02001195 struct tipc_dest *dst, *tmp;
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001196
Jon Maloya80ae532017-10-13 11:04:22 +02001197 list_for_each_entry_safe(dst, tmp, l, list) {
1198 list_del(&dst->list);
1199 kfree(dst);
Jon Paul Maloy3c724ac2015-02-05 08:36:43 -05001200 }
1201}
1202
Jon Maloya80ae532017-10-13 11:04:22 +02001203int tipc_dest_list_len(struct list_head *l)
Jon Paul Maloy3c724ac2015-02-05 08:36:43 -05001204{
Jon Maloya80ae532017-10-13 11:04:22 +02001205 struct tipc_dest *dst;
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001206 int i = 0;
Jon Paul Maloy3c724ac2015-02-05 08:36:43 -05001207
Jon Maloya80ae532017-10-13 11:04:22 +02001208 list_for_each_entry(dst, l, list) {
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001209 i++;
Jon Paul Maloy3c724ac2015-02-05 08:36:43 -05001210 }
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001211 return i;
Jon Paul Maloy3c724ac2015-02-05 08:36:43 -05001212}