vppinfra: refactor clib_socket_init, add linux netns support
[vpp.git] / src / vppinfra / socket.h
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 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 #ifndef _clib_included_socket_h
39 #define _clib_included_socket_h
40
41 #include <sys/types.h>
42 #include <sys/socket.h>
43 #include <netinet/in.h>
44
45 #include <vppinfra/clib.h>
46 #include <vppinfra/error.h>
47 #include <vppinfra/format.h>
48
49 typedef enum
50 {
51   CLIB_SOCKET_TYPE_UNKNOWN = 0,
52   CLIB_SOCKET_TYPE_INET,
53   CLIB_SOCKET_TYPE_UNIX,
54 #if CLIB_LINUX
55   CLIB_SOCKET_TYPE_LINUX_ABSTRACT,
56 #endif
57 } clib_socket_type_t;
58
59 typedef struct _socket_t
60 {
61   /* File descriptor. */
62   i32 fd;
63
64   /* Config string for socket HOST:PORT or just HOST. */
65   char *config;
66
67   union
68   {
69     struct
70     {
71       u32 is_server : 1;
72       u32 rx_end_of_file : 1;
73       u32 non_blocking_connect : 1;
74       u32 allow_group_write : 1;
75       u32 is_seqpacket : 1;
76       u32 passcred : 1;
77       u32 is_blocking : 1;
78       u32 local_only : 1;
79     };
80     u32 flags;
81   };
82
83   /* Transmit buffer.  Holds data waiting to be written. */
84   u8 *tx_buffer;
85
86   /* Receive buffer.  Holds data read from socket. */
87   u8 *rx_buffer;
88
89   /* Peer socket we are connected to. */
90   struct sockaddr_in peer;
91
92   /* Credentials, populated if CLIB_SOCKET_F_PASSCRED is set */
93   pid_t pid;
94   uid_t uid;
95   gid_t gid;
96
97   clib_error_t *(*write_func) (struct _socket_t * sock);
98   clib_error_t *(*read_func) (struct _socket_t * sock, int min_bytes);
99   clib_error_t *(*close_func) (struct _socket_t * sock);
100   clib_error_t *(*recvmsg_func) (struct _socket_t * s, void *msg, int msglen,
101                                  int fds[], int num_fds);
102   clib_error_t *(*sendmsg_func) (struct _socket_t * s, void *msg, int msglen,
103                                  int fds[], int num_fds);
104   clib_socket_type_t type;
105   uword private_data;
106 } clib_socket_t;
107
108 #define CLIB_SOCKET_FLAG(f)             (((clib_socket_t){ .f = 1 }).flags)
109 #define CLIB_SOCKET_F_IS_CLIENT         0
110 #define CLIB_SOCKET_F_IS_SERVER         CLIB_SOCKET_FLAG (is_server)
111 #define CLIB_SOCKET_F_ALLOW_GROUP_WRITE CLIB_SOCKET_FLAG (allow_group_write)
112 #define CLIB_SOCKET_F_SEQPACKET         CLIB_SOCKET_FLAG (is_seqpacket)
113 #define CLIB_SOCKET_F_PASSCRED          CLIB_SOCKET_FLAG (passcred)
114 #define CLIB_SOCKET_F_BLOCKING          CLIB_SOCKET_FLAG (is_blocking)
115
116 /* socket config format is host:port.
117    Unspecified port causes a free one to be chosen starting
118    from IPPORT_USERRESERVED (5000). */
119 clib_error_t *clib_socket_init (clib_socket_t * socket);
120
121 clib_error_t *clib_socket_init_netns (clib_socket_t *socket, u8 *namespace);
122
123 clib_error_t *clib_socket_accept (clib_socket_t * server,
124                                   clib_socket_t * client);
125
126 int clib_socket_prefix_is_valid (char *s);
127
128 always_inline uword
129 clib_socket_is_server (clib_socket_t * sock)
130 {
131   return sock->is_server;
132 }
133
134 always_inline uword
135 clib_socket_is_client (clib_socket_t * s)
136 {
137   return !clib_socket_is_server (s);
138 }
139
140 always_inline uword
141 clib_socket_is_connected (clib_socket_t * sock)
142 {
143   return sock->fd > 0;
144 }
145
146
147 always_inline int
148 clib_socket_rx_end_of_file (clib_socket_t * s)
149 {
150   return s->rx_end_of_file;
151 }
152
153 always_inline void *
154 clib_socket_tx_add (clib_socket_t * s, int n_bytes)
155 {
156   u8 *result;
157   vec_add2 (s->tx_buffer, result, n_bytes);
158   return result;
159 }
160
161 always_inline void
162 clib_socket_tx_add_va_formatted (clib_socket_t * s, char *fmt, va_list * va)
163 {
164   s->tx_buffer = va_format (s->tx_buffer, fmt, va);
165 }
166
167 always_inline clib_error_t *
168 clib_socket_tx (clib_socket_t * s)
169 {
170   return s->write_func (s);
171 }
172
173 always_inline clib_error_t *
174 clib_socket_rx (clib_socket_t * s, int n_bytes)
175 {
176   return s->read_func (s, n_bytes);
177 }
178
179 always_inline clib_error_t *
180 clib_socket_sendmsg (clib_socket_t * s, void *msg, int msglen,
181                      int fds[], int num_fds)
182 {
183   return s->sendmsg_func (s, msg, msglen, fds, num_fds);
184 }
185
186 always_inline clib_error_t *
187 clib_socket_recvmsg (clib_socket_t * s, void *msg, int msglen,
188                      int fds[], int num_fds)
189 {
190   return s->recvmsg_func (s, msg, msglen, fds, num_fds);
191 }
192
193 always_inline void
194 clib_socket_free (clib_socket_t * s)
195 {
196   vec_free (s->tx_buffer);
197   vec_free (s->rx_buffer);
198   if (clib_mem_is_heap_object (s->config))
199     vec_free (s->config);
200   clib_memset (s, 0, sizeof (s[0]));
201 }
202
203 always_inline clib_error_t *
204 clib_socket_close (clib_socket_t * sock)
205 {
206   clib_error_t *err;
207   err = (*sock->close_func) (sock);
208   return err;
209 }
210
211 void clib_socket_tx_add_formatted (clib_socket_t * s, char *fmt, ...);
212
213 #endif /* _clib_included_socket_h */
214
215 /*
216  * fd.io coding-style-patch-verification: ON
217  *
218  * Local Variables:
219  * eval: (c-set-style "gnu")
220  * End:
221  */