Blame view

net/tipc/name_table.c 30.3 KB
b97bf3fd8   Per Liden   [TIPC] Initial merge
1
2
  /*
   * net/tipc/name_table.c: TIPC name table code
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
3
   *
e50e73e10   Jon Maloy   tipc: some name c...
4
   * Copyright (c) 2000-2006, 2014-2018, Ericsson AB
993bfe5da   Ying Xue   tipc: make name t...
5
   * Copyright (c) 2004-2008, 2010-2014, Wind River Systems
b97bf3fd8   Per Liden   [TIPC] Initial merge
6
7
   * All rights reserved.
   *
9ea1fd3c1   Per Liden   [TIPC] License he...
8
   * Redistribution and use in source and binary forms, with or without
b97bf3fd8   Per Liden   [TIPC] Initial merge
9
10
   * modification, are permitted provided that the following conditions are met:
   *
9ea1fd3c1   Per Liden   [TIPC] License he...
11
12
13
14
15
16
17
18
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in the
   *    documentation and/or other materials provided with the distribution.
   * 3. Neither the names of the copyright holders nor the names of its
   *    contributors may be used to endorse or promote products derived from
   *    this software without specific prior written permission.
b97bf3fd8   Per Liden   [TIPC] Initial merge
19
   *
9ea1fd3c1   Per Liden   [TIPC] License he...
20
21
22
23
24
25
26
27
28
29
30
31
32
33
   * Alternatively, this software may be distributed under the terms of the
   * GNU General Public License ("GPL") version 2 as published by the Free
   * Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
b97bf3fd8   Per Liden   [TIPC] Initial merge
34
35
   * POSSIBILITY OF SUCH DAMAGE.
   */
4ac1c8d0e   Ying Xue   tipc: name tipc n...
36
  #include <net/sock.h>
41b416f1f   Tuong Lien   tipc: support in-...
37
  #include <linux/list_sort.h>
d5162f341   Tuong Lien   tipc: fix name ta...
38
  #include <linux/rbtree_augmented.h>
b97bf3fd8   Per Liden   [TIPC] Initial merge
39
  #include "core.h"
22ae7cff5   Richard Alpe   tipc: nl compat a...
40
  #include "netlink.h"
b97bf3fd8   Per Liden   [TIPC] Initial merge
41
42
  #include "name_table.h"
  #include "name_distr.h"
b97bf3fd8   Per Liden   [TIPC] Initial merge
43
  #include "subscr.h"
1da465683   Ying Xue   tipc: make tipc b...
44
  #include "bcast.h"
22ae7cff5   Richard Alpe   tipc: nl compat a...
45
  #include "addr.h"
1d7e1c259   Jon Paul Maloy   tipc: reduce code...
46
  #include "node.h"
75da2163d   Jon Maloy   tipc: introduce c...
47
  #include "group.h"
b97bf3fd8   Per Liden   [TIPC] Initial merge
48
49
  
  /**
218527fe2   Jon Maloy   tipc: replace nam...
50
51
52
53
   * struct service_range - container for all bindings of a service range
   * @lower: service range lower bound
   * @upper: service range upper bound
   * @tree_node: member of service range RB tree
d5162f341   Tuong Lien   tipc: fix name ta...
54
   * @max: largest 'upper' in this node subtree
218527fe2   Jon Maloy   tipc: replace nam...
55
56
57
58
   * @local_publ: list of identical publications made from this node
   *   Used by closest_first lookup and multicast lookup algorithm
   * @all_publ: all publications identical to this one, whatever node and scope
   *   Used by round-robin lookup algorithm
b97bf3fd8   Per Liden   [TIPC] Initial merge
59
   */
218527fe2   Jon Maloy   tipc: replace nam...
60
  struct service_range {
b52124a50   Allan Stephens   tipc: Partition n...
61
62
  	u32 lower;
  	u32 upper;
218527fe2   Jon Maloy   tipc: replace nam...
63
  	struct rb_node tree_node;
d5162f341   Tuong Lien   tipc: fix name ta...
64
  	u32 max;
218527fe2   Jon Maloy   tipc: replace nam...
65
66
  	struct list_head local_publ;
  	struct list_head all_publ;
b52124a50   Allan Stephens   tipc: Partition n...
67
68
69
  };
  
  /**
218527fe2   Jon Maloy   tipc: replace nam...
70
71
   * struct tipc_service - container for all published instances of a service type
   * @type: 32 bit 'type' value for service
41b416f1f   Tuong Lien   tipc: support in-...
72
   * @publ_cnt: increasing counter for publications in this service
218527fe2   Jon Maloy   tipc: replace nam...
73
74
75
76
   * @ranges: rb tree containing all service ranges for this service
   * @service_list: links to adjacent name ranges in hash chain
   * @subscriptions: list of subscriptions for this service type
   * @lock: spinlock controlling access to pertaining service ranges/publications
97ede29e8   Ying Xue   tipc: convert nam...
77
   * @rcu: RCU callback head used for deferred freeing
b97bf3fd8   Per Liden   [TIPC] Initial merge
78
   */
218527fe2   Jon Maloy   tipc: replace nam...
79
  struct tipc_service {
b97bf3fd8   Per Liden   [TIPC] Initial merge
80
  	u32 type;
41b416f1f   Tuong Lien   tipc: support in-...
81
  	u32 publ_cnt;
218527fe2   Jon Maloy   tipc: replace nam...
82
83
  	struct rb_root ranges;
  	struct hlist_node service_list;
b97bf3fd8   Per Liden   [TIPC] Initial merge
84
  	struct list_head subscriptions;
218527fe2   Jon Maloy   tipc: replace nam...
85
  	spinlock_t lock; /* Covers service range list */
97ede29e8   Ying Xue   tipc: convert nam...
86
  	struct rcu_head rcu;
b97bf3fd8   Per Liden   [TIPC] Initial merge
87
  };
d5162f341   Tuong Lien   tipc: fix name ta...
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
  #define service_range_upper(sr) ((sr)->upper)
  RB_DECLARE_CALLBACKS_MAX(static, sr_callbacks,
  			 struct service_range, tree_node, u32, max,
  			 service_range_upper)
  
  #define service_range_entry(rbtree_node)				\
  	(container_of(rbtree_node, struct service_range, tree_node))
  
  #define service_range_overlap(sr, start, end)				\
  	((sr)->lower <= (end) && (sr)->upper >= (start))
  
  /**
   * service_range_foreach_match - iterate over tipc service rbtree for each
   *                               range match
   * @sr: the service range pointer as a loop cursor
   * @sc: the pointer to tipc service which holds the service range rbtree
   * @start, end: the range (end >= start) for matching
   */
  #define service_range_foreach_match(sr, sc, start, end)			\
  	for (sr = service_range_match_first((sc)->ranges.rb_node,	\
  					    start,			\
  					    end);			\
  	     sr;							\
  	     sr = service_range_match_next(&(sr)->tree_node,		\
  					   start,			\
  					   end))
  
  /**
   * service_range_match_first - find first service range matching a range
   * @n: the root node of service range rbtree for searching
   * @start, end: the range (end >= start) for matching
   *
   * Return: the leftmost service range node in the rbtree that overlaps the
   * specific range if any. Otherwise, returns NULL.
   */
  static struct service_range *service_range_match_first(struct rb_node *n,
  						       u32 start, u32 end)
  {
  	struct service_range *sr;
  	struct rb_node *l, *r;
  
  	/* Non overlaps in tree at all? */
  	if (!n || service_range_entry(n)->max < start)
  		return NULL;
  
  	while (n) {
  		l = n->rb_left;
  		if (l && service_range_entry(l)->max >= start) {
  			/* A leftmost overlap range node must be one in the left
  			 * subtree. If not, it has lower > end, then nodes on
  			 * the right side cannot satisfy the condition either.
  			 */
  			n = l;
  			continue;
  		}
  
  		/* No one in the left subtree can match, return if this node is
  		 * an overlap i.e. leftmost.
  		 */
  		sr = service_range_entry(n);
  		if (service_range_overlap(sr, start, end))
  			return sr;
  
  		/* Ok, try to lookup on the right side */
  		r = n->rb_right;
  		if (sr->lower <= end &&
  		    r && service_range_entry(r)->max >= start) {
  			n = r;
  			continue;
  		}
  		break;
  	}
  
  	return NULL;
  }
  
  /**
   * service_range_match_next - find next service range matching a range
   * @n: a node in service range rbtree from which the searching starts
   * @start, end: the range (end >= start) for matching
   *
   * Return: the next service range node to the given node in the rbtree that
   * overlaps the specific range if any. Otherwise, returns NULL.
   */
  static struct service_range *service_range_match_next(struct rb_node *n,
  						      u32 start, u32 end)
  {
  	struct service_range *sr;
  	struct rb_node *p, *r;
  
  	while (n) {
  		r = n->rb_right;
  		if (r && service_range_entry(r)->max >= start)
  			/* A next overlap range node must be one in the right
  			 * subtree. If not, it has lower > end, then any next
  			 * successor (- an ancestor) of this node cannot
  			 * satisfy the condition either.
  			 */
  			return service_range_match_first(r, start, end);
  
  		/* No one in the right subtree can match, go up to find an
  		 * ancestor of this node which is parent of a left-hand child.
  		 */
  		while ((p = rb_parent(n)) && n == p->rb_right)
  			n = p;
  		if (!p)
  			break;
  
  		/* Return if this ancestor is an overlap */
  		sr = service_range_entry(p);
  		if (service_range_overlap(sr, start, end))
  			return sr;
  
  		/* Ok, try to lookup more from this ancestor */
  		if (sr->lower <= end) {
  			n = p;
  			continue;
  		}
  		break;
  	}
  
  	return NULL;
  }
