Ejemplo n.º 1
0
/*
 * "inet_ntoa/inet_pton" for struct sockaddr_gen
 */
static const char *
sgen_toa(struct sockaddr_gen *addr)
{
    static char buf[INET6_ADDRSTRLEN];
    return (inet_ntop(SGFAM(addr), SGADDRP(addr), buf, sizeof (buf)));
}
Ejemplo n.º 2
0
SERVER *
server_init(int fd,
	    const struct sockaddr_gen *sg,
	    int backlog,
	    int max_clients,
	    void (*handler)(CLIENT *cp))
{
    static int one = 1;
    socklen_t slen;
    SERVER *sp;
    

    if (debug)
	fprintf(stderr, "server_init(%d, ..., %d, %d, ...): Start\n",
		fd, backlog, max_clients);
    
    A_NEW(sp);

    sp->fd = -1;
    
    sp->state = 0;
    pthread_attr_init(&sp->ca_detached);
    pthread_attr_setdetachstate(&sp->ca_detached,
				PTHREAD_CREATE_DETACHED);
    
    pthread_mutex_init(&sp->clients_mtx, NULL);
    pthread_cond_init(&sp->clients_cv, NULL);
    sp->clients_cur = 0;
    sp->clients_max = max_clients;
    
    if (fd < 0)
    {
	if (sg == NULL)
	{
	    syslog(LOG_ERR,
		   "server_init: NULL address and no file descriptor");

	    server_destroy(sp);
	    if (debug)
		fprintf(stderr, "server_init(): End: Failure\n");
	    
	    return NULL;
	}
	
	sp->sin = *sg;
	
	sp->fd = socket(SGFAM(sp->sin), SOCK_STREAM, 0);
#ifdef HAVE_IPV6
	if (sp->fd < 0 &&
	    (errno == EAFNOSUPPORT || errno == EPFNOSUPPORT) &&
	    SGFAM(sp->sin) == AF_INET6)
	{
#if 0
	    /* Try to convert to IPv4 format... */
	    struct in6_addr *addr6 = (struct in6_addr *) SGADDRP(sp->sin);
	    
	    if (IN6_IS_ADDR_V4MAPPED(addr6))
	    {
		UINT32 addr4 = addr6->s6_addr32[3];
		
		SGFAM(sp->sin) = AF_INET;
		* (UINT32 *) SGADDRP(sp->sin) = addr4;
	    }
#endif

	    /* Let's try with an IPv4 socket - who knows, it might work */
	    errno = 0;
	    sp->fd = socket(PF_INET, SOCK_STREAM, 0);
	}
#endif
	
	if (sp->fd < 0)
	{
	    syslog(LOG_ERR, "socket(%s, SOCK_STREAM) failed (errno=%d): %m",
		   (SGFAM(sp->sin) == AF_INET ? "AF_INET" : "AF_INET6"),
		   errno);

	    server_destroy(sp);
	    if (debug)
		fprintf(stderr, "server_init(): End: Failure\n");
	    return NULL;
	}

	(void) setsockopt(sp->fd, SOL_SOCKET, SO_REUSEADDR,
			  (void *) &one, sizeof(one));

	if (s_bind(sp->fd, (struct sockaddr *) &sp->sin,
		   SGSOCKSIZE(sp->sin)) < 0)
	{
	    char buf1[16];

	    syslog(LOG_ERR, "bind(%d,%s:%d) failed: %m",
		   sp->fd,
		   s_inet_ntox(&sp->sin, buf1, sizeof(buf1)),
		   ntohs(SGPORT(sp->sin)));
	    
	    server_destroy(sp);
	    if (debug)
		fprintf(stderr, "server_init(): End: Failure\n");
	    return NULL;
	}
    }
    else
    {
	sp->fd = fd;
	slen = sizeof(sp->sin);
	getsockname(sp->fd, (struct sockaddr *) &sp->sin, &slen);
    }

    /* We do this outside the 'if' clause to support broken
       Inetd implementations */
    
    if (backlog >= 0 && listen(sp->fd, backlog) < 0)
    {
	syslog(LOG_ERR, "listen(%d, %d) failed: %m", sp->fd, backlog);
	
	server_destroy(sp);
	if (debug)
	    fprintf(stderr, "server_init(): End: Failure\n");
	return NULL;
    }
	
    sp->handler = handler;
    
    if (debug)
	fprintf(stderr, "server_init(): End: OK\n");
    return sp;
}