LD_PRELOAD: stateless LDP
[vpp.git] / src / vcl / vcom.c
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include <unistd.h>
16 #include <stdio.h>
17 #include <signal.h>
18 #include <dlfcn.h>
19 #include <pthread.h>
20 #include <time.h>
21 #include <stdarg.h>
22 #include <sys/resource.h>
23 #include <netinet/tcp.h>
24
25 #include <vcl/vcom_socket_wrapper.h>
26 #include <vcl/vcom.h>
27 #include <sys/time.h>
28
29 #include <vcl/vppcom.h>
30 #include <vppinfra/time.h>
31 #include <vppinfra/bitmap.h>
32
33 #define HAVE_CONSTRUCTOR_ATTRIBUTE
34 #ifdef HAVE_CONSTRUCTOR_ATTRIBUTE
35 #define CONSTRUCTOR_ATTRIBUTE                       \
36     __attribute__ ((constructor))
37 #else
38 #define CONSTRUCTOR_ATTRIBUTE
39 #endif /* HAVE_CONSTRUCTOR_ATTRIBUTE */
40
41 #define HAVE_DESTRUCTOR_ATTRIBUTE
42 #ifdef HAVE_DESTRUCTOR_ATTRIBUTE
43 #define DESTRUCTOR_ATTRIBUTE                        \
44     __attribute__ ((destructor))
45 #else
46 #define DESTRUCTOR_ATTRIBUTE
47 #endif
48
49 typedef struct
50 {
51   int init;
52   char app_name[VCOM_APP_NAME_MAX];
53   u32 sid_bit_val;
54   u32 sid_bit_mask;
55   u32 debug;
56   u8 *io_buffer;
57   clib_time_t clib_time;
58   clib_bitmap_t *rd_bitmap;
59   clib_bitmap_t *wr_bitmap;
60   clib_bitmap_t *ex_bitmap;
61   clib_bitmap_t *sid_rd_bitmap;
62   clib_bitmap_t *sid_wr_bitmap;
63   clib_bitmap_t *sid_ex_bitmap;
64   clib_bitmap_t *libc_rd_bitmap;
65   clib_bitmap_t *libc_wr_bitmap;
66   clib_bitmap_t *libc_ex_bitmap;
67   vcl_poll_t *vcl_poll;
68   u8 select_vcl;
69   u8 epoll_wait_vcl;
70 } vcom_main_t;
71 #define VCOM_DEBUG vcom->debug
72
73 static vcom_main_t vcom_main = {
74   .sid_bit_val = (1 << VCOM_SID_BIT_MIN),
75   .sid_bit_mask = (1 << VCOM_SID_BIT_MIN) - 1,
76   .debug = VCOM_DEBUG_INIT,
77 };
78
79 static vcom_main_t *vcom = &vcom_main;
80
81 /*
82  * RETURN:  0 on success or -1 on error.
83  * */
84 static inline void
85 vcom_set_app_name (char *app_name)
86 {
87   int rv = snprintf (vcom->app_name, VCOM_APP_NAME_MAX,
88                      "vcom-%d-%s", getpid (), app_name);
89
90   if (rv >= VCOM_APP_NAME_MAX)
91     app_name[VCOM_APP_NAME_MAX - 1] = 0;
92 }
93
94 static inline char *
95 vcom_get_app_name ()
96 {
97   if (vcom->app_name[0] == '\0')
98     vcom_set_app_name ("app");
99
100   return vcom->app_name;
101 }
102
103 static inline int
104 vcom_fd_from_sid (u32 sid)
105 {
106   if (PREDICT_FALSE (sid >= vcom->sid_bit_val))
107     return -EMFILE;
108   else
109     return (sid | vcom->sid_bit_val);
110 }
111
112 static inline int
113 vcom_fd_is_sid (int fd)
114 {
115   return ((u32) fd & vcom->sid_bit_val) ? 1 : 0;
116 }
117
118 static inline u32
119 vcom_sid_from_fd (int fd)
120 {
121   return (vcom_fd_is_sid (fd) ? ((u32) fd & vcom->sid_bit_mask) :
122           INVALID_SESSION_ID);
123 }
124
125 static inline int
126 vcom_init (void)
127 {
128   int rv = 0;
129
130   if (PREDICT_FALSE (!vcom->init))
131     {
132       vcom->init = 1;
133       rv = vppcom_app_create (vcom_get_app_name ());
134       if (rv == VPPCOM_OK)
135         {
136           char *env_var_str = getenv (VCOM_ENV_DEBUG);
137           if (env_var_str)
138             {
139               u32 tmp;
140               if (sscanf (env_var_str, "%u", &tmp) != 1)
141                 clib_warning ("LDP<%d>: WARNING: Invalid VCOM debug level "
142                               "specified in the env var " VCOM_ENV_DEBUG
143                               " (%s)!", getpid (), env_var_str);
144               else
145                 {
146                   vcom->debug = tmp;
147                   clib_warning ("LDP<%d>: configured VCOM debug level (%u) "
148                                 "from the env var " VCOM_ENV_DEBUG "!",
149                                 getpid (), vcom->debug);
150                 }
151             }
152
153           env_var_str = getenv (VCOM_ENV_APP_NAME);
154           if (env_var_str)
155             {
156               vcom_set_app_name (env_var_str);
157               clib_warning ("LDP<%d>: configured VCOM app name (%s) "
158                             "from the env var " VCOM_ENV_APP_NAME "!",
159                             getpid (), vcom->app_name);
160             }
161
162           env_var_str = getenv (VCOM_ENV_SID_BIT);
163           if (env_var_str)
164             {
165               u32 sb;
166               if (sscanf (env_var_str, "%u", &sb) != 1)
167                 {
168                   clib_warning ("LDP<%d>: WARNING: Invalid VCOM sid bit "
169                                 "specified in the env var "
170                                 VCOM_ENV_SID_BIT " (%s)!"
171                                 "sid bit value %d (0x%x)",
172                                 getpid (), env_var_str,
173                                 vcom->sid_bit_val, vcom->sid_bit_val);
174                 }
175               else if (sb < VCOM_SID_BIT_MIN)
176                 {
177                   vcom->sid_bit_val = (1 << VCOM_SID_BIT_MIN);
178                   vcom->sid_bit_mask = vcom->sid_bit_val - 1;
179
180                   clib_warning ("LDP<%d>: WARNING: VCOM sid bit (%u) "
181                                 "specified in the env var "
182                                 VCOM_ENV_SID_BIT " (%s) is too small. "
183                                 "Using VCOM_SID_BIT_MIN (%d)! "
184                                 "sid bit value %d (0x%x)",
185                                 getpid (), sb, env_var_str, VCOM_SID_BIT_MIN,
186                                 vcom->sid_bit_val, vcom->sid_bit_val);
187                 }
188               else if (sb > VCOM_SID_BIT_MAX)
189                 {
190                   vcom->sid_bit_val = (1 << VCOM_SID_BIT_MAX);
191                   vcom->sid_bit_mask = vcom->sid_bit_val - 1;
192
193                   clib_warning ("LDP<%d>: WARNING: VCOM sid bit (%u) "
194                                 "specified in the env var "
195                                 VCOM_ENV_SID_BIT " (%s) is too big. "
196                                 "Using VCOM_SID_BIT_MAX (%d)! "
197                                 "sid bit value %d (0x%x)",
198                                 getpid (), sb, env_var_str, VCOM_SID_BIT_MAX,
199                                 vcom->sid_bit_val, vcom->sid_bit_val);
200                 }
201               else
202                 {
203                   vcom->sid_bit_val = (1 << sb);
204                   vcom->sid_bit_mask = vcom->sid_bit_val - 1;
205
206                   clib_warning ("LDP<%d>: configured VCOM sid bit (%u) "
207                                 "from " VCOM_ENV_SID_BIT
208                                 "!  sid bit value %d (0x%x)", getpid (),
209                                 sb, vcom->sid_bit_val, vcom->sid_bit_val);
210                 }
211             }
212
213           clib_time_init (&vcom->clib_time);
214           clib_warning ("LDP<%d>: VCOM initialization: done!", getpid ());
215         }
216       else
217         {
218           fprintf (stderr, "\nLDP<%d>: ERROR: vcom_init: vppcom_app_create()"
219                    " failed!  rv = %d (%s)\n",
220                    getpid (), rv, vppcom_retval_str (rv));
221           vcom->init = 0;
222         }
223     }
224   return rv;
225 }
226
227 int
228 close (int fd)
229 {
230   int rv;
231   const char *func_str;
232   u32 sid = vcom_sid_from_fd (fd);
233
234   if ((errno = -vcom_init ()))
235     return -1;
236
237   if (sid != INVALID_SESSION_ID)
238     {
239       int epfd;
240
241       func_str = "vppcom_session_attr[GET_LIBC_EPFD]";
242       epfd = vppcom_session_attr (sid, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
243       if (epfd > 0)
244         {
245           func_str = "libc_close";
246
247           if (VCOM_DEBUG > 0)
248             clib_warning
249               ("LDP<%d>: fd %d (0x%x): calling %s(): epfd %u (0x%x)",
250                getpid (), fd, fd, func_str, epfd, epfd);
251
252           rv = libc_close (epfd);
253           if (rv < 0)
254             {
255               u32 size = sizeof (epfd);
256               epfd = 0;
257
258               (void) vppcom_session_attr (sid, VPPCOM_ATTR_SET_LIBC_EPFD,
259                                           &epfd, &size);
260             }
261         }
262       else if (PREDICT_FALSE (epfd < 0))
263         {
264           errno = -epfd;
265           rv = -1;
266           goto done;
267         }
268
269       func_str = "vppcom_session_close";
270
271       if (VCOM_DEBUG > 0)
272         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x)",
273                       getpid (), fd, fd, func_str, sid, sid);
274
275       rv = vppcom_session_close (sid);
276       if (rv != VPPCOM_OK)
277         {
278           errno = -rv;
279           rv = -1;
280         }
281     }
282   else
283     {
284       func_str = "libc_close";
285
286       if (VCOM_DEBUG > 0)
287         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s()",
288                       getpid (), fd, fd, func_str);
289
290       rv = libc_close (fd);
291     }
292
293 done:
294   if (VCOM_DEBUG > 0)
295     {
296       if (rv < 0)
297         {
298           int errno_val = errno;
299           perror (func_str);
300           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
301                         "rv %d, errno = %d", getpid (), fd, fd,
302                         func_str, rv, errno_val);
303           errno = errno_val;
304         }
305       else
306         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
307                       getpid (), fd, fd, rv, rv);
308     }
309   return rv;
310 }
311
312 ssize_t
313 read (int fd, void *buf, size_t nbytes)
314 {
315   ssize_t size;
316   const char *func_str;
317   u32 sid = vcom_sid_from_fd (fd);
318
319   if ((errno = -vcom_init ()))
320     return -1;
321
322   if (sid != INVALID_SESSION_ID)
323     {
324       func_str = "vppcom_session_read";
325
326       if (VCOM_DEBUG > 2)
327         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
328                       "sid %u (0x%x), buf %p, nbytes %u", getpid (),
329                       fd, fd, func_str, sid, sid, buf, nbytes);
330
331       size = vppcom_session_read (sid, buf, nbytes);
332       if (size < 0)
333         {
334           errno = -size;
335           size = -1;
336         }
337     }
338   else
339     {
340       func_str = "libc_read";
341
342       if (VCOM_DEBUG > 2)
343         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
344                       "buf %p, nbytes %u", getpid (),
345                       fd, fd, func_str, buf, nbytes);
346
347       size = libc_read (fd, buf, nbytes);
348     }
349
350   if (VCOM_DEBUG > 2)
351     {
352       if (size < 0)
353         {
354           int errno_val = errno;
355           perror (func_str);
356           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
357                         "rv %d, errno = %d", getpid (), fd, fd,
358                         func_str, size, errno_val);
359           errno = errno_val;
360         }
361       else
362         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
363                       getpid (), fd, fd, size, size);
364     }
365   return size;
366 }
367
368 ssize_t
369 readv (int fd, const struct iovec * iov, int iovcnt)
370 {
371   const char *func_str;
372   ssize_t size = 0;
373   u32 sid = vcom_sid_from_fd (fd);
374   int rv, i, total = 0;
375
376   if ((errno = -vcom_init ()))
377     return -1;
378
379   if (sid != INVALID_SESSION_ID)
380     {
381       func_str = "vppcom_session_read";
382       do
383         {
384           for (i = 0; i < iovcnt; ++i)
385             {
386               if (VCOM_DEBUG > 2)
387                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s() [%d]: "
388                               "sid %u (0x%x), iov %p, iovcnt %d, total %d",
389                               getpid (), fd, fd, func_str, i, sid, sid,
390                               iov, iovcnt, total);
391
392               rv = vppcom_session_read (sid, iov[i].iov_base, iov[i].iov_len);
393               if (rv < 0)
394                 break;
395               else
396                 {
397                   total += rv;
398                   if (rv < iov[i].iov_len)
399                     {
400                       if (VCOM_DEBUG > 2)
401                         clib_warning ("LDP<%d>: fd %d (0x%x): "
402                                       "rv (%d) < iov[%d].iov_len (%d)",
403                                       getpid (), fd, fd, rv, i,
404                                       iov[i].iov_len);
405                       break;
406                     }
407                 }
408             }
409         }
410       while ((rv >= 0) && (total == 0));
411
412       if (rv < 0)
413         {
414           errno = -rv;
415           size = -1;
416         }
417       else
418         size = total;
419     }
420   else
421     {
422       func_str = "libc_readv";
423
424       if (VCOM_DEBUG > 2)
425         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
426                       "iov %p, iovcnt %d", getpid (), fd, fd, iov, iovcnt);
427
428       size = libc_readv (fd, iov, iovcnt);
429     }
430
431   if (VCOM_DEBUG > 2)
432     {
433       if (size < 0)
434         {
435           int errno_val = errno;
436           perror (func_str);
437           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
438                         "rv %d, errno = %d", getpid (), fd, fd,
439                         func_str, size, errno_val);
440           errno = errno_val;
441         }
442       else
443         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
444                       getpid (), fd, fd, size, size);
445     }
446   return size;
447 }
448
449 ssize_t
450 write (int fd, const void *buf, size_t nbytes)
451 {
452   const char *func_str;
453   ssize_t size = 0;
454   u32 sid = vcom_sid_from_fd (fd);
455
456   if ((errno = -vcom_init ()))
457     return -1;
458
459   if (sid != INVALID_SESSION_ID)
460     {
461       func_str = "vppcom_session_write";
462
463       if (VCOM_DEBUG > 2)
464         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
465                       "sid %u (0x%x), buf %p, nbytes %u", getpid (),
466                       fd, fd, func_str, sid, sid, buf, nbytes);
467
468       size = vppcom_session_write (sid, (void *) buf, nbytes);
469       if (size < 0)
470         {
471           errno = -size;
472           size = -1;
473         }
474     }
475   else
476     {
477       func_str = "libc_write";
478
479       if (VCOM_DEBUG > 2)
480         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
481                       "buf %p, nbytes %u", getpid (),
482                       fd, fd, func_str, buf, nbytes);
483
484       size = libc_write (fd, buf, nbytes);
485     }
486
487   if (VCOM_DEBUG > 2)
488     {
489       if (size < 0)
490         {
491           int errno_val = errno;
492           perror (func_str);
493           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
494                         "rv %d, errno = %d", getpid (), fd, fd,
495                         func_str, size, errno_val);
496           errno = errno_val;
497         }
498       else
499         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
500                       getpid (), fd, fd, size, size);
501     }
502   return size;
503 }
504
505 ssize_t
506 writev (int fd, const struct iovec * iov, int iovcnt)
507 {
508   const char *func_str;
509   ssize_t size = 0, total = 0;
510   u32 sid = vcom_sid_from_fd (fd);
511   int rv, i;
512
513   /*
514    * Use [f]printf() instead of clib_warning() to prevent recursion SIGSEGV.
515    */
516
517   if ((errno = -vcom_init ()))
518     return -1;
519
520   if (sid != INVALID_SESSION_ID)
521     {
522       func_str = "vppcom_session_write";
523       do
524         {
525           for (i = 0; i < iovcnt; ++i)
526             {
527               if (VCOM_DEBUG > 4)
528                 printf ("%s:%d: LDP<%d>: fd %d (0x%x): calling %s() [%d]: "
529                         "sid %u (0x%x), buf %p, nbytes %ld, total %ld",
530                         __func__, __LINE__, getpid (), fd, fd, func_str,
531                         i, sid, sid, iov[i].iov_base, iov[i].iov_len, total);
532
533               rv = vppcom_session_write (sid, iov[i].iov_base,
534                                          iov[i].iov_len);
535               if (rv < 0)
536                 break;
537               else
538                 {
539                   total += rv;
540                   if (rv < iov[i].iov_len)
541                     {
542                       if (VCOM_DEBUG > 4)
543                         printf ("%s:%d: LDP<%d>: fd %d (0x%x): "
544                                 "rv (%d) < iov[%d].iov_len (%ld)",
545                                 __func__, __LINE__, getpid (), fd, fd,
546                                 rv, i, iov[i].iov_len);
547                       break;
548                     }
549                 }
550             }
551         }
552       while ((rv >= 0) && (total == 0));
553
554       if (rv < 0)
555         {
556           errno = -rv;
557           size = -1;
558         }
559       else
560         size = total;
561     }
562   else
563     {
564       func_str = "libc_writev";
565
566       if (VCOM_DEBUG > 4)
567         printf ("%s:%d: LDP<%d>: fd %d (0x%x): calling %s(): "
568                 "iov %p, iovcnt %d\n", __func__, __LINE__, getpid (),
569                 fd, fd, func_str, iov, iovcnt);
570
571       size = libc_writev (fd, iov, iovcnt);
572     }
573
574   if (VCOM_DEBUG > 4)
575     {
576       if (size < 0)
577         {
578           int errno_val = errno;
579           perror (func_str);
580           fprintf (stderr,
581                    "%s:%d: LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
582                    "rv %ld, errno = %d\n", __func__, __LINE__, getpid (), fd,
583                    fd, func_str, size, errno_val);
584           errno = errno_val;
585         }
586       else
587         printf ("%s:%d: LDP<%d>: fd %d (0x%x): returning %ld\n",
588                 __func__, __LINE__, getpid (), fd, fd, size);
589     }
590   return size;
591 }
592
593 int
594 fcntl (int fd, int cmd, ...)
595 {
596   const char *func_str = __func__;
597   int rv = 0;
598   va_list ap;
599   u32 sid = vcom_sid_from_fd (fd);
600
601   if ((errno = -vcom_init ()))
602     return -1;
603
604   va_start (ap, cmd);
605   if (sid != INVALID_SESSION_ID)
606     {
607       int flags = va_arg (ap, int);
608       u32 size;
609
610       size = sizeof (flags);
611       rv = -EOPNOTSUPP;
612       switch (cmd)
613         {
614         case F_SETFL:
615           func_str = "vppcom_session_attr[SET_FLAGS]";
616           if (VCOM_DEBUG > 2)
617             clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
618                           "sid %u (0x%x) flags %d (0x%x), size %d",
619                           getpid (), fd, fd, func_str, sid, sid,
620                           flags, flags, size);
621
622           rv =
623             vppcom_session_attr (sid, VPPCOM_ATTR_SET_FLAGS, &flags, &size);
624           break;
625
626         case F_GETFL:
627           func_str = "vppcom_session_attr[GET_FLAGS]";
628           if (VCOM_DEBUG > 2)
629             clib_warning
630               ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), "
631                "flags %d (0x%x), size %d", getpid (), fd, fd, func_str, sid,
632                sid, flags, flags, size);
633
634           rv =
635             vppcom_session_attr (sid, VPPCOM_ATTR_GET_FLAGS, &flags, &size);
636           if (rv == VPPCOM_OK)
637             {
638               if (VCOM_DEBUG > 2)
639                 clib_warning ("LDP<%d>: fd %d (0x%x), cmd %d (F_GETFL): "
640                               "%s() returned flags %d (0x%x)",
641                               getpid (), fd, fd, cmd, func_str, flags, flags);
642               rv = flags;
643             }
644           break;
645
646         default:
647           rv = -EOPNOTSUPP;
648           break;
649         }
650       if (rv < 0)
651         {
652           errno = -rv;
653           rv = -1;
654         }
655     }
656   else
657     {
658       func_str = "libc_vfcntl";
659
660       if (VCOM_DEBUG > 2)
661         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): cmd %d",
662                       getpid (), fd, fd, func_str, cmd);
663
664       rv = libc_vfcntl (fd, cmd, ap);
665     }
666
667   va_end (ap);
668
669   if (VCOM_DEBUG > 2)
670     {
671       if (rv < 0)
672         {
673           int errno_val = errno;
674           perror (func_str);
675           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
676                         "rv %d, errno = %d", getpid (), fd, fd,
677                         func_str, rv, errno_val);
678           errno = errno_val;
679         }
680       else
681         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
682                       getpid (), fd, fd, rv, rv);
683     }
684   return rv;
685 }
686
687 int
688 ioctl (int fd, unsigned long int cmd, ...)
689 {
690   const char *func_str;
691   int rv;
692   va_list ap;
693   u32 sid = vcom_sid_from_fd (fd);
694
695   if ((errno = -vcom_init ()))
696     return -1;
697
698   va_start (ap, cmd);
699   if (sid != INVALID_SESSION_ID)
700     {
701       func_str = "vppcom_session_attr[GET_NREAD]";
702
703       switch (cmd)
704         {
705         case FIONREAD:
706           if (VCOM_DEBUG > 2)
707             clib_warning
708               ("LDP<%d>: fd %d (0x%x): calling  %s(): sid %u (0x%x)",
709                getpid (), fd, fd, func_str, sid, sid);
710
711           rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_NREAD, 0, 0);
712           break;
713
714         case FIONBIO:
715           {
716             u32 flags = va_arg (ap, int) ? O_NONBLOCK : 0;
717             u32 size = sizeof (flags);
718
719             /* TBD: When VPPCOM_ATTR_[GS]ET_FLAGS supports flags other than
720              *      non-blocking, the flags should be read here and merged
721              *      with O_NONBLOCK.
722              */
723             if (VCOM_DEBUG > 2)
724               clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
725                             "sid %u (0x%x), flags %d (0x%x), size %d",
726                             getpid (), fd, fd, func_str, sid, sid,
727                             flags, flags, size);
728
729             rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_FLAGS, &flags,
730                                       &size);
731           }
732           break;
733
734         default:
735           rv = -EOPNOTSUPP;
736           break;
737         }
738       if (rv < 0)
739         {
740           errno = -rv;
741           rv = -1;
742         }
743     }
744   else
745     {
746       func_str = "libc_vioctl";
747
748       if (VCOM_DEBUG > 2)
749         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): cmd %d",
750                       getpid (), fd, fd, func_str, cmd);
751
752       rv = libc_vioctl (fd, cmd, ap);
753     }
754
755   if (VCOM_DEBUG > 2)
756     {
757       if (rv < 0)
758         {
759           int errno_val = errno;
760           perror (func_str);
761           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
762                         "rv %d, errno = %d", getpid (), fd, fd,
763                         func_str, rv, errno_val);
764           errno = errno_val;
765         }
766       else
767         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
768                       getpid (), fd, fd, rv, rv);
769     }
770   va_end (ap);
771   return rv;
772 }
773
774 int
775 vcom_pselect (int nfds, fd_set * __restrict readfds,
776               fd_set * __restrict writefds,
777               fd_set * __restrict exceptfds,
778               const struct timespec *__restrict timeout,
779               const __sigset_t * __restrict sigmask)
780 {
781   int rv;
782   char *func_str = "##";
783   f64 time_out;
784   int fd;
785   uword sid_bits, sid_bits_set, libc_bits, libc_bits_set;
786   u32 minbits = clib_max (nfds, BITS (uword));
787   u32 sid;
788
789   if (nfds < 0)
790     {
791       errno = EINVAL;
792       return -1;
793     }
794
795   if (nfds <= vcom->sid_bit_val)
796     {
797       func_str = "libc_pselect";
798
799       if (VCOM_DEBUG > 3)
800         clib_warning
801           ("LDP<%d>: calling %s(): nfds %d, readfds %p, writefds %p, "
802            "exceptfds %p, timeout %p, sigmask %p", getpid (), func_str, nfds,
803            readfds, writefds, exceptfds, timeout, sigmask);
804
805       rv = libc_pselect (nfds, readfds, writefds, exceptfds,
806                          timeout, sigmask);
807       goto done;
808     }
809
810   if (PREDICT_FALSE (vcom->sid_bit_val > FD_SETSIZE / 2))
811     {
812       clib_warning ("LDP<%d>: ERROR: VCOM sid bit value %d (0x%x) > "
813                     "FD_SETSIZE/2 %d (0x%x)!", getpid (),
814                     vcom->sid_bit_val, vcom->sid_bit_val,
815                     FD_SETSIZE / 2, FD_SETSIZE / 2);
816       errno = EOVERFLOW;
817       return -1;
818     }
819
820   if (timeout)
821     {
822       time_out = (timeout->tv_sec == 0 && timeout->tv_nsec == 0) ?
823         (f64) 0 : (f64) timeout->tv_sec +
824         (f64) timeout->tv_nsec / (f64) 1000000000 +
825         (f64) (timeout->tv_nsec % 1000000000) / (f64) 1000000000;
826
827       /* select as fine grained sleep */
828       if (!nfds)
829         {
830           if (VCOM_DEBUG > 3)
831             clib_warning ("LDP<%d>: sleeping for %f seconds",
832                           getpid (), time_out);
833
834           time_out += clib_time_now (&vcom->clib_time);
835           while (clib_time_now (&vcom->clib_time) < time_out)
836             ;
837           return 0;
838         }
839     }
840   else if (!nfds)
841     {
842       errno = EINVAL;
843       return -1;
844     }
845   else
846     time_out = -1;
847
848   sid_bits = libc_bits = 0;
849   if (readfds)
850     {
851       clib_bitmap_validate (vcom->sid_rd_bitmap, minbits);
852       clib_bitmap_validate (vcom->libc_rd_bitmap, minbits);
853       clib_bitmap_validate (vcom->rd_bitmap, minbits);
854       clib_memcpy (vcom->rd_bitmap, readfds,
855                    vec_len (vcom->rd_bitmap) * sizeof (clib_bitmap_t));
856       FD_ZERO (readfds);
857
858       /* *INDENT-OFF* */
859       clib_bitmap_foreach (fd, vcom->rd_bitmap,
860         ({
861           sid = vcom_sid_from_fd (fd);
862           if (VCOM_DEBUG > 3)
863             clib_warning ("LDP<%d>: readfds: fd %d (0x%x), sid %u (0x%x)",
864                           getpid (), fd, fd, sid, sid);
865           if (sid == INVALID_SESSION_ID)
866             clib_bitmap_set_no_check (vcom->libc_rd_bitmap, fd, 1);
867           else
868             clib_bitmap_set_no_check (vcom->sid_rd_bitmap, sid, 1);
869         }));
870       /* *INDENT-ON* */
871
872       sid_bits_set = clib_bitmap_last_set (vcom->sid_rd_bitmap) + 1;
873       sid_bits = (sid_bits_set > sid_bits) ? sid_bits_set : sid_bits;
874
875       libc_bits_set = clib_bitmap_last_set (vcom->libc_rd_bitmap) + 1;
876       libc_bits = (libc_bits_set > libc_bits) ? libc_bits_set : libc_bits;
877
878       if (VCOM_DEBUG > 3)
879         clib_warning ("LDP<%d>: readfds: sid_bits_set %d, sid_bits %d, "
880                       "libc_bits_set %d, libc_bits %d", getpid (),
881                       sid_bits_set, sid_bits, libc_bits_set, libc_bits);
882     }
883   if (writefds)
884     {
885       clib_bitmap_validate (vcom->sid_wr_bitmap, minbits);
886       clib_bitmap_validate (vcom->libc_wr_bitmap, minbits);
887       clib_bitmap_validate (vcom->wr_bitmap, minbits);
888       clib_memcpy (vcom->wr_bitmap, writefds,
889                    vec_len (vcom->wr_bitmap) * sizeof (clib_bitmap_t));
890       FD_ZERO (writefds);
891
892       /* *INDENT-OFF* */
893       clib_bitmap_foreach (fd, vcom->wr_bitmap,
894         ({
895           sid = vcom_sid_from_fd (fd);
896           if (VCOM_DEBUG > 3)
897             clib_warning ("LDP<%d>: writefds: fd %d (0x%x), sid %u (0x%x)",
898                           getpid (), fd, fd, sid, sid);
899           if (sid == INVALID_SESSION_ID)
900             clib_bitmap_set_no_check (vcom->libc_wr_bitmap, fd, 1);
901           else
902             clib_bitmap_set_no_check (vcom->sid_wr_bitmap, sid, 1);
903         }));
904       /* *INDENT-ON* */
905
906       sid_bits_set = clib_bitmap_last_set (vcom->sid_wr_bitmap) + 1;
907       sid_bits = (sid_bits_set > sid_bits) ? sid_bits_set : sid_bits;
908
909       libc_bits_set = clib_bitmap_last_set (vcom->libc_wr_bitmap) + 1;
910       libc_bits = (libc_bits_set > libc_bits) ? libc_bits_set : libc_bits;
911
912       if (VCOM_DEBUG > 3)
913         clib_warning ("LDP<%d>: writefds: sid_bits_set %d, sid_bits %d, "
914                       "libc_bits_set %d, libc_bits %d", getpid (),
915                       sid_bits_set, sid_bits, libc_bits_set, libc_bits);
916     }
917   if (exceptfds)
918     {
919       clib_bitmap_validate (vcom->sid_ex_bitmap, minbits);
920       clib_bitmap_validate (vcom->libc_ex_bitmap, minbits);
921       clib_bitmap_validate (vcom->ex_bitmap, minbits);
922       clib_memcpy (vcom->ex_bitmap, exceptfds,
923                    vec_len (vcom->ex_bitmap) * sizeof (clib_bitmap_t));
924       FD_ZERO (exceptfds);
925
926       /* *INDENT-OFF* */
927       clib_bitmap_foreach (fd, vcom->ex_bitmap,
928         ({
929           sid = vcom_sid_from_fd (fd);
930           if (VCOM_DEBUG > 3)
931             clib_warning ("LDP<%d>: exceptfds: fd %d (0x%x), sid %u (0x%x)",
932                           getpid (), fd, fd, sid, sid);
933           if (sid == INVALID_SESSION_ID)
934             clib_bitmap_set_no_check (vcom->libc_ex_bitmap, fd, 1);
935           else
936             clib_bitmap_set_no_check (vcom->sid_ex_bitmap, sid, 1);
937         }));
938       /* *INDENT-ON* */
939
940       sid_bits_set = clib_bitmap_last_set (vcom->sid_ex_bitmap) + 1;
941       sid_bits = (sid_bits_set > sid_bits) ? sid_bits_set : sid_bits;
942
943       libc_bits_set = clib_bitmap_last_set (vcom->libc_ex_bitmap) + 1;
944       libc_bits = (libc_bits_set > libc_bits) ? libc_bits_set : libc_bits;
945
946       if (VCOM_DEBUG > 3)
947         clib_warning ("LDP<%d>: exceptfds: sid_bits_set %d, sid_bits %d, "
948                       "libc_bits_set %d, libc_bits %d", getpid (),
949                       sid_bits_set, sid_bits, libc_bits_set, libc_bits);
950     }
951
952   if (PREDICT_FALSE (!sid_bits && !libc_bits))
953     {
954       errno = EINVAL;
955       rv = -1;
956       goto done;
957     }
958
959   do
960     {
961       if (sid_bits)
962         {
963           if (!vcom->select_vcl)
964             {
965               func_str = "vppcom_select";
966
967               if (readfds)
968                 clib_memcpy (vcom->rd_bitmap, vcom->sid_rd_bitmap,
969                              vec_len (vcom->rd_bitmap) *
970                              sizeof (clib_bitmap_t));
971               if (writefds)
972                 clib_memcpy (vcom->wr_bitmap, vcom->sid_wr_bitmap,
973                              vec_len (vcom->wr_bitmap) *
974                              sizeof (clib_bitmap_t));
975               if (exceptfds)
976                 clib_memcpy (vcom->ex_bitmap, vcom->sid_ex_bitmap,
977                              vec_len (vcom->ex_bitmap) *
978                              sizeof (clib_bitmap_t));
979
980               rv = vppcom_select (sid_bits,
981                                   readfds ? vcom->rd_bitmap : NULL,
982                                   writefds ? vcom->wr_bitmap : NULL,
983                                   exceptfds ? vcom->ex_bitmap : NULL, 0);
984               if (rv < 0)
985                 {
986                   errno = -rv;
987                   rv = -1;
988                 }
989               else if (rv > 0)
990                 {
991                   if (readfds)
992                     {
993                       /* *INDENT-OFF* */
994                       clib_bitmap_foreach (sid, vcom->rd_bitmap,
995                         ({
996                           fd = vcom_fd_from_sid (sid);
997                           if (PREDICT_FALSE (fd < 0))
998                             {
999                               errno = EBADFD;
1000                               rv = -1;
1001                               goto done;
1002                             }
1003                           FD_SET (fd, readfds);
1004                         }));
1005                       /* *INDENT-ON* */
1006                     }
1007                   if (writefds)
1008                     {
1009                       /* *INDENT-OFF* */
1010                       clib_bitmap_foreach (sid, vcom->wr_bitmap,
1011                         ({
1012                           fd = vcom_fd_from_sid (sid);
1013                           if (PREDICT_FALSE (fd < 0))
1014                             {
1015                               errno = EBADFD;
1016                               rv = -1;
1017                               goto done;
1018                             }
1019                           FD_SET (fd, writefds);
1020                         }));
1021                       /* *INDENT-ON* */
1022                     }
1023                   if (exceptfds)
1024                     {
1025                       /* *INDENT-OFF* */
1026                       clib_bitmap_foreach (sid, vcom->ex_bitmap,
1027                         ({
1028                           fd = vcom_fd_from_sid (sid);
1029                           if (PREDICT_FALSE (fd < 0))
1030                             {
1031                               errno = EBADFD;
1032                               rv = -1;
1033                               goto done;
1034                             }
1035                           FD_SET (fd, exceptfds);
1036                         }));
1037                       /* *INDENT-ON* */
1038                     }
1039                   vcom->select_vcl = 1;
1040                   goto done;
1041                 }
1042             }
1043           else
1044             vcom->select_vcl = 0;
1045         }
1046       if (libc_bits)
1047         {
1048           struct timespec tspec;
1049
1050           func_str = "libc_pselect";
1051
1052           if (readfds)
1053             clib_memcpy (readfds, vcom->libc_rd_bitmap,
1054                          vec_len (vcom->rd_bitmap) * sizeof (clib_bitmap_t));
1055           if (writefds)
1056             clib_memcpy (writefds, vcom->libc_wr_bitmap,
1057                          vec_len (vcom->wr_bitmap) * sizeof (clib_bitmap_t));
1058           if (exceptfds)
1059             clib_memcpy (exceptfds, vcom->libc_ex_bitmap,
1060                          vec_len (vcom->ex_bitmap) * sizeof (clib_bitmap_t));
1061           tspec.tv_sec = tspec.tv_nsec = 0;
1062           rv = libc_pselect (libc_bits,
1063                              readfds ? readfds : NULL,
1064                              writefds ? writefds : NULL,
1065                              exceptfds ? exceptfds : NULL, &tspec, sigmask);
1066           if (rv != 0)
1067             goto done;
1068         }
1069     }
1070   while ((time_out == -1) || (clib_time_now (&vcom->clib_time) < time_out));
1071   rv = 0;
1072
1073 done:
1074   /* TBD: set timeout to amount of time left */
1075   vec_reset_length (vcom->rd_bitmap);
1076   vec_reset_length (vcom->sid_rd_bitmap);
1077   vec_reset_length (vcom->libc_rd_bitmap);
1078   vec_reset_length (vcom->wr_bitmap);
1079   vec_reset_length (vcom->sid_wr_bitmap);
1080   vec_reset_length (vcom->libc_wr_bitmap);
1081   vec_reset_length (vcom->ex_bitmap);
1082   vec_reset_length (vcom->sid_ex_bitmap);
1083   vec_reset_length (vcom->libc_ex_bitmap);
1084
1085   if (VCOM_DEBUG > 3)
1086     {
1087       if (rv < 0)
1088         {
1089           int errno_val = errno;
1090           perror (func_str);
1091           clib_warning ("LDP<%d>: ERROR: %s() failed! "
1092                         "rv %d, errno = %d", getpid (),
1093                         func_str, rv, errno_val);
1094           errno = errno_val;
1095         }
1096       else
1097         clib_warning ("LDP<%d>: returning %d (0x%x)", getpid (), rv, rv);
1098     }
1099   return rv;
1100 }
1101
1102 int
1103 select (int nfds, fd_set * __restrict readfds,
1104         fd_set * __restrict writefds,
1105         fd_set * __restrict exceptfds, struct timeval *__restrict timeout)
1106 {
1107   struct timespec tspec;
1108
1109   if (timeout)
1110     {
1111       tspec.tv_sec = timeout->tv_sec;
1112       tspec.tv_nsec = timeout->tv_usec * 1000;
1113     }
1114   return vcom_pselect (nfds, readfds, writefds, exceptfds,
1115                        timeout ? &tspec : NULL, NULL);
1116 }
1117
1118 #ifdef __USE_XOPEN2K
1119 int
1120 pselect (int nfds, fd_set * __restrict readfds,
1121          fd_set * __restrict writefds,
1122          fd_set * __restrict exceptfds,
1123          const struct timespec *__restrict timeout,
1124          const __sigset_t * __restrict sigmask)
1125 {
1126   return vcom_pselect (nfds, readfds, writefds, exceptfds, timeout, 0);
1127 }
1128 #endif
1129
1130 int
1131 socket (int domain, int type, int protocol)
1132 {
1133   const char *func_str;
1134   int rv;
1135   u8 is_nonblocking = type & SOCK_NONBLOCK ? 1 : 0;
1136   int sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
1137
1138   if ((errno = -vcom_init ()))
1139     return -1;
1140
1141   if (((domain == AF_INET) || (domain == AF_INET6)) &&
1142       ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
1143     {
1144       int sid;
1145       u32 vrf = VPPCOM_VRF_DEFAULT;
1146       u8 proto = ((sock_type == SOCK_DGRAM) ?
1147                   VPPCOM_PROTO_UDP : VPPCOM_PROTO_TCP);
1148
1149       func_str = "vppcom_session_create";
1150
1151       if (VCOM_DEBUG > 0)
1152         clib_warning ("LDP<%d>: : calling %s(): vrf %u, "
1153                       "proto %u (%s), is_nonblocking %u",
1154                       getpid (), func_str, vrf, proto,
1155                       vppcom_proto_str (proto), is_nonblocking);
1156
1157       sid = vppcom_session_create (vrf, proto, is_nonblocking);
1158       if (sid < 0)
1159         {
1160           errno = -sid;
1161           rv = -1;
1162         }
1163       else
1164         {
1165           func_str = "vcom_fd_from_sid";
1166           rv = vcom_fd_from_sid (sid);
1167           if (rv < 0)
1168             {
1169               (void) vppcom_session_close (sid);
1170               errno = -rv;
1171               rv = -1;
1172             }
1173         }
1174     }
1175   else
1176     {
1177       func_str = "libc_socket";
1178
1179       if (VCOM_DEBUG > 0)
1180         clib_warning ("LDP<%d>: : calling %s()", getpid (), func_str);
1181
1182       rv = libc_socket (domain, type, protocol);
1183     }
1184
1185   if (VCOM_DEBUG > 0)
1186     {
1187       if (rv < 0)
1188         {
1189           int errno_val = errno;
1190           perror (func_str);
1191           clib_warning ("LDP<%d>: ERROR: %s() failed! "
1192                         "rv %d, errno = %d",
1193                         getpid (), func_str, rv, errno_val);
1194           errno = errno_val;
1195         }
1196       else
1197         clib_warning ("LDP<%d>: : returning fd %d (0x%x)", getpid (), rv, rv);
1198     }
1199   return rv;
1200 }
1201
1202 /*
1203  * Create two new sockets, of type TYPE in domain DOMAIN and using
1204  * protocol PROTOCOL, which are connected to each other, and put file
1205  * descriptors for them in FDS[0] and FDS[1].  If PROTOCOL is zero,
1206  * one will be chosen automatically.
1207  * Returns 0 on success, -1 for errors.
1208  * */
1209 int
1210 socketpair (int domain, int type, int protocol, int fds[2])
1211 {
1212   const char *func_str;
1213   int rv;
1214   int sock_type = type & ~(SOCK_CLOEXEC | SOCK_NONBLOCK);
1215
1216   if ((errno = -vcom_init ()))
1217     return -1;
1218
1219   if (((domain == AF_INET) || (domain == AF_INET6)) &&
1220       ((sock_type == SOCK_STREAM) || (sock_type == SOCK_DGRAM)))
1221     {
1222       clib_warning ("LDP<%d>: LDP-TBD", getpid ());
1223       errno = ENOSYS;
1224       rv = -1;
1225     }
1226   else
1227     {
1228       func_str = "libc_socket";
1229
1230       if (VCOM_DEBUG > 1)
1231         clib_warning ("LDP<%d>: : calling %s()", getpid (), func_str);
1232
1233       rv = libc_socket (domain, type, protocol);
1234     }
1235
1236   if (VCOM_DEBUG > 1)
1237     {
1238       if (rv < 0)
1239         {
1240           int errno_val = errno;
1241           perror (func_str);
1242           clib_warning ("LDP<%d>: ERROR: %s() failed! "
1243                         "rv %d, errno = %d",
1244                         getpid (), func_str, rv, errno_val);
1245           errno = errno_val;
1246         }
1247       else
1248         clib_warning ("LDP<%d>: : returning fd %d (0x%x)", getpid (), rv, rv);
1249     }
1250   return rv;
1251 }
1252
1253 int
1254 bind (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len)
1255 {
1256   int rv;
1257   const char *func_str;
1258   u32 sid = vcom_sid_from_fd (fd);
1259
1260   if ((errno = -vcom_init ()))
1261     return -1;
1262
1263   if (sid != INVALID_SESSION_ID)
1264     {
1265       vppcom_endpt_t ep;
1266
1267       func_str = "vppcom_session_bind";
1268
1269       ep.vrf = VPPCOM_VRF_DEFAULT;
1270       switch (addr->sa_family)
1271         {
1272         case AF_INET:
1273           if (len != sizeof (struct sockaddr_in))
1274             {
1275               clib_warning
1276                 ("LDP<%d>: ERROR: fd %d (0x%x): sid %u (0x%x): Invalid "
1277                  "AF_INET addr len %u!", getpid (), fd, fd, sid, sid, len);
1278               errno = EINVAL;
1279               rv = -1;
1280               goto done;
1281             }
1282           ep.is_ip4 = VPPCOM_IS_IP4;
1283           ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
1284           ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
1285           break;
1286
1287         case AF_INET6:
1288           if (len != sizeof (struct sockaddr_in6))
1289             {
1290               clib_warning
1291                 ("LDP<%d>: ERROR: fd %d (0x%x): sid %u (0x%x): Invalid "
1292                  "AF_INET6 addr len %u!", getpid (), fd, fd, sid, sid, len);
1293               errno = EINVAL;
1294               rv = -1;
1295               goto done;
1296             }
1297           ep.is_ip4 = VPPCOM_IS_IP6;
1298           ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1299           ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
1300           break;
1301
1302         default:
1303           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): sid %u (0x%x): "
1304                         "Unsupported address family %u!",
1305                         getpid (), fd, fd, sid, sid, addr->sa_family);
1306           errno = EAFNOSUPPORT;
1307           rv = -1;
1308           goto done;
1309         }
1310       if (VCOM_DEBUG > 0)
1311         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), "
1312                       "addr %p, len %u",
1313                       getpid (), fd, fd, func_str, sid, sid, addr, len);
1314
1315       rv = vppcom_session_bind (sid, &ep);
1316       if (rv != VPPCOM_OK)
1317         {
1318           errno = -rv;
1319           rv = -1;
1320         }
1321     }
1322   else
1323     {
1324       func_str = "libc_bind";
1325
1326       if (VCOM_DEBUG > 0)
1327         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1328                       "addr %p, len %u",
1329                       getpid (), fd, fd, func_str, addr, len);
1330
1331       rv = libc_bind (fd, addr, len);
1332     }
1333
1334 done:
1335   if (VCOM_DEBUG > 0)
1336     {
1337       if (rv < 0)
1338         {
1339           int errno_val = errno;
1340           perror (func_str);
1341           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1342                         "rv %d, errno = %d", getpid (), fd, fd,
1343                         func_str, rv, errno_val);
1344           errno = errno_val;
1345         }
1346       else
1347         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1348                       getpid (), fd, fd, rv, rv);
1349     }
1350   return rv;
1351 }
1352
1353 static inline int
1354 vcom_copy_ep_to_sockaddr (__SOCKADDR_ARG addr, socklen_t * __restrict len,
1355                           vppcom_endpt_t * ep)
1356 {
1357   int rv = 0;
1358   int sa_len, copy_len;
1359
1360   if ((errno = -vcom_init ()))
1361     return -1;
1362
1363   if (addr && len && ep)
1364     {
1365       addr->sa_family = (ep->is_ip4 == VPPCOM_IS_IP4) ? AF_INET : AF_INET6;
1366       switch (addr->sa_family)
1367         {
1368         case AF_INET:
1369           ((struct sockaddr_in *) addr)->sin_port = ep->port;
1370           if (*len > sizeof (struct sockaddr_in))
1371             *len = sizeof (struct sockaddr_in);
1372           sa_len = sizeof (struct sockaddr_in) - sizeof (struct in_addr);
1373           copy_len = *len - sa_len;
1374           if (copy_len > 0)
1375             memcpy (&((struct sockaddr_in *) addr)->sin_addr, ep->ip,
1376                     copy_len);
1377           break;
1378
1379         case AF_INET6:
1380           ((struct sockaddr_in6 *) addr)->sin6_port = ep->port;
1381           if (*len > sizeof (struct sockaddr_in6))
1382             *len = sizeof (struct sockaddr_in6);
1383           sa_len = sizeof (struct sockaddr_in6) - sizeof (struct in6_addr);
1384           copy_len = *len - sa_len;
1385           if (copy_len > 0)
1386             memcpy (((struct sockaddr_in6 *) addr)->sin6_addr.
1387                     __in6_u.__u6_addr8, ep->ip, copy_len);
1388           break;
1389
1390         default:
1391           /* Not possible */
1392           rv = -EAFNOSUPPORT;
1393           break;
1394         }
1395     }
1396   return rv;
1397 }
1398
1399 int
1400 getsockname (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len)
1401 {
1402   int rv;
1403   const char *func_str;
1404   u32 sid = vcom_sid_from_fd (fd);
1405
1406   if ((errno = -vcom_init ()))
1407     return -1;
1408
1409   if (sid != INVALID_SESSION_ID)
1410     {
1411       vppcom_endpt_t ep;
1412       u8 addr_buf[sizeof (struct in6_addr)];
1413       u32 size = sizeof (ep);
1414
1415       ep.ip = addr_buf;
1416       func_str = "vppcom_session_attr[GET_LCL_ADDR]";
1417
1418       if (VCOM_DEBUG > 2)
1419         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), "
1420                       "addr %p, len %u",
1421                       getpid (), fd, fd, func_str, sid, sid, addr, len);
1422
1423       rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_LCL_ADDR, &ep, &size);
1424       if (rv != VPPCOM_OK)
1425         {
1426           errno = -rv;
1427           rv = -1;
1428         }
1429       else
1430         {
1431           rv = vcom_copy_ep_to_sockaddr (addr, len, &ep);
1432           if (rv != VPPCOM_OK)
1433             {
1434               errno = -rv;
1435               rv = -1;
1436             }
1437         }
1438     }
1439   else
1440     {
1441       func_str = "libc_getsockname";
1442
1443       if (VCOM_DEBUG > 2)
1444         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1445                       "addr %p, len %u",
1446                       getpid (), fd, fd, func_str, addr, len);
1447
1448       rv = libc_getsockname (fd, addr, len);
1449     }
1450
1451   if (VCOM_DEBUG > 2)
1452     {
1453       if (rv < 0)
1454         {
1455           int errno_val = errno;
1456           perror (func_str);
1457           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1458                         "rv %d, errno = %d", getpid (), fd, fd,
1459                         func_str, rv, errno_val);
1460           errno = errno_val;
1461         }
1462       else
1463         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1464                       getpid (), fd, fd, rv, rv);
1465     }
1466   return rv;
1467 }
1468
1469 int
1470 connect (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len)
1471 {
1472   int rv;
1473   const char *func_str = __func__;
1474   u32 sid = vcom_sid_from_fd (fd);
1475
1476   if ((errno = -vcom_init ()))
1477     return -1;
1478
1479   if (!addr)
1480     {
1481       clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): NULL addr, len %u",
1482                     getpid (), fd, fd, len);
1483       errno = EINVAL;
1484       rv = -1;
1485       goto done;
1486     }
1487
1488   if (sid != INVALID_SESSION_ID)
1489     {
1490       vppcom_endpt_t ep;
1491
1492       func_str = "vppcom_session_connect";
1493
1494       ep.vrf = VPPCOM_VRF_DEFAULT;
1495       switch (addr->sa_family)
1496         {
1497         case AF_INET:
1498           if (len != sizeof (struct sockaddr_in))
1499             {
1500               clib_warning
1501                 ("LDP<%d>: fd %d (0x%x): ERROR sid %u (0x%x): Invalid "
1502                  "AF_INET addr len %u!", getpid (), fd, fd, sid, sid, len);
1503               errno = EINVAL;
1504               rv = -1;
1505               goto done;
1506             }
1507           ep.is_ip4 = VPPCOM_IS_IP4;
1508           ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
1509           ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
1510           break;
1511
1512         case AF_INET6:
1513           if (len != sizeof (struct sockaddr_in6))
1514             {
1515               clib_warning
1516                 ("LDP<%d>: fd %d (0x%x): ERROR sid %u (0x%x): Invalid "
1517                  "AF_INET6 addr len %u!", getpid (), fd, fd, sid, sid, len);
1518               errno = EINVAL;
1519               rv = -1;
1520               goto done;
1521             }
1522           ep.is_ip4 = VPPCOM_IS_IP6;
1523           ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1524           ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
1525           break;
1526
1527         default:
1528           clib_warning ("LDP<%d>: fd %d (0x%x): ERROR sid %u (0x%x): "
1529                         "Unsupported address family %u!",
1530                         getpid (), fd, fd, sid, sid, addr->sa_family);
1531           errno = EAFNOSUPPORT;
1532           rv = -1;
1533           goto done;
1534         }
1535       if (VCOM_DEBUG > 0)
1536         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x) "
1537                       "addr %p len %u",
1538                       getpid (), fd, fd, func_str, sid, sid, addr, len);
1539
1540       rv = vppcom_session_connect (sid, &ep);
1541       if (rv != VPPCOM_OK)
1542         {
1543           errno = -rv;
1544           rv = -1;
1545         }
1546     }
1547   else
1548     {
1549       func_str = "libc_connect";
1550
1551       if (VCOM_DEBUG > 0)
1552         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1553                       "addr %p, len %u",
1554                       getpid (), fd, fd, func_str, addr, len);
1555
1556       rv = libc_connect (fd, addr, len);
1557     }
1558
1559 done:
1560   if (VCOM_DEBUG > 0)
1561     {
1562       if (rv < 0)
1563         {
1564           int errno_val = errno;
1565           perror (func_str);
1566           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1567                         "rv %d, errno = %d", getpid (), fd, fd,
1568                         func_str, rv, errno_val);
1569           errno = errno_val;
1570         }
1571       else
1572         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1573                       getpid (), fd, fd, rv, rv);
1574     }
1575   return rv;
1576 }
1577
1578 int
1579 getpeername (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len)
1580 {
1581   int rv;
1582   const char *func_str;
1583   u32 sid = vcom_sid_from_fd (fd);
1584
1585   if ((errno = -vcom_init ()))
1586     return -1;
1587
1588   clib_warning ("LDP<%d>: fd %d (0x%x) ", getpid (), fd, fd);
1589
1590   if (sid != INVALID_SESSION_ID)
1591     {
1592       vppcom_endpt_t ep;
1593       u8 addr_buf[sizeof (struct in6_addr)];
1594       u32 size = sizeof (ep);
1595
1596       ep.ip = addr_buf;
1597       func_str = "vppcom_session_attr[GET_PEER_ADDR]";
1598
1599       if (VCOM_DEBUG > 2)
1600         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), "
1601                       "addr %p, len %u",
1602                       getpid (), fd, fd, func_str, sid, sid, addr, len);
1603
1604       rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_PEER_ADDR, &ep, &size);
1605       if (rv != VPPCOM_OK)
1606         {
1607           errno = -rv;
1608           rv = -1;
1609         }
1610       else
1611         {
1612           rv = vcom_copy_ep_to_sockaddr (addr, len, &ep);
1613           if (rv != VPPCOM_OK)
1614             {
1615               errno = -rv;
1616               rv = -1;
1617             }
1618         }
1619     }
1620   else
1621     {
1622       func_str = "libc_getpeername";
1623
1624       if (VCOM_DEBUG > 2)
1625         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1626                       "addr %p, len %u",
1627                       getpid (), fd, fd, func_str, addr, len);
1628
1629       rv = libc_getpeername (fd, addr, len);
1630     }
1631
1632   if (VCOM_DEBUG > 2)
1633     {
1634       if (rv < 0)
1635         {
1636           int errno_val = errno;
1637           perror (func_str);
1638           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1639                         "rv %d, errno = %d", getpid (), fd, fd,
1640                         func_str, rv, errno_val);
1641           errno = errno_val;
1642         }
1643       else
1644         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1645                       getpid (), fd, fd, rv, rv);
1646     }
1647   return rv;
1648 }
1649
1650 ssize_t
1651 send (int fd, const void *buf, size_t n, int flags)
1652 {
1653   ssize_t size;
1654   const char *func_str;
1655   u32 sid = vcom_sid_from_fd (fd);
1656
1657   if ((errno = -vcom_init ()))
1658     return -1;
1659
1660   if (sid != INVALID_SESSION_ID)
1661     {
1662
1663       func_str = "vppcom_session_sendto";
1664
1665       if (VCOM_DEBUG > 2)
1666         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), "
1667                       "buf %p, n %u, flags 0x%x",
1668                       getpid (), fd, fd, func_str, sid, sid, buf, n, flags);
1669
1670       size = vppcom_session_sendto (sid, (void *) buf, n, flags, NULL);
1671       if (size != VPPCOM_OK)
1672         {
1673           errno = -size;
1674           size = -1;
1675         }
1676     }
1677   else
1678     {
1679       func_str = "libc_send";
1680
1681       if (VCOM_DEBUG > 2)
1682         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1683                       "buf %p, n %u, flags 0x%x",
1684                       getpid (), fd, fd, func_str, buf, n, flags);
1685
1686       size = libc_send (fd, buf, n, flags);
1687     }
1688
1689   if (VCOM_DEBUG > 2)
1690     {
1691       if (size < 0)
1692         {
1693           int errno_val = errno;
1694           perror (func_str);
1695           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1696                         "rv %d, errno = %d", getpid (), fd, fd,
1697                         func_str, size, errno_val);
1698           errno = errno_val;
1699         }
1700       else
1701         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1702                       getpid (), fd, fd, size, size);
1703     }
1704   return size;
1705 }
1706
1707 ssize_t
1708 sendfile (int out_fd, int in_fd, off_t * offset, size_t len)
1709 {
1710   ssize_t size = 0;
1711   const char *func_str;
1712   u32 sid = vcom_sid_from_fd (out_fd);
1713
1714   if ((errno = -vcom_init ()))
1715     return -1;
1716
1717   if (sid != INVALID_SESSION_ID)
1718     {
1719       int rv;
1720       ssize_t results = 0;
1721       size_t n_bytes_left = len;
1722       size_t bytes_to_read;
1723       int nbytes;
1724       int errno_val;
1725       u8 eagain = 0;
1726       u32 flags, flags_len = sizeof (flags);
1727
1728       func_str = "vppcom_session_attr[GET_FLAGS]";
1729       rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_FLAGS, &flags,
1730                                 &flags_len);
1731       if (PREDICT_FALSE (rv != VPPCOM_OK))
1732         {
1733           clib_warning ("LDP<%d>: ERROR: out fd %d (0x%x): %s(): "
1734                         "sid %u (0x%x), returned %d (%s)!", getpid (),
1735                         out_fd, out_fd, func_str, sid, sid, rv,
1736                         vppcom_retval_str (rv));
1737
1738           vec_reset_length (vcom->io_buffer);
1739           errno = -rv;
1740           size = -1;
1741           goto done;
1742         }
1743
1744       if (offset)
1745         {
1746           off_t off = lseek (in_fd, *offset, SEEK_SET);
1747           if (PREDICT_FALSE (off == -1))
1748             {
1749               func_str = "lseek";
1750               errno_val = errno;
1751               clib_warning ("LDP<%d>: ERROR: out fd %d (0x%x): %s(): "
1752                             "SEEK_SET failed: in_fd %d, offset %p, "
1753                             "*offset %ld, rv %ld, errno %d", getpid (),
1754                             out_fd, out_fd, in_fd, offset, *offset, off,
1755                             errno_val);
1756               errno = errno_val;
1757               size = -1;
1758               goto done;
1759             }
1760
1761           ASSERT (off == *offset);
1762         }
1763
1764       do
1765         {
1766           func_str = "vppcom_session_attr[GET_NWRITE]";
1767           size = vppcom_session_attr (sid, VPPCOM_ATTR_GET_NWRITE, 0, 0);
1768           if (size < 0)
1769             {
1770               clib_warning
1771                 ("LDP<%d>: ERROR: fd %d (0x%x): %s(): sid %u (0x%x), "
1772                  "returned %d (%s)!", getpid (), out_fd, out_fd, func_str,
1773                  sid, sid, size, vppcom_retval_str (size));
1774               vec_reset_length (vcom->io_buffer);
1775               errno = -size;
1776               size = -1;
1777               goto done;
1778             }
1779
1780           bytes_to_read = size;
1781           if (VCOM_DEBUG > 2)
1782             clib_warning
1783               ("LDP<%d>: fd %d (0x%x): called %s(): sid %u (0x%x), "
1784                "results %ld, n_bytes_left %lu, bytes_to_read %lu", getpid (),
1785                out_fd, out_fd, func_str, sid, sid, results, n_bytes_left,
1786                bytes_to_read);
1787
1788           if (bytes_to_read == 0)
1789             {
1790               if (flags & O_NONBLOCK)
1791                 {
1792                   if (!results)
1793                     {
1794                       if (VCOM_DEBUG > 2)
1795                         clib_warning ("LDP<%d>: fd %d (0x%x): sid %u (0x%x): "
1796                                       "EAGAIN",
1797                                       getpid (), out_fd, out_fd, sid, sid);
1798                       eagain = 1;
1799                     }
1800                   goto update_offset;
1801                 }
1802               else
1803                 continue;
1804             }
1805           bytes_to_read = clib_min (n_bytes_left, bytes_to_read);
1806           vec_validate (vcom->io_buffer, bytes_to_read);
1807           nbytes = libc_read (in_fd, vcom->io_buffer, bytes_to_read);
1808           if (nbytes < 0)
1809             {
1810               func_str = "libc_read";
1811               errno_val = errno;
1812               clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): in_fd (%d), "
1813                             "io_buffer %p, bytes_to_read %lu, rv %d, "
1814                             "errno %d", getpid (), out_fd, out_fd, func_str,
1815                             in_fd, vcom->io_buffer, bytes_to_read, nbytes,
1816                             errno_val);
1817               errno = errno_val;
1818
1819               if (results == 0)
1820                 {
1821                   vec_reset_length (vcom->io_buffer);
1822                   size = -1;
1823                   goto done;
1824                 }
1825               goto update_offset;
1826             }
1827           func_str = "vppcom_session_write";
1828           if (VCOM_DEBUG > 2)
1829             clib_warning
1830               ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), "
1831                "buf %p, nbytes %u: results %d, n_bytes_left %d", getpid (),
1832                out_fd, out_fd, func_str, sid, sid, vcom->io_buffer, nbytes,
1833                results, n_bytes_left);
1834
1835           size = vppcom_session_write (sid, vcom->io_buffer, nbytes);
1836           if (size < 0)
1837             {
1838               if (size == VPPCOM_EAGAIN)
1839                 {
1840                   if (flags & O_NONBLOCK)
1841                     {
1842                       if (!results)
1843                         {
1844                           if (VCOM_DEBUG > 2)
1845                             clib_warning
1846                               ("LDP<%d>: fd %d (0x%x): sid %u (0x%x): "
1847                                "EAGAIN", getpid (), out_fd, out_fd, sid, sid);
1848                           eagain = 1;
1849                         }
1850                       goto update_offset;
1851                     }
1852                   else
1853                     continue;
1854                 }
1855               else
1856                 {
1857                   clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s():"
1858                                 "sid %u, io_buffer %p, nbytes %u "
1859                                 "returned %d (%s)",
1860                                 getpid (), out_fd, out_fd, func_str,
1861                                 sid, vcom->io_buffer, nbytes,
1862                                 size, vppcom_retval_str (size));
1863                 }
1864               if (results == 0)
1865                 {
1866                   vec_reset_length (vcom->io_buffer);
1867                   errno = -size;
1868                   size = -1;
1869                   goto done;
1870                 }
1871               goto update_offset;
1872             }
1873
1874           results += nbytes;
1875           ASSERT (n_bytes_left >= nbytes);
1876           n_bytes_left = n_bytes_left - nbytes;
1877         }
1878       while (n_bytes_left > 0);
1879
1880     update_offset:
1881       vec_reset_length (vcom->io_buffer);
1882       if (offset)
1883         {
1884           off_t off = lseek (in_fd, *offset, SEEK_SET);
1885           if (PREDICT_FALSE (off == -1))
1886             {
1887               func_str = "lseek";
1888               errno_val = errno;
1889               clib_warning ("LDP<%d>: ERROR: %s(): SEEK_SET failed: "
1890                             "in_fd %d, offset %p, *offset %ld, "
1891                             "rv %ld, errno %d", getpid (), in_fd,
1892                             offset, *offset, off, errno_val);
1893               errno = errno_val;
1894               size = -1;
1895               goto done;
1896             }
1897
1898           ASSERT (off == *offset);
1899           *offset += results + 1;
1900         }
1901       if (eagain)
1902         {
1903           errno = EAGAIN;
1904           size = -1;
1905         }
1906       else
1907         size = results;
1908     }
1909   else
1910     {
1911       func_str = "libc_send";
1912
1913       if (VCOM_DEBUG > 2)
1914         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1915                       "in_fd %d, offset %p, len %u",
1916                       getpid (), out_fd, out_fd, func_str,
1917                       in_fd, offset, len);
1918
1919       size = libc_sendfile (out_fd, in_fd, offset, len);
1920     }
1921
1922 done:
1923   if (VCOM_DEBUG > 2)
1924     {
1925       if (size < 0)
1926         {
1927           int errno_val = errno;
1928           perror (func_str);
1929           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1930                         "rv %d, errno = %d", getpid (), out_fd, out_fd,
1931                         func_str, size, errno_val);
1932           errno = errno_val;
1933         }
1934       else
1935         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1936                       getpid (), out_fd, out_fd, size, size);
1937     }
1938   return size;
1939 }
1940
1941 ssize_t
1942 sendfile64 (int out_fd, int in_fd, off_t * offset, size_t len)
1943 {
1944   return sendfile (out_fd, in_fd, offset, len);
1945 }
1946
1947 ssize_t
1948 recv (int fd, void *buf, size_t n, int flags)
1949 {
1950   ssize_t size;
1951   const char *func_str;
1952   u32 sid = vcom_sid_from_fd (fd);
1953
1954   if ((errno = -vcom_init ()))
1955     return -1;
1956
1957   if (sid != INVALID_SESSION_ID)
1958     {
1959       func_str = "vppcom_session_recvfrom";
1960
1961       if (VCOM_DEBUG > 2)
1962         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1963                       "sid %u (0x%x), buf %p, n %u, flags 0x%x", getpid (),
1964                       fd, fd, func_str, sid, sid, buf, n, flags);
1965
1966       size = vppcom_session_recvfrom (sid, buf, n, flags, NULL);
1967       if (size < 0)
1968         {
1969           errno = -size;
1970           size = -1;
1971         }
1972     }
1973   else
1974     {
1975       func_str = "libc_recv";
1976
1977       if (VCOM_DEBUG > 2)
1978         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1979                       "buf %p, n %u, flags 0x%x", getpid (),
1980                       fd, fd, func_str, buf, n, flags);
1981
1982       size = libc_recv (fd, buf, n, flags);
1983     }
1984
1985   if (VCOM_DEBUG > 2)
1986     {
1987       if (size < 0)
1988         {
1989           int errno_val = errno;
1990           perror (func_str);
1991           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1992                         "rv %d, errno = %d", getpid (), fd, fd,
1993                         func_str, size, errno_val);
1994           errno = errno_val;
1995         }
1996       else
1997         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1998                       getpid (), fd, fd, size, size);
1999     }
2000   return size;
2001 }
2002
2003 ssize_t
2004 sendto (int fd, const void *buf, size_t n, int flags,
2005         __CONST_SOCKADDR_ARG addr, socklen_t addr_len)
2006 {
2007   ssize_t size;
2008   const char *func_str = __func__;
2009   u32 sid = vcom_sid_from_fd (fd);
2010
2011   if ((errno = -vcom_init ()))
2012     return -1;
2013
2014   if (sid != INVALID_SESSION_ID)
2015     {
2016       vppcom_endpt_t *ep = 0;
2017       vppcom_endpt_t _ep;
2018
2019       if (addr)
2020         {
2021           ep = &_ep;
2022           ep->vrf = VPPCOM_VRF_DEFAULT;
2023           switch (addr->sa_family)
2024             {
2025             case AF_INET:
2026               ep->is_ip4 = VPPCOM_IS_IP4;
2027               ep->ip =
2028                 (uint8_t *) & ((const struct sockaddr_in *) addr)->sin_addr;
2029               ep->port =
2030                 (uint16_t) ((const struct sockaddr_in *) addr)->sin_port;
2031               break;
2032
2033             case AF_INET6:
2034               ep->is_ip4 = VPPCOM_IS_IP6;
2035               ep->ip =
2036                 (uint8_t *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
2037               ep->port =
2038                 (uint16_t) ((const struct sockaddr_in6 *) addr)->sin6_port;
2039               break;
2040
2041             default:
2042               errno = EAFNOSUPPORT;
2043               size = -1;
2044               goto done;
2045             }
2046         }
2047
2048       func_str = "vppcom_session_sendto";
2049
2050       if (VCOM_DEBUG > 2)
2051         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2052                       "sid %u (0x%x), buf %p, n %u, flags 0x%x, ep %p",
2053                       getpid (), fd, fd, func_str, sid, sid, buf, n,
2054                       flags, ep);
2055
2056       size = vppcom_session_sendto (sid, (void *) buf, n, flags, ep);
2057       if (size < 0)
2058         {
2059           errno = -size;
2060           size = -1;
2061         }
2062     }
2063   else
2064     {
2065       func_str = "libc_sendto";
2066
2067       if (VCOM_DEBUG > 2)
2068         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2069                       "buf %p, n %u, flags 0x%x, addr %p, addr_len %d",
2070                       getpid (), fd, fd, func_str, buf, n, flags,
2071                       addr, addr_len);
2072
2073       size = libc_sendto (fd, buf, n, flags, addr, addr_len);
2074     }
2075
2076 done:
2077   if (VCOM_DEBUG > 2)
2078     {
2079       if (size < 0)
2080         {
2081           int errno_val = errno;
2082           perror (func_str);
2083           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2084                         "rv %d, errno = %d", getpid (), fd, fd,
2085                         func_str, size, errno_val);
2086           errno = errno_val;
2087         }
2088       else
2089         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2090                       getpid (), fd, fd, size, size);
2091     }
2092   return size;
2093 }
2094
2095 ssize_t
2096 recvfrom (int fd, void *__restrict buf, size_t n, int flags,
2097           __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
2098 {
2099   ssize_t size;
2100   const char *func_str;
2101   u32 sid = vcom_sid_from_fd (fd);
2102
2103   if ((errno = -vcom_init ()))
2104     return -1;
2105
2106   if (sid != INVALID_SESSION_ID)
2107     {
2108       vppcom_endpt_t ep;
2109       u8 src_addr[sizeof (struct sockaddr_in6)];
2110
2111       func_str = "vppcom_session_recvfrom";
2112
2113       if (VCOM_DEBUG > 2)
2114         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2115                       "sid %u (0x%x), buf %p, n %u, flags 0x%x, ep %p",
2116                       getpid (), fd, fd, func_str, sid, sid, buf, n,
2117                       flags, &ep);
2118       if (addr)
2119         {
2120           ep.ip = src_addr;
2121           size = vppcom_session_recvfrom (sid, buf, n, flags, &ep);
2122
2123           if (size > 0)
2124             size = vcom_copy_ep_to_sockaddr (addr, addr_len, &ep);
2125         }
2126       else
2127         size = vppcom_session_recvfrom (sid, buf, n, flags, NULL);
2128
2129       if (size < 0)
2130         {
2131           errno = -size;
2132           size = -1;
2133         }
2134     }
2135   else
2136     {
2137       func_str = "libc_recvfrom";
2138
2139       if (VCOM_DEBUG > 2)
2140         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2141                       "buf %p, n %u, flags 0x%x, addr %p, addr_len %d",
2142                       getpid (), fd, fd, func_str, buf, n, flags,
2143                       addr, addr_len);
2144
2145       size = libc_recvfrom (fd, buf, n, flags, addr, addr_len);
2146     }
2147
2148   if (VCOM_DEBUG > 2)
2149     {
2150       if (size < 0)
2151         {
2152           int errno_val = errno;
2153           perror (func_str);
2154           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2155                         "rv %d, errno = %d", getpid (), fd, fd,
2156                         func_str, size, errno_val);
2157           errno = errno_val;
2158         }
2159       else
2160         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2161                       getpid (), fd, fd, size, size);
2162     }
2163   return size;
2164 }
2165
2166 ssize_t
2167 sendmsg (int fd, const struct msghdr * message, int flags)
2168 {
2169   ssize_t size;
2170   const char *func_str;
2171   u32 sid = vcom_sid_from_fd (fd);
2172
2173   if ((errno = -vcom_init ()))
2174     return -1;
2175
2176   if (sid != INVALID_SESSION_ID)
2177     {
2178       clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2179       errno = ENOSYS;
2180       size = -1;
2181     }
2182   else
2183     {
2184       func_str = "libc_sendmsg";
2185
2186       if (VCOM_DEBUG > 2)
2187         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2188                       "message %p, flags 0x%x",
2189                       getpid (), fd, fd, func_str, message, flags);
2190
2191       size = libc_sendmsg (fd, message, flags);
2192     }
2193
2194   if (VCOM_DEBUG > 2)
2195     {
2196       if (size < 0)
2197         {
2198           int errno_val = errno;
2199           perror (func_str);
2200           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2201                         "rv %d, errno = %d", getpid (), fd, fd,
2202                         func_str, size, errno_val);
2203           errno = errno_val;
2204         }
2205       else
2206         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2207                       getpid (), fd, fd, size, size);
2208     }
2209   return size;
2210 }
2211
2212 #ifdef USE_GNU
2213 int
2214 sendmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags)
2215 {
2216   ssize_t size;
2217   const char *func_str;
2218   u32 sid = vcom_sid_from_fd (fd);
2219
2220   if ((errno = -vcom_init ()))
2221     return -1;
2222
2223   if (sid != INVALID_SESSION_ID)
2224     {
2225       clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2226       errno = ENOSYS;
2227       size = -1;
2228     }
2229   else
2230     {
2231       func_str = "libc_sendmmsg";
2232
2233       if (VCOM_DEBUG > 2)
2234         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2235                       "vmessages %p, vlen %u, flags 0x%x",
2236                       getpid (), fd, fd, func_str, vmessages, vlen, flags);
2237
2238       size = libc_sendmmsg (fd, vmessages, vlen, flags);
2239     }
2240
2241   if (VCOM_DEBUG > 2)
2242     {
2243       if (size < 0)
2244         {
2245           int errno_val = errno;
2246           perror (func_str);
2247           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2248                         "rv %d, errno = %d", getpid (), fd, fd,
2249                         func_str, size, errno_val);
2250           errno = errno_val;
2251         }
2252       else
2253         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2254                       getpid (), fd, fd, size, size);
2255     }
2256   return size;
2257 }
2258 #endif
2259
2260 ssize_t
2261 recvmsg (int fd, struct msghdr * message, int flags)
2262 {
2263   ssize_t size;
2264   const char *func_str;
2265   u32 sid = vcom_sid_from_fd (fd);
2266
2267   if ((errno = -vcom_init ()))
2268     return -1;
2269
2270   if (sid != INVALID_SESSION_ID)
2271     {
2272       clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2273       errno = ENOSYS;
2274       size = -1;
2275     }
2276   else
2277     {
2278       func_str = "libc_recvmsg";
2279
2280       if (VCOM_DEBUG > 2)
2281         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2282                       "message %p, flags 0x%x",
2283                       getpid (), fd, fd, func_str, message, flags);
2284
2285       size = libc_recvmsg (fd, message, flags);
2286     }
2287
2288   if (VCOM_DEBUG > 2)
2289     {
2290       if (size < 0)
2291         {
2292           int errno_val = errno;
2293           perror (func_str);
2294           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2295                         "rv %d, errno = %d", getpid (), fd, fd,
2296                         func_str, size, errno_val);
2297           errno = errno_val;
2298         }
2299       else
2300         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2301                       getpid (), fd, fd, size, size);
2302     }
2303   return size;
2304 }
2305
2306 #ifdef USE_GNU
2307 int
2308 recvmmsg (int fd, struct mmsghdr *vmessages,
2309           unsigned int vlen, int flags, struct timespec *tmo)
2310 {
2311   ssize_t size;
2312   const char *func_str;
2313   u32 sid = vcom_sid_from_fd (fd);
2314
2315   if ((errno = -vcom_init ()))
2316     return -1;
2317
2318   if (sid != INVALID_SESSION_ID)
2319     {
2320       clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2321       errno = ENOSYS;
2322       size = -1;
2323     }
2324   else
2325     {
2326       func_str = "libc_recvmmsg";
2327
2328       if (VCOM_DEBUG > 2)
2329         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2330                       "vmessages %p, vlen %u, flags 0x%x, tmo %p",
2331                       getpid (), fd, fd, func_str, vmessages, vlen,
2332                       flags, tmo);
2333
2334       size = libc_recvmmsg (fd, vmessages, vlen, flags, tmo);
2335     }
2336
2337   if (VCOM_DEBUG > 2)
2338     {
2339       if (size < 0)
2340         {
2341           int errno_val = errno;
2342           perror (func_str);
2343           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2344                         "rv %d, errno = %d", getpid (), fd, fd,
2345                         func_str, size, errno_val);
2346           errno = errno_val;
2347         }
2348       else
2349         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2350                       getpid (), fd, fd, size, size);
2351     }
2352   return size;
2353 }
2354 #endif
2355
2356 int
2357 getsockopt (int fd, int level, int optname,
2358             void *__restrict optval, socklen_t * __restrict optlen)
2359 {
2360   int rv;
2361   const char *func_str = __func__;
2362   u32 sid = vcom_sid_from_fd (fd);
2363   u32 buflen = (u32) * optlen;
2364
2365   if ((errno = -vcom_init ()))
2366     return -1;
2367
2368   if (sid != INVALID_SESSION_ID)
2369     {
2370       rv = -EOPNOTSUPP;
2371
2372       switch (level)
2373         {
2374         case SOL_TCP:
2375           switch (optname)
2376             {
2377             case TCP_NODELAY:
2378               func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_NODELAY]";
2379               if (VCOM_DEBUG > 1)
2380                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2381                               "sid %u (0x%x)",
2382                               getpid (), fd, fd, func_str, sid, sid);
2383               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_NODELAY,
2384                                         optval, optlen);
2385               break;
2386             case TCP_MAXSEG:
2387               func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_USER_MSS]";
2388               if (VCOM_DEBUG > 1)
2389                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2390                               "sid %u (0x%x)",
2391                               getpid (), fd, fd, func_str, sid, sid);
2392               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_USER_MSS,
2393                                         optval, optlen);
2394               break;
2395             case TCP_KEEPIDLE:
2396               func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_KEEPIDLE]";
2397               if (VCOM_DEBUG > 1)
2398                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2399                               "sid %u (0x%x)",
2400                               getpid (), fd, fd, func_str, sid, sid);
2401               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_KEEPIDLE,
2402                                         optval, optlen);
2403               break;
2404             case TCP_KEEPINTVL:
2405               func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_KEEPINTVL]";
2406               if (VCOM_DEBUG > 1)
2407                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2408                               "sid %u (0x%x), SOL_TCP",
2409                               getpid (), fd, fd, func_str, sid, sid);
2410               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_KEEPINTVL,
2411                                         optval, optlen);
2412               break;
2413             case TCP_INFO:
2414               if (optval && optlen && (*optlen == sizeof (struct tcp_info)))
2415                 {
2416                   if (VCOM_DEBUG > 1)
2417                     clib_warning ("LDP<%d>: fd %d (0x%x): sid %u (0x%x), "
2418                                   "SOL_TCP, TCP_INFO, optval %p, "
2419                                   "optlen %d: #LDP-NOP#",
2420                                   getpid (), fd, fd, sid, sid,
2421                                   optval, *optlen);
2422                   memset (optval, 0, *optlen);
2423                   rv = VPPCOM_OK;
2424                 }
2425               else
2426                 rv = -EFAULT;
2427               break;
2428             default:
2429               if (VCOM_DEBUG > 1)
2430                 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
2431                               "sid %u (0x%x), SOL_TCP, "
2432                               "optname %d unsupported!",
2433                               getpid (), fd, fd, func_str, sid, sid, optname);
2434               break;
2435             }
2436           break;
2437         case SOL_IPV6:
2438           switch (optname)
2439             {
2440             case IPV6_V6ONLY:
2441               func_str = "vppcom_session_attr[SOL_IPV6,GET_V6ONLY]";
2442               if (VCOM_DEBUG > 1)
2443                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2444                               "sid %u (0x%x)",
2445                               getpid (), fd, fd, func_str, sid, sid);
2446               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_V6ONLY,
2447                                         optval, optlen);
2448               break;
2449             default:
2450               if (VCOM_DEBUG > 1)
2451                 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
2452                               "sid %u (0x%x), SOL_IPV6, "
2453                               "optname %d unsupported!",
2454                               getpid (), fd, fd, func_str, sid, sid, optname);
2455               break;
2456             }
2457           break;
2458         case SOL_SOCKET:
2459           switch (optname)
2460             {
2461             case SO_ACCEPTCONN:
2462               func_str = "vppcom_session_attr[SOL_SOCKET,GET_ACCEPTCONN]";
2463               if (VCOM_DEBUG > 1)
2464                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2465                               "sid %u (0x%x)",
2466                               getpid (), fd, fd, func_str, sid, sid);
2467               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_LISTEN,
2468                                         optval, optlen);
2469               break;
2470             case SO_KEEPALIVE:
2471               func_str = "vppcom_session_attr[SOL_SOCKET,GET_KEEPALIVE]";
2472               if (VCOM_DEBUG > 1)
2473                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2474                               "sid %u (0x%x)",
2475                               getpid (), fd, fd, func_str, sid, sid);
2476               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_KEEPALIVE,
2477                                         optval, optlen);
2478               break;
2479             case SO_PROTOCOL:
2480               func_str = "vppcom_session_attr[SOL_SOCKET,GET_PROTOCOL]";
2481               if (VCOM_DEBUG > 1)
2482                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2483                               "sid %u (0x%x)",
2484                               getpid (), fd, fd, func_str, sid, sid);
2485               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_PROTOCOL,
2486                                         optval, optlen);
2487               *(int *) optval = *(int *) optval ? SOCK_DGRAM : SOCK_STREAM;
2488               break;
2489             case SO_SNDBUF:
2490               func_str = "vppcom_session_attr[SOL_SOCKET,GET_TX_FIFO_LEN]";
2491               if (VCOM_DEBUG > 1)
2492                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2493                               "sid %u (0x%x), optlen %d",
2494                               getpid (), fd, fd, func_str, sid, sid, buflen);
2495               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TX_FIFO_LEN,
2496                                         optval, optlen);
2497               break;
2498             case SO_RCVBUF:
2499               func_str = "vppcom_session_attr[SOL_SOCKET,GET_RX_FIFO_LEN]";
2500               if (VCOM_DEBUG > 1)
2501                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2502                               "sid %u (0x%x), optlen %d",
2503                               getpid (), fd, fd, func_str, sid, sid, *optlen);
2504               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_RX_FIFO_LEN,
2505                                         optval, optlen);
2506               break;
2507             case SO_REUSEADDR:
2508               func_str = "vppcom_session_attr[SOL_SOCKET,GET_REUSEADDR]";
2509               if (VCOM_DEBUG > 1)
2510                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2511                               "sid %u (0x%x)",
2512                               getpid (), fd, fd, func_str, sid, sid);
2513               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_REUSEADDR,
2514                                         optval, optlen);
2515               break;
2516             case SO_BROADCAST:
2517               func_str = "vppcom_session_attr[SOL_SOCKET,GET_BROADCAST]";
2518               if (VCOM_DEBUG > 1)
2519                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2520                               "sid %u (0x%x)",
2521                               getpid (), fd, fd, func_str, sid, sid);
2522               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_BROADCAST,
2523                                         optval, optlen);
2524               break;
2525             case SO_ERROR:
2526               func_str = "vppcom_session_attr[SOL_SOCKET,GET_ERROR]";
2527               if (VCOM_DEBUG > 1)
2528                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2529                               "sid %u (0x%x)",
2530                               getpid (), fd, fd, func_str, sid, sid);
2531               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_ERROR,
2532                                         optval, optlen);
2533               break;
2534             default:
2535               if (VCOM_DEBUG > 1)
2536                 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
2537                               "sid %u (0x%x), SOL_SOCKET, "
2538                               "optname %d unsupported!",
2539                               getpid (), fd, fd, func_str, sid, sid, optname);
2540               break;
2541             }
2542           break;
2543         default:
2544           break;
2545         }
2546
2547       if (rv != VPPCOM_OK)
2548         {
2549           errno = -rv;
2550           rv = -1;
2551         }
2552     }
2553   else
2554     {
2555       func_str = "libc_getsockopt";
2556
2557       if (VCOM_DEBUG > 1)
2558         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): level %d, "
2559                       "optname %d, optval %p, optlen %d",
2560                       getpid (), fd, fd, func_str, level, optname,
2561                       optval, optlen);
2562
2563       rv = libc_getsockopt (fd, level, optname, optval, optlen);
2564     }
2565
2566   if (VCOM_DEBUG > 1)
2567     {
2568       if (rv < 0)
2569         {
2570           int errno_val = errno;
2571           perror (func_str);
2572           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2573                         "rv %d, errno = %d", getpid (), fd, fd,
2574                         func_str, rv, errno_val);
2575           errno = errno_val;
2576         }
2577       else
2578         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2579                       getpid (), fd, fd, rv, rv);
2580     }
2581   return rv;
2582 }
2583
2584 int
2585 setsockopt (int fd, int level, int optname,
2586             const void *optval, socklen_t optlen)
2587 {
2588   int rv;
2589   const char *func_str = __func__;
2590   u32 sid = vcom_sid_from_fd (fd);
2591
2592   if ((errno = -vcom_init ()))
2593     return -1;
2594
2595   if (sid != INVALID_SESSION_ID)
2596     {
2597       rv = -EOPNOTSUPP;
2598
2599       switch (level)
2600         {
2601         case SOL_TCP:
2602           switch (optname)
2603             {
2604             case TCP_NODELAY:
2605               func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_NODELAY]";
2606               if (VCOM_DEBUG > 1)
2607                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2608                               "sid %u (0x%x)",
2609                               getpid (), fd, fd, func_str, sid, sid);
2610               rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_NODELAY,
2611                                         (void *) optval, &optlen);
2612               break;
2613             case TCP_MAXSEG:
2614               func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_USER_MSS]";
2615               if (VCOM_DEBUG > 1)
2616                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2617                               "sid %u (0x%x)",
2618                               getpid (), fd, fd, func_str, sid, sid);
2619               rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_USER_MSS,
2620                                         (void *) optval, &optlen);
2621               break;
2622             case TCP_KEEPIDLE:
2623               func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_KEEPIDLE]";
2624               if (VCOM_DEBUG > 1)
2625                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2626                               "sid %u (0x%x)",
2627                               getpid (), fd, fd, func_str, sid, sid);
2628               rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_KEEPIDLE,
2629                                         (void *) optval, &optlen);
2630               break;
2631             case TCP_KEEPINTVL:
2632               func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_KEEPINTVL]";
2633               if (VCOM_DEBUG > 1)
2634                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2635                               "sid %u (0x%x), SOL_TCP",
2636                               getpid (), fd, fd, func_str, sid, sid);
2637               rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_KEEPINTVL,
2638                                         (void *) optval, &optlen);
2639               break;
2640             default:
2641               if (VCOM_DEBUG > 1)
2642                 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
2643                               "sid %u (0x%x), SOL_TCP, "
2644                               "optname %d unsupported!",
2645                               getpid (), fd, fd, func_str, sid, sid, optname);
2646               break;
2647             }
2648           break;
2649         case SOL_IPV6:
2650           switch (optname)
2651             {
2652             case IPV6_V6ONLY:
2653               func_str = "vppcom_session_attr[SOL_IPV6,SET_V6ONLY]";
2654               if (VCOM_DEBUG > 1)
2655                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2656                               "sid %u (0x%x)",
2657                               getpid (), fd, fd, func_str, sid, sid);
2658               rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_V6ONLY,
2659                                         (void *) optval, &optlen);
2660               break;
2661             default:
2662               if (VCOM_DEBUG > 1)
2663                 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
2664                               "sid %u (0x%x), SOL_IPV6, "
2665                               "optname %d unsupported!",
2666                               getpid (), fd, fd, func_str, sid, sid, optname);
2667               break;
2668             }
2669           break;
2670         case SOL_SOCKET:
2671           switch (optname)
2672             {
2673             case SO_KEEPALIVE:
2674               func_str = "vppcom_session_attr[SOL_SOCKET,SET_KEEPALIVE]";
2675               if (VCOM_DEBUG > 1)
2676                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2677                               "sid %u (0x%x)",
2678                               getpid (), fd, fd, func_str, sid, sid);
2679               rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_KEEPALIVE,
2680                                         (void *) optval, &optlen);
2681               break;
2682             case SO_REUSEADDR:
2683               func_str = "vppcom_session_attr[SOL_SOCKET,SET_REUSEADDR]";
2684               if (VCOM_DEBUG > 1)
2685                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2686                               "sid %u (0x%x)",
2687                               getpid (), fd, fd, func_str, sid, sid);
2688               rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_REUSEADDR,
2689                                         (void *) optval, &optlen);
2690               break;
2691             case SO_BROADCAST:
2692               func_str = "vppcom_session_attr[SOL_SOCKET,SET_BROADCAST]";
2693               if (VCOM_DEBUG > 1)
2694                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2695                               "sid %u (0x%x)",
2696                               getpid (), fd, fd, func_str, sid, sid);
2697               rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_BROADCAST,
2698                                         (void *) optval, &optlen);
2699               break;
2700             default:
2701               if (VCOM_DEBUG > 1)
2702                 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
2703                               "sid %u (0x%x), SOL_SOCKET, "
2704                               "optname %d unsupported!",
2705                               getpid (), fd, fd, func_str, sid, sid, optname);
2706               break;
2707             }
2708           break;
2709         default:
2710           break;
2711         }
2712
2713       if (rv != VPPCOM_OK)
2714         {
2715           errno = -rv;
2716           rv = -1;
2717         }
2718     }
2719   else
2720     {
2721       func_str = "libc_setsockopt";
2722
2723       if (VCOM_DEBUG > 1)
2724         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): level %d, "
2725                       "optname %d, optval %p, optlen %d",
2726                       getpid (), fd, fd, func_str, level, optname,
2727                       optval, optlen);
2728
2729       rv = libc_setsockopt (fd, level, optname, optval, optlen);
2730     }
2731
2732   if (VCOM_DEBUG > 1)
2733     {
2734       if (rv < 0)
2735         {
2736           int errno_val = errno;
2737           perror (func_str);
2738           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2739                         "rv %d, errno = %d", getpid (), fd, fd,
2740                         func_str, rv, errno_val);
2741           errno = errno_val;
2742         }
2743       else
2744         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2745                       getpid (), fd, fd, rv, rv);
2746     }
2747   return rv;
2748 }
2749
2750 int
2751 listen (int fd, int n)
2752 {
2753   int rv;
2754   const char *func_str;
2755   u32 sid = vcom_sid_from_fd (fd);
2756
2757   if ((errno = -vcom_init ()))
2758     return -1;
2759
2760   if (sid != INVALID_SESSION_ID)
2761     {
2762       func_str = "vppcom_session_listen";
2763
2764       if (VCOM_DEBUG > 0)
2765         clib_warning
2766           ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), n %d",
2767            getpid (), fd, fd, func_str, sid, sid, n);
2768
2769       rv = vppcom_session_listen (sid, n);
2770       if (rv != VPPCOM_OK)
2771         {
2772           errno = -rv;
2773           rv = -1;
2774         }
2775     }
2776   else
2777     {
2778       func_str = "libc_listen";
2779
2780       if (VCOM_DEBUG > 0)
2781         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): n %d",
2782                       getpid (), fd, fd, func_str, n);
2783
2784       rv = libc_listen (fd, n);
2785     }
2786
2787   if (VCOM_DEBUG > 0)
2788     {
2789       if (rv < 0)
2790         {
2791           int errno_val = errno;
2792           perror (func_str);
2793           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2794                         "rv %d, errno = %d", getpid (), fd, fd,
2795                         func_str, rv, errno_val);
2796           errno = errno_val;
2797         }
2798       else
2799         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2800                       getpid (), fd, fd, rv, rv);
2801     }
2802   return rv;
2803 }
2804
2805 static inline int
2806 vcom_accept4 (int listen_fd, __SOCKADDR_ARG addr,
2807               socklen_t * __restrict addr_len, int flags)
2808 {
2809   int rv;
2810   const char *func_str;
2811   u32 listen_sid = vcom_sid_from_fd (listen_fd);
2812   int accept_sid;
2813
2814   if ((errno = -vcom_init ()))
2815     return -1;
2816
2817   if (listen_sid != INVALID_SESSION_ID)
2818     {
2819       vppcom_endpt_t ep;
2820       u8 src_addr[sizeof (struct sockaddr_in6)];
2821       ep.ip = src_addr;
2822
2823       func_str = "vppcom_session_accept";
2824
2825       if (VCOM_DEBUG > 0)
2826         clib_warning ("LDP<%d>: listen fd %d (0x%x): calling %s(): "
2827                       "listen sid %u (0x%x), ep %p, flags 0x%x",
2828                       getpid (), listen_fd, listen_fd, func_str,
2829                       listen_sid, listen_sid, ep, flags);
2830
2831       accept_sid = vppcom_session_accept (listen_sid, &ep, flags);
2832       if (accept_sid < 0)
2833         {
2834           errno = -accept_sid;
2835           rv = -1;
2836         }
2837       else
2838         {
2839           rv = vcom_copy_ep_to_sockaddr (addr, addr_len, &ep);
2840           if (rv != VPPCOM_OK)
2841             {
2842               (void) vppcom_session_close ((u32) accept_sid);
2843               errno = -rv;
2844               rv = -1;
2845             }
2846           else
2847             {
2848               func_str = "vcom_fd_from_sid";
2849               if (VCOM_DEBUG > 0)
2850                 clib_warning ("LDP<%d>: listen fd %d (0x%x): calling %s(): "
2851                               "accept sid %u (0x%x), ep %p, flags 0x%x",
2852                               getpid (), listen_fd, listen_fd,
2853                               func_str, accept_sid, accept_sid, ep, flags);
2854               rv = vcom_fd_from_sid ((u32) accept_sid);
2855               if (rv < 0)
2856                 {
2857                   (void) vppcom_session_close ((u32) accept_sid);
2858                   errno = -rv;
2859                   rv = -1;
2860                 }
2861             }
2862         }
2863     }
2864   else
2865     {
2866       func_str = "libc_accept4";
2867
2868       if (VCOM_DEBUG > 0)
2869         clib_warning ("LDP<%d>: listen fd %d (0x%x): calling %s(): "
2870                       "addr %p, addr_len %p, flags 0x%x",
2871                       getpid (), listen_fd, listen_fd, func_str,
2872                       addr, addr_len, flags);
2873
2874       rv = libc_accept4 (listen_fd, addr, addr_len, flags);
2875     }
2876
2877   if (VCOM_DEBUG > 0)
2878     {
2879       if (rv < 0)
2880         {
2881           int errno_val = errno;
2882           perror (func_str);
2883           clib_warning ("LDP<%d>: ERROR: listen fd %d (0x%x): %s() failed! "
2884                         "rv %d, errno = %d", getpid (), listen_fd,
2885                         listen_fd, func_str, rv, errno_val);
2886           errno = errno_val;
2887         }
2888       else
2889         clib_warning ("LDP<%d>: listen fd %d (0x%x): returning %d (0x%x)",
2890                       getpid (), listen_fd, listen_fd, rv, rv);
2891     }
2892   return rv;
2893 }
2894
2895 int
2896 accept4 (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len,
2897          int flags)
2898 {
2899   return vcom_accept4 (fd, addr, addr_len, flags);
2900 }
2901
2902 int
2903 accept (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
2904 {
2905   return vcom_accept4 (fd, addr, addr_len, 0);
2906 }
2907
2908 int
2909 shutdown (int fd, int how)
2910 {
2911   int rv;
2912   const char *func_str;
2913   u32 sid = vcom_sid_from_fd (fd);
2914
2915   if ((errno = -vcom_init ()))
2916     return -1;
2917
2918   if (sid != INVALID_SESSION_ID)
2919     {
2920       clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2921       errno = ENOSYS;
2922       rv = -1;
2923     }
2924   else
2925     {
2926       func_str = "libc_shutdown";
2927
2928       if (VCOM_DEBUG > 1)
2929         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): how %d",
2930                       getpid (), fd, fd, func_str, how);
2931
2932       rv = libc_shutdown (fd, how);
2933     }
2934
2935   if (VCOM_DEBUG > 1)
2936     {
2937       if (rv < 0)
2938         {
2939           int errno_val = errno;
2940           perror (func_str);
2941           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2942                         "rv %d, errno = %d", getpid (), fd, fd,
2943                         func_str, rv, errno_val);
2944           errno = errno_val;
2945         }
2946       else
2947         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2948                       getpid (), fd, fd, rv, rv);
2949     }
2950   return rv;
2951 }
2952
2953 int
2954 epoll_create1 (int flags)
2955 {
2956   const char *func_str;
2957   int rv;
2958
2959   if ((errno = -vcom_init ()))
2960     return -1;
2961
2962   func_str = "vppcom_epoll_create";
2963
2964   if (VCOM_DEBUG > 1)
2965     clib_warning ("LDP<%d>: calling %s()", getpid (), func_str);
2966
2967   rv = vppcom_epoll_create ();
2968
2969   if (PREDICT_FALSE (rv < 0))
2970     {
2971       errno = -rv;
2972       rv = -1;
2973     }
2974   else
2975     rv = vcom_fd_from_sid ((u32) rv);
2976
2977   if (VCOM_DEBUG > 1)
2978     {
2979       if (rv < 0)
2980         {
2981           int errno_val = errno;
2982           perror (func_str);
2983           clib_warning ("LDP<%d>: ERROR: %s() failed! "
2984                         "rv %d, errno = %d",
2985                         getpid (), func_str, rv, errno_val);
2986           errno = errno_val;
2987         }
2988       else
2989         clib_warning ("LDP<%d>: returning epfd %d (0x%x)", getpid (), rv, rv);
2990     }
2991   return rv;
2992 }
2993
2994 int
2995 epoll_create (int size)
2996 {
2997   return epoll_create1 (0);
2998 }
2999
3000 int
3001 epoll_ctl (int epfd, int op, int fd, struct epoll_event *event)
3002 {
3003   int rv;
3004   const char *func_str;
3005   u32 vep_idx = vcom_sid_from_fd (epfd);
3006
3007   if ((errno = -vcom_init ()))
3008     return -1;
3009
3010   if (vep_idx != INVALID_SESSION_ID)
3011     {
3012       u32 sid = vcom_sid_from_fd (fd);
3013
3014       if (sid != INVALID_SESSION_ID)
3015         {
3016           func_str = "vppcom_epoll_create";
3017
3018           if (VCOM_DEBUG > 1)
3019             clib_warning ("LDP<%d>: epfd %d (0x%x): calling %s(): "
3020                           "vep_idx %d (0x%x), op %d, sid %u (0x%x), event %p",
3021                           getpid (), epfd, epfd, func_str, vep_idx, vep_idx,
3022                           sid, sid, event);
3023
3024           rv = vppcom_epoll_ctl (vep_idx, op, sid, event);
3025           if (rv != VPPCOM_OK)
3026             {
3027               errno = -rv;
3028               rv = -1;
3029             }
3030         }
3031       else
3032         {
3033           int epfd;
3034           u32 size = sizeof (epfd);
3035
3036           func_str = "vppcom_session_attr[GET_LIBC_EPFD]";
3037           epfd = vppcom_session_attr (vep_idx, VPPCOM_ATTR_GET_LIBC_EPFD,
3038                                       0, 0);
3039           if (!epfd)
3040             {
3041               func_str = "libc_epoll_create1";
3042
3043               if (VCOM_DEBUG > 1)
3044                 clib_warning ("LDP<%d>: calling %s(): EPOLL_CLOEXEC",
3045                               getpid (), func_str);
3046
3047               epfd = libc_epoll_create1 (EPOLL_CLOEXEC);
3048               if (epfd < 0)
3049                 {
3050                   rv = epfd;
3051                   goto done;
3052                 }
3053
3054               func_str = "vppcom_session_attr[SET_LIBC_EPFD]";
3055               rv = vppcom_session_attr (vep_idx, VPPCOM_ATTR_SET_LIBC_EPFD,
3056                                         &epfd, &size);
3057               if (rv < 0)
3058                 {
3059                   errno = -rv;
3060                   rv = -1;
3061                   goto done;
3062                 }
3063             }
3064           else if (PREDICT_FALSE (epfd < 0))
3065             {
3066               errno = -epfd;
3067               rv = -1;
3068               goto done;
3069             }
3070
3071           rv = libc_epoll_ctl (epfd, op, fd, event);
3072         }
3073     }
3074   else
3075     {
3076       func_str = "libc_epoll_ctl";
3077
3078       if (VCOM_DEBUG > 1)
3079         clib_warning ("LDP<%d>: epfd %d (0x%x): calling %s(): "
3080                       "op %d, fd %d (0x%x), event %p",
3081                       getpid (), epfd, epfd, func_str, op, fd, fd, event);
3082
3083       rv = libc_epoll_ctl (epfd, op, fd, event);
3084     }
3085
3086 done:
3087   if (VCOM_DEBUG > 1)
3088     {
3089       if (rv < 0)
3090         {
3091           int errno_val = errno;
3092           perror (func_str);
3093           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
3094                         "rv %d, errno = %d", getpid (), fd, fd,
3095                         func_str, rv, errno_val);
3096           errno = errno_val;
3097         }
3098       else
3099         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
3100                       getpid (), fd, fd, rv, rv);
3101     }
3102   return rv;
3103 }
3104
3105 static inline int
3106 vcom_epoll_pwait (int epfd, struct epoll_event *events,
3107                   int maxevents, int timeout, const sigset_t * sigmask)
3108 {
3109   const char *func_str;
3110   int rv;
3111   double time_to_wait = (double) 0;
3112   double time_out, now = 0;
3113   u32 vep_idx = vcom_sid_from_fd (epfd);
3114   int libc_epfd;
3115
3116   if ((errno = -vcom_init ()))
3117     return -1;
3118
3119   if (PREDICT_FALSE (!events || (timeout < -1)))
3120     {
3121       errno = EFAULT;
3122       return -1;
3123     }
3124
3125   if (PREDICT_FALSE (vep_idx == INVALID_SESSION_ID))
3126     {
3127       clib_warning ("LDP<%d>: ERROR: epfd %d (0x%x): bad vep_idx %d (0x%x)!",
3128                     getpid (), epfd, epfd, vep_idx, vep_idx);
3129       errno = EBADFD;
3130       return -1;
3131     }
3132
3133   time_to_wait = ((timeout >= 0) ? (double) timeout / (double) 1000 : 0);
3134   time_out = clib_time_now (&vcom->clib_time) + time_to_wait;
3135
3136   func_str = "vppcom_session_attr[GET_LIBC_EPFD]";
3137   libc_epfd = vppcom_session_attr (vep_idx, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
3138   if (PREDICT_FALSE (libc_epfd < 0))
3139     {
3140       errno = -libc_epfd;
3141       rv = -1;
3142       goto done;
3143     }
3144
3145   if (VCOM_DEBUG > 2)
3146     clib_warning ("LDP<%d>: epfd %d (0x%x): vep_idx %d (0x%x), "
3147                   "libc_epfd %d (0x%x), events %p, maxevents %d, "
3148                   "timeout %d, sigmask %p", getpid (), epfd, epfd,
3149                   vep_idx, vep_idx, libc_epfd, libc_epfd, events,
3150                   maxevents, timeout, sigmask);
3151   do
3152     {
3153       if (!vcom->epoll_wait_vcl)
3154         {
3155           func_str = "vppcom_epoll_wait";
3156
3157           if (VCOM_DEBUG > 3)
3158             clib_warning ("LDP<%d>: epfd %d (0x%x): calling %s(): "
3159                           "vep_idx %d (0x%x), events %p, maxevents %d",
3160                           getpid (), epfd, epfd, func_str,
3161                           vep_idx, vep_idx, events, maxevents);
3162
3163           rv = vppcom_epoll_wait (vep_idx, events, maxevents, 0);
3164           if (rv > 0)
3165             {
3166               vcom->epoll_wait_vcl = 1;
3167               goto done;
3168             }
3169           else if (rv < 0)
3170             {
3171               errno = -rv;
3172               rv = -1;
3173               goto done;
3174             }
3175         }
3176       else
3177         vcom->epoll_wait_vcl = 0;
3178
3179       if (libc_epfd > 0)
3180         {
3181           func_str = "libc_epoll_pwait";
3182
3183           if (VCOM_DEBUG > 3)
3184             clib_warning ("LDP<%d>: epfd %d (0x%x): calling %s(): "
3185                           "libc_epfd %d (0x%x), events %p, "
3186                           "maxevents %d, sigmask %p",
3187                           getpid (), epfd, epfd, func_str,
3188                           libc_epfd, libc_epfd, events, maxevents, sigmask);
3189
3190           rv = libc_epoll_pwait (epfd, events, maxevents, 1, sigmask);
3191           if (rv != 0)
3192             goto done;
3193         }
3194
3195       if (timeout != -1)
3196         now = clib_time_now (&vcom->clib_time);
3197     }
3198   while (now < time_out);
3199
3200 done:
3201   if (VCOM_DEBUG > 3)
3202     {
3203       if (rv < 0)
3204         {
3205           int errno_val = errno;
3206           perror (func_str);
3207           clib_warning ("LDP<%d>: ERROR: epfd %d (0x%x): %s() failed! "
3208                         "rv %d, errno = %d", getpid (), epfd, epfd,
3209                         func_str, rv, errno_val);
3210           errno = errno_val;
3211         }
3212       else
3213         clib_warning ("LDP<%d>: epfd %d (0x%x): returning %d (0x%x)",
3214                       getpid (), epfd, epfd, rv, rv);
3215     }
3216   return rv;
3217 }
3218
3219 int
3220 epoll_pwait (int epfd, struct epoll_event *events,
3221              int maxevents, int timeout, const sigset_t * sigmask)
3222 {
3223   return vcom_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
3224 }
3225
3226 int
3227 epoll_wait (int epfd, struct epoll_event *events, int maxevents, int timeout)
3228 {
3229   return vcom_epoll_pwait (epfd, events, maxevents, timeout, NULL);
3230 }
3231
3232 int
3233 poll (struct pollfd *fds, nfds_t nfds, int timeout)
3234 {
3235   const char *func_str = __func__;
3236   int rv, i, n_libc_fds, n_revents;
3237   u32 sid;
3238   vcl_poll_t *vp;
3239   double wait_for_time;
3240
3241   if (VCOM_DEBUG > 3)
3242     clib_warning ("LDP<%d>: fds %p, nfds %d, timeout %d",
3243                   getpid (), fds, nfds, timeout);
3244
3245   if (timeout >= 0)
3246     wait_for_time = (f64) timeout / 1000;
3247   else
3248     wait_for_time = -1;
3249
3250   n_libc_fds = 0;
3251   for (i = 0; i < nfds; i++)
3252     {
3253       if (fds[i].fd >= 0)
3254         {
3255           if (VCOM_DEBUG > 3)
3256             clib_warning ("LDP<%d>: fds[%d].fd %d (0x%0x), .events = 0x%x, "
3257                           ".revents = 0x%x", getpid (), i, fds[i].fd,
3258                           fds[i].fd, fds[i].events, fds[i].revents);
3259
3260           sid = vcom_sid_from_fd (fds[i].fd);
3261           if (sid != INVALID_SESSION_ID)
3262             {
3263               fds[i].fd = -fds[i].fd;
3264               vec_add2 (vcom->vcl_poll, vp, 1);
3265               vp->fds_ndx = i;
3266               vp->sid = sid;
3267               vp->events = fds[i].events;
3268 #ifdef __USE_XOPEN2K
3269               if (fds[i].events & POLLRDNORM)
3270                 vp->events |= POLLIN;
3271               if (fds[i].events & POLLWRNORM)
3272                 vp->events |= POLLOUT;
3273 #endif
3274               vp->revents = &fds[i].revents;
3275             }
3276           else
3277             n_libc_fds++;
3278         }
3279     }
3280
3281   n_revents = 0;
3282   do
3283     {
3284       if (vec_len (vcom->vcl_poll))
3285         {
3286           func_str = "vppcom_poll";
3287
3288           if (VCOM_DEBUG > 3)
3289             clib_warning ("LDP<%d>: calling %s(): "
3290                           "vcl_poll %p, n_sids %u (0x%x): "
3291                           "n_libc_fds %u",
3292                           getpid (), func_str, vcom->vcl_poll,
3293                           vec_len (vcom->vcl_poll), vec_len (vcom->vcl_poll),
3294                           n_libc_fds);
3295
3296           rv = vppcom_poll (vcom->vcl_poll, vec_len (vcom->vcl_poll), 0);
3297           if (rv < 0)
3298             {
3299               errno = -rv;
3300               rv = -1;
3301               goto done;
3302             }
3303           else
3304             n_revents += rv;
3305         }
3306
3307       if (n_libc_fds)
3308         {
3309           func_str = "libc_poll";
3310
3311           if (VCOM_DEBUG > 3)
3312             clib_warning ("LDP<%d>: calling %s(): fds %p, nfds %u: n_sids %u",
3313                           getpid (), fds, nfds, vec_len (vcom->vcl_poll));
3314
3315           rv = libc_poll (fds, nfds, 0);
3316           if (rv < 0)
3317             goto done;
3318           else
3319             n_revents += rv;
3320         }
3321
3322       if (n_revents)
3323         {
3324           rv = n_revents;
3325           goto done;
3326         }
3327     }
3328   while ((wait_for_time == -1) ||
3329          (clib_time_now (&vcom->clib_time) < wait_for_time));
3330   rv = 0;
3331
3332 done:
3333   vec_foreach (vp, vcom->vcl_poll)
3334   {
3335     fds[vp->fds_ndx].fd = -fds[vp->fds_ndx].fd;
3336 #ifdef __USE_XOPEN2K
3337     if ((fds[vp->fds_ndx].revents & POLLIN) &&
3338         (fds[vp->fds_ndx].events & POLLRDNORM))
3339       fds[vp->fds_ndx].revents |= POLLRDNORM;
3340     if ((fds[vp->fds_ndx].revents & POLLOUT) &&
3341         (fds[vp->fds_ndx].events & POLLWRNORM))
3342       fds[vp->fds_ndx].revents |= POLLWRNORM;
3343 #endif
3344   }
3345   vec_reset_length (vcom->vcl_poll);
3346
3347   if (VCOM_DEBUG > 3)
3348     {
3349       if (rv < 0)
3350         {
3351           int errno_val = errno;
3352           perror (func_str);
3353           clib_warning ("LDP<%d>: ERROR: %s() failed! "
3354                         "rv %d, errno = %d", getpid (),
3355                         func_str, rv, errno_val);
3356           errno = errno_val;
3357         }
3358       else
3359         {
3360           clib_warning ("LDP<%d>: returning %d (0x%x): n_sids %u, "
3361                         "n_libc_fds %d", getpid (), rv, rv,
3362                         vec_len (vcom->vcl_poll), n_libc_fds);
3363
3364           for (i = 0; i < nfds; i++)
3365             {
3366               if (fds[i].fd >= 0)
3367                 {
3368                   if (VCOM_DEBUG > 3)
3369                     clib_warning ("LDP<%d>: fds[%d].fd %d (0x%0x), "
3370                                   ".events = 0x%x, .revents = 0x%x",
3371                                   getpid (), i, fds[i].fd, fds[i].fd,
3372                                   fds[i].events, fds[i].revents);
3373                 }
3374             }
3375         }
3376     }
3377
3378   return rv;
3379 }
3380
3381 #ifdef USE_GNU
3382 int
3383 ppoll (struct pollfd *fds, nfds_t nfds,
3384        const struct timespec *timeout, const sigset_t * sigmask)
3385 {
3386   if ((errno = -vcom_init ()))
3387     return -1;
3388
3389   clib_warning ("LDP<%d>: LDP-TBD", getpid ());
3390   errno = ENOSYS;
3391
3392
3393   return -1;
3394 }
3395 #endif
3396
3397 void CONSTRUCTOR_ATTRIBUTE vcom_constructor (void);
3398
3399 void DESTRUCTOR_ATTRIBUTE vcom_destructor (void);
3400
3401 /*
3402  * This function is called when the library is loaded
3403  */
3404 void
3405 vcom_constructor (void)
3406 {
3407   swrap_constructor ();
3408   if (vcom_init () != 0)
3409     fprintf (stderr, "\nLDP<%d>: ERROR: vcom_constructor: failed!\n",
3410              getpid ());
3411   else
3412     clib_warning ("LDP<%d>: VCOM constructor: done!\n", getpid ());
3413 }
3414
3415 /*
3416  * This function is called when the library is unloaded
3417  */
3418 void
3419 vcom_destructor (void)
3420 {
3421   swrap_destructor ();
3422   if (vcom->init)
3423     {
3424       vppcom_app_destroy ();
3425       vcom->init = 0;
3426     }
3427
3428   /* Don't use clib_warning() here because that calls writev()
3429    * which will call vcom_init().
3430    */
3431   printf ("%s:%d: LDP<%d>: VCOM destructor: done!\n",
3432           __func__, __LINE__, getpid ());
3433 }
3434
3435
3436 /*
3437  * fd.io coding-style-patch-verification: ON
3438  *
3439  * Local Variables:
3440  * eval: (c-set-style "gnu")
3441  * End:
3442  */