chiark / gitweb /
server/: Use modern functions for address/text conversions.
[tripe] / server / peer.c
index ea6e09bb8a8b85897bfa47685e45e3ca590c893a..34bfb6c4d2b3653de18bb77424c9e5b409048b6c 100644 (file)
@@ -336,6 +336,10 @@ static void p_read(int fd, unsigned mode, void *v)
   ssize_t n;
   int ch;
   buf b, bb;
+#ifndef NTRACE
+  int ix = -1;
+  char name[NI_MAXHOST], svc[NI_MAXSERV];
+#endif
 
   /* --- Read the data --- */
 
@@ -346,14 +350,18 @@ static void p_read(int fd, unsigned mode, void *v)
     a_warn("PEER", "-", "socket-read-error", "?ERRNO", A_END);
     return;
   }
+  IF_TRACING(T_PEER, {
+    ix = afix(a.sa.sa_family);
+    getnameinfo(&a.sa, sz, name, sizeof(name), svc, sizeof(svc),
+               NI_NUMERICHOST | NI_NUMERICSERV);
+  })
 
   /* --- If the packet is a greeting, don't check peers --- */
 
   if (n && buf_i[0] == (MSG_MISC | MISC_GREET)) {
     IF_TRACING(T_PEER, {
-      trace(T_PEER, "peer: greeting received from INET %s %u",
-           inet_ntoa(a.sin.sin_addr),
-           (unsigned)ntohs(a.sin.sin_port));
+      trace(T_PEER, "peer: greeting received from %s %s %s",
+           aftab[ix].name, name, svc);
       trace_block(T_PACKET, "peer: greeting contents", buf_i, n);
     })
     buf_init(&b, buf_i, n);
@@ -379,11 +387,11 @@ static void p_read(int fd, unsigned mode, void *v)
   IF_TRACING(T_PEER, {
     if (p) {
       trace(T_PEER,
-           "peer: packet received from `%s' from address INET %s %d",
-           p_name(p), inet_ntoa(a.sin.sin_addr), ntohs(a.sin.sin_port));
+           "peer: packet received from `%s' from address %s %s %s",
+           p_name(p), aftab[ix].name, name, svc);
     } else {
-      trace(T_PEER, "peer: packet received from unknown address INET %s %d",
-           inet_ntoa(a.sin.sin_addr), ntohs(a.sin.sin_port));
+      trace(T_PEER, "peer: packet received from unknown address %s %s %s",
+           aftab[ix].name, name, svc);
     }
     trace_block(T_PACKET, "peer: packet contents", buf_i, n);
   })
@@ -772,45 +780,62 @@ const addr *p_addr(peer *p) { return (&p->spec.sa); }
 
 /* --- @p_init@ --- *
  *
- * Arguments:  @struct in_addr addr@ = address to bind to
- *             @unsigned port@ = port number to listen to
+ * Arguments:  @struct addrinfo *ailist@ = addresses to bind to
  *
  * Returns:    ---
  *
  * Use:                Initializes the peer system; creates the socket.
  */
 
-void p_init(struct in_addr addr, unsigned port)
+void p_init(struct addrinfo *ailist)
 {
   int fd;
-  struct sockaddr_in sin;
   int len = PKBUFSZ;
+  int i;
+  struct addrinfo *ai;
+  unsigned port, lastport = 0;
+  addr a;
+  socklen_t sz;
 
-  /* --- Note on socket buffer sizes --- *
-   *
-   * For some bizarre reason, Linux 2.2 (at least) doubles the socket buffer
-   * sizes I pass to @setsockopt@.  I'm not putting special-case code here
-   * for Linux: BSD (at least TCPv2) does what I tell it rather than second-
-   * guessing me.
-   */
-
-  if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
-    die(EXIT_FAILURE, "socket creation failed: %s", strerror(errno));
-  BURN(sin);
-  sin.sin_family = AF_INET;
-  sin.sin_addr = addr;
-  sin.sin_port = htons(port);
-  if (bind(fd, (struct sockaddr *)&sin, sizeof(sin)))
-    die(EXIT_FAILURE, "bind failed: %s", strerror(errno));
-  if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len)) ||
-      setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &len, sizeof(len))) {
-    die(EXIT_FAILURE, "failed to set socket buffer sizes: %s",
-       strerror(errno));
+  for (i = 0; i < NADDRFAM; i++) udpsock[i].fd = -1;
+
+  for (ai = ailist; ai; ai = ai->ai_next) {
+    if ((i = afix(ai->ai_family)) < 0) continue;
+    if (udpsock[i].fd != -1) continue;
+
+    /* --- Note on socket buffer sizes --- *
+     *
+     * For some bizarre reason, Linux 2.2 (at least) doubles the socket
+     * buffer sizes I pass to @setsockopt@.  I'm not putting special-case
+     * code here for Linux: BSD (at least TCPv2) does what I tell it rather
+     * than second-guessing me.
+     */
+
+    if ((fd = socket(ai->ai_family, SOCK_DGRAM, 0)) < 0)
+      die(EXIT_FAILURE, "socket creation failed: %s", strerror(errno));
+    assert(ai->ai_addrlen <= sizeof(a));
+    memcpy(&a, ai->ai_addr, ai->ai_addrlen);
+    if ((port = getport(&a)) == 0 && lastport) setport(&a, lastport);
+    if (bind(fd, &a.sa, addrsz(&a)))
+      die(EXIT_FAILURE, "bind failed: %s", strerror(errno));
+    if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len)) ||
+       setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &len, sizeof(len))) {
+      die(EXIT_FAILURE, "failed to set socket buffer sizes: %s",
+         strerror(errno));
+    }
+    fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
+    sel_initfile(&sel, &udpsock[i], fd, SEL_READ, p_read, 0);
+    sel_addfile(&udpsock[i]);
+    T( trace(T_PEER, "peer: created %s socket", aftab[i].name); )
+    if (!port) {
+      sz = sizeof(a);
+      if (getsockname(fd, &a.sa, &sz)) {
+       die(EXIT_FAILURE, "failed to read local socket address: %s",
+           strerror(errno));
+      }
+      lastport = getport(&a);
+    }
   }
-  fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC);
-  sel_initfile(&sel, &udpsock[AFIX_INET], fd, SEL_READ, p_read, 0);
-  sel_addfile(&udpsock[AFIX_INET]);
-  T( trace(T_PEER, "peer: created socket"); )
 
   sym_create(&byname);
   am_create(&byaddr);