Adicionar e atualizar rotas usando RtmAddRouteToDest
A função RtmAddRouteToDest é usada para adicionar novas rotas e atualizar rotas existentes para um destino. Os procedimentos a seguir explicam os dois casos. O código de exemplo a seguir mostra como implementar o primeiro procedimento.
Para adicionar uma rota, o cliente deve seguir as etapas a seguir
Se o cliente já tiver armazenado em cache o identificador do próximo salto, vá para a etapa 4.
Crie uma estrutura RTM_NEXTHOP_INFO e preencha-a com as informações apropriadas.
Adicione o próximo salto à tabela de roteamento chamando RtmAddNextHop. O gerenciador de tabelas de roteamento retorna um identificador para o próximo salto. Se o próximo salto já existir, a tabela de roteamento não adicionará o próximo salto; em vez disso, retorna o identificador para o próximo salto.
Crie uma estrutura RTM_ROUTE_INFO e preencha-a com as informações apropriadas, incluindo o identificador do próximo salto retornado pelo gerenciador de tabelas de roteamento.
Adicione a rota à tabela de roteamento chamando RtmAddRouteToDest. O gerenciador de tabelas de roteamento compara a nova rota com as rotas que já estão na tabela de roteamento. Duas rotas serão iguais se todas as seguintes condições forem verdadeiras:
- A rota está sendo adicionada ao mesmo destino.
- A rota está sendo adicionada pelo mesmo cliente especificado pelo membro Proprietário da estrutura RTM_ROUTE_INFO .
- A rota é anunciada pelo mesmo vizinho especificado pelo membro Vizinho da estrutura RTM_ROUTE_INFO .
Se a rota existir, o gerenciador de tabelas de roteamento retornará o identificador para a rota existente. Caso contrário, o gerenciador de tabelas de roteamento adiciona a rota e retorna o identificador para a nova rota.
O cliente pode definir o parâmetro Change_Flags como RTM_ROUTE_CHANGE_NEW para instruir o gerenciador de tabelas de roteamento a adicionar uma nova rota no destino, mesmo que exista outra rota com os mesmos campos proprietário e vizinho.
O cliente pode definir o parâmetro Change_Flags como RTM_ROUTE_CHANGE_FIRST para informar o gerenciador de tabelas de roteamento a atualizar a primeira rota no destino pertencente ao cliente. Essa atualização poderá ser executada se essa rota existir, mesmo que o campo vizinho não corresponda. Esse sinalizador é usado por clientes que mantêm uma única rota por destino.
Para atualizar uma rota, o cliente deve seguir as etapas a seguir
- Chame RtmGetRouteInfo com o identificador para a rota. O identificador é um armazenado em cache anteriormente pelo cliente ou retornado pelo gerenciador de tabelas de roteamento de uma chamada que retorna um identificador de rota como RtmGetRouteInfo.
- Faça as alterações na estrutura RTM_ROUTE_INFO retornada pelo gerenciador de tabelas de roteamento.
- Chame RtmAddRouteToDest com o identificador para a rota e a estrutura de RTM_ROUTE_INFO alterada.
O código de exemplo a seguir mostra como adicionar uma rota a um destino usando o gerenciador de tabelas de roteamento como intermediário.
// 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);
}