18c2ecf20Sopenharmony_ci#include <stdio.h> 28c2ecf20Sopenharmony_ci#include <stdlib.h> 38c2ecf20Sopenharmony_ci#include <string.h> 48c2ecf20Sopenharmony_ci#include <unistd.h> 58c2ecf20Sopenharmony_ci#include <sys/types.h> 68c2ecf20Sopenharmony_ci#include <sys/socket.h> 78c2ecf20Sopenharmony_ci#include <sys/time.h> 88c2ecf20Sopenharmony_ci#include <sys/un.h> 98c2ecf20Sopenharmony_ci#include <errno.h> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include "ipcsocket.h" 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ciint opensocket(int *sockfd, const char *name, int connecttype) 158c2ecf20Sopenharmony_ci{ 168c2ecf20Sopenharmony_ci int ret, temp = 1; 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci if (!name || strlen(name) > MAX_SOCK_NAME_LEN) { 198c2ecf20Sopenharmony_ci fprintf(stderr, "<%s>: Invalid socket name.\n", __func__); 208c2ecf20Sopenharmony_ci return -1; 218c2ecf20Sopenharmony_ci } 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci ret = socket(PF_LOCAL, SOCK_STREAM, 0); 248c2ecf20Sopenharmony_ci if (ret < 0) { 258c2ecf20Sopenharmony_ci fprintf(stderr, "<%s>: Failed socket: <%s>\n", 268c2ecf20Sopenharmony_ci __func__, strerror(errno)); 278c2ecf20Sopenharmony_ci return ret; 288c2ecf20Sopenharmony_ci } 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci *sockfd = ret; 318c2ecf20Sopenharmony_ci if (setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR, 328c2ecf20Sopenharmony_ci (char *)&temp, sizeof(int)) < 0) { 338c2ecf20Sopenharmony_ci fprintf(stderr, "<%s>: Failed setsockopt: <%s>\n", 348c2ecf20Sopenharmony_ci __func__, strerror(errno)); 358c2ecf20Sopenharmony_ci goto err; 368c2ecf20Sopenharmony_ci } 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci sprintf(sock_name, "/tmp/%s", name); 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci if (connecttype == 1) { 418c2ecf20Sopenharmony_ci /* This is for Server connection */ 428c2ecf20Sopenharmony_ci struct sockaddr_un skaddr; 438c2ecf20Sopenharmony_ci int clientfd; 448c2ecf20Sopenharmony_ci socklen_t sklen; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci unlink(sock_name); 478c2ecf20Sopenharmony_ci memset(&skaddr, 0, sizeof(skaddr)); 488c2ecf20Sopenharmony_ci skaddr.sun_family = AF_LOCAL; 498c2ecf20Sopenharmony_ci strcpy(skaddr.sun_path, sock_name); 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci ret = bind(*sockfd, (struct sockaddr *)&skaddr, 528c2ecf20Sopenharmony_ci SUN_LEN(&skaddr)); 538c2ecf20Sopenharmony_ci if (ret < 0) { 548c2ecf20Sopenharmony_ci fprintf(stderr, "<%s>: Failed bind: <%s>\n", 558c2ecf20Sopenharmony_ci __func__, strerror(errno)); 568c2ecf20Sopenharmony_ci goto err; 578c2ecf20Sopenharmony_ci } 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci ret = listen(*sockfd, 5); 608c2ecf20Sopenharmony_ci if (ret < 0) { 618c2ecf20Sopenharmony_ci fprintf(stderr, "<%s>: Failed listen: <%s>\n", 628c2ecf20Sopenharmony_ci __func__, strerror(errno)); 638c2ecf20Sopenharmony_ci goto err; 648c2ecf20Sopenharmony_ci } 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci memset(&skaddr, 0, sizeof(skaddr)); 678c2ecf20Sopenharmony_ci sklen = sizeof(skaddr); 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci ret = accept(*sockfd, (struct sockaddr *)&skaddr, 708c2ecf20Sopenharmony_ci (socklen_t *)&sklen); 718c2ecf20Sopenharmony_ci if (ret < 0) { 728c2ecf20Sopenharmony_ci fprintf(stderr, "<%s>: Failed accept: <%s>\n", 738c2ecf20Sopenharmony_ci __func__, strerror(errno)); 748c2ecf20Sopenharmony_ci goto err; 758c2ecf20Sopenharmony_ci } 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci clientfd = ret; 788c2ecf20Sopenharmony_ci *sockfd = clientfd; 798c2ecf20Sopenharmony_ci } else { 808c2ecf20Sopenharmony_ci /* This is for client connection */ 818c2ecf20Sopenharmony_ci struct sockaddr_un skaddr; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci memset(&skaddr, 0, sizeof(skaddr)); 848c2ecf20Sopenharmony_ci skaddr.sun_family = AF_LOCAL; 858c2ecf20Sopenharmony_ci strcpy(skaddr.sun_path, sock_name); 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci ret = connect(*sockfd, (struct sockaddr *)&skaddr, 888c2ecf20Sopenharmony_ci SUN_LEN(&skaddr)); 898c2ecf20Sopenharmony_ci if (ret < 0) { 908c2ecf20Sopenharmony_ci fprintf(stderr, "<%s>: Failed connect: <%s>\n", 918c2ecf20Sopenharmony_ci __func__, strerror(errno)); 928c2ecf20Sopenharmony_ci goto err; 938c2ecf20Sopenharmony_ci } 948c2ecf20Sopenharmony_ci } 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci return 0; 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_cierr: 998c2ecf20Sopenharmony_ci if (*sockfd) 1008c2ecf20Sopenharmony_ci close(*sockfd); 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci return ret; 1038c2ecf20Sopenharmony_ci} 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ciint sendtosocket(int sockfd, struct socketdata *skdata) 1068c2ecf20Sopenharmony_ci{ 1078c2ecf20Sopenharmony_ci int ret, buffd; 1088c2ecf20Sopenharmony_ci unsigned int len; 1098c2ecf20Sopenharmony_ci char cmsg_b[CMSG_SPACE(sizeof(int))]; 1108c2ecf20Sopenharmony_ci struct cmsghdr *cmsg; 1118c2ecf20Sopenharmony_ci struct msghdr msgh; 1128c2ecf20Sopenharmony_ci struct iovec iov; 1138c2ecf20Sopenharmony_ci struct timeval timeout; 1148c2ecf20Sopenharmony_ci fd_set selFDs; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci if (!skdata) { 1178c2ecf20Sopenharmony_ci fprintf(stderr, "<%s>: socketdata is NULL\n", __func__); 1188c2ecf20Sopenharmony_ci return -1; 1198c2ecf20Sopenharmony_ci } 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci FD_ZERO(&selFDs); 1228c2ecf20Sopenharmony_ci FD_SET(0, &selFDs); 1238c2ecf20Sopenharmony_ci FD_SET(sockfd, &selFDs); 1248c2ecf20Sopenharmony_ci timeout.tv_sec = 20; 1258c2ecf20Sopenharmony_ci timeout.tv_usec = 0; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci ret = select(sockfd+1, NULL, &selFDs, NULL, &timeout); 1288c2ecf20Sopenharmony_ci if (ret < 0) { 1298c2ecf20Sopenharmony_ci fprintf(stderr, "<%s>: Failed select: <%s>\n", 1308c2ecf20Sopenharmony_ci __func__, strerror(errno)); 1318c2ecf20Sopenharmony_ci return -1; 1328c2ecf20Sopenharmony_ci } 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci if (FD_ISSET(sockfd, &selFDs)) { 1358c2ecf20Sopenharmony_ci buffd = skdata->data; 1368c2ecf20Sopenharmony_ci len = skdata->len; 1378c2ecf20Sopenharmony_ci memset(&msgh, 0, sizeof(msgh)); 1388c2ecf20Sopenharmony_ci msgh.msg_control = &cmsg_b; 1398c2ecf20Sopenharmony_ci msgh.msg_controllen = CMSG_LEN(len); 1408c2ecf20Sopenharmony_ci iov.iov_base = "OK"; 1418c2ecf20Sopenharmony_ci iov.iov_len = 2; 1428c2ecf20Sopenharmony_ci msgh.msg_iov = &iov; 1438c2ecf20Sopenharmony_ci msgh.msg_iovlen = 1; 1448c2ecf20Sopenharmony_ci cmsg = CMSG_FIRSTHDR(&msgh); 1458c2ecf20Sopenharmony_ci cmsg->cmsg_level = SOL_SOCKET; 1468c2ecf20Sopenharmony_ci cmsg->cmsg_type = SCM_RIGHTS; 1478c2ecf20Sopenharmony_ci cmsg->cmsg_len = CMSG_LEN(len); 1488c2ecf20Sopenharmony_ci memcpy(CMSG_DATA(cmsg), &buffd, len); 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci ret = sendmsg(sockfd, &msgh, MSG_DONTWAIT); 1518c2ecf20Sopenharmony_ci if (ret < 0) { 1528c2ecf20Sopenharmony_ci fprintf(stderr, "<%s>: Failed sendmsg: <%s>\n", 1538c2ecf20Sopenharmony_ci __func__, strerror(errno)); 1548c2ecf20Sopenharmony_ci return -1; 1558c2ecf20Sopenharmony_ci } 1568c2ecf20Sopenharmony_ci } 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci return 0; 1598c2ecf20Sopenharmony_ci} 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ciint receivefromsocket(int sockfd, struct socketdata *skdata) 1628c2ecf20Sopenharmony_ci{ 1638c2ecf20Sopenharmony_ci int ret, buffd; 1648c2ecf20Sopenharmony_ci unsigned int len = 0; 1658c2ecf20Sopenharmony_ci char cmsg_b[CMSG_SPACE(sizeof(int))]; 1668c2ecf20Sopenharmony_ci struct cmsghdr *cmsg; 1678c2ecf20Sopenharmony_ci struct msghdr msgh; 1688c2ecf20Sopenharmony_ci struct iovec iov; 1698c2ecf20Sopenharmony_ci fd_set recvFDs; 1708c2ecf20Sopenharmony_ci char data[32]; 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci if (!skdata) { 1738c2ecf20Sopenharmony_ci fprintf(stderr, "<%s>: socketdata is NULL\n", __func__); 1748c2ecf20Sopenharmony_ci return -1; 1758c2ecf20Sopenharmony_ci } 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci FD_ZERO(&recvFDs); 1788c2ecf20Sopenharmony_ci FD_SET(0, &recvFDs); 1798c2ecf20Sopenharmony_ci FD_SET(sockfd, &recvFDs); 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci ret = select(sockfd+1, &recvFDs, NULL, NULL, NULL); 1828c2ecf20Sopenharmony_ci if (ret < 0) { 1838c2ecf20Sopenharmony_ci fprintf(stderr, "<%s>: Failed select: <%s>\n", 1848c2ecf20Sopenharmony_ci __func__, strerror(errno)); 1858c2ecf20Sopenharmony_ci return -1; 1868c2ecf20Sopenharmony_ci } 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci if (FD_ISSET(sockfd, &recvFDs)) { 1898c2ecf20Sopenharmony_ci len = sizeof(buffd); 1908c2ecf20Sopenharmony_ci memset(&msgh, 0, sizeof(msgh)); 1918c2ecf20Sopenharmony_ci msgh.msg_control = &cmsg_b; 1928c2ecf20Sopenharmony_ci msgh.msg_controllen = CMSG_LEN(len); 1938c2ecf20Sopenharmony_ci iov.iov_base = data; 1948c2ecf20Sopenharmony_ci iov.iov_len = sizeof(data)-1; 1958c2ecf20Sopenharmony_ci msgh.msg_iov = &iov; 1968c2ecf20Sopenharmony_ci msgh.msg_iovlen = 1; 1978c2ecf20Sopenharmony_ci cmsg = CMSG_FIRSTHDR(&msgh); 1988c2ecf20Sopenharmony_ci cmsg->cmsg_level = SOL_SOCKET; 1998c2ecf20Sopenharmony_ci cmsg->cmsg_type = SCM_RIGHTS; 2008c2ecf20Sopenharmony_ci cmsg->cmsg_len = CMSG_LEN(len); 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci ret = recvmsg(sockfd, &msgh, MSG_DONTWAIT); 2038c2ecf20Sopenharmony_ci if (ret < 0) { 2048c2ecf20Sopenharmony_ci fprintf(stderr, "<%s>: Failed recvmsg: <%s>\n", 2058c2ecf20Sopenharmony_ci __func__, strerror(errno)); 2068c2ecf20Sopenharmony_ci return -1; 2078c2ecf20Sopenharmony_ci } 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci memcpy(&buffd, CMSG_DATA(cmsg), len); 2108c2ecf20Sopenharmony_ci skdata->data = buffd; 2118c2ecf20Sopenharmony_ci skdata->len = len; 2128c2ecf20Sopenharmony_ci } 2138c2ecf20Sopenharmony_ci return 0; 2148c2ecf20Sopenharmony_ci} 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ciint closesocket(int sockfd, char *name) 2178c2ecf20Sopenharmony_ci{ 2188c2ecf20Sopenharmony_ci char sockname[MAX_SOCK_NAME_LEN]; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci if (sockfd) 2218c2ecf20Sopenharmony_ci close(sockfd); 2228c2ecf20Sopenharmony_ci sprintf(sockname, "/tmp/%s", name); 2238c2ecf20Sopenharmony_ci unlink(sockname); 2248c2ecf20Sopenharmony_ci shutdown(sockfd, 2); 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci return 0; 2278c2ecf20Sopenharmony_ci} 228