int
bgp_socket (unsigned short port, const char *address)
{
  struct addrinfo *ainfo;
  struct addrinfo *ainfo_save;
  static const struct addrinfo req = {
    .ai_family = AF_UNSPEC,
    .ai_flags = AI_PASSIVE,
    .ai_socktype = SOCK_STREAM,
  };
  int ret, count;
  char port_str[BUFSIZ];

  snprintf (port_str, sizeof(port_str), "%d", port);
  port_str[sizeof (port_str) - 1] = '\0';

  ret = getaddrinfo (address, port_str, &req, &ainfo_save);
  if (ret != 0)
    {
      zlog_err ("getaddrinfo: %s", gai_strerror (ret));
      return -1;
    }

  count = 0;
  for (ainfo = ainfo_save; ainfo; ainfo = ainfo->ai_next)
    {
      int sock;

      if (ainfo->ai_family != AF_INET && ainfo->ai_family != AF_INET6)
	continue;
     
      sock = socket (ainfo->ai_family, ainfo->ai_socktype, ainfo->ai_protocol);
      if (sock < 0)
	{
	  zlog_err ("socket: %s", safe_strerror (errno));
	  continue;
	}
	
      /* if we intend to implement ttl-security, this socket needs ttl=255 */
      sockopt_ttl (ainfo->ai_family, sock, MAXTTL);
      
      ret = bgp_listener (sock, ainfo->ai_addr, ainfo->ai_addrlen);
      if (ret == 0)
	++count;
      else
	close(sock);
    }
  freeaddrinfo (ainfo_save);
  if (count == 0)
    {
      zlog_err ("%s: no usable addresses", __func__);
      return -1;
    }

  return 0;
}
/* Traditional IPv4 only version.  */
int
bgp_socket (unsigned short port, const char *address)
{
  int sock;
  int socklen;
  struct sockaddr_in sin;
  int ret, en;

  sock = socket (AF_INET, SOCK_STREAM, 0);
  if (sock < 0)
    {
      zlog_err ("socket: %s", safe_strerror (errno));
      return sock;
    }

  /* if we intend to implement ttl-security, this socket needs ttl=255 */
  sockopt_ttl (AF_INET, sock, MAXTTL);

  memset (&sin, 0, sizeof (struct sockaddr_in));
  sin.sin_family = AF_INET;
  sin.sin_port = htons (port);
  socklen = sizeof (struct sockaddr_in);

  if (address && ((ret = inet_aton(address, &sin.sin_addr)) < 1))
    {
      zlog_err("bgp_socket: could not parse ip address %s: %s",
                address, safe_strerror (errno));
      return ret;
    }
#ifdef HAVE_STRUCT_SOCKADDR_IN_SIN_LEN
  sin.sin_len = socklen;
#endif /* HAVE_STRUCT_SOCKADDR_IN_SIN_LEN */

  ret = bgp_listener (sock, (struct sockaddr *) &sin, socklen);
  if (ret < 0) 
    {
      close (sock);
      return ret;
    }
  return sock;
}
Пример #3
0
/* IPv6 supported version of BGP server socket setup.  */
int bgp_socket(struct bgp *bgp, unsigned short port, const char *address)
{
	struct addrinfo *ainfo;
	struct addrinfo *ainfo_save;
	static const struct addrinfo req = {
		.ai_family = AF_UNSPEC,
		.ai_flags = AI_PASSIVE,
		.ai_socktype = SOCK_STREAM,
	};
	int ret, count;
	char port_str[BUFSIZ];

	snprintf(port_str, sizeof(port_str), "%d", port);
	port_str[sizeof(port_str) - 1] = '\0';

	frr_elevate_privs(&bgpd_privs) {
		ret = vrf_getaddrinfo(address, port_str, &req, &ainfo_save,
				      bgp->vrf_id);
	}
	if (ret != 0) {
		flog_err_sys(EC_LIB_SOCKET, "getaddrinfo: %s",
			     gai_strerror(ret));
		return -1;
	}
	if (bgp_option_check(BGP_OPT_NO_ZEBRA) &&
	    bgp->vrf_id != VRF_DEFAULT) {
		freeaddrinfo(ainfo_save);
		return -1;
	}
	count = 0;
	for (ainfo = ainfo_save; ainfo; ainfo = ainfo->ai_next) {
		int sock;

		if (ainfo->ai_family != AF_INET && ainfo->ai_family != AF_INET6)
			continue;

		frr_elevate_privs(&bgpd_privs) {
			sock = vrf_socket(ainfo->ai_family,
					  ainfo->ai_socktype,
					  ainfo->ai_protocol, bgp->vrf_id,
					  (bgp->inst_type
					   == BGP_INSTANCE_TYPE_VRF
					   ? bgp->name : NULL));
		}
		if (sock < 0) {
			flog_err_sys(EC_LIB_SOCKET, "socket: %s",
				     safe_strerror(errno));
			continue;
		}

		/* if we intend to implement ttl-security, this socket needs
		 * ttl=255 */
		sockopt_ttl(ainfo->ai_family, sock, MAXTTL);

		ret = bgp_listener(sock, ainfo->ai_addr, ainfo->ai_addrlen,
				   bgp);
		if (ret == 0)
			++count;
		else
			close(sock);
	}
	freeaddrinfo(ainfo_save);
	if (count == 0 && bgp->inst_type != BGP_INSTANCE_TYPE_VRF) {
		flog_err(
			EC_LIB_SOCKET,
			"%s: no usable addresses please check other programs usage of specified port %d",
			__func__, port);
		flog_err_sys(EC_LIB_SOCKET, "%s: Program cannot continue",
			     __func__);
		exit(-1);
	}

	return 0;
}