ignore ECHConfig that have IP address as public name
diff --git a/lib/picotls.c b/lib/picotls.c
index b69db72..9d58141 100644
--- a/lib/picotls.c
+++ b/lib/picotls.c
@@ -1011,6 +1011,7 @@
 static int decode_one_ech_config(ptls_hpke_kem_t **kems, ptls_hpke_cipher_suite_t **ciphers,
                                  struct st_decoded_ech_config_t *decoded, const uint8_t **src, const uint8_t *const end)
 {
+    char *public_name_buf = NULL;
     int ret;
 
     *decoded = (struct st_decoded_ech_config_t){0};
@@ -1054,14 +1055,33 @@
     });
     if ((ret = ptls_decode8(&decoded->max_name_length, src, end)) != 0)
         goto Exit;
+
+#define SKIP_DECODED()                                                                                                             \
+    do {                                                                                                                           \
+        decoded->kem = NULL;                                                                                                       \
+        decoded->cipher = NULL;                                                                                                    \
+    } while (0)
+
+    /* Decode public_name. The specification requires clients to ignore (upon parsing ESNIConfigList) or reject (upon handshake)
+     * public names that are not DNS names or IPv4 addresses. We ignore IPv4 and v6 addresses during parsing (IPv6 addresses never
+     * looks like DNS names), and delegate the responsibility of rejecting non-DNS names to the certificate verify callback. */
     ptls_decode_open_block(*src, end, 1, {
         if (*src == end) {
             ret = PTLS_ALERT_DECODE_ERROR;
             goto Exit;
         }
-        decoded->public_name = ptls_iovec_init(*src, end - *src);
+        if ((public_name_buf = duplicate_as_str(*src, end - *src)) != NULL) {
+            ret = PTLS_ERROR_NO_MEMORY;
+            goto Exit;
+        }
+        if (ptls_server_name_is_ipaddr(public_name_buf)) {
+            SKIP_DECODED();
+        } else {
+            decoded->public_name = ptls_iovec_init(*src, end - *src);
+        }
         *src = end;
     });
+
     ptls_decode_block(*src, end, 2, {
         while (*src < end) {
             uint16_t type;
@@ -1069,14 +1089,15 @@
                 goto Exit;
             ptls_decode_open_block(*src, end, 2, { *src = end; });
             /* if a critital extension is found, indicate that the config cannot be used */
-            if ((type & 0x8000) != 0) {
-                decoded->kem = NULL;
-                decoded->cipher = NULL;
-            }
+            if ((type & 0x8000) != 0)
+                SKIP_DECODED();
         }
     });
 
+#undef SKIP_DECODED
+
 Exit:
+    free(public_name_buf);
     return ret;
 }