ping localhost

mouseが老衰した

15年近く飼っているマウスが老衰した。女房がマウス欲しいと言って、猫のイラストが入ったパッドと一緒に買った物。スケルトンの小ぶりな奴。

こいつの動きが数日前から、すこぶる悪くなった。ただパソコンの周りを走り回っているだけで、無理はさせなかったんだけどな。老衰で光の発信が弱くなったのかな? で、乱反射の状況を網膜で上手く補足出来なくなったのだろう。

ならば、白黒はっきりするような現場に置いてみるか。藤色のパッドより、より黒いパッドが良いだろう。家の中見回しても黒色の表面が平板な物って、余り無いな。まさか、玉子焼き用のフライパンの裏を使う訳にもいかないしね。

借りてきている本の表紙が夜空の写真と言うのがあった。これを厚いマウスパッドと思って使ってみたら、キビキビと動き出した。応急処置だな。はて、今後はどうする?

ThinkPadなんで、マウスの代わりは、タッチパッドとかトラックポインター(赤ポッチ)で代用可能。だけど、近頃のWindows10は、おさわり画面を推してるみたいで、スクロールバーが極狭。これじゃ、赤ポッチで操作するのは嫌になる。やっぱり、2匹目のうなぎ(7/28)じゃなくて、マウスを用意するかな。まずは100均方面に狩りに出かけてみるか。

ctags -R -e

前回はgdbを使って、kernel側でICMPパケットの処理具合をトレースした。目ぼしい場所にBPを置いて、ヒットしたら、そこに至る経路を表示するってやつ。

この経路情報ってかバックトレースって、schemeで言う継続を見せてくれているのではなかろうか。どこにも有る継続なんて言えば、括弧いいじゃん。いや、scheme知らない人には、糸と言っておこう。それじゃ余りに日本語的と言うなら、スレッドって言えばいい。これなら、あらかたなプログラマーにも理解出来るだろう。

カーネルは割り込み主導型なんで、あちこちにこの継続って言うかスレッドが存在してて、しかもそれらが独立してる。だから、ソースを読む時は、何の目的なスレッドかってのをしっかり把握しとく必要が有る(と思うよ)。前回の例だと、ICMPのパケットが到着した時、カーネルはどんな経路で処理するか、だね。

if_put() に処理が委ねられる、なんて書いたけど、それじゃ、その関数は何処に定義されてたの? 生憎記録を残していなかったので、ソースツリーから再度検索する事になる。

そんな事もあらーなって事で、emacs用のTAGSファイルを作っておいたんだけど、そこには登録が無かった。んな馬鹿な。今回初めて使うのかな。昔の事でうろ覚えなんだけど、

find . -name '*.[ch]' | xargs etags

とかやって作ったと思う。これじゃ、対応出来ないのかな? ググれ。

cd /usr/src/sys
ctags -R -e

こういうのが多数ヒットした。注意書きとして、emacsをインストールすると、ctags,etagsも一緒にインストールされるけど、このctagsを使ってはいけないとの事。ちゃんと sudo apt install ctags して、お勧めの拡張されたctagsをインストールしなさいって事みたい。

確かに、emacsから来たctagsには、-eオプション(emacs用のtag生成)はサポートされていなかった。拡張版はちゃんとサポートされてた。識者によると、debianの場合は、色々なアプリが取替可能になってるそうである。

sakae@pen:~$ ls -l /etc/alternatives/ctags
lrwxrwxrwx 1 root root 24 Jul 11 15:24 /etc/alternatives/ctags -> /usr/bin/ctags-exuberant

ctags xxってやると、/etc/alternativesの下を見て、リンクをたどるって機構になってる。恐ろしいと言うか便利と言うか。。。300個近い代替アプリが登録されてたぞ。

こんな機構はOpenBSDでは許し難い。じゃ、etagsで何とかするしかないだろう(デフォのctagsはBSD由来の奴だからね)。穴の開くほどetagsのマニュアルを参照。

-a, --append
       Append to existing tag file.  (For vi-format tag files, see also
       --update.)

これを使えばいいのかな。

カーネルソースを読む ( 3 ) タグファイルを作る ( Emacs )

やっぱりね。どうやら当たりのようです。こちらの方は、アセンブラまで視野に入れてらっしゃるみたいで、頭が下がりますよ。オイラーはインテル石のアセンブラなんて読めないのさ。

