Thursday 2 February 2023

UnifiUSG latest release still has PPPoE Promiscuous issue - Reconnection leaves connection in bad state

Copied from my post on Unifi's community:

Hopefully this will be of some use to people.

========8<=======

Hi all,

Just received latest update of Unifi USG-3P (4.4.57) and it still has the ppp promiscuous reconnect issue.

See my earlier post for how I tracked down the problem:

https://community.ui.com/questions/USG-pppoe-bad-packet-filtering-and-mysterious-Promiscuous-mode-on-reconnect/56283429-70e9-43d2-aad5-d36ca06c75b2

Symptoms:

  • Connecting OK via PPPoE using a VLAN.
  • Connection dropped by provider - as part of periodic maintenance
  • USG succesfully reconnects but then receives spurious packet meant for another device on the provider's network
  • USG kernel ppp acks that and then the connection goes in to an unknown state.

Reason:

  • On reconnect - the VLAN Device that the PPP connects over is Promiscuous and there's a bug in the PPP Kernel driver that does not correctly filter packets.

User Solution:

  • Drop the following file into /etc/ppp/ip-pre-up.d/0001-turn-promisc-off and make it executable:
#!/bin/sh
if [ "$DEVICE" = "" ]
then
	echo "========= 0001-turn-promisc-off: Expecting DEVICE"
	exit 0
fi


if ip link show "$DEVICE" | fgrep -q PROMISC
then
	echo "========= 0001-turn-promisc-off: Clearing PROMISC on $DEVICE"
	ip link set "$DEVICE" promisc off
fi
exit 0

Real Solution

