hc
2024-08-16 a24a44ff9ca902811b99aa9663d697cf452e08ef
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// SPDX-License-Identifier: GPL-2.0-only
/******************************************************************************
*******************************************************************************
**
**  Copyright (C) Sistina Software, Inc.  1997-2003  All rights reserved.
**  Copyright (C) 2004-2008 Red Hat, Inc.  All rights reserved.
**
**
*******************************************************************************
******************************************************************************/
 
/*
 * midcomms.c
 *
 * This is the appallingly named "mid-level" comms layer.
 *
 * Its purpose is to take packets from the "real" comms layer,
 * split them up into packets and pass them to the interested
 * part of the locking mechanism.
 *
 * It also takes messages from the locking layer, formats them
 * into packets and sends them to the comms layer.
 */
 
#include <asm/unaligned.h>
 
#include "dlm_internal.h"
#include "lowcomms.h"
#include "config.h"
#include "lock.h"
#include "midcomms.h"
 
/*
 * Called from the low-level comms layer to process a buffer of
 * commands.
 */
 
int dlm_process_incoming_buffer(int nodeid, unsigned char *buf, int len)
{
   const unsigned char *ptr = buf;
   const struct dlm_header *hd;
   uint16_t msglen;
   int ret = 0;
 
   while (len >= sizeof(struct dlm_header)) {
       hd = (struct dlm_header *)ptr;
 
       /* no message should be more than this otherwise we
        * cannot deliver this message to upper layers
        */
       msglen = get_unaligned_le16(&hd->h_length);
       if (msglen > DEFAULT_BUFFER_SIZE ||
           msglen < sizeof(struct dlm_header)) {
           log_print("received invalid length header: %u from node %d, will abort message parsing",
                 msglen, nodeid);
           return -EBADMSG;
       }
 
       /* caller will take care that leftover
        * will be parsed next call with more data
        */
       if (msglen > len)
           break;
 
       switch (hd->h_cmd) {
       case DLM_MSG:
           if (msglen < sizeof(struct dlm_message)) {
               log_print("dlm msg too small: %u, will skip this message",
                     msglen);
               goto skip;
           }
 
           break;
       case DLM_RCOM:
           if (msglen < sizeof(struct dlm_rcom)) {
               log_print("dlm rcom msg too small: %u, will skip this message",
                     msglen);
               goto skip;
           }
 
           break;
       default:
           log_print("unsupported h_cmd received: %u, will skip this message",
                 hd->h_cmd);
           goto skip;
       }
 
       /* for aligned memory access, we just copy current message
        * to begin of the buffer which contains already parsed buffer
        * data and should provide align access for upper layers
        * because the start address of the buffer has a aligned
        * address. This memmove can be removed when the upperlayer
        * is capable of unaligned memory access.
        */
       memmove(buf, ptr, msglen);
       dlm_receive_buffer((union dlm_packet *)buf, nodeid);
 
skip:
       ret += msglen;
       len -= msglen;
       ptr += msglen;
   }
 
   return ret;
}