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 38int 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 msglen < sizeof(struct dlm_header)) { 54 log_print("received invalid length header: %u from node %d, will abort message parsing", 55 msglen, nodeid); 56 return -EBADMSG; 57 } 58 59 /* caller will take care that leftover 60 * will be parsed next call with more data 61 */ 62 if (msglen > len) 63 break; 64 65 switch (hd->h_cmd) { 66 case DLM_MSG: 67 if (msglen < sizeof(struct dlm_message)) { 68 log_print("dlm msg too small: %u, will skip this message", 69 msglen); 70 goto skip; 71 } 72 73 break; 74 case DLM_RCOM: 75 if (msglen < sizeof(struct dlm_rcom)) { 76 log_print("dlm rcom msg too small: %u, will skip this message", 77 msglen); 78 goto skip; 79 } 80 81 break; 82 default: 83 log_print("unsupported h_cmd received: %u, will skip this message", 84 hd->h_cmd); 85 goto skip; 86 } 87 88 /* for aligned memory access, we just copy current message 89 * to begin of the buffer which contains already parsed buffer 90 * data and should provide align access for upper layers 91 * because the start address of the buffer has a aligned 92 * address. This memmove can be removed when the upperlayer 93 * is capable of unaligned memory access. 94 */ 95 memmove(buf, ptr, msglen); 96 dlm_receive_buffer((union dlm_packet *)buf, nodeid); 97 98skip: 99 ret += msglen; 100 len -= msglen; 101 ptr += msglen; 102 } 103 104 return ret; 105} 106 107