Of course rather than dropping the above file to work around the issue - the real fix is two-fold.

  1. Unifi needs to investigate why Vyatta code is bringing up the interface in promiscuous mode - maybe there is a later version of Vyatta that has this resolved.
  2. Unifi should pull the later kernel release that has the PPP Kernel filtering bug fixed (See https://bugzilla.kernel.org/show_bug.cgi?id=207597 )
========8<=======

Friday 3 July 2020

Linux Touch Screen transformation for Docking and Undocking laptops

I finally decided to fix the touchscreen calibration of my Linux laptop when I dock and undock it.

If you find the touch screen of your laptop is offset after you dock or undock or even change the screen resolution - this might help you.

The laptop is running XUbuntu 19.10 but this should work with any vanilla X install.

You first need to obtain the following:
  • xrandr - if not already installed run: apt install x11-xserver-utils
  • xinput - this can be installed with: apt install xinput 
  • panelName - the name of your laptop's display panel:
    run xrandr and it should be obvious which it is. On my Dell Precision 5510 it is "eDP-1":
eDP-1 connected 2560x1440+5120+0 (normal left inverted right x axis y axis) 346mm x 194mm 

  • touchScreenName - The name of your touch screen:
    Run xinput. On my laptop this shows as "ELAN Touchscreen": 
⎡ Virtual core pointer                     id=2 [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer               id=4 [slave  pointer  (2)]
⎜   ↳ ELAN Touchscreen                         id=12 [slave  pointer  (2)]
⎜   ↳ DLL06E5:01 06CB:7A13 Touchpad            id=13 [slave  pointer  (2)]
⎜   ↳ SEM USB Keyboard Consumer Control        id=16 [slave  pointer  (2)]
⎜   ↳ USB Optical Mouse                        id=18 [slave  pointer  (2)]
⎜   ↳ Realtek RTL2832U reference design        id=22 [slave  pointer  (2)]

Once you have these things then you can edit the panelName and touchScreenName shell variables at the top of the script below and run it from the command line to fix the touch positions on your laptop screen.

It works by calculating:
  • the x and y Transform ratios by dividing the panel's width and height by the overall screen's width and height;
  • the x and y Translations by dividing the panel's x and y offset by the screens width and height;
  • it then sets the Coordinate Transformation Matrix to the following:
| xTransform 0          xTranslation |
| 0          yTransform yTranslation |
| 0          0          1            |
See https://en.wikipedia.org/wiki/Transformation_matrix for further details on Transformation Matrices on Wikipedia.


set-touchscreen-scale.sh:
===========8<===========
#!/bin/sh

# Set the Touch Transformation matrix for Touch Panels based on output of xrandr
#       Assumptions:
#       - Only one touch screen
#       - No Rotation

panelName="eDP-1"
touchScreenName="ELAN Touchscreen"

die() {
        echo "$@"
        exit 1
}

ratio() {
        dividend="$1"
        divisor="$2"
        dps="$3"
        
        echo "scale=$dps; $dividend/$divisor" | bc -q
}

xrandr=`xrandr`

# Eg: Screen 0: minimum 320 x 200, current 7680 x 1440, maximum 16384 x 16384
screenWidth=`echo "$xrandr" | sed -n -e 's/^.*current \([0-9][0-9]*\) x \([0-9][0-9]*\),.*$/\1/p'`
screenHeight=`echo "$xrandr" | sed -n -e 's/^.*current \([0-9][0-9]*\) x \([0-9][0-9]*\),.*$/\2/p'`

# Eg: eDP-1 connected 2560x1440+0+0 (normal left inverted right x axis y axis) 346mm x 194mm
panelWidth=`echo "$xrandr" | sed -n -e 's/^'"$panelName"' connected \([0-9][0-9]*\)x\([0-9][0-9]*\)+\([0-9][0-9]*\)+\([0-9][0-9]*\) .*$/\1/p'`
panelHeight=`echo "$xrandr" | sed -n -e 's/^'"$panelName"' connected \([0-9][0-9]*\)x\([0-9][0-9]*\)+\([0-9][0-9]*\)+\([0-9][0-9]*\) .*$/\2/p'`
panelXOffset=`echo "$xrandr" | sed -n -e 's/^'"$panelName"' connected \([0-9][0-9]*\)x\([0-9][0-9]*\)+\([0-9][0-9]*\)+\([0-9][0-9]*\) .*$/\3/p'`
panelYOffset=`echo "$xrandr" | sed -n -e 's/^'"$panelName"' connected \([0-9][0-9]*\)x\([0-9][0-9]*\)+\([0-9][0-9]*\)+\([0-9][0-9]*\) .*$/\4/p'`

#echo $screenWidth $screenHeight
#echo $panelWidth $panelHeight

[ -z "$screenWidth" -o -z "$screenHeight" -o -z "$panelWidth" -o -z "$panelHeight" -o -z "$panelXOffset" -o -z "$panelYOffset" ]  \
        && die "Missing paramater:" \
                "screenWidth=$screenWidth screenHeight=$screenHeight" \
                "panelWidth=$panelWidth panelHeight=$panelHeight" \
                "panelXOffset=$panelXOffset panelYOffset=$panelYOffset"

xTransform=`ratio $panelWidth $screenWidth 6`
yTransform=`ratio $panelHeight $screenHeight 6`
xTranslate=`ratio $panelXOffset $screenWidth 6`
yTranslate=`ratio $panelYOffset $screenHeight 6`

echo "xinput --set-prop '$touchScreenName' 'Coordinate Transformation Matrix' $xTransform 0 $xTranslate 0 $yTransform $yTranslate 0 0 1"
xinput --set-prop "$touchScreenName" 'Coordinate Transformation Matrix' $xTransform 0 $xTranslate 0 $yTransform $yTranslate 0 0 1
===========8<===========

Sunday 5 January 2020

svn: E220001: Item is not readable

SVN Error
svn: E220001: Item is not readable

Had this error crop up on my home SVN Server (Debian: subversion:1.6.17dfsg-4+deb7u12):
$ svn log nodered/README.txt
Authentication realm: <svn: svn.cregganna.com:3690> Cregganna Source Repository
Password for 'myuserid': *******

svn: E220001: Item is not readable
There's lot of queries about this error on the internet but its very hard to find the real answer. Most answers provide the patch: "Temporarily enable anonymous Read Access".

This is not a proper solution.

The Problem Config

The issue is that the repo is configured with with some form of restricted access that is inconsistent.
~svn/repos/cregganna/conf/svnserve.conf:
[general]
anon-access = read
auth-access = write
password-db = passwd
authz-db = authz
realm = Cregganna Source Repository
[sasl]
use-sasl = true
~svn/repos/cregganna/conf/authz:
[/]
$authenticated = rw
* =

The Fixed Config

The issue is that the svnserve.conf defines Anonymous access for read but it is blocked in the authz. The log query is attempted with anonymous access but this then fails the authz.

The answer is the anon-access in the svnserve.conf for this repo should be changed to none to match the * = entry in the authz that denies anonymous read only access.

Thus:

~svn/repos/cregganna/conf/svnserve.conf:
[general]
anon-access = none
auth-access = write
password-db = passwd
authz-db = authz
realm = Cregganna Source Repository
[sasl]
use-sasl = true

And now we have:

$ svn log nodered/README.txt
Authentication realm: <svn: svn.cregganna.com:3690> Cregganna Source Repository
Password for 'myuserid': *******

------------------------------------------------------------------------
r144 | myuserid | 2020-01-05 10:41:43 +0000 (Sun, 05 Jan 2020) | 3 lines


Test Commit
....

Wednesday 30 October 2019

Xubuntu 19.10 Mesa DRI Intel P530 - glitchy flurry screensaver

I recently upgraded from Xubuntu 17.04 to 19.10 and came across an issue where the flurry screensaver would be very glitchy. It would jump and skip every few seconds giving a very unpleasant experience. Far from the usual psychedelic smoothness that we are all used to.

I tried all sorts of things but eventually came across this reference:
https://wiki.archlinux.org/index.php/intel_graphics#Disable_Vertical_Synchronization_(VSYNC)

Setting my ~/.drirc to:

<driconf>
    <device>
        <application name="Flurry Screensaver" executable="flurry">
          <!--
            Without this flurry screen saver will jump about
            Turn vertical synchronization off:
            -->
          <option name="vblank_mode" value="0"/>
        </application>
    </device>
</driconf> 
As the comment says - this disables vertical synchronization - something to do with using triple buffering on the Intel Driver.

Friday 15 June 2018

SDXC UHS-I card with exfat FS corrupted on Android Orio (8.0)

In case anyone else hits this issue I thought I'd document it here:

Whenever I get a new phone, I buy a new mico-SD Card and transfer all my Pictures, Music and useful stuff from my old card to my new. I have just been hit by rather annoying issue. When I plugged the SDXC card in to my Moto G6 (Orio 8.0.0) it gave corrupt card with the only option be to reformat it.

Turns out that the issue is a 16 bit UTF filename in the file system - something created on my old Galaxy phone with place names in picture filenames.

The exfat (1.2.5-2) driver that I installed on my Linux laptop:
apt install exfat-fuse exfat-utils
would give the following on an fsck:
Jun 15 11:25:30 tonydell mount.exfat: illegal UTF-16 sequence
Jun 15 11:25:30 tonydell mount.exfat: failed to convert name to UTF-8
My guess is, this is the same reason the Android device reports the issue as I guess it uses the same FS driver.

So, the fix is to first find the directory that has the file:

  1. First mount your card on the unix box
  2. Run "find mountdir"
    This will fail with some error message - can't remember exactly but something along the lines of "software abort" or some such. But the key is that it will give you the directory name.
  3. The FS is now disabled on linux so:
    umount the card on linux
  4. Put the card in to a window laptop and navigate to that directory
  5. Windows seems to at least cope with the strange UTF-16 filenames and you can rename all files in the directory that have non-ascii characters in them.
  6. Put the sdcard back in your Linux box and run fsck again.
    It should complete cleanly unless you have other directories with the same issue in which case just repeat the process.
If you don't have a windows box (and why should you) you will need to be more careful on transferring the files across - first checking for UTF-16 filenames.

I think this is a potential issue with Linux exfat FS implementation - rather than failing the FS on UTF-16 convert - they should just report the error and map to "?" or some such. Its bizarre that the directory write completes but the read fails.

See: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=847236



Friday 26 December 2014

XVnc does not present GDM Greeter (Login) after openvpn installed - XDMCP

I thought I'd write this up so that it can help anyone else who hits the same issue.

I have a Xvnc set up on my Debian Wheezy (7) with xinetd serving on ports 5900 and up.

All was working fine until I installed openvpn and set up a tunnel to my other site.

After that, I could connect using vnc but Xvnc would only show the default X background - Xvnc was not connecting to GDM using XDMCP to present the login and complete the Display Manager startup.

After a bit of strace'ing of the gdm3 process - the server for XDMCP UDP port 177 - it became obvious that gdm was having trouble resolving the IP Addresses. It all started working when I added the tunnel's local address in the /etc/hosts.

Here's the important parts of the etc/gdm3/daemon.conf:
[security]
DisallowTCP=false

[xdmcp]
Enable=true
DisplaysPerHost=3

Here's the /etc/xinetd
service Xvnc
{
        type = UNLISTED
        disable = no
        socket_type = stream
        protocol = tcp
        wait = no
        user = nobody
        server = /usr/bin/Xvnc
        server_args = -inetd -desktop Acer -query localhost -depth 24 -cc 3 -once -SecurityTypes=none -x XFIXES -geometry 1280x1024 -geometry 1440x900 -geometry 1024x768 -geometry 2560x1440
        port = 5901
}

And as my host has the following Interfaces:
eth0: 192.168.15.10
lo: 127.0.0.1
tun0: 192.168.88.6

Here is my /etc/hosts:
127.0.0.1       localhost
127.0.1.1       acer.cregganna.com      acer
192.168.15.10   acer.cregganna.com      acer
192.168.88.6    acer.cregganna.com      acer

Tuesday 15 October 2013

Copying music to In Car Entertainment (ICE) system with limited Memory Card capacity

My car has a decent In Car Entertainment (ICE) system but unfortunately the only way of getting music on to the Hard Disc is via a Memory Card with maximum 2Gb capacity.

I therefore have to transfer the music files piece meal. I have therefore written a bit of perl that supports the copying of files but maintains a Tag file of what files have been transferred - ie its a simple mirror program that:

  • Keeps a record of files that already been copied;
  • Restricts the files transferred to those with a given suffix (currently .mp3);
  • Fails carefully when out of space on target directory;
  • Will recopy files that have changed since original copy.
It is designed for my NAS which is an ARM based Linux box with perl installed. Anybody who wishes to use it would need to ensure they have perl installed and change the "#!" header to their perl location.

Usage is (mount/umount will probably have be done as root):

  1. Mount memory card on your linux computer
    Eg: if you're card is /dev/sdb and you have created a directory /tmp/ext, as root:
    mount -t auto /dev/sdb /tmp/ext
  2. Make sure memory card is empty:
    rm -rf /tmp/ext/*
  3. Run perl copy script calling out:
    - The tags file you want to use
    - The Source directory
    - The Target directory on your memory card:
    Eg:
    ./cpto.pl ~/carmusic.tags /home/music /tmp/ext/music
  4. This will either complete fully or will fail with "No space left on device"
  5. Unmount the card on your linux computer:
    umount /tmp/ext
  6. Put memory card in your ICE and copy to Hard Disk selecting Replace files
  7. If step 4 failed with "No space left on device" then repeat from step 1.
The tags file looks like this:
/home/music/la_roux/la_roux/armour_love.mp3^1251554384^C /home/music/la_roux/la_roux/reflections_are_protection.mp3^1251554386^C /home/music/la_roux/la_roux/growing_pains.mp3^1251554686^C /home/music/Green Day/International Superhits/Basket Case.mp3^1235913966^C /home/music/Green Day/International Superhits/Brainstew.mp3^1235914182^C /home/music/Green Day/International Superhits/Geek Stink Breath.mp3^1235914132^C /home/music/Green Day/International Superhits/Good Riddance Time of Your Life.mp3^1235914370^C /home/music/Green Day/International Superhits/Hitchin A Ride.mp3^1235914324^C /home/music/Green Day/International Superhits/JAR Jason Andrew Relva.mp3^1235914098^C /home/music/Green Day/International Superhits/Jaded.mp3^1235914206^.
Note that the file format is:
FromFileName^ModificationTime^Status

Where Status is "." if copy is in progress and "C" is completed copy. Source: cpto.pl

#!/opt/bin/perl

#       This perl script is used to mirro files from one dir to another
#       It keeps a tag file of files that have been copied and the modification time
#       of the source file when copy was done so that copies
#       are not repeated.
#
#       It is designed to fill up a device with files to be copied until its out of space
#       You can then do what you want with the files on the device (eg copy them to another device)
#       clear the device nd run the copy again. The tags file ensures that only as yet uncopied
#       files are placed on the device.
#
#       I wrote this so that I can transfer my music files to my car's enterntainment system using
#       a 2Gb memory card - the maximum card size supported by the ICE.
#
#       Usage:
#       cpto.pl tagFileName /home/music /mnt/extcard/music

#       Author: Tony.Jewell@Cregganna.Com
#       See: http://www.tonyjewell.com/2013/10/copying-music-to-in-car-entertainment.html
#       Disclaimer: I take not responsibility for any damage or other nepharious effects this
#               script will have on your PC - use at yoru own risk.

use strict;
use warnings;
use diagnostics;

use File::stat;
use File::Basename;
use File::Path;

if ( $#ARGV < 2 ) {
        print "Usage: cpto TagFile Source Destination\n";
        exit 1;
}

my @suffixes = ( ".mp3" );
my $buffSize = 8 * 2**10;
my $tagsFile = "${ARGV[0]}";
# tags is keyed by file name and value is date/time of cp from file
my %tags;

sub loadTags {
        # Check that we can write to it
        open (TAGS, ">>${tagsFile}") || die "Unable to open ${tagsFile} for writing: $!";
        close(TAGS);

        if ( -f "${tagsFile}" ) {
                open( my $TAGS, "<${tagsFile}") || die "Unable to open ${tagsFile}: $!";
                while (my $tagLine = <$TAGS>) {
                        chomp $tagLine;
                        my @tag = split('\^', $tagLine);
                        if ($#tag >= 2 && $tag[2] =~ "C") {
                                $tags{$tag[0]} = $tag[1];
                        }
                }
                close(TAGS);
        }
}

# We write a start Copy to make sure there is room to write to the tags file
# This writes a pending line with status "."
sub tagStartCopy {
        my $name = shift;
        my $mtime = shift;
        open (TAGS, "+<${tagsFile}") || die "Unable to open ${tagsFile} for writing: $!";

        # Seek to end
        sysseek(TAGS, 0, 2 ) || die "Unable to seek file $tagsFile: $!";

        my $tagPos = tell(TAGS);
        syswrite(TAGS, "$name^$mtime^.\n");     # Mark as pending

        close(TAGS) || die "Unable to close $tagsFile after writing: $!";

        return $tagPos;
}

# Rewrite the tag line with the completed copy status of "C".
sub tagEndCopy {
        my $tagPos = shift;
        my $name = shift;
        my $mtime = shift;

        open (TAGS, "+<${tagsFile}") || die "Unable to open ${tagsFile} for writing: $!";

        sysseek(TAGS, $tagPos, 0 ) || die "Unable to seek file $tagsFile: $!";
        syswrite(TAGS, "$name^$mtime^C\n");

        close(TAGS) || die "Unable to close $tagsFile after writing: $!";

        $tags{$name} = $mtime;
}

sub chkDirExists {
        my $dir = dirname(shift);

        if (! -d $dir) {
                mkpath($dir) || die "Unable to create Directory: $dir: $!";
        }
}


sub cpFile {
        my $fromName = shift;
        my $toName = shift;

        my($filename, $directories, $suffix) = fileparse($fromName, @suffixes);
        if ( ! $suffix ) {
                return;
        }

        my $from = stat($fromName) || die "Unable to stat $fromName: $!";
        my $tag = $tags{$fromName};

        if ( $tag && $tag >= $from->mtime ) {
                # Already done this one
                return;
        }

        print "$fromName => $toName....";

        &chkDirExists($toName);
        my $tagPos = &tagStartCopy($fromName, $from->mtime);

        open( IN, "< $fromName") || die "Unable to open for Reading: $fromName: $!";
        open( OUT, "> $toName") || die "Unable to open for Writing: $toName: $!";
        binmode(IN);
        binmode(OUT);
        my $buff;
        while (read(IN, $buff, $buffSize)) {
                print OUT $buff;
        }
        close( IN ) || die "Unable to close for Reading: $fromName: $!";
        close( OUT ) || die "Unable to close for Writing: $toName: $!";

        &tagEndCopy($tagPos, $fromName, $from->mtime);

        print "\n";
}

sub cpDir {
        my $fromName = shift;
        my $toName = shift;

        opendir(my $DIR, $fromName) || die "Unable to read directory: $fromName: $!";

        while(my $file = readdir $DIR) {
                if ( ! ($file =~ /^[.]+$/ ) ) {
                        &cp($fromName . '/' . $file, $toName . '/' . $file);
                }
        }

        closedir $DIR;
}

sub cp {
        my $fromName = shift;
        my $toName = shift;

        if (-d $fromName) {
                &cpDir($fromName, $toName);
        } elsif (-f $fromName) {
                &cpFile($fromName, $toName);
        }
}



&loadTags();
&cp($ARGV[1], $ARGV[2]);