blob: 92d04dc2a44b7a3e68e425035316a3191fef46f4 [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
Per Lidenb97bf3f2006-01-02 19:04:38 +01006 * All rights reserved.
7 *
Per Liden9ea1fd32006-01-11 13:30:43 +01008 * Redistribution and use in source and binary forms, with or without
Per Lidenb97bf3f2006-01-02 19:04:38 +01009 * modification, are permitted provided that the following conditions are met:
10 *
Per Liden9ea1fd32006-01-11 13:30:43 +010011 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the names of the copyright holders nor the names of its
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
Per Lidenb97bf3f2006-01-02 19:04:38 +010019 *
Per Liden9ea1fd32006-01-11 13:30:43 +010020 * Alternatively, this software may be distributed under the terms of the
21 * GNU General Public License ("GPL") version 2 as published by the Free
22 * Software Foundation.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
Per Lidenb97bf3f2006-01-02 19:04:38 +010034 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
Ying Xue4ac1c8d2015-01-09 15:27:09 +080037#include <net/sock.h>
Tuong Lien41b416f2019-11-21 15:34:58 +070038#include <linux/list_sort.h>
Per Lidenb97bf3f2006-01-02 19:04:38 +010039#include "core.h"
Richard Alpe22ae7cf2015-02-09 09:50:18 +010040#include "netlink.h"
Per Lidenb97bf3f2006-01-02 19:04:38 +010041#include "name_table.h"
42#include "name_distr.h"
Per Lidenb97bf3f2006-01-02 19:04:38 +010043#include "subscr.h"
Ying Xue1da46562015-01-09 15:27:07 +080044#include "bcast.h"
Richard Alpe22ae7cf2015-02-09 09:50:18 +010045#include "addr.h"
Jon Paul Maloy1d7e1c22015-11-19 14:30:42 -050046#include "node.h"
Jon Maloy75da2162017-10-13 11:04:23 +020047#include "group.h"
Per Lidenb97bf3f2006-01-02 19:04:38 +010048
49/**
Jon Maloy218527f2018-03-29 23:20:41 +020050 * struct service_range - container for all bindings of a service range
51 * @lower: service range lower bound
52 * @upper: service range upper bound
53 * @tree_node: member of service range RB tree
54 * @local_publ: list of identical publications made from this node
55 * Used by closest_first lookup and multicast lookup algorithm
56 * @all_publ: all publications identical to this one, whatever node and scope
57 * Used by round-robin lookup algorithm
Per Lidenb97bf3f2006-01-02 19:04:38 +010058 */
Jon Maloy218527f2018-03-29 23:20:41 +020059struct service_range {
60 u32 lower;
61 u32 upper;
62 struct rb_node tree_node;
Jon Maloye50e73e2018-03-15 16:48:55 +010063 struct list_head local_publ;
64 struct list_head all_publ;
Per Lidenb97bf3f2006-01-02 19:04:38 +010065};
66
YOSHIFUJI Hideakic4307282007-02-09 23:25:21 +090067/**
Jon Maloy218527f2018-03-29 23:20:41 +020068 * struct tipc_service - container for all published instances of a service type
69 * @type: 32 bit 'type' value for service
Tuong Lien41b416f2019-11-21 15:34:58 +070070 * @publ_cnt: increasing counter for publications in this service
Jon Maloy218527f2018-03-29 23:20:41 +020071 * @ranges: rb tree containing all service ranges for this service
72 * @service_list: links to adjacent name ranges in hash chain
73 * @subscriptions: list of subscriptions for this service type
74 * @lock: spinlock controlling access to pertaining service ranges/publications
Ying Xue97ede292014-12-02 15:00:30 +080075 * @rcu: RCU callback head used for deferred freeing
Per Lidenb97bf3f2006-01-02 19:04:38 +010076 */
Jon Maloy218527f2018-03-29 23:20:41 +020077struct tipc_service {
Per Lidenb97bf3f2006-01-02 19:04:38 +010078 u32 type;
Tuong Lien41b416f2019-11-21 15:34:58 +070079 u32 publ_cnt;
Jon Maloy218527f2018-03-29 23:20:41 +020080 struct rb_root ranges;
81 struct hlist_node service_list;
Per Lidenb97bf3f2006-01-02 19:04:38 +010082 struct list_head subscriptions;
Jon Maloy218527f2018-03-29 23:20:41 +020083 spinlock_t lock; /* Covers service range list */
Ying Xue97ede292014-12-02 15:00:30 +080084 struct rcu_head rcu;
Per Lidenb97bf3f2006-01-02 19:04:38 +010085};
86
Sam Ravnborg05790c62006-03-20 22:37:04 -080087static int hash(int x)
Per Lidenb97bf3f2006-01-02 19:04:38 +010088{
Ying Xuef046e7d2012-08-16 12:09:11 +000089 return x & (TIPC_NAMETBL_SIZE - 1);
Per Lidenb97bf3f2006-01-02 19:04:38 +010090}
91
92/**
Jon Maloy218527f2018-03-29 23:20:41 +020093 * tipc_publ_create - create a publication structure
Per Lidenb97bf3f2006-01-02 19:04:38 +010094 */
Jon Maloy218527f2018-03-29 23:20:41 +020095static struct publication *tipc_publ_create(u32 type, u32 lower, u32 upper,
96 u32 scope, u32 node, u32 port,
97 u32 key)
Per Lidenb97bf3f2006-01-02 19:04:38 +010098{
Panagiotis Issaris0da974f2006-07-21 14:51:30 -070099 struct publication *publ = kzalloc(sizeof(*publ), GFP_ATOMIC);
Jon Maloy218527f2018-03-29 23:20:41 +0200100
101 if (!publ)
Sam Ravnborg1fc54d82006-03-20 22:36:47 -0800102 return NULL;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100103
Per Lidenb97bf3f2006-01-02 19:04:38 +0100104 publ->type = type;
105 publ->lower = lower;
106 publ->upper = upper;
107 publ->scope = scope;
108 publ->node = node;
Jon Maloye50e73e2018-03-15 16:48:55 +0100109 publ->port = port;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100110 publ->key = key;
Jon Maloye50e73e2018-03-15 16:48:55 +0100111 INIT_LIST_HEAD(&publ->binding_sock);
Jon Maloy218527f2018-03-29 23:20:41 +0200112 INIT_LIST_HEAD(&publ->binding_node);
113 INIT_LIST_HEAD(&publ->local_publ);
114 INIT_LIST_HEAD(&publ->all_publ);
Tuong Lien41b416f2019-11-21 15:34:58 +0700115 INIT_LIST_HEAD(&publ->list);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100116 return publ;
117}
118
119/**
Jon Maloy218527f2018-03-29 23:20:41 +0200120 * tipc_service_create - create a service structure for the specified 'type'
YOSHIFUJI Hideakic4307282007-02-09 23:25:21 +0900121 *
Jon Maloy218527f2018-03-29 23:20:41 +0200122 * Allocates a single range structure and sets it to all 0's.
Per Lidenb97bf3f2006-01-02 19:04:38 +0100123 */
Jon Maloy218527f2018-03-29 23:20:41 +0200124static struct tipc_service *tipc_service_create(u32 type, struct hlist_head *hd)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100125{
Jon Maloy218527f2018-03-29 23:20:41 +0200126 struct tipc_service *service = kzalloc(sizeof(*service), GFP_ATOMIC);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100127
Jon Maloy218527f2018-03-29 23:20:41 +0200128 if (!service) {
129 pr_warn("Service creation failed, no memory\n");
Sam Ravnborg1fc54d82006-03-20 22:36:47 -0800130 return NULL;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100131 }
132
Jon Maloy218527f2018-03-29 23:20:41 +0200133 spin_lock_init(&service->lock);
134 service->type = type;
135 service->ranges = RB_ROOT;
136 INIT_HLIST_NODE(&service->service_list);
137 INIT_LIST_HEAD(&service->subscriptions);
138 hlist_add_head_rcu(&service->service_list, hd);
139 return service;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100140}
141
Ben Hutchings2c530402012-07-10 10:55:09 +0000142/**
Jon Maloy5f307212018-05-09 02:59:41 +0200143 * tipc_service_first_range - find first service range in tree matching instance
YOSHIFUJI Hideakic4307282007-02-09 23:25:21 +0900144 *
Jon Maloy218527f2018-03-29 23:20:41 +0200145 * Very time-critical, so binary search through range rb tree
Per Lidenb97bf3f2006-01-02 19:04:38 +0100146 */
Jon Maloy5f307212018-05-09 02:59:41 +0200147static struct service_range *tipc_service_first_range(struct tipc_service *sc,
148 u32 instance)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100149{
Jon Maloy218527f2018-03-29 23:20:41 +0200150 struct rb_node *n = sc->ranges.rb_node;
151 struct service_range *sr;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100152
Jon Maloy218527f2018-03-29 23:20:41 +0200153 while (n) {
154 sr = container_of(n, struct service_range, tree_node);
155 if (sr->lower > instance)
156 n = n->rb_left;
157 else if (sr->upper < instance)
158 n = n->rb_right;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100159 else
Jon Maloy218527f2018-03-29 23:20:41 +0200160 return sr;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100161 }
Sam Ravnborg1fc54d82006-03-20 22:36:47 -0800162 return NULL;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100163}
164
Jon Maloy5f307212018-05-09 02:59:41 +0200165/* tipc_service_find_range - find service range matching publication parameters
166 */
167static struct service_range *tipc_service_find_range(struct tipc_service *sc,
168 u32 lower, u32 upper)
169{
170 struct rb_node *n = sc->ranges.rb_node;
171 struct service_range *sr;
172
173 sr = tipc_service_first_range(sc, lower);
174 if (!sr)
175 return NULL;
176
177 /* Look for exact match */
178 for (n = &sr->tree_node; n; n = rb_next(n)) {
179 sr = container_of(n, struct service_range, tree_node);
180 if (sr->upper == upper)
181 break;
182 }
183 if (!n || sr->lower != lower || sr->upper != upper)
184 return NULL;
185
186 return sr;
187}
188
Jon Maloy218527f2018-03-29 23:20:41 +0200189static struct service_range *tipc_service_create_range(struct tipc_service *sc,
190 u32 lower, u32 upper)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100191{
Jon Maloy218527f2018-03-29 23:20:41 +0200192 struct rb_node **n, *parent = NULL;
193 struct service_range *sr, *tmp;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100194
Jon Maloy218527f2018-03-29 23:20:41 +0200195 n = &sc->ranges.rb_node;
196 while (*n) {
197 tmp = container_of(*n, struct service_range, tree_node);
198 parent = *n;
199 tmp = container_of(parent, struct service_range, tree_node);
200 if (lower < tmp->lower)
201 n = &(*n)->rb_left;
Jon Maloy37922ea2018-03-29 23:20:43 +0200202 else if (lower > tmp->lower)
203 n = &(*n)->rb_right;
204 else if (upper < tmp->upper)
205 n = &(*n)->rb_left;
Jon Maloy218527f2018-03-29 23:20:41 +0200206 else if (upper > tmp->upper)
207 n = &(*n)->rb_right;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100208 else
Jon Maloy37922ea2018-03-29 23:20:43 +0200209 return tmp;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100210 }
Jon Maloy218527f2018-03-29 23:20:41 +0200211 sr = kzalloc(sizeof(*sr), GFP_ATOMIC);
212 if (!sr)
213 return NULL;
214 sr->lower = lower;
215 sr->upper = upper;
216 INIT_LIST_HEAD(&sr->local_publ);
217 INIT_LIST_HEAD(&sr->all_publ);
218 rb_link_node(&sr->tree_node, parent, n);
219 rb_insert_color(&sr->tree_node, &sc->ranges);
220 return sr;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100221}
222
Jon Maloy218527f2018-03-29 23:20:41 +0200223static struct publication *tipc_service_insert_publ(struct net *net,
224 struct tipc_service *sc,
Ying Xue34747532015-01-09 15:27:10 +0800225 u32 type, u32 lower,
226 u32 upper, u32 scope,
Jon Maloy218527f2018-03-29 23:20:41 +0200227 u32 node, u32 port,
228 u32 key)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100229{
Jon Maloy218527f2018-03-29 23:20:41 +0200230 struct tipc_subscription *sub, *tmp;
231 struct service_range *sr;
232 struct publication *p;
233 bool first = false;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100234
Jon Maloy37922ea2018-03-29 23:20:43 +0200235 sr = tipc_service_create_range(sc, lower, upper);
236 if (!sr)
237 goto err;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100238
Jon Maloy37922ea2018-03-29 23:20:43 +0200239 first = list_empty(&sr->all_publ);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100240
Jon Maloy218527f2018-03-29 23:20:41 +0200241 /* Return if the publication already exists */
242 list_for_each_entry(p, &sr->all_publ, all_publ) {
243 if (p->key == key && (!p->node || p->node == node))
244 return NULL;
245 }
Per Lidenb97bf3f2006-01-02 19:04:38 +0100246
Jon Maloy218527f2018-03-29 23:20:41 +0200247 /* Create and insert publication */
248 p = tipc_publ_create(type, lower, upper, scope, node, port, key);
249 if (!p)
250 goto err;
Tuong Lien41b416f2019-11-21 15:34:58 +0700251 /* Suppose there shouldn't be a huge gap btw publs i.e. >INT_MAX */
252 p->id = sc->publ_cnt++;
Jon Maloyba765ec2018-03-15 16:48:53 +0100253 if (in_own_node(net, node))
Jon Maloy218527f2018-03-29 23:20:41 +0200254 list_add(&p->local_publ, &sr->local_publ);
255 list_add(&p->all_publ, &sr->all_publ);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100256
Paul Gortmaker617d3c72012-04-30 15:29:02 -0400257 /* Any subscriptions waiting for notification? */
Jon Maloy218527f2018-03-29 23:20:41 +0200258 list_for_each_entry_safe(sub, tmp, &sc->subscriptions, service_list) {
259 tipc_sub_report_overlap(sub, p->lower, p->upper, TIPC_PUBLISHED,
260 p->port, p->node, p->scope, first);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100261 }
Jon Maloy218527f2018-03-29 23:20:41 +0200262 return p;
263err:
264 pr_warn("Failed to bind to %u,%u,%u, no memory\n", type, lower, upper);
265 return NULL;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100266}
267
268/**
Jon Maloy218527f2018-03-29 23:20:41 +0200269 * tipc_service_remove_publ - remove a publication from a service
Per Lidenb97bf3f2006-01-02 19:04:38 +0100270 */
Jon Maloy5f307212018-05-09 02:59:41 +0200271static struct publication *tipc_service_remove_publ(struct service_range *sr,
272 u32 node, u32 key)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100273{
Jon Maloy218527f2018-03-29 23:20:41 +0200274 struct publication *p;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100275
Jon Maloy218527f2018-03-29 23:20:41 +0200276 list_for_each_entry(p, &sr->all_publ, all_publ) {
277 if (p->key != key || (node && node != p->node))
278 continue;
Jon Maloy5f307212018-05-09 02:59:41 +0200279 list_del(&p->all_publ);
280 list_del(&p->local_publ);
281 return p;
Allan Stephensf6f0a4d2011-05-30 10:48:48 -0400282 }
Jon Maloy5f307212018-05-09 02:59:41 +0200283 return NULL;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100284}
285
286/**
Tuong Lien41b416f2019-11-21 15:34:58 +0700287 * Code reused: time_after32() for the same purpose
288 */
289#define publication_after(pa, pb) time_after32((pa)->id, (pb)->id)
290static int tipc_publ_sort(void *priv, struct list_head *a,
291 struct list_head *b)
292{
293 struct publication *pa, *pb;
294
295 pa = container_of(a, struct publication, list);
296 pb = container_of(b, struct publication, list);
297 return publication_after(pa, pb);
298}
299
300/**
Jon Maloy218527f2018-03-29 23:20:41 +0200301 * tipc_service_subscribe - attach a subscription, and optionally
302 * issue the prescribed number of events if there is any service
303 * range overlapping with the requested range
Per Lidenb97bf3f2006-01-02 19:04:38 +0100304 */
Jon Maloy218527f2018-03-29 23:20:41 +0200305static void tipc_service_subscribe(struct tipc_service *service,
Jon Maloy8985ecc2018-02-15 10:40:46 +0100306 struct tipc_subscription *sub)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100307{
Jon Maloy218527f2018-03-29 23:20:41 +0200308 struct tipc_subscr *sb = &sub->evt.s;
Tuong Lien41b416f2019-11-21 15:34:58 +0700309 struct publication *p, *first, *tmp;
310 struct list_head publ_list;
Jon Maloy218527f2018-03-29 23:20:41 +0200311 struct service_range *sr;
Parthasarathy Bhuvaragana4273c72016-02-02 10:52:10 +0100312 struct tipc_name_seq ns;
Jon Maloy218527f2018-03-29 23:20:41 +0200313 struct rb_node *n;
Tuong Lien41b416f2019-11-21 15:34:58 +0700314 u32 filter;
Parthasarathy Bhuvaragana4273c72016-02-02 10:52:10 +0100315
Jon Maloy218527f2018-03-29 23:20:41 +0200316 ns.type = tipc_sub_read(sb, seq.type);
317 ns.lower = tipc_sub_read(sb, seq.lower);
318 ns.upper = tipc_sub_read(sb, seq.upper);
Tuong Lien41b416f2019-11-21 15:34:58 +0700319 filter = tipc_sub_read(sb, filter);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100320
Jon Maloyda0a75e2018-02-15 10:40:48 +0100321 tipc_sub_get(sub);
Jon Maloy218527f2018-03-29 23:20:41 +0200322 list_add(&sub->service_list, &service->subscriptions);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100323
Tuong Lien41b416f2019-11-21 15:34:58 +0700324 if (filter & TIPC_SUB_NO_STATUS)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100325 return;
326
Tuong Lien41b416f2019-11-21 15:34:58 +0700327 INIT_LIST_HEAD(&publ_list);
Jon Maloy218527f2018-03-29 23:20:41 +0200328 for (n = rb_first(&service->ranges); n; n = rb_next(n)) {
329 sr = container_of(n, struct service_range, tree_node);
330 if (sr->lower > ns.upper)
331 break;
332 if (!tipc_sub_check_overlap(&ns, sr->lower, sr->upper))
333 continue;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100334
Tuong Lien41b416f2019-11-21 15:34:58 +0700335 first = NULL;
Jon Maloy218527f2018-03-29 23:20:41 +0200336 list_for_each_entry(p, &sr->all_publ, all_publ) {
Tuong Lien41b416f2019-11-21 15:34:58 +0700337 if (filter & TIPC_SUB_PORTS)
338 list_add_tail(&p->list, &publ_list);
339 else if (!first || publication_after(first, p))
340 /* Pick this range's *first* publication */
341 first = p;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100342 }
Tuong Lien41b416f2019-11-21 15:34:58 +0700343 if (first)
344 list_add_tail(&first->list, &publ_list);
345 }
346
347 /* Sort the publications before reporting */
348 list_sort(NULL, &publ_list, tipc_publ_sort);
349 list_for_each_entry_safe(p, tmp, &publ_list, list) {
350 tipc_sub_report_overlap(sub, p->lower, p->upper,
351 TIPC_PUBLISHED, p->port, p->node,
352 p->scope, true);
353 list_del_init(&p->list);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100354 }
355}
356
Jon Maloy218527f2018-03-29 23:20:41 +0200357static struct tipc_service *tipc_service_find(struct net *net, u32 type)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100358{
Jon Maloy218527f2018-03-29 23:20:41 +0200359 struct name_table *nt = tipc_name_table(net);
360 struct hlist_head *service_head;
361 struct tipc_service *service;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100362
Jon Maloy218527f2018-03-29 23:20:41 +0200363 service_head = &nt->services[hash(type)];
364 hlist_for_each_entry_rcu(service, service_head, service_list) {
365 if (service->type == type)
366 return service;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100367 }
Sam Ravnborg1fc54d82006-03-20 22:36:47 -0800368 return NULL;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100369};
370
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800371struct publication *tipc_nametbl_insert_publ(struct net *net, u32 type,
Jon Maloy218527f2018-03-29 23:20:41 +0200372 u32 lower, u32 upper,
373 u32 scope, u32 node,
374 u32 port, u32 key)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100375{
Jon Maloy218527f2018-03-29 23:20:41 +0200376 struct name_table *nt = tipc_name_table(net);
377 struct tipc_service *sc;
378 struct publication *p;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100379
Jon Maloy928df182018-03-15 16:48:51 +0100380 if (scope > TIPC_NODE_SCOPE || lower > upper) {
Jon Maloy218527f2018-03-29 23:20:41 +0200381 pr_debug("Failed to bind illegal {%u,%u,%u} with scope %u\n",
Erik Hugne2cf8aa12012-06-29 00:16:37 -0400382 type, lower, upper, scope);
Sam Ravnborg1fc54d82006-03-20 22:36:47 -0800383 return NULL;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100384 }
Jon Maloy218527f2018-03-29 23:20:41 +0200385 sc = tipc_service_find(net, type);
386 if (!sc)
387 sc = tipc_service_create(type, &nt->services[hash(type)]);
388 if (!sc)
Sam Ravnborg1fc54d82006-03-20 22:36:47 -0800389 return NULL;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100390
Jon Maloy218527f2018-03-29 23:20:41 +0200391 spin_lock_bh(&sc->lock);
392 p = tipc_service_insert_publ(net, sc, type, lower, upper,
393 scope, node, port, key);
394 spin_unlock_bh(&sc->lock);
395 return p;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100396}
397
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800398struct publication *tipc_nametbl_remove_publ(struct net *net, u32 type,
Jon Maloy37922ea2018-03-29 23:20:43 +0200399 u32 lower, u32 upper,
400 u32 node, u32 key)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100401{
Jon Maloy218527f2018-03-29 23:20:41 +0200402 struct tipc_service *sc = tipc_service_find(net, type);
Jon Maloy5f307212018-05-09 02:59:41 +0200403 struct tipc_subscription *sub, *tmp;
Jon Maloybe47e412018-04-17 21:25:42 +0200404 struct service_range *sr = NULL;
Jon Maloy218527f2018-03-29 23:20:41 +0200405 struct publication *p = NULL;
Jon Maloy5f307212018-05-09 02:59:41 +0200406 bool last;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100407
Jon Maloy218527f2018-03-29 23:20:41 +0200408 if (!sc)
Sam Ravnborg1fc54d82006-03-20 22:36:47 -0800409 return NULL;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100410
Jon Maloy218527f2018-03-29 23:20:41 +0200411 spin_lock_bh(&sc->lock);
Jon Maloy5f307212018-05-09 02:59:41 +0200412 sr = tipc_service_find_range(sc, lower, upper);
413 if (!sr)
414 goto exit;
415 p = tipc_service_remove_publ(sr, node, key);
416 if (!p)
417 goto exit;
418
419 /* Notify any waiting subscriptions */
420 last = list_empty(&sr->all_publ);
421 list_for_each_entry_safe(sub, tmp, &sc->subscriptions, service_list) {
422 tipc_sub_report_overlap(sub, lower, upper, TIPC_WITHDRAWN,
423 p->port, node, p->scope, last);
424 }
Jon Maloybe47e412018-04-17 21:25:42 +0200425
426 /* Remove service range item if this was its last publication */
Jon Maloy5f307212018-05-09 02:59:41 +0200427 if (list_empty(&sr->all_publ)) {
Jon Maloybe47e412018-04-17 21:25:42 +0200428 rb_erase(&sr->tree_node, &sc->ranges);
429 kfree(sr);
430 }
Jon Maloy218527f2018-03-29 23:20:41 +0200431
432 /* Delete service item if this no more publications and subscriptions */
433 if (RB_EMPTY_ROOT(&sc->ranges) && list_empty(&sc->subscriptions)) {
434 hlist_del_init_rcu(&sc->service_list);
435 kfree_rcu(sc, rcu);
Ying Xuefb9962f2014-12-02 15:00:26 +0800436 }
Jon Maloy5f307212018-05-09 02:59:41 +0200437exit:
Jon Maloy218527f2018-03-29 23:20:41 +0200438 spin_unlock_bh(&sc->lock);
439 return p;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100440}
441
Ben Hutchings2c530402012-07-10 10:55:09 +0000442/**
Jon Maloy218527f2018-03-29 23:20:41 +0200443 * tipc_nametbl_translate - perform service instance to socket translation
Per Lidenb97bf3f2006-01-02 19:04:38 +0100444 *
Jon Maloyf20889f2018-03-29 23:20:42 +0200445 * On entry, 'dnode' is the search domain used during translation.
Allan Stephensbc9f8142011-11-07 17:00:54 -0500446 *
447 * On exit:
Jon Maloyf20889f2018-03-29 23:20:42 +0200448 * - if translation is deferred to another node, leave 'dnode' unchanged and
449 * return 0
450 * - if translation is attempted and succeeds, set 'dnode' to the publishing
451 * node and return the published (non-zero) port number
452 * - if translation is attempted and fails, set 'dnode' to 0 and return 0
453 *
454 * Note that for legacy users (node configured with Z.C.N address format) the
455 * 'closest-first' lookup algorithm must be maintained, i.e., if dnode is 0
456 * we must look in the local binding list first
Per Lidenb97bf3f2006-01-02 19:04:38 +0100457 */
Jon Maloyf20889f2018-03-29 23:20:42 +0200458u32 tipc_nametbl_translate(struct net *net, u32 type, u32 instance, u32 *dnode)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100459{
Jon Maloyb89afb12018-03-22 20:42:48 +0100460 struct tipc_net *tn = tipc_net(net);
461 bool legacy = tn->legacy_addr_format;
462 u32 self = tipc_own_addr(net);
Jon Maloy218527f2018-03-29 23:20:41 +0200463 struct service_range *sr;
464 struct tipc_service *sc;
Jon Maloyf20889f2018-03-29 23:20:42 +0200465 struct list_head *list;
Jon Maloy218527f2018-03-29 23:20:41 +0200466 struct publication *p;
Jon Maloye50e73e2018-03-15 16:48:55 +0100467 u32 port = 0;
Allan Stephensbc9f8142011-11-07 17:00:54 -0500468 u32 node = 0;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100469
Jon Maloyf20889f2018-03-29 23:20:42 +0200470 if (!tipc_in_scope(legacy, *dnode, self))
Per Lidenb97bf3f2006-01-02 19:04:38 +0100471 return 0;
472
Ying Xue97ede292014-12-02 15:00:30 +0800473 rcu_read_lock();
Jon Maloy218527f2018-03-29 23:20:41 +0200474 sc = tipc_service_find(net, type);
475 if (unlikely(!sc))
Per Lidenb97bf3f2006-01-02 19:04:38 +0100476 goto not_found;
Jon Maloy218527f2018-03-29 23:20:41 +0200477
478 spin_lock_bh(&sc->lock);
Jon Maloy5f307212018-05-09 02:59:41 +0200479 sr = tipc_service_first_range(sc, instance);
Jon Maloy218527f2018-03-29 23:20:41 +0200480 if (unlikely(!sr))
Ying Xuefb9962f2014-12-02 15:00:26 +0800481 goto no_match;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100482
Jon Maloyf20889f2018-03-29 23:20:42 +0200483 /* Select lookup algorithm: local, closest-first or round-robin */
484 if (*dnode == self) {
485 list = &sr->local_publ;
486 if (list_empty(list))
Allan Stephensf6f0a4d2011-05-30 10:48:48 -0400487 goto no_match;
Jon Maloyf20889f2018-03-29 23:20:42 +0200488 p = list_first_entry(list, struct publication, local_publ);
489 list_move_tail(&p->local_publ, &sr->local_publ);
490 } else if (legacy && !*dnode && !list_empty(&sr->local_publ)) {
491 list = &sr->local_publ;
492 p = list_first_entry(list, struct publication, local_publ);
Jon Maloy218527f2018-03-29 23:20:41 +0200493 list_move_tail(&p->local_publ, &sr->local_publ);
Jon Maloyba765ec2018-03-15 16:48:53 +0100494 } else {
Jon Maloyf20889f2018-03-29 23:20:42 +0200495 list = &sr->all_publ;
496 p = list_first_entry(list, struct publication, all_publ);
Jon Maloy218527f2018-03-29 23:20:41 +0200497 list_move_tail(&p->all_publ, &sr->all_publ);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100498 }
Jon Maloy218527f2018-03-29 23:20:41 +0200499 port = p->port;
500 node = p->node;
Allan Stephensf6f0a4d2011-05-30 10:48:48 -0400501no_match:
Jon Maloy218527f2018-03-29 23:20:41 +0200502 spin_unlock_bh(&sc->lock);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100503not_found:
Ying Xue97ede292014-12-02 15:00:30 +0800504 rcu_read_unlock();
Jon Maloyf20889f2018-03-29 23:20:42 +0200505 *dnode = node;
Jon Maloye50e73e2018-03-15 16:48:55 +0100506 return port;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100507}
508
Jon Maloy232d07b2018-01-08 21:03:30 +0100509bool tipc_nametbl_lookup(struct net *net, u32 type, u32 instance, u32 scope,
Jon Maloyee106d72017-10-13 11:04:28 +0200510 struct list_head *dsts, int *dstcnt, u32 exclude,
511 bool all)
512{
513 u32 self = tipc_own_addr(net);
Jon Maloy218527f2018-03-29 23:20:41 +0200514 struct service_range *sr;
515 struct tipc_service *sc;
516 struct publication *p;
Jon Maloyee106d72017-10-13 11:04:28 +0200517
Jon Maloyee106d72017-10-13 11:04:28 +0200518 *dstcnt = 0;
519 rcu_read_lock();
Jon Maloy218527f2018-03-29 23:20:41 +0200520 sc = tipc_service_find(net, type);
521 if (unlikely(!sc))
Jon Maloyee106d72017-10-13 11:04:28 +0200522 goto exit;
Jon Maloy218527f2018-03-29 23:20:41 +0200523
524 spin_lock_bh(&sc->lock);
525
Jon Maloy5f307212018-05-09 02:59:41 +0200526 sr = tipc_service_first_range(sc, instance);
Jon Maloy218527f2018-03-29 23:20:41 +0200527 if (!sr)
528 goto no_match;
529
530 list_for_each_entry(p, &sr->all_publ, all_publ) {
531 if (p->scope != scope)
532 continue;
533 if (p->port == exclude && p->node == self)
534 continue;
535 tipc_dest_push(dsts, p->node, p->port);
536 (*dstcnt)++;
537 if (all)
538 continue;
539 list_move_tail(&p->all_publ, &sr->all_publ);
540 break;
Jon Maloyee106d72017-10-13 11:04:28 +0200541 }
Jon Maloy218527f2018-03-29 23:20:41 +0200542no_match:
543 spin_unlock_bh(&sc->lock);
Jon Maloyee106d72017-10-13 11:04:28 +0200544exit:
545 rcu_read_unlock();
546 return !list_empty(dsts);
547}
548
Jon Maloyba765ec2018-03-15 16:48:53 +0100549void tipc_nametbl_mc_lookup(struct net *net, u32 type, u32 lower, u32 upper,
550 u32 scope, bool exact, struct list_head *dports)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100551{
Jon Maloy218527f2018-03-29 23:20:41 +0200552 struct service_range *sr;
553 struct tipc_service *sc;
Jon Maloy232d07b2018-01-08 21:03:30 +0100554 struct publication *p;
Jon Maloy218527f2018-03-29 23:20:41 +0200555 struct rb_node *n;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100556
Ying Xue97ede292014-12-02 15:00:30 +0800557 rcu_read_lock();
Jon Maloy218527f2018-03-29 23:20:41 +0200558 sc = tipc_service_find(net, type);
559 if (!sc)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100560 goto exit;
561
Jon Maloy218527f2018-03-29 23:20:41 +0200562 spin_lock_bh(&sc->lock);
563
564 for (n = rb_first(&sc->ranges); n; n = rb_next(n)) {
565 sr = container_of(n, struct service_range, tree_node);
566 if (sr->upper < lower)
567 continue;
568 if (sr->lower > upper)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100569 break;
Jon Maloy218527f2018-03-29 23:20:41 +0200570 list_for_each_entry(p, &sr->local_publ, local_publ) {
Jon Maloy232d07b2018-01-08 21:03:30 +0100571 if (p->scope == scope || (!exact && p->scope < scope))
Jon Maloye50e73e2018-03-15 16:48:55 +0100572 tipc_dest_push(dports, 0, p->port);
Allan Stephens968edbe2008-07-14 22:45:33 -0700573 }
Per Lidenb97bf3f2006-01-02 19:04:38 +0100574 }
Jon Maloy218527f2018-03-29 23:20:41 +0200575 spin_unlock_bh(&sc->lock);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100576exit:
Ying Xue97ede292014-12-02 15:00:30 +0800577 rcu_read_unlock();
Per Lidenb97bf3f2006-01-02 19:04:38 +0100578}
579
Jon Paul Maloy2ae0b8a2017-01-18 13:50:51 -0500580/* tipc_nametbl_lookup_dst_nodes - find broadcast destination nodes
581 * - Creates list of nodes that overlap the given multicast address
Jon Maloy218527f2018-03-29 23:20:41 +0200582 * - Determines if any node local destinations overlap
Jon Paul Maloy2ae0b8a2017-01-18 13:50:51 -0500583 */
584void tipc_nametbl_lookup_dst_nodes(struct net *net, u32 type, u32 lower,
Jon Maloye9a03442018-01-12 20:56:50 +0100585 u32 upper, struct tipc_nlist *nodes)
Jon Paul Maloy2ae0b8a2017-01-18 13:50:51 -0500586{
Jon Maloy218527f2018-03-29 23:20:41 +0200587 struct service_range *sr;
588 struct tipc_service *sc;
589 struct publication *p;
590 struct rb_node *n;
Jon Paul Maloy2ae0b8a2017-01-18 13:50:51 -0500591
592 rcu_read_lock();
Jon Maloy218527f2018-03-29 23:20:41 +0200593 sc = tipc_service_find(net, type);
594 if (!sc)
Jon Paul Maloy2ae0b8a2017-01-18 13:50:51 -0500595 goto exit;
596
Jon Maloy218527f2018-03-29 23:20:41 +0200597 spin_lock_bh(&sc->lock);
598
599 for (n = rb_first(&sc->ranges); n; n = rb_next(n)) {
600 sr = container_of(n, struct service_range, tree_node);
601 if (sr->upper < lower)
602 continue;
603 if (sr->lower > upper)
604 break;
605 list_for_each_entry(p, &sr->all_publ, all_publ) {
606 tipc_nlist_add(nodes, p->node);
Jon Paul Maloy2ae0b8a2017-01-18 13:50:51 -0500607 }
608 }
Jon Maloy218527f2018-03-29 23:20:41 +0200609 spin_unlock_bh(&sc->lock);
Jon Paul Maloy2ae0b8a2017-01-18 13:50:51 -0500610exit:
611 rcu_read_unlock();
612}
613
Jon Maloy75da2162017-10-13 11:04:23 +0200614/* tipc_nametbl_build_group - build list of communication group members
615 */
616void tipc_nametbl_build_group(struct net *net, struct tipc_group *grp,
Jon Maloy232d07b2018-01-08 21:03:30 +0100617 u32 type, u32 scope)
Jon Maloy75da2162017-10-13 11:04:23 +0200618{
Jon Maloy218527f2018-03-29 23:20:41 +0200619 struct service_range *sr;
620 struct tipc_service *sc;
Jon Maloy75da2162017-10-13 11:04:23 +0200621 struct publication *p;
Jon Maloy218527f2018-03-29 23:20:41 +0200622 struct rb_node *n;
Jon Maloy75da2162017-10-13 11:04:23 +0200623
624 rcu_read_lock();
Jon Maloy218527f2018-03-29 23:20:41 +0200625 sc = tipc_service_find(net, type);
626 if (!sc)
Jon Maloy75da2162017-10-13 11:04:23 +0200627 goto exit;
628
Jon Maloy218527f2018-03-29 23:20:41 +0200629 spin_lock_bh(&sc->lock);
630 for (n = rb_first(&sc->ranges); n; n = rb_next(n)) {
631 sr = container_of(n, struct service_range, tree_node);
632 list_for_each_entry(p, &sr->all_publ, all_publ) {
Jon Maloy232d07b2018-01-08 21:03:30 +0100633 if (p->scope != scope)
Jon Maloy75da2162017-10-13 11:04:23 +0200634 continue;
Jon Maloye50e73e2018-03-15 16:48:55 +0100635 tipc_group_add_member(grp, p->node, p->port, p->lower);
Jon Maloy75da2162017-10-13 11:04:23 +0200636 }
637 }
Jon Maloy218527f2018-03-29 23:20:41 +0200638 spin_unlock_bh(&sc->lock);
Jon Maloy75da2162017-10-13 11:04:23 +0200639exit:
640 rcu_read_unlock();
641}
642
Jon Maloy218527f2018-03-29 23:20:41 +0200643/* tipc_nametbl_publish - add service binding to name table
Per Lidenb97bf3f2006-01-02 19:04:38 +0100644 */
Ying Xuef2f98002015-01-09 15:27:05 +0800645struct publication *tipc_nametbl_publish(struct net *net, u32 type, u32 lower,
Jon Maloy218527f2018-03-29 23:20:41 +0200646 u32 upper, u32 scope, u32 port,
Ying Xuef2f98002015-01-09 15:27:05 +0800647 u32 key)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100648{
Jon Maloy218527f2018-03-29 23:20:41 +0200649 struct name_table *nt = tipc_name_table(net);
650 struct tipc_net *tn = tipc_net(net);
651 struct publication *p = NULL;
652 struct sk_buff *skb = NULL;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100653
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800654 spin_lock_bh(&tn->nametbl_lock);
Jon Maloy218527f2018-03-29 23:20:41 +0200655
656 if (nt->local_publ_count >= TIPC_MAX_PUBL) {
657 pr_warn("Bind failed, max limit %u reached\n", TIPC_MAX_PUBL);
658 goto exit;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100659 }
Per Lidenb97bf3f2006-01-02 19:04:38 +0100660
Jon Maloy218527f2018-03-29 23:20:41 +0200661 p = tipc_nametbl_insert_publ(net, type, lower, upper, scope,
662 tipc_own_addr(net), port, key);
663 if (p) {
664 nt->local_publ_count++;
665 skb = tipc_named_publish(net, p);
Allan Stephensfd6eced2011-11-09 14:22:52 -0500666 }
Jon Maloy218527f2018-03-29 23:20:41 +0200667exit:
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800668 spin_unlock_bh(&tn->nametbl_lock);
Ying Xueeab8c0452014-04-28 18:00:10 +0800669
Jon Maloy218527f2018-03-29 23:20:41 +0200670 if (skb)
671 tipc_node_broadcast(net, skb);
672 return p;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100673}
674
675/**
Jon Maloy218527f2018-03-29 23:20:41 +0200676 * tipc_nametbl_withdraw - withdraw a service binding
Per Lidenb97bf3f2006-01-02 19:04:38 +0100677 */
Jon Maloy218527f2018-03-29 23:20:41 +0200678int tipc_nametbl_withdraw(struct net *net, u32 type, u32 lower,
Jon Maloy37922ea2018-03-29 23:20:43 +0200679 u32 upper, u32 key)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100680{
Jon Maloy218527f2018-03-29 23:20:41 +0200681 struct name_table *nt = tipc_name_table(net);
682 struct tipc_net *tn = tipc_net(net);
683 u32 self = tipc_own_addr(net);
Ying Xue54923902014-12-02 15:00:28 +0800684 struct sk_buff *skb = NULL;
Jon Maloy218527f2018-03-29 23:20:41 +0200685 struct publication *p;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100686
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800687 spin_lock_bh(&tn->nametbl_lock);
Jon Maloy218527f2018-03-29 23:20:41 +0200688
Jon Maloy37922ea2018-03-29 23:20:43 +0200689 p = tipc_nametbl_remove_publ(net, type, lower, upper, self, key);
Jon Maloy218527f2018-03-29 23:20:41 +0200690 if (p) {
691 nt->local_publ_count--;
692 skb = tipc_named_withdraw(net, p);
Jon Maloy218527f2018-03-29 23:20:41 +0200693 list_del_init(&p->binding_sock);
694 kfree_rcu(p, rcu);
Ying Xue54923902014-12-02 15:00:28 +0800695 } else {
Jon Maloy218527f2018-03-29 23:20:41 +0200696 pr_err("Failed to remove local publication {%u,%u,%u}/%u\n",
Jon Maloy37922ea2018-03-29 23:20:43 +0200697 type, lower, upper, key);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100698 }
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800699 spin_unlock_bh(&tn->nametbl_lock);
Ying Xue54923902014-12-02 15:00:28 +0800700
701 if (skb) {
Jon Paul Maloy1d7e1c22015-11-19 14:30:42 -0500702 tipc_node_broadcast(net, skb);
Ying Xue54923902014-12-02 15:00:28 +0800703 return 1;
704 }
Per Lidenb97bf3f2006-01-02 19:04:38 +0100705 return 0;
706}
707
708/**
Per Liden4323add2006-01-18 00:38:21 +0100709 * tipc_nametbl_subscribe - add a subscription object to the name table
Per Lidenb97bf3f2006-01-02 19:04:38 +0100710 */
Jon Maloyc3317f42018-04-11 22:52:09 +0200711bool tipc_nametbl_subscribe(struct tipc_subscription *sub)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100712{
Jon Maloy218527f2018-03-29 23:20:41 +0200713 struct name_table *nt = tipc_name_table(sub->net);
Jon Maloy5c45ab22018-02-15 10:40:49 +0100714 struct tipc_net *tn = tipc_net(sub->net);
Jon Maloy8985ecc2018-02-15 10:40:46 +0100715 struct tipc_subscr *s = &sub->evt.s;
716 u32 type = tipc_sub_read(s, seq.type);
Jon Maloy218527f2018-03-29 23:20:41 +0200717 struct tipc_service *sc;
Jon Maloyc3317f42018-04-11 22:52:09 +0200718 bool res = true;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100719
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800720 spin_lock_bh(&tn->nametbl_lock);
Jon Maloy218527f2018-03-29 23:20:41 +0200721 sc = tipc_service_find(sub->net, type);
722 if (!sc)
723 sc = tipc_service_create(type, &nt->services[hash(type)]);
724 if (sc) {
725 spin_lock_bh(&sc->lock);
726 tipc_service_subscribe(sc, sub);
727 spin_unlock_bh(&sc->lock);
YOSHIFUJI Hideakic4307282007-02-09 23:25:21 +0900728 } else {
Jon Maloy218527f2018-03-29 23:20:41 +0200729 pr_warn("Failed to subscribe for {%u,%u,%u}\n", type,
730 tipc_sub_read(s, seq.lower),
731 tipc_sub_read(s, seq.upper));
Jon Maloyc3317f42018-04-11 22:52:09 +0200732 res = false;
YOSHIFUJI Hideakic4307282007-02-09 23:25:21 +0900733 }
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800734 spin_unlock_bh(&tn->nametbl_lock);
Jon Maloyc3317f42018-04-11 22:52:09 +0200735 return res;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100736}
737
738/**
Per Liden4323add2006-01-18 00:38:21 +0100739 * tipc_nametbl_unsubscribe - remove a subscription object from name table
Per Lidenb97bf3f2006-01-02 19:04:38 +0100740 */
Jon Maloy8985ecc2018-02-15 10:40:46 +0100741void tipc_nametbl_unsubscribe(struct tipc_subscription *sub)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100742{
Jon Maloy5c45ab22018-02-15 10:40:49 +0100743 struct tipc_net *tn = tipc_net(sub->net);
Jon Maloy218527f2018-03-29 23:20:41 +0200744 struct tipc_subscr *s = &sub->evt.s;
Jon Maloy8985ecc2018-02-15 10:40:46 +0100745 u32 type = tipc_sub_read(s, seq.type);
Jon Maloy218527f2018-03-29 23:20:41 +0200746 struct tipc_service *sc;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100747
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800748 spin_lock_bh(&tn->nametbl_lock);
Jon Maloy218527f2018-03-29 23:20:41 +0200749 sc = tipc_service_find(sub->net, type);
750 if (!sc)
751 goto exit;
752
753 spin_lock_bh(&sc->lock);
754 list_del_init(&sub->service_list);
755 tipc_sub_put(sub);
756
757 /* Delete service item if no more publications and subscriptions */
758 if (RB_EMPTY_ROOT(&sc->ranges) && list_empty(&sc->subscriptions)) {
759 hlist_del_init_rcu(&sc->service_list);
760 kfree_rcu(sc, rcu);
YOSHIFUJI Hideakic4307282007-02-09 23:25:21 +0900761 }
Jon Maloy218527f2018-03-29 23:20:41 +0200762 spin_unlock_bh(&sc->lock);
763exit:
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800764 spin_unlock_bh(&tn->nametbl_lock);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100765}
766
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800767int tipc_nametbl_init(struct net *net)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100768{
Jon Maloy218527f2018-03-29 23:20:41 +0200769 struct tipc_net *tn = tipc_net(net);
770 struct name_table *nt;
Ying Xue993bfe52014-12-02 15:00:24 +0800771 int i;
772
Jia-Ju Bai04b9ce42018-07-27 17:28:25 +0800773 nt = kzalloc(sizeof(*nt), GFP_KERNEL);
Jon Maloy218527f2018-03-29 23:20:41 +0200774 if (!nt)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100775 return -ENOMEM;
776
Ying Xue993bfe52014-12-02 15:00:24 +0800777 for (i = 0; i < TIPC_NAMETBL_SIZE; i++)
Jon Maloy218527f2018-03-29 23:20:41 +0200778 INIT_HLIST_HEAD(&nt->services[i]);
Ying Xue993bfe52014-12-02 15:00:24 +0800779
Jon Maloy218527f2018-03-29 23:20:41 +0200780 INIT_LIST_HEAD(&nt->node_scope);
781 INIT_LIST_HEAD(&nt->cluster_scope);
Jon Maloy988f3f12018-10-19 19:55:40 +0200782 rwlock_init(&nt->cluster_scope_lock);
Jon Maloy218527f2018-03-29 23:20:41 +0200783 tn->nametbl = nt;
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800784 spin_lock_init(&tn->nametbl_lock);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100785 return 0;
786}
787
Erik Hugne1bb8dce2014-03-06 14:40:20 +0100788/**
Jon Maloy218527f2018-03-29 23:20:41 +0200789 * tipc_service_delete - purge all publications for a service and delete it
Erik Hugne1bb8dce2014-03-06 14:40:20 +0100790 */
Jon Maloy218527f2018-03-29 23:20:41 +0200791static void tipc_service_delete(struct net *net, struct tipc_service *sc)
Erik Hugne1bb8dce2014-03-06 14:40:20 +0100792{
Jon Maloy218527f2018-03-29 23:20:41 +0200793 struct service_range *sr, *tmpr;
Jon Maloybe47e412018-04-17 21:25:42 +0200794 struct publication *p, *tmp;
Erik Hugne1bb8dce2014-03-06 14:40:20 +0100795
Jon Maloy218527f2018-03-29 23:20:41 +0200796 spin_lock_bh(&sc->lock);
797 rbtree_postorder_for_each_entry_safe(sr, tmpr, &sc->ranges, tree_node) {
Jon Maloybe47e412018-04-17 21:25:42 +0200798 list_for_each_entry_safe(p, tmp, &sr->all_publ, all_publ) {
Jon Maloy5f307212018-05-09 02:59:41 +0200799 tipc_service_remove_publ(sr, p->node, p->key);
Jon Maloy218527f2018-03-29 23:20:41 +0200800 kfree_rcu(p, rcu);
801 }
Jon Maloybe47e412018-04-17 21:25:42 +0200802 rb_erase(&sr->tree_node, &sc->ranges);
803 kfree(sr);
Erik Hugne1bb8dce2014-03-06 14:40:20 +0100804 }
Jon Maloy218527f2018-03-29 23:20:41 +0200805 hlist_del_init_rcu(&sc->service_list);
806 spin_unlock_bh(&sc->lock);
807 kfree_rcu(sc, rcu);
Erik Hugne1bb8dce2014-03-06 14:40:20 +0100808}
809
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800810void tipc_nametbl_stop(struct net *net)
Per Lidenb97bf3f2006-01-02 19:04:38 +0100811{
Jon Maloy218527f2018-03-29 23:20:41 +0200812 struct name_table *nt = tipc_name_table(net);
813 struct tipc_net *tn = tipc_net(net);
814 struct hlist_head *service_head;
815 struct tipc_service *service;
Per Lidenb97bf3f2006-01-02 19:04:38 +0100816 u32 i;
817
Erik Hugne1bb8dce2014-03-06 14:40:20 +0100818 /* Verify name table is empty and purge any lingering
819 * publications, then release the name table
820 */
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800821 spin_lock_bh(&tn->nametbl_lock);
Ying Xuef046e7d2012-08-16 12:09:11 +0000822 for (i = 0; i < TIPC_NAMETBL_SIZE; i++) {
Jon Maloy218527f2018-03-29 23:20:41 +0200823 if (hlist_empty(&nt->services[i]))
Paul Gortmakerf705ab92012-07-11 17:35:01 -0400824 continue;
Jon Maloy218527f2018-03-29 23:20:41 +0200825 service_head = &nt->services[i];
826 hlist_for_each_entry_rcu(service, service_head, service_list) {
827 tipc_service_delete(net, service);
Erik Hugne1bb8dce2014-03-06 14:40:20 +0100828 }
Per Lidenb97bf3f2006-01-02 19:04:38 +0100829 }
Ying Xue4ac1c8d2015-01-09 15:27:09 +0800830 spin_unlock_bh(&tn->nametbl_lock);
Ying Xue993bfe52014-12-02 15:00:24 +0800831
Ying Xue97ede292014-12-02 15:00:30 +0800832 synchronize_net();
Jon Maloy218527f2018-03-29 23:20:41 +0200833 kfree(nt);
Per Lidenb97bf3f2006-01-02 19:04:38 +0100834}
Richard Alpe15931232014-11-20 10:29:20 +0100835
Richard Alped8182802014-11-24 11:10:29 +0100836static int __tipc_nl_add_nametable_publ(struct tipc_nl_msg *msg,
Jon Maloy218527f2018-03-29 23:20:41 +0200837 struct tipc_service *service,
838 struct service_range *sr,
839 u32 *last_key)
Richard Alpe15931232014-11-20 10:29:20 +0100840{
Richard Alpe15931232014-11-20 10:29:20 +0100841 struct publication *p;
Jon Maloy218527f2018-03-29 23:20:41 +0200842 struct nlattr *attrs;
843 struct nlattr *b;
844 void *hdr;
Richard Alpe15931232014-11-20 10:29:20 +0100845
Jon Maloy218527f2018-03-29 23:20:41 +0200846 if (*last_key) {
847 list_for_each_entry(p, &sr->all_publ, all_publ)
848 if (p->key == *last_key)
Richard Alpe15931232014-11-20 10:29:20 +0100849 break;
Jon Maloy218527f2018-03-29 23:20:41 +0200850 if (p->key != *last_key)
Richard Alpe15931232014-11-20 10:29:20 +0100851 return -EPIPE;
852 } else {
Jon Maloy218527f2018-03-29 23:20:41 +0200853 p = list_first_entry(&sr->all_publ,
854 struct publication,
Jon Maloye50e73e2018-03-15 16:48:55 +0100855 all_publ);
Richard Alpe15931232014-11-20 10:29:20 +0100856 }
857
Jon Maloy218527f2018-03-29 23:20:41 +0200858 list_for_each_entry_from(p, &sr->all_publ, all_publ) {
859 *last_key = p->key;
Richard Alpe15931232014-11-20 10:29:20 +0100860
861 hdr = genlmsg_put(msg->skb, msg->portid, msg->seq,
Richard Alpebfb3e5d2015-02-09 09:50:03 +0100862 &tipc_genl_family, NLM_F_MULTI,
Richard Alpe15931232014-11-20 10:29:20 +0100863 TIPC_NL_NAME_TABLE_GET);
864 if (!hdr)
865 return -EMSGSIZE;
866
Michal Kubecekae0be8d2019-04-26 11:13:06 +0200867 attrs = nla_nest_start_noflag(msg->skb, TIPC_NLA_NAME_TABLE);
Richard Alpe15931232014-11-20 10:29:20 +0100868 if (!attrs)
869 goto msg_full;
870
Michal Kubecekae0be8d2019-04-26 11:13:06 +0200871 b = nla_nest_start_noflag(msg->skb, TIPC_NLA_NAME_TABLE_PUBL);
Jon Maloy218527f2018-03-29 23:20:41 +0200872 if (!b)
Richard Alpe15931232014-11-20 10:29:20 +0100873 goto attr_msg_full;
874
Jon Maloy218527f2018-03-29 23:20:41 +0200875 if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_TYPE, service->type))
Richard Alpe15931232014-11-20 10:29:20 +0100876 goto publ_msg_full;
Jon Maloy218527f2018-03-29 23:20:41 +0200877 if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_LOWER, sr->lower))
Richard Alpe15931232014-11-20 10:29:20 +0100878 goto publ_msg_full;
Jon Maloy218527f2018-03-29 23:20:41 +0200879 if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_UPPER, sr->upper))
Richard Alpe15931232014-11-20 10:29:20 +0100880 goto publ_msg_full;
881 if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_SCOPE, p->scope))
882 goto publ_msg_full;
883 if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_NODE, p->node))
884 goto publ_msg_full;
Jon Maloye50e73e2018-03-15 16:48:55 +0100885 if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_REF, p->port))
Richard Alpe15931232014-11-20 10:29:20 +0100886 goto publ_msg_full;
887 if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_KEY, p->key))
888 goto publ_msg_full;
889
Jon Maloy218527f2018-03-29 23:20:41 +0200890 nla_nest_end(msg->skb, b);
Richard Alpe15931232014-11-20 10:29:20 +0100891 nla_nest_end(msg->skb, attrs);
892 genlmsg_end(msg->skb, hdr);
893 }
Jon Maloy218527f2018-03-29 23:20:41 +0200894 *last_key = 0;
Richard Alpe15931232014-11-20 10:29:20 +0100895
896 return 0;
897
898publ_msg_full:
Jon Maloy218527f2018-03-29 23:20:41 +0200899 nla_nest_cancel(msg->skb, b);
Richard Alpe15931232014-11-20 10:29:20 +0100900attr_msg_full:
901 nla_nest_cancel(msg->skb, attrs);
902msg_full:
903 genlmsg_cancel(msg->skb, hdr);
904
905 return -EMSGSIZE;
906}
907
Jon Maloy218527f2018-03-29 23:20:41 +0200908static int __tipc_nl_service_range_list(struct tipc_nl_msg *msg,
909 struct tipc_service *sc,
910 u32 *last_lower, u32 *last_key)
Richard Alpe15931232014-11-20 10:29:20 +0100911{
Jon Maloy218527f2018-03-29 23:20:41 +0200912 struct service_range *sr;
913 struct rb_node *n;
Richard Alpe15931232014-11-20 10:29:20 +0100914 int err;
915
Jon Maloy218527f2018-03-29 23:20:41 +0200916 for (n = rb_first(&sc->ranges); n; n = rb_next(n)) {
917 sr = container_of(n, struct service_range, tree_node);
918 if (sr->lower < *last_lower)
919 continue;
920 err = __tipc_nl_add_nametable_publ(msg, sc, sr, last_key);
Richard Alpe15931232014-11-20 10:29:20 +0100921 if (err) {
Jon Maloy218527f2018-03-29 23:20:41 +0200922 *last_lower = sr->lower;
Richard Alpe15931232014-11-20 10:29:20 +0100923 return err;
924 }
925 }
926 *last_lower = 0;
Richard Alpe15931232014-11-20 10:29:20 +0100927 return 0;
928}
929
Jon Maloy218527f2018-03-29 23:20:41 +0200930static int tipc_nl_service_list(struct net *net, struct tipc_nl_msg *msg,
931 u32 *last_type, u32 *last_lower, u32 *last_key)
Richard Alpe15931232014-11-20 10:29:20 +0100932{
Jon Maloy218527f2018-03-29 23:20:41 +0200933 struct tipc_net *tn = tipc_net(net);
934 struct tipc_service *service = NULL;
935 struct hlist_head *head;
Richard Alpe15931232014-11-20 10:29:20 +0100936 int err;
937 int i;
938
939 if (*last_type)
940 i = hash(*last_type);
941 else
942 i = 0;
943
944 for (; i < TIPC_NAMETBL_SIZE; i++) {
Jon Maloy218527f2018-03-29 23:20:41 +0200945 head = &tn->nametbl->services[i];
Richard Alpe15931232014-11-20 10:29:20 +0100946
Hoang Led1841532019-04-09 14:59:24 +0700947 if (*last_type ||
948 (!i && *last_key && (*last_lower == *last_key))) {
Jon Maloy218527f2018-03-29 23:20:41 +0200949 service = tipc_service_find(net, *last_type);
950 if (!service)
Richard Alpe15931232014-11-20 10:29:20 +0100951 return -EPIPE;
952 } else {
Jon Maloy218527f2018-03-29 23:20:41 +0200953 hlist_for_each_entry_rcu(service, head, service_list)
Ying Xue97ede292014-12-02 15:00:30 +0800954 break;
Jon Maloy218527f2018-03-29 23:20:41 +0200955 if (!service)
Richard Alpe15931232014-11-20 10:29:20 +0100956 continue;
957 }
958
Jon Maloy218527f2018-03-29 23:20:41 +0200959 hlist_for_each_entry_from_rcu(service, service_list) {
960 spin_lock_bh(&service->lock);
961 err = __tipc_nl_service_range_list(msg, service,
962 last_lower,
963 last_key);
Richard Alpe15931232014-11-20 10:29:20 +0100964
965 if (err) {
Jon Maloy218527f2018-03-29 23:20:41 +0200966 *last_type = service->type;
967 spin_unlock_bh(&service->lock);
Richard Alpe15931232014-11-20 10:29:20 +0100968 return err;
969 }
Jon Maloy218527f2018-03-29 23:20:41 +0200970 spin_unlock_bh(&service->lock);
Richard Alpe15931232014-11-20 10:29:20 +0100971 }
972 *last_type = 0;
973 }
974 return 0;
975}
976
977int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb)
978{
Jon Maloy218527f2018-03-29 23:20:41 +0200979 struct net *net = sock_net(skb->sk);
Richard Alpe15931232014-11-20 10:29:20 +0100980 u32 last_type = cb->args[0];
981 u32 last_lower = cb->args[1];
Jon Maloy218527f2018-03-29 23:20:41 +0200982 u32 last_key = cb->args[2];
983 int done = cb->args[3];
Richard Alpe15931232014-11-20 10:29:20 +0100984 struct tipc_nl_msg msg;
Jon Maloy218527f2018-03-29 23:20:41 +0200985 int err;
Richard Alpe15931232014-11-20 10:29:20 +0100986
987 if (done)
988 return 0;
989
990 msg.skb = skb;
991 msg.portid = NETLINK_CB(cb->skb).portid;
992 msg.seq = cb->nlh->nlmsg_seq;
993
Ying Xue97ede292014-12-02 15:00:30 +0800994 rcu_read_lock();
Jon Maloy218527f2018-03-29 23:20:41 +0200995 err = tipc_nl_service_list(net, &msg, &last_type,
996 &last_lower, &last_key);
Richard Alpe15931232014-11-20 10:29:20 +0100997 if (!err) {
998 done = 1;
999 } else if (err != -EMSGSIZE) {
1000 /* We never set seq or call nl_dump_check_consistent() this
1001 * means that setting prev_seq here will cause the consistence
1002 * check to fail in the netlink callback handler. Resulting in
1003 * the NLMSG_DONE message having the NLM_F_DUMP_INTR flag set if
1004 * we got an error.
1005 */
1006 cb->prev_seq = 1;
1007 }
Ying Xue97ede292014-12-02 15:00:30 +08001008 rcu_read_unlock();
Richard Alpe15931232014-11-20 10:29:20 +01001009
1010 cb->args[0] = last_type;
1011 cb->args[1] = last_lower;
Jon Maloy218527f2018-03-29 23:20:41 +02001012 cb->args[2] = last_key;
Richard Alpe15931232014-11-20 10:29:20 +01001013 cb->args[3] = done;
1014
1015 return skb->len;
1016}
Jon Paul Maloy3c724ac2015-02-05 08:36:43 -05001017
Jon Maloya80ae532017-10-13 11:04:22 +02001018struct tipc_dest *tipc_dest_find(struct list_head *l, u32 node, u32 port)
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001019{
Jon Maloya80ae532017-10-13 11:04:22 +02001020 struct tipc_dest *dst;
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001021
Jon Maloya80ae532017-10-13 11:04:22 +02001022 list_for_each_entry(dst, l, list) {
Haiqing Bai30935192018-08-27 09:32:26 +08001023 if (dst->node == node && dst->port == port)
1024 return dst;
Jon Paul Maloy3c724ac2015-02-05 08:36:43 -05001025 }
Jon Maloya80ae532017-10-13 11:04:22 +02001026 return NULL;
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001027}
1028
Jon Maloya80ae532017-10-13 11:04:22 +02001029bool tipc_dest_push(struct list_head *l, u32 node, u32 port)
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001030{
Jon Maloya80ae532017-10-13 11:04:22 +02001031 struct tipc_dest *dst;
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001032
Jon Maloya80ae532017-10-13 11:04:22 +02001033 if (tipc_dest_find(l, node, port))
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001034 return false;
1035
Jon Maloya80ae532017-10-13 11:04:22 +02001036 dst = kmalloc(sizeof(*dst), GFP_ATOMIC);
1037 if (unlikely(!dst))
1038 return false;
Haiqing Bai30935192018-08-27 09:32:26 +08001039 dst->node = node;
1040 dst->port = port;
Jon Maloya80ae532017-10-13 11:04:22 +02001041 list_add(&dst->list, l);
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001042 return true;
1043}
1044
Jon Maloya80ae532017-10-13 11:04:22 +02001045bool tipc_dest_pop(struct list_head *l, u32 *node, u32 *port)
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001046{
Jon Maloya80ae532017-10-13 11:04:22 +02001047 struct tipc_dest *dst;
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001048
1049 if (list_empty(l))
Jon Maloya80ae532017-10-13 11:04:22 +02001050 return false;
1051 dst = list_first_entry(l, typeof(*dst), list);
1052 if (port)
1053 *port = dst->port;
1054 if (node)
1055 *node = dst->node;
1056 list_del(&dst->list);
1057 kfree(dst);
1058 return true;
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001059}
1060
Jon Maloya80ae532017-10-13 11:04:22 +02001061bool tipc_dest_del(struct list_head *l, u32 node, u32 port)
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001062{
Jon Maloya80ae532017-10-13 11:04:22 +02001063 struct tipc_dest *dst;
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001064
Jon Maloya80ae532017-10-13 11:04:22 +02001065 dst = tipc_dest_find(l, node, port);
1066 if (!dst)
1067 return false;
1068 list_del(&dst->list);
1069 kfree(dst);
1070 return true;
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001071}
1072
Jon Maloya80ae532017-10-13 11:04:22 +02001073void tipc_dest_list_purge(struct list_head *l)
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001074{
Jon Maloya80ae532017-10-13 11:04:22 +02001075 struct tipc_dest *dst, *tmp;
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001076
Jon Maloya80ae532017-10-13 11:04:22 +02001077 list_for_each_entry_safe(dst, tmp, l, list) {
1078 list_del(&dst->list);
1079 kfree(dst);
Jon Paul Maloy3c724ac2015-02-05 08:36:43 -05001080 }
1081}
1082
Jon Maloya80ae532017-10-13 11:04:22 +02001083int tipc_dest_list_len(struct list_head *l)
Jon Paul Maloy3c724ac2015-02-05 08:36:43 -05001084{
Jon Maloya80ae532017-10-13 11:04:22 +02001085 struct tipc_dest *dst;
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001086 int i = 0;
Jon Paul Maloy3c724ac2015-02-05 08:36:43 -05001087
Jon Maloya80ae532017-10-13 11:04:22 +02001088 list_for_each_entry(dst, l, list) {
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001089 i++;
Jon Paul Maloy3c724ac2015-02-05 08:36:43 -05001090 }
Jon Paul Maloy4d8642d2017-01-03 10:55:10 -05001091 return i;
Jon Paul Maloy3c724ac2015-02-05 08:36:43 -05001092}