WvStreams
|
00001 /* 00002 * Worldvisions Weaver Software: 00003 * Copyright (C) 1997-2002 Net Integration Technologies, Inc. 00004 * 00005 * WvIPAliaser handles IP aliasing in the Linux kernel. See wvipaliaser.h. 00006 */ 00007 #include "wvipaliaser.h" 00008 #include "wvinterface.h" 00009 #include <assert.h> 00010 00011 00012 WvIPAliaser::AliasList WvIPAliaser::all_aliases; 00013 00014 00015 00017 00018 00019 00020 WvIPAliaser::Alias::Alias(const WvIPAddr &_ip) : ip(_ip) 00021 { 00022 WvIPAddr noip; 00023 WvIPNet nonet(noip, noip); 00024 link_count = 0; 00025 00026 for (index = 0; index < 256; index++) 00027 { 00028 WvInterface i(WvString("lo:wv%s", index)); 00029 00030 if (!i.isup() || i.ipaddr() == nonet) // not in use yet! 00031 { 00032 i.setipaddr(ip); 00033 i.up(true); 00034 if (WvIPAddr(i.ipaddr()) != ip) 00035 { 00036 // no permission, most likely. 00037 index = -1; 00038 i.up(false); 00039 } 00040 return; 00041 } 00042 00043 if (i.isup() && WvIPNet(i.ipaddr(),32) == ip) 00044 { 00045 // a bit weird... this alias already has the right address. 00046 // Keep it. 00047 return; 00048 } 00049 } 00050 00051 // got through all possible names without a free one? Weird! 00052 index = -1; 00053 } 00054 00055 00056 WvIPAliaser::Alias::~Alias() 00057 { 00058 if (index >= 0) 00059 { 00060 WvInterface i(WvString("lo:wv%s", index)); 00061 // i.setipaddr(WvIPAddr()); // not necessary in recent kernels 00062 i.up(false); 00063 } 00064 } 00065 00066 00067 00069 00070 00071 00072 WvIPAliaser::WvIPAliaser() : interfaces() 00073 { 00074 // nothing to do 00075 } 00076 00077 00078 WvIPAliaser::~WvIPAliaser() 00079 { 00080 // clear the alias list 00081 start_edit(); 00082 done_edit(); 00083 } 00084 00085 00086 void WvIPAliaser::start_edit() 00087 { 00088 AliasList::Iter i(aliases); 00089 00090 #ifndef NDEBUG 00091 AliasList::Iter i_all(all_aliases); 00092 #endif 00093 00094 interfaces.update(); 00095 00096 for (i.rewind(); i.next(); ) 00097 { 00098 assert(i_all.find(i.ptr())); 00099 00100 // the global alias entry goes down by one 00101 i().link_count--; 00102 } 00103 00104 // empty out the local list 00105 aliases.zap(); 00106 } 00107 00108 00109 WvIPAliaser::Alias *WvIPAliaser::ipsearch(WvIPAliaser::AliasList &l, 00110 const WvIPAddr &ip) 00111 { 00112 AliasList::Iter i(l); 00113 00114 for (i.rewind(); i.next(); ) 00115 { 00116 if (i->ip == WvIPAddr(ip)) 00117 return i.ptr(); 00118 } 00119 00120 return NULL; 00121 } 00122 00123 00124 bool WvIPAliaser::add(const WvIPAddr &ip) 00125 { 00126 Alias *a; 00127 00128 if (WvIPAddr(ip) == WvIPAddr() || ipsearch(aliases, ip)) 00129 return false; // already done. 00130 00131 // If the alias is already a local address, there is no need for an alias. 00132 // We have to be careful that we don't find an existing alias as the 00133 // local interface. Otherwise, we'll toggle that alias on and off. 00134 WvString ifc(interfaces.islocal(WvIPAddr(ip))); 00135 if (!!ifc && !strchr(ifc, ':')) // Make sure it is a real interface 00136 return false; 00137 00138 a = ipsearch(all_aliases, ip); 00139 if (a) 00140 { 00141 // It's already in the global list, so we add its entry to 00142 // our list and increase the link count. 00143 aliases.append(a, false); 00144 a->link_count++; 00145 return false; 00146 } 00147 else 00148 { 00149 // It's not there, so we add a new alias to the global list and 00150 // our local list. 00151 a = new Alias(ip); 00152 aliases.append(a, false); 00153 all_aliases.append(a, true); 00154 a->link_count++; 00155 return true; 00156 } 00157 } 00158 00159 00160 bool WvIPAliaser::done_edit() 00161 { 00162 bool any_change=false; 00163 AliasList::Iter i(all_aliases); 00164 00165 i.rewind(); i.next(); 00166 while (i.cur()) 00167 { 00168 Alias &a = *i; 00169 if (!a.link_count) { 00170 i.unlink(); 00171 any_change = true; 00172 } else 00173 i.next(); 00174 } 00175 00176 return any_change; 00177 } 00178 00179 00180 void WvIPAliaser::dump() 00181 { 00182 { 00183 WvLog log("local aliases"); 00184 AliasList::Iter i(aliases); 00185 for (i.rewind(); i.next(); ) 00186 { 00187 Alias &a = *i; 00188 log("#%s = lo:wv%s: %s (%s links)\n", 00189 a.index, a.index, a.ip, a.link_count); 00190 } 00191 log(".\n"); 00192 } 00193 00194 { 00195 WvLog log("global aliases"); 00196 AliasList::Iter i(all_aliases); 00197 for (i.rewind(); i.next(); ) 00198 { 00199 Alias &a = *i; 00200 log("#%s = lo:wv%s: %s (%s links)\n", 00201 a.index, a.index, a.ip, a.link_count); 00202 } 00203 log(".\n.\n"); 00204 } 00205 }