というワケでKLab社の所で5日間インターンしてきました。というワケとは。

事の発端は逆求人イベントなのですけど、その時指名をいただいて、
気がついたら東京本社近辺で会食を設けていただいたりしました。寿司が止まってた。
本当にありがとうございました…

この時にインターンのお誘いをいただいたので色々話していたのですけど、
終始ルータ作りたいしか言ってなかった気がするので、後の面談を経てIPルーティングを実装するという形に行き着きました。
実施日が3/11から5日間というスケジュールで、面談日が2月の上旬だったので1ヶ月ほど時間がありました。
インターンはC言語との格闘になることが確定していたので、インターン当日までの間にクソ分厚い本と、インターンで使用するmicropsの実装を読んだりしていました。
クソ分厚い本は全然読めてなかったのですけど、micropsはとりあえずinitの処理を片っ端から舐めたりしていました。多分他の関数も読んでた。
当初はポインタの使い方とか本当に分かってなかったのでやっててよかったですね。
あと配列名がその配列の先頭要素のアドレスを示すとかもこの時知った気がする。無知が過ぎるぞ。

こんなんで森ビルから五体満足で退館できるのかという気持ちになっていました。

Day 0

就活でお世話になったキャリアアドバイザーの方とご飯を食べる約束をしていたので、朝7時に家を出て伊賀健二(新幹線)に乗りました。
品川で降りて六本木のロッカーに荷物預けたあと赤坂に行こうとしたのですけど、千代田線が人身事故で止まってました。なんやねんほんま
間に合わなくて死ぬのではと思ったけれど、六本木から赤坂までの距離を調べてみたら15分くらいで着く距離だったので歩きました。
その後は話しながら肉食いました。赤坂の肉うますぎワロタ 赤坂なんも関係ないけど 花粉症で死にかけてた事しか覚えてない
ちなみに奢っていただきました。ありがとうございます….

肉食ったあと浅草に行ってやげん堀七味唐辛子本舗に直進しました。
やげん堀に行く前になんか提灯みたいな有名なアレを見たりしました(死ぬほど適当)
10回以上東京来てる気がするけど、浅草に来たのは多分初です。七味買おうと思わなかったら一生来てないかも。
やげん堀は日本が誇る三大七味(やげん堀, 七味家, 八幡屋礒五郎)の一つとされています。
店が東京に集中しているので、せっかくなので買っていこうかと。
別に七味のオタクじゃないのですけどね。欲しかったので。
やげん堀の七味を構成する香辛料は以下の7種類から成ります。

  • 唐辛子
  • 陳皮(みかんの皮)
  • 粉山椒
  • 黒胡麻
  • けしの実
  • 麻の実
  • 焼唐辛子

また、やげん堀は関東周辺にて屋台出店をしばしばされています。

屋台の場合は構成が少し変わるようです。

  • 唐辛子
  • 陳皮
  • 青海苔
  • 白胡麻
  • 粉山椒
  • 麻の実
  • 焼唐辛子

こっちも欲しいので機会があったら買いに行きたい。というか口上が見たすぎる。
いや七味のオタクではないのですけどね。あと買ったのは七味中辛です。

七味を買ったあとはホテルにチェックインして、micropsのコードを永遠に読んでいました。
ぜんぜん読めなかったので寝ました。

Day 1

遅刻せずに森ビルに着弾しました。えらい
オフィスにお邪魔して諸々の手続きを済ませたあと、メンターの山本雅也さん(@pandax381)と顔合わせ。
micropsにIPルーティングを実装するという方向で進めていきます。

当方それなりにネットワ~クを勉強してきた身ですから、基本的な事柄は大体理解しているつもりです。
IPパケットのヘッダフォーマットとかも調べたら出てくるので、それ見ながら実装すれば終わりちゃうの
みたいな気持ちでいました。ここで「TAPって何ですか」となるワケですね。雲行きが怪しくなる。
まあTAPは超便利だったのですけど。

使うネットワークトポロジはこんな感じです。

お昼は寿司の動きを止めてもらいました。
六本木の寿司うますぎワロタ。

