octeon: add clear counters for port and queues
[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 #if 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 #if 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 #if CLIB_LINUX
318   { .prefix = "abstract:",
319     .family = AF_UNIX,
320     .type = CLIB_SOCKET_TYPE_LINUX_ABSTRACT,
321     .skip_prefix = 1,
322     .is_local = 1 },
323 #endif /* CLIB_LINUX */
324   { .prefix = "/",
325     .family = AF_UNIX,
326     .type = CLIB_SOCKET_TYPE_UNIX,
327     .skip_prefix = 0,
328     .is_local = 1 },
329   { .prefix = "",
330     .family = AF_INET,
331     .type = CLIB_SOCKET_TYPE_INET,
332     .skip_prefix = 0,
333     .is_local = 0 },
334   { .prefix = "",
335     .family = AF_UNIX,
336     .type = CLIB_SOCKET_TYPE_UNIX,
337     .skip_prefix = 0,
338     .is_local = 1 },
339 };
340
341 static u8 *
342 _clib_socket_get_string (char **p, int is_hostname)
343 {
344   u8 *s = 0;
345   while (**p)
346     {
347       switch (**p)
348         {
349         case '_':
350           if (is_hostname)
351             return s;
352         case 'a' ... 'z':
353         case 'A' ... 'Z':
354         case '0' ... '9':
355         case '/':
356         case '-':
357         case '.':
358           vec_add1 (s, **p);
359           (*p)++;
360           break;
361           break;
362         default:
363           return s;
364         }
365     }
366   return s;
367 }
368
369 __clib_export int
370 clib_socket_prefix_is_valid (char *s)
371 {
372   for (typeof (clib_socket_type_data[0]) *d = clib_socket_type_data;
373        d - clib_socket_type_data < ARRAY_LEN (clib_socket_type_data); d++)
374     if (d->skip_prefix && strncmp (s, d->prefix, strlen (d->prefix)) == 0)
375       return 1;
376   return 0;
377 }
378
379 __clib_export int
380 clib_socket_prefix_get_type (char *s)
381 {
382   for (typeof (clib_socket_type_data[0]) *d = clib_socket_type_data;
383        d - clib_socket_type_data < ARRAY_LEN (clib_socket_type_data); d++)
384     if (strncmp (s, d->prefix, strlen (d->prefix)) == 0)
385       return d->type;
386   return 0;
387 }
388
389 __clib_export clib_error_t *
390 clib_socket_init (clib_socket_t *s)
391 {
392   struct sockaddr_un su = { .sun_family = AF_UNIX };
393   struct sockaddr_in si = { .sin_family = AF_INET };
394   struct sockaddr *sa = 0;
395   typeof (clib_socket_type_data[0]) *data = 0;
396   socklen_t addr_len = 0;
397   int rv;
398   char *p;
399   clib_error_t *err = 0;
400   u8 *name = 0;
401   u16 port = 0;
402 #if CLIB_LINUX
403   int netns_fd = -1;
404 #endif
405
406   s->fd = -1;
407
408   if (!s->config)
409     s->config = "";
410
411   for (int i = 0; i < ARRAY_LEN (clib_socket_type_data); i++)
412     {
413       typeof (clib_socket_type_data[0]) *d = clib_socket_type_data + i;
414
415       if (d->is_local == 0 && s->local_only)
416         continue;
417
418       if (strncmp (s->config, d->prefix, strlen (d->prefix)) == 0)
419         {
420           data = d;
421           break;
422         }
423     }
424
425   if (data == 0)
426     return clib_error_return (0, "unsupported socket config '%s'", s->config);
427
428   s->type = data->type;
429   p = s->config + (data->skip_prefix ? strlen (data->prefix) : 0);
430
431   name = _clib_socket_get_string (&p, data->type == CLIB_SOCKET_TYPE_INET);
432   vec_add1 (name, 0);
433
434   /* parse port type for INET sockets */
435   if (data->type == CLIB_SOCKET_TYPE_INET && p[0] == ':')
436     {
437       char *old_p = p + 1;
438       long long ll = strtoll (old_p, &p, 0);
439
440       if (p == old_p)
441         {
442           err = clib_error_return (0, "invalid port");
443           goto done;
444         }
445
446       if (ll > CLIB_U16_MAX || ll < 1)
447         {
448           err = clib_error_return (0, "port out of range");
449           goto done;
450         }
451       port = ll;
452     }
453
454   while (p[0] == ',')
455     {
456       p++;
457       if (0)
458         ;
459 #if CLIB_LINUX
460       else if (s->type == CLIB_SOCKET_TYPE_LINUX_ABSTRACT && netns_fd == -1 &&
461                strncmp (p, "netns_name=", 11) == 0)
462         {
463           p += 11;
464           u8 *str = _clib_socket_get_string (&p, 0);
465           u8 *pathname = 0;
466           if (str[0] == '/')
467             pathname = format (0, "%v%c", str, 0);
468           else
469             pathname = format (0, "/var/run/netns/%v%c", str, 0);
470           if ((netns_fd = open ((char *) pathname, O_RDONLY)) < 0)
471             err = clib_error_return_unix (0, "open('%s')", pathname);
472           vec_free (str);
473           vec_free (pathname);
474           if (err)
475             goto done;
476         }
477       else if (s->type == CLIB_SOCKET_TYPE_LINUX_ABSTRACT && netns_fd == -1 &&
478                strncmp (p, "netns_pid=", 10) == 0)
479         {
480           char *old_p = p = p + 10;
481           u32 pid = (u32) strtol (old_p, &p, 0);
482
483           if (p == old_p)
484             err = clib_error_return (0, "invalid pid");
485           else
486             {
487               u8 *pathname = format (0, "/proc/%u/ns/net%c", pid, 0);
488               if ((netns_fd = open ((char *) pathname, O_RDONLY)) < 0)
489                 err = clib_error_return_unix (0, "open('%s')", pathname);
490               vec_free (pathname);
491             }
492           if (err)
493             goto done;
494         }
495 #endif
496       else
497         break;
498     }
499
500   if (p[0] != 0)
501     {
502       err = clib_error_return (0, "unknown input `%s'", p);
503       goto done;
504     }
505
506 #if CLIB_LINUX
507   /* change netns if requested */
508   if (s->type != CLIB_SOCKET_TYPE_INET && netns_fd != -1)
509     {
510       int fd = open ("/proc/self/ns/net", O_RDONLY);
511
512       if (setns (netns_fd, CLONE_NEWNET) < 0)
513         {
514           close (fd);
515           err = clib_error_return_unix (0, "setns(%d)", netns_fd);
516           goto done;
517         }
518       netns_fd = fd;
519     }
520 #endif
521
522   if (s->type == CLIB_SOCKET_TYPE_INET)
523     {
524       addr_len = sizeof (si);
525       si.sin_port = htons (port);
526
527       if (name)
528         {
529           struct in_addr host_addr;
530           vec_add1 (name, 0);
531
532           /* Recognize localhost to avoid host lookup in most common cast. */
533           if (!strcmp ((char *) name, "localhost"))
534             si.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
535
536           else if (inet_aton ((char *) name, &host_addr))
537             si.sin_addr = host_addr;
538
539           else if (strlen ((char *) name) > 0)
540             {
541               struct hostent *host = gethostbyname ((char *) name);
542               if (!host)
543                 err = clib_error_return (0, "unknown host `%s'", name);
544               else
545                 clib_memcpy (&si.sin_addr.s_addr, host->h_addr_list[0],
546                              host->h_length);
547             }
548
549           else
550             si.sin_addr.s_addr =
551               htonl (s->is_server ? INADDR_LOOPBACK : INADDR_ANY);
552
553           if (err)
554             goto done;
555         }
556       sa = (struct sockaddr *) &si;
557     }
558   else if (s->type == CLIB_SOCKET_TYPE_UNIX)
559     {
560       struct stat st = { 0 };
561       char *path = (char *) &su.sun_path;
562
563       if (vec_len (name) > sizeof (su.sun_path) - 1)
564         {
565           err = clib_error_return (0, "File path '%v' too long", name);
566           goto done;
567         }
568
569       clib_memcpy (path, s->config, vec_len (name));
570       addr_len = sizeof (su);
571       sa = (struct sockaddr *) &su;
572
573       rv = stat (path, &st);
574       if (!s->is_server && rv < 0)
575         {
576           err = clib_error_return_unix (0, "stat ('%s')", path);
577           goto done;
578         }
579
580       if (s->is_server && rv == 0)
581         {
582           if (S_ISSOCK (st.st_mode))
583             {
584               int client_fd = socket (AF_UNIX, SOCK_STREAM, 0);
585               int ret = connect (client_fd, (const struct sockaddr *) &su,
586                                  sizeof (su));
587               typeof (errno) connect_errno = errno;
588               close (client_fd);
589
590               if (ret == 0 || (ret < 0 && connect_errno != ECONNREFUSED))
591                 {
592                   err = clib_error_return (0, "Active listener on '%s'", path);
593                   goto done;
594                 }
595
596               if (unlink (path) < 0)
597                 {
598                   err = clib_error_return_unix (0, "unlink ('%s')", path);
599                   goto done;
600                 }
601             }
602           else
603             {
604               err = clib_error_return (0, "File '%s' already exists", path);
605               goto done;
606             }
607         }
608     }
609 #if CLIB_LINUX
610   else if (s->type == CLIB_SOCKET_TYPE_LINUX_ABSTRACT)
611     {
612       if (vec_len (name) > sizeof (su.sun_path) - 2)
613         {
614           err = clib_error_return (0, "Socket name '%v' too long", name);
615           goto done;
616         }
617
618       clib_memcpy (&su.sun_path[1], name, vec_len (name));
619       addr_len = sizeof (su.sun_family) + vec_len (name);
620       sa = (struct sockaddr *) &su;
621       s->allow_group_write = 0;
622     }
623 #endif
624   else
625     {
626       err = clib_error_return_unix (0, "unknown socket family");
627       goto done;
628     }
629
630   socket_init_funcs (s);
631
632   if ((s->fd = socket (sa->sa_family,
633                        s->is_seqpacket ? SOCK_SEQPACKET : SOCK_STREAM, 0)) < 0)
634     {
635       err =
636         clib_error_return_unix (0, "socket (fd %d, '%s')", s->fd, s->config);
637       goto done;
638     }
639
640   if (s->is_server)
641     {
642       uword need_bind = 1;
643
644       if (sa->sa_family == AF_INET && si.sin_port == 0)
645         {
646           word port = find_free_port (s->fd);
647           if (port < 0)
648             {
649               err = clib_error_return (0, "no free port (fd %d, '%s')", s->fd,
650                                        s->config);
651               goto done;
652             }
653           si.sin_port = port;
654           need_bind = 0;
655         }
656
657       if (setsockopt (s->fd, SOL_SOCKET, SO_REUSEADDR, &((int){ 1 }),
658                       sizeof (int)) < 0)
659         clib_unix_warning ("setsockopt SO_REUSEADDR fails");
660
661 #if CLIB_LINUX
662       if (sa->sa_family == AF_UNIX && s->passcred)
663         {
664           if (setsockopt (s->fd, SOL_SOCKET, SO_PASSCRED, &((int){ 1 }),
665                           sizeof (int)) < 0)
666             {
667               err = clib_error_return_unix (0,
668                                             "setsockopt (SO_PASSCRED, "
669                                             "fd %d, '%s')",
670                                             s->fd, s->config);
671               goto done;
672             }
673         }
674 #endif
675
676       if (need_bind)
677         {
678           int bind_ret;
679           if (sa->sa_family == AF_UNIX && s->allow_group_write)
680             {
681               mode_t def_restrictions = umask (S_IWOTH);
682               bind_ret = bind (s->fd, sa, addr_len);
683               umask (def_restrictions);
684             }
685           else
686             bind_ret = bind (s->fd, sa, addr_len);
687
688           if (bind_ret < 0)
689             {
690               err = clib_error_return_unix (0, "bind (fd %d, '%s')", s->fd,
691                                             s->config);
692               goto done;
693             }
694         }
695
696       if (listen (s->fd, 5) < 0)
697         {
698           err = clib_error_return_unix (0, "listen (fd %d, '%s')", s->fd,
699                                         s->config);
700           goto done;
701         }
702     }
703   else
704     {
705       if (s->non_blocking_connect && fcntl (s->fd, F_SETFL, O_NONBLOCK) < 0)
706         {
707           err = clib_error_return_unix (0, "fcntl NONBLOCK (fd %d, '%s')",
708                                         s->fd, s->config);
709           goto done;
710         }
711
712       while ((rv = connect (s->fd, sa, addr_len)) < 0 && errno == EAGAIN)
713         ;
714       if (rv < 0 && !(s->non_blocking_connect && errno == EINPROGRESS))
715         {
716           err = clib_error_return_unix (0, "connect (fd %d, '%s')", s->fd,
717                                         s->config);
718           goto done;
719         }
720       /* Connect was blocking so set fd to non-blocking now unless
721        * blocking mode explicitly requested. */
722       if (!s->non_blocking_connect && !s->is_blocking &&
723           fcntl (s->fd, F_SETFL, O_NONBLOCK) < 0)
724         {
725           err = clib_error_return_unix (0, "fcntl NONBLOCK2 (fd %d, '%s')",
726                                         s->fd, s->config);
727           goto done;
728         }
729     }
730
731 done:
732   if (err && s->fd > -1)
733     {
734       close (s->fd);
735       s->fd = -1;
736     }
737 #if CLIB_LINUX
738   if (netns_fd != -1)
739     {
740       setns (netns_fd, CLONE_NEWNET);
741       close (netns_fd);
742     }
743 #endif
744   vec_free (name);
745   return err;
746 }
747
748 __clib_export clib_error_t *
749 clib_socket_accept (clib_socket_t * server, clib_socket_t * client)
750 {
751   clib_error_t *err = 0;
752   socklen_t len = 0;
753
754   clib_memset (client, 0, sizeof (client[0]));
755
756   /* Accept the new socket connection. */
757   client->fd = accept (server->fd, 0, 0);
758   if (client->fd < 0)
759     return clib_error_return_unix (0, "accept (fd %d, '%s')",
760                                    server->fd, server->config);
761
762   /* Set the new socket to be non-blocking. */
763   if (fcntl (client->fd, F_SETFL, O_NONBLOCK) < 0)
764     {
765       err = clib_error_return_unix (0, "fcntl O_NONBLOCK (fd %d)",
766                                     client->fd);
767       goto close_client;
768     }
769
770   /* Get peer info. */
771   len = sizeof (client->peer);
772   if (getpeername (client->fd, (struct sockaddr *) &client->peer, &len) < 0)
773     {
774       err = clib_error_return_unix (0, "getpeername (fd %d)", client->fd);
775       goto close_client;
776     }
777
778   client->flags = CLIB_SOCKET_F_IS_CLIENT;
779
780   socket_init_funcs (client);
781   return 0;
782
783 close_client:
784   close (client->fd);
785   return err;
786 }
787
788 /*
789  * fd.io coding-style-patch-verification: ON
790  *
791  * Local Variables:
792  * eval: (c-set-style "gnu")
793  * End:
794  */