diff options
Diffstat (limited to 'net/tipc/msg.c')
-rw-r--r-- | net/tipc/msg.c | 153 |
1 files changed, 106 insertions, 47 deletions
diff --git a/net/tipc/msg.c b/net/tipc/msg.c index a687b30a699c..b6eb90cd3ef7 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c | |||
@@ -34,6 +34,7 @@ | |||
34 | * POSSIBILITY OF SUCH DAMAGE. | 34 | * POSSIBILITY OF SUCH DAMAGE. |
35 | */ | 35 | */ |
36 | 36 | ||
37 | #include <net/sock.h> | ||
37 | #include "core.h" | 38 | #include "core.h" |
38 | #include "msg.h" | 39 | #include "msg.h" |
39 | #include "addr.h" | 40 | #include "addr.h" |
@@ -46,25 +47,48 @@ static unsigned int align(unsigned int i) | |||
46 | return (i + 3) & ~3u; | 47 | return (i + 3) & ~3u; |
47 | } | 48 | } |
48 | 49 | ||
49 | void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, u32 hsize, | 50 | /** |
50 | u32 destnode) | 51 | * tipc_buf_acquire - creates a TIPC message buffer |
52 | * @size: message size (including TIPC header) | ||
53 | * | ||
54 | * Returns a new buffer with data pointers set to the specified size. | ||
55 | * | ||
56 | * NOTE: Headroom is reserved to allow prepending of a data link header. | ||
57 | * There may also be unrequested tailroom present at the buffer's end. | ||
58 | */ | ||
59 | struct sk_buff *tipc_buf_acquire(u32 size) | ||
60 | { | ||
61 | struct sk_buff *skb; | ||
62 | unsigned int buf_size = (BUF_HEADROOM + size + 3) & ~3u; | ||
63 | |||
64 | skb = alloc_skb_fclone(buf_size, GFP_ATOMIC); | ||
65 | if (skb) { | ||
66 | skb_reserve(skb, BUF_HEADROOM); | ||
67 | skb_put(skb, size); | ||
68 | skb->next = NULL; | ||
69 | } | ||
70 | return skb; | ||
71 | } | ||
72 | |||
73 | void tipc_msg_init(u32 own_node, struct tipc_msg *m, u32 user, u32 type, | ||
74 | u32 hsize, u32 dnode) | ||
51 | { | 75 | { |
52 | memset(m, 0, hsize); | 76 | memset(m, 0, hsize); |
53 | msg_set_version(m); | 77 | msg_set_version(m); |
54 | msg_set_user(m, user); | 78 | msg_set_user(m, user); |
55 | msg_set_hdr_sz(m, hsize); | 79 | msg_set_hdr_sz(m, hsize); |
56 | msg_set_size(m, hsize); | 80 | msg_set_size(m, hsize); |
57 | msg_set_prevnode(m, tipc_own_addr); | 81 | msg_set_prevnode(m, own_node); |
58 | msg_set_type(m, type); | 82 | msg_set_type(m, type); |
59 | if (hsize > SHORT_H_SIZE) { | 83 | if (hsize > SHORT_H_SIZE) { |
60 | msg_set_orignode(m, tipc_own_addr); | 84 | msg_set_orignode(m, own_node); |
61 | msg_set_destnode(m, destnode); | 85 | msg_set_destnode(m, dnode); |
62 | } | 86 | } |
63 | } | 87 | } |
64 | 88 | ||
65 | struct sk_buff *tipc_msg_create(uint user, uint type, uint hdr_sz, | 89 | struct sk_buff *tipc_msg_create(uint user, uint type, |
66 | uint data_sz, u32 dnode, u32 onode, | 90 | uint hdr_sz, uint data_sz, u32 dnode, |
67 | u32 dport, u32 oport, int errcode) | 91 | u32 onode, u32 dport, u32 oport, int errcode) |
68 | { | 92 | { |
69 | struct tipc_msg *msg; | 93 | struct tipc_msg *msg; |
70 | struct sk_buff *buf; | 94 | struct sk_buff *buf; |
@@ -74,9 +98,8 @@ struct sk_buff *tipc_msg_create(uint user, uint type, uint hdr_sz, | |||
74 | return NULL; | 98 | return NULL; |
75 | 99 | ||
76 | msg = buf_msg(buf); | 100 | msg = buf_msg(buf); |
77 | tipc_msg_init(msg, user, type, hdr_sz, dnode); | 101 | tipc_msg_init(onode, msg, user, type, hdr_sz, dnode); |
78 | msg_set_size(msg, hdr_sz + data_sz); | 102 | msg_set_size(msg, hdr_sz + data_sz); |
79 | msg_set_prevnode(msg, onode); | ||
80 | msg_set_origport(msg, oport); | 103 | msg_set_origport(msg, oport); |
81 | msg_set_destport(msg, dport); | 104 | msg_set_destport(msg, dport); |
82 | msg_set_errcode(msg, errcode); | 105 | msg_set_errcode(msg, errcode); |
@@ -163,15 +186,14 @@ err: | |||
163 | * tipc_msg_build - create buffer chain containing specified header and data | 186 | * tipc_msg_build - create buffer chain containing specified header and data |
164 | * @mhdr: Message header, to be prepended to data | 187 | * @mhdr: Message header, to be prepended to data |
165 | * @m: User message | 188 | * @m: User message |
166 | * @offset: Posision in iov to start copying from | ||
167 | * @dsz: Total length of user data | 189 | * @dsz: Total length of user data |
168 | * @pktmax: Max packet size that can be used | 190 | * @pktmax: Max packet size that can be used |
169 | * @list: Buffer or chain of buffers to be returned to caller | 191 | * @list: Buffer or chain of buffers to be returned to caller |
170 | * | 192 | * |
171 | * Returns message data size or errno: -ENOMEM, -EFAULT | 193 | * Returns message data size or errno: -ENOMEM, -EFAULT |
172 | */ | 194 | */ |
173 | int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, int offset, | 195 | int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, |
174 | int dsz, int pktmax, struct sk_buff_head *list) | 196 | int offset, int dsz, int pktmax, struct sk_buff_head *list) |
175 | { | 197 | { |
176 | int mhsz = msg_hdr_sz(mhdr); | 198 | int mhsz = msg_hdr_sz(mhdr); |
177 | int msz = mhsz + dsz; | 199 | int msz = mhsz + dsz; |
@@ -191,19 +213,19 @@ int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, int offset, | |||
191 | skb = tipc_buf_acquire(msz); | 213 | skb = tipc_buf_acquire(msz); |
192 | if (unlikely(!skb)) | 214 | if (unlikely(!skb)) |
193 | return -ENOMEM; | 215 | return -ENOMEM; |
216 | skb_orphan(skb); | ||
194 | __skb_queue_tail(list, skb); | 217 | __skb_queue_tail(list, skb); |
195 | skb_copy_to_linear_data(skb, mhdr, mhsz); | 218 | skb_copy_to_linear_data(skb, mhdr, mhsz); |
196 | pktpos = skb->data + mhsz; | 219 | pktpos = skb->data + mhsz; |
197 | if (!dsz || !memcpy_fromiovecend(pktpos, m->msg_iter.iov, offset, | 220 | if (copy_from_iter(pktpos, dsz, &m->msg_iter) == dsz) |
198 | dsz)) | ||
199 | return dsz; | 221 | return dsz; |
200 | rc = -EFAULT; | 222 | rc = -EFAULT; |
201 | goto error; | 223 | goto error; |
202 | } | 224 | } |
203 | 225 | ||
204 | /* Prepare reusable fragment header */ | 226 | /* Prepare reusable fragment header */ |
205 | tipc_msg_init(&pkthdr, MSG_FRAGMENTER, FIRST_FRAGMENT, | 227 | tipc_msg_init(msg_prevnode(mhdr), &pkthdr, MSG_FRAGMENTER, |
206 | INT_H_SIZE, msg_destnode(mhdr)); | 228 | FIRST_FRAGMENT, INT_H_SIZE, msg_destnode(mhdr)); |
207 | msg_set_size(&pkthdr, pktmax); | 229 | msg_set_size(&pkthdr, pktmax); |
208 | msg_set_fragm_no(&pkthdr, pktno); | 230 | msg_set_fragm_no(&pkthdr, pktno); |
209 | 231 | ||
@@ -211,6 +233,7 @@ int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, int offset, | |||
211 | skb = tipc_buf_acquire(pktmax); | 233 | skb = tipc_buf_acquire(pktmax); |
212 | if (!skb) | 234 | if (!skb) |
213 | return -ENOMEM; | 235 | return -ENOMEM; |
236 | skb_orphan(skb); | ||
214 | __skb_queue_tail(list, skb); | 237 | __skb_queue_tail(list, skb); |
215 | pktpos = skb->data; | 238 | pktpos = skb->data; |
216 | skb_copy_to_linear_data(skb, &pkthdr, INT_H_SIZE); | 239 | skb_copy_to_linear_data(skb, &pkthdr, INT_H_SIZE); |
@@ -224,12 +247,11 @@ int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, int offset, | |||
224 | if (drem < pktrem) | 247 | if (drem < pktrem) |
225 | pktrem = drem; | 248 | pktrem = drem; |
226 | 249 | ||
227 | if (memcpy_fromiovecend(pktpos, m->msg_iter.iov, offset, pktrem)) { | 250 | if (copy_from_iter(pktpos, pktrem, &m->msg_iter) != pktrem) { |
228 | rc = -EFAULT; | 251 | rc = -EFAULT; |
229 | goto error; | 252 | goto error; |
230 | } | 253 | } |
231 | drem -= pktrem; | 254 | drem -= pktrem; |
232 | offset += pktrem; | ||
233 | 255 | ||
234 | if (!drem) | 256 | if (!drem) |
235 | break; | 257 | break; |
@@ -244,6 +266,7 @@ int tipc_msg_build(struct tipc_msg *mhdr, struct msghdr *m, int offset, | |||
244 | rc = -ENOMEM; | 266 | rc = -ENOMEM; |
245 | goto error; | 267 | goto error; |
246 | } | 268 | } |
269 | skb_orphan(skb); | ||
247 | __skb_queue_tail(list, skb); | 270 | __skb_queue_tail(list, skb); |
248 | msg_set_type(&pkthdr, FRAGMENT); | 271 | msg_set_type(&pkthdr, FRAGMENT); |
249 | msg_set_size(&pkthdr, pktsz); | 272 | msg_set_size(&pkthdr, pktsz); |
@@ -304,6 +327,40 @@ bool tipc_msg_bundle(struct sk_buff_head *list, struct sk_buff *skb, u32 mtu) | |||
304 | } | 327 | } |
305 | 328 | ||
306 | /** | 329 | /** |
330 | * tipc_msg_extract(): extract bundled inner packet from buffer | ||
331 | * @skb: linear outer buffer, to be extracted from. | ||
332 | * @iskb: extracted inner buffer, to be returned | ||
333 | * @pos: position of msg to be extracted. Returns with pointer of next msg | ||
334 | * Consumes outer buffer when last packet extracted | ||
335 | * Returns true when when there is an extracted buffer, otherwise false | ||
336 | */ | ||
337 | bool tipc_msg_extract(struct sk_buff *skb, struct sk_buff **iskb, int *pos) | ||
338 | { | ||
339 | struct tipc_msg *msg = buf_msg(skb); | ||
340 | int imsz; | ||
341 | struct tipc_msg *imsg = (struct tipc_msg *)(msg_data(msg) + *pos); | ||
342 | |||
343 | /* Is there space left for shortest possible message? */ | ||
344 | if (*pos > (msg_data_sz(msg) - SHORT_H_SIZE)) | ||
345 | goto none; | ||
346 | imsz = msg_size(imsg); | ||
347 | |||
348 | /* Is there space left for current message ? */ | ||
349 | if ((*pos + imsz) > msg_data_sz(msg)) | ||
350 | goto none; | ||
351 | *iskb = tipc_buf_acquire(imsz); | ||
352 | if (!*iskb) | ||
353 | goto none; | ||
354 | skb_copy_to_linear_data(*iskb, imsg, imsz); | ||
355 | *pos += align(imsz); | ||
356 | return true; | ||
357 | none: | ||
358 | kfree_skb(skb); | ||
359 | *iskb = NULL; | ||
360 | return false; | ||
361 | } | ||
362 | |||
363 | /** | ||
307 | * tipc_msg_make_bundle(): Create bundle buf and append message to its tail | 364 | * tipc_msg_make_bundle(): Create bundle buf and append message to its tail |
308 | * @list: the buffer chain | 365 | * @list: the buffer chain |
309 | * @skb: buffer to be appended and replaced | 366 | * @skb: buffer to be appended and replaced |
@@ -312,8 +369,8 @@ bool tipc_msg_bundle(struct sk_buff_head *list, struct sk_buff *skb, u32 mtu) | |||
312 | * Replaces buffer if successful | 369 | * Replaces buffer if successful |
313 | * Returns true if success, otherwise false | 370 | * Returns true if success, otherwise false |
314 | */ | 371 | */ |
315 | bool tipc_msg_make_bundle(struct sk_buff_head *list, struct sk_buff *skb, | 372 | bool tipc_msg_make_bundle(struct sk_buff_head *list, |
316 | u32 mtu, u32 dnode) | 373 | struct sk_buff *skb, u32 mtu, u32 dnode) |
317 | { | 374 | { |
318 | struct sk_buff *bskb; | 375 | struct sk_buff *bskb; |
319 | struct tipc_msg *bmsg; | 376 | struct tipc_msg *bmsg; |
@@ -336,7 +393,8 @@ bool tipc_msg_make_bundle(struct sk_buff_head *list, struct sk_buff *skb, | |||
336 | 393 | ||
337 | skb_trim(bskb, INT_H_SIZE); | 394 | skb_trim(bskb, INT_H_SIZE); |
338 | bmsg = buf_msg(bskb); | 395 | bmsg = buf_msg(bskb); |
339 | tipc_msg_init(bmsg, MSG_BUNDLER, 0, INT_H_SIZE, dnode); | 396 | tipc_msg_init(msg_prevnode(msg), bmsg, MSG_BUNDLER, 0, |
397 | INT_H_SIZE, dnode); | ||
340 | msg_set_seqno(bmsg, msg_seqno(msg)); | 398 | msg_set_seqno(bmsg, msg_seqno(msg)); |
341 | msg_set_ack(bmsg, msg_ack(msg)); | 399 | msg_set_ack(bmsg, msg_ack(msg)); |
342 | msg_set_bcast_ack(bmsg, msg_bcast_ack(msg)); | 400 | msg_set_bcast_ack(bmsg, msg_bcast_ack(msg)); |
@@ -353,7 +411,8 @@ bool tipc_msg_make_bundle(struct sk_buff_head *list, struct sk_buff *skb, | |||
353 | * Consumes buffer if failure | 411 | * Consumes buffer if failure |
354 | * Returns true if success, otherwise false | 412 | * Returns true if success, otherwise false |
355 | */ | 413 | */ |
356 | bool tipc_msg_reverse(struct sk_buff *buf, u32 *dnode, int err) | 414 | bool tipc_msg_reverse(u32 own_addr, struct sk_buff *buf, u32 *dnode, |
415 | int err) | ||
357 | { | 416 | { |
358 | struct tipc_msg *msg = buf_msg(buf); | 417 | struct tipc_msg *msg = buf_msg(buf); |
359 | uint imp = msg_importance(msg); | 418 | uint imp = msg_importance(msg); |
@@ -374,7 +433,7 @@ bool tipc_msg_reverse(struct sk_buff *buf, u32 *dnode, int err) | |||
374 | msg_set_errcode(msg, err); | 433 | msg_set_errcode(msg, err); |
375 | msg_set_origport(msg, msg_destport(&ohdr)); | 434 | msg_set_origport(msg, msg_destport(&ohdr)); |
376 | msg_set_destport(msg, msg_origport(&ohdr)); | 435 | msg_set_destport(msg, msg_origport(&ohdr)); |
377 | msg_set_prevnode(msg, tipc_own_addr); | 436 | msg_set_prevnode(msg, own_addr); |
378 | if (!msg_short(msg)) { | 437 | if (!msg_short(msg)) { |
379 | msg_set_orignode(msg, msg_destnode(&ohdr)); | 438 | msg_set_orignode(msg, msg_destnode(&ohdr)); |
380 | msg_set_destnode(msg, msg_orignode(&ohdr)); | 439 | msg_set_destnode(msg, msg_orignode(&ohdr)); |
@@ -386,43 +445,43 @@ bool tipc_msg_reverse(struct sk_buff *buf, u32 *dnode, int err) | |||
386 | return true; | 445 | return true; |
387 | exit: | 446 | exit: |
388 | kfree_skb(buf); | 447 | kfree_skb(buf); |
448 | *dnode = 0; | ||
389 | return false; | 449 | return false; |
390 | } | 450 | } |
391 | 451 | ||
392 | /** | 452 | /** |
393 | * tipc_msg_eval: determine fate of message that found no destination | 453 | * tipc_msg_lookup_dest(): try to find new destination for named message |
394 | * @buf: the buffer containing the message. | 454 | * @skb: the buffer containing the message. |
395 | * @dnode: return value: next-hop node, if message to be forwarded | 455 | * @dnode: return value: next-hop node, if destination found |
396 | * @err: error code to use, if message to be rejected | 456 | * @err: return value: error code to use, if message to be rejected |
397 | * | ||
398 | * Does not consume buffer | 457 | * Does not consume buffer |
399 | * Returns 0 (TIPC_OK) if message ok and we can try again, -TIPC error | 458 | * Returns true if a destination is found, false otherwise |
400 | * code if message to be rejected | ||
401 | */ | 459 | */ |
402 | int tipc_msg_eval(struct sk_buff *buf, u32 *dnode) | 460 | bool tipc_msg_lookup_dest(struct net *net, struct sk_buff *skb, |
461 | u32 *dnode, int *err) | ||
403 | { | 462 | { |
404 | struct tipc_msg *msg = buf_msg(buf); | 463 | struct tipc_msg *msg = buf_msg(skb); |
405 | u32 dport; | 464 | u32 dport; |
406 | 465 | ||
407 | if (msg_type(msg) != TIPC_NAMED_MSG) | 466 | if (!msg_isdata(msg)) |
408 | return -TIPC_ERR_NO_PORT; | 467 | return false; |
409 | if (skb_linearize(buf)) | 468 | if (!msg_named(msg)) |
410 | return -TIPC_ERR_NO_NAME; | 469 | return false; |
411 | if (msg_data_sz(msg) > MAX_FORWARD_SIZE) | 470 | *err = -TIPC_ERR_NO_NAME; |
412 | return -TIPC_ERR_NO_NAME; | 471 | if (skb_linearize(skb)) |
472 | return false; | ||
413 | if (msg_reroute_cnt(msg) > 0) | 473 | if (msg_reroute_cnt(msg) > 0) |
414 | return -TIPC_ERR_NO_NAME; | 474 | return false; |
415 | 475 | *dnode = addr_domain(net, msg_lookup_scope(msg)); | |
416 | *dnode = addr_domain(msg_lookup_scope(msg)); | 476 | dport = tipc_nametbl_translate(net, msg_nametype(msg), |
417 | dport = tipc_nametbl_translate(msg_nametype(msg), | 477 | msg_nameinst(msg), dnode); |
418 | msg_nameinst(msg), | ||
419 | dnode); | ||
420 | if (!dport) | 478 | if (!dport) |
421 | return -TIPC_ERR_NO_NAME; | 479 | return false; |
422 | msg_incr_reroute_cnt(msg); | 480 | msg_incr_reroute_cnt(msg); |
423 | msg_set_destnode(msg, *dnode); | 481 | msg_set_destnode(msg, *dnode); |
424 | msg_set_destport(msg, dport); | 482 | msg_set_destport(msg, dport); |
425 | return TIPC_OK; | 483 | *err = TIPC_OK; |
484 | return true; | ||
426 | } | 485 | } |
427 | 486 | ||
428 | /* tipc_msg_reassemble() - clone a buffer chain of fragments and | 487 | /* tipc_msg_reassemble() - clone a buffer chain of fragments and |