SDOCM00117774: IPSec Inflow tests are getting failed on all platforms with error...
[keystone-rtos/netapi.git] / ti / runtime / netapi / utils / sockutils.c
1 /*
2  * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
3  *
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions
7  *  are met:
8  *
9  *    Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  *    Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the
15  *    distribution.
16  *
17  *    Neither the name of Texas Instruments Incorporated nor the names of
18  *    its contributors may be used to endorse or promote products derived
19  *    from this software without specific prior written permission.
20  *
21  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  *
33  */
35 #include <string.h>
36 #include <unistd.h>
37 #include <errno.h>
38 #include <malloc.h>
39 #include <sys/stat.h>
40 #include <sys/types.h>
41 #include <sys/ioctl.h>
43 #include "sockutils.h"
45 #define error_msg printf
47 typedef struct sock_data {
48     struct sockaddr_un addr;
49     fd_set  readfds;
50     int fd;
51 } sock_data_t;
53 int check_and_create_path (char *path)
54 {
55     char *d = path;
56     if (!d)
57         return -1;
59     while ((d = strchr(d + 1, '/'))) {
60         *d = 0;
61         if (mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) < 0) {
62             if (errno != EEXIST) {
63                 *d = '/';
64                 error_msg("can't create path %s (error: %s)",
65                         path, strerror(errno));
66                 return -1;
67             }
68         }
69         *d = '/';
70     }
71     return 0;
72 }
74 sock_h sock_open (sock_name_t *sock_name)
75 {
76     sock_data_t *sd = 0;
77     int retval = 0;
79     if (!sock_name) {
80         return 0;
81     }
83     sd = calloc (1, sizeof(sock_data_t));
85     if (sock_name->type == sock_addr_e) {
86         memcpy (&sd->addr, sock_name->s.addr, sizeof(struct sockaddr_un));
87     } else {
88         if (check_and_create_path(sock_name->s.name) < 0) {
89             goto check_n_return;
90         }
91         sd->addr.sun_family = AF_UNIX;
92         strncpy(sd->addr.sun_path, sock_name->s.name, UNIX_PATH_MAX);
93     }
95     sd->fd =  socket(AF_UNIX, SOCK_DGRAM, 0);
96     if (sd->fd < 0) {
97         error_msg("can't open socket %s (error: %s)",
98                   sd->addr.sun_path, strerror(errno));
99         goto check_n_return;
100     }
102     unlink(sd->addr.sun_path);
103     if (bind(sd->fd, (struct sockaddr *) &sd->addr, sizeof(struct sockaddr_un)) < 0) {
104         error_msg("can't bind socket %s (error: %s)",
105                   sd->addr.sun_path, strerror(errno));
106         goto check_n_return;
107     }
109     FD_ZERO(&sd->readfds);
110     FD_SET(sd->fd, &sd->readfds);
112     retval = (int) sd;
114 check_n_return:
115     if (!retval) {
116         sock_close ((sock_h) &sd);
117     }
119     return ((sock_h) retval);
122 int sock_close (sock_h handle)
124     sock_data_t *sd = (sock_data_t *) handle;
126     if (!sd) {
127         return -1;
128     }
130     if (sd->fd)
131         close (sd->fd);
132     free (sd);
134     return 0;    
137 int sock_send (sock_h handle, const char *data, int length,
138             sock_name_t *to)
140     int fd;
141     sock_data_t *sd = (sock_data_t *) handle;
142     struct sockaddr_un to_addr;
144     if (!to) {
145         return -1;
146     }
148     if (to->type == sock_addr_e) {
149         memcpy (&to_addr, to->s.addr, sizeof(struct sockaddr_un));
150     } else {
151         to_addr.sun_family = AF_UNIX;
152         strncpy(to_addr.sun_path, to->s.name, UNIX_PATH_MAX);
153     }
155     if (sd) {
156         fd = sd->fd;
157     } else {
158         fd =  socket(AF_UNIX, SOCK_DGRAM, 0);
159         if (fd < 0) {
160             error_msg("can't open socket %s (error: %s)",
161                       to_addr.sun_path, strerror(errno));
162             return -1;
163         }
164     }
166     if (sendto (fd, data, length, 0, (struct sockaddr *) &to_addr,
167                 sizeof(struct sockaddr_un)) < 0) {
168         error_msg("can't send data to %s (error: %s)",
169                 to_addr.sun_path, strerror(errno));
170         return -1;
172     }
174     if (!sd) {
175         close(fd);
176     }
178     return 0;
181 int sock_wait (sock_h handle, int *size, struct timeval *timeout, int extern_fd)
183     sock_data_t *sd = (sock_data_t *) handle;
184     int retval;
185     fd_set fds;
187     if (!sd) {
188         error_msg("invalid hanlde");
189         return -1;
190     }
192     fds = sd->readfds;
194     if (extern_fd != -1) {
195         FD_SET(extern_fd, &fds);
196     }
198     retval = select(FD_SETSIZE, &fds, NULL, NULL, timeout);
199     if (retval == -1) {
200         error_msg("select failed for %s (error: %s)",
201                 sd->addr.sun_path, strerror(errno));
202         return -1;
203     }
205     if ((extern_fd != -1) && (FD_ISSET(extern_fd, &fds))) {
206         return 1;
207     }
209     if (!FD_ISSET(sd->fd, &fds)) {
210         /* Wait timedout */
211         return -2;
212     }
214     if (!retval) {
215         return 0;
216     }
218     if (size != 0) {
219         retval = ioctl(sd->fd, FIONREAD, size);
220         if (retval == -1) {
221             error_msg("can't read datagram size for %s (error: %s)",
222                     sd->addr.sun_path, strerror(errno));
223             return -1;
224         }
225     }
227     return 0;
230 int sock_recv (sock_h handle, char *data, int length, sock_name_t *from)
232     int size;
233     sock_data_t *sd = (sock_data_t *) handle;
234     socklen_t from_length = 0;
236     if (!sd) {
237         error_msg("invalid hanlde");
238         return -1;
239     }
241     if (from) {
242         if((from->type == sock_addr_e) && (from->s.addr))
243             from_length = sizeof(struct sockaddr_un);
244         else {
245             error_msg("invalid from parameter");
246             return -1;
247         }
248     }
250     size = recvfrom(sd->fd, data, length, 0, (struct sockaddr *)((from_length) ? from->s.addr : NULL), &from_length);
251     if (size < 1) {
252         error_msg("can't read datagram from socket for %s (error: %s), size %d",
253                 sd->addr.sun_path, strerror(errno), size);
254         return -1;
255     }
257     return size;
258