X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=unix%2Fuxnet.c;h=5058d8ab20409a82f92c159979f6f0cd841ded6d;hb=a063e522970946bf7d5dc052079d7773c0dee76d;hp=3ceb985854f177e940ec58ce683c64dca2675b96;hpb=8be6fbaa09f1e0d73a533b5623970a872ec14cc6;p=PuTTY.git diff --git a/unix/uxnet.c b/unix/uxnet.c index 3ceb9858..5058d8ab 100644 --- a/unix/uxnet.c +++ b/unix/uxnet.c @@ -16,6 +16,8 @@ #include #include #include +#include +#include #define DEFINE_PLUG_METHOD_MACROS #include "putty.h" @@ -126,9 +128,12 @@ struct SockAddr_tag { (addr)->superfamily == UNIX ? AF_UNIX : \ (step).ai ? (step).ai->ai_family : AF_INET) #else +/* Here we gratuitously reference 'step' to avoid gcc warnings about + * 'set but not used' when compiling -DNO_IPV6 */ #define SOCKADDR_FAMILY(addr, step) \ ((addr)->superfamily == UNRESOLVED ? AF_UNSPEC : \ - (addr)->superfamily == UNIX ? AF_UNIX : AF_INET) + (addr)->superfamily == UNIX ? AF_UNIX : \ + (step).curraddr ? AF_INET : AF_INET) #endif /* @@ -221,7 +226,11 @@ SockAddr sk_namelookup(const char *host, char **canonicalname, int address_famil hints.ai_addr = NULL; hints.ai_canonname = NULL; hints.ai_next = NULL; - err = getaddrinfo(host, NULL, &hints, &ret->ais); + { + char *trimmed_host = host_strduptrim(host); /* strip [] on literals */ + err = getaddrinfo(trimmed_host, NULL, &hints, &ret->ais); + sfree(trimmed_host); + } if (err != 0) { ret->error = gai_strerror(err); return ret; @@ -337,6 +346,15 @@ void sk_getaddr(SockAddr addr, char *buf, int buflen) } } +int sk_addr_needs_port(SockAddr addr) +{ + if (addr->superfamily == UNRESOLVED || addr->superfamily == UNIX) { + return FALSE; + } else { + return TRUE; + } +} + int sk_hostname_is_local(const char *name) { return !strcmp(name, "localhost") || @@ -469,6 +487,7 @@ static int sk_tcp_write(Socket s, const char *data, int len); static int sk_tcp_write_oob(Socket s, const char *data, int len); static void sk_tcp_write_eof(Socket s); static void sk_tcp_set_frozen(Socket s, int is_frozen); +static char *sk_tcp_peer_info(Socket s); static const char *sk_tcp_socket_error(Socket s); static struct socket_function_table tcp_fn_table = { @@ -479,7 +498,8 @@ static struct socket_function_table tcp_fn_table = { sk_tcp_write_eof, sk_tcp_flush, sk_tcp_set_frozen, - sk_tcp_socket_error + sk_tcp_socket_error, + sk_tcp_peer_info, }; static Socket sk_tcp_accept(accept_ctx_t ctx, Plug plug) @@ -764,7 +784,7 @@ Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only, i { int s; #ifndef NO_IPV6 - struct addrinfo hints, *ai; + struct addrinfo hints, *ai = NULL; char portstr[6]; #endif union sockaddr_union u; @@ -859,7 +879,11 @@ Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only, i hints.ai_next = NULL; assert(port >= 0 && port <= 99999); sprintf(portstr, "%d", port); - retcode = getaddrinfo(srcaddr, portstr, &hints, &ai); + { + char *trimmed_addr = host_strduptrim(srcaddr); + retcode = getaddrinfo(trimmed_addr, portstr, &hints, &ai); + sfree(trimmed_addr); + } if (retcode == 0) { addr = (union sockaddr_union *)ai->ai_addr; addrlen = ai->ai_addrlen; @@ -906,6 +930,12 @@ Socket sk_newlistener(char *srcaddr, int port, Plug plug, int local_host_only, i } retcode = bind(s, &addr->sa, addrlen); + +#ifndef NO_IPV6 + if (ai) + freeaddrinfo(ai); +#endif + if (retcode < 0) { close(s); ret->error = strerror(errno); @@ -1393,6 +1423,51 @@ static void sk_tcp_set_frozen(Socket sock, int is_frozen) uxsel_tell(s); } +static char *sk_tcp_peer_info(Socket sock) +{ + Actual_Socket s = (Actual_Socket) sock; + struct sockaddr_storage addr; + socklen_t addrlen = sizeof(addr); + char buf[INET6_ADDRSTRLEN]; + + if (getpeername(s->s, (struct sockaddr *)&addr, &addrlen) < 0) + return NULL; + if (addr.ss_family == AF_INET) { + return dupprintf + ("%s:%d", + inet_ntoa(((struct sockaddr_in *)&addr)->sin_addr), + (int)ntohs(((struct sockaddr_in *)&addr)->sin_port)); +#ifndef NO_IPV6 + } else if (addr.ss_family == AF_INET6) { + return dupprintf + ("[%s]:%d", + inet_ntop(AF_INET6, &((struct sockaddr_in6 *)&addr)->sin6_addr, + buf, sizeof(buf)), + (int)ntohs(((struct sockaddr_in6 *)&addr)->sin6_port)); +#endif + } else if (addr.ss_family == AF_UNIX) { + /* + * For Unix sockets, the source address is unlikely to be + * helpful. Instead, we try SO_PEERCRED and try to get the + * source pid. + */ + int pid, uid, gid; + if (so_peercred(s->s, &pid, &uid, &gid)) { + char uidbuf[64], gidbuf[64]; + sprintf(uidbuf, "%d", uid); + sprintf(gidbuf, "%d", gid); + struct passwd *pw = getpwuid(uid); + struct group *gr = getgrgid(gid); + return dupprintf("pid %d (%s:%s)", pid, + pw ? pw->pw_name : uidbuf, + gr ? gr->gr_name : gidbuf); + } + return NULL; + } else { + return NULL; + } +} + static void uxsel_tell(Actual_Socket s) { int rwx = 0;