util/rfc3484.lua
changeset 5552 40e7a6cf15ff
parent 5550 557583904dc5
child 5553 7baf59444b31
equal deleted inserted replaced
5550:557583904dc5 5552:40e7a6cf15ff
     1 -- Prosody IM
       
     2 -- Copyright (C) 2008-2011 Florian Zeitz
       
     3 --
       
     4 -- This project is MIT/X11 licensed. Please see the
       
     5 -- COPYING file in the source package for more information.
       
     6 --
       
     7 
       
     8 local commonPrefixLength = require"util.ip".commonPrefixLength
       
     9 local new_ip = require"util.ip".new_ip;
       
    10 
       
    11 local function t_sort(t, comp)
       
    12 	for i = 1, (#t - 1) do
       
    13 		for j = (i + 1), #t do
       
    14 			local a, b = t[i], t[j];
       
    15 			if not comp(a,b) then
       
    16 				t[i], t[j] = b, a;
       
    17 			end
       
    18 		end
       
    19 	end
       
    20 end
       
    21 
       
    22 local function source(dest, candidates)
       
    23 	local function comp(ipA, ipB)
       
    24 		-- Rule 1: Prefer same address
       
    25 		if dest == ipA then
       
    26 			return true;
       
    27 		elseif dest == ipB then
       
    28 			return false;
       
    29 		end
       
    30 
       
    31 		-- Rule 2: Prefer appropriate scope
       
    32 		if ipA.scope < ipB.scope then
       
    33 			if ipA.scope < dest.scope then
       
    34 				return false;
       
    35 			else
       
    36 				return true;
       
    37 			end
       
    38 		elseif ipA.scope > ipB.scope then
       
    39 			if ipB.scope < dest.scope then
       
    40 				return true;
       
    41 			else
       
    42 				return false;
       
    43 			end
       
    44 		end
       
    45 
       
    46 		-- Rule 3: Avoid deprecated addresses
       
    47 		-- XXX: No way to determine this
       
    48 		-- Rule 4: Prefer home addresses
       
    49 		-- XXX: Mobility Address related, no way to determine this
       
    50 		-- Rule 5: Prefer outgoing interface
       
    51 		-- XXX: Interface to address relation. No way to determine this
       
    52 		-- Rule 6: Prefer matching label
       
    53 		if ipA.label == dest.label and ipB.label ~= dest.label then
       
    54 			return true;
       
    55 		elseif ipB.label == dest.label and ipA.label ~= dest.label then
       
    56 			return false;
       
    57 		end
       
    58 
       
    59 		-- Rule 7: Prefer public addresses (over temporary ones)
       
    60 		-- XXX: No way to determine this
       
    61 		-- Rule 8: Use longest matching prefix
       
    62 		if commonPrefixLength(ipA, dest) > commonPrefixLength(ipB, dest) then
       
    63 			return true;
       
    64 		else
       
    65 			return false;
       
    66 		end
       
    67 	end
       
    68 
       
    69 	t_sort(candidates, comp);
       
    70 	return candidates[1];
       
    71 end
       
    72 
       
    73 local function destination(candidates, sources)
       
    74 	local sourceAddrs = {};
       
    75 	local function comp(ipA, ipB)
       
    76 		local ipAsource = sourceAddrs[ipA];
       
    77 		local ipBsource = sourceAddrs[ipB];
       
    78 		-- Rule 1: Avoid unusable destinations
       
    79 		-- XXX: No such information
       
    80 		-- Rule 2: Prefer matching scope
       
    81 		if ipA.scope == ipAsource.scope and ipB.scope ~= ipBsource.scope then
       
    82 			return true;
       
    83 		elseif ipA.scope ~= ipAsource.scope and ipB.scope == ipBsource.scope then
       
    84 			return false;
       
    85 		end
       
    86 
       
    87 		-- Rule 3: Avoid deprecated addresses
       
    88 		-- XXX: No way to determine this
       
    89 		-- Rule 4: Prefer home addresses
       
    90 		-- XXX: Mobility Address related, no way to determine this
       
    91 		-- Rule 5: Prefer matching label
       
    92 		if ipAsource.label == ipA.label and ipBsource.label ~= ipB.label then
       
    93 			return true;
       
    94 		elseif ipBsource.label == ipB.label and ipAsource.label ~= ipA.label then
       
    95 			return false;
       
    96 		end
       
    97 
       
    98 		-- Rule 6: Prefer higher precedence
       
    99 		if ipA.precedence > ipB.precedence then
       
   100 			return true;
       
   101 		elseif ipA.precedence < ipB.precedence then
       
   102 			return false;
       
   103 		end
       
   104 
       
   105 		-- Rule 7: Prefer native transport
       
   106 		-- XXX: No way to determine this
       
   107 		-- Rule 8: Prefer smaller scope
       
   108 		if ipA.scope < ipB.scope then
       
   109 			return true;
       
   110 		elseif ipA.scope > ipB.scope then
       
   111 			return false;
       
   112 		end
       
   113 
       
   114 		-- Rule 9: Use longest matching prefix
       
   115 		if commonPrefixLength(ipA, ipAsource) > commonPrefixLength(ipB, ipBsource) then
       
   116 			return true;
       
   117 		elseif commonPrefixLength(ipA, ipAsource) < commonPrefixLength(ipB, ipBsource) then
       
   118 			return false;
       
   119 		end
       
   120 
       
   121 		-- Rule 10: Otherwise, leave order unchanged
       
   122 		return true;
       
   123 	end
       
   124 	for _, ip in ipairs(candidates) do
       
   125 		sourceAddrs[ip] = source(ip, sources);
       
   126 	end
       
   127 
       
   128 	t_sort(candidates, comp);
       
   129 	return candidates;
       
   130 end
       
   131 
       
   132 return {source = source,
       
   133 	destination = destination};