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