とりあえず、動くことを目標にパケット受信処理の中にフォワーディングの処理を書いていきました。
あと途中でセキュリティガイダンスを受けました。入出館用のカードを失くすと終わるので5日間がんばって死守しました(頑張る所ではない)
案の定C言語が分からなすぎたので、既存の実装を読んだりしてアレしてました。正直1日目の事はあまり覚えていない。
転送時にTTLを引かなかったことは覚えています。

当方それなりにネットワ~クを勉強してきた身ですから、

色々悩みながら最低限動く(と思う)所までは実装できたのでGitHubにブチ上げました。
その後ルータのアプリケーションを書いて実際に動かしてみた所で今日の業務終了です。
ちなみに、動くと思っていたフォワーディング処理は動かんらしい 泣いた
ここからパケット(とブリッジ)の気持ちになっていきます。
まじでブリッジ絶対許さねえからな

晩飯はマクド。
いやクロスポイントが目と鼻の先なのですよね。

Day 2

今日も遅刻せずに森ビルに着弾しました。あと出社が11時からになった。とても白い(何が)。
出社即パケットの気持ちになったワケですけど、パケットの気持ちになる前にブリッジの気持ちを理解する必要がありました。

この時点の実装だとtap11まではARP Requestが飛んでるはずなのですよね。
しかし見えない 意味不明になる
iptablesをflushしたりサービスごと止めたりufwも止めたりしたけど治りませんでした。
解決の目処が立たなかったので、VirtualBox入れて試そうとしたら出てきたウインドウが死ぬほど小さいのですよね

i3wmさんw?w?となる
不思議な力でなんとか拡大して、なんとかVM動かして、VM上でmicropsを実行した所なんとかtap11まではパケットが飛んでいて安心しました。全部Manjaroが悪い。

お昼は麻婆豆腐の気持ちになってました。すごいうまい。しかし辛い。
進捗払い、最終的にはできたはず。
ここからはパケットの気持ちになります。

フォワードがうまく行かない原因を探ってみた所、
フォワード時にTTL引いてるのにチェックサム再計算してなかったり、

当方それなりにネットワ~クを勉強してきた身ですから、

宛先として常にnexthopを常に使ってるからDirect Connectedの時0.0.0.0が宛先になって誰もARP返してくれなかったり、

基本的な事柄は大体理解しているつもりです。

死にたくなってきた。
上記2点を修正したらEcho Replyがちゃんと帰ってきて感動しました。俺がインターネットや

1
2
3
4
5
6
7
8
9
10
11
> ping 172.16.1.2
PING 172.16.1.2 (172.16.1.2) 56(84) bytes of data.
64 bytes from 172.16.1.2: icmp_seq=1 ttl=254 time=0.420 ms
64 bytes from 172.16.1.2: icmp_seq=2 ttl=254 time=0.408 ms
64 bytes from 172.16.1.2: icmp_seq=3 ttl=254 time=0.459 ms
64 bytes from 172.16.1.2: icmp_seq=4 ttl=254 time=0.383 ms
64 bytes from 172.16.1.2: icmp_seq=5 ttl=254 time=0.193 ms
^C
--- 172.16.1.2 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 59ms
rtt min/avg/max/mdev = 0.193/0.372/0.459/0.095 ms

しかしながら、本来ルータのパケット転送処理で何らかのエラーが出た場合、そのエラーに対応するICMPエラーメッセージが帰ってくるはずです。
今の実装ではそれが無いので、現時点でキャッチできるエラーに対応するICMPエラーメッセージを送り返す関数を実装していく必要がありました。
ここからICMPの気持ちになります。

手始めとして、とりあえずルーティングエントリがなかった時にNet Unreachableを返す処理をip.cに直書きしました。
最初はNetwork Unknownを返すつもりだったのですけど、RFC792に従うということでNet Unreachableを返すことになりました。
雑に実装して雑に動いてくれたので本日の業務終了です。

ホスト側でブリッジ使えない事件が本当に不便でストレスマッハだったので、夜中に調べ回したら解決しました。

