| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <unistd.h> |
| #include <sys/types.h> |
| #include <sys/socket.h> |
| #include <sys/time.h> |
| #include <sys/un.h> |
| #include <errno.h> |
| |
| #include "ipcsocket.h" |
| |
| |
| int opensocket(int *sockfd, const char *name, int connecttype) |
| { |
| int ret, temp = 1; |
| |
| if (!name || strlen(name) > MAX_SOCK_NAME_LEN) { |
| fprintf(stderr, "<%s>: Invalid socket name.\n", __func__); |
| return -1; |
| } |
| |
| ret = socket(PF_LOCAL, SOCK_STREAM, 0); |
| if (ret < 0) { |
| fprintf(stderr, "<%s>: Failed socket: <%s>\n", |
| __func__, strerror(errno)); |
| return ret; |
| } |
| |
| *sockfd = ret; |
| if (setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR, |
| (char *)&temp, sizeof(int)) < 0) { |
| fprintf(stderr, "<%s>: Failed setsockopt: <%s>\n", |
| __func__, strerror(errno)); |
| goto err; |
| } |
| |
| sprintf(sock_name, "/tmp/%s", name); |
| |
| if (connecttype == 1) { |
| /* This is for Server connection */ |
| struct sockaddr_un skaddr; |
| int clientfd; |
| socklen_t sklen; |
| |
| unlink(sock_name); |
| memset(&skaddr, 0, sizeof(skaddr)); |
| skaddr.sun_family = AF_LOCAL; |
| strcpy(skaddr.sun_path, sock_name); |
| |
| ret = bind(*sockfd, (struct sockaddr *)&skaddr, |
| SUN_LEN(&skaddr)); |
| if (ret < 0) { |
| fprintf(stderr, "<%s>: Failed bind: <%s>\n", |
| __func__, strerror(errno)); |
| goto err; |
| } |
| |
| ret = listen(*sockfd, 5); |
| if (ret < 0) { |
| fprintf(stderr, "<%s>: Failed listen: <%s>\n", |
| __func__, strerror(errno)); |
| goto err; |
| } |
| |
| memset(&skaddr, 0, sizeof(skaddr)); |
| sklen = sizeof(skaddr); |
| |
| ret = accept(*sockfd, (struct sockaddr *)&skaddr, |
| (socklen_t *)&sklen); |
| if (ret < 0) { |
| fprintf(stderr, "<%s>: Failed accept: <%s>\n", |
| __func__, strerror(errno)); |
| goto err; |
| } |
| |
| clientfd = ret; |
| *sockfd = clientfd; |
| } else { |
| /* This is for client connection */ |
| struct sockaddr_un skaddr; |
| |
| memset(&skaddr, 0, sizeof(skaddr)); |
| skaddr.sun_family = AF_LOCAL; |
| strcpy(skaddr.sun_path, sock_name); |
| |
| ret = connect(*sockfd, (struct sockaddr *)&skaddr, |
| SUN_LEN(&skaddr)); |
| if (ret < 0) { |
| fprintf(stderr, "<%s>: Failed connect: <%s>\n", |
| __func__, strerror(errno)); |
| goto err; |
| } |
| } |
| |
| return 0; |
| |
| err: |
| if (*sockfd) |
| close(*sockfd); |
| |
| return ret; |
| } |
| |
| int sendtosocket(int sockfd, struct socketdata *skdata) |
| { |
| int ret, buffd; |
| unsigned int len; |
| char cmsg_b[CMSG_SPACE(sizeof(int))]; |
| struct cmsghdr *cmsg; |
| struct msghdr msgh; |
| struct iovec iov; |
| struct timeval timeout; |
| fd_set selFDs; |
| |
| if (!skdata) { |
| fprintf(stderr, "<%s>: socketdata is NULL\n", __func__); |
| return -1; |
| } |
| |
| FD_ZERO(&selFDs); |
| FD_SET(0, &selFDs); |
| FD_SET(sockfd, &selFDs); |
| timeout.tv_sec = 20; |
| timeout.tv_usec = 0; |
| |
| ret = select(sockfd+1, NULL, &selFDs, NULL, &timeout); |
| if (ret < 0) { |
| fprintf(stderr, "<%s>: Failed select: <%s>\n", |
| __func__, strerror(errno)); |
| return -1; |
| } |
| |
| if (FD_ISSET(sockfd, &selFDs)) { |
| buffd = skdata->data; |
| len = skdata->len; |
| memset(&msgh, 0, sizeof(msgh)); |
| msgh.msg_control = &cmsg_b; |
| msgh.msg_controllen = CMSG_LEN(len); |
| iov.iov_base = "OK"; |
| iov.iov_len = 2; |
| msgh.msg_iov = &iov; |
| msgh.msg_iovlen = 1; |
| cmsg = CMSG_FIRSTHDR(&msgh); |
| cmsg->cmsg_level = SOL_SOCKET; |
| cmsg->cmsg_type = SCM_RIGHTS; |
| cmsg->cmsg_len = CMSG_LEN(len); |
| memcpy(CMSG_DATA(cmsg), &buffd, len); |
| |
| ret = sendmsg(sockfd, &msgh, MSG_DONTWAIT); |
| if (ret < 0) { |
| fprintf(stderr, "<%s>: Failed sendmsg: <%s>\n", |
| __func__, strerror(errno)); |
| return -1; |
| } |
| } |
| |
| return 0; |
| } |
| |
| int receivefromsocket(int sockfd, struct socketdata *skdata) |
| { |
| int ret, buffd; |
| unsigned int len = 0; |
| char cmsg_b[CMSG_SPACE(sizeof(int))]; |
| struct cmsghdr *cmsg; |
| struct msghdr msgh; |
| struct iovec iov; |
| fd_set recvFDs; |
| char data[32]; |
| |
| if (!skdata) { |
| fprintf(stderr, "<%s>: socketdata is NULL\n", __func__); |
| return -1; |
| } |
| |
| FD_ZERO(&recvFDs); |
| FD_SET(0, &recvFDs); |
| FD_SET(sockfd, &recvFDs); |
| |
| ret = select(sockfd+1, &recvFDs, NULL, NULL, NULL); |
| if (ret < 0) { |
| fprintf(stderr, "<%s>: Failed select: <%s>\n", |
| __func__, strerror(errno)); |
| return -1; |
| } |
| |
| if (FD_ISSET(sockfd, &recvFDs)) { |
| len = sizeof(buffd); |
| memset(&msgh, 0, sizeof(msgh)); |
| msgh.msg_control = &cmsg_b; |
| msgh.msg_controllen = CMSG_LEN(len); |
| iov.iov_base = data; |
| iov.iov_len = sizeof(data)-1; |
| msgh.msg_iov = &iov; |
| msgh.msg_iovlen = 1; |
| cmsg = CMSG_FIRSTHDR(&msgh); |
| cmsg->cmsg_level = SOL_SOCKET; |
| cmsg->cmsg_type = SCM_RIGHTS; |
| cmsg->cmsg_len = CMSG_LEN(len); |
| |
| ret = recvmsg(sockfd, &msgh, MSG_DONTWAIT); |
| if (ret < 0) { |
| fprintf(stderr, "<%s>: Failed recvmsg: <%s>\n", |
| __func__, strerror(errno)); |
| return -1; |
| } |
| |
| memcpy(&buffd, CMSG_DATA(cmsg), len); |
| skdata->data = buffd; |
| skdata->len = len; |
| } |
| return 0; |
| } |
| |
| int closesocket(int sockfd, char *name) |
| { |
| char sockname[MAX_SOCK_NAME_LEN]; |
| |
| if (sockfd) |
| close(sockfd); |
| sprintf(sockname, "/tmp/%s", name); |
| unlink(sockname); |
| shutdown(sockfd, 2); |
| |
| return 0; |
| } |