05790c645   Sam Ravnborg   [TIPC]: Remove in...
211
  static int hash(int x)
b97bf3fd8   Per Liden   [TIPC] Initial merge
212
  {
f046e7d9b   Ying Xue   tipc: convert tip...
213
  	return x & (TIPC_NAMETBL_SIZE - 1);
b97bf3fd8   Per Liden   [TIPC] Initial merge
214
215
216
  }
  
  /**
218527fe2   Jon Maloy   tipc: replace nam...
217
   * tipc_publ_create - create a publication structure
b97bf3fd8   Per Liden   [TIPC] Initial merge
218
   */
218527fe2   Jon Maloy   tipc: replace nam...
219
220
221
  static struct publication *tipc_publ_create(u32 type, u32 lower, u32 upper,
  					    u32 scope, u32 node, u32 port,
  					    u32 key)
b97bf3fd8   Per Liden   [TIPC] Initial merge
222
  {
0da974f4f   Panagiotis Issaris   [NET]: Conversion...
223
  	struct publication *publ = kzalloc(sizeof(*publ), GFP_ATOMIC);
218527fe2   Jon Maloy   tipc: replace nam...
224
225
  
  	if (!publ)
1fc54d8f4   Sam Ravnborg   [TIPC]: Fix simpl...
226
  		return NULL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
227

b97bf3fd8   Per Liden   [TIPC] Initial merge
228
229
230
231
232
  	publ->type = type;
  	publ->lower = lower;
  	publ->upper = upper;
  	publ->scope = scope;
  	publ->node = node;
e50e73e10   Jon Maloy   tipc: some name c...
233
  	publ->port = port;
b97bf3fd8   Per Liden   [TIPC] Initial merge
234
  	publ->key = key;
e50e73e10   Jon Maloy   tipc: some name c...
235
  	INIT_LIST_HEAD(&publ->binding_sock);
218527fe2   Jon Maloy   tipc: replace nam...
236
237
238
  	INIT_LIST_HEAD(&publ->binding_node);
  	INIT_LIST_HEAD(&publ->local_publ);
  	INIT_LIST_HEAD(&publ->all_publ);
41b416f1f   Tuong Lien   tipc: support in-...
239
  	INIT_LIST_HEAD(&publ->list);
b97bf3fd8   Per Liden   [TIPC] Initial merge
240
241
242
243
  	return publ;
  }
  
  /**
218527fe2   Jon Maloy   tipc: replace nam...
244
   * tipc_service_create - create a service structure for the specified 'type'
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
245
   *
218527fe2   Jon Maloy   tipc: replace nam...
246
   * Allocates a single range structure and sets it to all 0's.
b97bf3fd8   Per Liden   [TIPC] Initial merge
247
   */
218527fe2   Jon Maloy   tipc: replace nam...
248
  static struct tipc_service *tipc_service_create(u32 type, struct hlist_head *hd)
