Blame common-src/ambind.c

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