blob: 31b33df539326f5210337abe2f6021892b97390e [file] [log] [blame]
Dave Barach371e4e12016-07-08 09:38:52 -04001/*
Ed Warnickecb9cada2015-12-08 15:45:58 -07002 *------------------------------------------------------------------
3 * socksvr_vlib.c
4 *
5 * Copyright (c) 2009 Cisco and/or its affiliates.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at:
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *------------------------------------------------------------------
18 */
19
Dave Barach371e4e12016-07-08 09:38:52 -040020#include <sys/types.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070021#include <sys/socket.h>
22#include <netinet/in.h>
23#include <sys/ioctl.h>
24#include <vppinfra/byte_order.h>
25
26#include <fcntl.h>
27#include <sys/stat.h>
28
29#include <vlibsocket/api.h>
30#include <vlibmemory/api.h>
31
Dave Barach371e4e12016-07-08 09:38:52 -040032#include <vlibsocket/vl_socket_msg_enum.h> /* enumerate all vlib messages */
Ed Warnickecb9cada2015-12-08 15:45:58 -070033
Dave Barach371e4e12016-07-08 09:38:52 -040034#define vl_typedefs /* define message structures */
35#include <vlibsocket/vl_socket_api_h.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070036#undef vl_typedefs
37
38/* instantiate all the print functions we know about */
39#define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
40#define vl_printfun
Dave Barach371e4e12016-07-08 09:38:52 -040041#include <vlibsocket/vl_socket_api_h.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070042#undef vl_printfun
43
44/* instantiate all the endian swap functions we know about */
45#define vl_endianfun
Dave Barach371e4e12016-07-08 09:38:52 -040046#include <vlibsocket/vl_socket_api_h.h>
Ed Warnickecb9cada2015-12-08 15:45:58 -070047#undef vl_endianfun
48
49socket_main_t socket_main;
50
Dave Barach371e4e12016-07-08 09:38:52 -040051void
52dump_socket_clients (vlib_main_t * vm, api_main_t * am)
Ed Warnickecb9cada2015-12-08 15:45:58 -070053{
Dave Barach371e4e12016-07-08 09:38:52 -040054 vl_api_registration_t *reg;
55 socket_main_t *sm = &socket_main;
Damjan Marion56dd5432017-09-08 19:52:02 +020056 clib_file_main_t *fm = &file_main;
57 clib_file_t *f;
Ed Warnickecb9cada2015-12-08 15:45:58 -070058
Dave Barach371e4e12016-07-08 09:38:52 -040059 /*
60 * Must have at least one active client, not counting the
61 * REGISTRATION_TYPE_SOCKET_LISTEN bind/accept socket
62 */
63 if (pool_elts (sm->registration_pool) < 2)
64 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -070065
Dave Barach371e4e12016-07-08 09:38:52 -040066 vlib_cli_output (vm, "TCP socket clients");
67 vlib_cli_output (vm, "%16s %8s", "Name", "Fildesc");
68 /* *INDENT-OFF* */
69 pool_foreach (reg, sm->registration_pool,
Ed Warnickecb9cada2015-12-08 15:45:58 -070070 ({
71 if (reg->registration_type == REGISTRATION_TYPE_SOCKET_SERVER) {
Damjan Marion56dd5432017-09-08 19:52:02 +020072 f = pool_elt_at_index (fm->file_pool, reg->clib_file_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -070073 vlib_cli_output (vm, "%16s %8d",
74 reg->name, f->file_descriptor);
75 }
76 }));
Dave Barach371e4e12016-07-08 09:38:52 -040077/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -070078}
79
Dave Barach371e4e12016-07-08 09:38:52 -040080void
81vl_socket_api_send (vl_api_registration_t * rp, u8 * elem)
Ed Warnickecb9cada2015-12-08 15:45:58 -070082{
Dave Barach371e4e12016-07-08 09:38:52 -040083 u32 nbytes = 4; /* for the length... */
84 u16 msg_id = ntohs (*(u16 *) elem);
85 u32 msg_length;
86 u32 tmp;
87 api_main_t *am = &api_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -070088
Dave Barach371e4e12016-07-08 09:38:52 -040089 ASSERT (rp->registration_type > REGISTRATION_TYPE_SHMEM);
Ed Warnickecb9cada2015-12-08 15:45:58 -070090
Dave Barach371e4e12016-07-08 09:38:52 -040091 if (msg_id >= vec_len (am->api_trace_cfg))
92 {
93 clib_warning ("id out of range: %d", msg_id);
94 vl_msg_api_free ((void *) elem);
95 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -070096 }
97
Dave Barach371e4e12016-07-08 09:38:52 -040098 msg_length = am->api_trace_cfg[msg_id].size;
99 nbytes += msg_length;
100 tmp = clib_host_to_net_u32 (nbytes);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700101
Damjan Marion56dd5432017-09-08 19:52:02 +0200102 vl_socket_add_pending_output (rp->clib_file_index
103 + file_main.file_pool,
Dave Barach371e4e12016-07-08 09:38:52 -0400104 rp->vl_api_registration_pool_index
105 + socket_main.registration_pool,
106 (u8 *) & tmp, sizeof (tmp));
Damjan Marion56dd5432017-09-08 19:52:02 +0200107 vl_socket_add_pending_output (rp->clib_file_index
108 + file_main.file_pool,
Dave Barach371e4e12016-07-08 09:38:52 -0400109 rp->vl_api_registration_pool_index
110 + socket_main.registration_pool,
111 elem, msg_length);
112 vl_msg_api_free ((void *) elem);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700113}
114
Dave Barach371e4e12016-07-08 09:38:52 -0400115void
116vl_socket_api_send_with_data (vl_api_registration_t * rp,
117 u8 * elem, u8 * data_vector)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700118{
Dave Barach371e4e12016-07-08 09:38:52 -0400119 u32 nbytes = 4; /* for the length... */
120 u16 msg_id = ntohs (*(u16 *) elem);
121 u32 msg_length;
122 u32 tmp;
123 api_main_t *am = &api_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700124
Dave Barach371e4e12016-07-08 09:38:52 -0400125 ASSERT (rp->registration_type > REGISTRATION_TYPE_SHMEM);
126
127 if (msg_id >= vec_len (am->api_trace_cfg))
128 {
129 clib_warning ("id out of range: %d", msg_id);
130 vec_free (data_vector);
131 vl_msg_api_free ((void *) elem);
132 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700133 }
134
Dave Barach371e4e12016-07-08 09:38:52 -0400135 msg_length = am->api_trace_cfg[msg_id].size;
136 nbytes += msg_length;
137 nbytes += vec_len (data_vector);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700138
Dave Barach371e4e12016-07-08 09:38:52 -0400139 /* Length in network byte order */
140 tmp = clib_host_to_net_u32 (nbytes);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700141
Damjan Marion56dd5432017-09-08 19:52:02 +0200142 vl_socket_add_pending_output (rp->clib_file_index
143 + file_main.file_pool,
Dave Barach371e4e12016-07-08 09:38:52 -0400144 rp->vl_api_registration_pool_index
145 + socket_main.registration_pool,
146 (u8 *) & tmp, sizeof (tmp));
Damjan Marion56dd5432017-09-08 19:52:02 +0200147 vl_socket_add_pending_output (rp->clib_file_index
148 + file_main.file_pool,
Dave Barach371e4e12016-07-08 09:38:52 -0400149 rp->vl_api_registration_pool_index
150 + socket_main.registration_pool,
151 elem, msg_length);
Damjan Marion56dd5432017-09-08 19:52:02 +0200152 vl_socket_add_pending_output (rp->clib_file_index
153 + file_main.file_pool,
Dave Barach371e4e12016-07-08 09:38:52 -0400154 rp->vl_api_registration_pool_index
155 + socket_main.registration_pool,
156 data_vector, vec_len (data_vector));
157 vl_msg_api_free ((void *) elem);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700158}
159
160static inline void
Dave Barach371e4e12016-07-08 09:38:52 -0400161vl_socket_api_send_with_length_internal (vl_api_registration_t * rp,
162 u8 * elem, u32 msg_length, int free)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700163{
Dave Barach371e4e12016-07-08 09:38:52 -0400164 u32 nbytes = 4; /* for the length... */
165 u16 msg_id = ntohs (*(u16 *) elem);
166 u32 tmp;
167 api_main_t *am = &api_main;
168
169 ASSERT (rp->registration_type > REGISTRATION_TYPE_SHMEM);
170
171 if (msg_id >= vec_len (am->api_trace_cfg))
172 {
173 clib_warning ("id out of range: %d", msg_id);
174 if (free)
175 vl_msg_api_free ((void *) elem);
176 return;
177 }
178
179 nbytes += msg_length;
180
181 /* Length in network byte order */
182 tmp = clib_host_to_net_u32 (nbytes);
183
Damjan Marion56dd5432017-09-08 19:52:02 +0200184 vl_socket_add_pending_output (rp->clib_file_index
185 + file_main.file_pool,
Dave Barach371e4e12016-07-08 09:38:52 -0400186 rp->vl_api_registration_pool_index
187 + socket_main.registration_pool,
188 (u8 *) & tmp, sizeof (tmp));
Damjan Marion56dd5432017-09-08 19:52:02 +0200189 vl_socket_add_pending_output (rp->clib_file_index
190 + file_main.file_pool,
Dave Barach371e4e12016-07-08 09:38:52 -0400191 rp->vl_api_registration_pool_index
192 + socket_main.registration_pool,
193 elem, msg_length);
194 if (free)
195 vl_msg_api_free ((void *) elem);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700196}
197
Dave Barach371e4e12016-07-08 09:38:52 -0400198void
199vl_socket_api_send_with_length (vl_api_registration_t * rp,
200 u8 * elem, u32 msg_length)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700201{
Dave Barach371e4e12016-07-08 09:38:52 -0400202 vl_socket_api_send_with_length_internal (rp, elem, msg_length,
203 1 /* free */ );
204}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700205
Dave Barach371e4e12016-07-08 09:38:52 -0400206void
207vl_socket_api_send_with_length_no_free (vl_api_registration_t * rp,
208 u8 * elem, u32 msg_length)
209{
210 vl_socket_api_send_with_length_internal (rp, elem, msg_length,
211 0 /* free */ );
212}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700213
Dave Barach371e4e12016-07-08 09:38:52 -0400214void
215vl_free_socket_registration_index (u32 pool_index)
216{
217 vl_api_registration_t *rp;
218 if (pool_is_free_index (socket_main.registration_pool, pool_index))
219 {
220 clib_warning ("main pool index %d already free", pool_index);
221 return;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700222 }
Dave Barach371e4e12016-07-08 09:38:52 -0400223 rp = pool_elt_at_index (socket_main.registration_pool, pool_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700224
Dave Barach371e4e12016-07-08 09:38:52 -0400225 ASSERT (rp->registration_type != REGISTRATION_TYPE_FREE);
226 vec_free (rp->name);
227 vec_free (rp->unprocessed_input);
228 vec_free (rp->output_vector);
229 rp->registration_type = REGISTRATION_TYPE_FREE;
230 pool_put (socket_main.registration_pool, rp);
231}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700232
Dave Barach371e4e12016-07-08 09:38:52 -0400233static inline void
Damjan Marion56dd5432017-09-08 19:52:02 +0200234socket_process_msg (clib_file_t * uf, vl_api_registration_t * rp,
Dave Barach371e4e12016-07-08 09:38:52 -0400235 i8 * input_v)
236{
237 u8 *the_msg = (u8 *) (input_v + sizeof (u32));
238 socket_main.current_uf = uf;
239 socket_main.current_rp = rp;
240 vl_msg_api_socket_handler (the_msg);
241 socket_main.current_uf = 0;
242 socket_main.current_rp = 0;
243}
Ed Warnickecb9cada2015-12-08 15:45:58 -0700244
Dave Barach371e4e12016-07-08 09:38:52 -0400245clib_error_t *
Damjan Marion56dd5432017-09-08 19:52:02 +0200246vl_socket_read_ready (clib_file_t * uf)
Dave Barach371e4e12016-07-08 09:38:52 -0400247{
Damjan Marion56dd5432017-09-08 19:52:02 +0200248 clib_file_main_t *fm = &file_main;
Dave Barach371e4e12016-07-08 09:38:52 -0400249 vl_api_registration_t *rp;
250 int n;
251 i8 *msg_buffer = 0;
252 u32 msg_len;
253 u32 save_input_buffer_length = vec_len (socket_main.input_buffer);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700254
Dave Barach371e4e12016-07-08 09:38:52 -0400255 rp = pool_elt_at_index (socket_main.registration_pool, uf->private_data);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700256
Dave Barach371e4e12016-07-08 09:38:52 -0400257 n = read (uf->file_descriptor, socket_main.input_buffer,
258 vec_len (socket_main.input_buffer));
Ed Warnickecb9cada2015-12-08 15:45:58 -0700259
Dave Barach371e4e12016-07-08 09:38:52 -0400260 if (n <= 0 && errno != EAGAIN)
261 {
Damjan Marion56dd5432017-09-08 19:52:02 +0200262 clib_file_del (fm, uf);
Dave Barach371e4e12016-07-08 09:38:52 -0400263
264 if (!pool_is_free (socket_main.registration_pool, rp))
265 {
266 u32 index = rp - socket_main.registration_pool;
267 vl_free_socket_registration_index (index);
268 }
269 else
270 {
271 clib_warning ("client index %d already free?",
272 rp->vl_api_registration_pool_index);
273 }
274 return 0;
275 }
276
277 _vec_len (socket_main.input_buffer) = n;
278
279 /*
280 * Look for bugs here. This code is tricky because
281 * data read from a stream socket does honor message
282 * boundaries. In the case of a long message (>4K bytes)
283 * we have to do (at least) 2 reads, etc.
284 */
285 do
286 {
287 if (vec_len (rp->unprocessed_input))
288 {
289 vec_append (rp->unprocessed_input, socket_main.input_buffer);
290 msg_buffer = rp->unprocessed_input;
291 msg_len = rp->unprocessed_msg_length;
292 }
293 else
294 {
295 msg_buffer = socket_main.input_buffer;
296 msg_len = 0;
297 }
298
299 if (msg_len == 0)
300 {
301 /* Length may be split across two reads */
302 if (vec_len (msg_buffer) < sizeof (u32))
303 goto save_and_split;
304
305 /* total length, including msg_len itself, in network byte order */
306 msg_len = clib_net_to_host_u32 (*((u32 *) msg_buffer));
307 }
308
309 /* Happens if the client sent msg_len == 0 */
310 if (msg_len == 0)
311 {
312 clib_warning ("msg_len == 0");
313 goto turf_it;
314 }
315
316 /* We don't have the entire message yet. */
317 if (msg_len > vec_len (msg_buffer))
318 {
319 save_and_split:
320 /*
321 * if we were using the shared input buffer,
322 * save the fragment.
323 */
324 if (msg_buffer == socket_main.input_buffer)
325 {
326 ASSERT (vec_len (rp->unprocessed_input) == 0);
327 vec_validate (rp->unprocessed_input, vec_len (msg_buffer) - 1);
328 clib_memcpy (rp->unprocessed_input, msg_buffer,
329 vec_len (msg_buffer));
330 _vec_len (rp->unprocessed_input) = vec_len (msg_buffer);
331 }
332 _vec_len (socket_main.input_buffer) = save_input_buffer_length;
333 rp->unprocessed_msg_length = msg_len;
334 return 0;
335 }
336
337 socket_process_msg (uf, rp, msg_buffer);
338 if (n > msg_len)
339 vec_delete (msg_buffer, msg_len, 0);
340 else
341 _vec_len (msg_buffer) = 0;
342 n -= msg_len;
343 msg_len = 0;
344 rp->unprocessed_msg_length = 0;
345 }
346 while (n > 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700347
348turf_it:
Dave Barach371e4e12016-07-08 09:38:52 -0400349 _vec_len (socket_main.input_buffer) = save_input_buffer_length;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700350
Dave Barach371e4e12016-07-08 09:38:52 -0400351 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700352}
353
354void
Damjan Marion56dd5432017-09-08 19:52:02 +0200355vl_socket_add_pending_output (clib_file_t * uf,
Dave Barach371e4e12016-07-08 09:38:52 -0400356 vl_api_registration_t * rp,
357 u8 * buffer, uword buffer_bytes)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700358{
Damjan Marion56dd5432017-09-08 19:52:02 +0200359 clib_file_main_t *fm = &file_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700360
Dave Barach371e4e12016-07-08 09:38:52 -0400361 vec_add (rp->output_vector, buffer, buffer_bytes);
362 if (vec_len (rp->output_vector) > 0)
363 {
364 int skip_update = 0 != (uf->flags & UNIX_FILE_DATA_AVAILABLE_TO_WRITE);
365 uf->flags |= UNIX_FILE_DATA_AVAILABLE_TO_WRITE;
366 if (!skip_update)
Damjan Marion56dd5432017-09-08 19:52:02 +0200367 fm->file_update (uf, UNIX_FILE_UPDATE_MODIFY);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700368 }
369}
370
371static void
Damjan Marion56dd5432017-09-08 19:52:02 +0200372socket_del_pending_output (clib_file_t * uf,
Dave Barach371e4e12016-07-08 09:38:52 -0400373 vl_api_registration_t * rp, uword n_bytes)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700374{
Damjan Marion56dd5432017-09-08 19:52:02 +0200375 clib_file_main_t *fm = &file_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700376
Dave Barach371e4e12016-07-08 09:38:52 -0400377 vec_delete (rp->output_vector, n_bytes, 0);
378 if (vec_len (rp->output_vector) <= 0)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700379 {
Dave Barach371e4e12016-07-08 09:38:52 -0400380 int skip_update = 0 == (uf->flags & UNIX_FILE_DATA_AVAILABLE_TO_WRITE);
381 uf->flags &= ~UNIX_FILE_DATA_AVAILABLE_TO_WRITE;
382 if (!skip_update)
Damjan Marion56dd5432017-09-08 19:52:02 +0200383 fm->file_update (uf, UNIX_FILE_UPDATE_MODIFY);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700384 }
385}
386
Dave Barach371e4e12016-07-08 09:38:52 -0400387clib_error_t *
Damjan Marion56dd5432017-09-08 19:52:02 +0200388vl_socket_write_ready (clib_file_t * uf)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700389{
Damjan Marion56dd5432017-09-08 19:52:02 +0200390 clib_file_main_t *fm = &file_main;
Dave Barach371e4e12016-07-08 09:38:52 -0400391 vl_api_registration_t *rp;
392 int n;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700393
Dave Barach371e4e12016-07-08 09:38:52 -0400394 rp = pool_elt_at_index (socket_main.registration_pool, uf->private_data);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700395
Dave Barach371e4e12016-07-08 09:38:52 -0400396 /* Flush output vector. */
397 n = write (uf->file_descriptor,
398 rp->output_vector, vec_len (rp->output_vector));
399
400 if (n < 0)
401 {
Ed Warnickecb9cada2015-12-08 15:45:58 -0700402#if DEBUG > 2
Dave Barach371e4e12016-07-08 09:38:52 -0400403 clib_warning ("write error, close the file...\n");
Ed Warnickecb9cada2015-12-08 15:45:58 -0700404#endif
Damjan Marion56dd5432017-09-08 19:52:02 +0200405 clib_file_del (fm, uf);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700406
Dave Barach371e4e12016-07-08 09:38:52 -0400407 vl_free_socket_registration_index (rp - socket_main.registration_pool);
408 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700409 }
410
Dave Barach371e4e12016-07-08 09:38:52 -0400411 else if (n > 0)
412 socket_del_pending_output (uf, rp, n);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700413
Dave Barach371e4e12016-07-08 09:38:52 -0400414 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700415}
416
Dave Barach371e4e12016-07-08 09:38:52 -0400417clib_error_t *
Damjan Marion56dd5432017-09-08 19:52:02 +0200418vl_socket_error_ready (clib_file_t * uf)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700419{
Dave Barach371e4e12016-07-08 09:38:52 -0400420 vl_api_registration_t *rp;
Damjan Marion56dd5432017-09-08 19:52:02 +0200421 clib_file_main_t *fm = &file_main;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700422
Dave Barach371e4e12016-07-08 09:38:52 -0400423 rp = pool_elt_at_index (socket_main.registration_pool, uf->private_data);
Damjan Marion56dd5432017-09-08 19:52:02 +0200424 clib_file_del (fm, uf);
Dave Barach371e4e12016-07-08 09:38:52 -0400425 vl_free_socket_registration_index (rp - socket_main.registration_pool);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700426
Dave Barach371e4e12016-07-08 09:38:52 -0400427 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700428}
429
Dave Barach371e4e12016-07-08 09:38:52 -0400430void
Damjan Marion56dd5432017-09-08 19:52:02 +0200431socksvr_file_add (clib_file_main_t * fm, int fd)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700432{
Dave Barach371e4e12016-07-08 09:38:52 -0400433 vl_api_registration_t *rp;
Damjan Marion56dd5432017-09-08 19:52:02 +0200434 clib_file_t template = { 0 };
Dave Barach371e4e12016-07-08 09:38:52 -0400435
436 pool_get (socket_main.registration_pool, rp);
437 memset (rp, 0, sizeof (*rp));
438
439 template.read_function = vl_socket_read_ready;
440 template.write_function = vl_socket_write_ready;
441 template.error_function = vl_socket_error_ready;
442 template.file_descriptor = fd;
443 template.private_data = rp - socket_main.registration_pool;
444
445 rp->registration_type = REGISTRATION_TYPE_SOCKET_SERVER;
446 rp->vl_api_registration_pool_index = rp - socket_main.registration_pool;
Damjan Marion56dd5432017-09-08 19:52:02 +0200447 rp->clib_file_index = clib_file_add (fm, &template);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700448}
449
Dave Barach371e4e12016-07-08 09:38:52 -0400450static clib_error_t *
Damjan Marion56dd5432017-09-08 19:52:02 +0200451socksvr_accept_ready (clib_file_t * uf)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700452{
Damjan Marion56dd5432017-09-08 19:52:02 +0200453 clib_file_main_t *fm = &file_main;
Dave Barach371e4e12016-07-08 09:38:52 -0400454 struct sockaddr_in client_addr;
455 int client_fd;
456 int client_len;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700457
Dave Barach371e4e12016-07-08 09:38:52 -0400458 client_len = sizeof (client_addr);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700459
Dave Barach371e4e12016-07-08 09:38:52 -0400460 /*
461 * Supposedly acquires the non-blocking attrib from the
462 * server socket.
463 */
464 client_fd = accept (uf->file_descriptor,
465 (struct sockaddr *) &client_addr,
466 (socklen_t *) & client_len);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700467
Dave Barach371e4e12016-07-08 09:38:52 -0400468 if (client_fd < 0)
469 return clib_error_return_unix (0, "socksvr_accept_ready: accept");
470
Damjan Marion56dd5432017-09-08 19:52:02 +0200471 socksvr_file_add (fm, client_fd);
Dave Barach371e4e12016-07-08 09:38:52 -0400472 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700473}
474
Dave Barach371e4e12016-07-08 09:38:52 -0400475static clib_error_t *
Damjan Marion56dd5432017-09-08 19:52:02 +0200476socksvr_bogus_write (clib_file_t * uf)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700477{
Dave Barach371e4e12016-07-08 09:38:52 -0400478 clib_warning ("why am I here?");
479 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700480}
481
482/*
483 * vl_api_sockclnt_create_t_handler
484 */
Dave Barach371e4e12016-07-08 09:38:52 -0400485void
486vl_api_sockclnt_create_t_handler (vl_api_sockclnt_create_t * mp)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700487{
Dave Barach371e4e12016-07-08 09:38:52 -0400488 vl_api_registration_t *regp;
489 vl_api_sockclnt_create_reply_t *rp;
490 int rv = 1;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700491
Dave Barach371e4e12016-07-08 09:38:52 -0400492 regp = socket_main.current_rp;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700493
Dave Barach371e4e12016-07-08 09:38:52 -0400494 ASSERT (regp->registration_type == REGISTRATION_TYPE_SOCKET_SERVER);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700495
Dave Barach371e4e12016-07-08 09:38:52 -0400496 regp->name = format (0, "%s%c", mp->name, 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700497
Dave Barach371e4e12016-07-08 09:38:52 -0400498 rp = vl_msg_api_alloc (sizeof (*rp));
499 rp->_vl_msg_id = htons (VL_API_SOCKCLNT_CREATE_REPLY);
500 rp->handle = (uword) regp;
501 rp->index = (uword) regp->vl_api_registration_pool_index;
502 rp->context = mp->context;
503 rp->response = htonl (rv);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700504
Dave Barach371e4e12016-07-08 09:38:52 -0400505 vl_msg_api_send (regp, (u8 *) rp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700506}
507
508/*
509 * vl_api_sockclnt_delete_t_handler
510 */
Dave Barach371e4e12016-07-08 09:38:52 -0400511void
512vl_api_sockclnt_delete_t_handler (vl_api_sockclnt_delete_t * mp)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700513{
Dave Barach371e4e12016-07-08 09:38:52 -0400514 vl_api_registration_t *regp;
515 vl_api_sockclnt_delete_reply_t *rp;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700516
Dave Barach371e4e12016-07-08 09:38:52 -0400517 if (!pool_is_free_index (socket_main.registration_pool, mp->index))
518 {
519 regp = pool_elt_at_index (socket_main.registration_pool, mp->index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700520
Dave Barach371e4e12016-07-08 09:38:52 -0400521 rp = vl_msg_api_alloc (sizeof (*rp));
522 rp->_vl_msg_id = htons (VL_API_SOCKCLNT_DELETE_REPLY);
523 rp->handle = mp->handle;
524 rp->response = htonl (1);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700525
Dave Barach371e4e12016-07-08 09:38:52 -0400526 vl_msg_api_send (regp, (u8 *) rp);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700527
Damjan Marion56dd5432017-09-08 19:52:02 +0200528 clib_file_del (&file_main, file_main.file_pool + regp->clib_file_index);
Dave Barach371e4e12016-07-08 09:38:52 -0400529
530 vl_free_socket_registration_index (mp->index);
531 }
532 else
533 {
534 clib_warning ("unknown client ID %d", mp->index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700535 }
536}
537
538#define foreach_vlib_api_msg \
539_(SOCKCLNT_CREATE, sockclnt_create) \
Dave Barach371e4e12016-07-08 09:38:52 -0400540_(SOCKCLNT_DELETE, sockclnt_delete)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700541
Dave Barach371e4e12016-07-08 09:38:52 -0400542static clib_error_t *
543socksvr_api_init (vlib_main_t * vm)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700544{
Damjan Marion56dd5432017-09-08 19:52:02 +0200545 clib_file_main_t *fm = &file_main;
546 clib_file_t template = { 0 };
Dave Barach371e4e12016-07-08 09:38:52 -0400547 int sockfd;
548 int one = 1;
549 int rv;
550 struct sockaddr_in serv_addr;
551 vl_api_registration_t *rp;
552 u16 portno;
553 u32 bind_address;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700554
555#define _(N,n) \
556 vl_msg_api_set_handlers(VL_API_##N, #n, \
557 vl_api_##n##_t_handler, \
558 vl_noop_handler, \
559 vl_api_##n##_t_endian, \
560 vl_api_##n##_t_print, \
Dave Barach371e4e12016-07-08 09:38:52 -0400561 sizeof(vl_api_##n##_t), 1);
562 foreach_vlib_api_msg;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700563#undef _
564
Dave Barach371e4e12016-07-08 09:38:52 -0400565 vec_resize (socket_main.input_buffer, 4096);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700566
Dave Barach371e4e12016-07-08 09:38:52 -0400567 /* Set up non-blocking server socket on CLIENT_API_SERVER_PORT */
568 sockfd = socket (AF_INET, SOCK_STREAM, 0);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700569
Dave Barach371e4e12016-07-08 09:38:52 -0400570 if (sockfd < 0)
571 {
572 return clib_error_return_unix (0, "socket");
Ed Warnickecb9cada2015-12-08 15:45:58 -0700573 }
574
Dave Barach371e4e12016-07-08 09:38:52 -0400575 rv = ioctl (sockfd, FIONBIO, &one);
576 if (rv < 0)
577 {
Dave Barachf9c231e2016-08-05 10:10:18 -0400578 close (sockfd);
Dave Barach371e4e12016-07-08 09:38:52 -0400579 return clib_error_return_unix (0, "FIONBIO");
Ed Warnickecb9cada2015-12-08 15:45:58 -0700580 }
581
Dave Barach371e4e12016-07-08 09:38:52 -0400582 rv = setsockopt (sockfd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof (one));
583 if (rv < 0)
584 {
Dave Barachf9c231e2016-08-05 10:10:18 -0400585 close (sockfd);
Dave Barach371e4e12016-07-08 09:38:52 -0400586 return clib_error_return_unix (0, "SO_REUSEADDR");
Ed Warnickecb9cada2015-12-08 15:45:58 -0700587 }
588
Dave Barach371e4e12016-07-08 09:38:52 -0400589 bzero ((char *) &serv_addr, sizeof (serv_addr));
590 serv_addr.sin_family = AF_INET;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700591
Dave Barach371e4e12016-07-08 09:38:52 -0400592 if (socket_main.bind_address)
593 bind_address = socket_main.bind_address;
594 else
595 bind_address = INADDR_LOOPBACK;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700596
Dave Barach371e4e12016-07-08 09:38:52 -0400597 if (socket_main.portno)
598 portno = socket_main.portno;
599 else
600 portno = SOCKSVR_DEFAULT_PORT;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700601
Dave Barach371e4e12016-07-08 09:38:52 -0400602 serv_addr.sin_port = clib_host_to_net_u16 (portno);
603 serv_addr.sin_addr.s_addr = clib_host_to_net_u32 (bind_address);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700604
Dave Barach371e4e12016-07-08 09:38:52 -0400605 if (bind (sockfd, (struct sockaddr *) &serv_addr, sizeof (serv_addr)) < 0)
606 {
Dave Barachb2a6e252016-07-27 10:00:58 -0400607 close (sockfd);
Dave Barach371e4e12016-07-08 09:38:52 -0400608 return clib_error_return_unix (0, "bind");
Ed Warnickecb9cada2015-12-08 15:45:58 -0700609 }
610
Dave Barach371e4e12016-07-08 09:38:52 -0400611 rv = listen (sockfd, 5);
612 if (rv < 0)
613 {
Ed Warnicke853e7202016-08-12 11:42:26 -0700614 close (sockfd);
Dave Barach371e4e12016-07-08 09:38:52 -0400615 return clib_error_return_unix (0, "listen");
616 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700617
Dave Barach371e4e12016-07-08 09:38:52 -0400618 pool_get (socket_main.registration_pool, rp);
619 memset (rp, 0, sizeof (*rp));
620
621 rp->registration_type = REGISTRATION_TYPE_SOCKET_LISTEN;
622
623 template.read_function = socksvr_accept_ready;
624 template.write_function = socksvr_bogus_write;
625 template.file_descriptor = sockfd;
626 template.private_data = rp - socket_main.registration_pool;
627
Damjan Marion56dd5432017-09-08 19:52:02 +0200628 rp->clib_file_index = clib_file_add (fm, &template);
Dave Barach371e4e12016-07-08 09:38:52 -0400629 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700630}
631
632static clib_error_t *
633socket_exit (vlib_main_t * vm)
634{
Damjan Marion56dd5432017-09-08 19:52:02 +0200635 clib_file_main_t *fm = &file_main;
Dave Barach371e4e12016-07-08 09:38:52 -0400636 vl_api_registration_t *rp;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700637
Dave Barach371e4e12016-07-08 09:38:52 -0400638 /* Defensive driving in case something wipes out early */
639 if (socket_main.registration_pool)
640 {
641 u32 index;
642 /* *INDENT-OFF* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700643 pool_foreach (rp, socket_main.registration_pool, ({
Damjan Marion56dd5432017-09-08 19:52:02 +0200644 clib_file_del (fm, fm->file_pool + rp->clib_file_index);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700645 index = rp->vl_api_registration_pool_index;
646 vl_free_socket_registration_index (index);
647 }));
Dave Barach371e4e12016-07-08 09:38:52 -0400648/* *INDENT-ON* */
Ed Warnickecb9cada2015-12-08 15:45:58 -0700649 }
650
Dave Barach371e4e12016-07-08 09:38:52 -0400651 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700652}
653
654VLIB_MAIN_LOOP_EXIT_FUNCTION (socket_exit);
655
656static clib_error_t *
657socksvr_config (vlib_main_t * vm, unformat_input_t * input)
658{
Dave Barach371e4e12016-07-08 09:38:52 -0400659 int portno;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700660
Dave Barach371e4e12016-07-08 09:38:52 -0400661 while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700662 {
Dave Barach371e4e12016-07-08 09:38:52 -0400663 if (unformat (input, "port %d", &portno))
664 {
665 socket_main.portno = portno;
666 }
667 else
668 {
669 return clib_error_return (0, "unknown input '%U'",
670 format_unformat_error, input);
671 }
Ed Warnickecb9cada2015-12-08 15:45:58 -0700672 }
Dave Barach371e4e12016-07-08 09:38:52 -0400673 return socksvr_api_init (vm);
Ed Warnickecb9cada2015-12-08 15:45:58 -0700674}
675
676VLIB_CONFIG_FUNCTION (socksvr_config, "socksvr");
677
678/* argument in host byte order */
Dave Barach371e4e12016-07-08 09:38:52 -0400679void
680socksvr_set_port (u16 port)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700681{
Dave Barach371e4e12016-07-08 09:38:52 -0400682 socket_main.portno = port;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700683}
684
685/* argument in host byte order */
Dave Barach371e4e12016-07-08 09:38:52 -0400686void
687socksvr_set_bind_address (u32 bind_address)
Ed Warnickecb9cada2015-12-08 15:45:58 -0700688{
Dave Barach371e4e12016-07-08 09:38:52 -0400689 socket_main.bind_address = bind_address;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700690}
691
692clib_error_t *
693vlibsocket_init (vlib_main_t * vm)
694{
Dave Barach371e4e12016-07-08 09:38:52 -0400695 return 0;
Ed Warnickecb9cada2015-12-08 15:45:58 -0700696}
697
698VLIB_INIT_FUNCTION (vlibsocket_init);
Dave Barach371e4e12016-07-08 09:38:52 -0400699
700/*
701 * fd.io coding-style-patch-verification: ON
702 *
703 * Local Variables:
704 * eval: (c-set-style "gnu")
705 * End:
706 */