b97bf3fd8   Per Liden   [TIPC] Initial merge
249
  {
218527fe2   Jon Maloy   tipc: replace nam...
250
  	struct tipc_service *service = kzalloc(sizeof(*service), GFP_ATOMIC);
b97bf3fd8   Per Liden   [TIPC] Initial merge
251

218527fe2   Jon Maloy   tipc: replace nam...
252
253
254
  	if (!service) {
  		pr_warn("Service creation failed, no memory
  ");
1fc54d8f4   Sam Ravnborg   [TIPC]: Fix simpl...
255
  		return NULL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
256
  	}
218527fe2   Jon Maloy   tipc: replace nam...
257
258
259
260
261
262
263
  	spin_lock_init(&service->lock);
  	service->type = type;
  	service->ranges = RB_ROOT;
  	INIT_HLIST_NODE(&service->service_list);
  	INIT_LIST_HEAD(&service->subscriptions);
  	hlist_add_head_rcu(&service->service_list, hd);
  	return service;
b97bf3fd8   Per Liden   [TIPC] Initial merge
264
  }
5f30721c5   Jon Maloy   tipc: clean up re...
265
266
267
268
269
  /*  tipc_service_find_range - find service range matching publication parameters
   */
  static struct service_range *tipc_service_find_range(struct tipc_service *sc,
  						     u32 lower, u32 upper)
  {
5f30721c5   Jon Maloy   tipc: clean up re...
270
  	struct service_range *sr;
d5162f341   Tuong Lien   tipc: fix name ta...
271
272
273
274
  	service_range_foreach_match(sr, sc, lower, upper) {
  		/* Look for exact match */
  		if (sr->lower == lower && sr->upper == upper)
  			return sr;
5f30721c5   Jon Maloy   tipc: clean up re...
275
  	}
5f30721c5   Jon Maloy   tipc: clean up re...
276

d5162f341   Tuong Lien   tipc: fix name ta...
277
  	return NULL;
5f30721c5   Jon Maloy   tipc: clean up re...
278
  }
218527fe2   Jon Maloy   tipc: replace nam...
279
280
  static struct service_range *tipc_service_create_range(struct tipc_service *sc,
  						       u32 lower, u32 upper)
b97bf3fd8   Per Liden   [TIPC] Initial merge
281
  {
218527fe2   Jon Maloy   tipc: replace nam...
282
  	struct rb_node **n, *parent = NULL;
d5162f341   Tuong Lien   tipc: fix name ta...
283
  	struct service_range *sr;
218527fe2   Jon Maloy   tipc: replace nam...
284
285
286
  
  	n = &sc->ranges.rb_node;
  	while (*n) {
218527fe2   Jon Maloy   tipc: replace nam...
287
  		parent = *n;
d5162f341   Tuong Lien   tipc: fix name ta...
288
289
290
291
292
293
294
  		sr = service_range_entry(parent);
  		if (lower == sr->lower && upper == sr->upper)
  			return sr;
  		if (sr->max < upper)
  			sr->max = upper;
  		if (lower <= sr->lower)
  			n = &parent->rb_left;
b97bf3fd8   Per Liden   [TIPC] Initial merge
295
  		else
d5162f341   Tuong Lien   tipc: fix name ta...
296
  			n = &parent->rb_right;
b97bf3fd8   Per Liden   [TIPC] Initial merge
297
  	}
218527fe2   Jon Maloy   tipc: replace nam...
298
299
300
301
302
  	sr = kzalloc(sizeof(*sr), GFP_ATOMIC);
  	if (!sr)
  		return NULL;
  	sr->lower = lower;
  	sr->upper = upper;
d5162f341   Tuong Lien   tipc: fix name ta...
303
  	sr->max = upper;
218527fe2   Jon Maloy   tipc: replace nam...
304
305
306
  	INIT_LIST_HEAD(&sr->local_publ);
  	INIT_LIST_HEAD(&sr->all_publ);
  	rb_link_node(&sr->tree_node, parent, n);
d5162f341   Tuong Lien   tipc: fix name ta...
307
  	rb_insert_augmented(&sr->tree_node, &sc->ranges, &sr_callbacks);
218527fe2   Jon Maloy   tipc: replace nam...
308
  	return sr;
b97bf3fd8   Per Liden   [TIPC] Initial merge
309
  }
218527fe2   Jon Maloy   tipc: replace nam...
310
311
  static struct publication *tipc_service_insert_publ(struct net *net,
  						    struct tipc_service *sc,
347475395   Ying Xue   tipc: make tipc n...
312
313
  						    u32 type, u32 lower,
  						    u32 upper, u32 scope,
218527fe2   Jon Maloy   tipc: replace nam...
314
315
  						    u32 node, u32 port,
  						    u32 key)
b97bf3fd8   Per Liden   [TIPC] Initial merge
316
  {
218527fe2   Jon Maloy   tipc: replace nam...
317
318
319
320
  	struct tipc_subscription *sub, *tmp;
  	struct service_range *sr;
  	struct publication *p;
  	bool first = false;
b52124a50   Allan Stephens   tipc: Partition n...
321

37922ea4a   Jon Maloy   tipc: permit over...
322
323
324
  	sr = tipc_service_create_range(sc, lower, upper);
  	if (!sr)
  		goto  err;
b97bf3fd8   Per Liden   [TIPC] Initial merge
325

37922ea4a   Jon Maloy   tipc: permit over...
326
  	first = list_empty(&sr->all_publ);
b97bf3fd8   Per Liden   [TIPC] Initial merge
327

218527fe2   Jon Maloy   tipc: replace nam...
328
329
330
331
332
  	/* Return if the publication already exists */
  	list_for_each_entry(p, &sr->all_publ, all_publ) {
  		if (p->key == key && (!p->node || p->node == node))
  			return NULL;
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
333

218527fe2   Jon Maloy   tipc: replace nam...
334
335
336
337
  	/* Create and insert publication */
  	p = tipc_publ_create(type, lower, upper, scope, node, port, key);
  	if (!p)
  		goto err;
41b416f1f   Tuong Lien   tipc: support in-...
338
339
  	/* Suppose there shouldn't be a huge gap btw publs i.e. >INT_MAX */
  	p->id = sc->publ_cnt++;
ba765ec63   Jon Maloy   tipc: remove zone...
340
  	if (in_own_node(net, node))
218527fe2   Jon Maloy   tipc: replace nam...
341
342
  		list_add(&p->local_publ, &sr->local_publ);
  	list_add(&p->all_publ, &sr->all_publ);
b97bf3fd8   Per Liden   [TIPC] Initial merge
343

617d3c7a5   Paul Gortmaker   tipc: compress ou...
344
  	/* Any subscriptions waiting for notification?  */
218527fe2   Jon Maloy   tipc: replace nam...
345
346
347
  	list_for_each_entry_safe(sub, tmp, &sc->subscriptions, service_list) {
  		tipc_sub_report_overlap(sub, p->lower, p->upper, TIPC_PUBLISHED,
  					p->port, p->node, p->scope, first);
b97bf3fd8   Per Liden   [TIPC] Initial merge
348
  	}
218527fe2   Jon Maloy   tipc: replace nam...
349
350
351
352
353
  	return p;
  err:
  	pr_warn("Failed to bind to %u,%u,%u, no memory
  ", type, lower, upper);
  	return NULL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
354
355
356
  }
  
  /**
218527fe2   Jon Maloy   tipc: replace nam...
357
   * tipc_service_remove_publ - remove a publication from a service
b97bf3fd8   Per Liden   [TIPC] Initial merge
358
   */
5f30721c5   Jon Maloy   tipc: clean up re...
359
360
  static struct publication *tipc_service_remove_publ(struct service_range *sr,
  						    u32 node, u32 key)
b97bf3fd8   Per Liden   [TIPC] Initial merge
361
  {
218527fe2   Jon Maloy   tipc: replace nam...
362
  	struct publication *p;
b52124a50   Allan Stephens   tipc: Partition n...
363

218527fe2   Jon Maloy   tipc: replace nam...
364
365
366
  	list_for_each_entry(p, &sr->all_publ, all_publ) {
  		if (p->key != key || (node && node != p->node))
  			continue;
5f30721c5   Jon Maloy   tipc: clean up re...
367
368
369
  		list_del(&p->all_publ);
  		list_del(&p->local_publ);
  		return p;
f6f0a4d2d   Allan Stephens   tipc: Convert nam...
370
  	}
5f30721c5   Jon Maloy   tipc: clean up re...
371
  	return NULL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
372
373
374
  }
  
  /**
41b416f1f   Tuong Lien   tipc: support in-...
375
376
377
378
379
380
381
382
383
384
385
386
387
388
   * Code reused: time_after32() for the same purpose
   */
  #define publication_after(pa, pb) time_after32((pa)->id, (pb)->id)
  static int tipc_publ_sort(void *priv, struct list_head *a,
  			  struct list_head *b)
  {
  	struct publication *pa, *pb;
  
  	pa = container_of(a, struct publication, list);
  	pb = container_of(b, struct publication, list);
  	return publication_after(pa, pb);
  }
  
  /**
218527fe2   Jon Maloy   tipc: replace nam...
389
390
391
   * tipc_service_subscribe - attach a subscription, and optionally
   * issue the prescribed number of events if there is any service
   * range overlapping with the requested range
b97bf3fd8   Per Liden   [TIPC] Initial merge
392
   */
218527fe2   Jon Maloy   tipc: replace nam...
393
  static void tipc_service_subscribe(struct tipc_service *service,
8985ecc7c   Jon Maloy   tipc: simplify en...
394
  				   struct tipc_subscription *sub)
b97bf3fd8   Per Liden   [TIPC] Initial merge
395
  {
218527fe2   Jon Maloy   tipc: replace nam...
396
  	struct tipc_subscr *sb = &sub->evt.s;
41b416f1f   Tuong Lien   tipc: support in-...
397
398
  	struct publication *p, *first, *tmp;
  	struct list_head publ_list;
218527fe2   Jon Maloy   tipc: replace nam...
399
  	struct service_range *sr;
a4273c73e   Parthasarathy Bhuvaragan   tipc: remove stru...
400
  	struct tipc_name_seq ns;
41b416f1f   Tuong Lien   tipc: support in-...
401
  	u32 filter;
a4273c73e   Parthasarathy Bhuvaragan   tipc: remove stru...
402

218527fe2   Jon Maloy   tipc: replace nam...
403
404
405
  	ns.type = tipc_sub_read(sb, seq.type);
  	ns.lower = tipc_sub_read(sb, seq.lower);
  	ns.upper = tipc_sub_read(sb, seq.upper);
41b416f1f   Tuong Lien   tipc: support in-...
406
  	filter = tipc_sub_read(sb, filter);
b97bf3fd8   Per Liden   [TIPC] Initial merge
407

da0a75e86   Jon Maloy   tipc: some prefix...
408
  	tipc_sub_get(sub);
218527fe2   Jon Maloy   tipc: replace nam...
409
  	list_add(&sub->service_list, &service->subscriptions);
b97bf3fd8   Per Liden   [TIPC] Initial merge
410

41b416f1f   Tuong Lien   tipc: support in-...
411
  	if (filter & TIPC_SUB_NO_STATUS)
b97bf3fd8   Per Liden   [TIPC] Initial merge
412
  		return;
41b416f1f   Tuong Lien   tipc: support in-...
413
  	INIT_LIST_HEAD(&publ_list);
d5162f341   Tuong Lien   tipc: fix name ta...
414
  	service_range_foreach_match(sr, service, ns.lower, ns.upper) {
41b416f1f   Tuong Lien   tipc: support in-...
415
  		first = NULL;
218527fe2   Jon Maloy   tipc: replace nam...
416
  		list_for_each_entry(p, &sr->all_publ, all_publ) {
41b416f1f   Tuong Lien   tipc: support in-...
417
418
419
420
421
  			if (filter & TIPC_SUB_PORTS)
  				list_add_tail(&p->list, &publ_list);
  			else if (!first || publication_after(first, p))
  				/* Pick this range's *first* publication */
  				first = p;
b97bf3fd8   Per Liden   [TIPC] Initial merge
422
  		}
41b416f1f   Tuong Lien   tipc: support in-...
423
424
425
426
427
428
429
430
431
432
433
  		if (first)
  			list_add_tail(&first->list, &publ_list);
  	}
  
  	/* Sort the publications before reporting */
  	list_sort(NULL, &publ_list, tipc_publ_sort);
  	list_for_each_entry_safe(p, tmp, &publ_list, list) {
  		tipc_sub_report_overlap(sub, p->lower, p->upper,
  					TIPC_PUBLISHED, p->port, p->node,
  					p->scope, true);
  		list_del_init(&p->list);
b97bf3fd8   Per Liden   [TIPC] Initial merge
434
435
  	}
  }
218527fe2   Jon Maloy   tipc: replace nam...
436
  static struct tipc_service *tipc_service_find(struct net *net, u32 type)
b97bf3fd8   Per Liden   [TIPC] Initial merge
437
  {
218527fe2   Jon Maloy   tipc: replace nam...
438
439
440
  	struct name_table *nt = tipc_name_table(net);
  	struct hlist_head *service_head;
  	struct tipc_service *service;
b97bf3fd8   Per Liden   [TIPC] Initial merge
441

218527fe2   Jon Maloy   tipc: replace nam...
442
443
444
445
446
  	service_head = &nt->services[hash(type)];
  	hlist_for_each_entry_rcu(service, service_head, service_list) {
  		if (service->type == type)
  			return service;
  	}
1fc54d8f4   Sam Ravnborg   [TIPC]: Fix simpl...
447
  	return NULL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
448
  };
4ac1c8d0e   Ying Xue   tipc: name tipc n...
449
  struct publication *tipc_nametbl_insert_publ(struct net *net, u32 type,
218527fe2   Jon Maloy   tipc: replace nam...
450
451
452
  					     u32 lower, u32 upper,
  					     u32 scope, u32 node,
  					     u32 port, u32 key)
b97bf3fd8   Per Liden   [TIPC] Initial merge
453
  {
218527fe2   Jon Maloy   tipc: replace nam...
454
455
456
  	struct name_table *nt = tipc_name_table(net);
  	struct tipc_service *sc;
  	struct publication *p;
b97bf3fd8   Per Liden   [TIPC] Initial merge
457

928df1880   Jon Maloy   tipc: obsolete TI...
458
  	if (scope > TIPC_NODE_SCOPE || lower > upper) {
218527fe2   Jon Maloy   tipc: replace nam...
459
460
  		pr_debug("Failed to bind illegal {%u,%u,%u} with scope %u
  ",
2cf8aa19f   Erik Hugne   tipc: use standar...
461
  			 type, lower, upper, scope);
1fc54d8f4   Sam Ravnborg   [TIPC]: Fix simpl...
462
  		return NULL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
463
  	}
218527fe2   Jon Maloy   tipc: replace nam...
464
465
466
467
  	sc = tipc_service_find(net, type);
  	if (!sc)
  		sc = tipc_service_create(type, &nt->services[hash(type)]);
  	if (!sc)
1fc54d8f4   Sam Ravnborg   [TIPC]: Fix simpl...
468
  		return NULL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
469

218527fe2   Jon Maloy   tipc: replace nam...
470
471
472
473
474
  	spin_lock_bh(&sc->lock);
  	p = tipc_service_insert_publ(net, sc, type, lower, upper,
  				     scope, node, port, key);
  	spin_unlock_bh(&sc->lock);
  	return p;
b97bf3fd8   Per Liden   [TIPC] Initial merge
475
  }
4ac1c8d0e   Ying Xue   tipc: name tipc n...
476
  struct publication *tipc_nametbl_remove_publ(struct net *net, u32 type,
37922ea4a   Jon Maloy   tipc: permit over...
477
478
  					     u32 lower, u32 upper,
  					     u32 node, u32 key)
b97bf3fd8   Per Liden   [TIPC] Initial merge
479
  {
218527fe2   Jon Maloy   tipc: replace nam...
480
  	struct tipc_service *sc = tipc_service_find(net, type);
5f30721c5   Jon Maloy   tipc: clean up re...
481
  	struct tipc_subscription *sub, *tmp;
be47e41d7   Jon Maloy   tipc: fix use-aft...
482
  	struct service_range *sr = NULL;
218527fe2   Jon Maloy   tipc: replace nam...
483
  	struct publication *p = NULL;
5f30721c5   Jon Maloy   tipc: clean up re...
484
  	bool last;
b97bf3fd8   Per Liden   [TIPC] Initial merge
485

218527fe2   Jon Maloy   tipc: replace nam...
486
  	if (!sc)
1fc54d8f4   Sam Ravnborg   [TIPC]: Fix simpl...
487
  		return NULL;
b97bf3fd8   Per Liden   [TIPC] Initial merge
488

218527fe2   Jon Maloy   tipc: replace nam...
489
  	spin_lock_bh(&sc->lock);
5f30721c5   Jon Maloy   tipc: clean up re...
490
491
492
493
494
495
496
497
498
499
500
501
502
  	sr = tipc_service_find_range(sc, lower, upper);
  	if (!sr)
  		goto exit;
  	p = tipc_service_remove_publ(sr, node, key);
  	if (!p)
  		goto exit;
  
  	/* Notify any waiting subscriptions */
  	last = list_empty(&sr->all_publ);
  	list_for_each_entry_safe(sub, tmp, &sc->subscriptions, service_list) {
  		tipc_sub_report_overlap(sub, lower, upper, TIPC_WITHDRAWN,
  					p->port, node, p->scope, last);
  	}
be47e41d7   Jon Maloy   tipc: fix use-aft...
503
504
  
  	/* Remove service range item if this was its last publication */
5f30721c5   Jon Maloy   tipc: clean up re...
505
  	if (list_empty(&sr->all_publ)) {
d5162f341   Tuong Lien   tipc: fix name ta...
506
  		rb_erase_augmented(&sr->tree_node, &sc->ranges, &sr_callbacks);
be47e41d7   Jon Maloy   tipc: fix use-aft...
507
508
  		kfree(sr);
  	}
218527fe2   Jon Maloy   tipc: replace nam...
509
510
511
512
513
  
  	/* Delete service item if this no more publications and subscriptions */
  	if (RB_EMPTY_ROOT(&sc->ranges) && list_empty(&sc->subscriptions)) {
  		hlist_del_init_rcu(&sc->service_list);
  		kfree_rcu(sc, rcu);
fb9962f3c   Ying Xue   tipc: ensure all ...
514
  	}
5f30721c5   Jon Maloy   tipc: clean up re...
515
  exit:
218527fe2   Jon Maloy   tipc: replace nam...
516
517
  	spin_unlock_bh(&sc->lock);
  	return p;
b97bf3fd8   Per Liden   [TIPC] Initial merge
518
  }
2c53040f0   Ben Hutchings   net: Fix (nearly-...
519
  /**
218527fe2   Jon Maloy   tipc: replace nam...
520
   * tipc_nametbl_translate - perform service instance to socket translation
b97bf3fd8   Per Liden   [TIPC] Initial merge
521
   *
f20889f72   Jon Maloy   tipc: refactor na...
522
   * On entry, 'dnode' is the search domain used during translation.
bc9f8143e   Allan Stephens   tipc: Revert name...
523
524
   *
   * On exit:
f20889f72   Jon Maloy   tipc: refactor na...
525
526
527
528
529
530
531
532
533
   * - if translation is deferred to another node, leave 'dnode' unchanged and
   *   return 0
   * - if translation is attempted and succeeds, set 'dnode' to the publishing
   *   node and return the published (non-zero) port number
   * - if translation is attempted and fails, set 'dnode' to 0 and return 0
   *
   * Note that for legacy users (node configured with Z.C.N address format) the
   * 'closest-first' lookup algorithm must be maintained, i.e., if dnode is 0
   * we must look in the local binding list first
b97bf3fd8   Per Liden   [TIPC] Initial merge
534
   */
f20889f72   Jon Maloy   tipc: refactor na...
535
  u32 tipc_nametbl_translate(struct net *net, u32 type, u32 instance, u32 *dnode)
b97bf3fd8   Per Liden   [TIPC] Initial merge
536
  {
b89afb116   Jon Maloy   tipc: allow close...
537
538
539
  	struct tipc_net *tn = tipc_net(net);
  	bool legacy = tn->legacy_addr_format;
  	u32 self = tipc_own_addr(net);
218527fe2   Jon Maloy   tipc: replace nam...
540
541
  	struct service_range *sr;
  	struct tipc_service *sc;
f20889f72   Jon Maloy   tipc: refactor na...
542
  	struct list_head *list;
218527fe2   Jon Maloy   tipc: replace nam...
543
  	struct publication *p;
e50e73e10   Jon Maloy   tipc: some name c...
544
  	u32 port = 0;
bc9f8143e   Allan Stephens   tipc: Revert name...
545
  	u32 node = 0;
b97bf3fd8   Per Liden   [TIPC] Initial merge
546

f20889f72   Jon Maloy   tipc: refactor na...
547
  	if (!tipc_in_scope(legacy, *dnode, self))
b97bf3fd8   Per Liden   [TIPC] Initial merge
548
  		return 0;
97ede29e8   Ying Xue   tipc: convert nam...
549
  	rcu_read_lock();
218527fe2   Jon Maloy   tipc: replace nam...
550
551
  	sc = tipc_service_find(net, type);
  	if (unlikely(!sc))
d5162f341   Tuong Lien   tipc: fix name ta...
552
  		goto exit;
218527fe2   Jon Maloy   tipc: replace nam...
553
554
  
  	spin_lock_bh(&sc->lock);
d5162f341   Tuong Lien   tipc: fix name ta...
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
  	service_range_foreach_match(sr, sc, instance, instance) {
  		/* Select lookup algo: local, closest-first or round-robin */
  		if (*dnode == self) {
  			list = &sr->local_publ;
  			if (list_empty(list))
  				continue;
  			p = list_first_entry(list, struct publication,
  					     local_publ);
  			list_move_tail(&p->local_publ, &sr->local_publ);
  		} else if (legacy && !*dnode && !list_empty(&sr->local_publ)) {
  			list = &sr->local_publ;
  			p = list_first_entry(list, struct publication,
  					     local_publ);
  			list_move_tail(&p->local_publ, &sr->local_publ);
  		} else {
  			list = &sr->all_publ;
  			p = list_first_entry(list, struct publication,
  					     all_publ);
  			list_move_tail(&p->all_publ, &sr->all_publ);
  		}
  		port = p->port;
  		node = p->node;
  		/* Todo: as for legacy, pick the first matching range only, a
  		 * "true" round-robin will be performed as needed.
  		 */
  		break;
b97bf3fd8   Per Liden   [TIPC] Initial merge
581
  	}
218527fe2   Jon Maloy   tipc: replace nam...
582
  	spin_unlock_bh(&sc->lock);
d5162f341   Tuong Lien   tipc: fix name ta...
583
584
  
  exit:
97ede29e8   Ying Xue   tipc: convert nam...
585
  	rcu_read_unlock();
f20889f72   Jon Maloy   tipc: refactor na...
586
  	*dnode = node;
e50e73e10   Jon Maloy   tipc: some name c...
587
  	return port;
b97bf3fd8   Per Liden   [TIPC] Initial merge
588
  }
232d07b74   Jon Maloy   tipc: improve gro...
589
  bool tipc_nametbl_lookup(struct net *net, u32 type, u32 instance, u32 scope,
ee106d7f9   Jon Maloy   tipc: introduce g...
590
591
592
593
  			 struct list_head *dsts, int *dstcnt, u32 exclude,
  			 bool all)
  {
  	u32 self = tipc_own_addr(net);
218527fe2   Jon Maloy   tipc: replace nam...
594
595
596
  	struct service_range *sr;
  	struct tipc_service *sc;
  	struct publication *p;
ee106d7f9   Jon Maloy   tipc: introduce g...
597

ee106d7f9   Jon Maloy   tipc: introduce g...
598
599
  	*dstcnt = 0;
  	rcu_read_lock();
218527fe2   Jon Maloy   tipc: replace nam...
600
601
  	sc = tipc_service_find(net, type);
  	if (unlikely(!sc))
ee106d7f9   Jon Maloy   tipc: introduce g...
602
  		goto exit;
218527fe2   Jon Maloy   tipc: replace nam...
603
604
  
  	spin_lock_bh(&sc->lock);
d5162f341   Tuong Lien   tipc: fix name ta...
605
606
  	/* Todo: a full search i.e. service_range_foreach_match() instead? */
  	sr = service_range_match_first(sc->ranges.rb_node, instance, instance);
218527fe2   Jon Maloy   tipc: replace nam...
607
608
609
610
611
612
613
614
615
616
617
618
619
620
  	if (!sr)
  		goto no_match;
  
  	list_for_each_entry(p, &sr->all_publ, all_publ) {
  		if (p->scope != scope)
  			continue;
  		if (p->port == exclude && p->node == self)
  			continue;
  		tipc_dest_push(dsts, p->node, p->port);
  		(*dstcnt)++;
  		if (all)
  			continue;
  		list_move_tail(&p->all_publ, &sr->all_publ);
  		break;
ee106d7f9   Jon Maloy   tipc: introduce g...
621
  	}
218527fe2   Jon Maloy   tipc: replace nam...
622
623
  no_match:
  	spin_unlock_bh(&sc->lock);
ee106d7f9   Jon Maloy   tipc: introduce g...
624
625
626
627
  exit:
  	rcu_read_unlock();
  	return !list_empty(dsts);
  }
ba765ec63   Jon Maloy   tipc: remove zone...
628
629
  void tipc_nametbl_mc_lookup(struct net *net, u32 type, u32 lower, u32 upper,
  			    u32 scope, bool exact, struct list_head *dports)
b97bf3fd8   Per Liden   [TIPC] Initial merge
630
  {
218527fe2   Jon Maloy   tipc: replace nam...
631
632
  	struct service_range *sr;
  	struct tipc_service *sc;
232d07b74   Jon Maloy   tipc: improve gro...
633
  	struct publication *p;
b97bf3fd8   Per Liden   [TIPC] Initial merge
634

97ede29e8   Ying Xue   tipc: convert nam...
635
  	rcu_read_lock();
218527fe2   Jon Maloy   tipc: replace nam...
636
637
  	sc = tipc_service_find(net, type);
  	if (!sc)
b97bf3fd8   Per Liden   [TIPC] Initial merge
638
  		goto exit;
218527fe2   Jon Maloy   tipc: replace nam...
639
  	spin_lock_bh(&sc->lock);
d5162f341   Tuong Lien   tipc: fix name ta...
640
  	service_range_foreach_match(sr, sc, lower, upper) {
218527fe2   Jon Maloy   tipc: replace nam...
641
  		list_for_each_entry(p, &sr->local_publ, local_publ) {
232d07b74   Jon Maloy   tipc: improve gro...
642
  			if (p->scope == scope || (!exact && p->scope < scope))
e50e73e10   Jon Maloy   tipc: some name c...
643
  				tipc_dest_push(dports, 0, p->port);
968edbe1c   Allan Stephens   tipc: Optimizatio...
644
  		}
b97bf3fd8   Per Liden   [TIPC] Initial merge
645
  	}
218527fe2   Jon Maloy   tipc: replace nam...
646
  	spin_unlock_bh(&sc->lock);
b97bf3fd8   Per Liden   [TIPC] Initial merge
647
  exit:
97ede29e8   Ying Xue   tipc: convert nam...
648
  	rcu_read_unlock();
b97bf3fd8   Per Liden   [TIPC] Initial merge
649
  }
2ae0b8af1   Jon Paul Maloy   tipc: add functio...
650
651
  /* tipc_nametbl_lookup_dst_nodes - find broadcast destination nodes
   * - Creates list of nodes that overlap the given multicast address
218527fe2   Jon Maloy   tipc: replace nam...
652
   * - Determines if any node local destinations overlap
2ae0b8af1   Jon Paul Maloy   tipc: add functio...
653
654
   */
  void tipc_nametbl_lookup_dst_nodes(struct net *net, u32 type, u32 lower,
e9a034456   Jon Maloy   tipc: fix bug dur...
655
  				   u32 upper, struct tipc_nlist *nodes)
2ae0b8af1   Jon Paul Maloy   tipc: add functio...
656
  {
218527fe2   Jon Maloy   tipc: replace nam...
657
658
659
  	struct service_range *sr;
  	struct tipc_service *sc;
  	struct publication *p;
2ae0b8af1   Jon Paul Maloy   tipc: add functio...
660
661
  
  	rcu_read_lock();
218527fe2   Jon Maloy   tipc: replace nam...
662
663
  	sc = tipc_service_find(net, type);
  	if (!sc)
2ae0b8af1   Jon Paul Maloy   tipc: add functio...
664
  		goto exit;
218527fe2   Jon Maloy   tipc: replace nam...
665
  	spin_lock_bh(&sc->lock);
d5162f341   Tuong Lien   tipc: fix name ta...
666
  	service_range_foreach_match(sr, sc, lower, upper) {
218527fe2   Jon Maloy   tipc: replace nam...
667
668
  		list_for_each_entry(p, &sr->all_publ, all_publ) {
  			tipc_nlist_add(nodes, p->node);
2ae0b8af1   Jon Paul Maloy   tipc: add functio...
669
670
  		}
  	}
218527fe2   Jon Maloy   tipc: replace nam...
671
  	spin_unlock_bh(&sc->lock);
2ae0b8af1   Jon Paul Maloy   tipc: add functio...
672
673
674
  exit:
  	rcu_read_unlock();
  }
75da2163d   Jon Maloy   tipc: introduce c...
675
676
677
  /* tipc_nametbl_build_group - build list of communication group members
   */
  void tipc_nametbl_build_group(struct net *net, struct tipc_group *grp,
232d07b74   Jon Maloy   tipc: improve gro...
678
  			      u32 type, u32 scope)
75da2163d   Jon Maloy   tipc: introduce c...
679
  {
218527fe2   Jon Maloy   tipc: replace nam...
680
681
  	struct service_range *sr;
  	struct tipc_service *sc;
75da2163d   Jon Maloy   tipc: introduce c...
682
  	struct publication *p;
218527fe2   Jon Maloy   tipc: replace nam...
683
  	struct rb_node *n;
75da2163d   Jon Maloy   tipc: introduce c...
684
685
  
  	rcu_read_lock();
218527fe2   Jon Maloy   tipc: replace nam...
686
687
  	sc = tipc_service_find(net, type);
  	if (!sc)
75da2163d   Jon Maloy   tipc: introduce c...
688
  		goto exit;
218527fe2   Jon Maloy   tipc: replace nam...
689
690
691
692
  	spin_lock_bh(&sc->lock);
  	for (n = rb_first(&sc->ranges); n; n = rb_next(n)) {
  		sr = container_of(n, struct service_range, tree_node);
  		list_for_each_entry(p, &sr->all_publ, all_publ) {
232d07b74   Jon Maloy   tipc: improve gro...
693
  			if (p->scope != scope)
75da2163d   Jon Maloy   tipc: introduce c...
694
  				continue;
e50e73e10   Jon Maloy   tipc: some name c...
695
  			tipc_group_add_member(grp, p->node, p->port, p->lower);
75da2163d   Jon Maloy   tipc: introduce c...
696
697
  		}
  	}
218527fe2   Jon Maloy   tipc: replace nam...
698
  	spin_unlock_bh(&sc->lock);
75da2163d   Jon Maloy   tipc: introduce c...
699
700
701
  exit:
  	rcu_read_unlock();
  }
218527fe2   Jon Maloy   tipc: replace nam...
702
  /* tipc_nametbl_publish - add service binding to name table
b97bf3fd8   Per Liden   [TIPC] Initial merge
703
   */
f2f9800d4   Ying Xue   tipc: make tipc n...
704
  struct publication *tipc_nametbl_publish(struct net *net, u32 type, u32 lower,
218527fe2   Jon Maloy   tipc: replace nam...
705
  					 u32 upper, u32 scope, u32 port,
f2f9800d4   Ying Xue   tipc: make tipc n...
706
  					 u32 key)
b97bf3fd8   Per Liden   [TIPC] Initial merge
707
  {
218527fe2   Jon Maloy   tipc: replace nam...
708
709
710
711
  	struct name_table *nt = tipc_name_table(net);
  	struct tipc_net *tn = tipc_net(net);
  	struct publication *p = NULL;
  	struct sk_buff *skb = NULL;
cad2929dc   Hoang Huu Le   tipc: update a bi...
712
  	u32 rc_dests;
b97bf3fd8   Per Liden   [TIPC] Initial merge
713

4ac1c8d0e   Ying Xue   tipc: name tipc n...
714
  	spin_lock_bh(&tn->nametbl_lock);
218527fe2   Jon Maloy   tipc: replace nam...
715
716
717
718
719
  
  	if (nt->local_publ_count >= TIPC_MAX_PUBL) {
  		pr_warn("Bind failed, max limit %u reached
  ", TIPC_MAX_PUBL);
  		goto exit;
b97bf3fd8   Per Liden   [TIPC] Initial merge
720
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
721

218527fe2   Jon Maloy   tipc: replace nam...
722
723
724
725
726
  	p = tipc_nametbl_insert_publ(net, type, lower, upper, scope,
  				     tipc_own_addr(net), port, key);
  	if (p) {
  		nt->local_publ_count++;
  		skb = tipc_named_publish(net, p);
fd6eced8a   Allan Stephens   tipc: Don't recor...
727
  	}
cad2929dc   Hoang Huu Le   tipc: update a bi...
728
  	rc_dests = nt->rc_dests;
218527fe2   Jon Maloy   tipc: replace nam...
729
  exit:
4ac1c8d0e   Ying Xue   tipc: name tipc n...
730
  	spin_unlock_bh(&tn->nametbl_lock);
eab8c0457   Ying Xue   tipc: move the de...
731

218527fe2   Jon Maloy   tipc: replace nam...
732
  	if (skb)
cad2929dc   Hoang Huu Le   tipc: update a bi...
733
  		tipc_node_broadcast(net, skb, rc_dests);
218527fe2   Jon Maloy   tipc: replace nam...
734
  	return p;
cad2929dc   Hoang Huu Le   tipc: update a bi...
735

b97bf3fd8   Per Liden   [TIPC] Initial merge
736
737
738
  }
  
  /**
218527fe2   Jon Maloy   tipc: replace nam...
739
   * tipc_nametbl_withdraw - withdraw a service binding
b97bf3fd8   Per Liden   [TIPC] Initial merge
740
   */
218527fe2   Jon Maloy   tipc: replace nam...
741
  int tipc_nametbl_withdraw(struct net *net, u32 type, u32 lower,
37922ea4a   Jon Maloy   tipc: permit over...
742
  			  u32 upper, u32 key)
b97bf3fd8   Per Liden   [TIPC] Initial merge
743
  {
218527fe2   Jon Maloy   tipc: replace nam...
744
745
746
  	struct name_table *nt = tipc_name_table(net);
  	struct tipc_net *tn = tipc_net(net);
  	u32 self = tipc_own_addr(net);
5492390a9   Ying Xue   tipc: simplify re...
747
  	struct sk_buff *skb = NULL;
218527fe2   Jon Maloy   tipc: replace nam...
748
  	struct publication *p;
cad2929dc   Hoang Huu Le   tipc: update a bi...
749
  	u32 rc_dests;
b97bf3fd8   Per Liden   [TIPC] Initial merge
750

4ac1c8d0e   Ying Xue   tipc: name tipc n...
751
  	spin_lock_bh(&tn->nametbl_lock);
218527fe2   Jon Maloy   tipc: replace nam...
752

37922ea4a   Jon Maloy   tipc: permit over...
753
  	p = tipc_nametbl_remove_publ(net, type, lower, upper, self, key);
218527fe2   Jon Maloy   tipc: replace nam...
754
755
756
  	if (p) {
  		nt->local_publ_count--;
  		skb = tipc_named_withdraw(net, p);
218527fe2   Jon Maloy   tipc: replace nam...
757
758
  		list_del_init(&p->binding_sock);
  		kfree_rcu(p, rcu);
5492390a9   Ying Xue   tipc: simplify re...
759
  	} else {
218527fe2   Jon Maloy   tipc: replace nam...
760
761
  		pr_err("Failed to remove local publication {%u,%u,%u}/%u
  ",
37922ea4a   Jon Maloy   tipc: permit over...
762
  		       type, lower, upper, key);
5492390a9   Ying Xue   tipc: simplify re...
763
  	}
cad2929dc   Hoang Huu Le   tipc: update a bi...
764
  	rc_dests = nt->rc_dests;
4ac1c8d0e   Ying Xue   tipc: name tipc n...
765
  	spin_unlock_bh(&tn->nametbl_lock);
eab8c0457   Ying Xue   tipc: move the de...
766

5492390a9   Ying Xue   tipc: simplify re...
767
  	if (skb) {
cad2929dc   Hoang Huu Le   tipc: update a bi...
768
  		tipc_node_broadcast(net, skb, rc_dests);
b97bf3fd8   Per Liden   [TIPC] Initial merge
769
770
  		return 1;
  	}
b97bf3fd8   Per Liden   [TIPC] Initial merge
771
772
773
774
  	return 0;
  }
  
  /**
4323add67   Per Liden   [TIPC] Avoid poll...
775
   * tipc_nametbl_subscribe - add a subscription object to the name table
b97bf3fd8   Per Liden   [TIPC] Initial merge
776
   */
c3317f4db   Jon Maloy   tipc: fix unbalan...
777
  bool tipc_nametbl_subscribe(struct tipc_subscription *sub)
b97bf3fd8   Per Liden   [TIPC] Initial merge
778
  {
218527fe2   Jon Maloy   tipc: replace nam...
779
  	struct name_table *nt = tipc_name_table(sub->net);
5c45ab24a   Jon Maloy   tipc: make struct...
780
  	struct tipc_net *tn = tipc_net(sub->net);
8985ecc7c   Jon Maloy   tipc: simplify en...
781
782
  	struct tipc_subscr *s = &sub->evt.s;
  	u32 type = tipc_sub_read(s, seq.type);
218527fe2   Jon Maloy   tipc: replace nam...
783
  	struct tipc_service *sc;
c3317f4db   Jon Maloy   tipc: fix unbalan...
784
  	bool res = true;
b97bf3fd8   Per Liden   [TIPC] Initial merge
785

4ac1c8d0e   Ying Xue   tipc: name tipc n...
786
  	spin_lock_bh(&tn->nametbl_lock);
218527fe2   Jon Maloy   tipc: replace nam...
787
788
789
790
791
792
793
  	sc = tipc_service_find(sub->net, type);
  	if (!sc)
  		sc = tipc_service_create(type, &nt->services[hash(type)]);
  	if (sc) {
  		spin_lock_bh(&sc->lock);
  		tipc_service_subscribe(sc, sub);
  		spin_unlock_bh(&sc->lock);
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
794
  	} else {
218527fe2   Jon Maloy   tipc: replace nam...
795
796
797
798
  		pr_warn("Failed to subscribe for {%u,%u,%u}
  ", type,
  			tipc_sub_read(s, seq.lower),
  			tipc_sub_read(s, seq.upper));
c3317f4db   Jon Maloy   tipc: fix unbalan...
799
  		res = false;
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
800
  	}
4ac1c8d0e   Ying Xue   tipc: name tipc n...
801
  	spin_unlock_bh(&tn->nametbl_lock);
c3317f4db   Jon Maloy   tipc: fix unbalan...
802
  	return res;
b97bf3fd8   Per Liden   [TIPC] Initial merge
803
804
805
  }
  
  /**
4323add67   Per Liden   [TIPC] Avoid poll...
806
   * tipc_nametbl_unsubscribe - remove a subscription object from name table
b97bf3fd8   Per Liden   [TIPC] Initial merge
807
   */
8985ecc7c   Jon Maloy   tipc: simplify en...
808
  void tipc_nametbl_unsubscribe(struct tipc_subscription *sub)
b97bf3fd8   Per Liden   [TIPC] Initial merge
809
  {
5c45ab24a   Jon Maloy   tipc: make struct...
810
  	struct tipc_net *tn = tipc_net(sub->net);
218527fe2   Jon Maloy   tipc: replace nam...
811
  	struct tipc_subscr *s = &sub->evt.s;
8985ecc7c   Jon Maloy   tipc: simplify en...
812
  	u32 type = tipc_sub_read(s, seq.type);
218527fe2   Jon Maloy   tipc: replace nam...
813
  	struct tipc_service *sc;
b97bf3fd8   Per Liden   [TIPC] Initial merge
814

4ac1c8d0e   Ying Xue   tipc: name tipc n...
815
  	spin_lock_bh(&tn->nametbl_lock);
218527fe2   Jon Maloy   tipc: replace nam...
816
817
818
819
820
821
822
823
824
825
826
827
  	sc = tipc_service_find(sub->net, type);
  	if (!sc)
  		goto exit;
  
  	spin_lock_bh(&sc->lock);
  	list_del_init(&sub->service_list);
  	tipc_sub_put(sub);
  
  	/* Delete service item if no more publications and subscriptions */
  	if (RB_EMPTY_ROOT(&sc->ranges) && list_empty(&sc->subscriptions)) {
  		hlist_del_init_rcu(&sc->service_list);
  		kfree_rcu(sc, rcu);
c43072852   YOSHIFUJI Hideaki   [NET] TIPC: Fix w...
828
  	}
218527fe2   Jon Maloy   tipc: replace nam...
829
830
  	spin_unlock_bh(&sc->lock);
  exit:
4ac1c8d0e   Ying Xue   tipc: name tipc n...
831
  	spin_unlock_bh(&tn->nametbl_lock);
b97bf3fd8   Per Liden   [TIPC] Initial merge
832
  }
4ac1c8d0e   Ying Xue   tipc: name tipc n...
833
  int tipc_nametbl_init(struct net *net)
b97bf3fd8   Per Liden   [TIPC] Initial merge
834
  {
218527fe2   Jon Maloy   tipc: replace nam...
835
836
  	struct tipc_net *tn = tipc_net(net);
  	struct name_table *nt;
993bfe5da   Ying Xue   tipc: make name t...
837
  	int i;
04b9ce48e   Jia-Ju Bai   net: tipc: name_t...
838
  	nt = kzalloc(sizeof(*nt), GFP_KERNEL);
218527fe2   Jon Maloy   tipc: replace nam...
839
  	if (!nt)
b97bf3fd8   Per Liden   [TIPC] Initial merge
840
  		return -ENOMEM;
993bfe5da   Ying Xue   tipc: make name t...
841
  	for (i = 0; i < TIPC_NAMETBL_SIZE; i++)
218527fe2   Jon Maloy   tipc: replace nam...
842
  		INIT_HLIST_HEAD(&nt->services[i]);
993bfe5da   Ying Xue   tipc: make name t...
843

218527fe2   Jon Maloy   tipc: replace nam...
844
845
  	INIT_LIST_HEAD(&nt->node_scope);
  	INIT_LIST_HEAD(&nt->cluster_scope);
988f3f160   Jon Maloy   tipc: eliminate m...
846
  	rwlock_init(&nt->cluster_scope_lock);
218527fe2   Jon Maloy   tipc: replace nam...
847
  	tn->nametbl = nt;
4ac1c8d0e   Ying Xue   tipc: name tipc n...
848
  	spin_lock_init(&tn->nametbl_lock);
b97bf3fd8   Per Liden   [TIPC] Initial merge
849
850
  	return 0;
  }
1bb8dce57   Erik Hugne   tipc: fix memory ...
851
  /**
218527fe2   Jon Maloy   tipc: replace nam...
852
   *  tipc_service_delete - purge all publications for a service and delete it
1bb8dce57   Erik Hugne   tipc: fix memory ...
853
   */
218527fe2   Jon Maloy   tipc: replace nam...
854
  static void tipc_service_delete(struct net *net, struct tipc_service *sc)
1bb8dce57   Erik Hugne   tipc: fix memory ...
855
  {
218527fe2   Jon Maloy   tipc: replace nam...
856
  	struct service_range *sr, *tmpr;
be47e41d7   Jon Maloy   tipc: fix use-aft...
857
  	struct publication *p, *tmp;
218527fe2   Jon Maloy   tipc: replace nam...
858
859
860
  
  	spin_lock_bh(&sc->lock);
  	rbtree_postorder_for_each_entry_safe(sr, tmpr, &sc->ranges, tree_node) {
be47e41d7   Jon Maloy   tipc: fix use-aft...
861
  		list_for_each_entry_safe(p, tmp, &sr->all_publ, all_publ) {
5f30721c5   Jon Maloy   tipc: clean up re...
862
  			tipc_service_remove_publ(sr, p->node, p->key);
218527fe2   Jon Maloy   tipc: replace nam...
863
864
  			kfree_rcu(p, rcu);
  		}
d5162f341   Tuong Lien   tipc: fix name ta...
865
  		rb_erase_augmented(&sr->tree_node, &sc->ranges, &sr_callbacks);
be47e41d7   Jon Maloy   tipc: fix use-aft...
866
  		kfree(sr);
1bb8dce57   Erik Hugne   tipc: fix memory ...
867
  	}
218527fe2   Jon Maloy   tipc: replace nam...
868
869
870
  	hlist_del_init_rcu(&sc->service_list);
  	spin_unlock_bh(&sc->lock);
  	kfree_rcu(sc, rcu);
1bb8dce57   Erik Hugne   tipc: fix memory ...
871
  }
4ac1c8d0e   Ying Xue   tipc: name tipc n...
872
  void tipc_nametbl_stop(struct net *net)
b97bf3fd8   Per Liden   [TIPC] Initial merge
873
  {
218527fe2   Jon Maloy   tipc: replace nam...
874
875
876
877
  	struct name_table *nt = tipc_name_table(net);
  	struct tipc_net *tn = tipc_net(net);
  	struct hlist_head *service_head;
  	struct tipc_service *service;
b97bf3fd8   Per Liden   [TIPC] Initial merge
878
  	u32 i;
1bb8dce57   Erik Hugne   tipc: fix memory ...
879
880
881
  	/* Verify name table is empty and purge any lingering
  	 * publications, then release the name table
  	 */
4ac1c8d0e   Ying Xue   tipc: name tipc n...
882
  	spin_lock_bh(&tn->nametbl_lock);
f046e7d9b   Ying Xue   tipc: convert tip...
883
  	for (i = 0; i < TIPC_NAMETBL_SIZE; i++) {
218527fe2   Jon Maloy   tipc: replace nam...
884
  		if (hlist_empty(&nt->services[i]))
f705ab956   Paul Gortmaker   tipc: limit error...
885
  			continue;
218527fe2   Jon Maloy   tipc: replace nam...
886
887
888
  		service_head = &nt->services[i];
  		hlist_for_each_entry_rcu(service, service_head, service_list) {
  			tipc_service_delete(net, service);
1bb8dce57   Erik Hugne   tipc: fix memory ...
889
  		}
b97bf3fd8   Per Liden   [TIPC] Initial merge
890
  	}
4ac1c8d0e   Ying Xue   tipc: name tipc n...
891
  	spin_unlock_bh(&tn->nametbl_lock);
993bfe5da   Ying Xue   tipc: make name t...
892

97ede29e8   Ying Xue   tipc: convert nam...
893
  	synchronize_net();
218527fe2   Jon Maloy   tipc: replace nam...
894
  	kfree(nt);
b97bf3fd8   Per Liden   [TIPC] Initial merge
895
  }
1593123a6   Richard Alpe   tipc: add name ta...
896

d8182804c   Richard Alpe   tipc: fix sparse ...
897
  static int __tipc_nl_add_nametable_publ(struct tipc_nl_msg *msg,
218527fe2   Jon Maloy   tipc: replace nam...
898
899
900
  					struct tipc_service *service,
  					struct service_range *sr,
  					u32 *last_key)
1593123a6   Richard Alpe   tipc: add name ta...
901
  {
1593123a6   Richard Alpe   tipc: add name ta...
902
  	struct publication *p;
218527fe2   Jon Maloy   tipc: replace nam...
903
904
905
  	struct nlattr *attrs;
  	struct nlattr *b;
  	void *hdr;
1593123a6   Richard Alpe   tipc: add name ta...
906

218527fe2   Jon Maloy   tipc: replace nam...
907
908
909
  	if (*last_key) {
  		list_for_each_entry(p, &sr->all_publ, all_publ)
  			if (p->key == *last_key)
1593123a6   Richard Alpe   tipc: add name ta...
910
  				break;
218527fe2   Jon Maloy   tipc: replace nam...
911
  		if (p->key != *last_key)
1593123a6   Richard Alpe   tipc: add name ta...
912
913
  			return -EPIPE;
  	} else {
218527fe2   Jon Maloy   tipc: replace nam...
914
915
  		p = list_first_entry(&sr->all_publ,
  				     struct publication,
e50e73e10   Jon Maloy   tipc: some name c...
916
  				     all_publ);
1593123a6   Richard Alpe   tipc: add name ta...
917
  	}
218527fe2   Jon Maloy   tipc: replace nam...
918
919
  	list_for_each_entry_from(p, &sr->all_publ, all_publ) {
  		*last_key = p->key;
1593123a6   Richard Alpe   tipc: add name ta...
920
921
  
  		hdr = genlmsg_put(msg->skb, msg->portid, msg->seq,
bfb3e5dd8   Richard Alpe   tipc: move and re...
922
  				  &tipc_genl_family, NLM_F_MULTI,
1593123a6   Richard Alpe   tipc: add name ta...
923
924
925
  				  TIPC_NL_NAME_TABLE_GET);
  		if (!hdr)
  			return -EMSGSIZE;
ae0be8de9   Michal Kubecek   netlink: make nla...
926
  		attrs = nla_nest_start_noflag(msg->skb, TIPC_NLA_NAME_TABLE);
1593123a6   Richard Alpe   tipc: add name ta...
927
928
  		if (!attrs)
  			goto msg_full;
ae0be8de9   Michal Kubecek   netlink: make nla...
929
  		b = nla_nest_start_noflag(msg->skb, TIPC_NLA_NAME_TABLE_PUBL);
218527fe2   Jon Maloy   tipc: replace nam...
930
  		if (!b)
1593123a6   Richard Alpe   tipc: add name ta...
931
  			goto attr_msg_full;
218527fe2   Jon Maloy   tipc: replace nam...
932
  		if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_TYPE, service->type))
1593123a6   Richard Alpe   tipc: add name ta...
933
  			goto publ_msg_full;
218527fe2   Jon Maloy   tipc: replace nam...
934
  		if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_LOWER, sr->lower))
1593123a6   Richard Alpe   tipc: add name ta...
935
  			goto publ_msg_full;
218527fe2   Jon Maloy   tipc: replace nam...
936
  		if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_UPPER, sr->upper))
1593123a6   Richard Alpe   tipc: add name ta...
937
938
939
940
941
  			goto publ_msg_full;
  		if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_SCOPE, p->scope))
  			goto publ_msg_full;
  		if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_NODE, p->node))
  			goto publ_msg_full;
