Free or Net or Open?

TCPIPアクマ本を読むに当たって折角だから生きたコードを見てみたいと考えて、さて、どれいれようか?と迷う。FreeBSDNetBSDOpenBSDか。
早速ぐうぐる先生に聞いてみると以下のページに判りやすく纏めてあった(ありがとうございます)。
http://d.hatena.ne.jp/hcr/20041027/p1
なるほど。大雑把には FreeBSD ... 革新派, NetBSD ... 保守派, OpenBSD ... 真ん中くらい?*1
というところかな。今回の目的だと more clean の Net or Open かな、というところ。

たとえばPCBは?

早速勉強したてホヤホヤのPCBのところのコードを見てみる、と。。。

FreeBSD

IPv6からIPSecまで全部いりなんだけど比較的整理されていてきれい。


netinet/in_pcb.h

  156 struct inpcb {
  157         LIST_ENTRY(inpcb) inp_hash;     /* (i/p) hash list */
  158         LIST_ENTRY(inpcb) inp_list;     /* (i/p) list for all PCBs for proto */
  159         void    *inp_ppcb;              /* (i) pointer to per-protocol pcb */
  160         struct  inpcbinfo *inp_pcbinfo; /* (c) PCB list info */
  161         struct  socket *inp_socket;     /* (i) back pointer to socket */
  162         struct  ucred   *inp_cred;      /* (c) cache of socket cred */
  163         u_int32_t inp_flow;             /* (i) IPv6 flow information */
  164         int     inp_flags;              /* (i) generic IP/datagram flags */
  165         int     inp_flags2;             /* (i) generic IP/datagram flags #2*/
  166         u_char  inp_vflag;              /* (i) IP version flag (v4/v6) */
  167         u_char  inp_ip_ttl;             /* (i) time to live proto */
  168         u_char  inp_ip_p;               /* (c) protocol proto */
  169         u_char  inp_ip_minttl;          /* (i) minimum TTL or drop */
  170         uint32_t inp_flowid;            /* (x) flow id / queue id */
  171         u_int   inp_refcount;           /* (i) refcount */
  172         void    *inp_pspare[4];         /* (x) rtentry / general use */
  173         u_int   inp_ispare[4];          /* general use */
  174 
  175         /* Local and foreign ports, local and foreign addr. */
  176         struct  in_conninfo inp_inc;    /* (i/p) list for PCB's local port */
  177 
  178         /* MAC and IPSEC policy information. */
  179         struct  label *inp_label;       /* (i) MAC label */
  180         struct  inpcbpolicy *inp_sp;    /* (s) for IPSEC */
  181 
  182         /* Protocol-dependent part; options. */
  183         struct {
  184                 u_char  inp4_ip_tos;            /* (i) type of service proto */
  185                 struct  mbuf *inp4_options;     /* (i) IP options */
  186                 struct  ip_moptions *inp4_moptions; /* (i) IP mcast options */
  187         } inp_depend4;
  188         struct {
  189                 /* (i) IP options */
  190                 struct  mbuf *inp6_options;
  191                 /* (i) IP6 options for outgoing packets */
  192                 struct  ip6_pktopts *inp6_outputopts;
  193                 /* (i) IP multicast options */
  194                 struct  ip6_moptions *inp6_moptions;
  195                 /* (i) ICMPv6 code type filter */
  196                 struct  icmp6_filter *inp6_icmp6filt;
  197                 /* (i) IPV6_CHECKSUM setsockopt */
  198                 int     inp6_cksum;
  199                 short   inp6_hops;
  200         } inp_depend6;
  201         LIST_ENTRY(inpcb) inp_portlist; /* (i/p) */
  202         struct  inpcbport *inp_phd;     /* (i/p) head of this list */
  203 #define inp_zero_size offsetof(struct inpcb, inp_gencnt)
  204         inp_gen_t       inp_gencnt;     /* (c) generation count */
  205         struct llentry  *inp_lle;       /* cached L2 information */
  206         struct rtentry  *inp_rt;        /* cached L3 information */
  207         struct rwlock   inp_lock;
  208 };

NetBSD

こちらはNet/3のコードそのまんま。やはり今回の勉強にはこれがよさそう。ちなみにIPv6に関しては netinet6/in6_pcb.hに別物として定義されている。哲学どおり1つ1つは短く、明快になっている。


netinet/in_pcb.h

   76 struct inpcb {
   77         struct inpcb_hdr inp_head;
   78 #define inp_hash        inp_head.inph_hash
   79 #define inp_queue       inp_head.inph_queue
   80 #define inp_af          inp_head.inph_af
   81 #define inp_ppcb        inp_head.inph_ppcb
   82 #define inp_state       inp_head.inph_state
   83 #define inp_socket      inp_head.inph_socket
   84 #define inp_table       inp_head.inph_table
   85 #define inp_sp          inp_head.inph_sp
   86         struct    route inp_route;      /* placeholder for routing entry */
   87         u_int16_t inp_fport;            /* foreign port */
   88         u_int16_t inp_lport;            /* local port */
   89         int       inp_flags;            /* generic IP/datagram flags */
   90         struct    ip inp_ip;            /* header prototype; should have more */
   91         struct    mbuf *inp_options;    /* IP options */
   92         struct    ip_moptions *inp_moptions; /* IP multicast options */
   93         int       inp_errormtu;         /* MTU of last xmit status = EMSGSIZE */
   94 };

