Fix some IPv6 address compatibility issues.
[srvx.git] / src / proto-p10.c
index c5ce032d4c001072bdcc4635e1f2513f81064bd8..a5d61e47664f133e2765650ec40dae2f3397d25b 100644 (file)
@@ -368,10 +368,10 @@ irc_server(struct server *srv)
     inttobase64(extranum, srv->num_mask, (srv->numeric[1] || (srv->num_mask >= 64*64)) ? 3 : 2);
     if (srv == self) {
         /* The +s, ignored by Run's ircu, means "service" to Undernet's ircu */
-        putsock(P10_SERVER " %s %d %li %li J10 %s%s +s :%s",
+        putsock(P10_SERVER " %s %d %li %li J10 %s%s +s6 :%s",
                 srv->name, srv->hops+1, srv->boot, srv->link, srv->numeric, extranum, srv->description);
     } else {
-        putsock("%s " P10_SERVER " %s %d %li %li %c10 %s%s +s :%s",
+        putsock("%s " P10_SERVER " %s %d %li %li %c10 %s%s +s6 :%s",
                 self->numeric, srv->name, srv->hops+1, srv->boot, srv->link, (srv->self_burst ? 'J' : 'P'), srv->numeric, extranum, srv->description);
     }
 }
@@ -383,6 +383,8 @@ irc_p10_pton(irc_in_addr_t *ip, const char *input)
         unsigned int value;
         memset(ip, 0, 6 * sizeof(ip->in6[0]));
         value = base64toint(input, 6);
+        if (value)
+            ip->in6[5] = htons(65535);
         ip->in6[6] = htons(value >> 16);
         ip->in6[7] = htons(value & 65535);
     } else {
@@ -404,7 +406,9 @@ irc_p10_pton(irc_in_addr_t *ip, const char *input)
 static void
 irc_p10_ntop(char *output, const irc_in_addr_t *ip)
 {
-    if (irc_in_addr_is_ipv4(*ip)) {
+    if (!irc_in_addr_is_valid(*ip)) {
+        strcpy(output, "AAAAAA");
+    } else if (irc_in_addr_is_ipv4(*ip)) {
         unsigned int in4;
         in4 = (ntohs(ip->in6[6]) << 16) | ntohs(ip->in6[7]);
         inttobase64(output, in4, 6);
@@ -596,6 +600,21 @@ irc_pong(const char *who, const char *data)
     putsock("%s " P10_PONG " %s :%s", self->numeric, who, data);
 }
 
+void
+irc_pong_asll(const char *who, const char *orig_ts)
+{
+    char *delim;
+    struct timeval orig;
+    struct timeval now;
+    int diff;
+
+    orig.tv_sec = strtoul(orig_ts, &delim, 10);
+    orig.tv_usec = (*delim == '.') ? strtoul(delim + 1, NULL, 10) : 0;
+    gettimeofday(&now, NULL);
+    diff = (now.tv_sec - orig.tv_sec) * 1000 + (now.tv_usec - orig.tv_usec) / 1000;
+    putsock("%s " P10_PONG " %s %s %d " FMT_TIME_T ".%06u", self->numeric, who, orig_ts, diff, now.tv_sec, (unsigned)now.tv_usec);
+}
+
 void
 irc_pass(const char *passwd)
 {
@@ -957,8 +976,8 @@ static CMD_FUNC(cmd_ping)
     struct server *srv;
     struct userNode *un;
 
-    if(argc > 3)
-        irc_pong(argv[2], argv[1]);
+    if (argc > 3)
+        irc_pong_asll(argv[2], argv[3]);
     else if ((srv = GetServerH(origin)))
         irc_pong(self->name, srv->numeric);
     else if ((un = GetUserH(origin)))