e50e73e10   Jon Maloy   tipc: some name c...
942
  		if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_REF, p->port))
1593123a6   Richard Alpe   tipc: add name ta...
943
944
945
  			goto publ_msg_full;
  		if (nla_put_u32(msg->skb, TIPC_NLA_PUBL_KEY, p->key))
  			goto publ_msg_full;
218527fe2   Jon Maloy   tipc: replace nam...
946
  		nla_nest_end(msg->skb, b);
1593123a6   Richard Alpe   tipc: add name ta...
947
948
949
  		nla_nest_end(msg->skb, attrs);
  		genlmsg_end(msg->skb, hdr);
  	}
218527fe2   Jon Maloy   tipc: replace nam...
950
  	*last_key = 0;
1593123a6   Richard Alpe   tipc: add name ta...
951
952
953
954
  
  	return 0;
  
  publ_msg_full:
218527fe2   Jon Maloy   tipc: replace nam...
955
  	nla_nest_cancel(msg->skb, b);
1593123a6   Richard Alpe   tipc: add name ta...
956
957
958
959
960
961
962
  attr_msg_full:
  	nla_nest_cancel(msg->skb, attrs);
  msg_full:
  	genlmsg_cancel(msg->skb, hdr);
  
  	return -EMSGSIZE;
  }
