WvStreams
wvipaliaser.cc
1 /*
2  * Worldvisions Weaver Software:
3  * Copyright (C) 1997-2002 Net Integration Technologies, Inc.
4  *
5  * WvIPAliaser handles IP aliasing in the Linux kernel. See wvipaliaser.h.
6  */
7 #include "wvipaliaser.h"
8 #include "wvinterface.h"
9 #include <assert.h>
10 
11 
12 WvIPAliaser::AliasList WvIPAliaser::all_aliases;
13 
14 
15 
17 
18 
19 
20 WvIPAliaser::Alias::Alias(const WvIPAddr &_ip) : ip(_ip)
21 {
22  WvIPAddr noip;
23  WvIPNet nonet(noip, noip);
24  link_count = 0;
25 
26  for (index = 0; index < 256; index++)
27  {
28  WvInterface i(WvString("lo:wv%s", index));
29 
30  if (!i.isup() || i.ipaddr() == nonet) // not in use yet!
31  {
32  i.setipaddr(ip);
33  i.up(true);
34  if (WvIPAddr(i.ipaddr()) != ip)
35  {
36  // no permission, most likely.
37  index = -1;
38  i.up(false);
39  }
40  return;
41  }
42 
43  if (i.isup() && WvIPNet(i.ipaddr(),32) == ip)
44  {
45  // a bit weird... this alias already has the right address.
46  // Keep it.
47  return;
48  }
49  }
50 
51  // got through all possible names without a free one? Weird!
52  index = -1;
53 }
54 
55 
56 WvIPAliaser::Alias::~Alias()
57 {
58  if (index >= 0)
59  {
60  WvInterface i(WvString("lo:wv%s", index));
61  // i.setipaddr(WvIPAddr()); // not necessary in recent kernels
62  i.up(false);
63  }
64 }
65 
66 
67 
69 
70 
71 
72 WvIPAliaser::WvIPAliaser() : interfaces()
73 {
74  // nothing to do
75 }
76 
77 
78 WvIPAliaser::~WvIPAliaser()
79 {
80  // clear the alias list
81  start_edit();
82  done_edit();
83 }
84 
85 
87 {
88  AliasList::Iter i(aliases);
89 
90  #ifndef NDEBUG
91  AliasList::Iter i_all(all_aliases);
92  #endif
93 
94  interfaces.update();
95 
96  for (i.rewind(); i.next(); )
97  {
98  assert(i_all.find(i.ptr()));
99 
100  // the global alias entry goes down by one
101  i().link_count--;
102  }
103 
104  // empty out the local list
105  aliases.zap();
106 }
107 
108 
109 WvIPAliaser::Alias *WvIPAliaser::ipsearch(WvIPAliaser::AliasList &l,
110  const WvIPAddr &ip)
111 {
112  AliasList::Iter i(l);
113 
114  for (i.rewind(); i.next(); )
115  {
116  if (i->ip == WvIPAddr(ip))
117  return i.ptr();
118  }
119 
120  return NULL;
121 }
122 
123 
124 bool WvIPAliaser::add(const WvIPAddr &ip)
125 {
126  Alias *a;
127 
128  if (WvIPAddr(ip) == WvIPAddr() || ipsearch(aliases, ip))
129  return false; // already done.
130 
131  // If the alias is already a local address, there is no need for an alias.
132  // We have to be careful that we don't find an existing alias as the
133  // local interface. Otherwise, we'll toggle that alias on and off.
134  WvString ifc(interfaces.islocal(WvIPAddr(ip)));
135  if (!!ifc && !strchr(ifc, ':')) // Make sure it is a real interface
136  return false;
137 
138  a = ipsearch(all_aliases, ip);
139  if (a)
140  {
141  // It's already in the global list, so we add its entry to
142  // our list and increase the link count.
143  aliases.append(a, false);
144  a->link_count++;
145  return false;
146  }
147  else
148  {
149  // It's not there, so we add a new alias to the global list and
150  // our local list.
151  a = new Alias(ip);
152  aliases.append(a, false);
153  all_aliases.append(a, true);
154  a->link_count++;
155  return true;
156  }
157 }
158 
159 
160 bool WvIPAliaser::done_edit()
161 {
162  bool any_change=false;
163  AliasList::Iter i(all_aliases);
164 
165  i.rewind(); i.next();
166  while (i.cur())
167  {
168  Alias &a = *i;
169  if (!a.link_count) {
170  i.unlink();
171  any_change = true;
172  } else
173  i.next();
174  }
175 
176  return any_change;
177 }
178 
179 
180 void WvIPAliaser::dump()
181 {
182  {
183  WvLog log("local aliases");
184  AliasList::Iter i(aliases);
185  for (i.rewind(); i.next(); )
186  {
187  Alias &a = *i;
188  log("#%s = lo:wv%s: %s (%s links)\n",
189  a.index, a.index, a.ip, a.link_count);
190  }
191  log(".\n");
192  }
193 
194  {
195  WvLog log("global aliases");
196  AliasList::Iter i(all_aliases);
197  for (i.rewind(); i.next(); )
198  {
199  Alias &a = *i;
200  log("#%s = lo:wv%s: %s (%s links)\n",
201  a.index, a.index, a.ip, a.link_count);
202  }
203  log(".\n.\n");
204  }
205 }
WvIPNet
An IP network comprises two WvIPAddr structures: an address and a netmask.
Definition: wvaddr.h:312
WvString
WvString is an implementation of a simple and efficient printable-string class.
Definition: wvstring.h:329
WvLog
A WvLog stream accepts log messages from applications and forwards them to all registered WvLogRcv's.
Definition: wvlog.h:56
WvIPAliaser::start_edit
void start_edit()
you must call start_edit() once, then add() any number of times, then done_edit() once,...
Definition: wvipaliaser.cc:86
WvInterface
A WvInterface manages a particular network interface.
Definition: wvinterface.h:24
WvIPAddr
An IP address is made up of a "dotted quad" – four decimal numbers in the form www....
Definition: wvaddr.h:249