IPv6 through WLAN access point revisited
Wednesday, August 28. 2013
This is a follow-up for my previous article about running IPv6 and WLAN access point. There I said "This was actually very easy to do into DD-WRT" and now I'd like to take that back.
It seemed to be easy, but ... Here are my settings in detail. Btw. I'm running DD-WRT v24-sp2 big
Release: 07/24/13 (SVN revision: 22118)
1. disable the autoconfiguration from the WLAN access-point and manually define a static IPv6-address
This is the part which I struggled the most. Sure it is easy to remove the manually assigned IPv6-address from an interface, just run:
ip -6 addr delete 2001::-da-IP-here-/64 dev br0
on a shell. It will drop the autoconfigured address and it will stay away. For a while. It surely won't survive a reboot.
To make this stick, go to web GUI Administration --> Commands and add a startup command:
echo 1 > /proc/sys/net/ipv6/conf/all/forwarding
echo 0 > /proc/sys/net/ipv6/conf/all/autoconf
echo 0 > /proc/sys/net/ipv6/conf/all/accept_ra
echo 0 > /proc/sys/net/ipv6/conf/all/accept_ra_pinfo
/usr/sbin/ip -6 addr add 2001:-da-IP-here-/64 dev br0
That makes the settings stick. Autoconfiguration will be gone and a static address will be assigned instead. I attempted at least 20 different combinations while looking the sysctl-settings list, but that was the 1st one I found to be actually functional for deactivating the autoconfig.
2. use a static default route from the WLAN access-point and confirm that it has proper IPv6-connectivity
4. make sure, that any incoming traffic from the mobile clients is
properly routed to the real IPv6-router, and confirm that traffic flows
both ways
Yet again, go to web GUI Administration --> Commands and add a startup command:
/usr/sbin/ip -6 route add default via 2001:-da-router-IP-here-::1 metric 1
That creates a static route which will work and fulfill the 2). To achieve 4) make sure to have the metric 1 at the end.
3. run router advertisement daemon (RADVD) to advertise the WLAN access-point as a proper router for any wireless clients
In the DD-WRT IPv6 article it said that RADVD configuration should be like this:
interface br0 {
AdvSendAdvert on;
prefix 0:0:0:1::/64 {
AdvOnLink on;
AdvAutonomous off;
};
};
Don't do that! DON'T! It will royally fuck up your LAN. Nothing in IPv6-land will work if you literally copy/paste that like they suggest. The problem is with the prefix of 0:0:0:1::/64, it will assume that your network has that /64-prefix and assign route and IP-address for any IPv6-host with that prefix. I can bet you $1.000.000 dollars, that it will not be your IPv6-prefix. ... and win.
Just put the exactly same prefix your real IPv6-router has. The WLAN access point's RADVD should be configured pretty much exactly alike. For the configuration directives see radvd.conf manual-page. It literally says:
- AdvSendAdvert: do send advertisements, default is off
- AdvOnLink: use the prefix for link determination (meaning: yes you can get to The Net via this), it is on by default, you really don't need this line at all
- AdvAutonomous: do distribute new the IP-addresses from this RADVD to your wireless (and wired) clients, yet again it is on by default and you really don't need this
With these settings I succeeded a reboot and still had my wireless and wired clients working using either of the two IPv6-routers. On Windows the setup will display two default routes, like this:
PS C:\Windows\system32> netsh interface ipv6 show route
Publish Type Met Prefix Idx Gatewa
------- -------- --- ------------------------ --- ------
No Manual 256 ::/0 18 fe80::
No Manual 256 ::/0 18 fe80::
On Linux:
# ip -6 route show | fgrep default
default via fe80:: dev eth0 metric 1024 expires 0sec mtu 1280 hoplimit 64
default via fe80:: dev eth0 metric 1024 expires 0sec mtu 1280 hoplimit 64
That's ok. IPv6 will support that ok. Just be aware, that your traffic may route either way.
Windows IPv6 connection starting to "rot" over time [Solved!]
Tuesday, August 27. 2013
I've been using IPv6 on my own LAN for years. Most of the things I use on daily basis have IPv6 and it seems to work. For example a Sony television or iPhone 4S does not use IPv6, but iPad does.
On my router there is a Router Advertisement Damon to do stateless auto-configuration. On Windows 7 and 8 they have really weird things running out-of-the-box, but I'm in a habit of running (as admin):
netsh interface ipv6 set privacy state=disabled store=active
netsh interface ipv6 set privacy state=disabled store=persistent
netsh interface ipv6 set global randomizeidentifiers=disabled store=active
netsh interface ipv6 set global randomizeidentifiers=disabled store=persistent
netsh interface teredo set state disabled
That way I'm using fixed IPv6-addresses and disable the unnecessary Teredo-tunnel.
I don't exactly know why or how, but on one of my computers (running Windows 7), the IPv6-sockects started to not work properly. The symptoms include lot of reconnections and for example in SSH-client, the connection would simply drop. I did everything I knew, but nothing helped. A failing SSH-connection would look like this on the wire:
After 31 seconds of connection, there is a sporadic retransmission. That is not dangrous and it happens sometimes. My Windows 7 would respond with a duplicate ACK into it, waits 3 seconds and goes ballistic. It simply starts re-transmitting the already transmitted data with 1, 3 and 5 second intervals before determining that the connection has died. WTF?! The connection is not bad! It works on all other computers. The issue can be easily repeated and it works the same way every time. Windows thinks it needs to start a burst of re-transmissions and disconnects when they seem to fail.
During one of the Google-session for the fix, I found netsh interface ipv6 reset command. I tried it:
PS C:\Windows\system32> .\netsh.exe interface ipv6 reset
Reseting Global, OK!
Reseting Interface, OK!
Reseting Subinterface, OK!
Restart the computer to complete this action.
Did the Windows restart, ran the above commands to disable privacy, randomization and teredo-tunnel. Everything started to work! Whooo-hoo! Now my SSH-connections don't drop anymore. How cool is that!
The fix is very microsoft-ish. Some counter ticked into illegal value and in their mind the correct fix is to reset everything to the post-installation state. On *nix-world network-stack -code would be of much better quality and the entire issue would never happen!
What programming languages to learn?
Monday, August 26. 2013
This is a classic question which I get to answer a lot. N00bs know the answer, but somebody outside the IT-business might ask something like that. This is also quite a popular question among young people trying to figure out if programming would be for them.
Anyway, here 5 Programming Languages Everyone Should Know from two people who actually have created some of the most popular languages currently used.
Nobody should call themselves a professional if they knew only one language.
- Bjarne Stroustrup
Larry Wall
See his interview: http://youtu.be/LR8fQiskYII
His list:
- JavaScript
- Java
- Haskell
- C
- Perl
Perl is not a surprise in his list. He created it in the 80s.
Bjarne Stroustrup
See his interview: http://youtu.be/NvWTnIoQZj4
His list:
- C++
- Java
- Python
- JavaScript
- C
- C#
Again, seeing C++ in his list is not a big surprise, he was one of the authors of the language in the 80s. The funny thing is that he mentions 6 languages.
Linus Torvalds
This two year old interview keeps popping up. In this video http://youtu.be/Aa55RKWZxxI mr. Linux mentions one programming language not to use.
The again, this person is well known from his more than colorful opinions about various issues. But anyway his work on Linux kernel and Git version management are well known, he is a fan of C.
me
Being a blog-author I have to express an opinion of my own. To solely copy/paste opinions of three very skilled persons is too much of a cheap thing. So, here goes:
- C
- Pretty much all languages created after 1970 owe something to C, it is imperative to know this.
- JavaScript
- When doing any kind of web-stuff, this is the only language being used in 100% of the cases. All browsers run this and it is the de-facto client-side language today.
- C#
- Very versatile compiled language by Microsoft, has lot of influence from C, C++, Java, PHP, Perl, etc. the list goes on. It is mainly used with .Net to create server-side stuff.
- PHP
- IMHO the most important web-server language there is. This is wildly popular and shares similarity with C, JavaScript, Perl, Visual Basic, etc.
In addition to learning programming languages, I encourage everybody to learn also following widely popular frameworks:
- Microsoft .Net
- Zend Framework
My reasoning between this is that if you understand how they work, you're pretty well covered and also going to Python/Django or Ruby on Rails is much easier task. I know that these are web-frameworks and people program a lot other stuff than web, but sticking to the topic of what languages to learn, these are the first ones to try. There are so many other frameworks, especially in PHP-land, but they don't have such an essential position as the framework made by people who created the PHP-language. In Microsoftland there are no other significiant frameworks to learn. Anyway, both are properly documented and lot of information can be found of them.
Exploring Dijit.Editor of Dojo toolkit
Sunday, August 25. 2013
My favorite JavaScript-library Dojo has a very nice HTML-editor. During a project I even enhanced it a bit. Anyway the Dojo/Dijit-documentation is not the best in the world, so I'll demonstrate the three operating modes that are available. All of them have the same functionality, but how they appear visually to the person doing the HTML-editing differs.
Classic fixed size
This is the vanilla operating mode. From the beginning of time, a HTML <TEXTAREA> has been like this (without any formatting, of course). A fixed block-container of multi-line text editor which will scroll on overflow.
Example:
HTML for declarative instantiation:
<div id="terms-Editor" data-dojo-type="dijit.Editor"
height="150px"
data-dojo-props="extraPlugins:['insertanchor','viewsource']">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>
There is really nothing special, I'm just using two extra plugins insertanchor and viewsource to produce two new icons to the editor toolbar to add functionality for the end user. I found out that the plugins really need to be all lower-case for them to load properly. The class-names and filenames are in CamelCase, but putting them like that makes loading fail.
The obvious thing is that the editor is 150 pixels high. I didn't set the width, but since the editor is a simple div, any size can be set.
Auto-expanding
This is a plugin expansion for the previous. The only real difference is that this type of editor does not overflow. Ever. It keeps auto-expanding to any possible size to be able to display the entire text at once. During testing I found out that the auto-resize -code does not work on all browsers. There seems to be a discrepancy of exactly one line on for example Chrome. The bug manifests itself when you try to edit the last line, pretty much nothing is visible there. I didn't fix the bug, as I concluded that I won't be using this mode at all.
HTML for declarative instantiation:
<div id="terms-Editor" data-dojo-type="dijit.Editor"
height="" minHeight="100px"
data-dojo-props="extraPlugins:['alwaysshowtoolbar','insertanchor','viewsource']">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>
This has three things to be taken into notice:
- The auto-expansion is achieved by plugin called alwaysshowtoolbar. It does not work in current Dojo version of 1.9.1, I had to fix it. See the patch at the end of this post.
- It is absolutely critical to set the height="". Forget that and the alwaysshowtoolbar-plugin does not work.
- It is advisable to set a minimum height, in my example I'm using 100 pixels. The editor will be really slim, if there is no text. This sets the size into something visually appealing.
Manually resizable
This is how a <TEXTAREA> behaves on many modern browsers. When using plugin statusbar you'll get a handle to resize the block. During testing I found out that it is a bad idea to allow the user to be able to make the editor wider. I enhanced the class with additional parameter which gets passed to plugin's constructor to limit the ResizeHandle functionality.
Example:
HTML for declarative instantiation:
<div id="terms-Editor" data-dojo-type="dijit.Editor"
height="200px"
data-dojo-props="extraPlugins:[{name:'statusbar',resizeAxis:'y'},'insertanchor','viewsource']">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>
Note that specifying the resizeAxis won't work in your code. If you really want the code I can e-mail it to you, it is longish enough for me not to post it here. The height is 200 pixels initially, but user can make the editor any size.
Hope this helps to clarify the complexity of this fine editor. It would be also nice if a filed bug report would be processed in Dojo-project. Also their discussion in Google Groups is closed, the group is set to moderate any posts, but there is nobody doing that. So, effectively new people cannot post. There is nothing left, but to complain in a blog.
Appendix 1:AlwaysShowToolbar.js patch to fix the plugin-loading
--- dojo/dijit/_editor/plugins/AlwaysShowToolbar.js.orig 2013-07-19 13:21:17.000000000 +0300
+++ dojo/dijit/_editor/plugins/AlwaysShowToolbar.js 2013-08-02 17:31:44.384216198 +0300
@@ -13,7 +13,7 @@
// module:
// dijit/_editor/plugins/AlwaysShowToolbar
- return declare("dijit._editor.plugins.AlwaysShowToolbar", _Plugin, {
+ var AlwaysShowToolbar = declare("dijit._editor.plugins.AlwaysShowToolbar", _Plugin, {
// summary:
// This plugin is required for Editors in auto-expand mode.
// It handles the auto-expansion as the user adds/deletes text,
@@ -198,4 +198,11 @@
}
});
+ // Register this plugin.
+ // For back-compat accept "alwaysshowtoolbar" (all lowercase) too, remove in 2.0
+ _Plugin.registry["alwaysshowtoolbar"] = _Plugin.registry["alwaysshowtoolbar"] = function(args){
+ return new AlwaysShowToolbar();
+ };
+
+ return AlwaysShowToolbar;
});
IPv6 through WLAN access-point
Wednesday, August 21. 2013
I had a glitch with my DD-WRT -setup as it failed to pass-trough native IPv6-traffic on my own network. It took me a while to understand why only IPv4-traffic was getting trough it, but I managed to get it working. Here is my setup:
It is pretty trivial, the internet connection goes trough firewall and a router. Behind the router, there is my wired Ethernet and wireless connection to mobile devices. I had no issues with wired devices, IPv6 was working fine, so I guessed my WLAN-setup was flawed.
A closer inspection revealed, that my DD-WRT was configured to use IPv6 Stateless address autoconfiguration. This is part of IPv6-specification and a closer inspection of the traffic reveals, that autoconfiguration is done with couple of specially crafted ICMPv6-packets. I bumped into Mr. Matt Brown's blog, which pointed me to the RFC 4862 which defines the protocol. It states that there exists two kinds of nodes:
- router - a node that forwards IP packets not explicitly addressed to itself
- host - any node that is not a router
Then it struck me:
My WLAN access-point is considered a router, altough it is a bridge by definition, but for the sake of IPv6 autoconfiguration it is a router. As it came out, the autoconfiguration packages are using link-local addresses from address-space of fe80::/64, which by definition won't survive a hop over a router. (Which in my mind I didn't have, it was a WLAN bridge!)
The plan was to:
- disable the autoconfiguration from the WLAN access-point and manually define a static IPv6-address
- use a static default route from the WLAN access-point and confirm that it has proper IPv6-connectivity
- run router advertisement daemon (RADVD) to advertise the WLAN access-point as a proper router for any wireless clients
- make sure, that any incoming traffic from the mobile clients is properly routed to the real IPv6-router, and confirm that traffic flows both ways
This was actually very easy to do into DD-WRT. After disabling and enabling the wireless interface on my Windows 8, I finally got a default route:
PS C:\Windows\system32> netsh interface ipv6 show route
Publish Type Met Prefix Idx Gateway/Interface Name
------- -------- --- ------------------------ --- ------------------------
No Manual 256 ::/0 18 fe80::c2c1:c0ff:c2c1:c0ff
This was nice! Everything simply started working. What I'm still looking for are ways of getting the default route without disable/enable for the interface. Both, on Linux and Windows.
NTPd vs. Chrony
Monday, August 19. 2013
In my Fedora 19 I've been wondering why my NTPd does not start on boot. It used to do so couple of Fedora installations ago. This is not a big deal, so I've been mostly ignoring it. Today I dug up some energy to investigate.
The reason was much simpler than I tought. On my very short checklist were:
- Confirm that systemd has ntpd.service enabled, it was.
- Confirm that ntpd.service has a dependency to start the service after network interfaces are up, it was chained to do a single ntpdate update and start the daemon after it.
- Needed interfaces have not been blocked and/or needed interfaces have been enabled in config, everything was out-of-the-box: all network interfaces allowed.
The daemon even had the panic-threshold disabled in the config, so it wouldn't choke on startup if time was badly off for some reason. I found no reason for the daemon to start.
However, doing a search for ntpd in /usr/lib/systemd/system revealed what was going on. chronyd.service has Conflicts=ntpd.service in the service description. WTF?! What the hell is chronyd?
According to http://chrony.tuxfamily.org/ it is "a pair of programs which are used to maintain the accuracy of the system clock on a computer". Sounds like a NTPd to me. Running netstat confirmed the fact:
# netstat -nap | fgrep :123
udp 0 0 0.0.0.0:123 0.0.0.0:* 666/chronyd
udp6 0 0 :::123 :::* 666/chronyd
The daemon does bind to NTP-ports. To get chronyd running properly, all I had to do was add proper time source and allowed updates from my LAN with allow-directives.
That's it!
Linux failing to mount iSCSI on boot
Thursday, August 15. 2013
My Fedora 19 failed to boot if I had an entry for an iSCSI-mount in /etc/fstab. During boot the system just fell to emergency mode. To get the box to boot, I simply did a "stupd man's solution", and commented the line out. This is what happens if I have the standard line in fstab:
My fstab line is:
/dev/qnap /mnt/qnap ext4 defaults 1 0
It took me a while to get back to the issue and investigate, it was that bad. This is the clue I found on Fedora project's documentation about iSCSI. They said, that any iSCSI-volumes should be mounted with a special flag _netdev. I changed to that, and hey presto! During bootup, it first does something and then mounts the iSCSI-drive. I merged those two occurrences into a single photo:
It works! I'm so happy about this. For clarity, the fstab-line is:
/dev/qnap /mnt/qnap ext4 _netdev 0 0
QNAP Turbo NAS firmware version 4
Wednesday, August 14. 2013
QNAP released their version 4 firmware. Its GUI has iPad-look and feel and is a major improvement overall. It has all the existing features (actually I don't know of any new interesting things), but the management interface has been completely re-written. It responds much faster and is really nice to use. Actually the version 3 GUI was very, very slow to log-in or respond to a click. It looks like this:
The only thing I noticed that didn't work was date/time settings. It chose a GMT-12 time zone for some reason. It does work in the background, I'm using Europe/Helsinki TZ and it shows EEST correctly on SSH-connection:
[~] # date
Wed Aug 14 13:24:52 EEST 2013
Also, I noticed that daylight savings time -setting displays the correct TZ.
To fix the NTP-client I did following:
# /sbin/setcfg NTP "Server1 IP" -my-IP-here-
# /etc/init.d/ntpd.sh stop
# /etc/init.d/ntpd.sh start
This does not reflect the change to the GUI.
Anyway, I'm looking forward to see the next firmware to fix those issues.
Own RPM package: Make symlink survive update/freshen
Friday, August 9. 2013
During my ventures in the Linux-land, I constantly package and re-package RPMs. Sometimes to introduce new functionality to existing package or to simply get a newer version that distro vendor is prepared to offer. Number of times I've created packaging to software that is not in the distro at all.
Another thing I love using are symlinks. I can have newer and older package of a software and can simply switch with updating the symlink into correct version. When I combined those two, it bit me in the ass.
I had quite simple script-blocks to handle the symlink:
%post
cd /my/package/directory/
%{__rm} -f my.cool.symlink-name
ln -s package/library/my.cool my.cool.symlink-name
%preun
%{__rm} -f /my/package/directory/my.cool.symlink-name
On install, that worked, but on update/freshen there was no symlink left. I was puzzled, why is that? Little bit of googling revealed two pieces of information: RPM spec-file documentation about scripts, especially the Install/Erase-time Scripts -part and 2nd the Fedora Project's packaging information, especially the scriptlet ordering. I'll abbreviate the Fedora's ordering here omitting the non-interesting parts:
- %pre of new package
This is the part where my script confirms that the symlink exists. - (package install)
- %post of new package
- %preun of old package
During update/freshen, this is the part where my script removes the symlink created in 1.)
Crap! - (removal of old package)
- %postun of old package
Further reading of RPM spec-docs said "the argument passed to version 1.0's scripts is 1". Ok, nice to how, but now what? How can I utilize the information? What is the exact syntax for the script? The only usable information I found was in the Fedora packaging instructions, there was an example:
%preun
if [ $1 = 0 ] ; then
/sbin/install-info --delete %{_infodir}/%{name}.info %{_infodir}/dir || :
fi
So this was the thing I had to try. My solution is to change the %preun-block:
%preun
if [ $1 -lt 1 ] ; then
# This is really an un-install, not deleting previous version on update
%{__rm} -f /my/package/directory/my.cool.symlink-name
fi
I did that and upgraded the package. Poooof! The symlink was gone like there was no change at all. WHY? I upgraded the revision number of the package and upgraded again. NOW it worked! Nice.
There is a simple explanation what happened. It says in the Fedora project's order-list that "%preun of old package". OLD package! It works starting from the next update, but not on the first one.
Anyway I was delighted to get that one sorted.
Running Linksys E4200 access point
Thursday, August 8. 2013
I got one of Linksys wireless access points. The original idea was to install Linux into it with DD-WRT, but the operation failed miserably due the fact, that there are actually two kinds of E4200 APs. Guess who has the "wrong" kind. That would be my 3rd Linksys wireless access-point. I love their products due to extensive Linux-support and very high quality hardware. Now it looks like, this one didn't turn out like I planned.
Anyway, the thingie had a very old firmware and I thought that it would be a good idea to upload the newest factory firmware into it. That failed immediately, all I got was a "Image File Is Incorrect" error message. The message was spat out from the GUI almost immediately, so I decided to debug it. Here is the code I found:
var len = F.file.value.length;
var ext = new Array('.','i','m','g');
if (F.file.value == '') {
alert(fwupgrade.upgradefile);
return false;
}
var IMAGE = F.file.value.toLowerCase();
for (i=0; i < 4; i++) {
if (ext[i] != IMAGE.charAt(len-4+i)){
alert(hupgrade.wrimage);
return false;
}
}
Nice! The manufacturer designated file of FW_E4200_2.1.39.145204.SSA hardly matches the required .img file extension. Also on the code side: is the way of checking for the file extension completely braindead, or is it just me? Guess what would happen, if the filename would contain less than 4 characters.
It was safe to rename the file and upload the firmware. It didn't brick the thing. There seems to be plenty of people having the same issue. The unit seems to have interesting ports open, nobody knows why. Here are the port scan results:
Starting Nmap 6.25 ( http://nmap.org ) at 2013-08-07 13:47 EEST
Nmap scan report for 192.168.1.1
Host is up (0.0017s latency).
Not shown: 992 closed ports
PORT STATE SERVICE
53/tcp open domain
80/tcp open http
139/tcp open netbios-ssn
443/tcp filtered https
445/tcp open microsoft-ds
8083/tcp open us-srv
49152/tcp open unknown
49153/tcp open unknown
MAC Address: 58:6D:8F:GG:2G:3G (Cisco-Linksys)
Nmap done: 1 IP address (1 host up) scanned in 1.32 seconds
There is a project to get Linux running on Marvell-chipsets also, but the site seems to be down. So, I'm linking the WikiDevi page instead: http://wikidevi.com/wiki/Linksys_E4200_v2
Hopefully that pans out and there will be support for DD-WRT some day.
Upgrading into SplashID password vault version 7 and the security of using one
Wednesday, August 7. 2013
My weapon-of-choice for storing passwords has been SplashID for ages. I cannot even remember which version was the first I installed into my Nokia running a S60 operating system.
Yesterday SplashData went into version 7. I've been wondering what they have been doing, since there has been no minor updates for a year or so. Couple of weeks ago they informed that version 7 is coming out and hang tight to wait it to be released.
For an existing user like me, the news was pretty good. It was a free upgrade! Yes. I could get new stuff without paying anything for it. To tell you the truth, I was mighty sceptical. Their track-record of getting things right is not the best one there is. Back in the days, Elcomsoft did a study about password management software, and SplashID wasn't in the winning side there. It is generally a very bad idea to store everybody's passwords using password "g.;59?^/0n1X*{OQlRwy". Sure it is very difficult to guess, but what would happen if you don't have to guess. All you have to do is get somebody's password vault, and it pops open using that password with a blowfish. The end result is unencrypted SQlite-database.
People at SplashData did listen. They did fix the issues pointed out by those nice white-hat guys. That is a very good display of morale from the company's side. Still today, there are so many corporations who simply laugh at security investigators. For example this is one of the recent ones, the Japanese toilet manufacturer Lixil ignores Trustwave's findings, so there is nothing else to do than go public with the findings.
Fortunately my scepticism (read: pessimism) didn't pan out. I upgraded my Desktop-edition on my Windows, it activated using my existing credentials. iPhone-edition upgraded automatically from the App Store, and also activated after my Desktop-edition was activated. My iPad-edition didn't upgrade automatically, I used the normal iTunes sync and clicked there to install the already existing app into my iPad also. On version 6, there were separate versions for iPhone and iPad, now there is only a single app, which is a much better way to go on user perspective. So, no glitches there. Everything works, WiFi-sync works.
Now they offer an option to sync to cloud. To my mind, that's insanity! It is the popular way of today, but I'd never do that. Ever. The inquisitive minds already are questioning Google and their mobile platform Android about password storage. There is no difference between KeePass or Firefox Sync to mention few of those password storage providers. You'd be handing them all of your most valuable items, your passwords, to store and use. When it comes to Google and Android, they don't encrypt your data, with Apple's iOS you at least have the option of doing so.
My final words to people at SplashData: Keep up the good work!
Handling /var/run with systemd
Tuesday, August 6. 2013
Previously I've studied the init.d replacement systemd.
Update 4th Jun 2017: See the new version
To my surprise, my contraption from the previous article didn't survive a reboot. WTF?! It turned out that in Fedora 19 the /var/run/
is a symlink into /run/
which has been turned into tmpfs. Goddamnit! It literally means, that it is pointless to create /var/run/<the daemon name here>/
with correct permissions in RPM spec-file. Everything will be wiped clean on next reboot anyway.
So, I just had to study the systemd some more.
This is my version 2 (the Unit
and Install
-parts are unchanged):
[Service]
Type=forking
PrivateTmp=yes
User=nobody
Group=nobody
# Run ExecStartPre with root-permissions
PermissionsStartOnly=true
ExecStartPre=-/usr/bin/mkdir /var/run/dhis
ExecStartPre=/usr/bin/chown -R nobody:nobody /var/run/dhis/
# Run ExecStart with User=nobody / Group=nobody
ExecStart=/usr/sbin/dhid -P /var/run/dhis/dhid.pid
PIDFile=/var/run/dhis/dhid.pid
The solution is two-fold. First an ExecStartPre
-directive is required. It allows to run stuff before actually executing the deamon. My first thing to do is create a directory, the minus sign before the command says to ignore any possible errors during creation. The target is mainly to ignore any errors from the fact that creation would fail due to the directory already existing. Anyway, all errors are ignored regardless of the reason.
The second command to run is to make sure that permissions are set correctly for my daemon to create a PID-file into the directory created earlier. That must succeed or there will be no attempt to start the daemon. chown
ing the directory will fail if the directory does not exist, or any other possible reason.
Sounds nice, huh? Initially I couldn't get that working. It was simply due to reason, that the entire Service
-part is run as the user pointed by the User=nobody
and Group=nobody
-directives. That user was intentionally chosen, because it has very limited permission anywhere or anything. Now it cannot create any new directories into/var/run/
. Darn!
This where the solution's 2nd part comes in. Somebody designing the systemd thought about this. Using the PermissionsStartOnly
-directive does the security context switch at the last moment before starting the daemon. This effectively changes the default behavior to allow running Service
-part as root, except for the daemon. Exactly what I was looking for! Now my daemon starts each and every time. Even during boot.
Another thing which I noticed, is that when I edit a systemd service-file, the changes really don't affect before I do a systemctl --system daemon-reload
. It was a big surprise to me, after all in traditional init.d everything was effective immediately.
PS.
Why cronie does not create a PID-file? I had an issue in CentOS where I had not one, but two cron-daemons running at the same time. This is yet another reason to go systemd, it simply works better with ill-behaving deamons like cronie.
QNAP Turbo NAS "Error message volume full"
Monday, August 5. 2013
5 am this morning I woke, because a thing was beeping somewhere. The sound was quite annoying, so I had to investigate. My NAS-box chose to go into error state during regular backup schedule and inform me with this audible alarm, that hard drive was full. Bullshit! I said.
In the front-panel there was a flashing message "Error message volume full". However, the hard drive was far from being full. With the text, I googled into this article about QNAP HDD full. The clue about Network Recycle Bin was helpful. The system information really said, that all of the available hard drive capacity was taken. Majority of the stuff I had there was files in the Network Recycle Bin.
The fix was easy: I reduced the file retention time into half of the previous and clicked "Empty". The box chewed the drives for a couple of minutes and new stats were much better. Also the annoying beep ended.
Falling back to sleep at 5:30 was another thing. No could do. Unfortunately.
How not to behave as a member of software project
Friday, August 2. 2013
This is about how NOT to behave, writing about the opposite, how to behave, is way beyond me. I don't even know that myself. However, during my years in various companies and multitude of software projects, I've met lot of people. Some working quite effectively as members of a software project than others (best-of-the-best, if borrowing a quote from the movie Men in Black is allowed), and then there are the worst-of-the-worst. Today I share a story of such project member.
There is this project where I've been working as a contractor for almost 5 years now. There were some changes in the organization and I thought now would be about the time for me to do something else for a while. I discussed this with management, gave my notice and they started looking for new contractor, whom I promised to train before I leave.
Everything was fine until for my sins they gave me one (if borrowing a quote from the movie Apocalypse Now is allowed).
In the beginning it was pretty standard operations. My manager said, that there would be this new guy and he needed access to source code and ticketing. Pretty soon the new guy contacted me and asked for the credentials. I told him to hang tight so that I'd create a personal LDAP-account for him. I created the account, put in the needed groupings for a software developer -profile and handed them out to him. Nothing fancy there. Nothing that you wouldn't expect to see or do when arriving to a new assignment.
The next day he said something like "his code isn't that wonderful" to a colleague of mine. Naturally my colleague pretty soon told me what had happened. We've been working in the project together for a while and it was pretty normal reaction of him to say that the new guy is dissing your code there. I confronted the new guy and said that "Come on! We're supposed to be working together, why would you dis my work there." He surely knew how to set the initial impression.
A couple of days passed by and my colleague comes to me again: "Did you see, that he posted his LDAP-account username and password to a public bulletin board?" There is so little to do in such a situation, except OMG!! and WTF!! Why would anybody do anything like that. This is yet again one thing way beyond me. Sharing your personal credentials with other people is grounds for termination of employment!
I don't know what's going to happen next. I informed my manager that I absolutely positively won't be working with this guy. He's obviously not qualified for this job and will most likely do more harm than good for the company. However, I've been getting a lot of visitors for my LinkedIn profile lately from his connections. Looks like I've made lot of new fans for my Fan Club. Perhaps the confidentiality agreement doesn't apply to all of us? It is generally a bad idea to blabber about company's internal things with your contacts.
To recap:
- Don't criticize your colleagues' work behind their backs.
- If you absolutely need to criticize somebody's work, do it at him/her.
- Don't share passwords with anybody, they are meant to be kept secret.
- If you really know that a password can be shared, or you have permission to do so, then it's ok. When in doubt, don't do it.
- Don't blabber internal company or customers' issues to your friends.
- If you must do that, make sure you won't be caught doing so. When you get caught and get fired, remember I told you so.
- Take responsibility of everything you say and do. Really, that means about everything.
- This is much easier, when you say and do things people would expect somebody to say and do. If you go beyond the socially acceptable envelope, be prepared to take some heat for it.
- Then again, if you code looks like shit and works like shit, some people will
call it shit. If you cannot quantify the results of your own work, then
you're in shit. It is very unlikely that your work is the best there
is. If you intentionally write code like shit and people call it shit, don't be surprised.
Internet Explorer 11 adventures
Wednesday, July 31. 2013
I've been using a Windows 8.1 preview for a while and being a web developer, I stumbled into couple of noteworthy issues with IE 11. See my previous entry about Win 8.1.
User-Agent string
There are pretty much 2 variants:
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.3; WOW64; Trident/7.0; .NET4.0E; .NET4.0C)
or:
Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
The only way I could get the "like Gecko" -mode enabled on a XHTML 1.0 -site, was from developers tools in the Edge-mode. My site also has a <meta http-equiv="X-UA-Compatible" content="IE=9" /> in it, but removing or adding the tag does not seem to have any effect. I'm guessing, that Edge-mode works out-of-the-box only in HTML 5. The important thing to not here is, that IE 11 declares itself as a IE 7.0, but unlike a "real" IE 7, this has Trident rendering engine 7.0. Also there is declaration of a "real-version" or rv:11.0.
Emulating previous browser versions
Gone. The good thing is that F12 developers tools have been completely re-written, but it is impossible to get the classic standards selection. I found two discussions about that. First is from superuser.com and second from stackoverflow.com.
Microsoft's idea is to go to http://www.modern.ie/en-us/virtualization-tools and use their virtualization service / tools to use a proper old browser. My advice would be: just ignore anybody using the ancient crap. I'd draw the line on IE 9, it still is pretty popular browser, but on my statistics anything older than IE 8 are totally gone.
Getting Zend Framework 1 to detect IE 11 properly
On my projects I have the ZF 1 running. I've been using Browser Capabilies Project's browscap.ini on PHP. It has solid integration into ZF 1. The bad thing is that BCP is not well maintained anymore due to key persons losing interest into maintaining one. Anyway, here is my patch into 5020:
--- php_browscap.ini.orig 2013-07-31 16:20:08.749140271 +0300
+++ php_browscap.ini 2013-07-31 16:24:14.563058655 +0300
@@ -31179,6 +31192,64 @@
Platform="WinNT"
Platform_Version=3.1
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; IE 11.0
+
+[IE 11.0]
+Parent=DefaultProperties
+Comment="IE 11.0"
+Browser="IE"
+Version=11.0
+MajorVer=11
+MinorVer=0
+Beta=true
+Win32=true
+Frames=true
+IFrames=true
+Tables=true
+Cookies=true
+BackgroundSounds=true
+JavaScript=true
+VBScript=true
+JavaApplets=true
+ActiveXControls=true
+CssVersion=3
+
+[Mozilla/*(Windows NT 6.1*64*Trident/7.0; rv:11.0*)]
+Parent=IE 11.0
+Platform="Win7"
+Platform_Version=6.1
+Win32=false
+Win64=true
+
+[Mozilla/*(Windows NT 6.1*Trident/7.0; rv:11.0*)]
+Parent=IE 11.0
+Platform="Win7"
+Platform_Version=6.1
+
+[Mozilla/*(Windows NT 6.2*Trident/7.0; rv:11.0*)]
+Parent=IE 11.0
+Platform="Win8"
+Platform_Version=6.2
+
+[Mozilla/*(Windows NT 6.3*Trident/7.0; rv:11.0*)]
+Parent=IE 11.0
+Platform="Win8.1"
+Platform_Version=6.3
+
+[Mozilla/*(Windows NT 6.3; WOW64*Trident/7.0; rv:11.0*)]
+Parent=IE 11.0
+Platform="Win8.1"
+Platform_Version=6.3
+Win32=false
+Win64=true
+
+[Mozilla/*(Windows NT 6.3; Win64*Trident/7.0; rv:11.0*)]
+Parent=IE 11.0
+Platform="Win8.1"
+Platform_Version=6.3
+Win32=false
+Win64=true
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; IE 10.0
[IE 10.0]
The 2nd glitch is that ZF 1 heavily relies on seeing string "MSIE" in the UserAgent identification to determine, that we're talking about Internet Explorer. IE 11 doesn't state that anymore. It want's to be like Mozilla's Gecko-engine, and happily says so. My patch for ZF 1:
--- library/Zend/Http/UserAgent/AbstractDevice.php.orig 2012-11-16 17:23:41.000000000 +0200
+++ library/Zend/Http/UserAgent/AbstractDevice.php 2013-07-31 13:58:15.422657840 +0300
@@ -512,6 +512,19 @@
} elseif ($product == 'mozilla' && $result['browser_version'] < 5.0) {
// handles the real Mozilla (or old Netscape if version < 5.0)
$result['browser_name'] = 'Netscape';
+ } elseif ($product == 'mozilla' && isset($result['comment']['full']) &&
+ preg_match('#^([^;]+);.+Trident/(.+);\s+rv:(.+)#', $result['comment']['full'], $real)) {
+ // MSIE 10+ in native mode.
+ // In emulation mode, will match MSIE 7.0
+ $result['browser_name'] = "MSIE";
+ $result['browser_engine'] = "MSIE";
+ $result['browser_version'] = $real[3];
+ $result['browser_token'] = 'MSIE ' . $real[3];
+ if (isset($result['others']['full'])) {
+ $result['compatibility_flag'] = $result['others']['full'];
+ unset($result['others']);
+ }
+ $result['device_os_token'] = $real[1];
}
/** windows */
@@ -523,6 +536,8 @@
if (strpos($result['device_os_token'], 'Win') !== false) {
$windows = array(
+ 'Windows NT 6.3' => 'Windows 8.1',
+ 'Windows NT 6.2' => 'Windows 8',
'Windows NT 6.1' => 'Windows 7',
'Windows NT 6.0' => 'Windows Vista',
'Windows NT 5.2' => 'Windows Server 2003',
That makes ZF 1 react alike for IE 11 and all other versions before that. I did test that on IE 8, IE 9, IE 10 and IE 11. Also I confirmed that to function with IE 10 and IE 11 in IE 7 emulator mode.
64-bit process
Normally I run only 64-bit browsers. Google's crappy Chrome won't do that, so I try to stay away from it. Firefox has excellent spin-off project of CyberFox, most IE versions have 64-bit counterparts, Opera has 64-bit version. The thing with 64-bit browsers is that there are a number of exploits for browsers which are tailored to run on 32-bit processes.
Anyway, the story is that on Windows 8 and Windows 8.1 the tile-mode IE is always 64-bit, but desktop-mode is always 32-bit. Ghacks.net has a story about getting IE 10 in Windows 8 to run 64-bit in desktop-mode, but I fail to confirm the results.
On IE 11 I found a setting of "Enable 64-bit processes for Enhanced Protected Mode":
... I don't know how it should affect the browser behaviour. I'm still getting:
The root-process of IE seems to be 64-bit, but anything with a real web-page in it, is always 32-bit on desktop side. Tile-mode looks like this:
So, no avail for me. Any ideas are welcome.