218527fe2   Jon Maloy   tipc: replace nam...
963
964
965
  static int __tipc_nl_service_range_list(struct tipc_nl_msg *msg,
  					struct tipc_service *sc,
  					u32 *last_lower, u32 *last_key)
1593123a6   Richard Alpe   tipc: add name ta...
966
  {
218527fe2   Jon Maloy   tipc: replace nam...
967
968
  	struct service_range *sr;
  	struct rb_node *n;
1593123a6   Richard Alpe   tipc: add name ta...
969
  	int err;
218527fe2   Jon Maloy   tipc: replace nam...
970
971
972
973
974
  	for (n = rb_first(&sc->ranges); n; n = rb_next(n)) {
  		sr = container_of(n, struct service_range, tree_node);
  		if (sr->lower < *last_lower)
  			continue;
  		err = __tipc_nl_add_nametable_publ(msg, sc, sr, last_key);
1593123a6   Richard Alpe   tipc: add name ta...
975
  		if (err) {
218527fe2   Jon Maloy   tipc: replace nam...
976
  			*last_lower = sr->lower;
1593123a6   Richard Alpe   tipc: add name ta...
977
978
979
980
  			return err;
  		}
  	}
  	*last_lower = 0;
1593123a6   Richard Alpe   tipc: add name ta...
981
982
  	return 0;
  }
