1511b41d2SMark Murray /* 2511b41d2SMark Murray * Author: Tatu Ylonen <ylo@cs.hut.fi> 3511b41d2SMark Murray * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4511b41d2SMark Murray * All rights reserved 5511b41d2SMark Murray * Functions for returning the canonical host name of the remote site. 6511b41d2SMark Murray * 7c2d3a559SKris Kennaway * As far as I am concerned, the code I have written for this software 8c2d3a559SKris Kennaway * can be used freely for any purpose. Any derived versions of this 9c2d3a559SKris Kennaway * software must be clearly marked as such, and if the derived work is 10c2d3a559SKris Kennaway * incompatible with the protocol description in the RFC file, it must be 11c2d3a559SKris Kennaway * called by a name other than "ssh" or "Secure Shell". 12511b41d2SMark Murray */ 13511b41d2SMark Murray 14511b41d2SMark Murray #include "includes.h" 1521e764dfSDag-Erling Smørgrav RCSID("$OpenBSD: canohost.c,v 1.41 2004/07/21 11:51:29 djm Exp $"); 16511b41d2SMark Murray 17511b41d2SMark Murray #include "packet.h" 18511b41d2SMark Murray #include "xmalloc.h" 19ca3176e7SBrian Feldman #include "log.h" 20ca3176e7SBrian Feldman #include "canohost.h" 21ca3176e7SBrian Feldman 22af12a3e7SDag-Erling Smørgrav static void check_ip_options(int, char *); 231ec0d754SDag-Erling Smørgrav static void ipv64_normalise_mapped(struct sockaddr_storage *, socklen_t *); 24511b41d2SMark Murray 25511b41d2SMark Murray /* 26511b41d2SMark Murray * Return the canonical name of the host at the other end of the socket. The 27511b41d2SMark Murray * caller should free the returned string with xfree. 28511b41d2SMark Murray */ 29511b41d2SMark Murray 30af12a3e7SDag-Erling Smørgrav static char * 3121e764dfSDag-Erling Smørgrav get_remote_hostname(int sock, int use_dns) 32511b41d2SMark Murray { 33511b41d2SMark Murray struct sockaddr_storage from; 34511b41d2SMark Murray int i; 35511b41d2SMark Murray socklen_t fromlen; 36511b41d2SMark Murray struct addrinfo hints, *ai, *aitop; 37ca3176e7SBrian Feldman char name[NI_MAXHOST], ntop[NI_MAXHOST], ntop2[NI_MAXHOST]; 38511b41d2SMark Murray 39511b41d2SMark Murray /* Get IP address of client. */ 40511b41d2SMark Murray fromlen = sizeof(from); 41511b41d2SMark Murray memset(&from, 0, sizeof(from)); 4221e764dfSDag-Erling Smørgrav if (getpeername(sock, (struct sockaddr *)&from, &fromlen) < 0) { 43511b41d2SMark Murray debug("getpeername failed: %.100s", strerror(errno)); 441ec0d754SDag-Erling Smørgrav cleanup_exit(255); 45511b41d2SMark Murray } 46989dd127SDag-Erling Smørgrav 475962c0e9SDag-Erling Smørgrav if (from.ss_family == AF_INET) 4821e764dfSDag-Erling Smørgrav check_ip_options(sock, ntop); 495962c0e9SDag-Erling Smørgrav 501ec0d754SDag-Erling Smørgrav ipv64_normalise_mapped(&from, &fromlen); 51989dd127SDag-Erling Smørgrav 52e73e9afaSDag-Erling Smørgrav if (from.ss_family == AF_INET6) 53e73e9afaSDag-Erling Smørgrav fromlen = sizeof(struct sockaddr_in6); 54ca3176e7SBrian Feldman 55511b41d2SMark Murray if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop), 56511b41d2SMark Murray NULL, 0, NI_NUMERICHOST) != 0) 57511b41d2SMark Murray fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed"); 58511b41d2SMark Murray 59cf2b5f3bSDag-Erling Smørgrav if (!use_dns) 60cf2b5f3bSDag-Erling Smørgrav return xstrdup(ntop); 61cf2b5f3bSDag-Erling Smørgrav 62ca3176e7SBrian Feldman debug3("Trying to reverse map address %.100s.", ntop); 63511b41d2SMark Murray /* Map the IP address to a host name. */ 64511b41d2SMark Murray if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name), 65ca3176e7SBrian Feldman NULL, 0, NI_NAMEREQD) != 0) { 66ca3176e7SBrian Feldman /* Host name not found. Use ip address. */ 67ca3176e7SBrian Feldman return xstrdup(ntop); 68ca3176e7SBrian Feldman } 69ca3176e7SBrian Feldman 70cf2b5f3bSDag-Erling Smørgrav /* 71cf2b5f3bSDag-Erling Smørgrav * if reverse lookup result looks like a numeric hostname, 72cf2b5f3bSDag-Erling Smørgrav * someone is trying to trick us by PTR record like following: 73cf2b5f3bSDag-Erling Smørgrav * 1.1.1.10.in-addr.arpa. IN PTR 2.3.4.5 74cf2b5f3bSDag-Erling Smørgrav */ 75cf2b5f3bSDag-Erling Smørgrav memset(&hints, 0, sizeof(hints)); 76cf2b5f3bSDag-Erling Smørgrav hints.ai_socktype = SOCK_DGRAM; /*dummy*/ 77cf2b5f3bSDag-Erling Smørgrav hints.ai_flags = AI_NUMERICHOST; 78cf2b5f3bSDag-Erling Smørgrav if (getaddrinfo(name, "0", &hints, &ai) == 0) { 79cf2b5f3bSDag-Erling Smørgrav logit("Nasty PTR record \"%s\" is set up for %s, ignoring", 80cf2b5f3bSDag-Erling Smørgrav name, ntop); 81cf2b5f3bSDag-Erling Smørgrav freeaddrinfo(ai); 82cf2b5f3bSDag-Erling Smørgrav return xstrdup(ntop); 83cf2b5f3bSDag-Erling Smørgrav } 84cf2b5f3bSDag-Erling Smørgrav 85511b41d2SMark Murray /* 86511b41d2SMark Murray * Convert it to all lowercase (which is expected by the rest 87511b41d2SMark Murray * of this software). 88511b41d2SMark Murray */ 89511b41d2SMark Murray for (i = 0; name[i]; i++) 90511b41d2SMark Murray if (isupper(name[i])) 91511b41d2SMark Murray name[i] = tolower(name[i]); 92511b41d2SMark Murray /* 93511b41d2SMark Murray * Map it back to an IP address and check that the given 94511b41d2SMark Murray * address actually is an address of this host. This is 95511b41d2SMark Murray * necessary because anyone with access to a name server can 96511b41d2SMark Murray * define arbitrary names for an IP address. Mapping from 97511b41d2SMark Murray * name to IP address can be trusted better (but can still be 98511b41d2SMark Murray * fooled if the intruder has access to the name server of 99511b41d2SMark Murray * the domain). 100511b41d2SMark Murray */ 101511b41d2SMark Murray memset(&hints, 0, sizeof(hints)); 102511b41d2SMark Murray hints.ai_family = from.ss_family; 103511b41d2SMark Murray hints.ai_socktype = SOCK_STREAM; 104511b41d2SMark Murray if (getaddrinfo(name, NULL, &hints, &aitop) != 0) { 105cf2b5f3bSDag-Erling Smørgrav logit("reverse mapping checking getaddrinfo for %.700s " 106ca3176e7SBrian Feldman "failed - POSSIBLE BREAKIN ATTEMPT!", name); 107ca3176e7SBrian Feldman return xstrdup(ntop); 108511b41d2SMark Murray } 109511b41d2SMark Murray /* Look for the address from the list of addresses. */ 110511b41d2SMark Murray for (ai = aitop; ai; ai = ai->ai_next) { 111511b41d2SMark Murray if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2, 112511b41d2SMark Murray sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 && 113511b41d2SMark Murray (strcmp(ntop, ntop2) == 0)) 114511b41d2SMark Murray break; 115511b41d2SMark Murray } 116511b41d2SMark Murray freeaddrinfo(aitop); 117511b41d2SMark Murray /* If we reached the end of the list, the address was not there. */ 118511b41d2SMark Murray if (!ai) { 119511b41d2SMark Murray /* Address not found for the host name. */ 120cf2b5f3bSDag-Erling Smørgrav logit("Address %.100s maps to %.600s, but this does not " 121ca3176e7SBrian Feldman "map back to the address - POSSIBLE BREAKIN ATTEMPT!", 122511b41d2SMark Murray ntop, name); 123ca3176e7SBrian Feldman return xstrdup(ntop); 124511b41d2SMark Murray } 125ca3176e7SBrian Feldman return xstrdup(name); 126511b41d2SMark Murray } 127511b41d2SMark Murray 128511b41d2SMark Murray /* 129511b41d2SMark Murray * If IP options are supported, make sure there are none (log and 130511b41d2SMark Murray * disconnect them if any are found). Basically we are worried about 131511b41d2SMark Murray * source routing; it can be used to pretend you are somebody 132511b41d2SMark Murray * (ip-address) you are not. That itself may be "almost acceptable" 133511b41d2SMark Murray * under certain circumstances, but rhosts autentication is useless 134511b41d2SMark Murray * if source routing is accepted. Notice also that if we just dropped 135511b41d2SMark Murray * source routing here, the other side could use IP spoofing to do 136511b41d2SMark Murray * rest of the interaction and could still bypass security. So we 137511b41d2SMark Murray * exit here if we detect any IP options. 138511b41d2SMark Murray */ 139ca3176e7SBrian Feldman /* IPv4 only */ 140af12a3e7SDag-Erling Smørgrav static void 14121e764dfSDag-Erling Smørgrav check_ip_options(int sock, char *ipaddr) 142ca3176e7SBrian Feldman { 143cf2b5f3bSDag-Erling Smørgrav #ifdef IP_OPTIONS 144ca3176e7SBrian Feldman u_char options[200]; 145ca3176e7SBrian Feldman char text[sizeof(options) * 3 + 1]; 146511b41d2SMark Murray socklen_t option_size; 147ca3176e7SBrian Feldman int i, ipproto; 148511b41d2SMark Murray struct protoent *ip; 149511b41d2SMark Murray 150511b41d2SMark Murray if ((ip = getprotobyname("ip")) != NULL) 151511b41d2SMark Murray ipproto = ip->p_proto; 152511b41d2SMark Murray else 153511b41d2SMark Murray ipproto = IPPROTO_IP; 154511b41d2SMark Murray option_size = sizeof(options); 15521e764dfSDag-Erling Smørgrav if (getsockopt(sock, ipproto, IP_OPTIONS, options, 156511b41d2SMark Murray &option_size) >= 0 && option_size != 0) { 157ca3176e7SBrian Feldman text[0] = '\0'; 158ca3176e7SBrian Feldman for (i = 0; i < option_size; i++) 159ca3176e7SBrian Feldman snprintf(text + i*3, sizeof(text) - i*3, 160ca3176e7SBrian Feldman " %2.2x", options[i]); 161cf2b5f3bSDag-Erling Smørgrav logit("Connection from %.100s with IP options:%.800s", 162ca3176e7SBrian Feldman ipaddr, text); 163511b41d2SMark Murray packet_disconnect("Connection from %.100s with IP options:%.800s", 164ca3176e7SBrian Feldman ipaddr, text); 165511b41d2SMark Murray } 166cf2b5f3bSDag-Erling Smørgrav #endif /* IP_OPTIONS */ 167511b41d2SMark Murray } 168511b41d2SMark Murray 1691ec0d754SDag-Erling Smørgrav static void 1701ec0d754SDag-Erling Smørgrav ipv64_normalise_mapped(struct sockaddr_storage *addr, socklen_t *len) 1711ec0d754SDag-Erling Smørgrav { 1721ec0d754SDag-Erling Smørgrav struct sockaddr_in6 *a6 = (struct sockaddr_in6 *)addr; 1731ec0d754SDag-Erling Smørgrav struct sockaddr_in *a4 = (struct sockaddr_in *)addr; 1741ec0d754SDag-Erling Smørgrav struct in_addr inaddr; 1751ec0d754SDag-Erling Smørgrav u_int16_t port; 1761ec0d754SDag-Erling Smørgrav 1771ec0d754SDag-Erling Smørgrav if (addr->ss_family != AF_INET6 || 1781ec0d754SDag-Erling Smørgrav !IN6_IS_ADDR_V4MAPPED(&a6->sin6_addr)) 1791ec0d754SDag-Erling Smørgrav return; 1801ec0d754SDag-Erling Smørgrav 1811ec0d754SDag-Erling Smørgrav debug3("Normalising mapped IPv4 in IPv6 address"); 1821ec0d754SDag-Erling Smørgrav 1831ec0d754SDag-Erling Smørgrav memcpy(&inaddr, ((char *)&a6->sin6_addr) + 12, sizeof(inaddr)); 1841ec0d754SDag-Erling Smørgrav port = a6->sin6_port; 1851ec0d754SDag-Erling Smørgrav 1861ec0d754SDag-Erling Smørgrav memset(addr, 0, sizeof(*a4)); 1871ec0d754SDag-Erling Smørgrav 1881ec0d754SDag-Erling Smørgrav a4->sin_family = AF_INET; 1891ec0d754SDag-Erling Smørgrav *len = sizeof(*a4); 1901ec0d754SDag-Erling Smørgrav memcpy(&a4->sin_addr, &inaddr, sizeof(inaddr)); 1911ec0d754SDag-Erling Smørgrav a4->sin_port = port; 1921ec0d754SDag-Erling Smørgrav } 1931ec0d754SDag-Erling Smørgrav 194511b41d2SMark Murray /* 195511b41d2SMark Murray * Return the canonical name of the host in the other side of the current 196511b41d2SMark Murray * connection. The host name is cached, so it is efficient to call this 197511b41d2SMark Murray * several times. 198511b41d2SMark Murray */ 199511b41d2SMark Murray 200511b41d2SMark Murray const char * 201cf2b5f3bSDag-Erling Smørgrav get_canonical_hostname(int use_dns) 202511b41d2SMark Murray { 203511b41d2SMark Murray static char *canonical_host_name = NULL; 204cf2b5f3bSDag-Erling Smørgrav static int use_dns_done = 0; 205511b41d2SMark Murray 206ca3176e7SBrian Feldman /* Check if we have previously retrieved name with same option. */ 207ca3176e7SBrian Feldman if (canonical_host_name != NULL) { 208cf2b5f3bSDag-Erling Smørgrav if (use_dns_done != use_dns) 209ca3176e7SBrian Feldman xfree(canonical_host_name); 210ca3176e7SBrian Feldman else 211511b41d2SMark Murray return canonical_host_name; 212ca3176e7SBrian Feldman } 213511b41d2SMark Murray 214511b41d2SMark Murray /* Get the real hostname if socket; otherwise return UNKNOWN. */ 215511b41d2SMark Murray if (packet_connection_is_on_socket()) 216ca3176e7SBrian Feldman canonical_host_name = get_remote_hostname( 217cf2b5f3bSDag-Erling Smørgrav packet_get_connection_in(), use_dns); 218511b41d2SMark Murray else 219511b41d2SMark Murray canonical_host_name = xstrdup("UNKNOWN"); 220511b41d2SMark Murray 221cf2b5f3bSDag-Erling Smørgrav use_dns_done = use_dns; 222511b41d2SMark Murray return canonical_host_name; 223511b41d2SMark Murray } 224511b41d2SMark Murray 225511b41d2SMark Murray /* 226e73e9afaSDag-Erling Smørgrav * Returns the local/remote IP-address/hostname of socket as a string. 227e73e9afaSDag-Erling Smørgrav * The returned string must be freed. 228ca3176e7SBrian Feldman */ 229af12a3e7SDag-Erling Smørgrav static char * 23021e764dfSDag-Erling Smørgrav get_socket_address(int sock, int remote, int flags) 231ca3176e7SBrian Feldman { 232ca3176e7SBrian Feldman struct sockaddr_storage addr; 233ca3176e7SBrian Feldman socklen_t addrlen; 234ca3176e7SBrian Feldman char ntop[NI_MAXHOST]; 235ca3176e7SBrian Feldman 236ca3176e7SBrian Feldman /* Get IP address of client. */ 237ca3176e7SBrian Feldman addrlen = sizeof(addr); 238ca3176e7SBrian Feldman memset(&addr, 0, sizeof(addr)); 239ca3176e7SBrian Feldman 240ca3176e7SBrian Feldman if (remote) { 24121e764dfSDag-Erling Smørgrav if (getpeername(sock, (struct sockaddr *)&addr, &addrlen) 242f388f5efSDag-Erling Smørgrav < 0) 243ca3176e7SBrian Feldman return NULL; 244ca3176e7SBrian Feldman } else { 24521e764dfSDag-Erling Smørgrav if (getsockname(sock, (struct sockaddr *)&addr, &addrlen) 246f388f5efSDag-Erling Smørgrav < 0) 247ca3176e7SBrian Feldman return NULL; 248ca3176e7SBrian Feldman } 249e73e9afaSDag-Erling Smørgrav 250e73e9afaSDag-Erling Smørgrav /* Work around Linux IPv6 weirdness */ 251e73e9afaSDag-Erling Smørgrav if (addr.ss_family == AF_INET6) 252e73e9afaSDag-Erling Smørgrav addrlen = sizeof(struct sockaddr_in6); 253e73e9afaSDag-Erling Smørgrav 254ca3176e7SBrian Feldman /* Get the address in ascii. */ 255ca3176e7SBrian Feldman if (getnameinfo((struct sockaddr *)&addr, addrlen, ntop, sizeof(ntop), 256ca3176e7SBrian Feldman NULL, 0, flags) != 0) { 257e73e9afaSDag-Erling Smørgrav error("get_socket_address: getnameinfo %d failed", flags); 258ca3176e7SBrian Feldman return NULL; 259ca3176e7SBrian Feldman } 260ca3176e7SBrian Feldman return xstrdup(ntop); 261ca3176e7SBrian Feldman } 262ca3176e7SBrian Feldman 263ca3176e7SBrian Feldman char * 26421e764dfSDag-Erling Smørgrav get_peer_ipaddr(int sock) 265ca3176e7SBrian Feldman { 266f388f5efSDag-Erling Smørgrav char *p; 267f388f5efSDag-Erling Smørgrav 26821e764dfSDag-Erling Smørgrav if ((p = get_socket_address(sock, 1, NI_NUMERICHOST)) != NULL) 269f388f5efSDag-Erling Smørgrav return p; 270f388f5efSDag-Erling Smørgrav return xstrdup("UNKNOWN"); 271ca3176e7SBrian Feldman } 272ca3176e7SBrian Feldman 273ca3176e7SBrian Feldman char * 27421e764dfSDag-Erling Smørgrav get_local_ipaddr(int sock) 275ca3176e7SBrian Feldman { 276f388f5efSDag-Erling Smørgrav char *p; 277f388f5efSDag-Erling Smørgrav 27821e764dfSDag-Erling Smørgrav if ((p = get_socket_address(sock, 0, NI_NUMERICHOST)) != NULL) 279f388f5efSDag-Erling Smørgrav return p; 280f388f5efSDag-Erling Smørgrav return xstrdup("UNKNOWN"); 281ca3176e7SBrian Feldman } 282ca3176e7SBrian Feldman 283ca3176e7SBrian Feldman char * 28421e764dfSDag-Erling Smørgrav get_local_name(int sock) 285ca3176e7SBrian Feldman { 28621e764dfSDag-Erling Smørgrav return get_socket_address(sock, 0, NI_NAMEREQD); 287ca3176e7SBrian Feldman } 288ca3176e7SBrian Feldman 289ca3176e7SBrian Feldman /* 290511b41d2SMark Murray * Returns the IP-address of the remote host as a string. The returned 291511b41d2SMark Murray * string must not be freed. 292511b41d2SMark Murray */ 293511b41d2SMark Murray 294511b41d2SMark Murray const char * 295af12a3e7SDag-Erling Smørgrav get_remote_ipaddr(void) 296511b41d2SMark Murray { 297511b41d2SMark Murray static char *canonical_host_ip = NULL; 298511b41d2SMark Murray 299ca3176e7SBrian Feldman /* Check whether we have cached the ipaddr. */ 300ca3176e7SBrian Feldman if (canonical_host_ip == NULL) { 301ca3176e7SBrian Feldman if (packet_connection_is_on_socket()) { 302ca3176e7SBrian Feldman canonical_host_ip = 303ca3176e7SBrian Feldman get_peer_ipaddr(packet_get_connection_in()); 304ca3176e7SBrian Feldman if (canonical_host_ip == NULL) 3051ec0d754SDag-Erling Smørgrav cleanup_exit(255); 306ca3176e7SBrian Feldman } else { 307ca3176e7SBrian Feldman /* If not on socket, return UNKNOWN. */ 308ca3176e7SBrian Feldman canonical_host_ip = xstrdup("UNKNOWN"); 309511b41d2SMark Murray } 310ca3176e7SBrian Feldman } 311511b41d2SMark Murray return canonical_host_ip; 312511b41d2SMark Murray } 313511b41d2SMark Murray 3147e03cf33SBrian Feldman const char * 315cf2b5f3bSDag-Erling Smørgrav get_remote_name_or_ip(u_int utmp_len, int use_dns) 3167e03cf33SBrian Feldman { 317ca3176e7SBrian Feldman static const char *remote = ""; 318ca3176e7SBrian Feldman if (utmp_len > 0) 319cf2b5f3bSDag-Erling Smørgrav remote = get_canonical_hostname(use_dns); 320ca3176e7SBrian Feldman if (utmp_len == 0 || strlen(remote) > utmp_len) 321ca3176e7SBrian Feldman remote = get_remote_ipaddr(); 322ca3176e7SBrian Feldman return remote; 3237e03cf33SBrian Feldman } 3247e03cf33SBrian Feldman 325511b41d2SMark Murray /* Returns the local/remote port for the socket. */ 326511b41d2SMark Murray 327af12a3e7SDag-Erling Smørgrav static int 328511b41d2SMark Murray get_sock_port(int sock, int local) 329511b41d2SMark Murray { 330511b41d2SMark Murray struct sockaddr_storage from; 331511b41d2SMark Murray socklen_t fromlen; 332511b41d2SMark Murray char strport[NI_MAXSERV]; 333511b41d2SMark Murray 334511b41d2SMark Murray /* Get IP address of client. */ 335511b41d2SMark Murray fromlen = sizeof(from); 336511b41d2SMark Murray memset(&from, 0, sizeof(from)); 337511b41d2SMark Murray if (local) { 338511b41d2SMark Murray if (getsockname(sock, (struct sockaddr *)&from, &fromlen) < 0) { 339511b41d2SMark Murray error("getsockname failed: %.100s", strerror(errno)); 340511b41d2SMark Murray return 0; 341511b41d2SMark Murray } 342511b41d2SMark Murray } else { 343511b41d2SMark Murray if (getpeername(sock, (struct sockaddr *)&from, &fromlen) < 0) { 344511b41d2SMark Murray debug("getpeername failed: %.100s", strerror(errno)); 3451ec0d754SDag-Erling Smørgrav cleanup_exit(255); 346511b41d2SMark Murray } 347511b41d2SMark Murray } 348e73e9afaSDag-Erling Smørgrav 349e73e9afaSDag-Erling Smørgrav /* Work around Linux IPv6 weirdness */ 350e73e9afaSDag-Erling Smørgrav if (from.ss_family == AF_INET6) 351e73e9afaSDag-Erling Smørgrav fromlen = sizeof(struct sockaddr_in6); 352e73e9afaSDag-Erling Smørgrav 353511b41d2SMark Murray /* Return port number. */ 354511b41d2SMark Murray if (getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0, 355511b41d2SMark Murray strport, sizeof(strport), NI_NUMERICSERV) != 0) 356511b41d2SMark Murray fatal("get_sock_port: getnameinfo NI_NUMERICSERV failed"); 357511b41d2SMark Murray return atoi(strport); 358511b41d2SMark Murray } 359511b41d2SMark Murray 360511b41d2SMark Murray /* Returns remote/local port number for the current connection. */ 361511b41d2SMark Murray 362af12a3e7SDag-Erling Smørgrav static int 363511b41d2SMark Murray get_port(int local) 364511b41d2SMark Murray { 365511b41d2SMark Murray /* 366511b41d2SMark Murray * If the connection is not a socket, return 65535. This is 367511b41d2SMark Murray * intentionally chosen to be an unprivileged port number. 368511b41d2SMark Murray */ 369511b41d2SMark Murray if (!packet_connection_is_on_socket()) 370511b41d2SMark Murray return 65535; 371511b41d2SMark Murray 372511b41d2SMark Murray /* Get socket and return the port number. */ 373511b41d2SMark Murray return get_sock_port(packet_get_connection_in(), local); 374511b41d2SMark Murray } 375511b41d2SMark Murray 376511b41d2SMark Murray int 377511b41d2SMark Murray get_peer_port(int sock) 378511b41d2SMark Murray { 379511b41d2SMark Murray return get_sock_port(sock, 0); 380511b41d2SMark Murray } 381511b41d2SMark Murray 382511b41d2SMark Murray int 383af12a3e7SDag-Erling Smørgrav get_remote_port(void) 384511b41d2SMark Murray { 38521e764dfSDag-Erling Smørgrav static int port = -1; 38621e764dfSDag-Erling Smørgrav 38721e764dfSDag-Erling Smørgrav /* Cache to avoid getpeername() on a dead connection */ 38821e764dfSDag-Erling Smørgrav if (port == -1) 38921e764dfSDag-Erling Smørgrav port = get_port(0); 39021e764dfSDag-Erling Smørgrav 39121e764dfSDag-Erling Smørgrav return port; 392511b41d2SMark Murray } 393511b41d2SMark Murray 394511b41d2SMark Murray int 395af12a3e7SDag-Erling Smørgrav get_local_port(void) 396511b41d2SMark Murray { 397511b41d2SMark Murray return get_port(1); 398511b41d2SMark Murray } 399