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