https://superuser.com/questions/1211852/why-linux-bridge-doesnt-work

どうやらiptablesのFORWARD ChainのDefault PolicyがDROPだったため、ブリッジのフォワードが抑制されていたということらしいです。
/proc/sys/net/bridge/bridge-nf-call-iptablesの値がデフォルト1なので0にするとフィルタリングが無効になるようです。成功しました。
サービスも切ったのに何仕事してくれとるねんという感じでした。解決したので良かった。
良かったのですけど、上のアレは再起動すると1に戻るのでフィルタリングが復活すると思うじゃないですか。
なんか普通に(tap11に)パケット通ってるんだよな 本当に意味わからん

晩飯はマクド。

Day 3

今日も遅刻せずに森ビルに着弾しました。
まずはip.cに直書きしてたICMPの処理をicmp.cに移しました。
移す所は別に困らなかったのですけど、includeしてんのにmakeでundefined referenceが一生出てきて死ぬかと思いました。
無限に悩んだ結果、Makefile内のarp_testのbuildでicmp.oが指定されてなかった(ip.oだけ指定されている状態)のが原因だったみたいですね。ip.cにicmp.hをincludeしたので。
Cのコンパイラとか2回くらいしか使ったことないので…
あとは他のICMPタイプをひたすら実装していました。

お昼はファミマの菓子パンの気持ちになってました。

Union

みなさんに思い出していただきたいのですけど、自分はC言語初心者です。
授業以外で殆ど書いたことが無いので、共用体とかも今日はじめて使ったワケです。
というのも、ICMPヘッダのフォーマット、実はタイプによってコロコロ変わりよるのですね。
今回実装したNet/Host Unreachableとか、TTL Exceeded in Transitとかは後半32bitがUnusedとして扱われるのですけど、
ICMP Redirectの場合は後半32bitにGateway Addressが入るためUnusedではないですし、
最新のICMPの仕様に準拠したFragment neededの場合は後半32bitのうち最初の16bitがUnused、残り16bitに最適なMTU値が入ることになります。
上記のようなヘッダの構造体を今の知識で愚直に定義すると

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
struct icmp_err_hdr {
uint8_t type;
uint8_t code;
uint16_t cksum;
uint32_t unused;
};

struct icmp_redirect_hdr {
uint8_t type;
uint8_t code;
uint16_t cksum;
uint32_t gateway;
};

struct icmp_fragneed_hdr {
uint8_t type;
uint8_t code;
uint16_t cksum;
uint16_t unused;
uint16_t mtu;
};

クソすぎワロタ
こんなん乱立したらさすがにキツイので、共用体でいい感じにしようというやつです。
共用体の内部で定義したデータ型は同じメモリ領域を共有します。
例えば以下に示す超カッコいいICMPヘッダの構造体の場合、union内部で定義しているデータ型で最も大きいものがuint32_tですから、
union内のデータ型は32bitのメモリ領域を共有することになります。
ちなみにuint8_t pointer;は、共有されている32bitのメモリ領域のうち8bitにだけアクセスすることができ、他の領域には指一本触れさせてくれません 多分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
struct icmp_hdr {
uint8_t type;
uint8_t code;
uint16_t cksum;
union {
struct {
uint16_t id;
uint16_t seq;
} echo;
uint8_t pointer;
uint32_t gateway;
uint32_t unused;
} un;
};

便利な世の中ですね(は?)

という感じでICMPヘッダの構造体をいい感じにしつつ、以下3種類のエラーメッセージがサポートされることになりました🎉
謎の数字はType/Codeです。

  • 3/0 Net Unreachable
  • 3/1 Host Unreachable
  • 11/0 Time to Live exceeded in Transit

せっかくなのであと1種類、3/4 Fragment Needed and DF was Setを実装することにしました。
DFビット立ってるか見てパケット長が宛先I/FのMTUよりデカかったら返せばいいので実装は結構チョロいと思ってました。

まあちょっとピヨったのですけども。

