Пример #1
0
request *get_sock_request(int sock_fd)
{
	int fd;						/* socket */
#ifdef INET6
	struct sockaddr_in6 remote_addr;
#else
	struct sockaddr_in remote_addr;		/* address */
#endif
	int remote_addrlen = sizeof(remote_addr);
	request *conn;				/* connection */

	if (max_connections != -1 && status.connections >= max_connections)
		return NULL;

#ifdef INET6
	remote_addr.sin6_family = 0xdead;
#else
  remote_addr.sin_family = 0xdead;
#endif
	fd = accept(sock_fd, (struct sockaddr *) &remote_addr, &remote_addrlen);

	if (fd == -1) {
		if (errno == EAGAIN || errno == EWOULDBLOCK)	/* no requests */
			return NULL;
		else {					/* accept error */
			log_error_time();
#if 0
			perror("accept");
#endif
			return NULL;
		}
	}
#ifdef DEBUGNONINET
	/*  This shows up due to race conditions in some Linux kernels 
	 *  when the client closes the socket sometime between 
	 *  the select() and accept() syscalls.
	 *  Code and description by Larry Doolittle <*****@*****.**>
	 */
#define HEX(x) (((x)>9)?(('a'-10)+(x)):('0'+(x)))
	if (remote_addr.sin_family != AF_INET) {
		struct sockaddr *bogus = (struct sockaddr *) &remote_addr;
		char *ap, ablock[44];
		int i;
		close(fd);
#ifdef BOA_TIME_LOG
		log_error_time();
#endif
		for (ap = ablock, i = 0; i < remote_addrlen && i < 14; i++) {
			*ap++ = ' ';
			*ap++ = HEX((bogus->sa_data[i] >> 4) & 0x0f);
			*ap++ = HEX(bogus->sa_data[i] & 0x0f);
		}
		*ap = '\0';
#ifdef BOA_TIME_LOG
		fprintf(stderr, "non-INET connection attempt: socket %d, "
				"sa_family = %hu, sa_data[%d] = %s\n",
				fd, bogus->sa_family, remote_addrlen, ablock);
#endif
		return NULL;
	}
#endif

	if ((setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void *) &sock_opt,
		sizeof(sock_opt))) == -1){
			die(NO_SETSOCKOPT);
			return NULL;
	}

	conn = new_request();
	conn->fd = fd;
	conn->status = READ_HEADER;
	conn->header_line = conn->client_stream;
	conn->time_last = time_counter;
#ifdef USE_CHARSET_HEADER
	conn->send_charset = 1;
#endif

	/* nonblocking socket */
	if (fcntl(conn->fd, F_SETFL, NOBLOCK) == -1) {
#ifdef BOA_TIME_LOG
		log_error_time();
		perror("request.c, fcntl");
#endif
	}
	/* set close on exec to true */
	if (fcntl(conn->fd, F_SETFD, 1) == -1) {
#ifdef BOA_TIME_LOG
		log_error_time();
		perror("request.c, fcntl-close-on-exec");
#endif
	}

	/* large buffers */
	if (setsockopt(conn->fd, SOL_SOCKET, SO_SNDBUF, (void *) &sockbufsize,
				   sizeof(sockbufsize)) == -1)
		die(NO_SETSOCKOPT);

	/* for log file and possible use by CGI programs */
#ifdef INET6
	if (getnameinfo((struct sockaddr *)&remote_addr, 
									NRL_SA_LEN((struct sockaddr *)&remote_addr), 
									conn->remote_ip_addr, 20,
								 	NULL, 0, NI_NUMERICHOST)) {
#if 0
			fprintf(stderr, "[IPv6] getnameinfo failed\n");
#endif
			conn->remote_ip_addr[0]=0;
		}
#else
	strncpy(conn->remote_ip_addr, (char *) inet_ntoa(remote_addr.sin_addr), 20);
#endif

	/* for possible use by CGI programs */
#ifdef INET6
	conn->remote_port = ntohs(remote_addr.sin6_port);
#else
	conn->remote_port = ntohs(remote_addr.sin_port);
