session: update due to clib_socket refactoring
[vpp.git] / src / vppinfra / socket.c
1 /*
2  * Copyright (c) 2015 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 /*
16   Copyright (c) 2001, 2002, 2003, 2005 Eliot Dresselhaus
17
18   Permission is hereby granted, free of charge, to any person obtaining
19   a copy of this software and associated documentation files (the
20   "Software"), to deal in the Software without restriction, including
21   without limitation the rights to use, copy, modify, merge, publish,
22   distribute, sublicense, and/or sell copies of the Software, and to
23   permit persons to whom the Software is furnished to do so, subject to
24   the following conditions:
25
26   The above copyright notice and this permission notice shall be
27   included in all copies or substantial portions of the Software.
28
29   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33   LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34   OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35   WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 */
37
38 #include <stdio.h>
39 #include <string.h>             /* strchr */
40 #define __USE_GNU
41 #define _GNU_SOURCE
42 #include <sys/types.h>
43 #include <sys/socket.h>
44 #include <sys/un.h>
45 #include <sys/stat.h>
46 #include <netinet/in.h>
47 #include <arpa/inet.h>
48 #include <netdb.h>
49 #include <unistd.h>
50 #include <fcntl.h>
51
52 #include <vppinfra/mem.h>
53 #include <vppinfra/vec.h>
54 #include <vppinfra/socket.h>
55 #include <vppinfra/linux/netns.h>
56 #include <vppinfra/format.h>
57 #include <vppinfra/error.h>
58
59 #ifndef __GLIBC__
60 /* IPPORT_USERRESERVED is not part of musl libc. */
61 #define IPPORT_USERRESERVED 5000
62 #endif
63
64 __clib_export void
65 clib_socket_tx_add_formatted (clib_socket_t * s, char *fmt, ...)
66 {
67   va_list va;
68   va_start (va, fmt);
69   clib_socket_tx_add_va_formatted (s, fmt, &va);
70   va_end (va);
71 }
72
73 /* Return and bind to an unused port. */
74 static word
75 find_free_port (word sock)
76 {
77   word port;
78
79   for (port = IPPORT_USERRESERVED; port < 1 << 16; port++)
80     {
81       struct sockaddr_in a;
82
83       clib_memset (&a, 0, sizeof (a));  /* Warnings be gone */
84
85       a.sin_family = PF_INET;
86       a.sin_addr.s_addr = INADDR_ANY;
87       a.sin_port = htons (port);
88
89       if (bind (sock, (struct sockaddr *) &a, sizeof (a)) >= 0)
90         break;
91     }
92
93   return port < 1 << 16 ? port : -1;
94 }
95
96 static clib_error_t *
97 default_socket_write (clib_socket_t * s)
98 {
99   clib_error_t *err = 0;
100   word written = 0;
101   word fd = 0;
102   word tx_len;
103
104   fd = s->fd;
105
106   /* Map standard input to standard output.
107      Typically, fd is a socket for which read/write both work. */
108   if (fd == 0)
109     fd = 1;
110
111   tx_len = vec_len (s->tx_buffer);
112   written = write (fd, s->tx_buffer, tx_len);
113
114   /* Ignore certain errors. */
115   if (written < 0 && !unix_error_is_fatal (errno))
116     written = 0;
117
118   /* A "real" error occurred. */
119   if (written < 0)
120     {
121       err = clib_error_return_unix (0, "write %wd bytes (fd %d, '%s')",
122                                     tx_len, s->fd, s->config);
123       vec_free (s->tx_buffer);
124       goto done;
125     }
126
127   /* Reclaim the transmitted part of the tx buffer on successful writes. */
128   else if (written > 0)
129     {
130       if (written == tx_len)
131         vec_set_len (s->tx_buffer, 0);
132       else
133         vec_delete (s->tx_buffer, written, 0);
134     }
135
136   /* If a non-fatal error occurred AND
137      the buffer is full, then we must free it. */
138   else if (written == 0 && tx_len > 64 * 1024)
139     {
140       vec_free (s->tx_buffer);
141     }
142
143 done:
144   return err;
145 }
146
147 static clib_error_t *
148 default_socket_read (clib_socket_t * sock, int n_bytes)
149 {
150   word fd, n_read;
151   u8 *buf;
152
153   /* RX side of socket is down once end of file is reached. */
154   if (sock->rx_end_of_file)
155     return 0;
156
157   fd = sock->fd;
158
159   n_bytes = clib_max (n_bytes, 4096);
160   vec_add2 (sock->rx_buffer, buf, n_bytes);
161
162   if ((n_read = read (fd, buf, n_bytes)) < 0)
163     {
164       n_read = 0;
165
166       /* Ignore certain errors. */
167       if (!unix_error_is_fatal (errno))
168         goto non_fatal;
169
170       return clib_error_return_unix (0, "read %d bytes (fd %d, '%s')",
171                                      n_bytes, sock->fd, sock->config);
172     }
173
174   /* Other side closed the socket. */
175   if (n_read == 0)
176     sock->rx_end_of_file = 1;
177
178 non_fatal:
179   vec_inc_len (sock->rx_buffer, n_read - n_bytes);
180
181   return 0;
182 }
183
184 static clib_error_t *
185 default_socket_close (clib_socket_t * s)
186 {
187   if (close (s->fd) < 0)
188     return clib_error_return_unix (0, "close (fd %d, %s)", s->fd, s->config);
189   return 0;
190 }
191
192 static clib_error_t *
193 default_socket_sendmsg (clib_socket_t * s, void *msg, int msglen,
194                         int fds[], int num_fds)
195 {
196   struct msghdr mh = { 0 };
197   struct iovec iov[1];
198   char ctl[CMSG_SPACE (sizeof (int) * num_fds)];
199   int rv;
200
201   iov[0].iov_base = msg;
202   iov[0].iov_len = msglen;
203   mh.msg_iov = iov;
204   mh.msg_iovlen = 1;
205
206   if (num_fds > 0)
207     {
208       struct cmsghdr *cmsg;
209       clib_memset (&ctl, 0, sizeof (ctl));
210       mh.msg_control = ctl;
211       mh.msg_controllen = sizeof (ctl);
212       cmsg = CMSG_FIRSTHDR (&mh);
213       cmsg->cmsg_len = CMSG_LEN (sizeof (int) * num_fds);
214       cmsg->cmsg_level = SOL_SOCKET;
215       cmsg->cmsg_type = SCM_RIGHTS;
216       memcpy (CMSG_DATA (cmsg), fds, sizeof (int) * num_fds);
217     }
218   rv = sendmsg (s->fd, &mh, 0);
219   if (rv < 0)
220     return clib_error_return_unix (0, "sendmsg");
221   return 0;
222 }
223
224
225 static clib_error_t *
226 default_socket_recvmsg (clib_socket_t * s, void *msg, int msglen,
227                         int fds[], int num_fds)
228 {
229 #ifdef CLIB_LINUX
230   char ctl[CMSG_SPACE (sizeof (int) * num_fds) +
231            CMSG_SPACE (sizeof (struct ucred))];
232   struct ucred *cr = 0;
233 #else
234   char ctl[CMSG_SPACE (sizeof (int) * num_fds)];
235 #endif
236   struct msghdr mh = { 0 };
237   struct iovec iov[1];
238   ssize_t size;
239   struct cmsghdr *cmsg;
240
241   iov[0].iov_base = msg;
242   iov[0].iov_len = msglen;
243   mh.msg_iov = iov;
244   mh.msg_iovlen = 1;
245   mh.msg_control = ctl;
246   mh.msg_controllen = sizeof (ctl);
247
248   clib_memset (ctl, 0, sizeof (ctl));
249
250   /* receive the incoming message */
251   size = recvmsg (s->fd, &mh, 0);
252   if (size != msglen)
253     {
254       return (size == 0) ? clib_error_return (0, "disconnected") :
255         clib_error_return_unix (0, "recvmsg: malformed message (fd %d, '%s')",
256                                 s->fd, s->config);
257     }
258
259   cmsg = CMSG_FIRSTHDR (&mh);
260   while (cmsg)
261     {
262       if (cmsg->cmsg_level == SOL_SOCKET)
263         {
264 #ifdef CLIB_LINUX
265           if (cmsg->cmsg_type == SCM_CREDENTIALS)
266             {
267               cr = (struct ucred *) CMSG_DATA (cmsg);
268               s->uid = cr->uid;
269               s->gid = cr->gid;
270               s->pid = cr->pid;
271             }
272           else
273 #endif
274           if (cmsg->cmsg_type == SCM_RIGHTS)
275             {
276               clib_memcpy_fast (fds, CMSG_DATA (cmsg),
277                                 num_fds * sizeof (int));
278             }
279         }
280       cmsg = CMSG_NXTHDR (&mh, cmsg);
281     }
282   return 0;
283 }
284
285 static void
286 socket_init_funcs (clib_socket_t * s)
287 {
288   if (!s->write_func)
289     s->write_func = default_socket_write;
290   if (!s->read_func)
291     s->read_func = default_socket_read;
292   if (!s->close_func)
293     s->close_func = default_socket_close;
294   if (!s->sendmsg_func)
295     s->sendmsg_func = default_socket_sendmsg;
296   if (!s->recvmsg_func)
297     s->recvmsg_func = default_socket_recvmsg;
298 }
299
300 static const struct
301 {
302   char *prefix;
303   sa_family_t family;
304   clib_socket_type_t type;
305   u16 skip_prefix : 1;
306   u16 is_local : 1;
307 } clib_socket_type_data[] = {
308   { .prefix = "unix:",
309     .family = AF_UNIX,
310     .type = CLIB_SOCKET_TYPE_UNIX,
311     .skip_prefix = 1,
312     .is_local = 1 },
313   { .prefix = "tcp:",
314     .family = AF_INET,
315     .type = CLIB_SOCKET_TYPE_INET,
316     .skip_prefix = 1 },
317   { .prefix = "abstract:",
318     .family = AF_UNIX,
319     .type = CLIB_SOCKET_TYPE_LINUX_ABSTRACT,
320     .skip_prefix = 1,
321     .is_local = 1 },
322   { .prefix = "/",
323     .family = AF_UNIX,
324     .type = CLIB_SOCKET_TYPE_UNIX,
325     .skip_prefix = 0,
326     .is_local = 1 },
327   { .prefix = "",
328     .family = AF_INET,
329     .type = CLIB_SOCKET_TYPE_INET,
330     .skip_prefix = 0,
331     .is_local = 0 },
332   { .prefix = "",
333     .family = AF_UNIX,
334     .type = CLIB_SOCKET_TYPE_UNIX,
335     .skip_prefix = 0,
336     .is_local = 1 },
337 };
338
339 static u8 *
340 _clib_socket_get_string (char **p, int is_hostname)
341 {
342   u8 *s = 0;
343   while (**p)
344     {
345       switch (**p)
346         {
347         case '_':
348           if (is_hostname)
349             return s;
350         case 'a' ... 'z':
351         case 'A' ... 'Z':
352         case '0' ... '9':
353         case '/':
354         case '-':
355         case '.':
356           vec_add1 (s, **p);
357           (*p)++;
358           break;
359           break;
360         default:
361           return s;
362         }
363     }
364   return s;
365 }
366
367 __clib_export int
368 clib_socket_prefix_is_valid (char *s)
369 {
370   for (typeof (clib_socket_type_data[0]) *d = clib_socket_type_data;
371        d - clib_socket_type_data < ARRAY_LEN (clib_socket_type_data); d++)
372     if (d->skip_prefix && strncmp (s, d->prefix, strlen (d->prefix)) == 0)
373       return 1;
374   return 0;
375 }
376
377 __clib_export int
378 clib_socket_prefix_get_type (char *s)
379 {
380   for (typeof (clib_socket_type_data[0]) *d = clib_socket_type_data;
381        d - clib_socket_type_data < ARRAY_LEN (clib_socket_type_data); d++)
382     if (strncmp (s, d->prefix, strlen (d->prefix)) == 0)
383       return d->type;
384   return 0;
385 }
386
387 __clib_export clib_error_t *
388 clib_socket_init (clib_socket_t *s)
389 {
390   struct sockaddr_un su = { .sun_family = AF_UNIX };
391   struct sockaddr_in si = { .sin_family = AF_INET };
392   struct sockaddr *sa = 0;
393   typeof (clib_socket_type_data[0]) *data = 0;
394   socklen_t addr_len = 0;
395   int rv;
396   char *p;
397   clib_error_t *err = 0;
398   u8 *name = 0;
399   u16 port = 0;
400 #if CLIB_LINUX
401   int netns_fd = -1;
402 #endif
403
404   s->fd = -1;
405
406   if (!s->config)
407     s->config = "";
408
409   for (int i = 0; i < ARRAY_LEN (clib_socket_type_data); i++)
410     {
411       typeof (clib_socket_type_data[0]) *d = clib_socket_type_data + i;
412
413       if (d->is_local == 0 && s->local_only)
414         continue;
415
416       if (strncmp (s->config, d->prefix, strlen (d->prefix)) == 0)
417         {
418           data = d;
419           break;
420         }
421     }
422
423   if (data == 0)
424     return clib_error_return (0, "unsupported socket config '%s'", s->config);
425
426   s->type = data->type;
427   p = s->config + (data->skip_prefix ? strlen (data->prefix) : 0);
428
429   name = _clib_socket_get_string (&p, data->type == CLIB_SOCKET_TYPE_INET);
430   vec_add1 (name, 0);
431
432   /* parse port type for INET sockets */
433   if (data->type == CLIB_SOCKET_TYPE_INET && p[0] == ':')
434     {
435       char *old_p = p + 1;
436       long long ll = strtoll (old_p, &p, 0);
437
438       if (p == old_p)
439         {
440           err = clib_error_return (0, "invalid port");
441           goto done;
442         }
443
444       if (ll > CLIB_U16_MAX || ll < 1)
445         {
446           err = clib_error_return (0, "port out of range");
447           goto done;
448         }
449       port = ll;
450     }
451
452   while (p[0] == ',')
453     {
454       p++;
455       if (0)
456         ;
457 #if CLIB_LINUX
458       else if (s->type == CLIB_SOCKET_TYPE_LINUX_ABSTRACT && netns_fd == -1 &&
459                strncmp (p, "netns_name=", 11) == 0)
460         {
461           p += 11;
462           u8 *str = _clib_socket_get_string (&p, 0);
463           u8 *pathname = 0;
464           if (str[0] == '/')
465             pathname = format (0, "%v%c", str, 0);
466           else
467             pathname = format (0, "/var/run/netns/%v%c", str, 0);
468           if ((netns_fd = open ((char *) pathname, O_RDONLY)) < 0)
469             err = clib_error_return_unix (0, "open('%s')", pathname);
470           vec_free (str);
471           vec_free (pathname);
472           if (err)
473             goto done;
474         }
475       else if (s->type == CLIB_SOCKET_TYPE_LINUX_ABSTRACT && netns_fd == -1 &&
476                strncmp (p, "netns_pid=", 10) == 0)
477         {
478           char *old_p = p = p + 10;
479           u32 pid = (u32) strtol (old_p, &p, 0);
480
481           if (p == old_p)
482             err = clib_error_return (0, "invalid pid");
483           else
484             {
485               u8 *pathname = format (0, "/proc/%u/ns/net%c", pid, 0);
486               if ((netns_fd = open ((char *) pathname, O_RDONLY)) < 0)
487                 err = clib_error_return_unix (0, "open('%s')", pathname);
488               vec_free (pathname);
489             }
490           if (err)
491             goto done;
492         }
493 #endif
494       else
495         break;
496     }
497
498   if (p[0] != 0)
499     {
500       err = clib_error_return (0, "unknown input `%s'", p);
501       goto done;
502     }
503
504 #if CLIB_LINUX
505   /* change netns if requested */
506   if (s->type != CLIB_SOCKET_TYPE_INET && netns_fd != -1)
507     {
508       int fd = open ("/proc/self/ns/net", O_RDONLY);
509
510       if (setns (netns_fd, CLONE_NEWNET) < 0)
511         {
512           close (fd);
513           err = clib_error_return_unix (0, "setns(%d)", netns_fd);
514           goto done;
515         }
516       netns_fd = fd;
517     }
518 #endif
519
520   if (s->type == CLIB_SOCKET_TYPE_INET)
521     {
522       addr_len = sizeof (si);
523       si.sin_port = htons (port);
524
525       if (name)
526         {
527           struct in_addr host_addr;
528           vec_add1 (name, 0);
529
530           /* Recognize localhost to avoid host lookup in most common cast. */
531           if (!strcmp ((char *) name, "localhost"))
532             si.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
533
534           else if (inet_aton ((char *) name, &host_addr))
535             si.sin_addr = host_addr;
536
537           else if (strlen ((char *) name) > 0)
538             {
539               struct hostent *host = gethostbyname ((char *) name);
540               if (!host)
541                 err = clib_error_return (0, "unknown host `%s'", name);
542               else
543                 clib_memcpy (&si.sin_addr.s_addr, host->h_addr_list[0],
544                              host->h_length);
545             }
546
547           else
548             si.sin_addr.s_addr =
549               htonl (s->is_server ? INADDR_LOOPBACK : INADDR_ANY);
550
551           if (err)
552             goto done;
553         }
554       sa = (struct sockaddr *) &si;
555     }
556   else if (s->type == CLIB_SOCKET_TYPE_UNIX)
557     {
558       struct stat st = { 0 };
559       char *path = (char *) &su.sun_path;
560
561       if (vec_len (name) > sizeof (su.sun_path) - 1)
562         {
563           err = clib_error_return (0, "File path '%v' too long", name);
564           goto done;
565         }
566
567       clib_memcpy (path, s->config, vec_len (name));
568       addr_len = sizeof (su);
569       sa = (struct sockaddr *) &su;
570
571       rv = stat (path, &st);
572       if (!s->is_server && rv < 0)
573         {
574           err = clib_error_return_unix (0, "stat ('%s')", path);
575           goto done;
576         }
577
578       if (s->is_server && rv == 0)
579         {
580           if (S_ISSOCK (st.st_mode))
581             {
582               int client_fd = socket (AF_UNIX, SOCK_STREAM, 0);
583               int ret = connect (client_fd, (const struct sockaddr *) &su,
584                                  sizeof (su));
585               typeof (errno) connect_errno = errno;
586               close (client_fd);
587
588               if (ret == 0 || (ret < 0 && connect_errno != ECONNREFUSED))
589                 {
590                   err = clib_error_return (0, "Active listener on '%s'", path);
591                   goto done;
592                 }
593
594               if (unlink (path) < 0)
595                 {
596                   err = clib_error_return_unix (0, "unlink ('%s')", path);
597                   goto done;
598                 }
599             }
600           else
601             {
602               err = clib_error_return (0, "File '%s' already exists", path);
603               goto done;
604             }
605         }
606     }
607 #if CLIB_LINUX
608   else if (s->type == CLIB_SOCKET_TYPE_LINUX_ABSTRACT)
609     {
610       if (vec_len (name) > sizeof (su.sun_path) - 2)
611         {
612           err = clib_error_return (0, "Socket name '%v' too long", name);
613           goto done;
614         }
615
616       clib_memcpy (&su.sun_path[1], name, vec_len (name));
617       addr_len = sizeof (su.sun_family) + vec_len (name);
618       sa = (struct sockaddr *) &su;
619       s->allow_group_write = 0;
620     }
621 #endif
622   else
623     {
624       err = clib_error_return_unix (0, "unknown socket family");
625       goto done;
626     }
627
628   socket_init_funcs (s);
629
630   if ((s->fd = socket (sa->sa_family,
631                        s->is_seqpacket ? SOCK_SEQPACKET : SOCK_STREAM, 0)) < 0)
632     {
633       err =
634         clib_error_return_unix (0, "socket (fd %d, '%s')", s->fd, s->config);
635       goto done;
636     }
637
638   if (s->is_server)
639     {
640       uword need_bind = 1;
641
642       if (sa->sa_family == AF_INET && si.sin_port == 0)
643         {
644           word port = find_free_port (s->fd);
645           if (port < 0)
646             {
647               err = clib_error_return (0, "no free port (fd %d, '%s')", s->fd,
648                                        s->config);
649               goto done;
650             }
651           si.sin_port = port;
652           need_bind = 0;
653         }
654
655       if (setsockopt (s->fd, SOL_SOCKET, SO_REUSEADDR, &((int){ 1 }),
656                       sizeof (int)) < 0)
657         clib_unix_warning ("setsockopt SO_REUSEADDR fails");
658
659 #if CLIB_LINUX
660       if (sa->sa_family == AF_UNIX && s->passcred)
661         {
662           if (setsockopt (s->fd, SOL_SOCKET, SO_PASSCRED, &((int){ 1 }),
663                           sizeof (int)) < 0)
664             {
665               err = clib_error_return_unix (0,
666                                             "setsockopt (SO_PASSCRED, "
667                                             "fd %d, '%s')",
668                                             s->fd, s->config);
669               goto done;
670             }
671         }
672 #endif
673
674       if (need_bind && bind (s->fd, sa, addr_len) < 0)
675         {
676           err =
677             clib_error_return_unix (0, "bind (fd %d, '%s')", s->fd, s->config);
678           goto done;
679         }
680
681       if (listen (s->fd, 5) < 0)
682         {
683           err = clib_error_return_unix (0, "listen (fd %d, '%s')", s->fd,
684                                         s->config);
685           goto done;
686         }
687
688       if (s->local_only && s->allow_group_write)
689         {
690           if (fchmod (s->fd, S_IWGRP) < 0)
691             {
692               err = clib_error_return_unix (
693                 0, "fchmod (fd %d, '%s', mode S_IWGRP)", s->fd, s->config);
694               goto done;
695             }
696         }
697     }
698   else
699     {
700       if (s->non_blocking_connect && fcntl (s->fd, F_SETFL, O_NONBLOCK) < 0)
701         {
702           err = clib_error_return_unix (0, "fcntl NONBLOCK (fd %d, '%s')",
703                                         s->fd, s->config);
704           goto done;
705         }
706
707       while ((rv = connect (s->fd, sa, addr_len)) < 0 && errno == EAGAIN)
708         ;
709       if (rv < 0 && !(s->non_blocking_connect && errno == EINPROGRESS))
710         {
711           err = clib_error_return_unix (0, "connect (fd %d, '%s')", s->fd,
712                                         s->config);
713           goto done;
714         }
715       /* Connect was blocking so set fd to non-blocking now unless
716        * blocking mode explicitly requested. */
717       if (!s->non_blocking_connect && !s->is_blocking &&
718           fcntl (s->fd, F_SETFL, O_NONBLOCK) < 0)
719         {
720           err = clib_error_return_unix (0, "fcntl NONBLOCK2 (fd %d, '%s')",
721                                         s->fd, s->config);
722           goto done;
723         }
724     }
725
726 done:
727   if (err && s->fd > -1)
728     {
729       close (s->fd);
730       s->fd = -1;
731     }
732 #if CLIB_LINUX
733   if (netns_fd != -1)
734     {
735       setns (CLONE_NEWNET, netns_fd);
736       close (netns_fd);
737     }
738 #endif
739   vec_free (name);
740   return err;
741 }
742
743 __clib_export clib_error_t *
744 clib_socket_accept (clib_socket_t * server, clib_socket_t * client)
745 {
746   clib_error_t *err = 0;
747   socklen_t len = 0;
748
749   clib_memset (client, 0, sizeof (client[0]));
750
751   /* Accept the new socket connection. */
752   client->fd = accept (server->fd, 0, 0);
753   if (client->fd < 0)
754     return clib_error_return_unix (0, "accept (fd %d, '%s')",
755                                    server->fd, server->config);
756
757   /* Set the new socket to be non-blocking. */
758   if (fcntl (client->fd, F_SETFL, O_NONBLOCK) < 0)
759     {
760       err = clib_error_return_unix (0, "fcntl O_NONBLOCK (fd %d)",
761                                     client->fd);
762       goto close_client;
763     }
764
765   /* Get peer info. */
766   len = sizeof (client->peer);
767   if (getpeername (client->fd, (struct sockaddr *) &client->peer, &len) < 0)
768     {
769       err = clib_error_return_unix (0, "getpeername (fd %d)", client->fd);
770       goto close_client;
771     }
772
773   client->flags = CLIB_SOCKET_F_IS_CLIENT;
774
775   socket_init_funcs (client);
776   return 0;
777
778 close_client:
779   close (client->fd);
780   return err;
781 }
782
783 /*
784  * fd.io coding-style-patch-verification: ON
785  *
786  * Local Variables:
787  * eval: (c-set-style "gnu")
788  * End:
789  */