トップ «前の日記 最新 次の日記»

2022-01-16 (Su) [長年日記]

_ Emacs + Wanderlust をデバッグ

いや、何かっていうと、

M-x wl すると、「無効な引数です」(英語名: Invalid argument) と言われて imap4 サーバに接続できない、という…

エラーメッセージにはその他いろいろ情報がくっついてるけど、さっぱりわからん。

でも、エラーメッセージ中の make client process failed が emacs の src/process.c に見つかったので、 そこを手がかりに調べていった。

なんでか connect に失敗してるんだよね… connect の引数 sa の内容を出力してみると、 どうも IPv6 の場合に失敗してるっぽい。

エラーが出ないこともあって、その場合は IPv4 っぽい。

だいぶん絞れてきたけど、「IPv6 の場合に失敗」って、彼らがそんな単純ミスを するとは思えんしなぁ...

で、思い立ったのが link-local。

imap サーバは家庭内 LAN に存在するので、IPv6 の場合は link-local になる。 そして link-local の場合は、インタフェースインデックスが必要で、 それは struct sockaddr_in6 の sin6_scope_id に入ってるはず。 process.c を scope_id で検索しても見つからない。

よしこれだぁ!

で修正して M-x wl で動作確認はできたものの…

若干互換性を破ってるんだよね… sockaddr は vector 型に変換されてて、 てことは、たぶん elisp に返せるようになってる。 そうすると、vector 中の要素数を見て云々してる elisp が存在する可能性がある。

はてさてどうしたものかな。

とりあえずここに貼っとこ。

diff --git a/src/process.c b/src/process.c
index 9664180cfd..709d2e5836 100644
--- a/src/process.c
+++ b/src/process.c
@@ -2510,9 +2510,10 @@ conv_sockaddr_to_lisp (struct sockaddr *sa, ptrdiff_t len)
       {
 	DECLARE_POINTER_ALIAS (sin6, struct sockaddr_in6, sa);
 	DECLARE_POINTER_ALIAS (ip6, uint16_t, &sin6->sin6_addr);
-	len = sizeof (sin6->sin6_addr) / 2 + 1;
+	len = sizeof (sin6->sin6_addr) / 2 + 2;
 	address = make_uninit_vector (len);
 	p = XVECTOR (address);
+	p->contents[--len] = make_fixnum (sin6->sin6_scope_id);
 	p->contents[--len] = make_fixnum (ntohs (sin6->sin6_port));
 	for (ptrdiff_t i = 0; i < len; i++)
 	  p->contents[i] = make_fixnum (ntohs (ip6[i]));
@@ -2582,7 +2583,7 @@ get_lisp_to_sockaddr_size (Lisp_Object address, int *familyp)
 	  return sizeof (struct sockaddr_in);
 	}
 #ifdef AF_INET6
-      else if (p->header.size == 9)
+      else if (p->header.size == 10)
 	{
 	  *familyp = AF_INET6;
 	  return sizeof (struct sockaddr_in6);
@@ -2643,7 +2644,8 @@ conv_lisp_to_sockaddr (int family, Lisp_Object address, struct sockaddr *sa, int
 	{
 	  DECLARE_POINTER_ALIAS (sin6, struct sockaddr_in6, sa);
 	  DECLARE_POINTER_ALIAS (ip6, uint16_t, &sin6->sin6_addr);
-	  len = sizeof (sin6->sin6_addr) / 2 + 1;
+	  len = sizeof (sin6->sin6_addr) / 2 + 2;
+	  sin6->sin6_scope_id = XFIXNUM (p->contents[--len]);
 	  hostport = XFIXNUM (p->contents[--len]);
 	  sin6->sin6_port = htons (hostport);
 	  for (i = 0; i < len; i++)

しばらく使って問題なければ本家に入れようか。

ところで、wanderlust って SSL証明書の確認してなくない…?

もしかして↓これでできる?

(setq gnutls-verify-error t)

んー自己署名証明書がエラーにならんなぁ... 使い方が違うのかも。


編集 パスワード変更