VCL/LD_PRELOAD: Fix unfiltered debug output.
[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 = 0, 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 i, rv = 0;
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       func_str = __func__;
1223
1224       clib_warning ("LDP<%d>: LDP-TBD", getpid ());
1225       errno = ENOSYS;
1226       rv = -1;
1227     }
1228   else
1229     {
1230       func_str = "libc_socket";
1231
1232       if (VCOM_DEBUG > 1)
1233         clib_warning ("LDP<%d>: : calling %s()", getpid (), func_str);
1234
1235       rv = libc_socket (domain, type, protocol);
1236     }
1237
1238   if (VCOM_DEBUG > 1)
1239     {
1240       if (rv < 0)
1241         {
1242           int errno_val = errno;
1243           perror (func_str);
1244           clib_warning ("LDP<%d>: ERROR: %s() failed! "
1245                         "rv %d, errno = %d",
1246                         getpid (), func_str, rv, errno_val);
1247           errno = errno_val;
1248         }
1249       else
1250         clib_warning ("LDP<%d>: : returning fd %d (0x%x)", getpid (), rv, rv);
1251     }
1252   return rv;
1253 }
1254
1255 int
1256 bind (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len)
1257 {
1258   int rv;
1259   const char *func_str;
1260   u32 sid = vcom_sid_from_fd (fd);
1261
1262   if ((errno = -vcom_init ()))
1263     return -1;
1264
1265   if (sid != INVALID_SESSION_ID)
1266     {
1267       vppcom_endpt_t ep;
1268
1269       func_str = "vppcom_session_bind";
1270
1271       ep.vrf = VPPCOM_VRF_DEFAULT;
1272       switch (addr->sa_family)
1273         {
1274         case AF_INET:
1275           if (len != sizeof (struct sockaddr_in))
1276             {
1277               clib_warning
1278                 ("LDP<%d>: ERROR: fd %d (0x%x): sid %u (0x%x): Invalid "
1279                  "AF_INET addr len %u!", getpid (), fd, fd, sid, sid, len);
1280               errno = EINVAL;
1281               rv = -1;
1282               goto done;
1283             }
1284           ep.is_ip4 = VPPCOM_IS_IP4;
1285           ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
1286           ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
1287           break;
1288
1289         case AF_INET6:
1290           if (len != sizeof (struct sockaddr_in6))
1291             {
1292               clib_warning
1293                 ("LDP<%d>: ERROR: fd %d (0x%x): sid %u (0x%x): Invalid "
1294                  "AF_INET6 addr len %u!", getpid (), fd, fd, sid, sid, len);
1295               errno = EINVAL;
1296               rv = -1;
1297               goto done;
1298             }
1299           ep.is_ip4 = VPPCOM_IS_IP6;
1300           ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1301           ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
1302           break;
1303
1304         default:
1305           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): sid %u (0x%x): "
1306                         "Unsupported address family %u!",
1307                         getpid (), fd, fd, sid, sid, addr->sa_family);
1308           errno = EAFNOSUPPORT;
1309           rv = -1;
1310           goto done;
1311         }
1312       if (VCOM_DEBUG > 0)
1313         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), "
1314                       "addr %p, len %u",
1315                       getpid (), fd, fd, func_str, sid, sid, addr, len);
1316
1317       rv = vppcom_session_bind (sid, &ep);
1318       if (rv != VPPCOM_OK)
1319         {
1320           errno = -rv;
1321           rv = -1;
1322         }
1323     }
1324   else
1325     {
1326       func_str = "libc_bind";
1327
1328       if (VCOM_DEBUG > 0)
1329         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1330                       "addr %p, len %u",
1331                       getpid (), fd, fd, func_str, addr, len);
1332
1333       rv = libc_bind (fd, addr, len);
1334     }
1335
1336 done:
1337   if (VCOM_DEBUG > 0)
1338     {
1339       if (rv < 0)
1340         {
1341           int errno_val = errno;
1342           perror (func_str);
1343           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1344                         "rv %d, errno = %d", getpid (), fd, fd,
1345                         func_str, rv, errno_val);
1346           errno = errno_val;
1347         }
1348       else
1349         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1350                       getpid (), fd, fd, rv, rv);
1351     }
1352   return rv;
1353 }
1354
1355 static inline int
1356 vcom_copy_ep_to_sockaddr (__SOCKADDR_ARG addr, socklen_t * __restrict len,
1357                           vppcom_endpt_t * ep)
1358 {
1359   int rv = 0;
1360   int sa_len, copy_len;
1361
1362   if ((errno = -vcom_init ()))
1363     return -1;
1364
1365   if (addr && len && ep)
1366     {
1367       addr->sa_family = (ep->is_ip4 == VPPCOM_IS_IP4) ? AF_INET : AF_INET6;
1368       switch (addr->sa_family)
1369         {
1370         case AF_INET:
1371           ((struct sockaddr_in *) addr)->sin_port = ep->port;
1372           if (*len > sizeof (struct sockaddr_in))
1373             *len = sizeof (struct sockaddr_in);
1374           sa_len = sizeof (struct sockaddr_in) - sizeof (struct in_addr);
1375           copy_len = *len - sa_len;
1376           if (copy_len > 0)
1377             memcpy (&((struct sockaddr_in *) addr)->sin_addr, ep->ip,
1378                     copy_len);
1379           break;
1380
1381         case AF_INET6:
1382           ((struct sockaddr_in6 *) addr)->sin6_port = ep->port;
1383           if (*len > sizeof (struct sockaddr_in6))
1384             *len = sizeof (struct sockaddr_in6);
1385           sa_len = sizeof (struct sockaddr_in6) - sizeof (struct in6_addr);
1386           copy_len = *len - sa_len;
1387           if (copy_len > 0)
1388             memcpy (((struct sockaddr_in6 *) addr)->sin6_addr.
1389                     __in6_u.__u6_addr8, ep->ip, copy_len);
1390           break;
1391
1392         default:
1393           /* Not possible */
1394           rv = -EAFNOSUPPORT;
1395           break;
1396         }
1397     }
1398   return rv;
1399 }
1400
1401 int
1402 getsockname (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len)
1403 {
1404   int rv;
1405   const char *func_str;
1406   u32 sid = vcom_sid_from_fd (fd);
1407
1408   if ((errno = -vcom_init ()))
1409     return -1;
1410
1411   if (sid != INVALID_SESSION_ID)
1412     {
1413       vppcom_endpt_t ep;
1414       u8 addr_buf[sizeof (struct in6_addr)];
1415       u32 size = sizeof (ep);
1416
1417       ep.ip = addr_buf;
1418       func_str = "vppcom_session_attr[GET_LCL_ADDR]";
1419
1420       if (VCOM_DEBUG > 2)
1421         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), "
1422                       "addr %p, len %u",
1423                       getpid (), fd, fd, func_str, sid, sid, addr, len);
1424
1425       rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_LCL_ADDR, &ep, &size);
1426       if (rv != VPPCOM_OK)
1427         {
1428           errno = -rv;
1429           rv = -1;
1430         }
1431       else
1432         {
1433           rv = vcom_copy_ep_to_sockaddr (addr, len, &ep);
1434           if (rv != VPPCOM_OK)
1435             {
1436               errno = -rv;
1437               rv = -1;
1438             }
1439         }
1440     }
1441   else
1442     {
1443       func_str = "libc_getsockname";
1444
1445       if (VCOM_DEBUG > 2)
1446         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1447                       "addr %p, len %u",
1448                       getpid (), fd, fd, func_str, addr, len);
1449
1450       rv = libc_getsockname (fd, addr, len);
1451     }
1452
1453   if (VCOM_DEBUG > 2)
1454     {
1455       if (rv < 0)
1456         {
1457           int errno_val = errno;
1458           perror (func_str);
1459           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1460                         "rv %d, errno = %d", getpid (), fd, fd,
1461                         func_str, rv, errno_val);
1462           errno = errno_val;
1463         }
1464       else
1465         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1466                       getpid (), fd, fd, rv, rv);
1467     }
1468   return rv;
1469 }
1470
1471 int
1472 connect (int fd, __CONST_SOCKADDR_ARG addr, socklen_t len)
1473 {
1474   int rv;
1475   const char *func_str = __func__;
1476   u32 sid = vcom_sid_from_fd (fd);
1477
1478   if ((errno = -vcom_init ()))
1479     return -1;
1480
1481   if (!addr)
1482     {
1483       clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): NULL addr, len %u",
1484                     getpid (), fd, fd, len);
1485       errno = EINVAL;
1486       rv = -1;
1487       goto done;
1488     }
1489
1490   if (sid != INVALID_SESSION_ID)
1491     {
1492       vppcom_endpt_t ep;
1493
1494       func_str = "vppcom_session_connect";
1495
1496       ep.vrf = VPPCOM_VRF_DEFAULT;
1497       switch (addr->sa_family)
1498         {
1499         case AF_INET:
1500           if (len != sizeof (struct sockaddr_in))
1501             {
1502               clib_warning
1503                 ("LDP<%d>: fd %d (0x%x): ERROR sid %u (0x%x): Invalid "
1504                  "AF_INET addr len %u!", getpid (), fd, fd, sid, sid, len);
1505               errno = EINVAL;
1506               rv = -1;
1507               goto done;
1508             }
1509           ep.is_ip4 = VPPCOM_IS_IP4;
1510           ep.ip = (u8 *) & ((const struct sockaddr_in *) addr)->sin_addr;
1511           ep.port = (u16) ((const struct sockaddr_in *) addr)->sin_port;
1512           break;
1513
1514         case AF_INET6:
1515           if (len != sizeof (struct sockaddr_in6))
1516             {
1517               clib_warning
1518                 ("LDP<%d>: fd %d (0x%x): ERROR sid %u (0x%x): Invalid "
1519                  "AF_INET6 addr len %u!", getpid (), fd, fd, sid, sid, len);
1520               errno = EINVAL;
1521               rv = -1;
1522               goto done;
1523             }
1524           ep.is_ip4 = VPPCOM_IS_IP6;
1525           ep.ip = (u8 *) & ((const struct sockaddr_in6 *) addr)->sin6_addr;
1526           ep.port = (u16) ((const struct sockaddr_in6 *) addr)->sin6_port;
1527           break;
1528
1529         default:
1530           clib_warning ("LDP<%d>: fd %d (0x%x): ERROR sid %u (0x%x): "
1531                         "Unsupported address family %u!",
1532                         getpid (), fd, fd, sid, sid, addr->sa_family);
1533           errno = EAFNOSUPPORT;
1534           rv = -1;
1535           goto done;
1536         }
1537       if (VCOM_DEBUG > 0)
1538         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x) "
1539                       "addr %p len %u",
1540                       getpid (), fd, fd, func_str, sid, sid, addr, len);
1541
1542       rv = vppcom_session_connect (sid, &ep);
1543       if (rv != VPPCOM_OK)
1544         {
1545           errno = -rv;
1546           rv = -1;
1547         }
1548     }
1549   else
1550     {
1551       func_str = "libc_connect";
1552
1553       if (VCOM_DEBUG > 0)
1554         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
1555                       "addr %p, len %u",
1556                       getpid (), fd, fd, func_str, addr, len);
1557
1558       rv = libc_connect (fd, addr, len);
1559     }
1560
1561 done:
1562   if (VCOM_DEBUG > 0)
1563     {
1564       if (rv < 0)
1565         {
1566           int errno_val = errno;
1567           perror (func_str);
1568           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
1569                         "rv %d, errno = %d", getpid (), fd, fd,
1570                         func_str, rv, errno_val);
1571           errno = errno_val;
1572         }
1573       else
1574         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
1575                       getpid (), fd, fd, rv, rv);
1576     }
1577   return rv;
1578 }
1579
1580 int
1581 getpeername (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict len)
1582 {
1583   int rv;
1584   const char *func_str;
1585   u32 sid = vcom_sid_from_fd (fd);
1586
1587   if ((errno = -vcom_init ()))
1588     return -1;
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       func_str = __func__;
2179
2180       clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2181       errno = ENOSYS;
2182       size = -1;
2183     }
2184   else
2185     {
2186       func_str = "libc_sendmsg";
2187
2188       if (VCOM_DEBUG > 2)
2189         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2190                       "message %p, flags 0x%x",
2191                       getpid (), fd, fd, func_str, message, flags);
2192
2193       size = libc_sendmsg (fd, message, flags);
2194     }
2195
2196   if (VCOM_DEBUG > 2)
2197     {
2198       if (size < 0)
2199         {
2200           int errno_val = errno;
2201           perror (func_str);
2202           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2203                         "rv %d, errno = %d", getpid (), fd, fd,
2204                         func_str, size, errno_val);
2205           errno = errno_val;
2206         }
2207       else
2208         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2209                       getpid (), fd, fd, size, size);
2210     }
2211   return size;
2212 }
2213
2214 #ifdef USE_GNU
2215 int
2216 sendmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags)
2217 {
2218   ssize_t size;
2219   const char *func_str;
2220   u32 sid = vcom_sid_from_fd (fd);
2221
2222   if ((errno = -vcom_init ()))
2223     return -1;
2224
2225   if (sid != INVALID_SESSION_ID)
2226     {
2227       clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2228       errno = ENOSYS;
2229       size = -1;
2230     }
2231   else
2232     {
2233       func_str = "libc_sendmmsg";
2234
2235       if (VCOM_DEBUG > 2)
2236         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2237                       "vmessages %p, vlen %u, flags 0x%x",
2238                       getpid (), fd, fd, func_str, vmessages, vlen, flags);
2239
2240       size = libc_sendmmsg (fd, vmessages, vlen, flags);
2241     }
2242
2243   if (VCOM_DEBUG > 2)
2244     {
2245       if (size < 0)
2246         {
2247           int errno_val = errno;
2248           perror (func_str);
2249           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2250                         "rv %d, errno = %d", getpid (), fd, fd,
2251                         func_str, size, errno_val);
2252           errno = errno_val;
2253         }
2254       else
2255         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2256                       getpid (), fd, fd, size, size);
2257     }
2258   return size;
2259 }
2260 #endif
2261
2262 ssize_t
2263 recvmsg (int fd, struct msghdr * message, int flags)
2264 {
2265   ssize_t size;
2266   const char *func_str;
2267   u32 sid = vcom_sid_from_fd (fd);
2268
2269   if ((errno = -vcom_init ()))
2270     return -1;
2271
2272   if (sid != INVALID_SESSION_ID)
2273     {
2274       func_str = __func__;
2275
2276       clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2277       errno = ENOSYS;
2278       size = -1;
2279     }
2280   else
2281     {
2282       func_str = "libc_recvmsg";
2283
2284       if (VCOM_DEBUG > 2)
2285         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2286                       "message %p, flags 0x%x",
2287                       getpid (), fd, fd, func_str, message, flags);
2288
2289       size = libc_recvmsg (fd, message, flags);
2290     }
2291
2292   if (VCOM_DEBUG > 2)
2293     {
2294       if (size < 0)
2295         {
2296           int errno_val = errno;
2297           perror (func_str);
2298           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2299                         "rv %d, errno = %d", getpid (), fd, fd,
2300                         func_str, size, errno_val);
2301           errno = errno_val;
2302         }
2303       else
2304         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2305                       getpid (), fd, fd, size, size);
2306     }
2307   return size;
2308 }
2309
2310 #ifdef USE_GNU
2311 int
2312 recvmmsg (int fd, struct mmsghdr *vmessages,
2313           unsigned int vlen, int flags, struct timespec *tmo)
2314 {
2315   ssize_t size;
2316   const char *func_str;
2317   u32 sid = vcom_sid_from_fd (fd);
2318
2319   if ((errno = -vcom_init ()))
2320     return -1;
2321
2322   if (sid != INVALID_SESSION_ID)
2323     {
2324       clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2325       errno = ENOSYS;
2326       size = -1;
2327     }
2328   else
2329     {
2330       func_str = "libc_recvmmsg";
2331
2332       if (VCOM_DEBUG > 2)
2333         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2334                       "vmessages %p, vlen %u, flags 0x%x, tmo %p",
2335                       getpid (), fd, fd, func_str, vmessages, vlen,
2336                       flags, tmo);
2337
2338       size = libc_recvmmsg (fd, vmessages, vlen, flags, tmo);
2339     }
2340
2341   if (VCOM_DEBUG > 2)
2342     {
2343       if (size < 0)
2344         {
2345           int errno_val = errno;
2346           perror (func_str);
2347           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2348                         "rv %d, errno = %d", getpid (), fd, fd,
2349                         func_str, size, errno_val);
2350           errno = errno_val;
2351         }
2352       else
2353         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2354                       getpid (), fd, fd, size, size);
2355     }
2356   return size;
2357 }
2358 #endif
2359
2360 int
2361 getsockopt (int fd, int level, int optname,
2362             void *__restrict optval, socklen_t * __restrict optlen)
2363 {
2364   int rv;
2365   const char *func_str = __func__;
2366   u32 sid = vcom_sid_from_fd (fd);
2367   u32 buflen = optlen ? (u32) * optlen : 0;
2368
2369   if ((errno = -vcom_init ()))
2370     return -1;
2371
2372   if (sid != INVALID_SESSION_ID)
2373     {
2374       rv = -EOPNOTSUPP;
2375
2376       switch (level)
2377         {
2378         case SOL_TCP:
2379           switch (optname)
2380             {
2381             case TCP_NODELAY:
2382               func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_NODELAY]";
2383               if (VCOM_DEBUG > 1)
2384                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2385                               "sid %u (0x%x)",
2386                               getpid (), fd, fd, func_str, sid, sid);
2387               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_NODELAY,
2388                                         optval, optlen);
2389               break;
2390             case TCP_MAXSEG:
2391               func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_USER_MSS]";
2392               if (VCOM_DEBUG > 1)
2393                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2394                               "sid %u (0x%x)",
2395                               getpid (), fd, fd, func_str, sid, sid);
2396               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_USER_MSS,
2397                                         optval, optlen);
2398               break;
2399             case TCP_KEEPIDLE:
2400               func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_KEEPIDLE]";
2401               if (VCOM_DEBUG > 1)
2402                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2403                               "sid %u (0x%x)",
2404                               getpid (), fd, fd, func_str, sid, sid);
2405               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_KEEPIDLE,
2406                                         optval, optlen);
2407               break;
2408             case TCP_KEEPINTVL:
2409               func_str = "vppcom_session_attr[SOL_TCP,GET_TCP_KEEPINTVL]";
2410               if (VCOM_DEBUG > 1)
2411                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2412                               "sid %u (0x%x), SOL_TCP",
2413                               getpid (), fd, fd, func_str, sid, sid);
2414               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TCP_KEEPINTVL,
2415                                         optval, optlen);
2416               break;
2417             case TCP_INFO:
2418               if (optval && optlen && (*optlen == sizeof (struct tcp_info)))
2419                 {
2420                   if (VCOM_DEBUG > 1)
2421                     clib_warning ("LDP<%d>: fd %d (0x%x): sid %u (0x%x), "
2422                                   "SOL_TCP, TCP_INFO, optval %p, "
2423                                   "optlen %d: #LDP-NOP#",
2424                                   getpid (), fd, fd, sid, sid,
2425                                   optval, *optlen);
2426                   memset (optval, 0, *optlen);
2427                   rv = VPPCOM_OK;
2428                 }
2429               else
2430                 rv = -EFAULT;
2431               break;
2432             default:
2433               if (VCOM_DEBUG > 1)
2434                 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
2435                               "sid %u (0x%x), SOL_TCP, "
2436                               "optname %d unsupported!",
2437                               getpid (), fd, fd, func_str, sid, sid, optname);
2438               break;
2439             }
2440           break;
2441         case SOL_IPV6:
2442           switch (optname)
2443             {
2444             case IPV6_V6ONLY:
2445               func_str = "vppcom_session_attr[SOL_IPV6,GET_V6ONLY]";
2446               if (VCOM_DEBUG > 1)
2447                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2448                               "sid %u (0x%x)",
2449                               getpid (), fd, fd, func_str, sid, sid);
2450               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_V6ONLY,
2451                                         optval, optlen);
2452               break;
2453             default:
2454               if (VCOM_DEBUG > 1)
2455                 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
2456                               "sid %u (0x%x), SOL_IPV6, "
2457                               "optname %d unsupported!",
2458                               getpid (), fd, fd, func_str, sid, sid, optname);
2459               break;
2460             }
2461           break;
2462         case SOL_SOCKET:
2463           switch (optname)
2464             {
2465             case SO_ACCEPTCONN:
2466               func_str = "vppcom_session_attr[SOL_SOCKET,GET_ACCEPTCONN]";
2467               if (VCOM_DEBUG > 1)
2468                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2469                               "sid %u (0x%x)",
2470                               getpid (), fd, fd, func_str, sid, sid);
2471               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_LISTEN,
2472                                         optval, optlen);
2473               break;
2474             case SO_KEEPALIVE:
2475               func_str = "vppcom_session_attr[SOL_SOCKET,GET_KEEPALIVE]";
2476               if (VCOM_DEBUG > 1)
2477                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2478                               "sid %u (0x%x)",
2479                               getpid (), fd, fd, func_str, sid, sid);
2480               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_KEEPALIVE,
2481                                         optval, optlen);
2482               break;
2483             case SO_PROTOCOL:
2484               func_str = "vppcom_session_attr[SOL_SOCKET,GET_PROTOCOL]";
2485               if (VCOM_DEBUG > 1)
2486                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2487                               "sid %u (0x%x)",
2488                               getpid (), fd, fd, func_str, sid, sid);
2489               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_PROTOCOL,
2490                                         optval, optlen);
2491               *(int *) optval = *(int *) optval ? SOCK_DGRAM : SOCK_STREAM;
2492               break;
2493             case SO_SNDBUF:
2494               func_str = "vppcom_session_attr[SOL_SOCKET,GET_TX_FIFO_LEN]";
2495               if (VCOM_DEBUG > 1)
2496                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2497                               "sid %u (0x%x), optlen %d",
2498                               getpid (), fd, fd, func_str, sid, sid, buflen);
2499               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_TX_FIFO_LEN,
2500                                         optval, optlen);
2501               break;
2502             case SO_RCVBUF:
2503               func_str = "vppcom_session_attr[SOL_SOCKET,GET_RX_FIFO_LEN]";
2504               if (VCOM_DEBUG > 1)
2505                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2506                               "sid %u (0x%x), optlen %d",
2507                               getpid (), fd, fd, func_str, sid, sid, buflen);
2508               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_RX_FIFO_LEN,
2509                                         optval, optlen);
2510               break;
2511             case SO_REUSEADDR:
2512               func_str = "vppcom_session_attr[SOL_SOCKET,GET_REUSEADDR]";
2513               if (VCOM_DEBUG > 1)
2514                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2515                               "sid %u (0x%x)",
2516                               getpid (), fd, fd, func_str, sid, sid);
2517               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_REUSEADDR,
2518                                         optval, optlen);
2519               break;
2520             case SO_BROADCAST:
2521               func_str = "vppcom_session_attr[SOL_SOCKET,GET_BROADCAST]";
2522               if (VCOM_DEBUG > 1)
2523                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2524                               "sid %u (0x%x)",
2525                               getpid (), fd, fd, func_str, sid, sid);
2526               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_BROADCAST,
2527                                         optval, optlen);
2528               break;
2529             case SO_ERROR:
2530               func_str = "vppcom_session_attr[SOL_SOCKET,GET_ERROR]";
2531               if (VCOM_DEBUG > 1)
2532                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2533                               "sid %u (0x%x)",
2534                               getpid (), fd, fd, func_str, sid, sid);
2535               rv = vppcom_session_attr (sid, VPPCOM_ATTR_GET_ERROR,
2536                                         optval, optlen);
2537               break;
2538             default:
2539               if (VCOM_DEBUG > 1)
2540                 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
2541                               "sid %u (0x%x), SOL_SOCKET, "
2542                               "optname %d unsupported!",
2543                               getpid (), fd, fd, func_str, sid, sid, optname);
2544               break;
2545             }
2546           break;
2547         default:
2548           break;
2549         }
2550
2551       if (rv != VPPCOM_OK)
2552         {
2553           errno = -rv;
2554           rv = -1;
2555         }
2556     }
2557   else
2558     {
2559       func_str = "libc_getsockopt";
2560
2561       if (VCOM_DEBUG > 1)
2562         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): level %d, "
2563                       "optname %d, optval %p, optlen %d",
2564                       getpid (), fd, fd, func_str, level, optname,
2565                       optval, optlen);
2566
2567       rv = libc_getsockopt (fd, level, optname, optval, optlen);
2568     }
2569
2570   if (VCOM_DEBUG > 1)
2571     {
2572       if (rv < 0)
2573         {
2574           int errno_val = errno;
2575           perror (func_str);
2576           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2577                         "rv %d, errno = %d", getpid (), fd, fd,
2578                         func_str, rv, errno_val);
2579           errno = errno_val;
2580         }
2581       else
2582         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2583                       getpid (), fd, fd, rv, rv);
2584     }
2585   return rv;
2586 }
2587
2588 int
2589 setsockopt (int fd, int level, int optname,
2590             const void *optval, socklen_t optlen)
2591 {
2592   int rv;
2593   const char *func_str = __func__;
2594   u32 sid = vcom_sid_from_fd (fd);
2595
2596   if ((errno = -vcom_init ()))
2597     return -1;
2598
2599   if (sid != INVALID_SESSION_ID)
2600     {
2601       rv = -EOPNOTSUPP;
2602
2603       switch (level)
2604         {
2605         case SOL_TCP:
2606           switch (optname)
2607             {
2608             case TCP_NODELAY:
2609               func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_NODELAY]";
2610               if (VCOM_DEBUG > 1)
2611                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2612                               "sid %u (0x%x)",
2613                               getpid (), fd, fd, func_str, sid, sid);
2614               rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_NODELAY,
2615                                         (void *) optval, &optlen);
2616               break;
2617             case TCP_MAXSEG:
2618               func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_USER_MSS]";
2619               if (VCOM_DEBUG > 1)
2620                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2621                               "sid %u (0x%x)",
2622                               getpid (), fd, fd, func_str, sid, sid);
2623               rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_USER_MSS,
2624                                         (void *) optval, &optlen);
2625               break;
2626             case TCP_KEEPIDLE:
2627               func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_KEEPIDLE]";
2628               if (VCOM_DEBUG > 1)
2629                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2630                               "sid %u (0x%x)",
2631                               getpid (), fd, fd, func_str, sid, sid);
2632               rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_KEEPIDLE,
2633                                         (void *) optval, &optlen);
2634               break;
2635             case TCP_KEEPINTVL:
2636               func_str = "vppcom_session_attr[SOL_TCP,SET_TCP_KEEPINTVL]";
2637               if (VCOM_DEBUG > 1)
2638                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2639                               "sid %u (0x%x), SOL_TCP",
2640                               getpid (), fd, fd, func_str, sid, sid);
2641               rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_TCP_KEEPINTVL,
2642                                         (void *) optval, &optlen);
2643               break;
2644             default:
2645               if (VCOM_DEBUG > 1)
2646                 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
2647                               "sid %u (0x%x), SOL_TCP, "
2648                               "optname %d unsupported!",
2649                               getpid (), fd, fd, func_str, sid, sid, optname);
2650               break;
2651             }
2652           break;
2653         case SOL_IPV6:
2654           switch (optname)
2655             {
2656             case IPV6_V6ONLY:
2657               func_str = "vppcom_session_attr[SOL_IPV6,SET_V6ONLY]";
2658               if (VCOM_DEBUG > 1)
2659                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2660                               "sid %u (0x%x)",
2661                               getpid (), fd, fd, func_str, sid, sid);
2662               rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_V6ONLY,
2663                                         (void *) optval, &optlen);
2664               break;
2665             default:
2666               if (VCOM_DEBUG > 1)
2667                 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
2668                               "sid %u (0x%x), SOL_IPV6, "
2669                               "optname %d unsupported!",
2670                               getpid (), fd, fd, func_str, sid, sid, optname);
2671               break;
2672             }
2673           break;
2674         case SOL_SOCKET:
2675           switch (optname)
2676             {
2677             case SO_KEEPALIVE:
2678               func_str = "vppcom_session_attr[SOL_SOCKET,SET_KEEPALIVE]";
2679               if (VCOM_DEBUG > 1)
2680                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2681                               "sid %u (0x%x)",
2682                               getpid (), fd, fd, func_str, sid, sid);
2683               rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_KEEPALIVE,
2684                                         (void *) optval, &optlen);
2685               break;
2686             case SO_REUSEADDR:
2687               func_str = "vppcom_session_attr[SOL_SOCKET,SET_REUSEADDR]";
2688               if (VCOM_DEBUG > 1)
2689                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2690                               "sid %u (0x%x)",
2691                               getpid (), fd, fd, func_str, sid, sid);
2692               rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_REUSEADDR,
2693                                         (void *) optval, &optlen);
2694               break;
2695             case SO_BROADCAST:
2696               func_str = "vppcom_session_attr[SOL_SOCKET,SET_BROADCAST]";
2697               if (VCOM_DEBUG > 1)
2698                 clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): "
2699                               "sid %u (0x%x)",
2700                               getpid (), fd, fd, func_str, sid, sid);
2701               rv = vppcom_session_attr (sid, VPPCOM_ATTR_SET_BROADCAST,
2702                                         (void *) optval, &optlen);
2703               break;
2704             default:
2705               if (VCOM_DEBUG > 1)
2706                 clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s(): "
2707                               "sid %u (0x%x), SOL_SOCKET, "
2708                               "optname %d unsupported!",
2709                               getpid (), fd, fd, func_str, sid, sid, optname);
2710               break;
2711             }
2712           break;
2713         default:
2714           break;
2715         }
2716
2717       if (rv != VPPCOM_OK)
2718         {
2719           errno = -rv;
2720           rv = -1;
2721         }
2722     }
2723   else
2724     {
2725       func_str = "libc_setsockopt";
2726
2727       if (VCOM_DEBUG > 1)
2728         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): level %d, "
2729                       "optname %d, optval %p, optlen %d",
2730                       getpid (), fd, fd, func_str, level, optname,
2731                       optval, optlen);
2732
2733       rv = libc_setsockopt (fd, level, optname, optval, optlen);
2734     }
2735
2736   if (VCOM_DEBUG > 1)
2737     {
2738       if (rv < 0)
2739         {
2740           int errno_val = errno;
2741           perror (func_str);
2742           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2743                         "rv %d, errno = %d", getpid (), fd, fd,
2744                         func_str, rv, errno_val);
2745           errno = errno_val;
2746         }
2747       else
2748         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2749                       getpid (), fd, fd, rv, rv);
2750     }
2751   return rv;
2752 }
2753
2754 int
2755 listen (int fd, int n)
2756 {
2757   int rv;
2758   const char *func_str;
2759   u32 sid = vcom_sid_from_fd (fd);
2760
2761   if ((errno = -vcom_init ()))
2762     return -1;
2763
2764   if (sid != INVALID_SESSION_ID)
2765     {
2766       func_str = "vppcom_session_listen";
2767
2768       if (VCOM_DEBUG > 0)
2769         clib_warning
2770           ("LDP<%d>: fd %d (0x%x): calling %s(): sid %u (0x%x), n %d",
2771            getpid (), fd, fd, func_str, sid, sid, n);
2772
2773       rv = vppcom_session_listen (sid, n);
2774       if (rv != VPPCOM_OK)
2775         {
2776           errno = -rv;
2777           rv = -1;
2778         }
2779     }
2780   else
2781     {
2782       func_str = "libc_listen";
2783
2784       if (VCOM_DEBUG > 0)
2785         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): n %d",
2786                       getpid (), fd, fd, func_str, n);
2787
2788       rv = libc_listen (fd, n);
2789     }
2790
2791   if (VCOM_DEBUG > 0)
2792     {
2793       if (rv < 0)
2794         {
2795           int errno_val = errno;
2796           perror (func_str);
2797           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2798                         "rv %d, errno = %d", getpid (), fd, fd,
2799                         func_str, rv, errno_val);
2800           errno = errno_val;
2801         }
2802       else
2803         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2804                       getpid (), fd, fd, rv, rv);
2805     }
2806   return rv;
2807 }
2808
2809 static inline int
2810 vcom_accept4 (int listen_fd, __SOCKADDR_ARG addr,
2811               socklen_t * __restrict addr_len, int flags)
2812 {
2813   int rv;
2814   const char *func_str;
2815   u32 listen_sid = vcom_sid_from_fd (listen_fd);
2816   int accept_sid;
2817
2818   if ((errno = -vcom_init ()))
2819     return -1;
2820
2821   if (listen_sid != INVALID_SESSION_ID)
2822     {
2823       vppcom_endpt_t ep;
2824       u8 src_addr[sizeof (struct sockaddr_in6)];
2825       memset (&ep, 0, sizeof (ep));
2826       ep.ip = src_addr;
2827
2828       func_str = "vppcom_session_accept";
2829
2830       if (VCOM_DEBUG > 0)
2831         clib_warning ("LDP<%d>: listen fd %d (0x%x): calling %s(): "
2832                       "listen sid %u (0x%x), ep %p, flags 0x%x",
2833                       getpid (), listen_fd, listen_fd, func_str,
2834                       listen_sid, listen_sid, ep, flags);
2835
2836       accept_sid = vppcom_session_accept (listen_sid, &ep, flags);
2837       if (accept_sid < 0)
2838         {
2839           errno = -accept_sid;
2840           rv = -1;
2841         }
2842       else
2843         {
2844           rv = vcom_copy_ep_to_sockaddr (addr, addr_len, &ep);
2845           if (rv != VPPCOM_OK)
2846             {
2847               (void) vppcom_session_close ((u32) accept_sid);
2848               errno = -rv;
2849               rv = -1;
2850             }
2851           else
2852             {
2853               func_str = "vcom_fd_from_sid";
2854               if (VCOM_DEBUG > 0)
2855                 clib_warning ("LDP<%d>: listen fd %d (0x%x): calling %s(): "
2856                               "accept sid %u (0x%x), ep %p, flags 0x%x",
2857                               getpid (), listen_fd, listen_fd,
2858                               func_str, accept_sid, accept_sid, ep, flags);
2859               rv = vcom_fd_from_sid ((u32) accept_sid);
2860               if (rv < 0)
2861                 {
2862                   (void) vppcom_session_close ((u32) accept_sid);
2863                   errno = -rv;
2864                   rv = -1;
2865                 }
2866             }
2867         }
2868     }
2869   else
2870     {
2871       func_str = "libc_accept4";
2872
2873       if (VCOM_DEBUG > 0)
2874         clib_warning ("LDP<%d>: listen fd %d (0x%x): calling %s(): "
2875                       "addr %p, addr_len %p, flags 0x%x",
2876                       getpid (), listen_fd, listen_fd, func_str,
2877                       addr, addr_len, flags);
2878
2879       rv = libc_accept4 (listen_fd, addr, addr_len, flags);
2880     }
2881
2882   if (VCOM_DEBUG > 0)
2883     {
2884       if (rv < 0)
2885         {
2886           int errno_val = errno;
2887           perror (func_str);
2888           clib_warning ("LDP<%d>: ERROR: listen fd %d (0x%x): %s() failed! "
2889                         "rv %d, errno = %d", getpid (), listen_fd,
2890                         listen_fd, func_str, rv, errno_val);
2891           errno = errno_val;
2892         }
2893       else
2894         clib_warning ("LDP<%d>: listen fd %d (0x%x): returning %d (0x%x)",
2895                       getpid (), listen_fd, listen_fd, rv, rv);
2896     }
2897   return rv;
2898 }
2899
2900 int
2901 accept4 (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len,
2902          int flags)
2903 {
2904   return vcom_accept4 (fd, addr, addr_len, flags);
2905 }
2906
2907 int
2908 accept (int fd, __SOCKADDR_ARG addr, socklen_t * __restrict addr_len)
2909 {
2910   return vcom_accept4 (fd, addr, addr_len, 0);
2911 }
2912
2913 int
2914 shutdown (int fd, int how)
2915 {
2916   int rv;
2917   const char *func_str;
2918   u32 sid = vcom_sid_from_fd (fd);
2919
2920   if ((errno = -vcom_init ()))
2921     return -1;
2922
2923   if (sid != INVALID_SESSION_ID)
2924     {
2925       func_str = __func__;
2926
2927       clib_warning ("LDP<%d>: LDP-TBD", getpid ());
2928       errno = ENOSYS;
2929       rv = -1;
2930     }
2931   else
2932     {
2933       func_str = "libc_shutdown";
2934
2935       if (VCOM_DEBUG > 1)
2936         clib_warning ("LDP<%d>: fd %d (0x%x): calling %s(): how %d",
2937                       getpid (), fd, fd, func_str, how);
2938
2939       rv = libc_shutdown (fd, how);
2940     }
2941
2942   if (VCOM_DEBUG > 1)
2943     {
2944       if (rv < 0)
2945         {
2946           int errno_val = errno;
2947           perror (func_str);
2948           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
2949                         "rv %d, errno = %d", getpid (), fd, fd,
2950                         func_str, rv, errno_val);
2951           errno = errno_val;
2952         }
2953       else
2954         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
2955                       getpid (), fd, fd, rv, rv);
2956     }
2957   return rv;
2958 }
2959
2960 int
2961 epoll_create1 (int flags)
2962 {
2963   const char *func_str;
2964   int rv;
2965
2966   if ((errno = -vcom_init ()))
2967     return -1;
2968
2969   func_str = "vppcom_epoll_create";
2970
2971   if (VCOM_DEBUG > 1)
2972     clib_warning ("LDP<%d>: calling %s()", getpid (), func_str);
2973
2974   rv = vppcom_epoll_create ();
2975
2976   if (PREDICT_FALSE (rv < 0))
2977     {
2978       errno = -rv;
2979       rv = -1;
2980     }
2981   else
2982     rv = vcom_fd_from_sid ((u32) rv);
2983
2984   if (VCOM_DEBUG > 1)
2985     {
2986       if (rv < 0)
2987         {
2988           int errno_val = errno;
2989           perror (func_str);
2990           clib_warning ("LDP<%d>: ERROR: %s() failed! "
2991                         "rv %d, errno = %d",
2992                         getpid (), func_str, rv, errno_val);
2993           errno = errno_val;
2994         }
2995       else
2996         clib_warning ("LDP<%d>: returning epfd %d (0x%x)", getpid (), rv, rv);
2997     }
2998   return rv;
2999 }
3000
3001 int
3002 epoll_create (int size)
3003 {
3004   return epoll_create1 (0);
3005 }
3006
3007 int
3008 epoll_ctl (int epfd, int op, int fd, struct epoll_event *event)
3009 {
3010   int rv;
3011   const char *func_str;
3012   u32 vep_idx = vcom_sid_from_fd (epfd);
3013
3014   if ((errno = -vcom_init ()))
3015     return -1;
3016
3017   if (vep_idx != INVALID_SESSION_ID)
3018     {
3019       u32 sid = vcom_sid_from_fd (fd);
3020
3021       if (sid != INVALID_SESSION_ID)
3022         {
3023           func_str = "vppcom_epoll_create";
3024
3025           if (VCOM_DEBUG > 1)
3026             clib_warning ("LDP<%d>: epfd %d (0x%x): calling %s(): "
3027                           "vep_idx %d (0x%x), op %d, sid %u (0x%x), event %p",
3028                           getpid (), epfd, epfd, func_str, vep_idx, vep_idx,
3029                           sid, sid, event);
3030
3031           rv = vppcom_epoll_ctl (vep_idx, op, sid, event);
3032           if (rv != VPPCOM_OK)
3033             {
3034               errno = -rv;
3035               rv = -1;
3036             }
3037         }
3038       else
3039         {
3040           int epfd;
3041           u32 size = sizeof (epfd);
3042
3043           func_str = "vppcom_session_attr[GET_LIBC_EPFD]";
3044           epfd = vppcom_session_attr (vep_idx, VPPCOM_ATTR_GET_LIBC_EPFD,
3045                                       0, 0);
3046           if (!epfd)
3047             {
3048               func_str = "libc_epoll_create1";
3049
3050               if (VCOM_DEBUG > 1)
3051                 clib_warning ("LDP<%d>: calling %s(): EPOLL_CLOEXEC",
3052                               getpid (), func_str);
3053
3054               epfd = libc_epoll_create1 (EPOLL_CLOEXEC);
3055               if (epfd < 0)
3056                 {
3057                   rv = epfd;
3058                   goto done;
3059                 }
3060
3061               func_str = "vppcom_session_attr[SET_LIBC_EPFD]";
3062               rv = vppcom_session_attr (vep_idx, VPPCOM_ATTR_SET_LIBC_EPFD,
3063                                         &epfd, &size);
3064               if (rv < 0)
3065                 {
3066                   errno = -rv;
3067                   rv = -1;
3068                   goto done;
3069                 }
3070             }
3071           else if (PREDICT_FALSE (epfd < 0))
3072             {
3073               errno = -epfd;
3074               rv = -1;
3075               goto done;
3076             }
3077
3078           rv = libc_epoll_ctl (epfd, op, fd, event);
3079         }
3080     }
3081   else
3082     {
3083       func_str = "libc_epoll_ctl";
3084
3085       if (VCOM_DEBUG > 1)
3086         clib_warning ("LDP<%d>: epfd %d (0x%x): calling %s(): "
3087                       "op %d, fd %d (0x%x), event %p",
3088                       getpid (), epfd, epfd, func_str, op, fd, fd, event);
3089
3090       rv = libc_epoll_ctl (epfd, op, fd, event);
3091     }
3092
3093 done:
3094   if (VCOM_DEBUG > 1)
3095     {
3096       if (rv < 0)
3097         {
3098           int errno_val = errno;
3099           perror (func_str);
3100           clib_warning ("LDP<%d>: ERROR: fd %d (0x%x): %s() failed! "
3101                         "rv %d, errno = %d", getpid (), fd, fd,
3102                         func_str, rv, errno_val);
3103           errno = errno_val;
3104         }
3105       else
3106         clib_warning ("LDP<%d>: fd %d (0x%x): returning %d (0x%x)",
3107                       getpid (), fd, fd, rv, rv);
3108     }
3109   return rv;
3110 }
3111
3112 static inline int
3113 vcom_epoll_pwait (int epfd, struct epoll_event *events,
3114                   int maxevents, int timeout, const sigset_t * sigmask)
3115 {
3116   const char *func_str;
3117   int rv = 0;
3118   double time_to_wait = (double) 0;
3119   double time_out, now = 0;
3120   u32 vep_idx = vcom_sid_from_fd (epfd);
3121   int libc_epfd;
3122
3123   if ((errno = -vcom_init ()))
3124     return -1;
3125
3126   if (PREDICT_FALSE (!events || (timeout < -1)))
3127     {
3128       errno = EFAULT;
3129       return -1;
3130     }
3131
3132   if (PREDICT_FALSE (vep_idx == INVALID_SESSION_ID))
3133     {
3134       clib_warning ("LDP<%d>: ERROR: epfd %d (0x%x): bad vep_idx %d (0x%x)!",
3135                     getpid (), epfd, epfd, vep_idx, vep_idx);
3136       errno = EBADFD;
3137       return -1;
3138     }
3139
3140   time_to_wait = ((timeout >= 0) ? (double) timeout / (double) 1000 : 0);
3141   time_out = clib_time_now (&vcom->clib_time) + time_to_wait;
3142
3143   func_str = "vppcom_session_attr[GET_LIBC_EPFD]";
3144   libc_epfd = vppcom_session_attr (vep_idx, VPPCOM_ATTR_GET_LIBC_EPFD, 0, 0);
3145   if (PREDICT_FALSE (libc_epfd < 0))
3146     {
3147       errno = -libc_epfd;
3148       rv = -1;
3149       goto done;
3150     }
3151
3152   if (VCOM_DEBUG > 2)
3153     clib_warning ("LDP<%d>: epfd %d (0x%x): vep_idx %d (0x%x), "
3154                   "libc_epfd %d (0x%x), events %p, maxevents %d, "
3155                   "timeout %d, sigmask %p", getpid (), epfd, epfd,
3156                   vep_idx, vep_idx, libc_epfd, libc_epfd, events,
3157                   maxevents, timeout, sigmask);
3158   do
3159     {
3160       if (!vcom->epoll_wait_vcl)
3161         {
3162           func_str = "vppcom_epoll_wait";
3163
3164           if (VCOM_DEBUG > 3)
3165             clib_warning ("LDP<%d>: epfd %d (0x%x): calling %s(): "
3166                           "vep_idx %d (0x%x), events %p, maxevents %d",
3167                           getpid (), epfd, epfd, func_str,
3168                           vep_idx, vep_idx, events, maxevents);
3169
3170           rv = vppcom_epoll_wait (vep_idx, events, maxevents, 0);
3171           if (rv > 0)
3172             {
3173               vcom->epoll_wait_vcl = 1;
3174               goto done;
3175             }
3176           else if (rv < 0)
3177             {
3178               errno = -rv;
3179               rv = -1;
3180               goto done;
3181             }
3182         }
3183       else
3184         vcom->epoll_wait_vcl = 0;
3185
3186       if (libc_epfd > 0)
3187         {
3188           func_str = "libc_epoll_pwait";
3189
3190           if (VCOM_DEBUG > 3)
3191             clib_warning ("LDP<%d>: epfd %d (0x%x): calling %s(): "
3192                           "libc_epfd %d (0x%x), events %p, "
3193                           "maxevents %d, sigmask %p",
3194                           getpid (), epfd, epfd, func_str,
3195                           libc_epfd, libc_epfd, events, maxevents, sigmask);
3196
3197           rv = libc_epoll_pwait (epfd, events, maxevents, 1, sigmask);
3198           if (rv != 0)
3199             goto done;
3200         }
3201
3202       if (timeout != -1)
3203         now = clib_time_now (&vcom->clib_time);
3204     }
3205   while (now < time_out);
3206
3207 done:
3208   if (VCOM_DEBUG > 3)
3209     {
3210       if (rv < 0)
3211         {
3212           int errno_val = errno;
3213           perror (func_str);
3214           clib_warning ("LDP<%d>: ERROR: epfd %d (0x%x): %s() failed! "
3215                         "rv %d, errno = %d", getpid (), epfd, epfd,
3216                         func_str, rv, errno_val);
3217           errno = errno_val;
3218         }
3219       else
3220         clib_warning ("LDP<%d>: epfd %d (0x%x): returning %d (0x%x)",
3221                       getpid (), epfd, epfd, rv, rv);
3222     }
3223   return rv;
3224 }
3225
3226 int
3227 epoll_pwait (int epfd, struct epoll_event *events,
3228              int maxevents, int timeout, const sigset_t * sigmask)
3229 {
3230   return vcom_epoll_pwait (epfd, events, maxevents, timeout, sigmask);
3231 }
3232
3233 int
3234 epoll_wait (int epfd, struct epoll_event *events, int maxevents, int timeout)
3235 {
3236   return vcom_epoll_pwait (epfd, events, maxevents, timeout, NULL);
3237 }
3238
3239 int
3240 poll (struct pollfd *fds, nfds_t nfds, int timeout)
3241 {
3242   const char *func_str = __func__;
3243   int rv, i, n_libc_fds, n_revents;
3244   u32 sid;
3245   vcl_poll_t *vp;
3246   double wait_for_time;
3247
3248   if (VCOM_DEBUG > 3)
3249     clib_warning ("LDP<%d>: fds %p, nfds %d, timeout %d",
3250                   getpid (), fds, nfds, timeout);
3251
3252   if (timeout >= 0)
3253     wait_for_time = (f64) timeout / 1000;
3254   else
3255     wait_for_time = -1;
3256
3257   n_libc_fds = 0;
3258   for (i = 0; i < nfds; i++)
3259     {
3260       if (fds[i].fd >= 0)
3261         {
3262           if (VCOM_DEBUG > 3)
3263             clib_warning ("LDP<%d>: fds[%d].fd %d (0x%0x), .events = 0x%x, "
3264                           ".revents = 0x%x", getpid (), i, fds[i].fd,
3265                           fds[i].fd, fds[i].events, fds[i].revents);
3266
3267           sid = vcom_sid_from_fd (fds[i].fd);
3268           if (sid != INVALID_SESSION_ID)
3269             {
3270               fds[i].fd = -fds[i].fd;
3271               vec_add2 (vcom->vcl_poll, vp, 1);
3272               vp->fds_ndx = i;
3273               vp->sid = sid;
3274               vp->events = fds[i].events;
3275 #ifdef __USE_XOPEN2K
3276               if (fds[i].events & POLLRDNORM)
3277                 vp->events |= POLLIN;
3278               if (fds[i].events & POLLWRNORM)
3279                 vp->events |= POLLOUT;
3280 #endif
3281               vp->revents = &fds[i].revents;
3282             }
3283           else
3284             n_libc_fds++;
3285         }
3286     }
3287
3288   n_revents = 0;
3289   do
3290     {
3291       if (vec_len (vcom->vcl_poll))
3292         {
3293           func_str = "vppcom_poll";
3294
3295           if (VCOM_DEBUG > 3)
3296             clib_warning ("LDP<%d>: calling %s(): "
3297                           "vcl_poll %p, n_sids %u (0x%x): "
3298                           "n_libc_fds %u",
3299                           getpid (), func_str, vcom->vcl_poll,
3300                           vec_len (vcom->vcl_poll), vec_len (vcom->vcl_poll),
3301                           n_libc_fds);
3302
3303           rv = vppcom_poll (vcom->vcl_poll, vec_len (vcom->vcl_poll), 0);
3304           if (rv < 0)
3305             {
3306               errno = -rv;
3307               rv = -1;
3308               goto done;
3309             }
3310           else
3311             n_revents += rv;
3312         }
3313
3314       if (n_libc_fds)
3315         {
3316           func_str = "libc_poll";
3317
3318           if (VCOM_DEBUG > 3)
3319             clib_warning ("LDP<%d>: calling %s(): fds %p, nfds %u: n_sids %u",
3320                           getpid (), fds, nfds, vec_len (vcom->vcl_poll));
3321
3322           rv = libc_poll (fds, nfds, 0);
3323           if (rv < 0)
3324             goto done;
3325           else
3326             n_revents += rv;
3327         }
3328
3329       if (n_revents)
3330         {
3331           rv = n_revents;
3332           goto done;
3333         }
3334     }
3335   while ((wait_for_time == -1) ||
3336          (clib_time_now (&vcom->clib_time) < wait_for_time));
3337   rv = 0;
3338
3339 done:
3340   vec_foreach (vp, vcom->vcl_poll)
3341   {
3342     fds[vp->fds_ndx].fd = -fds[vp->fds_ndx].fd;
3343 #ifdef __USE_XOPEN2K
3344     if ((fds[vp->fds_ndx].revents & POLLIN) &&
3345         (fds[vp->fds_ndx].events & POLLRDNORM))
3346       fds[vp->fds_ndx].revents |= POLLRDNORM;
3347     if ((fds[vp->fds_ndx].revents & POLLOUT) &&
3348         (fds[vp->fds_ndx].events & POLLWRNORM))
3349       fds[vp->fds_ndx].revents |= POLLWRNORM;
3350 #endif
3351   }
3352   vec_reset_length (vcom->vcl_poll);
3353
3354   if (VCOM_DEBUG > 3)
3355     {
3356       if (rv < 0)
3357         {
3358           int errno_val = errno;
3359           perror (func_str);
3360           clib_warning ("LDP<%d>: ERROR: %s() failed! "
3361                         "rv %d, errno = %d", getpid (),
3362                         func_str, rv, errno_val);
3363           errno = errno_val;
3364         }
3365       else
3366         {
3367           clib_warning ("LDP<%d>: returning %d (0x%x): n_sids %u, "
3368                         "n_libc_fds %d", getpid (), rv, rv,
3369                         vec_len (vcom->vcl_poll), n_libc_fds);
3370
3371           for (i = 0; i < nfds; i++)
3372             {
3373               if (fds[i].fd >= 0)
3374                 {
3375                   if (VCOM_DEBUG > 3)
3376                     clib_warning ("LDP<%d>: fds[%d].fd %d (0x%0x), "
3377                                   ".events = 0x%x, .revents = 0x%x",
3378                                   getpid (), i, fds[i].fd, fds[i].fd,
3379                                   fds[i].events, fds[i].revents);
3380                 }
3381             }
3382         }
3383     }
3384
3385   return rv;
3386 }
3387
3388 #ifdef USE_GNU
3389 int
3390 ppoll (struct pollfd *fds, nfds_t nfds,
3391        const struct timespec *timeout, const sigset_t * sigmask)
3392 {
3393   if ((errno = -vcom_init ()))
3394     return -1;
3395
3396   clib_warning ("LDP<%d>: LDP-TBD", getpid ());
3397   errno = ENOSYS;
3398
3399
3400   return -1;
3401 }
3402 #endif
3403
3404 void CONSTRUCTOR_ATTRIBUTE vcom_constructor (void);
3405
3406 void DESTRUCTOR_ATTRIBUTE vcom_destructor (void);
3407
3408 /*
3409  * This function is called when the library is loaded
3410  */
3411 void
3412 vcom_constructor (void)
3413 {
3414   swrap_constructor ();
3415   if (vcom_init () != 0)
3416     fprintf (stderr, "\nLDP<%d>: ERROR: vcom_constructor: failed!\n",
3417              getpid ());
3418   else
3419     clib_warning ("LDP<%d>: VCOM constructor: done!\n", getpid ());
3420 }
3421
3422 /*
3423  * This function is called when the library is unloaded
3424  */
3425 void
3426 vcom_destructor (void)
3427 {
3428   swrap_destructor ();
3429   if (vcom->init)
3430     {
3431       vppcom_app_destroy ();
3432       vcom->init = 0;
3433     }
3434
3435   /* Don't use clib_warning() here because that calls writev()
3436    * which will call vcom_init().
3437    */
3438   printf ("%s:%d: LDP<%d>: VCOM destructor: done!\n",
3439           __func__, __LINE__, getpid ());
3440 }
3441
3442
3443 /*
3444  * fd.io coding-style-patch-verification: ON
3445  *
3446  * Local Variables:
3447  * eval: (c-set-style "gnu")
3448  * End:
3449  */