xref: /openbmc/linux/fs/dlm/midcomms.c (revision f8a11425)
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 "dlm_internal.h"
26 #include "lowcomms.h"
27 #include "config.h"
28 #include "lock.h"
29 #include "midcomms.h"
30 
31 /*
32  * Called from the low-level comms layer to process a buffer of
33  * commands.
34  */
35 
36 int dlm_process_incoming_buffer(int nodeid, unsigned char *buf, int len)
37 {
38 	const unsigned char *ptr = buf;
39 	const struct dlm_header *hd;
40 	uint16_t msglen;
41 	int ret = 0;
42 
43 	while (len >= sizeof(struct dlm_header)) {
44 		hd = (struct dlm_header *)ptr;
45 
46 		/* no message should be more than DEFAULT_BUFFER_SIZE or
47 		 * less than dlm_header size.
48 		 *
49 		 * Some messages does not have a 8 byte length boundary yet
50 		 * which can occur in a unaligned memory access of some dlm
51 		 * messages. However this problem need to be fixed at the
52 		 * sending side, for now it seems nobody run into architecture
53 		 * related issues yet but it slows down some processing.
54 		 * Fixing this issue should be scheduled in future by doing
55 		 * the next major version bump.
56 		 */
57 		msglen = le16_to_cpu(hd->h_length);
58 		if (msglen > DEFAULT_BUFFER_SIZE ||
59 		    msglen < sizeof(struct dlm_header)) {
60 			log_print("received invalid length header: %u from node %d, will abort message parsing",
61 				  msglen, nodeid);
62 			return -EBADMSG;
63 		}
64 
65 		/* caller will take care that leftover
66 		 * will be parsed next call with more data
67 		 */
68 		if (msglen > len)
69 			break;
70 
71 		switch (hd->h_cmd) {
72 		case DLM_MSG:
73 			if (msglen < sizeof(struct dlm_message)) {
74 				log_print("dlm msg too small: %u, will skip this message",
75 					  msglen);
76 				goto skip;
77 			}
78 
79 			break;
80 		case DLM_RCOM:
81 			if (msglen < sizeof(struct dlm_rcom)) {
82 				log_print("dlm rcom msg too small: %u, will skip this message",
83 					  msglen);
84 				goto skip;
85 			}
86 
87 			break;
88 		default:
89 			log_print("unsupported h_cmd received: %u, will skip this message",
90 				  hd->h_cmd);
91 			goto skip;
92 		}
93 
94 		dlm_receive_buffer((union dlm_packet *)ptr, nodeid);
95 
96 skip:
97 		ret += msglen;
98 		len -= msglen;
99 		ptr += msglen;
100 	}
101 
102 	return ret;
103 }
104 
105