示例#1
1
文件: auxserver.c 项目: jujis008/pcp
/*
 * Create socket for incoming connections and bind to it an address for
 * clients to use.  Returns -1 on failure.
 *
 * If '*family' is AF_UNIX and unix domain sockets are supported:
 * 'port' is ignored and 'address' is the path to the socket file in the filesystem.
 *
 * Otherwise:
 * address is a string representing the Inet/IPv6 address that the port
 * is advertised for.  To allow connections to all this host's internet
 * addresses from clients use address == "INADDR_ANY", or for localhost
 * access only use address == "INADDR_LOOPBACK".
 * On input, 'family' is a pointer to the address family to use (AF_INET,
 * AF_INET6) if the address specified is empty.  If the spec is not
 * empty then family is ignored and is set to the actual address family
 * used. 'family' must be initialized to AF_UNSPEC, in this case.
 */
static int
OpenRequestSocket(int port, const char *address, int *family,
		  int backlog, __pmFdSet *fdset, int *maximum)
{
    int			fd = -1;
    int			one, sts;
    __pmSockAddr	*myAddr;
    int			isUnix = 0;

    /*
     * Using this flag will eliminate the need for more conditional
     * compilation below, hopefully making the code easier to read and maintain.
     */
#if defined(HAVE_STRUCT_SOCKADDR_UN)
    if (*family == AF_UNIX)
	isUnix = 1;
#endif

    if (isUnix) {
	if ((myAddr = __pmSockAddrAlloc()) == NULL) {
	    __pmNoMem("OpenRequestSocket: can't allocate socket address",
		      sizeof(*myAddr), PM_FATAL_ERR);
	}

	/* Initialize the address. */
	__pmSockAddrSetFamily(myAddr, *family);
	__pmSockAddrSetPath(myAddr, address);

	/* Create the socket. */
	fd = __pmCreateUnixSocket();
    }
    else {
	/*
	 * If the address is unspecified, then use the address family we
	 * have been given, otherwise the family will be determined by
	 * __pmStringToSockAddr.
	 */
	if (address == NULL || strcmp(address, "INADDR_ANY") == 0) {
	    if ((myAddr = __pmSockAddrAlloc()) == NULL) {
		__pmNoMem("OpenRequestSocket: can't allocate socket address",
			  sizeof(*myAddr), PM_FATAL_ERR);
	    }
	    __pmSockAddrInit(myAddr, *family, INADDR_ANY, 0);
	}
	else if (strcmp(address, "INADDR_LOOPBACK") == 0) {
	    if ((myAddr = __pmSockAddrAlloc()) == NULL) {
		__pmNoMem("OpenRequestSocket: can't allocate socket address",
			  sizeof(*myAddr), PM_FATAL_ERR);
	    }
	    __pmSockAddrInit(myAddr, *family, INADDR_LOOPBACK, 0);
	}
	else {
	    if ((myAddr = __pmStringToSockAddr(address)) == NULL) {
		__pmNotifyErr(LOG_ERR, "OpenRequestSocket(%d, %s) invalid address\n",
			      port, address);
		goto fail;
	    }
	    *family = __pmSockAddrGetFamily(myAddr);
	}
	__pmSockAddrSetPort(myAddr, port);

	/* Create the socket. */
	if (*family == AF_INET)
	    fd = __pmCreateSocket();
	else if (*family == AF_INET6)
	    fd = __pmCreateIPv6Socket();
	else {
	    __pmNotifyErr(LOG_ERR, "OpenRequestSocket(%d, %s) invalid address family: %d\n",
			  port, address, *family);
	    goto fail;
	}
    }

    if (fd < 0) {
	__pmNotifyErr(LOG_ERR, "OpenRequestSocket(%d, %s, %s) __pmCreateSocket: %s\n",
		port, address, AddressFamily(*family), netstrerror());
	goto fail;
    }

    /* Ignore dead client connections. */
    one = 1;
#ifndef IS_MINGW
    if (__pmSetSockOpt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one,
		       (__pmSockLen)sizeof(one)) < 0) {
	__pmNotifyErr(LOG_ERR,
		      "OpenRequestSocket(%d, %s, %s) __pmSetSockOpt(SO_REUSEADDR): %s\n",
		      port, address, AddressFamily(*family), netstrerror());
	goto fail;
    }
#else
    if (__pmSetSockOpt(fd, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char *)&one,
		       (__pmSockLen)sizeof(one)) < 0) {
	__pmNotifyErr(LOG_ERR,
		      "OpenRequestSocket(%d, %s, %s) __pmSetSockOpt(EXCLUSIVEADDRUSE): %s\n",
		      port, address, AddressFamily(*family), netstrerror());
	goto fail;
    }
