2 -- Copyright (C) 2011-2013 Florian Zeitz
4 -- This project is MIT/X11 licensed. Please see the
5 -- COPYING file in the source package for more information.
8 -- This is used to sort destination addresses by preference
9 -- during S2S connections.
10 -- We can't hand this off to getaddrinfo, since it blocks
12 local ip_commonPrefixLength = require"util.ip".commonPrefixLength
14 local function commonPrefixLength(ipA, ipB)
15 local len = ip_commonPrefixLength(ipA, ipB);
16 return len < 64 and len or 64;
19 local function t_sort(t, comp)
20 for i = 1, (#t - 1) do
21 for j = (i + 1), #t do
22 local a, b = t[i], t[j];
30 local function source(dest, candidates)
31 local function comp(ipA, ipB)
32 -- Rule 1: Prefer same address
35 elseif dest == ipB then
39 -- Rule 2: Prefer appropriate scope
40 if ipA.scope < ipB.scope then
41 if ipA.scope < dest.scope then
46 elseif ipA.scope > ipB.scope then
47 if ipB.scope < dest.scope then
54 -- Rule 3: Avoid deprecated addresses
55 -- XXX: No way to determine this
56 -- Rule 4: Prefer home addresses
57 -- XXX: Mobility Address related, no way to determine this
58 -- Rule 5: Prefer outgoing interface
59 -- XXX: Interface to address relation. No way to determine this
60 -- Rule 6: Prefer matching label
61 if ipA.label == dest.label and ipB.label ~= dest.label then
63 elseif ipB.label == dest.label and ipA.label ~= dest.label then
67 -- Rule 7: Prefer temporary addresses (over public ones)
68 -- XXX: No way to determine this
69 -- Rule 8: Use longest matching prefix
70 if commonPrefixLength(ipA, dest) > commonPrefixLength(ipB, dest) then
77 t_sort(candidates, comp);
81 local function destination(candidates, sources)
82 local sourceAddrs = {};
83 local function comp(ipA, ipB)
84 local ipAsource = sourceAddrs[ipA];
85 local ipBsource = sourceAddrs[ipB];
86 -- Rule 1: Avoid unusable destinations
87 -- XXX: No such information
88 -- Rule 2: Prefer matching scope
89 if ipA.scope == ipAsource.scope and ipB.scope ~= ipBsource.scope then
91 elseif ipA.scope ~= ipAsource.scope and ipB.scope == ipBsource.scope then
95 -- Rule 3: Avoid deprecated addresses
96 -- XXX: No way to determine this
97 -- Rule 4: Prefer home addresses
98 -- XXX: Mobility Address related, no way to determine this
99 -- Rule 5: Prefer matching label
100 if ipAsource.label == ipA.label and ipBsource.label ~= ipB.label then
102 elseif ipBsource.label == ipB.label and ipAsource.label ~= ipA.label then
106 -- Rule 6: Prefer higher precedence
107 if ipA.precedence > ipB.precedence then
109 elseif ipA.precedence < ipB.precedence then
113 -- Rule 7: Prefer native transport
114 -- XXX: No way to determine this
115 -- Rule 8: Prefer smaller scope
116 if ipA.scope < ipB.scope then
118 elseif ipA.scope > ipB.scope then
122 -- Rule 9: Use longest matching prefix
123 if commonPrefixLength(ipA, ipAsource) > commonPrefixLength(ipB, ipBsource) then
125 elseif commonPrefixLength(ipA, ipAsource) < commonPrefixLength(ipB, ipBsource) then
129 -- Rule 10: Otherwise, leave order unchanged
132 for _, ip in ipairs(candidates) do
133 sourceAddrs[ip] = source(ip, sources);
136 t_sort(candidates, comp);
140 return {source = source,
141 destination = destination};