1 /* 2 * net/tipc/msg.h: Include file for TIPC message header routines 3 * 4 * Copyright (c) 2000-2007, Ericsson AB 5 * Copyright (c) 2005-2007, Wind River Systems 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions are met: 10 * 11 * 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. 19 * 20 * 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 34 * POSSIBILITY OF SUCH DAMAGE. 35 */ 36 37 #ifndef _TIPC_MSG_H 38 #define _TIPC_MSG_H 39 40 #include "core.h" 41 42 #define TIPC_VERSION 2 43 44 #define SHORT_H_SIZE 24 /* Connected, in-cluster messages */ 45 #define DIR_MSG_H_SIZE 32 /* Directly addressed messages */ 46 #define LONG_H_SIZE 40 /* Named messages */ 47 #define MCAST_H_SIZE 44 /* Multicast messages */ 48 #define INT_H_SIZE 40 /* Internal messages */ 49 #define MIN_H_SIZE 24 /* Smallest legal TIPC header size */ 50 #define MAX_H_SIZE 60 /* Largest possible TIPC header size */ 51 52 #define MAX_MSG_SIZE (MAX_H_SIZE + TIPC_MAX_USER_MSG_SIZE) 53 54 55 /* 56 TIPC user data message header format, version 2 57 58 - Fundamental definitions available to privileged TIPC users 59 are located in tipc_msg.h. 60 - Remaining definitions available to TIPC internal users appear below. 61 */ 62 63 64 static inline void msg_set_word(struct tipc_msg *m, u32 w, u32 val) 65 { 66 m->hdr[w] = htonl(val); 67 } 68 69 static inline void msg_set_bits(struct tipc_msg *m, u32 w, 70 u32 pos, u32 mask, u32 val) 71 { 72 val = (val & mask) << pos; 73 mask = mask << pos; 74 m->hdr[w] &= ~htonl(mask); 75 m->hdr[w] |= htonl(val); 76 } 77 78 /* 79 * Word 0 80 */ 81 82 static inline u32 msg_version(struct tipc_msg *m) 83 { 84 return msg_bits(m, 0, 29, 7); 85 } 86 87 static inline void msg_set_version(struct tipc_msg *m) 88 { 89 msg_set_bits(m, 0, 29, 7, TIPC_VERSION); 90 } 91 92 static inline u32 msg_user(struct tipc_msg *m) 93 { 94 return msg_bits(m, 0, 25, 0xf); 95 } 96 97 static inline u32 msg_isdata(struct tipc_msg *m) 98 { 99 return (msg_user(m) <= TIPC_CRITICAL_IMPORTANCE); 100 } 101 102 static inline void msg_set_user(struct tipc_msg *m, u32 n) 103 { 104 msg_set_bits(m, 0, 25, 0xf, n); 105 } 106 107 static inline void msg_set_importance(struct tipc_msg *m, u32 i) 108 { 109 msg_set_user(m, i); 110 } 111 112 static inline void msg_set_hdr_sz(struct tipc_msg *m,u32 n) 113 { 114 msg_set_bits(m, 0, 21, 0xf, n>>2); 115 } 116 117 static inline int msg_non_seq(struct tipc_msg *m) 118 { 119 return msg_bits(m, 0, 20, 1); 120 } 121 122 static inline void msg_set_non_seq(struct tipc_msg *m) 123 { 124 msg_set_bits(m, 0, 20, 1, 1); 125 } 126 127 static inline int msg_dest_droppable(struct tipc_msg *m) 128 { 129 return msg_bits(m, 0, 19, 1); 130 } 131 132 static inline void msg_set_dest_droppable(struct tipc_msg *m, u32 d) 133 { 134 msg_set_bits(m, 0, 19, 1, d); 135 } 136 137 static inline int msg_src_droppable(struct tipc_msg *m) 138 { 139 return msg_bits(m, 0, 18, 1); 140 } 141 142 static inline void msg_set_src_droppable(struct tipc_msg *m, u32 d) 143 { 144 msg_set_bits(m, 0, 18, 1, d); 145 } 146 147 static inline void msg_set_size(struct tipc_msg *m, u32 sz) 148 { 149 m->hdr[0] = htonl((msg_word(m, 0) & ~0x1ffff) | sz); 150 } 151 152 153 /* 154 * Word 1 155 */ 156 157 static inline void msg_set_type(struct tipc_msg *m, u32 n) 158 { 159 msg_set_bits(m, 1, 29, 0x7, n); 160 } 161 162 static inline void msg_set_errcode(struct tipc_msg *m, u32 err) 163 { 164 msg_set_bits(m, 1, 25, 0xf, err); 165 } 166 167 static inline u32 msg_reroute_cnt(struct tipc_msg *m) 168 { 169 return msg_bits(m, 1, 21, 0xf); 170 } 171 172 static inline void msg_incr_reroute_cnt(struct tipc_msg *m) 173 { 174 msg_set_bits(m, 1, 21, 0xf, msg_reroute_cnt(m) + 1); 175 } 176 177 static inline void msg_reset_reroute_cnt(struct tipc_msg *m) 178 { 179 msg_set_bits(m, 1, 21, 0xf, 0); 180 } 181 182 static inline u32 msg_lookup_scope(struct tipc_msg *m) 183 { 184 return msg_bits(m, 1, 19, 0x3); 185 } 186 187 static inline void msg_set_lookup_scope(struct tipc_msg *m, u32 n) 188 { 189 msg_set_bits(m, 1, 19, 0x3, n); 190 } 191 192 static inline u32 msg_bcast_ack(struct tipc_msg *m) 193 { 194 return msg_bits(m, 1, 0, 0xffff); 195 } 196 197 static inline void msg_set_bcast_ack(struct tipc_msg *m, u32 n) 198 { 199 msg_set_bits(m, 1, 0, 0xffff, n); 200 } 201 202 203 /* 204 * Word 2 205 */ 206 207 static inline u32 msg_ack(struct tipc_msg *m) 208 { 209 return msg_bits(m, 2, 16, 0xffff); 210 } 211 212 static inline void msg_set_ack(struct tipc_msg *m, u32 n) 213 { 214 msg_set_bits(m, 2, 16, 0xffff, n); 215 } 216 217 static inline u32 msg_seqno(struct tipc_msg *m) 218 { 219 return msg_bits(m, 2, 0, 0xffff); 220 } 221 222 static inline void msg_set_seqno(struct tipc_msg *m, u32 n) 223 { 224 msg_set_bits(m, 2, 0, 0xffff, n); 225 } 226 227 228 /* 229 * Words 3-10 230 */ 231 232 233 static inline void msg_set_prevnode(struct tipc_msg *m, u32 a) 234 { 235 msg_set_word(m, 3, a); 236 } 237 238 static inline void msg_set_origport(struct tipc_msg *m, u32 p) 239 { 240 msg_set_word(m, 4, p); 241 } 242 243 static inline void msg_set_destport(struct tipc_msg *m, u32 p) 244 { 245 msg_set_word(m, 5, p); 246 } 247 248 static inline void msg_set_mc_netid(struct tipc_msg *m, u32 p) 249 { 250 msg_set_word(m, 5, p); 251 } 252 253 static inline void msg_set_orignode(struct tipc_msg *m, u32 a) 254 { 255 msg_set_word(m, 6, a); 256 } 257 258 static inline void msg_set_destnode(struct tipc_msg *m, u32 a) 259 { 260 msg_set_word(m, 7, a); 261 } 262 263 static inline int msg_is_dest(struct tipc_msg *m, u32 d) 264 { 265 return(msg_short(m) || (msg_destnode(m) == d)); 266 } 267 268 static inline u32 msg_routed(struct tipc_msg *m) 269 { 270 if (likely(msg_short(m))) 271 return 0; 272 return(msg_destnode(m) ^ msg_orignode(m)) >> 11; 273 } 274 275 static inline void msg_set_nametype(struct tipc_msg *m, u32 n) 276 { 277 msg_set_word(m, 8, n); 278 } 279 280 static inline u32 msg_transp_seqno(struct tipc_msg *m) 281 { 282 return msg_word(m, 8); 283 } 284 285 static inline void msg_set_timestamp(struct tipc_msg *m, u32 n) 286 { 287 msg_set_word(m, 8, n); 288 } 289 290 static inline u32 msg_timestamp(struct tipc_msg *m) 291 { 292 return msg_word(m, 8); 293 } 294 295 static inline void msg_set_transp_seqno(struct tipc_msg *m, u32 n) 296 { 297 msg_set_word(m, 8, n); 298 } 299 300 static inline void msg_set_namelower(struct tipc_msg *m, u32 n) 301 { 302 msg_set_word(m, 9, n); 303 } 304 305 static inline void msg_set_nameinst(struct tipc_msg *m, u32 n) 306 { 307 msg_set_namelower(m, n); 308 } 309 310 static inline void msg_set_nameupper(struct tipc_msg *m, u32 n) 311 { 312 msg_set_word(m, 10, n); 313 } 314 315 static inline struct tipc_msg *msg_get_wrapped(struct tipc_msg *m) 316 { 317 return (struct tipc_msg *)msg_data(m); 318 } 319 320 321 /* 322 TIPC internal message header format, version 2 323 324 1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0 325 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 326 w0:|vers |msg usr|hdr sz |n|resrv| packet size | 327 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 328 w1:|m typ|rsv=0| sequence gap | broadcast ack no | 329 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 330 w2:| link level ack no/bc_gap_from | seq no / bcast_gap_to | 331 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 332 w3:| previous node | 333 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 334 w4:| next sent broadcast/fragm no | next sent pkt/ fragm msg no | 335 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 336 w5:| session no |rsv=0|r|berid|link prio|netpl|p| 337 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 338 w6:| originating node | 339 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 340 w7:| destination node | 341 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 342 w8:| transport sequence number | 343 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 344 w9:| msg count / bcast tag | link tolerance | 345 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 346 \ \ 347 / User Specific Data / 348 \ \ 349 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 350 351 NB: CONN_MANAGER use data message format. LINK_CONFIG has own format. 352 */ 353 354 /* 355 * Internal users 356 */ 357 358 #define BCAST_PROTOCOL 5 359 #define MSG_BUNDLER 6 360 #define LINK_PROTOCOL 7 361 #define CONN_MANAGER 8 362 #define ROUTE_DISTRIBUTOR 9 363 #define CHANGEOVER_PROTOCOL 10 364 #define NAME_DISTRIBUTOR 11 365 #define MSG_FRAGMENTER 12 366 #define LINK_CONFIG 13 367 #define DSC_H_SIZE 40 368 369 /* 370 * Connection management protocol messages 371 */ 372 373 #define CONN_PROBE 0 374 #define CONN_PROBE_REPLY 1 375 #define CONN_ACK 2 376 377 /* 378 * Name distributor messages 379 */ 380 381 #define PUBLICATION 0 382 #define WITHDRAWAL 1 383 384 385 /* 386 * Word 1 387 */ 388 389 static inline u32 msg_seq_gap(struct tipc_msg *m) 390 { 391 return msg_bits(m, 1, 16, 0xff); 392 } 393 394 static inline void msg_set_seq_gap(struct tipc_msg *m, u32 n) 395 { 396 msg_set_bits(m, 1, 16, 0xff, n); 397 } 398 399 static inline u32 msg_req_links(struct tipc_msg *m) 400 { 401 return msg_bits(m, 1, 16, 0xfff); 402 } 403 404 static inline void msg_set_req_links(struct tipc_msg *m, u32 n) 405 { 406 msg_set_bits(m, 1, 16, 0xfff, n); 407 } 408 409 410 /* 411 * Word 2 412 */ 413 414 static inline u32 msg_dest_domain(struct tipc_msg *m) 415 { 416 return msg_word(m, 2); 417 } 418 419 static inline void msg_set_dest_domain(struct tipc_msg *m, u32 n) 420 { 421 msg_set_word(m, 2, n); 422 } 423 424 static inline u32 msg_bcgap_after(struct tipc_msg *m) 425 { 426 return msg_bits(m, 2, 16, 0xffff); 427 } 428 429 static inline void msg_set_bcgap_after(struct tipc_msg *m, u32 n) 430 { 431 msg_set_bits(m, 2, 16, 0xffff, n); 432 } 433 434 static inline u32 msg_bcgap_to(struct tipc_msg *m) 435 { 436 return msg_bits(m, 2, 0, 0xffff); 437 } 438 439 static inline void msg_set_bcgap_to(struct tipc_msg *m, u32 n) 440 { 441 msg_set_bits(m, 2, 0, 0xffff, n); 442 } 443 444 445 /* 446 * Word 4 447 */ 448 449 static inline u32 msg_last_bcast(struct tipc_msg *m) 450 { 451 return msg_bits(m, 4, 16, 0xffff); 452 } 453 454 static inline void msg_set_last_bcast(struct tipc_msg *m, u32 n) 455 { 456 msg_set_bits(m, 4, 16, 0xffff, n); 457 } 458 459 460 static inline u32 msg_fragm_no(struct tipc_msg *m) 461 { 462 return msg_bits(m, 4, 16, 0xffff); 463 } 464 465 static inline void msg_set_fragm_no(struct tipc_msg *m, u32 n) 466 { 467 msg_set_bits(m, 4, 16, 0xffff, n); 468 } 469 470 471 static inline u32 msg_next_sent(struct tipc_msg *m) 472 { 473 return msg_bits(m, 4, 0, 0xffff); 474 } 475 476 static inline void msg_set_next_sent(struct tipc_msg *m, u32 n) 477 { 478 msg_set_bits(m, 4, 0, 0xffff, n); 479 } 480 481 482 static inline u32 msg_long_msgno(struct tipc_msg *m) 483 { 484 return msg_bits(m, 4, 0, 0xffff); 485 } 486 487 static inline void msg_set_long_msgno(struct tipc_msg *m, u32 n) 488 { 489 msg_set_bits(m, 4, 0, 0xffff, n); 490 } 491 492 static inline u32 msg_bc_netid(struct tipc_msg *m) 493 { 494 return msg_word(m, 4); 495 } 496 497 static inline void msg_set_bc_netid(struct tipc_msg *m, u32 id) 498 { 499 msg_set_word(m, 4, id); 500 } 501 502 static inline u32 msg_link_selector(struct tipc_msg *m) 503 { 504 return msg_bits(m, 4, 0, 1); 505 } 506 507 static inline void msg_set_link_selector(struct tipc_msg *m, u32 n) 508 { 509 msg_set_bits(m, 4, 0, 1, (n & 1)); 510 } 511 512 /* 513 * Word 5 514 */ 515 516 static inline u32 msg_session(struct tipc_msg *m) 517 { 518 return msg_bits(m, 5, 16, 0xffff); 519 } 520 521 static inline void msg_set_session(struct tipc_msg *m, u32 n) 522 { 523 msg_set_bits(m, 5, 16, 0xffff, n); 524 } 525 526 static inline u32 msg_probe(struct tipc_msg *m) 527 { 528 return msg_bits(m, 5, 0, 1); 529 } 530 531 static inline void msg_set_probe(struct tipc_msg *m, u32 val) 532 { 533 msg_set_bits(m, 5, 0, 1, (val & 1)); 534 } 535 536 static inline char msg_net_plane(struct tipc_msg *m) 537 { 538 return msg_bits(m, 5, 1, 7) + 'A'; 539 } 540 541 static inline void msg_set_net_plane(struct tipc_msg *m, char n) 542 { 543 msg_set_bits(m, 5, 1, 7, (n - 'A')); 544 } 545 546 static inline u32 msg_linkprio(struct tipc_msg *m) 547 { 548 return msg_bits(m, 5, 4, 0x1f); 549 } 550 551 static inline void msg_set_linkprio(struct tipc_msg *m, u32 n) 552 { 553 msg_set_bits(m, 5, 4, 0x1f, n); 554 } 555 556 static inline u32 msg_bearer_id(struct tipc_msg *m) 557 { 558 return msg_bits(m, 5, 9, 0x7); 559 } 560 561 static inline void msg_set_bearer_id(struct tipc_msg *m, u32 n) 562 { 563 msg_set_bits(m, 5, 9, 0x7, n); 564 } 565 566 static inline u32 msg_redundant_link(struct tipc_msg *m) 567 { 568 return msg_bits(m, 5, 12, 0x1); 569 } 570 571 static inline void msg_set_redundant_link(struct tipc_msg *m) 572 { 573 msg_set_bits(m, 5, 12, 0x1, 1); 574 } 575 576 static inline void msg_clear_redundant_link(struct tipc_msg *m) 577 { 578 msg_set_bits(m, 5, 12, 0x1, 0); 579 } 580 581 582 /* 583 * Word 9 584 */ 585 586 static inline u32 msg_msgcnt(struct tipc_msg *m) 587 { 588 return msg_bits(m, 9, 16, 0xffff); 589 } 590 591 static inline void msg_set_msgcnt(struct tipc_msg *m, u32 n) 592 { 593 msg_set_bits(m, 9, 16, 0xffff, n); 594 } 595 596 static inline u32 msg_bcast_tag(struct tipc_msg *m) 597 { 598 return msg_bits(m, 9, 16, 0xffff); 599 } 600 601 static inline void msg_set_bcast_tag(struct tipc_msg *m, u32 n) 602 { 603 msg_set_bits(m, 9, 16, 0xffff, n); 604 } 605 606 static inline u32 msg_max_pkt(struct tipc_msg *m) 607 { 608 return (msg_bits(m, 9, 16, 0xffff) * 4); 609 } 610 611 static inline void msg_set_max_pkt(struct tipc_msg *m, u32 n) 612 { 613 msg_set_bits(m, 9, 16, 0xffff, (n / 4)); 614 } 615 616 static inline u32 msg_link_tolerance(struct tipc_msg *m) 617 { 618 return msg_bits(m, 9, 0, 0xffff); 619 } 620 621 static inline void msg_set_link_tolerance(struct tipc_msg *m, u32 n) 622 { 623 msg_set_bits(m, 9, 0, 0xffff, n); 624 } 625 626 /* 627 * Routing table message data 628 */ 629 630 631 static inline u32 msg_remote_node(struct tipc_msg *m) 632 { 633 return msg_word(m, msg_hdr_sz(m)/4); 634 } 635 636 static inline void msg_set_remote_node(struct tipc_msg *m, u32 a) 637 { 638 msg_set_word(m, msg_hdr_sz(m)/4, a); 639 } 640 641 static inline void msg_set_dataoctet(struct tipc_msg *m, u32 pos) 642 { 643 msg_data(m)[pos + 4] = 1; 644 } 645 646 /* 647 * Segmentation message types 648 */ 649 650 #define FIRST_FRAGMENT 0 651 #define FRAGMENT 1 652 #define LAST_FRAGMENT 2 653 654 /* 655 * Link management protocol message types 656 */ 657 658 #define STATE_MSG 0 659 #define RESET_MSG 1 660 #define ACTIVATE_MSG 2 661 662 /* 663 * Changeover tunnel message types 664 */ 665 #define DUPLICATE_MSG 0 666 #define ORIGINAL_MSG 1 667 668 /* 669 * Routing table message types 670 */ 671 #define EXT_ROUTING_TABLE 0 672 #define LOCAL_ROUTING_TABLE 1 673 #define SLAVE_ROUTING_TABLE 2 674 #define ROUTE_ADDITION 3 675 #define ROUTE_REMOVAL 4 676 677 /* 678 * Config protocol message types 679 */ 680 681 #define DSC_REQ_MSG 0 682 #define DSC_RESP_MSG 1 683 684 static inline u32 msg_tot_importance(struct tipc_msg *m) 685 { 686 if (likely(msg_isdata(m))) { 687 if (likely(msg_orignode(m) == tipc_own_addr)) 688 return msg_importance(m); 689 return msg_importance(m) + 4; 690 } 691 if ((msg_user(m) == MSG_FRAGMENTER) && 692 (msg_type(m) == FIRST_FRAGMENT)) 693 return msg_importance(msg_get_wrapped(m)); 694 return msg_importance(m); 695 } 696 697 698 static inline void msg_init(struct tipc_msg *m, u32 user, u32 type, 699 u32 err, u32 hsize, u32 destnode) 700 { 701 memset(m, 0, hsize); 702 msg_set_version(m); 703 msg_set_user(m, user); 704 msg_set_hdr_sz(m, hsize); 705 msg_set_size(m, hsize); 706 msg_set_prevnode(m, tipc_own_addr); 707 msg_set_type(m, type); 708 msg_set_errcode(m, err); 709 if (!msg_short(m)) { 710 msg_set_orignode(m, tipc_own_addr); 711 msg_set_destnode(m, destnode); 712 } 713 } 714 715 /** 716 * msg_calc_data_size - determine total data size for message 717 */ 718 719 static inline int msg_calc_data_size(struct iovec const *msg_sect, u32 num_sect) 720 { 721 int dsz = 0; 722 int i; 723 724 for (i = 0; i < num_sect; i++) 725 dsz += msg_sect[i].iov_len; 726 return dsz; 727 } 728 729 /** 730 * msg_build - create message using specified header and data 731 * 732 * Note: Caller must not hold any locks in case copy_from_user() is interrupted! 733 * 734 * Returns message data size or errno 735 */ 736 737 static inline int msg_build(struct tipc_msg *hdr, 738 struct iovec const *msg_sect, u32 num_sect, 739 int max_size, int usrmem, struct sk_buff** buf) 740 { 741 int dsz, sz, hsz, pos, res, cnt; 742 743 dsz = msg_calc_data_size(msg_sect, num_sect); 744 if (unlikely(dsz > TIPC_MAX_USER_MSG_SIZE)) { 745 *buf = NULL; 746 return -EINVAL; 747 } 748 749 pos = hsz = msg_hdr_sz(hdr); 750 sz = hsz + dsz; 751 msg_set_size(hdr, sz); 752 if (unlikely(sz > max_size)) { 753 *buf = NULL; 754 return dsz; 755 } 756 757 *buf = buf_acquire(sz); 758 if (!(*buf)) 759 return -ENOMEM; 760 skb_copy_to_linear_data(*buf, hdr, hsz); 761 for (res = 1, cnt = 0; res && (cnt < num_sect); cnt++) { 762 if (likely(usrmem)) 763 res = !copy_from_user((*buf)->data + pos, 764 msg_sect[cnt].iov_base, 765 msg_sect[cnt].iov_len); 766 else 767 skb_copy_to_linear_data_offset(*buf, pos, 768 msg_sect[cnt].iov_base, 769 msg_sect[cnt].iov_len); 770 pos += msg_sect[cnt].iov_len; 771 } 772 if (likely(res)) 773 return dsz; 774 775 buf_discard(*buf); 776 *buf = NULL; 777 return -EFAULT; 778 } 779 780 static inline void msg_set_media_addr(struct tipc_msg *m, struct tipc_media_addr *a) 781 { 782 memcpy(&((int *)m)[5], a, sizeof(*a)); 783 } 784 785 static inline void msg_get_media_addr(struct tipc_msg *m, struct tipc_media_addr *a) 786 { 787 memcpy(a, &((int*)m)[5], sizeof(*a)); 788 } 789 790 #endif 791