Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dtor/input
[linux-2.6-microblaze.git] / fs / dlm / midcomms.c
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