#endif

    /* and keep alive please - bad networks eat fds */
    if (__pmSetSockOpt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&one,
		(__pmSockLen)sizeof(one)) < 0) {
	__pmNotifyErr(LOG_ERR,
		"OpenRequestSocket(%d, %s, %s) __pmSetSockOpt(SO_KEEPALIVE): %s\n",
		port, address, AddressFamily(*family), netstrerror());
	goto fail;
    }

    sts = __pmBind(fd, (void *)myAddr, __pmSockAddrSize());
    __pmSockAddrFree(myAddr);
    myAddr = NULL;
    if (sts < 0) {
	sts = neterror();
	__pmNotifyErr(LOG_ERR, "OpenRequestSocket(%d, %s, %s) __pmBind: %s\n",
		port, address, AddressFamily(*family), netstrerror());
	if (sts == EADDRINUSE)
	    __pmNotifyErr(LOG_ERR, "%s may already be running\n", pmProgname);
	goto fail;
    }

    if (isUnix) {
	/*
	 * For unix domain sockets, grant rw access to the socket for all,
	 * otherwise, on linux platforms, connection will not be possible.
	 * This must be done AFTER binding the address. See Unix(7) for details.
	 */
	sts = chmod(address, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
	if (sts != 0) {
	    __pmNotifyErr(LOG_ERR,
		"OpenRequestSocket(%d, %s, %s) chmod(%s): %s\n",
		port, address, AddressFamily(*family), address, strerror(errno));
	    goto fail;
	}
    }

    sts = __pmListen(fd, backlog);	/* Max. pending connection requests */
    if (sts < 0) {
	__pmNotifyErr(LOG_ERR, "OpenRequestSocket(%d, %s, %s) __pmListen: %s\n",
		port, address, AddressFamily(*family), netstrerror());
	goto fail;
    }

    if (fd > *maximum)
	*maximum = fd;
    __pmFD_SET(fd, fdset);
    return fd;

fail:
    if (fd != -1) {
        __pmCloseSocket(fd);
	/* We must unlink the socket file. */
	if (isUnix)
	    unlink(address);
    }
    if (myAddr)
        __pmSockAddrFree(myAddr);
    return -1;
}
示例#2
0
文件: client.c 项目: rwongone/pcp
int
NewClient(void)
{
    int i, sz;

    for (i = 0; i < nClients; i++)
        if (!client[i].status.connected)
            break;

    if (i == clientSize) {
        clientSize = clientSize ? clientSize * 2 : MIN_CLIENTS_ALLOC;
        sz = sizeof(ClientInfo) * clientSize;
        client = (ClientInfo *) realloc(client, sz);
        if (client == NULL) {
            __pmNoMem("NewClient", sz, PM_RECOV_ERR);
            Shutdown();
            exit(1);
        }
        sz -= (sizeof(ClientInfo) * i);
        memset(&client[i], 0, sz);
    }
    client[i].addr = __pmSockAddrAlloc();
    if (client[i].addr == NULL) {
        __pmNoMem("NewClient", __pmSockAddrSize(), PM_RECOV_ERR);
        Shutdown();
        exit(1);
    }
    if (i >= nClients)
        nClients = i + 1;
    return i;
}
示例#3
0
文件: client.c 项目: rwongone/pcp
/* Establish a new socket connection to a client */
ClientInfo *
AcceptNewClient(int reqfd)
{
    static unsigned int	seq = 0;
    int			i, fd;
    __pmSockLen		addrlen;
    struct timeval	now;

    i = NewClient();
    addrlen = __pmSockAddrSize();
    fd = __pmAccept(reqfd, client[i].addr, &addrlen);
    if (fd == -1) {
        if (neterror() == EPERM) {
            __pmNotifyErr(LOG_NOTICE, "AcceptNewClient(%d): "
                          "Permission Denied\n", reqfd);
            client[i].fd = -1;
            DeleteClient(&client[i]);
            return NULL;
        }
        else {
            __pmNotifyErr(LOG_ERR, "AcceptNewClient(%d) __pmAccept: %s\n",
                          reqfd, netstrerror());
            Shutdown();
            exit(1);
        }
    }
    if (fd > maxClientFd)
        maxClientFd = fd;

    pmcd_openfds_sethi(fd);

    __pmFD_SET(fd, &clientFds);
    __pmSetVersionIPC(fd, UNKNOWN_VERSION);	/* before negotiation */
    __pmSetSocketIPC(fd);

    client[i].fd = fd;
    client[i].status.connected = 1;
    client[i].status.changes = 0;
    memset(&client[i].attrs, 0, sizeof(__pmHashCtl));

    /*
     * Note seq needs to be unique, but we're using a free running counter
     * and not bothering to check here ... unless we churn through
     * 4,294,967,296 (2^32) clients while one client remains connected
     * we won't have a problem
     */
    client[i].seq = seq++;
    __pmtimevalNow(&now);
    client[i].start = now.tv_sec;

#ifdef PCP_DEBUG
    if (pmDebug & DBG_TRACE_APPL0)
        fprintf(stderr, "AcceptNewClient(%d): client[%d] (fd %d)\n", reqfd, i, fd);
#endif
    pmcd_trace(TR_ADD_CLIENT, i, 0, 0);

    return &client[i];
}
示例#4
0
文件: client.c 项目: jujis008/pcp
/* Establish a new socket connection to a client */
ClientInfo *
AcceptNewClient(int reqfd)
{
    int		i;
    int		fd;
    __pmSockLen	addrlen;
    int		ok = 0;
    char	buf[MY_BUFLEN];
    char	*bp;
    char	*endp;
    char	*abufp;

    i = NewClient();
    addrlen = __pmSockAddrSize();
    fd = __pmAccept(reqfd, client[i].addr, &addrlen);
    if (fd == -1) {
	__pmNotifyErr(LOG_ERR, "AcceptNewClient(%d) __pmAccept failed: %s",
			reqfd, netstrerror());
	Shutdown();
	exit(1);
    }
    __pmSetSocketIPC(fd);
    if (fd > maxSockFd)
	maxSockFd = fd;
    __pmFD_SET(fd, &sockFds);

    client[i].fd = fd;
    client[i].pmcd_fd = -1;
    client[i].status.connected = 1;
    client[i].status.allowed = 0;
    client[i].pmcd_hostname = NULL;

    /*
     * version negotiation (converse to negotiate_proxy() logic in
     * libpcp
     *
     *   __pmRecv client version message
     *   __pmSend my server version message
     *   __pmRecv pmcd hostname and pmcd port
     */
    for (bp = buf; bp < &buf[MY_BUFLEN]; bp++) {
	if (__pmRecv(fd, bp, 1, 0) != 1) {
	    *bp = '\0';		/* null terminate what we have */
	    bp = &buf[MY_BUFLEN];	/* flag error */
	    break;
	}
	/* end of line means no more ... */
	if (*bp == '\n' || *bp == '\r') {
	    *bp = '\0';
	    break;
	}
    }
    if (bp < &buf[MY_BUFLEN]) {
	/* looks OK so far ... is this a version we can support? */
	if (strcmp(buf, "pmproxy-client 1") == 0) {
	    client[i].version = 1;
	    ok = 1;
	}
    }

    if (!ok) {
#ifdef PCP_DEBUG
	if (pmDebug & DBG_TRACE_CONTEXT) {
	    abufp = __pmSockAddrToString(client[i].addr);
	    __pmNotifyErr(LOG_INFO, "Bad version string from client at %s",
			abufp);
	    free(abufp);
	    fprintf(stderr, "AcceptNewClient: bad version string was \"");
	    for (bp = buf; *bp && bp < &buf[MY_BUFLEN]; bp++)
		fputc(*bp & 0xff, stderr);
	    fprintf(stderr, "\"\n");
	}
#endif
	DeleteClient(&client[i]);
	return NULL;
    }

    if (__pmSend(fd, MY_VERSION, strlen(MY_VERSION), 0) != strlen(MY_VERSION)) {
	abufp = __pmSockAddrToString(client[i].addr);
	__pmNotifyErr(LOG_WARNING, "AcceptNewClient: failed to send version "
			"string (%s) to client at %s\n", MY_VERSION, abufp);
	free(abufp);
	DeleteClient(&client[i]);
	return NULL;
    }

    for (bp = buf; bp < &buf[MY_BUFLEN]; bp++) {
	if (__pmRecv(fd, bp, 1, 0) != 1) {
	    *bp = '\0';		/* null terminate what we have */
	    bp = &buf[MY_BUFLEN];	/* flag error */
	    break;
	}
	/* end of line means no more ... */
	if (*bp == '\n' || *bp == '\r') {
	    *bp = '\0';
	    break;
	}
    }
    if (bp < &buf[MY_BUFLEN]) {
	/* looks OK so far ... get hostname and port */
	for (bp = buf; *bp && *bp != ' '; bp++)
	    ;
	if (bp != buf) {
	    *bp = '\0';
	    client[i].pmcd_hostname = strdup(buf);
	    if (client[i].pmcd_hostname == NULL)
		__pmNoMem("PMCD.hostname", strlen(buf), PM_FATAL_ERR);
	    bp++;
	    client[i].pmcd_port = (int)strtoul(bp, &endp, 10);
	    if (*endp != '\0') {
		abufp = __pmSockAddrToString(client[i].addr);
		__pmNotifyErr(LOG_WARNING, "AcceptNewClient: bad pmcd port "
				"\"%s\" from client at %s", bp, abufp);
		free(abufp);
		DeleteClient(&client[i]);
		return NULL;
	    }
	}
	/* error, fall through */
    }

    if (client[i].pmcd_hostname == NULL) {
	abufp = __pmSockAddrToString(client[i].addr);
	__pmNotifyErr(LOG_WARNING, "AcceptNewClient: failed to get PMCD "
				"hostname (%s) from client at %s", buf, abufp);
	free(abufp);
	DeleteClient(&client[i]);
	return NULL;
    }

#ifdef PCP_DEBUG
    if (pmDebug & DBG_TRACE_CONTEXT) {
	/*
	 * note error message gets appended to once pmcd connection is
	 * made in ClientLoop()
	 */
	abufp = __pmSockAddrToString(client[i].addr);
	fprintf(stderr, "AcceptNewClient [%d] fd=%d from %s to %s (port %s)",
		i, fd, abufp, client[i].pmcd_hostname, bp);
	free(abufp);
    }
#endif

    return &client[i];
}