218527fe2   Jon Maloy   tipc: replace nam...
983
984
  static int tipc_nl_service_list(struct net *net, struct tipc_nl_msg *msg,
  				u32 *last_type, u32 *last_lower, u32 *last_key)
1593123a6   Richard Alpe   tipc: add name ta...
985
  {
218527fe2   Jon Maloy   tipc: replace nam...
986
987
988
  	struct tipc_net *tn = tipc_net(net);
  	struct tipc_service *service = NULL;
  	struct hlist_head *head;
1593123a6   Richard Alpe   tipc: add name ta...
989
990
991
992
993
994
995
996
997
  	int err;
  	int i;
  
  	if (*last_type)
  		i = hash(*last_type);
  	else
  		i = 0;
  
  	for (; i < TIPC_NAMETBL_SIZE; i++) {
218527fe2   Jon Maloy   tipc: replace nam...
998
  		head = &tn->nametbl->services[i];
1593123a6   Richard Alpe   tipc: add name ta...
999

d1841533e   Hoang Le   tipc: missing ent...
1000
1001
  		if (*last_type ||
  		    (!i && *last_key && (*last_lower == *last_key))) {
218527fe2   Jon Maloy   tipc: replace nam...
1002
1003
  			service = tipc_service_find(net, *last_type);
  			if (!service)
1593123a6   Richard Alpe   tipc: add name ta...
1004
1005
  				return -EPIPE;
  		} else {
218527fe2   Jon Maloy   tipc: replace nam...
1006
  			hlist_for_each_entry_rcu(service, head, service_list)
97ede29e8   Ying Xue   tipc: convert nam...
1007
  				break;
218527fe2   Jon Maloy   tipc: replace nam...
1008
  			if (!service)
1593123a6   Richard Alpe   tipc: add name ta...
1009
1010
  				continue;
  		}
218527fe2   Jon Maloy   tipc: replace nam...
1011
1012
1013
1014
1015
  		hlist_for_each_entry_from_rcu(service, service_list) {
  			spin_lock_bh(&service->lock);
  			err = __tipc_nl_service_range_list(msg, service,
  							   last_lower,
  							   last_key);
1593123a6   Richard Alpe   tipc: add name ta...
1016
1017
  
  			if (err) {
218527fe2   Jon Maloy   tipc: replace nam...
1018
1019
  				*last_type = service->type;
  				spin_unlock_bh(&service->lock);
1593123a6   Richard Alpe   tipc: add name ta...
1020
1021
  				return err;
  			}
218527fe2   Jon Maloy   tipc: replace nam...
1022
  			spin_unlock_bh(&service->lock);
1593123a6   Richard Alpe   tipc: add name ta...
1023
1024
1025
1026
1027
1028
1029
1030
  		}
  		*last_type = 0;
  	}
  	return 0;
  }
  
  int tipc_nl_name_table_dump(struct sk_buff *skb, struct netlink_callback *cb)
  {
218527fe2   Jon Maloy   tipc: replace nam...
1031
  	struct net *net = sock_net(skb->sk);
1593123a6   Richard Alpe   tipc: add name ta...
1032
1033
  	u32 last_type = cb->args[0];
  	u32 last_lower = cb->args[1];
218527fe2   Jon Maloy   tipc: replace nam...
1034
1035
  	u32 last_key = cb->args[2];
  	int done = cb->args[3];
1593123a6   Richard Alpe   tipc: add name ta...
1036
  	struct tipc_nl_msg msg;
218527fe2   Jon Maloy   tipc: replace nam...
1037
  	int err;
1593123a6   Richard Alpe   tipc: add name ta...
1038
1039
1040
1041
1042
1043
1044
  
  	if (done)
  		return 0;
  
  	msg.skb = skb;
  	msg.portid = NETLINK_CB(cb->skb).portid;
  	msg.seq = cb->nlh->nlmsg_seq;
97ede29e8   Ying Xue   tipc: convert nam...
1045
  	rcu_read_lock();
218527fe2   Jon Maloy   tipc: replace nam...
1046
1047
  	err = tipc_nl_service_list(net, &msg, &last_type,
  				   &last_lower, &last_key);
1593123a6   Richard Alpe   tipc: add name ta...
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
  	if (!err) {
  		done = 1;
  	} else if (err != -EMSGSIZE) {
  		/* We never set seq or call nl_dump_check_consistent() this
  		 * means that setting prev_seq here will cause the consistence
  		 * check to fail in the netlink callback handler. Resulting in
  		 * the NLMSG_DONE message having the NLM_F_DUMP_INTR flag set if
  		 * we got an error.
  		 */
  		cb->prev_seq = 1;
  	}
97ede29e8   Ying Xue   tipc: convert nam...
1059
  	rcu_read_unlock();
1593123a6   Richard Alpe   tipc: add name ta...
1060
1061
1062
  
  	cb->args[0] = last_type;
  	cb->args[1] = last_lower;
218527fe2   Jon Maloy   tipc: replace nam...
1063
  	cb->args[2] = last_key;
1593123a6   Richard Alpe   tipc: add name ta...
1064
1065
1066
1067
  	cb->args[3] = done;
  
  	return skb->len;
  }
3c724acdd   Jon Paul Maloy   tipc: simplify so...
1068

a80ae5306   Jon Maloy   tipc: improve des...
1069
  struct tipc_dest *tipc_dest_find(struct list_head *l, u32 node, u32 port)
3c724acdd   Jon Paul Maloy   tipc: simplify so...
1070
  {
a80ae5306   Jon Maloy   tipc: improve des...
1071
  	struct tipc_dest *dst;
3c724acdd   Jon Paul Maloy   tipc: simplify so...
1072

a80ae5306   Jon Maloy   tipc: improve des...
1073
  	list_for_each_entry(dst, l, list) {
30935198b   Haiqing Bai   tipc: fix the big...
1074
1075
  		if (dst->node == node && dst->port == port)
  			return dst;
3c724acdd   Jon Paul Maloy   tipc: simplify so...
1076
  	}
a80ae5306   Jon Maloy   tipc: improve des...
1077
  	return NULL;
4d8642d89   Jon Paul Maloy   tipc: modify stru...
1078
  }
a80ae5306   Jon Maloy   tipc: improve des...
1079
  bool tipc_dest_push(struct list_head *l, u32 node, u32 port)
4d8642d89   Jon Paul Maloy   tipc: modify stru...
1080
  {
a80ae5306   Jon Maloy   tipc: improve des...
1081
  	struct tipc_dest *dst;
4d8642d89   Jon Paul Maloy   tipc: modify stru...
1082

a80ae5306   Jon Maloy   tipc: improve des...
1083
  	if (tipc_dest_find(l, node, port))
4d8642d89   Jon Paul Maloy   tipc: modify stru...
1084
  		return false;
a80ae5306   Jon Maloy   tipc: improve des...
1085
1086
1087
  	dst = kmalloc(sizeof(*dst), GFP_ATOMIC);
  	if (unlikely(!dst))
  		return false;
30935198b   Haiqing Bai   tipc: fix the big...
1088
1089
  	dst->node = node;
  	dst->port = port;
a80ae5306   Jon Maloy   tipc: improve des...
1090
  	list_add(&dst->list, l);
4d8642d89   Jon Paul Maloy   tipc: modify stru...
1091
1092
  	return true;
  }
