Annotation of src/usr.bin/ssh/canohost.c, Revision 1.76
1.76 ! djm 1: /* $OpenBSD: canohost.c,v 1.75 2020/10/18 11:32:01 djm Exp $ */
1.1 deraadt 2: /*
1.7 deraadt 3: * Author: Tatu Ylonen <ylo@cs.hut.fi>
4: * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5: * All rights reserved
6: * Functions for returning the canonical host name of the remote site.
1.12 markus 7: *
1.14 deraadt 8: * As far as I am concerned, the code I have written for this software
9: * can be used freely for any purpose. Any derived versions of this
10: * software must be clearly marked as such, and if the derived work is
11: * incompatible with the protocol description in the RFC file, it must be
12: * called by a name other than "ssh" or "Secure Shell".
1.7 deraadt 13: */
1.1 deraadt 14:
1.55 stevesk 15: #include <sys/types.h>
1.54 stevesk 16: #include <sys/socket.h>
1.71 millert 17: #include <sys/un.h>
1.54 stevesk 18:
19: #include <netinet/in.h>
1.49 stevesk 20:
1.56 stevesk 21: #include <errno.h>
1.57 stevesk 22: #include <netdb.h>
1.60 stevesk 23: #include <stdio.h>
1.59 stevesk 24: #include <stdlib.h>
1.58 stevesk 25: #include <string.h>
1.61 deraadt 26: #include <stdarg.h>
1.66 dtucker 27: #include <unistd.h>
1.1 deraadt 28:
1.61 deraadt 29: #include "xmalloc.h"
1.1 deraadt 30: #include "packet.h"
1.18 markus 31: #include "log.h"
1.21 itojun 32: #include "canohost.h"
1.62 dtucker 33: #include "misc.h"
1.1 deraadt 34:
1.8 markus 35: /*
1.35 stevesk 36: * Returns the local/remote IP-address/hostname of socket as a string.
37: * The returned string must be freed.
1.8 markus 38: */
1.27 itojun 39: static char *
1.40 avsm 40: get_socket_address(int sock, int remote, int flags)
1.1 deraadt 41: {
1.25 markus 42: struct sockaddr_storage addr;
43: socklen_t addrlen;
1.10 markus 44: char ntop[NI_MAXHOST];
1.42 djm 45: int r;
1.76 ! djm 46:
! 47: if (sock < 0)
! 48: return NULL;
1.1 deraadt 49:
1.6 markus 50: /* Get IP address of client. */
1.25 markus 51: addrlen = sizeof(addr);
52: memset(&addr, 0, sizeof(addr));
53:
54: if (remote) {
1.73 djm 55: if (getpeername(sock, (struct sockaddr *)&addr, &addrlen) != 0)
1.25 markus 56: return NULL;
57: } else {
1.73 djm 58: if (getsockname(sock, (struct sockaddr *)&addr, &addrlen) != 0)
1.25 markus 59: return NULL;
60: }
1.71 millert 61:
1.72 millert 62: switch (addr.ss_family) {
63: case AF_INET:
64: case AF_INET6:
65: /* Get the address in ascii. */
66: if ((r = getnameinfo((struct sockaddr *)&addr, addrlen, ntop,
67: sizeof(ntop), NULL, 0, flags)) != 0) {
1.75 djm 68: error_f("getnameinfo %d failed: %s",
1.72 millert 69: flags, ssh_gai_strerror(r));
70: return NULL;
71: }
72: return xstrdup(ntop);
73: case AF_UNIX:
1.71 millert 74: /* Get the Unix domain socket path. */
75: return xstrdup(((struct sockaddr_un *)&addr)->sun_path);
1.72 millert 76: default:
77: /* We can't look up remote Unix domain sockets. */
1.19 markus 78: return NULL;
79: }
1.25 markus 80: }
81:
82: char *
1.40 avsm 83: get_peer_ipaddr(int sock)
1.25 markus 84: {
1.34 stevesk 85: char *p;
86:
1.40 avsm 87: if ((p = get_socket_address(sock, 1, NI_NUMERICHOST)) != NULL)
1.34 stevesk 88: return p;
89: return xstrdup("UNKNOWN");
1.25 markus 90: }
91:
92: char *
1.40 avsm 93: get_local_ipaddr(int sock)
1.25 markus 94: {
1.34 stevesk 95: char *p;
96:
1.40 avsm 97: if ((p = get_socket_address(sock, 0, NI_NUMERICHOST)) != NULL)
1.34 stevesk 98: return p;
99: return xstrdup("UNKNOWN");
1.25 markus 100: }
101:
102: char *
1.66 dtucker 103: get_local_name(int fd)
1.25 markus 104: {
1.66 dtucker 105: char *host, myname[NI_MAXHOST];
106:
107: /* Assume we were passed a socket */
108: if ((host = get_socket_address(fd, 0, NI_NAMEREQD)) != NULL)
109: return host;
110:
111: /* Handle the case where we were passed a pipe */
112: if (gethostname(myname, sizeof(myname)) == -1) {
1.75 djm 113: verbose_f("gethostname: %s", strerror(errno));
1.73 djm 114: host = xstrdup("UNKNOWN");
1.66 dtucker 115: } else {
116: host = xstrdup(myname);
117: }
118:
119: return host;
1.19 markus 120: }
121:
1.10 markus 122: /* Returns the local/remote port for the socket. */
1.1 deraadt 123:
1.73 djm 124: static int
1.10 markus 125: get_sock_port(int sock, int local)
1.1 deraadt 126: {
1.10 markus 127: struct sockaddr_storage from;
128: socklen_t fromlen;
129: char strport[NI_MAXSERV];
1.42 djm 130: int r;
1.1 deraadt 131:
1.6 markus 132: /* Get IP address of client. */
133: fromlen = sizeof(from);
134: memset(&from, 0, sizeof(from));
1.10 markus 135: if (local) {
1.74 deraadt 136: if (getsockname(sock, (struct sockaddr *)&from, &fromlen) == -1) {
1.10 markus 137: error("getsockname failed: %.100s", strerror(errno));
138: return 0;
139: }
140: } else {
1.74 deraadt 141: if (getpeername(sock, (struct sockaddr *)&from, &fromlen) == -1) {
1.10 markus 142: debug("getpeername failed: %.100s", strerror(errno));
1.43 markus 143: return -1;
1.10 markus 144: }
1.6 markus 145: }
1.71 millert 146:
1.72 millert 147: /* Non-inet sockets don't have a port number. */
148: if (from.ss_family != AF_INET && from.ss_family != AF_INET6)
1.71 millert 149: return 0;
150:
1.6 markus 151: /* Return port number. */
1.42 djm 152: if ((r = getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0,
153: strport, sizeof(strport), NI_NUMERICSERV)) != 0)
1.75 djm 154: fatal_f("getnameinfo NI_NUMERICSERV failed: %s",
1.62 dtucker 155: ssh_gai_strerror(r));
1.10 markus 156: return atoi(strport);
1.1 deraadt 157: }
158:
1.12 markus 159: int
1.10 markus 160: get_peer_port(int sock)
161: {
162: return get_sock_port(sock, 0);
163: }
164:
1.12 markus 165: int
1.73 djm 166: get_local_port(int sock)
1.10 markus 167: {
1.73 djm 168: return get_sock_port(sock, 1);
1.1 deraadt 169: }