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; }
/* 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; }