/*
* Amanda, The Advanced Maryland Automatic Network Disk Archiver
* Copyright (c) 2016-2016 Carbonite, Inc. All Rights Reserved.
* All Rights Reserved.
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of U.M. not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. U.M. makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* Authors: the Amanda Development Team. Its members are listed in a
* file named AUTHORS, in the root directory of this distribution.
*/
#include <config.h>
#include <sys/types.h>
#include <netinet/in.h>
#include "sockaddr-util.h"
#include <sys/socket.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include "security-file.h"
int
main(
int argc,
char ** argv)
{
int s;
int r;
int rc;
struct msghdr msg;
struct msghdr msg_socket;
struct msghdr msg_ambind_data;
struct cmsghdr *cmsg;
char cmsg_socket[CMSG_SPACE(sizeof(s))];
char cmsgbuf[CMSG_SPACE(sizeof(s))];
ambind_t ambind;
struct iovec iov[2];
int sockfd;
if (argc < 2) {
}
sockfd = atoi(argv[1]);
do {
struct timeval timeout = { 5, 0 };
fd_set readSet;
FD_ZERO(&readSet);
FD_SET(sockfd, &readSet);
rc = select(sockfd+1, &readSet, NULL, NULL, &timeout);
} while (rc < 0 && errno == EINTR);
if (rc <= 0) {
fprintf(stderr, "ambind: select failed: %s\n", strerror(errno));
shutdown(sockfd, SHUT_RDWR);
return -1;
}
// read the message socket msg
memset(&msg_socket, 0, sizeof(msg_socket));
msg_socket.msg_control = cmsg_socket;
msg_socket.msg_controllen = sizeof(cmsg_socket);
rc = recvmsg(sockfd, &msg_socket, 0);
if (rc == -1) {
fprintf(stderr, "ambind: first recvmsg failed: %s\n", strerror(errno));
exit(1);
}
cmsg = CMSG_FIRSTHDR(&msg_socket);
if (cmsg == NULL || cmsg -> cmsg_type != SCM_RIGHTS) {
fprintf(stderr, "ambind: The first control structure contains no file descriptor.\n");
exit(2);
}
memcpy(&s, CMSG_DATA(cmsg), sizeof(s));
do {
struct timeval timeout = { 5, 0 };
fd_set readSet;
FD_ZERO(&readSet);
FD_SET(sockfd, &readSet);
rc = select(sockfd+1, &readSet, NULL, NULL, &timeout);
} while (rc < 0 && errno == EINTR);
if (rc <= 0) {
fprintf(stderr, "ambind: select failed: %s\n", strerror(errno));
shutdown(sockfd, SHUT_RDWR);
return -1;
}
// read the ambind msg
memset(&msg_ambind_data, 0, sizeof(msg_ambind_data));
iov[0].iov_base = &ambind;
iov[0].iov_len = sizeof(ambind_t);
iov[1].iov_base = NULL;
iov[1].iov_len = 0;
msg_ambind_data.msg_iov = iov;
msg_ambind_data.msg_iovlen = 1;
rc = recvmsg(sockfd, &msg_ambind_data, 0);
if (rc == -1) {
fprintf(stderr, "ambind: second recvmsg failed: %s\n", strerror(errno));
shutdown(sockfd, SHUT_RDWR);
exit(2);
}
if (rc != sizeof(ambind_t)) {
fprintf(stderr, "ambind: recvmsg failed: size == %d\n", rc);
shutdown(sockfd, SHUT_RDWR);
exit(2);
}
if (!security_allow_bind(s, &ambind.addr)) {
shutdown(sockfd, SHUT_RDWR);
exit(2);
}
r = bind(s, (struct sockaddr *)&ambind.addr, ambind.socklen);
if (r != 0) {
if (errno != EADDRINUSE) {
fprintf(stderr, "ambind: bind failed A: %s\n", strerror(errno));
shutdown(sockfd, SHUT_RDWR);
exit(2);
}
fprintf(stderr, "WARNING: ambind: bind failed B: %s\n", strerror(errno));
if (shutdown(sockfd, SHUT_RDWR) < 0) {
fprintf(stderr, "ambind: shutdown failed B: %s\n", strerror(errno));
exit(1);
}
exit(1);
}
memset(&msg,0, sizeof(msg));
msg.msg_control = cmsgbuf;
msg.msg_controllen = sizeof(cmsgbuf);
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(s));
memcpy(CMSG_DATA(cmsg), &s, sizeof(s));
msg.msg_controllen = cmsg->cmsg_len;
// send the socket
if ((sendmsg(sockfd, &msg, 0)) < 0) {
fprintf(stderr, "ambind: sendmsg failed: %s\n", strerror(errno));
exit(1);
}
if (shutdown(sockfd, SHUT_RDWR) < 0) {
fprintf(stderr, "ambind: shutdown failed C: %s\n", strerror(errno));
exit(1);
}
exit(0);
}