次の方法で共有


RtmAddRouteToDest を使用してルートを追加および更新する

関数 RtmAddRouteToDest は、新しいルートを追加し、宛先の既存のルートを更新するために使用されます。 次の手順では、両方のケースについて説明します。 次のサンプル コードは、最初のプロシージャを実装する方法を示しています。

ルートを追加するには、クライアントが次の手順を実行する必要があります

  1. クライアントがネクスト ホップ ハンドルを既にキャッシュしている場合は、手順 4 に進みます。

  2. RTM_NEXTHOP_INFO構造を作成し、適切な情報を入力します。

  3. RtmAddNextHop を呼び出して、ルーティング テーブルに次ホップを追加します。 ルーティング テーブル マネージャーは、次ホップにハンドルを返します。 ネクスト ホップが既に存在する場合、ルーティング テーブルは次ホップを追加しません。代わりに、次ホップにハンドルを返します。

  4. RTM_ROUTE_INFO構造を作成し、ルーティング テーブル マネージャーによって返されるネクスト ホップ ハンドルなど、適切な情報を入力します。

  5. RtmAddRouteToDest を呼び出してルーティング テーブルにルートを追加します。 ルーティング テーブル マネージャーは、新しいルートをルーティング テーブルに既に存在するルートと比較します。 次の条件がすべて満たされている場合、2 つのルートが等しくなります。

    • ルートが同じ宛先に追加されています。
    • ルートは、RTM_ROUTE_INFO構造体の Owner メンバーによって指定されたのと同じクライアントによって追加されます。
    • ルートは、RTM_ROUTE_INFO構造体の Neighbor メンバーによって指定されたのと同じネイバーによってアドバタイズされます。

    ルートが存在する場合、ルーティング テーブル マネージャーは既存のルートにハンドルを返します。 それ以外の場合、ルーティング テーブル マネージャーはルートを追加し、ハンドルを新しいルートに返します。

    クライアントは 、Change_Flags パラメーターを RTM_ROUTE_CHANGE_NEW に設定して、同じ所有者フィールドと近隣フィールドを持つ別のルートが存在する場合でも、宛先に新しいルートを追加するようにルーティング テーブル マネージャーに指示できます。

    クライアントは 、Change_Flags パラメーターを RTM_ROUTE_CHANGE_FIRST に設定して、クライアントが所有する宛先の最初のルートを更新するようにルーティング テーブル マネージャーに指示できます。 この更新は、近隣フィールドが一致しない場合でも、このようなルートが存在する場合に実行できます。 このフラグは、宛先ごとに 1 つのルートを維持するクライアントによって使用されます。

ルートを更新するには、クライアントは次の手順を実行する必要があります

  1. ルートへのハンドルを使用して RtmGetRouteInfo を呼び出します。 ハンドルは、クライアントによって以前にキャッシュされたハンドルか、 RtmGetRouteInfo などのルート ハンドルを返す呼び出しからルーティング テーブル マネージャーによって返されます。
  2. ルーティング テーブル マネージャーによって返される RTM_ROUTE_INFO 構造体に変更を加えます。
  3. ルートへのハンドルと変更されたRTM_ROUTE_INFO構造を使用して RtmAddRouteToDest を呼び出します。

次のサンプル コードは、ルーティング テーブル マネージャーを中間として使用して、宛先にルートを追加する方法を示しています。

// Add a route to a destination given by (addr, masklen)
// using a next hop reachable with an interface

RTM_NEXTHOP_INFO NextHopInfo;

// First, create and add a next hop to the caller's
// next-hop tree (if it does not already exist)

ZeroMemory(&NextHopInfo, sizeof(RTM_NEXTHOP_INFO);

RTM_IPV4_MAKE_NET_ADDRESS(&NextHopInfo.NextHopAddress,
                          nexthop, // Address of the next hop
                          32);

NextHopInfo.InterfaceIndex = interface;

NextHopHandle = NULL;

Status = RtmAddNextHop(RtmRegHandle,
                       &NextHopInfo,
                       &NextHopHandle,
                       &ChangeFlags);

if (Status == NO_ERROR)
{
    // Created a new next hop or found an old one

        // Fill in the route information for the route
    
    ZeroMemory(&RouteInfo, sizeof(RTM_ROUTE_INFO);

    // Fill in the destination network's address and mask values
    RTM_IPV4_MAKE_NET_ADDRESS(&NetAddress, addr, masklen);

    // Assume 'neighbour learnt from' is the first next hop
    RouteInfo.Neighbour = NextHopHandle;

    // Set metric for route; Preference set internally
    RouteInfo.PrefInfo.Metric = metric;

    // Adding a route to both the unicast and multicast views
    RouteInfo.BelongsToViews = RTM_VIEW_MASK_UCAST|RTM_VIEW_MASK_MCAST;

    RouteInfo.NextHopsList.NumNextHops = 1;
    RouteInfo.NextHopsList.NextHops[0] = NextHopHandle;

    // If you want to add a new route, regardless of
    // whether a similar route already exists, use the following 
    //     ChangeFlags = RTM_ROUTE_CHANGE_NEW;

    ChangeFlags = 0;

    Status = RtmAddRouteToDest(RtmRegHandle,
                               &RouteHandle,     // Can be NULL if you do not need handle
                               &NetAddress,
                               &RouteInfo,
                               1000,             // Time out route after 1000 ms
                               RouteListHandle1, // Also add the route to this list
                               0,
                               NULL,
                               &ChangeFlags);

    if (Status == NO_ERROR)
    {
        if (ChangeFlags & RTM_ROUTE_CHANGE_NEW)
        {
        ; // A new route has been created
        }
        else
        {
        ; // An existing route is updated
        }

        if (ChangeFlags & RTM_ROUTE_CHANGE_BEST)
        {
        ; // Best route information has changed
        }

        // Release the route handle if you do not need it
        RtmReleaseRoutes(RtmRegHandle, 1, &RouteHandle);
    }

    // Also release the next hop since it is no longer needed 
    RtmReleaseNextHops(RtmRegHandle, 1, &NextHopHandle);
}