#endif

	if (virtualhost) {
#ifdef INET6
		char host[20];
		struct sockaddr_in6 salocal;
		int dummy;
				
		dummy = sizeof(salocal);
		if (getsockname(conn->fd, (struct sockaddr *) &salocal, &dummy) == -1)
									      die(SERVER_ERROR);
			if (getnameinfo((struct sockaddr *)&salocal,
		              NRL_SA_LEN((struct sockaddr *)&salocal),
			          host, 20,
				      NULL, 0, NI_NUMERICHOST)) {
#if 0
				fprintf(stderr, "[IPv6] getnameinfo failed\n");
#endif
			}else
				conn->local_ip_addr = strdup(host);
#else		
		struct sockaddr_in salocal;
		int dummy;

		dummy = sizeof(salocal);
		if (getsockname(conn->fd, (struct sockaddr *) &salocal, &dummy) == -1){
			die(SERVER_ERROR);
			return NULL;
		}
		conn->local_ip_addr = strdup(inet_ntoa(salocal.sin_addr));
#endif
	}	
	status.requests++;
	status.connections++;

	/* Thanks to Jef Poskanzer <*****@*****.**> for this tweak */
	{
		int one = 1;
		if (setsockopt(conn->fd, IPPROTO_TCP, TCP_NODELAY, (void *) &one,
			sizeof(one)) == -1){
			die(NO_SETSOCKOPT);
			return NULL;
		}
	}
	enqueue(&request_ready, conn);
	return conn;
}
Пример #2
0
int getnameinfo(const struct sockaddr *sa, size_t addrlen, char *host, size_t hostlen, char *serv, size_t servlen, int flags)
{
  int serrno = errno;

  if (!sa || (addrlen != NRL_SA_LEN(sa)))
    return -1;

  if (host && (hostlen > 0))
    switch(sa->sa_family) {
      case AF_INET:
#ifdef AF_INET6
      case AF_INET6:
#endif /* AF_INET6 */
	if (!(flags & NI_NUMERICHOST)) {
	  struct hostent *h = NULL;
#if HOSTTABLE
#ifdef AF_INET6
	  if (sa->sa_family == AF_INET6)
	    h = _addr2hostname_hosts((void *)&(((struct sockaddr_in6 *)sa)->sin6_addr), sizeof(struct in6_addr), AF_INET6);
	  else
#endif /* AF_INET6 */
	    h = _addr2hostname_hosts((void *)&(((struct sockaddr_in *)sa)->sin_addr), sizeof(struct in_addr), AF_INET);
#endif /* HOSTTABLE */

	  if (!h) {
#ifdef AF_INET6
	    if (sa->sa_family == AF_INET6)
	      h = gethostbyaddr((void *)&(((struct sockaddr_in6 *)sa)->sin6_addr), sizeof(struct in6_addr), AF_INET6);
	    else
#endif /* INET6 */
	      h = gethostbyaddr((void *)&(((struct sockaddr_in *)sa)->sin_addr), sizeof(struct in_addr), AF_INET);
	    endhostent();
	  };
	  
	  if (h) {
	    if (flags & NI_NOFQDN) {
	      char *c, *c2;
	      if ((c = nrl_domainname()) && (c = strstr(h->h_name, c)) && (c != h->h_name) && (*(--c) == '.')) {
		strncpy(host, h->h_name, min(hostlen, (c - h->h_name)));
		break;
	      };
	    };
	    strncpy(host, h->h_name, hostlen);
	    break;
	  }
	}
	
	if (flags & NI_NAMEREQD)
	  goto fail;
	
        {
	  const char *c;
#ifdef AF_INET6
	  if (sa->sa_family == AF_INET6)
	    c = inet_ntop(AF_INET6, (void *)&(((struct sockaddr_in6 *)sa)->sin6_addr), host, hostlen);
	  else
#endif /* INET6 */
	    c = inet_ntop(AF_INET, (void *)&(((struct sockaddr_in *)sa)->sin_addr), host, hostlen);

	  if (!c)
	    goto fail;
	}
	break;
      case AF_LOCAL:
	if (!(flags & NI_NUMERICHOST)) {
	  struct utsname utsname;
	  
	  if (!uname(&utsname)) {
	    strncpy(host, utsname.nodename, hostlen);
	    break;
	  };
	};
	
	if (flags & NI_NAMEREQD)
	  goto fail;
	
	strncpy(host, "localhost", hostlen);
	break;
      default:
        return -1;
    }

  if (serv && (servlen > 0))
    switch(sa->sa_family) {
      case AF_INET:
#ifdef AF_INET6
      case AF_INET6:
#endif /* INET6 */
	if (!(flags & NI_NUMERICSERV)) {
	  struct servent *s;
	  if (s = getservbyport(((struct sockaddr_in *)sa)->sin_port, (flags & NI_DGRAM) ? "udp" : "tcp")) {
	    strncpy(serv, s->s_name, servlen);
	    break;
	  };
	};
	snprintf(serv, servlen, "%d", ntohs(((struct sockaddr_in *)sa)->sin_port));
	break;
      case AF_LOCAL:
	strncpy(serv, ((struct sockaddr_un *)sa)->sun_path, servlen);
	break;
    }

  if (host && (hostlen > 0))
    host[hostlen-1] = 0;
  if (serv && (servlen > 0))
    serv[servlen-1] = 0;
  errno = serrno;
  return 0;

fail:
  errno = serrno;
  return -1;
}