Interface Configuration (IPv6 Unicast Routing Protocols)

On startup, the route6d daemon collects information about each interface on the local node, including the link-level multicasting capability, IPv6 addresses configured on the interface, and the link MTU. The address information is also used to obtain the subnet prefix for the link to which the interface is attached, which will subsequently be advertised in RIPng response messages.

TABLE 1-12

Macro name and argument

Description

IN6_LINKLOCAL_IFINDEX(a)

Extracts the link index assuming it is embedded in address a (a pointer to in6_addr{}) in the form described in Section 1.8.1 and returns it as an integer.

SET_IN6_LINKLOCAL_IFINDEX(a, id)

Embeds an integer link ID id into address a (a pointer to in6_addr{}).

RIPSIZE(n)

Returns the number of bytes needed to construct a RIPng message containing n RTEs. This can be computed using a transformation of Equation (1.1) (page 14).

The collected information is maintained in such data structures as shown in Figure 1-47.

This initialization process is performed by the ifconfig() function described in Section 1.12.1. The ifconfig() function then calls a dedicated subroutine named ifconfig1(), which handles an IPv6 address configured on the interface. The ifconfig() function is also called when a new address is configured or an existing address is deleted while the route6d daemon is running. But for simplicity this section focuses on the initialization procedure.


ifconfig() Function

Function ifconfig() is called at the route6d daemon startup phase to install usable interfaces into the daemon’s internal table. The all-rip-routers multicast group membership is established over each usable interface. 

Listing 1-17

Listing 1-17

1431—1434 A socket is created here and is passed to function ifconfig1() for interfacing with the kernel.

1436-1439 Function getifaddrs() is called to retrieve the list of available system interface addresses. The retrieved list is stored in ifap. Since the memory is dynamically allocated inside getifaddrs(), a subsequent call to freeifaddrs() at the end of this function is necessary to free that memory (see Listing 1-21).

Listing 1-18

Listing 1-18

1441-1447 Each interface address in the list is examined to determine whether an IPv6 address is configured on the interface, and whether the interface is multicast capable. The interface is bypassed if any of the aforementioned conditions is not satisfied.

Function ifc_find() is called to search through the internal interface table of the route6d daemon to determine if the interface in question has already been installed previously. Note that the call to function ifc_find() may be relocated to after the check for interface multicast capability for efficiency reasons.

Listing 1-19

Listing 1-19

1448-1458 If the interface corresponding to this address has not been installed in the interface table maintained by the route6d daemon, a new ifc{} structure is created and is initialized here. The interface index ifc_index is set to —1 and it will be initialized in function ifconfig1() (Section 1.12.2). The new interface is then added into the interface list. The global counter nifc is incremented to account for the additional entry.

1459—1462 The ifc_name and the ifc_flags members are initialized with the values retrieved through getifaddrs(). The allocopy() function (not described in this topic) copies the given interface name to ifc_name after allocating necessary memory.

1465—1466 The pointer reference loopifcp is initialized here if the given interface is a loop-back interface. The loopback interface is used to install a special route into the kernel routing table for the purpose of route aggregation (details of aggregation is outside the scope of this topic).

Listing 1-20

Listing 1-20

1467—1476 If the interface is found in the list, the interface flags are updated because the state of the interface may have changed since it was installed, in which case the change flag IFC_CHANGED is set. Typically a change in the interface state will trigger an unsolicited RIPng message to be sent.

Listing 1-21

Listing 1-21

1477 The function ifconfig1() is called to store the address ifa into ifcp, which is an instance of the ifc{} structure. It also completes the initialization of ifcp when it is newly created in this function.

1478—1489 If the interface is operational and the route6d daemon has not joined the all-rip-routers multicast group on that interface, then function setsockopt() is called to join the multicast group over the interface given in ifc_index. The ifc_joined variable is set to indicate that the group membership has been established.

1491—1492 The temporary socket is closed here. The memory returned from the call to getifaddrs() is freed here as well.

ifconfig1() Function

The function ifconfig1() is called by ifconfig() to install an IPv6 address configured on the given interface. It also completes the initialization of a newly allocated interface structure.

Listing 1-22

Listing 1-22