a80ae5306   Jon Maloy   tipc: improve des...
1093
  bool tipc_dest_pop(struct list_head *l, u32 *node, u32 *port)
4d8642d89   Jon Paul Maloy   tipc: modify stru...
1094
  {
a80ae5306   Jon Maloy   tipc: improve des...
1095
  	struct tipc_dest *dst;
4d8642d89   Jon Paul Maloy   tipc: modify stru...
1096
1097
  
  	if (list_empty(l))
a80ae5306   Jon Maloy   tipc: improve des...
1098
1099
1100
1101
1102
1103
1104
1105
1106
  		return false;
  	dst = list_first_entry(l, typeof(*dst), list);
  	if (port)
  		*port = dst->port;
  	if (node)
  		*node = dst->node;
  	list_del(&dst->list);
  	kfree(dst);
  	return true;
4d8642d89   Jon Paul Maloy   tipc: modify stru...
1107
  }
a80ae5306   Jon Maloy   tipc: improve des...
1108
  bool tipc_dest_del(struct list_head *l, u32 node, u32 port)
4d8642d89   Jon Paul Maloy   tipc: modify stru...
1109
  {
a80ae5306   Jon Maloy   tipc: improve des...
1110
  	struct tipc_dest *dst;
4d8642d89   Jon Paul Maloy   tipc: modify stru...
1111

a80ae5306   Jon Maloy   tipc: improve des...
1112
1113
1114
1115
1116
1117
  	dst = tipc_dest_find(l, node, port);
  	if (!dst)
  		return false;
  	list_del(&dst->list);
  	kfree(dst);
  	return true;
4d8642d89   Jon Paul Maloy   tipc: modify stru...
1118
  }
a80ae5306   Jon Maloy   tipc: improve des...
1119
  void tipc_dest_list_purge(struct list_head *l)
4d8642d89   Jon Paul Maloy   tipc: modify stru...
1120
  {
a80ae5306   Jon Maloy   tipc: improve des...
1121
  	struct tipc_dest *dst, *tmp;
4d8642d89   Jon Paul Maloy   tipc: modify stru...
1122

a80ae5306   Jon Maloy   tipc: improve des...
1123
1124
1125
  	list_for_each_entry_safe(dst, tmp, l, list) {
  		list_del(&dst->list);
  		kfree(dst);
3c724acdd   Jon Paul Maloy   tipc: simplify so...
1126
1127
  	}
  }
a80ae5306   Jon Maloy   tipc: improve des...
1128
  int tipc_dest_list_len(struct list_head *l)
3c724acdd   Jon Paul Maloy   tipc: simplify so...
1129
  {
a80ae5306   Jon Maloy   tipc: improve des...
1130
  	struct tipc_dest *dst;
4d8642d89   Jon Paul Maloy   tipc: modify stru...
1131
  	int i = 0;
3c724acdd   Jon Paul Maloy   tipc: simplify so...
1132

a80ae5306   Jon Maloy   tipc: improve des...
1133
  	list_for_each_entry(dst, l, list) {
4d8642d89   Jon Paul Maloy   tipc: modify stru...
1134
  		i++;
3c724acdd   Jon Paul Maloy   tipc: simplify so...
1135
  	}
4d8642d89   Jon Paul Maloy   tipc: modify stru...
1136
  	return i;
3c724acdd   Jon Paul Maloy   tipc: simplify so...
1137
  }