Actually wrote the vlan uniconf generator. Whew, these switches sure are
[wvapps.git] / unity / vlan / superstackgen.cc
blobb61512ce2e9ca7d80be57949afaafe5fdcb1e498
1 #include "wvistreamlist.h"
2 #include "wvstreamclone.h"
3 #include "wvlog.h"
4 #include "wvstringlist.h"
5 #include "unifiltergen.h"
6 #include "wvstrutils.h"
7 #include "wvtclstring.h"
8 #include "wvmoniker.h"
9 #include <ctype.h>
11 class WvSuperStackStream : public WvStreamClone
13 public:
14 WvDynBuf in;
15 WvLog log, inlog;
17 WvSuperStackStream(IWvStream *s)
18 : WvStreamClone(s),
19 log("SuperStack >> ", WvLog::Debug2),
20 inlog("SuperStack << ", WvLog::Debug2)
22 const char setupstr[] = {0xff, 0xfb, 3, 0};
23 print("%s", setupstr); // telnet initiation sequence
24 print("\r\n", setupstr);
25 waitprompt();
28 void waitprompt()
30 log("Waiting...\n");
32 time_t timeout = 10000;
33 while (isok() && select(timeout, true, false))
35 char buf[128];
36 size_t len;
37 len = read(buf, sizeof(buf));
38 in.put(buf, len);
40 inlog.write(buf, len);
42 timeout = 10000;
43 size_t used = in.used();
44 if (used >= 2)
46 const unsigned char *cptr = in.get(used);
47 if (!memcmp(cptr+used-2, ": ", 2))
48 timeout = 200; // a prompt!
49 in.unget(used);
54 WvString _cmd(WvStringParm c)
56 log("%s\n", c);
57 print("%s\r\n", c);
58 waitprompt();
59 return in.getstr();
62 WvString cmd(WvStringParm c)
64 print("\r\n");
65 waitprompt();
66 in.zap();
68 return _cmd(c);
71 WvString cmd(WVSTRING_FORMAT_DECL)
72 { return cmd(WvString(WVSTRING_FORMAT_CALL)); }
74 void login(WvStringParm user, WvStringParm pass)
76 cmd(user);
77 _cmd(pass);
82 class SuperStackGen : public UniFilterGen
84 public:
85 WvLog log;
86 WvSuperStackStream s;
87 bool refreshed_once;
89 SuperStackGen(IUniConfGen *gen, IWvStream *conn,
90 WvStringParm user, WvStringParm pass)
91 : UniFilterGen(gen), log("SuperStackGen", WvLog::Info),
92 s(conn)
94 refreshed_once = false;
95 WvIStreamList::globallist.append(&s, false);
96 s.login(user, pass);
98 // refresh the inner whether *we* get refreshed or not
99 gen->refresh();
102 ~SuperStackGen()
104 s.cmd("logout");
105 WvIStreamList::globallist.unlink(&s);
108 virtual void set(const UniConfKey &key, WvStringParm value);
109 virtual bool refresh();
113 static IUniConfGen *creator(WvStringParm s, IObject *, void *)
115 WvConstInPlaceBuf buf(s, s.len());
116 IUniConfGen *gen = wvcreate<IUniConfGen>(wvtcl_getword(buf));
117 IWvStream *conn = wvcreate<IWvStream>(wvtcl_getword(buf));
118 WvString user = wvtcl_getword(buf), pass = wvtcl_getword(buf);
120 return new SuperStackGen(gen, conn, user, pass);
123 static WvMoniker<IUniConfGen> reg("vlan", creator);
127 void SuperStackGen::set(const UniConfKey &_key, WvStringParm value)
129 UniConfKey key(_key); // non-const
130 WvString vlan(key.pop());
132 if (key.pop() == "ports")
134 WvString port = key.pop();
135 if (key.pop() == "tagging")
137 WvString oldvalue = inner()->get(_key);
138 WvString type;
140 if (!value && !!oldvalue)
141 s.cmd("bridge vlan removePort %s %s", vlan, port);
142 else if (!oldvalue || !!strcasecmp(value, oldvalue))
144 s.cmd("bridge vlan removePort %s %s", vlan, port);
145 if (!strcasecmp(value, "802.1q"))
146 type = "802.1Q";
147 else if (!strcasecmp(value, "none"))
148 type = "none";
149 if (!!type)
150 s.cmd("bridge vlan addPort %s %s %s", vlan, port, type);
152 else
153 type = oldvalue;
155 inner()->set(_key, type);
161 bool SuperStackGen::refresh()
163 // refreshing is super slow, so ignore any requests to do it more than
164 // once. (Sigh...)
165 if (refreshed_once)
166 return false;
167 refreshed_once = true;
169 inner()->set("/", WvString::null);
171 WvStringList vlans;
172 vlans.split(s.cmd("bridge vlan summary all"), "\n");
173 WvStringList::Iter vlan(vlans);
174 for (vlan.rewind(); vlan.next(); )
176 int num, local;
177 char name[81];
178 if (sscanf(*vlan, " %d %d %80s", &num, &local, name) == 3)
180 log("Found vlan: vlan=%s, local=%s, name='%s'\n",
181 num, local, name);
182 inner()->set(WvString("%s/name", num), name);
186 for (int port = 1; port <= 24; port++)
188 int id, local;
189 char name[81], tagging[81];
190 WvString tagstr;
192 WvStringList tags;
193 tags.split(s.cmd("bridge port detail %s", port), "\r\n");
194 WvStringList::Iter tag(tags);
195 for (tag.rewind(); tag.next(); )
197 if (sscanf(*tag, "%d %d %80s %80s ",
198 &id, &local, name, tagging) == 4)
200 const char *cptr = strrchr(*tag, ' ');
201 if (cptr)
203 tagstr = cptr+1;
204 tagstr = trim_string(tagstr.edit());
206 else
207 tagstr = tagging;
208 log("Port#%s is on vlan #%s (%s) using '%s' tagging\n",
209 port, id, name, tagstr);
210 inner()->set(WvString("%s/ports/%s/tagging", id, port),
211 tagstr);
216 return true;