1495—1500 On input, name points to the name of the interface; sa points to the interface address; ifcp points to the interface; s is the socket that was created in the function ifconfig() and is used for retrieving additional information about the given interface from the kernel.

Listing 1-23

Listing 1-23

1508—1510 The lflag variable controls whether to exchange site-local prefixes, which is set to non-zero if and only if the —l command line option is specified.

If this option is disabled and the given address has a site-local scope, the ifconfig1() function returns immediately. Note ifc_index still has the value —L for the given interface structure.

1511-1517 The ioctl() call is issued here to retrieve the network mask associated with the given address, and then sin6mask2len() converts the mask to the prefix length by counting the leftmost consecutive bits on. The prefix length is saved in plen for a subsequent call to ifa_match().

1518-1523 The ifa_match() function (not described in this topic) matches the given address and the prefix length against all of the addresses that have been assigned to the interface. The function returns here if a match is found.

Listing 1-24

Listing 1-24

1527-1536 A new interface address structure ifac{} is allocated and initialized here. The new structure is linked into the address list. The new address is stored in the ifa_addr field.

Listing 1-25

Listing 1-25

1537-1547 For a point-to-point interface, the remote address is retrieved by issuing the SIOCGIFDSTADDR_IN6 command to the ioctl() function. The remote address of the point-to-point link is stored in the ifa_raddr field.

Listing 1-26

Listing 1-26

1551—1552 An interface must have a link-local address assigned to it in order for it to be usable by the route6d daemon because all of the unsolicited RIPng response packets must be sent using a link-local address. Even though multiple link-local addresses may be configured on an interface, only one is necessary for route6d’s operation and it is stored in ifc_mylladdr.

In fact, perhaps unintentionally, ifc_mylladdr is not used to send messages.

1553 The interface index is retrieved from the link-local address, which is stored in the third and fourth bytes of the in6_addr{} structure.

This is a bad practice. First, a link index is not always equal to an interface index in terms of the IPv6 scoped address architecture [RFC4007]. Second, even if these are equal, an application should not use the KAME-specific embedded index in link-local addresses as noted in Section 1.8.1 wherever possible. In this case, the actual index can be taken from the interface information with the return value of getifaddrs() (see Listing 1-17), which should be used instead.

1554 The global variable ripsin is a placeholder structure that is initialized to store the all-rip-routers multicast address at startup time. The contents of the variable are copied into the ifc_ripsin member of the ifc{} structure being currently configured.

1555—1556 These lines embed the interface index into the IPv6 address field of ifc_ripsin, which is not only a bad practice (see note above) but also meaningless. The address stored in the ifc_ripsin member is only used for the sendmsg() system call and for the IPV6_JOIN_GROUP socket option, which are APIs for a "normal application" and do not require the embedded form,for sendmsg(), sin6_scope_id should simply work. For the IPV6_JOIN_GROUP option, the interface index stored in ifcp can be passed in the socket option argument without embedding the index into the address.

1557 Function setindex2ifc() (not described in this topic) configures a separate array called index2ifc so that the array entry of this interface index points to the newly created ifc{} structure. This array is used so that the appropriate ifc{} structure can be efficiently identified by the index.

Figure 1-49 illustrates the relationship between the list of ifc{} structures shown in Figure 1-47 and the index2ifc array. A global variable nindex2ifc stores the number of array entries. If a given interface index is invalid, the corresponding index2ifc array entry points to NULL. Note that index2ifc[0] always points to NULL because interface indices begin with 1.

1558—1560 The local function getifmtu() is called to retrieve the MTU of the link to which the interface is attached via a system call (not described in this topic). The link MTU is stored in ifc_mtu. The RIP6_MAXMTU (1500) is an artificial limit, which is introduced by the route6d implementation and is not part of the specification.

1561-1565 The SIOCGIFMETRIC command is issued through ioctl() to retrieve the additional network costs for external routes. Note that the ioctl() call is actually not necessary because the routing metric information has already been retrieved in the call to getifmtu(). ifc_metric is discussed in more detail in Listing 1-41 (Section 1.13.2).

1569 If the code reaches here, that is because this function is processing a new interface address. The IFC_CHANGED flag is set to indicate the change condition and possibly trigger a RIPng response packet to be sent soon.

FIGURE 1-49

FIGURE 1-49

Next post:

Previous post: