Просмотр исходного кода

Use sockaddr_storage to accept sockets and getnameinfo(3) for initial hostname

Issue #55
Bryan Drewery 10 лет назад
Родитель
Сommit
2c54f3d283
6 измененных файлов с 63 добавлено и 86 удалено
  1. 27 18
      src/dcc.cc
  2. 8 1
      src/dcc.h
  3. 1 0
      src/dccutil.cc
  4. 7 4
      src/mod/transfer.mod/transfer.cc
  5. 19 62
      src/net.cc
  6. 1 1
      src/net.h

+ 27 - 18
src/dcc.cc

@@ -624,21 +624,19 @@ struct dcc_table DCC_IDENTD = {
 static void
 dcc_identd_connect(int idx, char *buf, int atr)
 {
-  in_addr_t ip;
   in_port_t port;
   int j, sock;
-  char s[UHOSTLEN + 1] = "";
 
   if (dcc_total + 1 > max_dcc) {
-    j = answer(dcc[idx].sock, s, &ip, &port, 0);
+    j = answer(dcc[idx].sock, &dcc[idx].sockname, &port, 0);
     if (j != -1)
       killsock(j);
     return;
   }
-  sock = answer(dcc[idx].sock, s, &ip, &port, 0);
+  sock = answer(dcc[idx].sock, &dcc[idx].sockname, &port, 0);
 
   while ((sock == -1) && (errno == EAGAIN))
-    sock = answer(sock, s, &ip, &port, 0);
+    sock = answer(sock, &dcc[idx].sockname, &port, 0);
 
   if (sock < 0) {
     putlog(LOG_MISC, "*", "Failed TELNET incoming (%s)", strerror(errno));
@@ -651,6 +649,7 @@ dcc_identd_connect(int idx, char *buf, int atr)
   dcc[j].sock = sock;
   dcc[j].port = port;
   dcc[j].addr = dcc[idx].addr;
+  memcpy(&dcc[j].sockname, &dcc[idx].sockname, sizeof(dcc[j].sockname));
   strlcpy(dcc[j].host, dcc[idx].host, sizeof(dcc[j].host));
   strlcpy(dcc[j].nick, "*", sizeof(dcc[j].nick));
   /* dcc[j].uint.ident_sock = dcc[idx].sock; */
@@ -1395,16 +1394,14 @@ static void dcc_telnet_dns_forward_callback(int, void *, const char *, bd::Array
 static void
 dcc_telnet(int idx, char *buf, int ii)
 {
-  in_addr_t ip;
   in_port_t port;
-  char s[UHOSTLEN + 1] = "";
   int i;
   char x[1024] = "";
 
   if (unlikely(dcc_total + 1 > max_dcc)) {
     int j;
 
-    j = answer(dcc[idx].sock, s, &ip, &port, 0);
+    j = answer(dcc[idx].sock, &dcc[idx].sockname, &port, 0);
     if (j != -1) {
       dprintf(-j, "Sorry, too many connections already.\r\n");
       killsock(j);
@@ -1412,10 +1409,10 @@ dcc_telnet(int idx, char *buf, int ii)
     return;
   }
 
-  int sock = answer(dcc[idx].sock, s, &ip, &port, 0);
+  int sock = answer(dcc[idx].sock, &dcc[idx].sockname, &port, 0);
 
   while ((sock == -1) && (errno == EAGAIN))
-    sock = answer(dcc[idx].sock, s, &ip, &port, 0);
+    sock = answer(dcc[idx].sock, &dcc[idx].sockname, &port, 0);
   if (unlikely(sock < 0)) {
     putlog(LOG_MISC, "*", "Failed TELNET incoming (%s)", strerror(errno));
 //    killsock(dcc[idx].sock);
@@ -1424,6 +1421,9 @@ dcc_telnet(int idx, char *buf, int ii)
   /* Buffer data received on this socket.  */
   sockoptions(sock, EGG_OPTION_SET, SOCK_BUFFER);
 
+  getnameinfo((struct sockaddr *)&dcc[idx].sockname, dcc[idx].sockname.ss_len,
+      (char*)&dcc[idx].host, sizeof(dcc[idx].host), NULL, 0, NI_NUMERICHOST);
+
   int af_type = sockprotocol(sock);
 
   if (af_type == AF_UNIX) {
@@ -1437,21 +1437,21 @@ dcc_telnet(int idx, char *buf, int ii)
     dcc[i].port = 0;
     dcc[i].timeval = now;
     strlcpy(dcc[i].nick, "*", sizeof(dcc[i].nick));
-    putlog(LOG_BOTS, "*", "Connection over local socket: %s", s);
+    putlog(LOG_BOTS, "*", "Connection over local socket: %s", dcc[idx].host);
     dcc_telnet_got_ident(i, x);
     return;
   }
 
   if (port < 1024 || port > 65534) {
-    putlog(LOG_BOTS, "*", "Refused %s/%d (bad src port)", s, port);
+    putlog(LOG_BOTS, "*", "Refused %s/%d (bad src port)", dcc[idx].host, port);
     killsock(sock);
     return;
   }
 
-  putlog(LOG_DEBUG, "*", "Telnet connection: %s/%d", s, port);
+  putlog(LOG_DEBUG, "*", "Telnet connection: %s/%d", dcc[idx].host, port);
 
   // Are they ignored by IP?
-  simple_snprintf(x, sizeof(x), "-telnet!telnet@%s", iptostr(htonl(ip)));
+  simple_snprintf(x, sizeof(x), "-telnet!telnet@%s", dcc[idx].host);
 
   if (unlikely(match_ignore(x) || detect_telnet_flood(x))) {
     putlog(LOG_DEBUG, "*", "Ignored telnet connection from: %s", x);
@@ -1466,13 +1466,21 @@ dcc_telnet(int idx, char *buf, int ii)
 
   i = new_dcc(&DCC_DNSWAIT, sizeof(struct dns_info));
 
-  dcc[i].addr = ip;
+  memcpy(&dcc[i].sockname, &dcc[idx].sockname, sizeof(dcc[i].sockname));
+  /* XXX: Remove this */
+  if (dcc[i].sockname.ss_family == AF_INET) {
+    dcc[i].addr = ntohl(((struct sockaddr_in*)&dcc[i].sockname)->sin_addr.s_addr);
+  } else {
+    dcc[i].addr = 0;
+  }
+
   dcc[i].sock = sock;
   dcc[i].user = get_user_by_host(x);		/* check for matching -telnet!telnet@ip */
-  strlcpy(dcc[i].host, s, sizeof(dcc[i].host));
+  strlcpy(dcc[i].host, dcc[idx].host, sizeof(dcc[i].host));
+  /* XXX: Remove this */
 #ifdef USE_IPV6
   if (af_type == AF_INET6)
-    strlcpy(dcc[i].host6, s, sizeof(dcc[i].host6));
+    strlcpy(dcc[i].host6, dcc[i].host, sizeof(dcc[i].host6));
 #endif /* USE_IPV6 */
   dcc[i].port = port;
   dcc[i].timeval = now;
@@ -1480,7 +1488,8 @@ dcc_telnet(int idx, char *buf, int ii)
 
   dcc[i].u.dns->ibuf = idx;
 
-  int dns_id = egg_dns_reverse(s, 20, dcc_telnet_dns_callback, (void *) (long) i);
+  int dns_id = egg_dns_reverse(dcc[idx].host, 20, dcc_telnet_dns_callback,
+      (void *) (long) i);
   if (dns_id >= 0)
     dcc[i].dns_id = dns_id;
 }

+ 8 - 1
src/dcc.h

@@ -5,6 +5,10 @@
 #  include "config.h"
 #endif
 
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
 #include "types.h"
 #include "enclink.h"
 #include "crypt.h"
@@ -44,6 +48,8 @@ struct dcc_t {
     int ident_sock;
   } uint;
 
+  sockaddr_storage sockname;	/* Connection host/port */
+  /* XXX: Remove this */
   in_addr_t addr;                      /* IP address in host byte order         */
   time_t simultime;             /* the time when the simul dcc is initiated, expires after a number of seconds */
   time_t timeval;               /* Use for any timing stuff
@@ -67,8 +73,9 @@ struct dcc_t {
   char shahash[SHA_HASH_LENGTH + 1];
   char nick[NICKLEN];
   char whois[UHOSTLEN];
-  char host[UHOSTLEN];
+  char host[NI_MAXHOST];	/* Resolved host. */
 #ifdef USE_IPV6
+  /* XXX: Remove this */
   char host6[121];              /* easier.. ipv6 address in regular notation (3ffe:80c0:225::) */
 #endif /* USE_IPV6 */
   int8_t cflags;	 	/* Color status flags. */

+ 1 - 0
src/dccutil.cc

@@ -534,6 +534,7 @@ dcc_read(bd::Stream& stream)
     }
 
     if (idx >= 0) {
+      /* XXX: Need to read sockname */
       if (type == STR("addr"))
         dcc[idx].addr = my_atoul(buf.c_str());
       if (type == STR("sock")) {

+ 7 - 4
src/mod/transfer.mod/transfer.cc

@@ -736,15 +736,18 @@ struct dcc_table DCC_GET_PENDING =
 
 static void dcc_get_pending(int idx, char *buf, int len)
 {
-  in_addr_t ip;
   in_port_t port;
   int i;
-  char s[UHOSTLEN] = "";
 
-  i = answer(dcc[idx].sock, s, &ip, &port, 1);
+  i = answer(dcc[idx].sock, &dcc[idx].sockname, &port, 1);
   killsock(dcc[idx].sock);
   dcc[idx].sock = i;
-  dcc[idx].addr = ip;
+  /* XXX: Remove this */
+  if (dcc[idx].sockname.ss_family == AF_INET) {
+    dcc[idx].addr = ntohl(((struct sockaddr_in*)&dcc[idx].sockname)->sin_addr.s_addr);
+  } else {
+    dcc[idx].addr = 0;
+  }
   dcc[idx].port = (int) port;
   if (dcc[idx].sock == -1) {
     bd::String msg;

+ 19 - 62
src/net.cc

@@ -859,80 +859,37 @@ char *iptostr(in_addr_t ip)
  * by open_listen ... returns hostname of the caller & the new socket
  * does NOT dispose of old "public" socket!
  */
-int answer(int sock, char *caller, in_addr_t *ip, in_port_t *port, int binary)
+int answer(int sock, sockaddr_storage *caller, in_port_t *port, int binary)
 {
   int new_sock;
   socklen_t addrlen;
-  struct sockaddr_in from;
-  int af_ty = sockprotocol(sock);
-#ifdef USE_IPV6
-  struct sockaddr_in6 from6;
 
-  bzero(&from6, sizeof(struct sockaddr_in6));
-  if (af_ty == AF_INET6) {
-    addrlen = sizeof(from6);
-    new_sock = accept(sock, (struct sockaddr *) &from6, &addrlen);
-  } else {
-#endif /* USE_IPV6 */
-    addrlen = sizeof(struct sockaddr);
-    new_sock = accept(sock, (struct sockaddr *) &from, &addrlen);
-#ifdef USE_IPV6
-  }
-#endif /* USE_IPV6 */
+  addrlen = sizeof(*caller);
+  new_sock = accept(sock, (struct sockaddr *)caller, &addrlen);
   
   if (new_sock < 0)
     return -1;
-  if (ip != NULL) {
-#ifdef USE_IPV6
-    /* Detect IPv4 in IPv6 mapped address .... */
-    if (af_ty == AF_INET6 && (!IN6_IS_ADDR_V4MAPPED(&from6.sin6_addr))) {
-      inet_ntop(AF_INET6, &from6.sin6_addr, caller, 119);
-      caller[120] = 0;
-      *ip = 0L;
-    } else if (IN6_IS_ADDR_V4MAPPED(&from6.sin6_addr)) {    /* ...and convert it to plain (AF_INET) IPv4 address (openssh) */
-      struct sockaddr_in *from4 = (struct sockaddr_in *)&from6;
-      struct in_addr addr;
-
-      memcpy(&addr, ((char *)&from6.sin6_addr) + 12, sizeof(addr));
-      memset(&from, 0, sizeof(from));
-
-      from4->sin_family = AF_INET;
-      addrlen = sizeof(*from4);
-      memcpy(&from4->sin_addr, &addr, sizeof(addr));
-
-      *ip = from4->sin_addr.s_addr;
-      strlcpy(caller, iptostr(*ip), 121);
-      *ip = ntohl(*ip);
+
+  if (port != NULL) {
+    if (caller->ss_family == AF_INET) {
+      *port = ntohs(((struct sockaddr_in *)caller)->sin_port);
+    } else if (caller->ss_family == AF_INET6) {
+      *port = ntohs(((struct sockaddr_in6 *)caller)->sin6_port);
     } else {
-#endif /* USE_IPV6 */
-      if (af_ty == AF_UNIX) {
-        struct sockaddr_un sock_un;
-        socklen_t socklen = sizeof(sock_un);
-
-        bzero(&sock_un, socklen);
-        getsockname(sock, (struct sockaddr*) &sock_un, &socklen);
-        strcpy(caller, sock_un.sun_path);
-        *port = 0;
-      } else {
-        *ip = from.sin_addr.s_addr;
-        strlcpy(caller, iptostr(*ip), 121);
-        *ip = ntohl(*ip);
-      }
-#ifdef USE_IPV6 
+      *port = 0;
     }
-#endif /* USE_IPV6 */
   }
-  if (port != NULL) {
-#ifdef USE_IPV6
-      if (af_ty == AF_INET6)
-        *port = ntohs(from6.sin6_port);
-      else if (af_ty == AF_INET)
-#endif /* USE_IPV6 */
-        *port = ntohs(from.sin_port);
-    }
   /* Set up all the normal socket crap */
   setsock(new_sock, (binary ? SOCK_BINARY : 0));
-  sdprintf("Answered socket %d: %s", new_sock, caller);
+
+#ifdef DEBUG
+  char hbuf[NI_MAXHOST];
+
+  getnameinfo((struct sockaddr *)caller, caller->ss_len, hbuf,
+      sizeof(hbuf), NULL, 0, NI_NUMERICHOST);
+
+  sdprintf("Answered socket %d: [%s]:%d", new_sock, hbuf, *port);
+#endif
   return new_sock;
 }
 

+ 1 - 1
src/net.h

@@ -119,7 +119,7 @@ int real_getsock(int, const char *, int);
 
 int sockprotocol(int);
 void real_killsock(int, const char *, int);
-int answer(int, char *, in_addr_t *, in_port_t *, int);
+int answer(int, sockaddr_storage *, in_port_t *, int);
 int findanysnum(int);
 int findanyidx(int sock);
 int open_listen(in_port_t *);