Share via


使用 RtmAddRouteToDest 新增和更新路由

RtmAddRouteToDest函式可用來新增路由,並更新目的地的現有路由。 下列程式說明這兩種情況。 下列範例程式碼示範如何實作第一個程式。

若要新增路由,用戶端應該採取下列步驟

  1. 如果用戶端已經快取下一個躍點控制碼,請移至步驟 4。

  2. 建立 RTM_NEXTHOP_INFO 結構,並填入適當的資訊。

  3. 藉由呼叫 RtmAddNextHop,將下一個躍點新增至路由表。 路由表管理員會傳回下一個躍點的控制碼。 如果下一個躍點已經存在,路由表就不會新增下一個躍點;相反地,它會傳回下一個躍點的控制碼。

  4. 建立 RTM_ROUTE_INFO 結構,並填入適當的資訊,包括路由表管理員傳回的下一個躍點控制碼。

  5. 藉由呼叫 RtmAddRouteToDest將路由新增至路由表。 路由表管理員會將新的路由與已在路由表中的路由進行比較。 如果下列所有條件都成立,則兩個路由相等:

    • 路由會新增至相同的目的地。
    • 路由會由RTM_ROUTE_INFO結構的擁有者成員所指定的相同用戶端新增。
    • 路由會由RTM_ROUTE_INFO結構之 Neighbor 成員所指定的相同鄰公告。

    如果路由存在,路由表管理員會將控制碼傳回至現有的路由。 否則,路由表管理員會新增路由,並將控制碼傳回至新的路由。

    用戶端可以將 Change_Flags 參數設定為 RTM_ROUTE_CHANGE_NEW,以指示路由表管理員在目的地上新增新的路由,即使有另一個具有相同擁有者和鄰近欄位的路由也一樣。

    用戶端可以將 Change_Flags 參數設定為 RTM_ROUTE_CHANGE_FIRST,告知路由表管理員更新用戶端擁有之目的地上的第一個路由。 如果這類路由存在,也可以執行此更新,即使鄰近欄位不相符也一樣。 用戶端會使用此旗標來維護每個目的地的單一路由。

若要更新路由,用戶端應該採取下列步驟

  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);
}