1
2
3
4
5
if ((hdr->offset & 0x4000) && (hdr->len > dst_route->netif->dev->mtu)) {
fprintf(stderr, "fragmentation needed and DF set.\n");
icmp_error_tx((struct netif *)iface, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG, dgram, dlen);
return -1;
}

これ書いたらpandaxさんにツッコミ受けました。

バイトオーダー

全く考えてなかった。
インタネットを流れるデータはほぼ確実にネットワークバイトオーダー(ビッグエンディアン)で流れています。
インタネットを流れてきたIPパケットは、IPパケットの構造体にビッグエンディアンのままブチ込まれます。
例えばOffsetの値は0x4000ですけどhdr->offsetは0x0040になったりしています。
パケット長とMTUを比較する所ですけど、hdr->lenの値は84(0x0054)ではなく21504(0x5400)です。
バイト代¥64,000(0xFA00)稼いだのに¥250(0x00FA)しか振り込まれなかったらバ先にダイナマイト投げに行く。
バイト代を256分の1にされたくなければバイトの並び順には気をつけたほうが良いですね。

バイトとバイト掛けてるのですけどそういう話じゃない?

というわけでこうします。

1
if ((ntoh16(hdr->offset) & 0x4000) && (ntoh16(hdr->len) > dst_route->netif->dev->mtu))

ntoh16(中身はntohs)を使ってネットワークバイトオーダーからホストバイトオーダーに変換してあげます。
これでFragment neededも実装できました。
肝心のフラグメント処理はできてないのですけど…
奇跡的に気が向いたらやります。
その前にpandaxさんが2秒で実装していそうな気もした。




ICMP実装するたびに叫んでた

というわけで今日で実質コーディング終了です。

晩飯はマクド。

Day 4

今日も遅刻せずに森ビルに着弾しました。遅刻しないのは当たり前なんだよな。
コードの軽微な修正とプルリク作成、あとは無限の時間があったのでスライド資料を作っていました。
動作確認の項とか結構細かく書いた。
そのあとMergeしてもらってミッションコンプリートです。
まだ作らないといけないところは山程ありますけど、ひとまず終了ということで。
micropsについては、存在自体は結構前から知っていたけれど、まさかそれに自分のコードが取り込まれるとは微塵も思っていなかったので、

Mergeされたときは**(´つヮ⊂) ウオオwww**になっていました。
pandaxさんにインターンの成果をツイートしてもらったら無限に通知が来てびびってました。

karory先生のオタクであることがバレてしまった。
あとなんかフォロワー5人くらい増えた…全員お返しして、あとはひたすらスライド資料を作ってました。
Markdownでしかスライドを書きたくないオタクなのでMarpで書きました。
退勤後も深夜3時まで書き続けてた(は?)

お昼はつけ麺の気持ちになってました。晩飯はマクド。

Last Day

最後まで遅刻せずに森ビルに着弾しました。褒めてくれ
資料作成続き&修正とか。
資料作成の時間はかなりあったので、盛り盛りに盛りまくって最終的に50ページになってしまった。

お昼はとんかつの気持ちになってました。
六本木のとんかつうますぎワロタ。

その後ひたすら発表資料の修正とか調整とか色々やって、つよつよエンジニアさんが集結する前で喋ってました。
死ぬかと思った。喋ってるだけで汗出ることはなかなか無い。

てなワケで、森ビルから生きたまま退館することができました。🎉

自分は今までC言語に殆ど触れられていないので、インターン前は結構な不安があったワケですけど、
pandaxさんからは「普通に書けてる」との評価をいただいて、かなり自信が付きました。
今回やった事より難しい内容だと死んでたかもしれん。

インターンに参加して思ったこととしては薄っぺらいかもしれないですけど、
低レイヤを学ぶことは”コンピュータそのものに触れる”という所があり、やっていてかなり楽しいです。
大学ではみっちりやるんでしょうけど、専門学校は殆どやらないですからね。かなり重要な部分だと思うのですけど。
またエンジニアをやっていく以上、低レイヤのお世話になる日は確実にやってくるはずなので、
トラブルシューティング、あるいはパフォーマンスチューニングにおいても今回取り組んだような事は必須になるはずです。
何より、KLab社のインターンで得た経験は、元々うっすら興味があった低レイヤに頭から突っ込むための起爆剤として十分な役割を果たしてくれました。
(こんな事言いつつ数ヶ月後ノータッチだったら背後を狙われそう)

