Поделиться через


Добавление и обновление маршрутов с помощью RtmAddRouteToDest

Функция RtmAddRouteToDest используется для добавления новых маршрутов и обновления существующих маршрутов для назначения. В следующих процедурах описаны оба случая. В следующем примере кода показано, как реализовать первую процедуру.

Чтобы добавить маршрут, клиент должен выполнить следующие действия.

  1. Если клиент уже кэшировал дескриптор следующего прыжка, перейдите к шагу 4.

  2. Создайте структуру RTM_NEXTHOP_INFO и заполните ее соответствующими сведениями.

  3. Добавьте следующий прыжок в таблицу маршрутизации, вызвав RtmAddNextHop. Диспетчер таблиц маршрутизации возвращает дескриптор для следующего прыжка. Если следующий прыжок уже существует, таблица маршрутизации не добавляет следующий прыжок. Вместо этого он возвращает дескриптор для следующего прыжка.

  4. Создайте структуру RTM_ROUTE_INFO и заполните ее соответствующими сведениями, включая дескриптор следующего прыжка, возвращенный диспетчером таблиц маршрутизации.

  5. Добавьте маршрут в таблицу маршрутизации, вызвав RtmAddRouteToDest. Диспетчер таблиц маршрутизации сравнивает новый маршрут с маршрутами, которые уже находятся в таблице маршрутизации. Два маршрута равны, если выполняются все следующие условия:

    • Маршрут добавляется в то же место назначения.
    • Маршрут добавляется тем же клиентом, который указан членом владельцаструктуры RTM_ROUTE_INFO .
    • Маршрут объявляется тем же соседом, который указан в элементе Сосед структуры RTM_ROUTE_INFO .

    Если маршрут существует, диспетчер таблиц маршрутизации возвращает дескриптор существующего маршрута. В противном случае диспетчер таблиц маршрутизации добавляет маршрут и возвращает дескриптор новому маршруту.

    Клиент может задать параметру Change_Flags значение RTM_ROUTE_CHANGE_NEW, чтобы диспетчер таблиц маршрутизации добавил новый маршрут в место назначения, даже если существует другой маршрут с теми же полями владельца и соседа.

    Клиент может задать для параметра Change_Flags значение RTM_ROUTE_CHANGE_FIRST, чтобы сообщить диспетчеру таблиц маршрутизации обновить первый маршрут в месте назначения, принадлежащей клиенту. Это обновление может быть выполнено, если такой маршрут существует, даже если соседнее поле не совпадает. Этот флаг используется клиентами, которые поддерживают один маршрут для каждого назначения.

Чтобы обновить маршрут, клиент должен выполнить следующие действия.

  1. Вызовите RtmGetRouteInfo с дескриптором маршрута. Дескриптор — это дескриптор, ранее кэшированный клиентом, или возвращенный диспетчером таблиц маршрутизации из вызова, который возвращает дескриптор маршрута, например RtmGetRouteInfo.
  2. Внесите изменения в структуру RTM_ROUTE_INFO , возвращаемую диспетчером таблиц маршрутизации.
  3. Вызовите RtmAddRouteToDest с дескриптором маршрута и измененной RTM_ROUTE_INFO структуры.

В следующем примере кода показано, как добавить маршрут к месту назначения с помощью диспетчера таблиц маршрутизации в качестве посредника.

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