gaddr - みる会図書館


検索対象: UNIX MAGAZINE 2004年8月号
15件見つかりました。

1. UNIX MAGAZINE 2004年8月号

図 18 473 474 475 476 477 478 479 480 図 19 526 527 528 531 532 533 534 535 536 537 538 連載 / v6 の実装ー 0 グローバルアドレスのオ for (galp = halp—>hagent—galist . hagent—next—gaddr ; galp ; galp = galp->hagent-next-gaddr) { if ( (galp—>hagent—prefixlen ha—prefixlen) & & IN6_ARE_ADDR_EQUAL ( & (galp->hagent_gaddr) , ha_addr) ) break ; return galp ; グローバルアドレス・リストの角攵 while (halp—>hagent—galist . hagent—next—gaddr) { tmp = halp—>hagent—galist . hagent—next—gaddr ; halp—>hagent—galist . hagent—next—gaddr = tmp—>hagent—next—gaddr ; if (tmp—>hagent—next—expire) { tmp¯>hagent—next—expire—>hagent—prev—expire tmp—>hagent—prev—expire ; if (tmp—>hagent—prev—expire) { tmp—>hagent—prev—expire—>hagent—next—expire tmp¯>hagent—next—expire ; ルアドレスの重複登録カ吮生することはありません。 グローバルアドレスの検索 あるホームエージェントのグローバルアドレス情報を検 索するには hal-gaddr-find() 関数を使います。 465 static struct hagent_gaddr * 466 hal—gaddr—f ind(halp , ha—addr , 467 468 469 ha—prefixlen) struct hagent—entry *halp ; struct in6_addr *ha_addr ; u—int8—t ha—prefixlen ; gaddr-clean() 関数で実装されます。 519 void 520 hal—gaddr—clean (halp) struct hagent—entry *halp ; 521 522 { hal-gaddr-clean() 関数は解放したいグローバルアドレ ス・リストをイ尉寺している hagent-entry 構造体へのポイ ンタを引数にとります。 グローバルアドレスのリストは hagent-entry 構造体の hagent-galist メンバー変数に保持されています。グロー バルアドレスは、インターフェイスごとのリストとノード 全体で管理されている有効時間川頁のリストの 2 つのリスト で管理されています。図 19 の 526 行目のループで、リス トのエントリを 1 つずったどりながら、効時間順のリス トからエントリを削除します。 470 { hal-gaddr-find() 関数は 3 つの引数をもちます。 halp は検索対象となるホームエージェントの情報を保持した hagent-entry 構造体へのポインタ、 ha-addr は検索した いホームエージェントのグローバルアドレス、 ha-prefix- len はグローバルアドレスのプレフィックス長です。 グローバルアドレスは hagent-gaddr 構造体リストのか たちで hagent-entry 構造体の hagent-galist 変数に保持 されています。リストを順番にたどりながら、指定された プレフィックス長をもち、 hal-gaddr-find() の引数で指定 されたグローバルアドレスと同じ値をもつ hagent-gaddr 構造体のポインタを返します ( 図 18 ) 。 グローバルアドレス・リストの解放 グローバルアドレスを保持するリストは、 hagent-en- try 構造体が解放されるときに同時に解放されなければな りません。グローバルアドレス・リストの解放処理は hal- UNIX MAGAZINE 2004.8 540 541 free(tmp) ; 542 } ノード全体のリストからエントリを取り除いたあと、 540 行目で情報をイ尉寺しているメモリを解放します。 ☆ 次回も引き続き、動的ホームエージェント探索処理を解 説します。 81 ( しま・けいいち IIJ)

2. UNIX MAGAZINE 2004年8月号

連載 / 旧 v6 の実装ー 0 図 7 ホームエージェン b'l 貶里する構本の系 hagent_ifinfo{ } 配列 hagent_ifinfo{ } halist_pref haif_gavec hagent_entry{ } hagent_next_expire hagent_prev_expire hagent_next_pref hagent_prev_pref hagent_ifinfo{ } halist_pref haif_gavec hagent_entry{ } リスト hagent—ifa—pair{ } 配列 hagent_ifinfo{ } halist_pref haif_gavec hagent_entry{ } リスト hagent—ifa—pair{ } 配列 hagent_galist hagent_entry{ } hagent_next_expire hagent_prev_expire hagent_next_pref hagent_prev_pref hagent_galist hagent—ifa—pair{ } 配列 hagent_gaddr{ } hagent_next_expire hagent_prev_expire hagent_next_gaddr hagent_prev_gaddr hagent_gaddr{ } hagent_next_expire hagent_prev_expire hagent_next_gaddr hagent_prev_gaddr hagent_gaddr{ } リスト hagent_ifa_pair{ } anycast glObal hagent_ifa_pair{ } glObal an ycast halist_expire_head hagent_entry{ } hagent_next_expire hagent_prev_expire が halist. c で定義されています。 hagent—ifa—pair{ } glObal anycast gaddr_expire_head hagent_gaddr{ } hagent_next_expire hagent_prev_expire 132 133 134 135 136 137 ha1 ホームエージェント情報の追加 hagent-entry 構造体をリストに追加するには hal-up- date() 関数を使います。 struct hagent—entry * 131 74 -update(ifindex, ha-addr, ha—lifetime, u—int 16 ー t ha—pref ; u—int16_t ha_lifetime ; struct in6_addr *ha_addr ; int ifindex; ha-pref) hal-update() は 4 つの引数をもちます。 ifindex は UNIX MAGAZINE 2004.8

3. UNIX MAGAZINE 2004年8月号

連載 / v6 の実装ー 0 図 12 優先偵 / 有交加蔀頁のリストからのエントリの肖畭 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 図 13 321 322 図 14 324 326 327 329 330 galp->hagent—flags . router 332 333 334 335 336 337 338 339 340 341 342 343 351 352 353 sizeof (struct in6—addr) ) ; bcopy(&(pi->nd-opt-pi-prefix) , &(galp->hagent—gaddr) , bzero(galp, sizeof (struct hagent-gaddr)) ; goto err; = NULL) { if (galp galp = malloc(sizeof (struct hagent—gaddr) ) ; if ( ! galp) { メモリび )i 寉保とメンバー変数のネ騏用ヒ pi—>nd—opt—pi—prefix—len) ; galp = hal-gaddr—find (halp , &pi—>nd-opt-pi—prefix , 〕ロするアドレスがリストにあるか C)E 忍 if if if if (halp->hagent-prev—pref) { halp—>hagent-prev-pref—>hagent-next-pref halp->hagent-next-pref ; (halp—>hagent—next—pref) { halp—>hagent—next—pref—>hagent—prev—pref halp->hagent-prev-pref ; (halp—>hagent—prev-expire) { halp¯>hagent—prev—expire—>hagent—next—expire halp—>hagent—next—expire ; (halp¯>hagent—next—expire) { halp¯>hagent—next—expire—>hagent—prev—expire halp—>hagent—prev—expire ; galp¯>hagent—pref ixlen = pi¯>nd—opt—pi—prefix—len; galp—>hagent—flags . onlink = (pi->nd-opt—pi-flags-reserved & ND_OPT_PI_FLAG_ONLINK) ? 1 (pi—>nd—opt—pi—flags—reserved & galp¯>hagent—flags . autonomous ND_OPT_PI_FLAG_AUTO) ? 1 (pi—>nd—opt—pi—flags—reserved & ND_OPT_PI_FLAG_ROUTER) ? 1 galp¯>hagent—vltime = ntOh1 (pi¯>nd—opt—pi—valid—time) ; galp¯>hagent—pltime = ntOhl (pi¯>nd—opt—pi—preferred—time) ; if (hal-gaddr—init—prefix—ltimes(galp) ) goto err ; のリストを保持している hagent-ifinfo 構造体へのポイン 夕、 ha-addr は検索したいホームエージェントのアドレス へのポインタです。 305 306 307 302 303 304 for (halp = haif—>halist—pref . hagent-next-pref ; halp ; halp = halp->hagent-next-pref ) if (IN6_ARE_ADDR_EQUAL ( & (halp—> hagent—addr) , ha—addr) ) return halp ; break; レスをもつ工ントリを探します。みつかればそのエントリ が、みつからなければ NULL が返されます。 グローバルアドレスの追加 ホームエージェント情報を保持する hagent-entry 構 造体には、ホームエージェントのグローバルアドレスを 示すリストへのポインタが含まれます。あるホームエージ ェント情報にグローノヾルアドレスを追加する場合は hal- gaddr-add() 関数を使います。 313 struct hagent—gaddr * 314 hal-gaddr-add(halp, lastp, pi) 308 } インターフェイスごとに管理されているホー ント・リストをたどりながら、同じリンクローカル・アド ンエ 78 315 316 struct hagent—entry *halp ; struct hagent—gaddr *lastp ; UNIX MAGAZINE 2004.8

4. UNIX MAGAZINE 2004年8月号

連載 / 旧 v6 の実装ー 0 図 6 hagent-gaddr 構〕本 121 135 134 133 132 131 130 129 128 127 126 125 124 123 122 struct hagent-gaddr { 1 ong 10 Ⅱ g u_int32_t u_int32_t } hagent—flags ; U_Char u_ Char u_ Char struct hagent—flags u_int8_t struct in6_addr struct hagent—gaddr struct hagent—gaddr *hagent-next-gaddr , *hagent-prev-gaddr ; *hagent—next—expire, *hagent—prev—expire ; hagent—preferred; hagent—expire; hagent—pltime ; hagent—vltime ; router : 1 ; autonomous onlink : 1 ; hagent—prefixlen ; hagent—gaddr ; スごと (hagentäfinfo 構造体ごと ) に管理されます。 ha- UNIX MAGAZINE 2004.8 gentäfa-pair 構造体の定義を示します。 ーキャスト・アドレスの組を保持します。以下に ha- バルアドレスと、それに対応するホームエージェント・エ hagent-ifa-pair 構造体はホームエージェントのグロー 時間が切れる時刻を表します。 と hagent-pltime から計算された、有勠時間と推奨有効 hagent-expire と hagent-preferred は hagent-vltime それぞれ、プレフィックスの有効時間と推奨有効時間です。 情報のコピーです。 hagent-vltime と hagent-pltime は hagent-flags はプレフィックス情報に付随していたフラグ ルアドレス、 hagent-prefixlen はプレフィックス長です。 gaddr はプレフィックス情報から取り出されたグローバ ード全体で 1 つのリストとして管理されます。 hagent- 効時間川頁のリストを構成します。有効時間順のリストはノ pire と hagent-prev-expire はグローバルアドレスの有 entry 構造体ごと ) に管理されます。 hagent-next-ex- します。このリストはホームエージェントごと (hagent- ントに割り当てられたグローバルアドレスのリストを構成 gent-gaddr 構造体へのポインタで、あるホームエージェ す。 hagent-next-gaddr と hagent-prev-gaddr は ha- バルアドレスを保持する構造体です。図 6 に定義を示しま hagent-gaddr 構造体はホームエージェントのグロー るグローバルアドレスのリストがイ尉寺されます。 体の変数で、このホームエージェントに割り当てられてい が切れる時刻です。 hagent-galist は hagent-gaddr 構造 優先度と有効時間を表します。 hagent-expire は肩効時間 レスです。 hagent-pref と hagent 」 ifetime はそれぞれ、 gent ー addr はホームエージェントのリンクローカル・アド 164 165 167 166 struct hagent—ifa—pair { struct ifaddrs struct ifaddrs *global; *anycast ; global はホームエージェントのグローバルアドレスを、 す。この情報を間違いなく操作するため、いくつかの関数 ホームエージェントの情報を表す構造はたいへん複雑で ホームエーシェント・リストのキ乍 りを示す矢印は省略しています。 に実装できます。なお、図では肩効時間順リストのつなが 別にもっことで、有効期限切れ工ントリの削除処理が簡単 トごとに管理されるリストに加え、有効時間順のリストを ます。インターフェイスごと、あるいはホームエージェン gent-entry 構造体と hagent-gaddr 構造体をイ尉寺してい のリストは、ホームエージェント上に存在するすべての ha ー prev-expire 変数を用いてリストが構成されます。これら gent-gaddr 構造体の hagent-next-expire と hagent- gaddr 構造体が有効時間順に並べられたリストです。 ha- リストが構成されます。 gaddr-expire-head は hagent- gent-next-expire と hagent-prev-expire 変数を使って に並べられたリストです。 hagent-entry 構造体の ha- list-expire-head は hagent-entry 構造体が有効時間順 expire-head の 2 つのリストが定義されています。 ha- 効時間を管理するために、 halist-expire-head と gaddr- ホームエージェントの情報や、グローバルアドレスの有 これらの構造体は、図 7 のような関係で管理されます。 工ージェント・ェニーキャスト・アドレスを表します。 anycast は、 global で示されるアドレスに対応するホーム 73

5. UNIX MAGAZINE 2004年8月号

連載 / 旧 v6 の実装ー 0 図 4 hagent-ifinfo 構 ; 本 151 struct hagent—ifinfo { 152 153 154 155 156 157 158 159 } ; struct hagent—entry int char struct ifaddrs struct hagent—ifa_pair int int 図 5 hagent-entry 構〕当本 138 139 140 141 142 143 144 145 146 740 741 struct hagent—entry { struct hagent—gaddr 1 ong u_int 16 ー t u_int 16 ー t struct in6_addr struct hagent—entry halist-pref ; ifindex ; ifname CIF-NAMESIZE] ; *linklocal; *haif-gavec; gavec_used; gavec_S1ze; *hagent—next—expire , *hagent_prev_expire , *hagent—next—pref , *hagent—prev—pref ; hagent ー addr ; hagent-pref ; hagent—lifetime ; hagent—expire ; hagent—galist ; 737 ~ 741 行目で、プレフィックス情報に含まれている ホームエージェントのグローバルアドレスを newgaddrs (lastp) 変数に追加します。プレフィックス情報にホーム 工ージェントのグローバルアドレスが含まれているかどう かは、 MobiIe IPv6 で拡張された ND-OPT-PI-FLAG- ROUTER フラグによって判断できます。 743 744 750 if (newgaddrs . hagent—next—gaddr NULL) goto done ; hal—gaddr—last (halp , newgaddrs . hagent—next—gaddr) ; 751 done : 752 } すべてのプレフィックス情報の処理が終了したら、ル ープの過程で作成されたホームエージェントのグローバル アドレスのリスト (newgaddrs 、 lastp) を、 hal_gaddr- last() 関数で hagent-entry 構造体に追加します ( 743 ~ 744 行目 ) 。 ホームエーシェント↑侵の管理構造 ホームエージェントの情報は、下記の 4 つの構造体で管 理されます。これらは halist. h で定義されています。 72 ・ hagent-gaddr 構造体 ・ hagent-entry 構造イ本 ・ hagent-ifinfo 構造体 ・ hagent-ifa-pair 構造体 hagent-ifinfo 構造体は、ホームエージェントがもつネ ットワーク・インターフェイスを表す構造体です。ホーム 工ージェントのリストはネットワーク・インターフェイス ごとに管理されるため、ホームエージェントは自分カ甘是供 しているホーム・ネットワークの数だけ hagent-ifinfo 構 造体をイ寺しています。図 4 に hagent-ifinfo 構造体の定 義を示します。 halist-pref は hagent-entry 構造体の変 数で、各ホームエージェントの情報を保持するリストを格 納するために利用されます。 ifindex は、各インターフェ イスのインデックス、 ifname はインターフェイス名です。 linklocal はインターフェイスに割り当てられているリン クローカル・アドレス、 haif_gavec は動的ホームエージェ ント探索に利用されるホームエージェント・ェニーキャス ト・アドレスの配列です。 gavec_used は haif_gavec に登 録されているェニーキャスト・アドレスの数、 gavec-size は haif-gavec 配列の大きさです。 hagent-entry 構造体は、ある 1 つのホームエージェン トに関連する情報を表す構造体です。図 5 に hagent-en- try 構造体の定義を示します。 hagent-next-expire と hagent-prev-expire は hagent-entry 構造イ本一のポイ ンタで、有効時間順に並べたリストを構成するために使 われます。 hagent-next-pref と hagent-prev-pref は 優先度順に並べたリストを構成するために使われます。な お、有効時間順のリストはノード全体で 1 つのリストと して管理されますが、優先度順のリストはインターフェイ UNIX MAGAZINE 2004.8

6. UNIX MAGAZINE 2004年8月号

連載 / 旧 v6 の実装ー 0 図 2 ホームエージェントの有交加罰と優先度の取得 654 ha—lifetime = ntohs(ra—>nd_ra—router—lifetime) ; if (ndopts . nd_opts—hai) { 655 ha—lifetime = ntohs (ndopts . nd—opts—hai—>nd—opt—hai—lifetime) ; 656 ha—pref = nt0hs (ndopts . nd—opts—hai—>nd—opt—hai—preference) ; 658 659 } 図 3 プレフィックス情報の正当性 Di 忍 690 fo て (pt (struct nd—opt—hdr * ) ndopts . nd—opts—pi ; 691 692 693 pt く = (struct nd—opt—hdr * ) ndopts . nd—opts—pi—end ; (struct nd—opt—hdr * ) ( (caddr—t)pt + pt ()t → nd-opt-len くく 3 ) ) ) { してきたルータがホームエージェントではない場合 ( 642 行目 ) 、ホームエージェント・リストから該当するアドレス を削除します ( 648 行目 ) 。 hal-delete() は、 hagent-ifinfo 構造体に内されてい るホームエージェント・リストから、指定されたアドレス をもつ工ントリを削除します。 654 ~ 659 行目 ( 図 2 ) ではホームエージェントの有効 時間と優先度を取得します。 MobiIe IPv6 では、ホーム 工ージェントの有効時間と優先度をルータ通知の一部とし て送信できるように、近隣探索のオプションにホームエー ジェント情報 (Home Agent lnformation) オプショ ンが追加されています。ルータ通知にホームエージェン ト情報オプションが含まれていると、 nd-options 共用体 の nd-opts-hai にオプションへのポインタが設疋される ので、 656 行目と 658 行目で、オプションに指定された 有効時間と優先度を取り出します。ホームエージェント情 報オプションが指定されていない場合、ホームエージェン トの有効時間は、ルータとしての有効時間を示す nd-ra- router 」 ifetime と同じになり ( 654 行目 ) 、優先度は標準 値の 0 が指定されたとみなされます。 662 664 668 669 halp = ha1—update(pinf0->ipi6-ifindex, &from—>sin6_addr , ha_lifetime , ha—pref ) ; if (!halp) { goto done ; 有効時間、第 4 引数は優先度です。有効時間が 0 の場合 は、該当するエントリがリストから削除されます。リスト の更新に失敗したり、エントリカ哨リ除された場合は NULL カ隧され、処理を中断します ( 664 ~ 669 行目 ) 。 if (ndopts . nd-opts-pi) { 675 675 行目以降では、ホームエージェント・リストに十絲タさ れたグローバルアドレスの情報を更新します。ホームエー ジェントのグローバルアドレスは、近隣探索のプレフィッ クス情報オプションとして配布されています。近隣探索の 仕様 ( RFC2461 ) で定義されたプレフィックス情報オプシ ョンには、リンクのプレフィックスの情報しか含まれてい ません。 MobiIe IPv6 では、プレフィックス情報オプショ ンを拡張し、プレフィックス情報と同時にホームエージェ ントのグローバルアドレスを含められるようにしています。 686 newgaddrs ・ hagent—next—gaddr = NULL ; 687 lastp = &newgaddrs ; newgaddrs は、ホームエージェントのグローバルアド レスを格納する hagent-gaddr 構造体の変数です。 ha- gent-gaddr 構造体はリストを構成できるように定義され ており、以下に続くプレフィックス情報の処理の過程で、受 信したグローバルアドレスが newgaddrs に追加されてい きます。 図 3 の 690 行目の for ループでは、ルータ通知に含まれ ているプレフィックス情報の正当性を確認します。これは カーネル内での正当性の確認と同じ処理なので、解説を省 略します。 662 ~ 669 行目でホームエージェント・リストを更新し ます。 hal-update() は 4 つの引数をもちます。第 1 引 数は更新するホームエージェント・リストに対応するイン ターフェイス、第 2 引数はホームエージェントのリンク ローカル・アドレス、第 3 引数はホームエージェントの UNIX MAGAZINE 2004.8 737 739 if ( (pi—>nd—opt-pi—flags-reserved & ND_OPT_PI_FLAG_ROUTER) ! = 0 ) { lastp = hal—gaddr-add(halp , lastp, (i) ; 71

7. UNIX MAGAZINE 2004年8月号

図 11 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 256 257 258 259 261 262 263 264 288 289 290 連載 / 旧 v6 の実装 for (prevp = curp = halist—expire—head. hagent—next—expire; 有咬加頁に並べられたリストへの挿入 curp—>hagent—prev—expire—>hagent—next—expire = halp ; if (curp->hagent-prev-expire) { curp ; halp—>hagent—next—expire halp—>hagent—prev-expire curp—>hagent—prev—expire ; if (curp—>hagent-expire > halp—>hagent—expire) { curp ; curp = curp¯>hagent—next—expire) { if curp—>hagent—prev—expire break; prevp = curp ; ( ! curp) { if (prevp) { prevp¯>hagent—next—expire halp->hagent-prev—expire else { halp ; halp ; prevp ; halist—expire—head. hagent—next—expire = halp ; halp—>hagent—prev—expire = &halist—expire—head ; halp = NULL ; goto done ; 索します。指定されたアドレスをもつ工ントリがリストに ない場合は処理を中断します ( 686 ~ 689 行目 ) 。 図 12 の 692 ~ 699 行目で優先度順のリストから、 700 ~ 707 行目で有効時間順のリストからエントリを取り除き リストの更新が正常に終了したら、 284 行目で対応する ホームエージェント情報へのポインタを返します。処理が 中断される場合は、 288 ~ 289 行目で NULL を返します。 ホームエーシェント情報の削除 ホームエージェント情報の削除には hal-delete() 関数 を使います。 674 int 675 hal_delete(haif , ha—addr) ます。 710 712 714 716 717 hal-gaddr-clean (halp) ; free(halp) ; done : return ret ; 676 677 struct hagent—ifinfo *haif ; struct in6_addr *ha—addr ; 678 { hal-delete() は 2 つの引数をとります。 haif は削除対 象のリストを保持している hagent-ifinfo 構造体へのポイ ンタ、 ha-addr は削除するホームエージェントのアドレス へのポインタです。 684 686 687 688 689 halp = hal-find(haif , ha—addr) ; if ( !halp) { ret goto done ; 最後に 710 行目でエントリに対応するグローバルアドレ スを保持するメモリを解放し、 712 行目でエントリ自身の メモリを解放します。 ホームエーシェント情報の検索 あるリンクローカル・アドレスをもつホームエージェン トをリストから検索するには hal-find() 関数を使います。 295 struct hagent_entry * 296 hal-find (haif , ha-addr) 297 298 struct hagent—ifinfo *haif ; struct in6_addr *ha—addr ; 684 ~ 689 行目で削除対象の hagent-entry 構造体を検 UNIX MAGAZINE 2004.8 299 { halffmd() は 2 つの引数をもちます。 haif は検索対象 77

8. UNIX MAGAZINE 2004年8月号

図 17 398 399 400 401 402 403 404 405 406 408 409 410 411 412 413 415 416 417 418 420 421 422 423 連載 / v6 の実装ー 0 有交加寺間偵に並んだリストへのエントリの挿入 for (prevp = curp = gaddr—expire—head. hagent—next—expire ; curp—>hagent—prev—expire—>hagent—next—expire = galp ; if (curp->hagent—prev-expire) { curp ; galp—>hagent—next—expire curp¯>hagent—prev—expire ; galp—>hagent-prev—expire if (curp—>hagent-expire > galp->hagent-expire) { curp ; curp = curp¯>hagent—next—expire) { curp—>hagent—prev—expire break ; prevp = curp ; if ( ! curp) { if (prevp) { prevp—>hagent—next—expire galp¯>hagent—prev—expire else { galp ; galp ; prevp ; gaddr—expire—head. hagent—next—expire = galp ; galp¯>hagent—prev—expire = &gaddr—expire—head ; 図 16 の 377 ~ 382 行目でフラグ情報を更新します。受 信したプレフィックス情報がオンリンク・プレフィックス だった場合、 384 ~ 389 行目で肩効時間も更新します。 392 lastp—>hagent—next—gaddr = galp ; 393 galp—>hagent—prev—gaddr = lastp ; 395 lastp = galp; 392 ~ 393 行目で、 lastp に確保されている一時メモリに グローバルアドレスの情報をリスト形式で追加します。 のリストが、最終的なグローバルアドレス群として登録さ れます。 398 ~ 423 行目 ( 図 17 ) で、もう 1 つの ( 有効時間順 の ) リストにエントリを挿入します。手川頁は、 hagent-en- try 構造体を有効時間順に並べたリストに挿入する場合 と同様です。グローバルアドレス全体のリストは gaddr- list-head 変数を先頭として保持されているので、 gaddr- list-head に内されている hagent-gaddr 構造体のポイ ンタ (hagent-next-expire) をたどりながら適切な位置に 工ントリを挿入します。 425 err: return lastp; 426 427 } 最後に、一時リストをオ内したアドレスを呼出し側の関 数に返して終了します。このアドレスは、次に解説する hal 80 -gaddr 」 ast() 関数に渡され、既存のグローノヾルアドレス・ リストと置き換えられます。 499 void 500 hal-gaddr-last (halp, newgal) リストへのポインタです。 add() 関数で作成されたグローバルアドレスを収めた一時 工ージェント情報へのポインタ、 newgal は hal-gaddr- はグローバルアドレス・リストの置換え対象となるホーム hal-gaddr-last() 関数は 2 つの引数をもちます。 halp 503 { 502 struct hagent—gaddr *newgal ; 501 struct hagent—entry *halp ; 506 507 508 511 512 for (galp = &halp—>hagent—galist ; galp¯>hagent—next—gaddr ! = NULL ; galp = galp¯>hagent—next—gaddr) / * nothing to do * / galp->hagent—next—gaddr = newgal ; newgal—>hagent—prev—gaddr = galp ; 506 ~ 508 行目で現在保持されているグローバルアド レス・リストの最後尾工ントリを検索します。その後、 511 行目で一時リストをリストの最後に追加します。 hal- gaddr-add() で一時リストを作成する過程で、一時リスト に格納されているアドレスは、 hagent-entry 構造体に登 録されているリストから取り除かれているので、グローバ 513 } UNIX MAGAZ 工 NE 2004.8

9. UNIX MAGAZINE 2004年8月号

図 15 354 366 367 368 369 370 371 372 373 374 図 16 377 378 379 380 381 382 356 357 358 359 360 361 362 363 364 384 385 386 387 388 389 390 317 318 連載 / 旧 v6 の実装ー 0 泉済みアドレスのリストからの削除 else { if (galp—>hagent-next-gaddr) { galp—>hagent—next—gaddr—>hagent—prev—gaddr galp->hagent-prev-gaddr ; if (galp->hagent—prev-gaddr) { galp—>hagent—prev—gaddr—>hagent—next—gaddr galp¯>hagent—next—gaddr ; galp->hagent—next-gaddr = galp->hagent—prev-gaddr if (galp—>hagent-next-expire) { galp¯>hagent—next—expire—>hagent—prev—expire galp->hagent-prev-expire ; if (galp->hagent—prev—expire) { galp¯>hagent—prev—expire—>hagent—next—expire galp—>hagent—next—expire ; NULL ; galp—>hagent—next—expire = galp¯>hagent—prev—expire = NULL ; フラグ情報と有咬加の更新 if (pi—>nd-opt—pi—flags-reserved & ND—OPT—PI-FLAG—ONLINK) galp—>hagent—flags ・ onlink = 1 ; (pi->nd-opt-pi—flags-reserved & galp—>hagent-flags . autonomous ND_OPT_PI_FLAG_AUTO) ? 1 galp—>hagent-flags. router = (pi->nd-opt-pi-flags-reserved & ND_OPT_PI_FLAG_ROUTER) ? 1 if (pi—>nd-opt-pi-flags—reserved & ND-OPT-PI—FLAG-ONLINK) { if (hal-gaddr-init-prefix—ltimes(galp) ) galp¯>hagent—pltime = nt0hl (pi¯>nd—opt—pi—preferred—time) ; galp->hagent—vltime = nt0h1 (pi—>nd—opt-pi—valid-time) ; goto err; struct nd—opt—prefix—info *pi ; hal-gaddr-add() 関数は 3 つの引数をもちます。 halp はアドレスを追加する hagent-entry 構造体へのポイン 夕、 lastp はグローバルアドレスのリストを一時的に保持 するメモリ領域へのポインタ、 pi はルータ通知で受信した プレフィックス情報へのポインタです。 ます、 321 ~ 322 行目 ( 図 13 ) で、追加しようとしている アドレスがすでにリストに登録済みかどうかを確認します。 hal-gaddr-find() は第 1 引数で指定した hagent-entry 構造体から第 2 引数で指定したアドレスと第 3 引数で指定 したプレフィックス長をもつグローバルアドレスのエント リを検索します。 指定されたアドレスが未登録だった場合、図 14 の 324 ~ 330 行目で新たにメモリを確保し、 332 ~ 352 行目で 各メンバー変数を初期化します。 hagent-gaddr にプレ UNIX MAGAZINE 2004.8 フィックス情報に収められていたグローバルアドレスを、 hagent-prefixlen にプレフィックス長を設疋します。 ha- gent-flags はプレフィックス情報のフラグ情報のコピー です。 hal-gaddr-init-prefix 」 times() は、プレフィッ クスの有効時間 (hagent-vltime) と推奨有効時間 (ha- gent-pltime) から有勠時間が切れる時刻を引算して、 ha- gent-expire と hagent-preferred を設疋します。 指定されたアドレスがすでにリストに登録されていた ら、ますリストからエントリを削除します。 hagent-entry 構造体と同様に、 hagent-gaddr 構造体も 2 つのリストで 管理されています。 1 つは、それぞれのホームエージェン ト情報 (hagent-entry 構造体 ) ごとに保持されたリスト、 もう 1 つはすべてのアドレス情報カ陏勠時間順に並んだリ ストです。図 15 の 356 ~ 364 行目で hagent-entry 構造 体ごとに管理されているリストから、 366 ~ 374 行目で有 効時間順のリストから該当するエントリを取り除きます。 79

10. UNIX MAGAZINE 2004年8月号

連載 / v6 の実装ー 0 図 8 リストからのエントリの肖郎余 if (halp) { 160 176 177 178 179 180 181 182 183 184 165 166 167 168 169 170 171 172 173 if (halp->hagent-next-pref) { halp—>hagent—next—pref—>hagent—prev—pref halp—>hagent—prev—pref ; if (halp->hagent-prev—pref) { halp—>hagent—prev—pref—>hagent—next—pref halp—>hagent—next—pref ; halp—>hagent—next—pref = halp—>hagent—prev—pref if (halp->hagent—next—expire) { halp—>hagent—next—expire—>hagent—prev—expire halp—>hagent—prev—expire ; if (halp->hagent—prev—expire) { halp—>hagent—prev—expire—>hagent—next—expire halp—>hagent—next—expire ; NULL ; halp—>hagent—next—expire = halp—>hagent—prev—expire NULL ; 185 } 図 9 新しいリストエントリの作成 187 if (ha_lifetime > 0 ) { 189 192 193 194 195 197 198 200 201 202 if ( ! halp) { halp = malloc(sizeof (struct hagent-entry) ) ; if (halp) { bzero(halp, sizeof (struct hagent—entry) ) ; bcopy(ha—addr, &halp—>hagent—addr, sizeof (struct in6—addr) ) ; goto err; else { hagent-entry 構造体が追加されるインターフェイスのイ ンデックスです。 ha-addr 、 ha 」 ifetime 、 ha-pref はそれ ぞれ、追加されるホームエージェントのリンクローカル・ア ドレス、効時間、優先度を示します。 149 153 154 151 haif = haif—find(ifindex) ; if (!haif) { goto err; 149 行目でインターフェイスのインデックスに対応する hagentäfinfo 構造体を検索します。 hagentäfinfo 構造 体はインターフェイスごとにかならす存在しなければなり ません。検索に失敗したら処理を中断します。 157 halp = hal-find(haif , ha-addr) ; 157 行目で、 hal-update() の引数に指定されたリンク ローカル・アドレスをもつ工ントリが、すでにリストにあ UNIX MAGAZINE 2004.8 るかどうかを調べます。 hal-find() 関数は第 1 引数で指定 された hagent-ifinfo 構造体のホームエージェント・リス トから、第 2 引数で指定されたアドレスをもつ工ントリを 検索する関数です。 該当するエントリがすでにリストにあれば、図 8 の 165 ~ 185 行目でリストからエントリを削除します。前述した とおり、 hagent-entry 構造体は 2 種類のリストで管理さ れています。 1 つは優先度順に並べられたインターフェイ スごとのホームエージェント・リスト、もう 1 つは有効時 間順に並べられた全体のホームエージェントを保持するリ ストです。この 2 つのリストからエントリを削除します。 187 ~ 202 行目 ( 図 9 ) で新しいリストエントリを作成 します。ホームエージェントの有効時間 ()a 」 ifetime) が 0 より大きい値に設定されており、該当するエントリがま だリストにない (halp が NULL の ) 場合、新しいエント リを作成します。 75