Initial commit of vpp code.
[vpp.git] / vppinfra / 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 <sys/un.h>
39 #include <sys/types.h>
40 #include <sys/socket.h>
41 #include <netinet/in.h>
42 #include <arpa/inet.h>
43 #include <netdb.h>
44 #include <unistd.h>
45 #include <stdio.h>
46 #include <fcntl.h>
47 #include <string.h>             /* strchr */
48
49 #include <vppinfra/mem.h>
50 #include <vppinfra/vec.h>
51 #include <vppinfra/socket.h>
52 #include <vppinfra/format.h>
53 #include <vppinfra/error.h>
54
55 void clib_socket_tx_add_formatted (clib_socket_t * s, char * fmt, ...)
56 {
57   va_list va;
58   va_start (va, fmt);
59   clib_socket_tx_add_va_formatted (s, fmt, &va);
60   va_end (va);
61 }
62
63 /* Return and bind to an unused port. */
64 static word find_free_port (word sock)
65 {
66   word port;
67
68   for (port = IPPORT_USERRESERVED; port < 1 << 16; port++)
69     {
70       struct sockaddr_in a;
71
72       memset(&a, 0, sizeof (a)); /* Warnings be gone */
73
74       a.sin_family = PF_INET;
75       a.sin_addr.s_addr = INADDR_ANY;
76       a.sin_port = htons (port);
77
78       if (bind (sock, (struct sockaddr *) &a, sizeof (a)) >= 0)
79         break;
80     }
81         
82   return port < 1 << 16 ? port : -1;
83 }
84
85 /* Convert a config string to a struct sockaddr and length for use
86    with bind or connect. */
87 static clib_error_t *
88 socket_config (char * config,
89                void * addr,
90                socklen_t * addr_len,
91                u32 ip4_default_address)
92 {
93   clib_error_t * error = 0;
94
95   if (! config)
96     config = "";
97
98   /* Anything that begins with a / is a local PF_LOCAL socket. */
99   if (config[0] == '/')
100     {
101       struct sockaddr_un * su = addr;
102       su->sun_family = PF_LOCAL;
103       memcpy (&su->sun_path, config,
104               clib_min (sizeof (su->sun_path), 1 + strlen (config)));
105       *addr_len = sizeof (su[0]);
106     }
107
108   /* Hostname or hostname:port or port. */
109   else
110     {
111       char * host_name;
112       int port = -1;
113       struct sockaddr_in * sa = addr;
114
115       host_name = 0;
116       port = -1;
117       if (config[0] != 0)
118         {
119           unformat_input_t i;
120
121           unformat_init_string (&i, config, strlen (config));
122           if (unformat (&i, "%s:%d", &host_name, &port)
123               || unformat (&i, "%s:0x%x", &host_name, &port))
124             ;
125           else if (unformat (&i, "%s", &host_name))
126             ;
127           else
128             error = clib_error_return (0, "unknown input `%U'",
129                                        format_unformat_error, &i);
130           unformat_free (&i);
131
132           if (error)
133             goto done;
134         }
135
136       sa->sin_family = PF_INET;
137       *addr_len = sizeof (sa[0]);
138       if (port != -1)
139         sa->sin_port = htons (port);
140       else
141         sa->sin_port = 0;
142
143       if (host_name)
144         {
145           struct in_addr host_addr;
146
147           /* Recognize localhost to avoid host lookup in most common cast. */
148           if (! strcmp (host_name, "localhost"))
149             sa->sin_addr.s_addr = htonl (INADDR_LOOPBACK);
150
151           else if (inet_aton (host_name, &host_addr))
152             sa->sin_addr = host_addr;
153
154           else if (host_name && strlen (host_name) > 0)
155             {
156               struct hostent * host = gethostbyname (host_name);
157               if (! host)
158                 error = clib_error_return (0, "unknown host `%s'", config);
159               else
160                 memcpy (&sa->sin_addr.s_addr, host->h_addr_list[0], host->h_length);
161             }
162
163           else
164             sa->sin_addr.s_addr = htonl (ip4_default_address);
165
166           vec_free (host_name);
167           if (error)
168             goto done;
169         }
170     }
171
172  done:
173   return error;
174 }
175
176 static clib_error_t *
177 default_socket_write (clib_socket_t * s)
178 {
179   clib_error_t  * err = 0;
180   word written = 0;
181   word fd = 0;
182   word tx_len;
183
184   fd = s->fd;
185
186   /* Map standard input to standard output.
187      Typically, fd is a socket for which read/write both work. */
188   if (fd == 0)
189     fd = 1;
190
191   tx_len = vec_len (s->tx_buffer);
192   written = write (fd, s->tx_buffer, tx_len);
193
194   /* Ignore certain errors. */
195   if (written < 0 && ! unix_error_is_fatal (errno))
196     written = 0;
197
198   /* A "real" error occurred. */
199   if (written < 0)
200     {
201       err = clib_error_return_unix (0, "write %wd bytes", tx_len);
202       vec_free (s->tx_buffer);
203       goto done;
204     }
205
206   /* Reclaim the transmitted part of the tx buffer on successful writes. */
207   else if (written > 0)
208     {
209       if (written == tx_len)
210         _vec_len (s->tx_buffer) = 0;
211       else
212         vec_delete (s->tx_buffer, written, 0);
213     }
214
215   /* If a non-fatal error occurred AND
216      the buffer is full, then we must free it. */
217   else if (written == 0 && tx_len > 64*1024)
218     {
219       vec_free (s->tx_buffer);
220     }
221
222  done:
223   return err;
224 }
225
226 static clib_error_t *
227 default_socket_read (clib_socket_t * sock, int n_bytes)
228 {
229   word fd, n_read;
230   u8 * buf;
231
232   /* RX side of socket is down once end of file is reached. */
233   if (sock->flags & SOCKET_RX_END_OF_FILE)
234     return 0;
235
236   fd = sock->fd;
237
238   n_bytes = clib_max (n_bytes, 4096);
239   vec_add2 (sock->rx_buffer, buf, n_bytes);
240
241   if ((n_read = read (fd, buf, n_bytes)) < 0)
242     {
243       n_read = 0;
244
245       /* Ignore certain errors. */
246       if (! unix_error_is_fatal (errno))
247         goto non_fatal;
248       
249       return clib_error_return_unix (0, "read %d bytes", n_bytes);
250     }
251       
252   /* Other side closed the socket. */
253   if (n_read == 0)
254     sock->flags |= SOCKET_RX_END_OF_FILE;
255
256  non_fatal:
257   _vec_len (sock->rx_buffer) += n_read - n_bytes;
258
259   return 0;
260 }
261
262 static clib_error_t * default_socket_close (clib_socket_t * s)
263 {
264   if (close (s->fd) < 0)
265     return clib_error_return_unix (0, "close");
266   return 0;
267 }
268
269 static void socket_init_funcs (clib_socket_t * s)
270 {
271   if (! s->write_func)
272     s->write_func = default_socket_write;
273   if (! s->read_func)
274     s->read_func = default_socket_read;
275   if (! s->close_func)
276     s->close_func = default_socket_close;
277 }
278
279 clib_error_t *
280 clib_socket_init (clib_socket_t * s)
281 {
282   union {
283     struct sockaddr sa;
284     struct sockaddr_un su;
285   } addr;
286   socklen_t addr_len = 0;
287   clib_error_t * error = 0;
288   word port;
289
290   error = socket_config (s->config, &addr.sa, &addr_len,
291                          (s->flags & SOCKET_IS_SERVER
292                           ? INADDR_LOOPBACK
293                           : INADDR_ANY));
294   if (error)
295     goto done;
296
297   socket_init_funcs (s);
298
299   s->fd = socket (addr.sa.sa_family, SOCK_STREAM, 0);
300   if (s->fd < 0)
301     {
302       error = clib_error_return_unix (0, "socket");
303       goto done;
304     }
305
306   port = 0;
307   if (addr.sa.sa_family == PF_INET)
308     port = ((struct sockaddr_in *) &addr)->sin_port;
309
310   if (s->flags & SOCKET_IS_SERVER)
311     {
312       uword need_bind = 1;
313
314       if (addr.sa.sa_family == PF_INET)
315         {
316           if (port == 0)
317             {
318               port = find_free_port (s->fd);
319               if (port < 0)
320                 {
321                   error = clib_error_return (0, "no free port");
322                   goto done;
323                 }
324               need_bind = 0;
325             }
326         }
327       if (addr.sa.sa_family == PF_LOCAL)
328         unlink (((struct sockaddr_un *) &addr)->sun_path);
329
330       /* Make address available for multiple users. */
331       {
332         int v = 1;
333         if (setsockopt (s->fd, SOL_SOCKET, SO_REUSEADDR, &v, sizeof (v)) < 0)
334           clib_unix_warning ("setsockopt SO_REUSEADDR fails");
335       }
336
337       if (need_bind
338           && bind (s->fd, &addr.sa, addr_len) < 0)
339         {
340           error = clib_error_return_unix (0, "bind");
341           goto done;
342         }
343
344       if (listen (s->fd, 5) < 0)
345         {
346           error = clib_error_return_unix (0, "listen");
347           goto done;
348         }
349     }
350   else
351     {
352       if ((s->flags & SOCKET_NON_BLOCKING_CONNECT)
353           && fcntl (s->fd, F_SETFL, O_NONBLOCK) < 0)
354         {
355           error = clib_error_return_unix (0, "fcntl NONBLOCK");
356           goto done;
357         }
358
359       if (connect (s->fd, &addr.sa, addr_len) < 0
360           && ! ((s->flags & SOCKET_NON_BLOCKING_CONNECT) &&
361                 errno == EINPROGRESS))
362         {
363           error = clib_error_return_unix (0, "connect");
364           goto done;
365         }
366     }
367
368   return error;
369
370  done:
371   if (s->fd > 0)
372     close (s->fd);
373   return error;
374 }
375
376 clib_error_t * clib_socket_accept (clib_socket_t * server, clib_socket_t * client)
377 {
378   clib_error_t  * err = 0;
379   socklen_t     len = 0;
380   
381   memset (client, 0, sizeof (client[0]));
382
383   /* Accept the new socket connection. */
384   client->fd = accept (server->fd, 0, 0);
385   if (client->fd < 0) 
386     return clib_error_return_unix (0, "accept");
387   
388   /* Set the new socket to be non-blocking. */
389   if (fcntl (client->fd, F_SETFL, O_NONBLOCK) < 0)
390     {
391       err = clib_error_return_unix (0, "fcntl O_NONBLOCK");
392       goto close_client;
393     }
394     
395   /* Get peer info. */
396   len = sizeof (client->peer);
397   if (getpeername (client->fd, (struct sockaddr *) &client->peer, &len) < 0)
398     {
399       err = clib_error_return_unix (0, "getpeername");
400       goto close_client;
401     }
402
403   client->flags = SOCKET_IS_CLIENT;
404
405   socket_init_funcs (client);
406   return 0;
407
408  close_client:
409   close (client->fd);
410   return err;
411 }