しかしながら、低レイヤで学ぶ事は”すぐには役立たない あるいは地味である”ものが多いと思うため、真面目にやる場合モチベーションの維持とかも課題になりそうです。
自分は低レイヤの技術はすごく面白いと思っているので、多分続けられると思っています。
また、伝説の灘校教師である橋本武さんは「すぐ役立つことは、すぐ役立たなくなる」という言葉を残されています。
これから学んでいくことを選ぶ際に即効性のような物差しで判断することは極力避けていきたいですね。どうしても今学ばないといけないことなら仕方ないけれど。
過去の同じような例でいえば、IP MulticastとかIntegrated IS-ISとか勉強したことがありましたけど、
勉強した理由はCCIEの範囲だからというだけでなく、考え方やアーキテクチャが面白いからというのもありました。
こういった技術が実生活で活きたことは一度もありませんでした。でも面白かったので後悔していないです。

KLab社の方々、そしてメンターの山本さん、5日間お世話になりました!

生贄としてかずきちを連れてきます。
即答だったのですけどね。

あ、晩飯はマクド。
5日連続マクドナルドで飯食うのやめたほうがいいですよ。

DAY 6

家に帰るまでがインタ~ンですから。
というワケで即ホテル出て即アキバ行って箱買いました。

あー箱箱箱箱箱!!!!!!!!!

その後えっふ&たちのんさんと合流してカレーを飲みました。
マジでカレーは飲み物って名前あるのずるいと思った。噛みましたけど。

飯食った後は自作キーボードのお店に行きました。
ハンドスピナーキーキャップとかいうのあって爆笑した。
意味わからんし高いし意味わからん。
多分osu!のBreakTime中にくるくる回すんだろうな(?)

https://www.amazon.co.jp/dp/B07GLH9XQR

誰が使うんだよ

キーボードの誘惑に耐え抜いた後良いイヤホンの店に行ってヒモの値段にビビったりしました。
イヤホンのケーブル部分だけのやつ。

28万のヒモってなんなんだよマジで。宗教?
あとRAM1GBの古代のMacBookがあってビックリした。音楽聞けるしいいのでしょう。

次はThink FactoryでX250のバッテリーを買いました。
Amazonにあるチャイニーズの怪しいバッテリーはさすがに怖いので、今買っておきました。
72Whで16000円。たけえなあ。
付け替えたらクソブスになった

その後ガス室(メロンブックス)をしばらく回って外出たら夕立でブチギレた。
時間つぶしにHeyでjubeatしたら即指に豆できてこれまたブチギレた。
久々にjubeatしたけど面白いですね。次やるのは100年後です。

雨が消滅したのでHUBに行ってえっふに毒(酒)を奢ってもらいながら3時間籠城しました。多謝🙏
危険な話をたくさんしてた気がする。
あずさんとの初対面名刺交換(Mastodonのアカウントを晒す)イベントが発生してお友達が増えました。

毒浴びた後クソ重い荷物を抱えて奈良に帰りましたとさ。

おわり。

D A Y 7

乗り過ごしたじゃねーかよクソがよ(00:10)

なんか気づいたら最寄り過ぎてて一駅先に着いてしまいました。対向の終電終わってた カス
タクシー呼ぶかと一瞬考えたけど面倒くさくなって、40分くらい歩きました。
荷物は重いし寒いしモバブの給電量が怪しくなってiPhoneのバッテリーが3~6%を行き来してて本当に死ぬかと思った。

帰宅したのは00:50くらいです。

良い子のみんなは終電間際まで遊ばないようにしようね。死ぬので。
特に田舎住みのお前 夜道が闇に染まってるから気をつけろ

以上。