OpenBSD

おうわーーーーー、Packet Filter から IPSecからIPv6まで全部入っている。NetBSDから喧嘩別れしてダークサイドに入った? 
というか正直カオス


netinet/in_pcb.h

   88 struct inpcb {
   89         LIST_ENTRY(inpcb) inp_hash;
   90         LIST_ENTRY(inpcb) inp_lhash;            /* extra hash for lport */
   91         CIRCLEQ_ENTRY(inpcb) inp_queue;
   92         struct    inpcbtable *inp_table;
   93         union     inpaddru inp_faddru;          /* Foreign address. */
   94         union     inpaddru inp_laddru;          /* Local address. */
   95 #define inp_faddr       inp_faddru.iau_a4u.inaddr
   96 #define inp_faddr6      inp_faddru.iau_addr6
   97 #define inp_laddr       inp_laddru.iau_a4u.inaddr
   98 #define inp_laddr6      inp_laddru.iau_addr6
   99         u_int16_t inp_fport;            /* foreign port */
  100         u_int16_t inp_lport;            /* local port */
  101         struct    socket *inp_socket;   /* back pointer to socket */
  102         caddr_t   inp_ppcb;             /* pointer to per-protocol pcb */
  103         union {                         /* Route (notice increased size). */
  104                 struct route ru_route;
  105                 struct route_in6 ru_route6;
  106         } inp_ru;
  107 #define inp_route       inp_ru.ru_route
  108 #define inp_route6      inp_ru.ru_route6
  109         int       inp_flags;            /* generic IP/datagram flags */
  110         union {                         /* Header prototype. */
  111                 struct ip hu_ip;
  112                 struct ip6_hdr hu_ipv6;
  113         } inp_hu;
  114 #define inp_ip          inp_hu.hu_ip
  115 #define inp_ipv6        inp_hu.hu_ipv6
  116         struct    mbuf *inp_options;    /* IP options */
  117         struct ip6_pktopts *inp_outputopts6; /* IP6 options for outgoing packets */
  118         int inp_hops;
  119         union {
  120                 struct ip_moptions *mou_mo;    /* IPv4 multicast options */
  121                 struct ip6_moptions *mou_mo6; /* IPv6 multicast options */
  122         } inp_mou;
  123 #define inp_moptions inp_mou.mou_mo
  124 #define inp_moptions6 inp_mou.mou_mo6
  125         u_char    inp_seclevel[4];
  126 #define SL_AUTH           0             /* Authentication level */
  127 #define SL_ESP_TRANS      1             /* ESP transport level */
  128 #define SL_ESP_NETWORK    2             /* ESP network (encapsulation) level */
  129 #define SL_IPCOMP         3             /* Compression level */
  130         u_int     inp_secrequire:4,     /* Condensed State from above */
  131                   inp_secresult:4;      /* Result from Key Management */
  132 #define SR_FAILED         1             /* Negotiation failed permanently */
  133 #define SR_SUCCESS        2             /* SA successfully established */
  134 #define SR_WAIT           3             /* Waiting for SA */
  135         u_char  inp_ip_minttl;          /* minimum TTL or drop */
  136         TAILQ_ENTRY(inpcb) inp_tdb_in_next, inp_tdb_out_next;
  137         struct tdb     *inp_tdb_in, *inp_tdb_out;
  138         struct ipsec_policy *inp_ipo;
  139         struct ipsec_ref *inp_ipsec_remotecred;
  140         struct ipsec_ref *inp_ipsec_remoteauth;
  141 #define inp_flowinfo    inp_hu.hu_ipv6.ip6_flow
  142 
  143         int     in6p_cksum;
  144 #ifndef _KERNEL
  145 #define inp_csumoffset  in6p_cksum
  146 #endif
  147         struct  icmp6_filter *inp_icmp6filt;
  148         void    *inp_pf_sk;
  149 };

というわけでやはり...

お勉強用にはNetBSDですね。組込みでも対応アーキテクチャの広さからNetBSDが選択されることが多いとかいう話(未確認)を聞いたことがあるし。まずはNetBSDで深みにはまってからFreeBSDを見てみよう、とか考えてる。

ちなみにLinuxは、というと、、、ちょうどPCB当たりはsock構造体にあたると思うんだけど、こちらは


include/net/inet_sock.h

108 struct inet_sock {
109     /* sk and pinet6 has to be the first two members of inet_sock */
110     struct sock     sk;
111 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
112     struct ipv6_pinfo   *pinet6;
113 #endif
114     /* Socket demultiplex comparisons on incoming packets. */
115     __be32          daddr;
116     __be32          rcv_saddr;
117     __be16          dport;
118     __u16           num;
119     __be32          saddr;

のようにファイルこそ分かれているんだけど、基本的にはチャンポン、だったり。でもきれいに分離されていて個人的には好き。

*1:コードを見た後の印象は FreeBSD ... 現実派, NetBSD ... 理想派, OpenBSD ... 軍事独裁政権