• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
dlm_process_incoming_buffer(int nodeid,unsigned char * buf,int len)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 		    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 
98 skip:
99 		ret += msglen;
100 		len -= msglen;
101 		ptr += msglen;
102 	}
103 
104 	return ret;
105 }
106 
107