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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
/* SPDX-License-Identifier: GPL-2.0 */
/** \file sideband.h exported symbols from sideband.c */
/**
* The valid sideband designators.
*
* A sideband packet consists of a header and a body. The header is sent prior
* to the data and contains the length of the buffer and the sideband
* designator, an integer. This scheme allows receivers to never read more data
* than what was specified in the header.
*
* The sideband designator indicates the type of the data. The authentication
* handshake between the server (para_server or para_audiod) and the client
* (para_client or para_audioc) requires to exchange several packages. Each
* such package is sent as a sideband package with a dedicated designator.
*
* Other designators are employed for normal command output and for log
* messages, where each loglevel corresponds to a sideband designator.
*
* Note that the values of this enum are part of the ABI, so never change
* or remove entries. Appending is OK though.
*/
#define SB_DESIGNATORS \
/* Special value for receiving only: Accept any band. */ \
DESIGNATOR(ANY), \
/* This packet contains the authentication challenge. */ \
DESIGNATOR(CHALLENGE), \
/* I solved your challenge and here is the proof. */ \
DESIGNATOR(CHALLENGE_RESPONSE), \
/* Congratulations, you are authenticated. */ \
DESIGNATOR(PROCEED), \
/* This is the command I want you to execute. */ \
DESIGNATOR(COMMAND), \
/* Ready to receive a blob (addblob commands only). */ \
DESIGNATOR(AWAITING_DATA), \
/* Normal command output (default). */ \
DESIGNATOR(OUTPUT), \
/* LL_DEBUG. */ \
DESIGNATOR(DEBUG_LOG), \
/* LL_INFO. */ \
DESIGNATOR(INFO_LOG), \
/* LL_NOTICE. */ \
DESIGNATOR(NOTICE_LOG), \
/* LL_WARNING, */ \
DESIGNATOR(WARNING_LOG), \
/* LL_ERROR. */ \
DESIGNATOR(ERROR_LOG), \
/* LL_CRIT. */ \
DESIGNATOR(CRIT_LOG), \
/* LL_EMERG. */ \
DESIGNATOR(EMERG_LOG), \
/* Command terminated successfully. */ \
DESIGNATOR(EXIT__SUCCESS), \
/* Command failed. */ \
DESIGNATOR(EXIT__FAILURE), \
/* The next chunk of the blob (addblob commands only) */ \
DESIGNATOR(BLOB_DATA), \
/* An afs callback failed. */ \
DESIGNATOR(AFS_CB_FAILURE), \
/** Just prefix with \p SBD_. */
#define DESIGNATOR(x) SBD_ ## x
/** All valid sideband designators. */
enum sb_designator {SB_DESIGNATORS NUM_SB_DESIGNATORS};
#undef DESIGNATOR
/** One stringified sideband designator. */
#define DESIGNATOR(x) #x
/** List of stringified sidedband designators. */
#define SB_DESIGNATORS_ARRAY SB_DESIGNATORS
/**
* The information contained in a sideband buffer.
*
* This structure is used for both sending and receiving data through a
* sideband channel. A pointer to a sideband buffer is passed to the sending
* side of a sideband while the receiving end yields a filled out structure
* once all data has been received.
*/
struct sb_buffer {
/** Data and length. */
struct iovec iov;
/** The band designator. */
uint8_t band;
};
static inline bool sideband_log(const char *pfx, struct sb_buffer *sbb)
{
size_t len = sbb->iov.iov_len;
char *base = sbb->iov.iov_base;
switch (sbb->band) {
case SBD_DEBUG_LOG:
case SBD_INFO_LOG:
case SBD_NOTICE_LOG:
case SBD_WARNING_LOG:
case SBD_ERROR_LOG:
case SBD_CRIT_LOG:
case SBD_EMERG_LOG:
if (len > INT_MAX)
return false;
para_log(sbb->band - SBD_DEBUG_LOG, "%s: %.*s", pfx, (int)len, base);
return true;
default:
return false;
}
}
/**
* The opaque sideband context structure.
*
* A pointer to a structure of this type is returned by the two sb_new_xxx
* functions as an opaque handle. Other public functions of the sideband
* API take such a handle as the first parameter.
*/
struct sb_context;
/**
* The type of a sideband transformation.
*
* The sideband API allows the filtering of data through an arbitrary
* transformation, which is useful for crypto purposes. The transformation may
* either transform the data in place, or return a pointer to a new buffer
* which contains the transformed source buffer. The internal sideband
* functions can tell the two types of transformations apart by checking
* whether the destination buffer coincides with the source buffer.
*
* If the transformation allocates a new buffer, it _must_ allocate one extra
* byte for NULL termination.
*/
typedef void (*sb_transformation)(struct iovec *src, struct iovec *dst,
void *trafo_context);
/** Initialize a sideband buffer. */
#define SBB_INIT(_band, _buf, _numbytes) \
{ \
.band = _band, \
.iov = { \
.iov_base = _buf, \
.iov_len = _numbytes \
} \
};
/* receiving */
struct sb_context *sb_new_recv(size_t max_size, sb_transformation t,
void *trafo_context);
void sb_get_recv_buffer(struct sb_context *c, struct iovec *iov);
int sb_received(struct sb_context *c, size_t nbytes, struct sb_buffer *result);
/* sending */
struct sb_context *sb_new_send(struct sb_buffer *sbb, bool dont_free,
sb_transformation t, void *trafo_context);
int sb_get_send_buffers(struct sb_context *c, struct iovec iov[2]);
bool sb_sent(struct sb_context *c, size_t nbytes);
void sb_free(struct sb_context *c);
|