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 /* 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 25 #include <asm/unaligned.h> 26 27 #include "dlm_internal.h" 28 #include "lowcomms.h" 29 #include "config.h" 30 #include "lock.h" 31 #include "midcomms.h" 32 33 /* 34 * Called from the low-level comms layer to process a buffer of 35 * commands. 36 */ 37 38 int dlm_process_incoming_buffer(int nodeid, unsigned char *buf, int len) 39 { 40 const unsigned char *ptr = buf; 41 const struct dlm_header *hd; 42 uint16_t msglen; 43 int ret = 0; 44 45 while (len >= sizeof(struct dlm_header)) { 46 hd = (struct dlm_header *)ptr; 47 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; 56 } 57 58 /* caller will take care that leftover 59 * will be parsed next call with more data 60 */ 61 if (msglen > len) 62 break; 63 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 } 71 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; 85 } 86 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); 96 97 skip: 98 ret += msglen; 99 len -= msglen; 100 ptr += msglen; 101 } 102 103 return ret; 104 } 105 106