TAGSファイルが有ると、defineの場所とかへも簡単に飛んで行けるので、便利です。例

netinet/ip_icmp.c

case ICMP_ECHO:
        if (!icmpbmcastecho &&
            (m->m_flags & (M_MCAST | M_BCAST)) != 0) {
                icmpstat_inc(icps_bmcastecho);
                break;

ICMP_ECHO って、何よ? カーソル合わせてタグジャンプ ip_icmp.h

#define ICMP_ECHO               8               /* echo service */

ヘッダーファイル・ファーストって、都民ファーストに通じるものがあるな。よく忘れるけどね(小池のボスさん)。 この便利なデータベースは巨大です。140Mも有りました。使う時、巨大だけど本当に使っていいかってemacsが確認を求めてきますよ。

Linux src

上の方もリナのソースを見ているし、食わず嫌いはいかんぜよ、とばかりオイラーも参照してみる(本当は、前回の最後にチラ出ししたeBPFを見たいと言う野次馬根性)。 kernel.orgへ行って次期でびあんに採用されるであろうやつを落としてきた。展開すると、 1.1Gって、どんだけオバケだ。ハリボテ具合を確認。

sakae@debian:/usr/src/linux-5.10.46$ du -s * | sort -nr
686216	drivers
136912	arch
53632	Documentation
47436	include
43416	fs
43116	tools
41584	sound
33880	net
11156	kernel
6280	lib
4228	mm
3816	scripts
3644	crypto
3176	security
1868	block
1712	samples
564	MAINTAINERS
264	ipc
256	LICENSES
228	virt
200	init
100	CREDITS
64	usr
64	Makefile
56	certs
4	README
4	Kconfig
4	Kbuild
4	COPYING

半分以上は、ドライバーか。世の中にあるデバイスを貪欲に取り込んでいるのが魅力なのかな。

今ちょうどやってるICMPな部分がどうなっているか、ちょいと調べてみる。全く土地勘がないので、特徴的な語句を探す。

sakae@debian:/usr/src/linux-5.10.46$ find . -name '*.c' | xargs grep -l ICMP_ECHO
./tools/testing/selftests/bpf/progs/xdping_kern.c
./tools/testing/selftests/bpf/progs/test_cls_redirect.c
./net/ipv4/proc.c
./net/ipv4/ping.c
./net/ipv4/route.c
./net/ipv4/icmp.c
./net/ipv4/netfilter/nf_log_ipv4.c
./net/ipv4/netfilter/ipt_REJECT.c
./net/ipv4/netfilter/ipt_CLUSTERIP.c
./net/core/flow_dissector.c
./net/netfilter/nf_nat_proto.c
./net/netfilter/nf_conntrack_proto_icmp.c

ぴったりそうな、net/ipv4/icmp.cを開いてみた。

static bool icmp_echo(struct sk_buff *skb)
{
	struct net *net;

	net = dev_net(skb_dst(skb)->dev);
	if (!net->ipv4.sysctl_icmp_echo_ignore_all) {
		struct icmp_bxm icmp_param;

		icmp_param.data.icmph	   = *icmp_hdr(skb);
		icmp_param.data.icmph.type = ICMP_ECHOREPLY;
		icmp_param.skb		   = skb;
		icmp_param.offset	   = 0;
		icmp_param.data_len	   = skb->len;
		icmp_param.head_len	   = sizeof(struct icmphdr);
		icmp_reply(&icmp_param, skb);
	}
	/* should there be an ICMP stat for ignored echos? */
	return true;
}

要求を受けたら、即返信モードに設定して、返事をだしてるね。後は、どんな継続が組み立てられているかは、gdbを使った方が圧倒的に楽。簡単にgdb出来る環境って組み立てられるの?

gdb-kernel-debugging.txt

Linux kernelのデバッグ

やっぱり、qemuにdebug用のカーネルを入れてやるんだね。ユーザーアプリが、initだけってのは、寂しいぞ。OSを丸ごと入れた物って、用意が大変だからね。その点、オイラーのOpenBSD観光は、どんなユーザーランドにも対応してる。小粒だけど、非常に便利で楽しいぞ。

OpenBSD src

対抗上、OpenBSDのカーネルエリアの容量も確認。全体では283Mと小粒です。

vbox$ du -s * | sort -nr
501004  dev
47876   arch
6152    net
4260    kern
3776    lib
2436    sys
2288    netinet
1728    ufs
1672    uvm
1440    net80211
1176    netinet6
1028    scsi
964     crypto
912     nfs
472     isofs
444     stand
444     msdosfs
404     ddb
284     tmpfs
260     ntfs
224     miscfs
116     conf
76      netmpls
4       Makefile

やっぱりデバドラの容量がダントツだね。archも大きいので、一応確認

vbox$ ls arch
alpha/     arm64/     i386/      luna88k/   mips64/    powerpc64/ sparc64/
amd64/     armv7/     landisk/   m88k/      octeon/    sgi/
arm/       hppa/      loongson/  macppc/    powerpc/   sh/

これってOpenBSDの元になったNetBSDのDNAを継承してるのかな。ちょっと歴史的だな。何でも新しい方が良いと、IDEのツリーを最近削除しちまったリナとは、大違い。

リナではnet-dirの下にipv4とかipv6ってdirが配置されてるけど、OpenBSDは、独立してるね。考え方の違いが有るんだな。多分、こうだったんじゃなかろうか劇場(あれをパクってます)。

昔々、その昔、4.X BSDを継承した時、netが現れた。混沌とした世界、ゼロックスは独自プロトコルを流行らせようとするし、それを牽制しようとISOと言う標準機構も口出し。そんな事になって見通しがつかないため、それらは袂を別れたじゃなくて、dirを別にして独立性を保った。

が、主流はTCP/IPに傾き、今後の大いなる発展が期待された。で、netの下に関係者を全部入れてしまえって案も出たが、ファイル個数のバランスを考慮してnetinetが並列的に作成された(ここはIPv4関係者)。

そのうちに、日本発のIPv6プロジェクトとして、 kameプロジェクトが発動した。名前の由来は、同プロジェクトの主要開発者 萩野純一郎氏の行動による。開発合宿で、どうしても取れないバグに遭遇。その時、近くに有った亀さんぬいぐるみにすがった所、霊感新たに、バグが取れたらしい。で、縁起物の亀がプロジェクト名になった。

このIPv6スタックは、勿論OpenBSDに移植されてる。netinet6 としてね。このIPv6が取り込まれたOpenBSD 4.2は、直前に急逝した彼に捧げられている。

リナは対抗してIPv6プロジェクトとして、うさぎ を利用したが、絶対に亀には追いつけないぞ。ウサギとカメとアキレスとゼノン

ping localhost

前回苦労して作った、tapを使った環境。遊んでいる時、HostOSのネットがハングアップしちゃう事が有った。これじゃ、安心して遊べない。そこで頭を振る回転、目眩がして出た結論は?

強い味方がいるじゃないですか。loopbackデバイスという奴ね。これなら、送り出したパケットがOS内部で折り返される。だから、普通にpingしたら、送受の継続が実行されるんではなかろうか。

ホストOSで、予備実験してみる。

sakae@pen:~$ ping -c 2 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.184 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.082 ms

普通にlocalhostを指定すると、IPv6のそれが使われちゃったので、生IPを指定したよ。

sakae@pen:/tmp$ sudo tcpdump -i lo icmp
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes
08:21:08.164755 IP localhost > localhost: ICMP echo request, id 2724, seq 1, length 64
08:21:08.164818 IP localhost > localhost: ICMP echo reply, id 2724, seq 1, length 64
08:21:09.186158 IP localhost > localhost: ICMP echo request, id 2724, seq 2, length 64
08:21:09.186182 IP localhost > localhost: ICMP echo reply, id 2724, seq 2, length 64

tcpdumpと言う、公正な観測者からもお墨付きを得たぞ。これで思う存分、楽しめそう。

lo

localhostは文字通り、ローカルで完結する。使うデバイスはloだ。manを引いてみると

NAME
     lo – software loopback network interface

SYNOPSIS
     pseudo-device loop

DESCRIPTION
     The loop interface is a software loopback mechanism which may be used for
     performance analysis, software testing, and/or local communication.

仮想デバイスってなってる。何処に定義されてるの? loopbackなんて言うコメント文字を全文検索。辿りついた所は、 net/if_loop.c

/*
 * Loopback interface driver for protocol testing and timing.
 */

#define LOMTU   32768

int     loioctl(struct ifnet *, u_long, caddr_t);
void    loopattach(int);
void    lortrequest(struct ifnet *, int, struct rtentry *);
void    loinput(struct ifnet *, struct mbuf *);
int     looutput(struct ifnet *,
            struct mbuf *, struct sockaddr *, struct rtentry *);

int     loop_clone_create(struct if_clone *, int);
int     loop_clone_destroy(struct ifnet *);

パケットが外に出ていかないので、1パケットの梱包サイズを大きくしても大丈夫。皆様に迷惑をかける事が無い。ってんで、通常1500サイズの所を、大判振る舞いで32768にしてる。IPv6とかで、無理するとジャイアント・パケットを設定出来たかな。ジャイアントと言っても、16kだったような。。

デバドラの体裁になってますなあ。デバイスを作ったり、接続したり破棄したり。

ob$ doas ifconfig lo1 create
ob$ ifconfig -a
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 32768
        index 3 priority 0 llprio 3
        groups: lo
        inet6 ::1 prefixlen 128
        inet6 fe80::1%lo0 prefixlen 64 scopeid 0x3
        inet 127.0.0.1 netmask 0xff000000
        :
lo1: flags=8008<LOOPBACK,MULTICAST> mtu 32768
        index 4 priority 0 llprio 3
        groups: lo

lo1って言う2番目のデバイスを作ってみた。登録はされたけど、まだ活動出来ない。

ob$ doas ifconfig lo1 127.0.0.2
ob$ ifconfig lo1
lo1: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 32768
        index 4 priority 0 llprio 3
        groups: lo
        inet 127.0.0.2 netmask 0xff000000
ob$ ping 127.0.0.2
PING 127.0.0.2 (127.0.0.2): 56 data bytes
64 bytes from 127.0.0.2: icmp_seq=0 ttl=255 time=0.156 ms
64 bytes from 127.0.0.2: icmp_seq=1 ttl=255 time=0.202 ms
   :

IPを振ると同時に、活性化した。一応動作確認。

using lo driver

loinput,looutputに網を張ってから、ping localhostしてみた。

(gdb) bt 8
#0  looutput (ifp=0xd180bc00, m=0xd1893300, dst=0xd17b0758, rt=0xd178ad5c) at /usr/src/sys/net/if_loop.c:246
#1  0xd06332ca in ip_output (m0=0xd1893300, opt=0x0, ro=0xd17b0750, flags=32, imo=0x0, inp=0xd17b0708, ipsecflowinfo=0) at /usr/src/sys/netinet/ip_output.c:470
#2  0xd0da551e in rip_output (m=0xd1893300, so=0xd17b1d20, dstaddr=0xf1d09368, control=0x0) at /usr/src/sys/netinet/raw_ip.c:286
#3  0xd0da5fa4 in rip_usrreq (so=0xd17b1d20, req=9, m=0xd1893900, nam=0xd1893700, control=0x0, p=0xd1681d8c) at /usr/src/sys/netinet/raw_ip.c:538
#4  0xd021ccef in sosend (so=0xd17b1d20, addr=0xd1893700, uio=0xf1d094b0, top=0xd1893900, control=0x0, flags=0) at /usr/src/sys/kern/uipc_socket.c:524
#5  0xd051e618 in sendit (p=0xd1681d8c, s=3, mp=0xf1d09530, flags=0, retsize=0xf1d0967c) at /usr/src/sys/kern/uipc_syscalls.c:662
#6  0xd051e9f4 in sys_sendmsg (p=0xd1681d8c, v=0xf1d09684, retval=0xf1d0967c) at /usr/src/sys/kern/uipc_syscalls.c:567
#7  0xd06bae59 in mi_syscall (p=0xd1681d8c, code=28, callp=0xd10f8ff8 <sysent+336>, argp=0xf1d09684, retval=0xf1d0967c) at /usr/src/sys/sys/syscall_mi.h:92
(More stack frames follow...)

frame 6で、システムコールが見て取れる。

(gdb) bt
#0  loinput (ifp=0xd180bc00, m=0xd1893300, cookie=0x0) at /usr/src/sys/net/if_loop.c:232
#1  0xd0398db4 in if_ih_input (ifp=0xd180bc00, m=0xd1893300) at /usr/src/sys/net/if.c:912
#2  0xd0398d36 in if_input_process (ifp=0xd180bc00, ml=0xf1cc6c48) at /usr/src/sys/net/if.c:946
#3  0xd0a54e13 in ifiq_process (arg=0xd180be70) at /usr/src/sys/net/ifq.c:607
#4  0xd06be752 in taskq_thread (xtq=0xd17fd040) at /usr/src/sys/kern/kern_task.c:367
#5  0xd09af481 in proc_trampoline ()

こちらは、受信の方だから、システムコールは見えていない。丹念に追っていけば、見えるかな?

見えない、見えない! デカとしては筋読み失敗の新人刑事ですよ。このスレッドが、何処に繋がるか、裏読みしてミロ。

長くなりそうなので、今日の所はこれぐらいにしといたる。

Blue LED

な、マウスをget。結局100均には無くて、ホームセンターへ。 主流は無線マウスになってて、有線マウスは2種しか無かった。赤と青バージョンのLED式。どっちかから選べ。中村先生に敬意を表して、青色式のやつにした。金648円也。赤式はこれよりちょっと安かったけど、時代の進歩に追従って事で。

この青色式は、白い紙の上でも反応した。ガラス面上では動かない場合があるそうだけど、そこまでは、求めまい。

昔のマウスは、玉がゴロゴロする機械式。ずっと使っているとゴミを巻き込んで、動きが悪くなる。そんな時は、綿棒で掃除をしたものだ。それに、USBなんて無い時代だから、PS2なんて言う規格の丸いコネクタが主流だったな。ああ、懐かしい。

更に余談になるけど、 どうやら都会の100均ではマウスも手に入るみたい。 Bluetoothマウスも100円ショップで手に入る!? 楽しい事、やってますなあ。

password gen

パスワード管理ってみんなどうしてるの??こうするといいと思うよ!

オイラーも真似してみよう。Windows10に入っているWSL上のDebian用

sakae@pen:~$ echo -n hallo | shasum -a 256 | base64 -w0 | cut -b -20
ZDM3NTFkMzNmOWNkNTA0
sakae@pen:~$ echo -n hall | shasum -a 256 | base64 -w0 | cut -b -20
M2NiYWViNTdjNjQwMjBl

記号を混ぜろとか言われると、プチ面倒。cutの所をawkにでもして、ちょっとプログラミングぽい事をせにゃならん。でも、記号は3文字以上、数字は4文字以上とか面倒言うのには、対応が難しいな。

あ、ここで使ったshasumは、母語がperlさんか。彼がPerl module Digest::SHAを呼び出しているとな。ならば、記号の事は、彼に任せればいいのか。って、今更記号言語perlなんて、オイラーには、難し過ぎて使えませんよ。ちょいと覗いてみたら、正規表現のオンパレード、桑原桑原、ブルブルブル。

ついでに、リナでしか動かない事にも、ブルブルブルブルしとく。OpenBSDでも動くように汎用化しとけ。道具は、どんな環境でも動いてこそ、です。

vbox$ echo ha | openssl sha224
(stdin)= b936af95a546a471264bfea2662a2029fdc7cd333df0308fd06fcd0c
vbox$ echo 9fdc7cd333df0308fd06f | openssl base64
OWZkYzdjZDMzM2RmMDMwOGZkMDZmCg==

主要エンジン部分の置き換えが可能か、確認しました。ここまでやったら、スクリプトにしておくってのが親切ってものだろう。

#!/bin/sh
# Usage: pg.sh mypassword [n]

n=$2
if [ "x$2" = "x" ]; then
    n=20
fi

start=66
stop=`expr $start + $n`
stop=`expr $stop - 1`

echo -n "$1"    |
openssl sha512  |
openssl base64  |
tr -d '\n'      |
cut -b $start-$stop

nはデフォルトのパスワード長。startの66は、ソルトの積り。この値を変更する時は、よく考えてね。小さすぎてもいけないし、長すぎてもまずいです。

[sakae@fb /tmp]$ ./pg.sh sakae
mU2NWQ1NTJkYjUzZTI1M
[sakae@fb /tmp]$ ./pg.sh sakae 10
mU2NWQ1NTJ
[sakae@fb /tmp]$ ./pg.sh 'sakae desu'
WQ1MzA4NTQ4MDA1MDI5M

FreeBSDでの実行例です。

password checker にかけたら、10000世紀のうちにに解読されるかも、ですってさ。


This year's Index

Home