I assume this page might apply to all Cisco Small Business Managed Switches (Linksys Business Series) but since I've only experience with one particual model - the SRW2008P - I'm limiting the scope to that model and the exact firmware revision:
Model Name SRW2008P Hardware Version 00.03.00 Boot Version 1.0.1 Firmware Version 1.0.4
Please let me know if the hints on this page has been successfully used with any other model.
I recently bought a Cisco SRW2008P as it seemed perfect for my home usage. I needed managed gigabit switch, and Power over Ethernet has been on my wishlist for some time. The ability to install wireless access points and PD switches like the SLM2008 with a minimum of cables and power bricks is IMHO even more important for home usage than for business.
On the marketing papers the SRW2008P has
So I hooked up the console and powered it on, only to be surprised by the rather short menu presented there. The first task would be to replace the default "admin" user, but where were my RADIUS settings? Strange. Even stranger: Where the heck were the VLAN configuration menu?
OK, time for reading the documentation. Let's see. "Advanced Configuration" sounds good. This chapter describes the features included in the Web-based Utility.
Come again? Right. So it doesn't really have console, ssh, telnet and SNMP management after all? OK, I've been screwed. No problem. I'm a bit pissed, but I can live with having to use a browser. I enter http://192.168.1.254/ in Opera and get a mostly blank webpage. OK, so it doesn't work with Opera. No big deal. I enter http://192.168.1.254/ in Firefox and I get the same mostly blank page. Starting to worry. Trying iceape and konqueror doesn't help anything.
Time for Google. "SRW2008P firefox" brought me to http://forums.linksysbycisco.com/linksys/board/message?board.id=Switches&message.id=628 which only confirmed my experience.
The SRW2008P just doesn't work. It does not support any standard management interface at all, neither console, ssh, telnet nor http. It requires a dedicated management application sold by Microsoft only as part of their line of operating systems. If you don't have a management station with such an operating system already, you're up for a cost far exceeding the price of the switch itself. Nice.
I later found that Cisco confirms this. It's in fact in the release notes and their Q&A:
Do note that the mentioned "Firefox IE Tab add-on" is a Windows only add-on allowing you to run Internet Explorer embedded in a Firefox tab. It does not change anything, and most important: It is not a solution unless you are using Windows.
After writing this page, I did a bit more Googling and finally found this procedure:
Voila! You've now got a IOS-like CLI:
srw2008a# sh ver SW version 1.0.4 ( date 06-Sep-2007 time 09:11:40 ) Boot version 1.0.1 ( date 06-Jun-2006 time 17:23:21 ) HW version 00.03.00
It's not IOS, but sufficiently lookalike that anyone familiar with IOS should be able to use it. Some notable differences:
This might work with ssh too, but I haven't tested it as I can't find any way to generate host keys of sufficient length for my ssh-client
Note that although I had configured radius+local authentication prior to testing this, the second login only accepted local accounts. This could be fixed after logging into the CLI shell with
aaa authentication login default radius local
I've not found any way of doing that in the Web GUI.
This might just be me, but I do find the CLI version of the VLAN configuration much more intuitive than the web GUI:
vlan database vlan 7 exit interface range ethernet g(2-4,6-8) switchport access vlan 7 exit interface range ethernet g(1,5) switchport trunk allowed vlan add 7 exit interface vlan 7 name Wireless exit
Nice and clean. Note the usage of port ranges. This is in fact much nicer than (switch) IOS. It looks more like Foundry's IOS CLI clone, IMHO.
The existence of a real CLI opens a whole new world. Personally I like keeping simple config backups using RANCID. So I wrote (well, copied mostly) two small scripts to be able to use it against these switches as well. I guess the srwlogin might be useful to do automated logins for other purposes as well:
To use these from RANCID,
--- /usr/lib/rancid/bin/rancid-fe.orig 2008-11-15 12:26:06.000000000 +0100 +++ /usr/lib/rancid/bin/rancid-fe 2009-06-05 15:54:53.000000000 +0200 @@ -68,6 +68,7 @@ 'hitachi' => 'htrancid', 'hp' => 'hrancid', 'juniper' => 'jrancid', + 'linksys' => 'srwrancid', 'mrtd' => 'mrancid', 'netscaler' => 'nsrancid', 'netscreen' => 'nrancid',
srw2008p.example.com:linksys:up:
I am lucky enough to be using Linux on PC hardware, so I do have the ability to run Windows applications under WINE. I got a tip that installing older Internet Explorer versions is really easier under WINE than under real Windows. There are even automated solutions: IEs4Linux - Internet Explorer 6, 5.5, 5 on Linux
This is sufficient to configure the switch and may be the best solution if you can run WINE. That is if you run Linux, BSD, Solaris or Mac OS X on "PC like" hardware.
But what if you can't or won't run WINE? There is a rather unpleasant license problem with the solution above - as menitoned before: Microsoft will only sell you an Internet Explorer license as part an operating system. So for those of us who try our best to respect licensing, Internet Explorer is really not an option.
Unfortunately, the other option seems to be violating Cisco's firmware license. Personally I feel fine about that. I live in a country where I'm explicitly allowed to do that if it's necessary to make a device/software I've bought work. And it certainly is in this case. But YMMV and I guess there are strange places around the world where you actually risk being sued by Cisco for tampering with their code. Consider yourself warned.
The device uses cookie authentication, but fortunately
I started out by looking a the Error Console in Firefox. Boy were there many errors! No way I'm going to be able to fix all those. If you want an example of Cisco's firmware quality assurance, download http://192.168.1.254/css/newlink.css from the device and look at it. You don't have to be a CSS guru to notice that this doesn't look good. You'll find spelling errors like
TEXT-ALIGN: ceneter;Value errors like
FONT-STYLE: bold;(bold is not a style, it's a weight) Typos like
align=centeretc. There are so many of these that I gave up fixing them all. In fact, Internet Explorer will also fail on most of these and we can therefore conclude that they don't matter. It's ugly as hell, but let's look for the real problem.
Looking at the source of /home.htm:
<script src="js/common_data.js"></script> <script src="js/initFunctions.js"></script> <script src="js/common_functions.js"></script> <script src="js/tabs.js"></script> <script src="js/tab_items_208_no_poe.js"></script> <script src="js/tab_items_srs.js"></script> <script src="js/tab_items_cheetah.js"></script> <script src="js/tab_items_soho.js"></script> <script src="js/tab_items_salsa.js"></script> <script src="js/tab_items_cheetah_cut.js"></script> <script src="js/tab_items_106.js"></script> <script src="js/String.js"></script>Ugh, lots of code to fix. I downloaded all of these from the switch, using wget, and started grepping for the problems reported by the Firefox Error Console. Note that Firefox will display the source for you if you select an error in the Error Console. But I wanted a local copy I could modify, so therefore the wget download.
After several hours of fixing bugs all over the place to try to pinpoint the exact bugs preventing Firefox from displaying the Web GUI properly, I ended up with only a handful of small changes to two of the script files:
In addition to the list above, I could not resist making two optional changes to initFunctions.js since I already was modifying it:
There are several possible approaches. The best would of course be to upload a fixed firmware to the device. I have not, and I will not, modify the firmware myself. I fear I'll break it, and I don't want to risk that. So I've used a http proxy configured to replace the files in question with local copies. Another solution would be to create a dedicated frontend doing the same http proxy job.
Note that as we only fiddle with static JavaScript files, which are executed locally by the browser anyway, the changes should be totally transparent to the device itself. Given that we don't change the exposed API of course...
You'll of course need to replace 192.168.1.254 with whatever address your device has if it's different.
wget http://192.168.1.254/js/initFunctions.js wget http://192.168.1.254/js/tabs.jsNote: Some of the other files contain code used for other models. You may have to modify some of these if your device isn't a SRW2008x
NEW: Note that this patch just comments out part of the code that failed. Dave Hall has analysed that particular bug and suggested a fix. I''ve not implemented this.
Patch the files using this patch:
patch -p1 < srw2008-js.diffThe patch is included below for easy viewing and reference. You can cut it from this page, save it to a file and patch, but be careful as it is likely that either your browser or my web conversion will corrupt it...
Index: js/initFunctions.js =================================================================== RCS file: /usr/local/cvsroot/scripts/privat/diverse/srw2008/js/initFunctions.js,v retrieving revision 1.1 retrieving revision 1.2 diff -u -u -r1.1 -r1.2 --- js/initFunctions.js 3 Jun 2009 17:06:31 -0000 1.1 +++ js/initFunctions.js 3 Jun 2009 17:07:04 -0000 1.2 @@ -29,12 +29,12 @@ if (funcOnLoad=='getGeneralDB'){xmlToLoad='../device/generalDB.xml?Filter:(rlHostParamName="l2_num_of_out_of_band_ports")||(rlHostParamName="l2_first_out_of_band_ifIndex")||(rlHostParamName="l2_num_of_trunks")||(rlHostParamName="l2_first_trunk_ifIndex")||(rlHostParamName="l2_max_num_ports_in_trunk")||(rlHostParamName="cosParams_ingressRateLimitSupported")||(rlHostParamName="poe_supported")||(rlHostParamName="unit_max_number_of_units") || (rlHostParamName="vlanDefaultVID")||(rlHostParamName="l2_num_of_vlans")'; nextFunct='getPortDB'; nextURL='../device/portDB.xml?Filter:(ifOperStatus!=6)';} else if (funcOnLoad=='getPortDB'){nextFunct='getModuleDB'; nextURL='../device/moduleDB.xml';} else if (funcOnLoad=='getModuleDB'){nextFunct='getLAGDB'; nextURL='../device/lagDB.xml?[portsToLAGsDataTable]Filter:(ifOperStatus!=6)[LAGsDataTable]Filter:(ifOperStatus!=6)';} -else if (funcOnLoad=='getLAGDB'){nextFunct='endOfFunc';nextURL=''}; +else if (funcOnLoad=='getLAGDB'){nextFunct='endOfFunc';nextURL=''} else if (funcOnLoad=='getExtraPortsDB'){nextFunct='endOfFunc';nextURL=''} else if (funcOnLoad=='endOfFunc') { -set_ref_state('sub_tab_','hand'); -set_ref_state('tab_','hand'); +set_ref_state('sub_tab_','pointer'); +set_ref_state('tab_','pointer'); setTimeout("importXML('getPortDB','../device/portDB.xml?Filter:(ifOperStatus!=6)')",pollingInterval); if(isFirstLoad==true) writeModel(document.getElementById("t1")); @@ -47,7 +47,7 @@ { if (window.XMLHttpRequest && window.navigator.userAgent.indexOf("MSIE")==-1) { xmlDoc = new XMLHttpRequest(); -addEventReadyState(xmlDoc); +//addEventReadyState(xmlDoc); xmlDoc.onreadystatechange = function() { if (nextURL!=null && xmlDoc.readyState == 4) {eval( funcOnLoad+'(xmlDoc.responseXML)');importXML(nextFunct,nextURL); }}; xmlDoc.open("GET", xmlToLoad, true); xmlDoc.send(null); @@ -66,7 +66,7 @@ } else{alert('Your browser can\'t handle this script');} } -catch(e) { if(funcOnLoad=='getGeneralDB'){setTimeout("importXML('"+funcOnLoad+"','"+xmlToLoad+"')",20000);} +catch(e) { alert(e.message); if(funcOnLoad=='getGeneralDB'){setTimeout("importXML('"+funcOnLoad+"','"+xmlToLoad+"')",20000);} else {setTimeout("importXML('getPortDB','../device/portDB.xml?Filter:(ifOperStatus!=6)')",top.pollingInterval);} } } Index: js/tabs.js =================================================================== RCS file: /usr/local/cvsroot/scripts/privat/diverse/srw2008/js/tabs.js,v retrieving revision 1.1 retrieving revision 1.2 diff -u -u -r1.1 -r1.2 --- js/tabs.js 3 Jun 2009 17:06:31 -0000 1.1 +++ js/tabs.js 3 Jun 2009 17:07:04 -0000 1.2 @@ -17,26 +17,31 @@ if( !confirm(msg) ) return; } +/* FIXME: Why doesn't this work, and what's the purpose? curTd=tbl.firstChild.firstChild.childNodes[parseInt(ths.id.substr(4))].style; curTd.backgroundColor=""; if(tbl.lastChild.firstChild.childNodes[tab])tbl.lastChild.firstChild.childNodes[tab].style.backgroundColor="#000000"; +*/ tab=i+1; +/* curTd= tbl.firstChild.firstChild.childNodes[parseInt(ths.id.substr(4))].style curTd.backgroundColor="#6666cc"; curTd.backgroundImage="url('')" tbl.lastChild.firstChild.childNodes[parseInt(ths.id.substr(4))].style.backgroundColor="#6666cc"; +*/ idx=i; -} +/*} else { curTd=tbl.firstChild.firstChild.childNodes[i].style; curTd.backgroundColor=""; curTd.backgroundImage="url('../images/img22_1.jpg')" tbl.lastChild.firstChild.childNodes[i].style.backgroundColor="#000000"; +*/ } } -var txt=ths.innerHTML -document.getElementById('caption').innerHTML=txt +var txt=ths.innerHTML; +document.getElementById('caption').innerHTML=txt; removeTabs(); Loading(idx); subTab=0; @@ -272,12 +277,12 @@ { for(var i=0;i<tabs.length;i++) { -var tdObjHead = createElement("<TD align='center'>") +var tdObjHead = createElement("TD") oHeadTr.appendChild(tdObjHead); } for(var i=0;i<tabs.length;i++) { -var tdObj = createElement("<TD align='center'>") +var tdObj = createElement("TD") tdObj.innerHTML ="<A name='lnk' id='tab_"+i+"' onclick=setTabset(this);>" + tabs[i].title + "</A>" oTabTr.appendChild(tdObj); }
Place the fixed versions on some web server and use a redirector script to point squid there. E.g. something like
#!/usr/bin/perl # squid redirector plugin - save as e.g. /usr/local/sbin/fix_srw2008p.pl my %srw2008p = ( '/js/initFunctions.js' => 'http://www.example.com/srw2008p/js/initFunctions.js', '/js/tabs.js' => 'http://www.example.com/srw2008p/js/tabs.js', ); $|=1; # autoflush required while (<>) { if (m!^http://192.168.1.254/([^? ]*)! && (my $r = $srw2008p{"/$1"})) { s!^http://192.168.1.254/([^? ]*)!$r!; print; } else { print "\n"; } }Include this in squid.conf:
redirect_program /usr/local/sbin/fix_srw2008p.plrefer to the squid manual for details.
Add a new virtual server forwarding anything but requests for the modified files to the switch using mod_proxy. You'll probably want to change this definition to suit your needs wrt locations, server name etc:
<VirtualHost 127.0.0.1:80> ServerName srw2008a.viaproxy.example.com DocumentRoot /var/www/srw2008 <IfModule mod_proxy.c> ProxyRequests Off ProxyPass /js/initFunctions.js ! ProxyPass /js/tabs.js ! ProxyPass / http://192.168.1.254/ ProxyPassReverse / http://192.168.1.254/ <Proxy *> Order deny,allow Allow from 127.0.0.1 </Proxy> </IfModule> </VirtualHost>
This config assumes that
You need to enable the virtual server and ensure that mod_proxy is loaded. Refer to the apache manual for further details.
The hostname can be added to /etc/hosts if it's only going to be used by the local host (like the config example suggests):
127.0.0.1 srw2008a.viaproxy.example.com
Because it's all about content. The main advantage is that there are no CSS related bugs. If only Cisco could do the same...
Yes, please do! I'd love to know if this is useful to anyone. My address is bjorn@mork.no
Please feel free to ask any questions too. The above was written primarily as a summary to myself, and I do realise that it does presume a bit of additional knowledge. Either pre-aquired or Googled. But then again: It's only applicable to those not using Windows, so I consider it safe :-)
Yes, please do! In particular, if Cisco is interested in integrating the patch above, hire a web developer for a week fixing all the remaining bugs, and releasing a fixed firmware, then Go Ahead! I'll applaud and include a nice link to the fixed firmware download here instead of this page.
Some of this information was taken from other pages. Thanks!
explains the
curTd = tbl.firstChild.firstChild.childNodes[tab].style;bug and shows how it can be fixed
shows how to access the cli:
Ctrl+Z lcli
authenticate using *local* user/password!