/
soccr.h
233 lines (204 loc) · 6.3 KB
/
soccr.h
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
#ifndef __LIBSOCCR_H__
#define __LIBSOCCR_H__
#include <netinet/in.h> /* sockaddr_in, sockaddr_in6 */
#include <netinet/tcp.h> /* TCP_REPAIR_WINDOW, TCP_TIMESTAMP */
#include <stdint.h> /* uint32_t */
#include <sys/socket.h> /* sockaddr */
#include "common/config.h"
/* All packets with this mark have not to be blocked. */
#define SOCCR_MARK 0xC114
#ifndef CONFIG_HAS_TCP_REPAIR_WINDOW
struct tcp_repair_window {
uint32_t snd_wl1;
uint32_t snd_wnd;
uint32_t max_window;
uint32_t rcv_wnd;
uint32_t rcv_wup;
};
#endif
#ifndef CONFIG_HAS_TCP_REPAIR
/*
* It's been reported that both tcp_repair_opt
* and TCP_ enum already shipped in netinet/tcp.h
* system header by some distros thus we need a
* test if we can use predefined ones or provide
* our own.
*/
struct tcp_repair_opt {
uint32_t opt_code;
uint32_t opt_val;
};
enum {
TCP_NO_QUEUE,
TCP_RECV_QUEUE,
TCP_SEND_QUEUE,
TCP_QUEUES_NR,
};
#endif
#ifndef TCP_TIMESTAMP
#define TCP_TIMESTAMP 24
#endif
#ifndef TCP_REPAIR_WINDOW
#define TCP_REPAIR_WINDOW 29
#endif
void libsoccr_set_log(unsigned int level, void (*fn)(unsigned int level, const char *fmt, ...));
#define SOCCR_LOG_ERR 1
#define SOCCR_LOG_DBG 2
/*
* An opaque handler for C/R-ing a TCP socket.
*/
struct libsoccr_sk;
union libsoccr_addr {
struct sockaddr sa;
struct sockaddr_in v4;
struct sockaddr_in6 v6;
};
/*
* Connection info that should be saved after fetching from the
* socket and given back into the library in two steps (see below).
*/
struct libsoccr_sk_data {
uint32_t state;
uint32_t inq_len;
uint32_t inq_seq;
uint32_t outq_len;
uint32_t outq_seq;
uint32_t unsq_len;
uint32_t opt_mask;
uint32_t mss_clamp;
uint32_t snd_wscale;
uint32_t rcv_wscale;
uint32_t timestamp;
uint32_t flags; /* SOCCR_FLAGS_... below */
uint32_t snd_wl1;
uint32_t snd_wnd;
uint32_t max_window;
uint32_t rcv_wnd;
uint32_t rcv_wup;
};
/*
* The flags below denote which data on libsoccr_sk_data was get
* from the kernel and is required for restore. Not present data
* is zeroified by the library.
*
* Ideally the caller should carry the whole _data structure between
* calls, but for optimization purposes it may analyze the flags
* field and drop the unneeded bits.
*/
/*
* Window parameters. Mark snd_wl1, snd_wnd, max_window, rcv_wnd
* and rcv_wup fields.
*/
#define SOCCR_FLAGS_WINDOW 0x1
/*
* These two calls pause and resume the socket for and after C/R
* The first one returns an opaque handle that is to be used by all
* the subsequent calls.
*
* For now the library only supports ESTABLISHED sockets. The caller
* should check the socket is supported before calling the library.
*
* Before doing socket C/R make sure no packets can reach the socket
* you're working with, nor any packet can leave the node from this
* socket. This can be done by using netfilter DROP target (of by
* DOWN-ing an interface in case of containers).
*/
struct libsoccr_sk *libsoccr_pause(int fd);
void libsoccr_resume(struct libsoccr_sk *sk);
/* This one is like _resume, but doesn't turn repair off on socket. */
void libsoccr_release(struct libsoccr_sk *sk);
/*
* Flags for calls below
*/
/*
* Memory given to or taken from library is in exclusive ownership
* of the resulting owner. I.e. -- when taken by caller from library,
* the former will free() one, when given to the library, the latter
* is to free() it.
*/
#define SOCCR_MEM_EXCL 0x1
/*
* CHECKPOINTING calls
*
* Roughly the checkpoint steps for sockets in supported states are
*
* h = libsoccr_pause(sk);
* libsoccr_save(h, &data, sizeof(data))
* inq = libsoccr_get_queue_bytes(h, TCP_RECV_QUEUE, 0)
* outq = libsoccr_get_queue_bytes(h, TCP_SEND_QUEUE, 0)
* getsocname(sk, &name, ...)
* getpeername(sk, &peer, ...)
*
* save_all_bytes(h, inq, outq, name, peer)
*
* Resuming the socket afterwards effectively obsoletes the saved
* info, as the connection resumes and old saved bytes become
* outdated.
*
* Please note, that getsocname() and getpeername() are standard glibc
* calls, not the libsoccr's ones.
*/
/*
* Fills in the libsoccr_sk_data structure with connection info. The
* data_size shows the size of a buffer. The returned value is the
* amount of bytes put into data (the rest is zeroed with memcpy).
*/
int libsoccr_save(struct libsoccr_sk *sk, struct libsoccr_sk_data *data, unsigned data_size);
/*
* Get a pointer on the contents of queues. The amount of bytes is
* determined from the filled libsoccr_sk_data by queue_id.
*
* For TCP_RECV_QUEUE the length is .inq_len
* For TCP_SEND_QUEUE the length is .outq_len
*
* For any other queues returns NULL.
*
* The steal argument means that the caller grabs the buffer from
* library and should free() it himself. Otherwise the buffer can
* be claimed again and will be free by library upon _resume call.
*/
char *libsoccr_get_queue_bytes(struct libsoccr_sk *sk, int queue_id, unsigned flags);
/*
* Returns filled libsoccr_addr for a socket. This value is also required
* on restore, but addresses may be obtained from somewhere else, these
* are just common sockaddr-s.
*/
union libsoccr_addr *libsoccr_get_addr(struct libsoccr_sk *sk, int self, unsigned flags);
/*
* RESTORING calls
*
* The restoring of a socket is like below
*
* get_all_bytes(h, inq, outq, name, peer)
*
* sk = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
*
* h = libsoccr_pause(sk)
* libsoccr_set_queue_bytes(h, TCP_SEND_QUEUE, outq);
* libsoccr_set_queue_bytes(h, TCP_RECV_QUEUE, inq);
* libsoccr_set_addr(h, 1, src_addr);
* libsoccr_set_addr(h, 0, dst_addr);
* libsoccr_restore(h, &data, sizeof(data))
*
* libsoccr_resume(h)
*
* Only after this the packets path from and to the socket can be
* enabled back.
*/
/*
* Set a pointer on the send/recv queue data.
* If flags have SOCCR_MEM_EXCL, the buffer is stolen by the library and is
* free()-ed after libsoccr_resume().
*/
int libsoccr_set_queue_bytes(struct libsoccr_sk *sk, int queue_id, char *bytes, unsigned flags);
/*
* Set a pointer on the libsoccr_addr for src/dst.
* If flags have SOCCR_MEM_EXCL, the buffer is stolen by the library and is
* fre()-ed after libsoccr_resume().
*/
int libsoccr_set_addr(struct libsoccr_sk *sk, int self, union libsoccr_addr *, unsigned flags);
/*
* Performs restore actions on a socket
*/
int libsoccr_restore(struct libsoccr_sk *sk, struct libsoccr_sk_data *data, unsigned data_size);
#endif