midcomms.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /******************************************************************************
  3. *******************************************************************************
  4. **
  5. ** Copyright (C) Sistina Software, Inc. 1997-2003 All rights reserved.
  6. ** Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
  7. **
  8. **
  9. *******************************************************************************
  10. ******************************************************************************/
  11. /*
  12. * midcomms.c
  13. *
  14. * This is the appallingly named "mid-level" comms layer.
  15. *
  16. * Its purpose is to take packets from the "real" comms layer,
  17. * split them up into packets and pass them to the interested
  18. * part of the locking mechanism.
  19. *
  20. * It also takes messages from the locking layer, formats them
  21. * into packets and sends them to the comms layer.
  22. */
  23. #include <asm/unaligned.h>
  24. #include "dlm_internal.h"
  25. #include "lowcomms.h"
  26. #include "config.h"
  27. #include "lock.h"
  28. #include "midcomms.h"
  29. /*
  30. * Called from the low-level comms layer to process a buffer of
  31. * commands.
  32. */
  33. int dlm_process_incoming_buffer(int nodeid, unsigned char *buf, int len)
  34. {
  35. const unsigned char *ptr = buf;
  36. const struct dlm_header *hd;
  37. uint16_t msglen;
  38. int ret = 0;
  39. while (len >= sizeof(struct dlm_header)) {
  40. hd = (struct dlm_header *)ptr;
  41. /* no message should be more than this otherwise we
  42. * cannot deliver this message to upper layers
  43. */
  44. msglen = get_unaligned_le16(&hd->h_length);
  45. if (msglen > DEFAULT_BUFFER_SIZE ||
  46. msglen < sizeof(struct dlm_header)) {
  47. log_print("received invalid length header: %u from node %d, will abort message parsing",
  48. msglen, nodeid);
  49. return -EBADMSG;
  50. }
  51. /* caller will take care that leftover
  52. * will be parsed next call with more data
  53. */
  54. if (msglen > len)
  55. break;
  56. switch (hd->h_cmd) {
  57. case DLM_MSG:
  58. if (msglen < sizeof(struct dlm_message)) {
  59. log_print("dlm msg too small: %u, will skip this message",
  60. msglen);
  61. goto skip;
  62. }
  63. break;
  64. case DLM_RCOM:
  65. if (msglen < sizeof(struct dlm_rcom)) {
  66. log_print("dlm rcom msg too small: %u, will skip this message",
  67. msglen);
  68. goto skip;
  69. }
  70. break;
  71. default:
  72. log_print("unsupported h_cmd received: %u, will skip this message",
  73. hd->h_cmd);
  74. goto skip;
  75. }
  76. /* for aligned memory access, we just copy current message
  77. * to begin of the buffer which contains already parsed buffer
  78. * data and should provide align access for upper layers
  79. * because the start address of the buffer has a aligned
  80. * address. This memmove can be removed when the upperlayer
  81. * is capable of unaligned memory access.
  82. */
  83. memmove(buf, ptr, msglen);
  84. dlm_receive_buffer((union dlm_packet *)buf, nodeid);
  85. skip:
  86. ret += msglen;
  87. len -= msglen;
  88. ptr += msglen;
  89. }
  90. return ret;
  91. }