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 28 29 #include <sys/types.h> 30 #include <sys/socket.h> 31 #include <string.h> 32 33 #include "ff_ipc.h" 34 35 static int 36 ipfw_ctl(int cmd, int level, int optname, void *optval, socklen_t *optlen) 37 { 38 struct ff_msg *msg, *retmsg = NULL; 39 int len; 40 41 switch (cmd) { 42 case FF_IPFW_GET: 43 if (optval == NULL || optlen == NULL) { 44 return EINVAL; 45 } 46 break; 47 case FF_IPFW_SET: 48 break; 49 default: 50 return EINVAL; 51 } 52 53 msg = ff_ipc_msg_alloc(); 54 if (msg == NULL) { 55 errno = ENOMEM; 56 return -1; 57 } 58 59 len = sizeof(struct ff_ipfw_args) + *optlen + sizeof(socklen_t); 60 if (len > msg->buf_len) { 61 errno = EINVAL; 62 ff_ipc_msg_free(msg); 63 return -1; 64 } 65 66 msg->msg_type = FF_IPFW_CTL; 67 msg->ipfw.cmd = cmd; 68 msg->ipfw.level = level; 69 msg->ipfw.optname = optname; 70 msg->ipfw.optval = (void *)msg->buf_addr; 71 msg->ipfw.optlen = (socklen_t *)(msg->buf_addr + (*optlen)); 72 73 memcpy(msg->ipfw.optval, optval, *optlen); 74 memcpy(msg->ipfw.optlen, optlen, sizeof(socklen_t)); 75 76 int ret = ff_ipc_send(msg); 77 if (ret < 0) { 78 errno = EPIPE; 79 ff_ipc_msg_free(msg); 80 return -1; 81 } 82 83 do { 84 if (retmsg != NULL) { 85 ff_ipc_msg_free(retmsg); 86 } 87 ret = ff_ipc_recv(&retmsg, msg->msg_type); 88 if (ret < 0) { 89 errno = EPIPE; 90 return -1; 91 } 92 } while (msg != retmsg); 93 94 if (retmsg->result != 0) { 95 ret = -1; 96 errno = retmsg->result; 97 } else { 98 ret = 0; 99 100 if (cmd == FF_IPFW_GET) { 101 memcpy(optval, retmsg->ipfw.optval, *(retmsg->ipfw.optlen)); 102 memcpy(optlen, retmsg->ipfw.optlen, sizeof(socklen_t)); 103 } 104 } 105 106 ff_ipc_msg_free(msg); 107 108 return ret; 109 } 110 111 int 112 ff_socket(int domain, int type, int protocol) 113 { 114 return 0; 115 } 116 117 int ff_getsockopt(int sockfd, int level, int optname, 118 void *optval, socklen_t *optlen) 119 { 120 return ipfw_ctl(FF_IPFW_GET, level, optname, optval, optlen); 121 } 122 123 int ff_setsockopt(int sockfd, int level, int optname, 124 const void *optval, socklen_t optlen) 125 { 126 return ipfw_ctl(FF_IPFW_SET, level, optname, (void *)optval, &optlen); 127 } 128 129