1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37#include "core.h"
38#include "link.h"
39#include "discover.h"
40
41
42#define TIPC_LINK_REQ_INIT msecs_to_jiffies(125)
43
44#define TIPC_LINK_REQ_FAST msecs_to_jiffies(1000)
45
46#define TIPC_LINK_REQ_SLOW msecs_to_jiffies(60000)
47
48#define TIPC_LINK_REQ_INACTIVE 0xffffffff
49
50
51
52
53
54
55
56
57
58
59
60
61
62struct tipc_link_req {
63 u32 bearer_id;
64 struct tipc_media_addr dest;
65 struct net *net;
66 u32 domain;
67 int num_nodes;
68 spinlock_t lock;
69 struct sk_buff *buf;
70 struct timer_list timer;
71 unsigned long timer_intv;
72};
73
74
75
76
77
78
79
80static void tipc_disc_init_msg(struct net *net, struct sk_buff *buf, u32 type,
81 struct tipc_bearer *b_ptr)
82{
83 struct tipc_net *tn = net_generic(net, tipc_net_id);
84 struct tipc_msg *msg;
85 u32 dest_domain = b_ptr->domain;
86
87 msg = buf_msg(buf);
88 tipc_msg_init(tn->own_addr, msg, LINK_CONFIG, type,
89 MAX_H_SIZE, dest_domain);
90 msg_set_non_seq(msg, 1);
91 msg_set_node_sig(msg, tn->random);
92 msg_set_node_capabilities(msg, 0);
93 msg_set_dest_domain(msg, dest_domain);
94 msg_set_bc_netid(msg, tn->net_id);
95 b_ptr->media->addr2msg(msg_media_addr(msg), &b_ptr->addr);
96}
97
98
99
100
101
102
103
104static void disc_dupl_alert(struct tipc_bearer *b_ptr, u32 node_addr,
105 struct tipc_media_addr *media_addr)
106{
107 char node_addr_str[16];
108 char media_addr_str[64];
109
110 tipc_addr_string_fill(node_addr_str, node_addr);
111 tipc_media_addr_printf(media_addr_str, sizeof(media_addr_str),
112 media_addr);
113 pr_warn("Duplicate %s using %s seen on <%s>\n", node_addr_str,
114 media_addr_str, b_ptr->name);
115}
116
117
118
119
120
121
122
123void tipc_disc_rcv(struct net *net, struct sk_buff *buf,
124 struct tipc_bearer *bearer)
125{
126 struct tipc_net *tn = net_generic(net, tipc_net_id);
127 struct tipc_node *node;
128 struct tipc_link *link;
129 struct tipc_media_addr maddr;
130 struct sk_buff *rbuf;
131 struct tipc_msg *msg = buf_msg(buf);
132 u32 ddom = msg_dest_domain(msg);
133 u32 onode = msg_prevnode(msg);
134 u32 net_id = msg_bc_netid(msg);
135 u32 mtyp = msg_type(msg);
136 u32 signature = msg_node_sig(msg);
137 u16 caps = msg_node_capabilities(msg);
138 bool addr_match = false;
139 bool sign_match = false;
140 bool link_up = false;
141 bool accept_addr = false;
142 bool accept_sign = false;
143 bool respond = false;
144
145 bearer->media->msg2addr(bearer, &maddr, msg_media_addr(msg));
146 kfree_skb(buf);
147
148
149 if (net_id != tn->net_id)
150 return;
151 if (maddr.broadcast)
152 return;
153 if (!tipc_addr_domain_valid(ddom))
154 return;
155 if (!tipc_addr_node_valid(onode))
156 return;
157
158 if (in_own_node(net, onode)) {
159 if (memcmp(&maddr, &bearer->addr, sizeof(maddr)))
160 disc_dupl_alert(bearer, tn->own_addr, &maddr);
161 return;
162 }
163 if (!tipc_in_scope(ddom, tn->own_addr))
164 return;
165 if (!tipc_in_scope(bearer->domain, onode))
166 return;
167
168 node = tipc_node_create(net, onode);
169 if (!node)
170 return;
171 tipc_node_lock(node);
172 node->capabilities = caps;
173 link = node->links[bearer->identity];
174
175
176 sign_match = (signature == node->signature);
177 addr_match = link && !memcmp(&link->media_addr, &maddr, sizeof(maddr));
178 link_up = link && tipc_link_is_up(link);
179
180
181
182
183 if (sign_match && addr_match && link_up) {
184
185 } else if (sign_match && addr_match && !link_up) {
186
187 respond = true;
188 } else if (sign_match && !addr_match && link_up) {
189
190
191
192
193
194
195
196
197 disc_dupl_alert(bearer, onode, &maddr);
198 } else if (sign_match && !addr_match && !link_up) {
199
200
201
202
203
204 accept_addr = true;
205 respond = true;
206 } else if (!sign_match && addr_match && link_up) {
207
208
209
210
211
212
213
214
215
216
217
218 accept_sign = true;
219 } else if (!sign_match && addr_match && !link_up) {
220
221
222
223 accept_sign = true;
224 respond = true;
225 } else if (!sign_match && !addr_match && link_up) {
226
227
228
229 disc_dupl_alert(bearer, onode, &maddr);
230 } else if (!sign_match && !addr_match && !link_up) {
231
232
233
234 accept_sign = true;
235 accept_addr = true;
236 respond = true;
237 }
238
239 if (accept_sign)
240 node->signature = signature;
241
242 if (accept_addr) {
243 if (!link)
244 link = tipc_link_create(node, bearer, &maddr);
245 if (link) {
246 memcpy(&link->media_addr, &maddr, sizeof(maddr));
247 tipc_link_reset(link);
248 } else {
249 respond = false;
250 }
251 }
252
253
254 if (respond && (mtyp == DSC_REQ_MSG)) {
255 rbuf = tipc_buf_acquire(MAX_H_SIZE);
256 if (rbuf) {
257 tipc_disc_init_msg(net, rbuf, DSC_RESP_MSG, bearer);
258 tipc_bearer_send(net, bearer->identity, rbuf, &maddr);
259 kfree_skb(rbuf);
260 }
261 }
262 tipc_node_unlock(node);
263 tipc_node_put(node);
264}
265
266
267
268
269
270
271
272
273static void disc_update(struct tipc_link_req *req)
274{
275 if (!req->num_nodes) {
276 if ((req->timer_intv == TIPC_LINK_REQ_INACTIVE) ||
277 (req->timer_intv > TIPC_LINK_REQ_FAST)) {
278 req->timer_intv = TIPC_LINK_REQ_INIT;
279 mod_timer(&req->timer, jiffies + req->timer_intv);
280 }
281 }
282}
283
284
285
286
287
288void tipc_disc_add_dest(struct tipc_link_req *req)
289{
290 spin_lock_bh(&req->lock);
291 req->num_nodes++;
292 spin_unlock_bh(&req->lock);
293}
294
295
296
297
298
299void tipc_disc_remove_dest(struct tipc_link_req *req)
300{
301 spin_lock_bh(&req->lock);
302 req->num_nodes--;
303 disc_update(req);
304 spin_unlock_bh(&req->lock);
305}
306
307
308
309
310
311
312
313static void disc_timeout(unsigned long data)
314{
315 struct tipc_link_req *req = (struct tipc_link_req *)data;
316 int max_delay;
317
318 spin_lock_bh(&req->lock);
319
320
321 if (tipc_node(req->domain) && req->num_nodes) {
322 req->timer_intv = TIPC_LINK_REQ_INACTIVE;
323 goto exit;
324 }
325
326
327
328
329
330
331
332
333 tipc_bearer_send(req->net, req->bearer_id, req->buf, &req->dest);
334
335
336 req->timer_intv *= 2;
337 if (req->num_nodes)
338 max_delay = TIPC_LINK_REQ_SLOW;
339 else
340 max_delay = TIPC_LINK_REQ_FAST;
341 if (req->timer_intv > max_delay)
342 req->timer_intv = max_delay;
343
344 mod_timer(&req->timer, jiffies + req->timer_intv);
345exit:
346 spin_unlock_bh(&req->lock);
347}
348
349
350
351
352
353
354
355
356
357
358int tipc_disc_create(struct net *net, struct tipc_bearer *b_ptr,
359 struct tipc_media_addr *dest)
360{
361 struct tipc_link_req *req;
362
363 req = kmalloc(sizeof(*req), GFP_ATOMIC);
364 if (!req)
365 return -ENOMEM;
366 req->buf = tipc_buf_acquire(MAX_H_SIZE);
367 if (!req->buf) {
368 kfree(req);
369 return -ENOMEM;
370 }
371
372 tipc_disc_init_msg(net, req->buf, DSC_REQ_MSG, b_ptr);
373 memcpy(&req->dest, dest, sizeof(*dest));
374 req->net = net;
375 req->bearer_id = b_ptr->identity;
376 req->domain = b_ptr->domain;
377 req->num_nodes = 0;
378 req->timer_intv = TIPC_LINK_REQ_INIT;
379 spin_lock_init(&req->lock);
380 setup_timer(&req->timer, disc_timeout, (unsigned long)req);
381 mod_timer(&req->timer, jiffies + req->timer_intv);
382 b_ptr->link_req = req;
383 tipc_bearer_send(net, req->bearer_id, req->buf, &req->dest);
384 return 0;
385}
386
387
388
389
390
391void tipc_disc_delete(struct tipc_link_req *req)
392{
393 del_timer_sync(&req->timer);
394 kfree_skb(req->buf);
395 kfree(req);
396}
397
398
399
400
401
402
403
404void tipc_disc_reset(struct net *net, struct tipc_bearer *b_ptr)
405{
406 struct tipc_link_req *req = b_ptr->link_req;
407
408 spin_lock_bh(&req->lock);
409 tipc_disc_init_msg(net, req->buf, DSC_REQ_MSG, b_ptr);
410 req->net = net;
411 req->bearer_id = b_ptr->identity;
412 req->domain = b_ptr->domain;
413 req->num_nodes = 0;
414 req->timer_intv = TIPC_LINK_REQ_INIT;
415 mod_timer(&req->timer, jiffies + req->timer_intv);
416 tipc_bearer_send(net, req->bearer_id, req->buf, &req->dest);
417 spin_unlock_bh(&req->lock);
418}
419