connect(2)を呼ぶと、まずsys_connect()が呼ばれる。sys_connect()はsys/kern/uipc_syscalls.cにある。
if ((error = getsock(p->p_fd, SCARG(uap, s), &fp)) != 0)
return (error);
...
so = (struct socket *)fp->f_data;
...
error = soconnect(so, nam, l);
sys_connect()ではgetsock()でsocketを取得。そのsocketをsoconnect()へ渡している。
soconnect()はsys/kern/uipc_socket.cにある。
error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT,
(struct mbuf *)0, nam, (struct mbuf *)0, l);
で、プロトコル(so_proto)に応じたusrreq関数を呼んでいる。TCPの場合はtcp_usrreq()が呼ばれる。
tcp_usrreq()はsys/netinet/tcp_usrreq.cにあり、
case PRU_CONNECT:
...
error = in_pcbconnect(inp, nam, l);
と、in_pcbconnect()を呼んでいる。
netinet/in_pcb.cのin_pcbconnect()で、
if (sin->sin_port == 0)
return (EADDRNOTAVAIL);
とEADDRNOTAVAILを返している。
本当はgetsock()あたりで、__linkset_add_dataや__linkset_foreachなどおもしろいことが行われているのだが、それはまたいつか書こう。
ところで、uipcとpcbって何の略だろう?
この辺の略語は、どうやって調べたらよいのやら。
