xref: /f-stack/tools/compat/rtioctl.c (revision 92bcc6b4)
1 /*
2  * Copyright (C) 2017 THL A29 Limited, a Tencent company.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this
9  *   list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright notice,
11  *   this list of conditions and the following disclaimer in the documentation
12  *   and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
18  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  */
26 
27 #include <string.h>
28 #include <errno.h>
29 #include <sys/socket.h>
30 
31 #include "rtioctl.h"
32 #include "ff_ipc.h"
33 
34 int rt_shutdown_rd = 0;
35 int rt_sofib = 0;
36 
37 int
38 rt_socket(int domain, int type, int protocol)
39 {
40     if (domain != PF_ROUTE || type != SOCK_RAW) {
41         errno = EINVAL;
42         return -1;
43     }
44 
45     return 0;
46 }
47 
48 int
49 rt_shutdown(int fd, int how)
50 {
51     if (how == SHUT_RD) {
52         rt_shutdown_rd = 1;
53     }
54     return 0;
55 }
56 
57 int
58 rt_setsockopt(int sockfd, int level, int optname,
59     const void *optval, socklen_t optlen)
60 {
61     if (level == SOL_SOCKET && optname == SO_SETFIB) {
62         rt_sofib = *(int *)optval;
63     }
64     return 0;
65 }
66 
67 void
68 rt_close(int fd)
69 {
70     return;
71 }
72 
73 int
74 rtioctl(char *data, unsigned len, unsigned read_len)
75 {
76     struct ff_msg *msg, *retmsg = NULL;
77     unsigned maxlen;
78 
79     msg = ff_ipc_msg_alloc();
80     if (msg == NULL) {
81         errno = ENOMEM;
82         return -1;
83     }
84 
85     if (len > msg->buf_len) {
86         errno = EINVAL;
87         ff_ipc_msg_free(msg);
88         return -1;
89     }
90 
91     if (read_len > msg->buf_len) {
92         read_len = msg->buf_len;
93     }
94 
95     maxlen = read_len ? read_len : len;
96 
97     msg->msg_type = FF_ROUTE;
98     msg->route.fib = rt_sofib;
99     msg->route.len = len;
100     msg->route.maxlen = maxlen;
101     msg->route.data = msg->buf_addr;
102     memcpy(msg->route.data, data, len);
103     msg->buf_addr += len;
104 
105     int ret = ff_ipc_send(msg);
106     if (ret < 0) {
107         errno = EPIPE;
108         ff_ipc_msg_free(msg);
109         return -1;
110     }
111 
112     do {
113         if (retmsg != NULL) {
114             ff_ipc_msg_free(retmsg);
115         }
116         ret = ff_ipc_recv(&retmsg, msg->msg_type);
117         if (ret < 0) {
118             errno = EPIPE;
119             return -1;
120         }
121     } while (msg != retmsg);
122 
123     if (retmsg->result == 0) {
124         ret = retmsg->route.len;
125 
126         if (!rt_shutdown_rd && read_len > 0) {
127             memcpy(data, retmsg->route.data, retmsg->route.len);
128         }
129     } else {
130         ret = -1;
131         errno = retmsg->result;
132     }
133 
134     ff_ipc_msg_free(msg);
135 
136     return ret;
137 }
138 
139