かってきままな日々
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)
んー自己署名証明書がエラーにならんなぁ... 使い方が違うのかも。