Start Cygwin/X to notification area for X-Forwarding

cygwin_x_non-suck
Cygwin/X used to have a nice batch file that started the Cygwin X server without a bash shell, or any other unwanted crap. I’d place a shortcut for it in my “Startup” program group, and life would be good. I could have an X server in the background should I ever need it, and I could ignore it when I didn’t need it. It appears through some act of lunacy this method “has been retired“. There are some suggested alternatives, which from my [limited] review, seemed to suck. So I decided to do the unrecommended thing and start my Cygwin/X server instance as follows (adjust for your installation path):

C:\cygwin\bin\XWin.exe -multiwindow -clipboard -silent-dup-error -dpi 100

This works, and I’m totally happy with it. Shame they had to make an overly complicated process even harder.

Posted in General Nonsense | Leave a comment

Bash Snippet: Friendly MAC Address Names

This article is about adding manufacturer information when displaying MAC addresses in bash script output to create friendlier data for the user. A manufacturer name can suggest more about a device than just the MAC address alone. For example, if you saw a MAC address with an OUI of B8-27-EB it probably wouldn’t mean much to you, but if you saw the name “Raspberry Pi Foundation” you’d have a pretty good clue that the device in question was a Raspberry Pi.

As you may know, MAC address ranges are registered to manufacturers by the IEEE Standards Association. The IEEE-SA provides a web-based look-up form where you can see which OUI is assigned to a vendor, or vice versa. It’s possible for your script to scrap the IEEE-SA’s web look-up resource (in fact I’ve done that in a script to detect and report new Wi-Fi clients on my home network). This is a slow (and not very nice) process when dealing with a larger number of MAC addresses, and so an offline method would be preferable.

The IEEE-SA has a set of data files you could download for this purpose:

http://standards.ieee.org/develop/regauth/oui/oui.txt
http://standards.ieee.org/develop/regauth/iab/iab.txt
http://standards.ieee.org/develop/regauth/oui36/oui36.txt

That method requires occasionally freshening local copies of those files to make sure OUI assignment changes are reflected in the script output.

An alternative option, and the one I’m going to be using is to reference the data in the “manuf” file that Wireshark uses for this same purpose. Wireshark displays ethernet addresses by replacing the vendor/OUI portion of the MAC address with a shortened vendor name, but leaves the unique device portion of the address untouched. Here is an example screen shot taken from Wireshark:

wireshark_macs

You can see that the MAC address 1c:6f:65:95:2b:ad belongs to a device made by Giga-byte and it is talking to 00:07:50:52:86:d1, a device made by Cisco.

If you download Wireshark’s “manuf” file through your package manager, you should receive updates to this list as part of your normal update routines. It is not necessary to download a full copy of Wireshark. Under Ubuntu and probably other Debian-based systems the file is provided by the package libwireshark-data.

apt-get install libwireshark-data

On Ubuntu the manuf file resides in /usr/share/wireshark, but you might need to update the script for your system.

get_line() {
        while read line
        do
                if [ "${line//$1}" != "$line" ]; then
                        echo "$line"
                        break
                fi
        done
}

format_mac() {
        MAC="$1"
        if [ -f "/usr/share/wireshark/manuf" ]; then
                #prefix="$(grep -m1 "${MAC:0:8}" "/usr/share/wireshark/manuf")"
                prefix="$(get_line "${MAC:0:8}" <"/usr/share/wireshark/manuf")"
                prefix="${prefix#*$'\t'}"
                prefix="${prefix%%'#'*}"
                prefix="${prefix%% *}"
                if [ -n "$prefix" ]; then
                        MAC="${prefix}_${MAC: -8}"
                fi
        fi
        echo "$MAC"
}
$ format_mac "00:07:50:52:86:d1"
Cisco_52:86:d1

The above example uses shell built-ins, but if you do not care about the purity of your bash script you could use grep (as shown in the comment) and omit the get_line function from your script for faster results. Notice that this script doesn’t currently parse OUI ranges that are shared across manufacturer’s despite that information being available in the manuf file.

Posted in General Nonsense | Leave a comment

Install Certified Asterisk 13 from source on Ubuntu 14.04 LTS

Need an Asterisk setup? Why not combine the long term support of an Ubuntu LTS release with the long term support of a Certified Asterisk release?

Certified Asterisk releases are supported for around 4 years, and Ubuntu LTS for around 5 years, helping ensure you don’t need to mess around with major reconfiguration again for some time.

We’ll be working with Certified Asterisk 13 and Ubuntu 14.04. Certified Asterisk 13 has an end-of-life date (EOL) of October 24, 2019, and Ubuntu 14.04 has an EOL of April 2019.

A list of Asterisk versions and their end of life dates can be found here:
https://wiki.asterisk.org/wiki/display/AST/Asterisk+Versions

Prerequisites

Let’s start by making sure we are up to date

apt-get update && apt-get -y upgrade

Make sure kernel headers are installed

apt-get -y install linux-headers-$(uname -r)

Grab a sensible build environment along with subversion and git which we will use later to retrieve additional source code

apt-get -y install build-essential subversion git

For many people, the next two sections will be optional, you can probably skip down to the “Asterisk” section below.

DAHDI

On the system I’m working with, I have a Digium T1/E1 PRI card, so I’m going to grab the DAHDI modules and tools as well. You may want to install DAHDI regardless of your hardware for the dahdi_dummy timing driver. At one point the Zaptel dummy driver was used for MeetMe conferences when Digium hardware based timing was absent, although I’m not sure if this still remains the case.

We’ll be building our source under /usr/local/src, so switch in to that directory.

cd /usr/local/src

Download and unpack DAHDI

wget http://downloads.asterisk.org/pub/telephony/dahdi-linux-complete/dahdi-linux-complete-current.tar.gz
tar zxvf dahdi-linux-complete-current.tar.gz

Switch in to the newly created source directory, compile, and install DAHDI.

cd dahdi-linux-complete-2.10.0.1+2.10.0.1/
make all
make install
make config

If you have DAHDI hardware you should see the type of card in the make config output

 Adding system startup for /etc/init.d/dahdi ...
   /etc/rc0.d/K30dahdi -> ../init.d/dahdi
   /etc/rc1.d/K30dahdi -> ../init.d/dahdi
   /etc/rc6.d/K30dahdi -> ../init.d/dahdi
   /etc/rc2.d/S15dahdi -> ../init.d/dahdi
   /etc/rc3.d/S15dahdi -> ../init.d/dahdi
   /etc/rc4.d/S15dahdi -> ../init.d/dahdi
   /etc/rc5.d/S15dahdi -> ../init.d/dahdi
DAHDI has been configured.

List of detected DAHDI devices:

pci:0000:04:02.0     wcte13xp+    d161:800b Wildcard TE132/TE134

run 'dahdi_genconf modules' to load support for only
the DAHDI hardware installed in this system.  By
default support for all DAHDI hardware is loaded at
DAHDI start.

Switch back to /usr/local/src to continue building other packages

cd /usr/local/src

LIBPRI


As I mentioned above I have a PRI card, so I also will be installing libpri, but you can skip this step if it doesn’t apply to you.

wget http://downloads.asterisk.org/pub/telephony/libpri/libpri-1.4-current.tar.gz
tar zxvf libpri-1.4-current.tar.gz
cd libpri-1.4.15/
make
make install
cd ..

Asterisk

OK, finally we can get to building Asterisk. Let’s find the latest certified Asterisk 13 on this page:
http://www.asterisk.org/downloads/asterisk/all-asterisk-versions

At the time of writing it looks like that is 13.1-cert1, so that’s what we’ll use in this example (you may need to adjust these instructions accordingly).

Download the gzip compressed Asterisk tarball.

cd /usr/local/src
wget http://downloads.asterisk.org/pub/telephony/certified-asterisk/certified-asterisk-13.1-current.tar.gz

Decompress and unpack the file

tar zxvf certified-asterisk-13.1-current.tar.gz

Switch in to the newly created source directory

cd certified-asterisk-13.1-cert1/

Add mp3 support

./contrib/scripts/get_mp3_source.sh

Fetch all the prerequisites available in the package repository

 ./contrib/scripts/install_prereq install

If libvpb0 gets installed you may be prompted to type in your country calling code

asterisk13_libvpb0

After installation completes you should see a message indicating success.

#############################################
## install completed successfully
#############################################

There may be additional source code to grab that wasn’t retrieved from the Ubuntu repository. This will potentially install Network Broadcast Sound, libresample, jansson, libsrtp, and pjproject

./contrib/scripts/install_prereq install-unpackaged

Now that the prerequisites should be well covered, let’s configure Asterisk.
Run the configure script

./configure

If everything works out, you should get the ASCII art Asterisk logo

               .$$$$$$$$$$$$$$$=..
            .$7$7..          .7$$7:.
          .$$:.                 ,$7.7
        .$7.     7$$$$           .$$77
     ..$$.       $$$$$            .$$$7
    ..7$   .?.   $$$$$   .?.       7$$$.
   $.$.   .$$$7. $$$$7 .7$$$.      .$$$.
 .777.   .$$$$$$77$$$77$$$$$7.      $$$,
 $$$~      .7$$$$$$$$$$$$$7.       .$$$.
.$$7          .7$$$$$$$7:          ?$$$.
$$$          ?7$$$$$$$$$$I        .$$$7
$$$       .7$$$$$$$$$$$$$$$$      :$$$.
$$$       $$$$$$7$$$$$$$$$$$$    .$$$.
$$$        $$$   7$$$7  .$$$    .$$$.
$$$$             $$$$7         .$$$.
7$$$7            7$$$$        7$$$
 $$$$$                        $$$
  $$$$7.                       $$  (TM)
   $$$$$$$.           .7$$$$$$  $$
     $$$$$$$$$$$$7$$$$$$$$$.$$$$$$
       $$$$$$$$$$$$$$$$.

Ensure the the modules you want are enabled.

make menuconfig

You might want to see if there are any neat things you want. format_mp3 for example, or EXTRA-SOUNDS-EN-GSM might be desirable.

Channel Drivers -> chan_sip
Add-ons -> format_mp3
Extra Sounds Packages -> EXTRA-SOUNDS-EN-GSM

asterisk13_makemenuconfig

N.B.
Recently the Asterisk project started using PJSIP as a replacement for the older chan_sip. If you want or need the classic Asterisk SIP module you’ll have to manually select it.

To use the deprecated chan_sip, unselect the the PJSIP channel driver.

asterisk13_chan_pjsip_default

Next, select the chan_sip driver.
asterisk13_chan_sip

When you are done making any changes “Save & Exit” out of menuconfig.

Now it is time to build Asterisk

make

You should get a message that the build completed successfully.

 +--------- Asterisk Build Complete ---------+
 + Asterisk has successfully been built, and +
 + can be installed by running:              +
 +                                           +
 +                make install               +
 +-------------------------------------------+

So let’s copy the newly built files into the right places on the system

make install

If everything went to plan, you should see a message that the install completed successfully.

 +---- Asterisk Installation Complete -------+
 +                                           +
 +    YOU MUST READ THE SECURITY DOCUMENT    +
 +                                           +
 + Asterisk has successfully been installed. +
 + If you would like to install the sample   +
 + configuration files (overwriting any      +
 + existing config files), run:              +
 +                                           +
 +                make samples               +
 +                                           +
 +-----------------  or ---------------------+
 +                                           +
 + You can go ahead and install the asterisk +
 + program documentation now or later run:   +
 +                                           +
 +               make progdocs               +
 +                                           +
 + **Note** This requires that you have      +
 + doxygen installed on your local system    +
 +-------------------------------------------+

Copy the init startup scripts to make asterisk start on boot

make config
 Adding system startup for /etc/init.d/asterisk ...
   /etc/rc0.d/K91asterisk -> ../init.d/asterisk
   /etc/rc1.d/K91asterisk -> ../init.d/asterisk
   /etc/rc6.d/K91asterisk -> ../init.d/asterisk
   /etc/rc2.d/S50asterisk -> ../init.d/asterisk
   /etc/rc3.d/S50asterisk -> ../init.d/asterisk
   /etc/rc4.d/S50asterisk -> ../init.d/asterisk
   /etc/rc5.d/S50asterisk -> ../init.d/asterisk

And you’re done.

Posted in General Nonsense | Leave a comment

Disable User Lookup Popup in osTicket v1.9.5.1

It appears I’m not the only person using osTicket for internal ticket tracking. The project has come a long way since I started using it, unfortunately most of the advancements are undesirable to my use. The software is geared toward having new tickets represent requests created by or in behalf of a user, rather than a pool of tasks needing assignment to agents. After replacing most of the default department names, groups, help topics, and SLA plans with things more meaningful to my use I was ready to get to work adding tickets. As I was populating tickets I grew increasingly annoyed by the need to fill in my name as the requester for each ticket. This dialog floats over the rest of the page content each time I click New Ticket.

osticket_new_ticket_popup

Coworkers in my department already seemed uninterested in the prospect of using an internal ticket system, so I felt compelled to try and iron out foreseeable gripes about the particular implementation before subjecting them to it.

My fix for this annoyance was a quick edit to the file include/staff/ticket-open.inc.php. At the very end of that file I commented out the original javascript and added some that behaves as if a user was just selected through the popup. The user ID I choose was “6” which corresponds to a new user I created named “Internal Ticket”, but this value will obviously need to be adjusted for your own use.

   <?php
    // Popup user lookup on the initial page load (not post) if we don't have a
    // user selected
    if (!$_POST && !$user) {?>
    /*setTimeout(function() {
      $.userLookup('ajax.php/users/lookup/form', function (user) {
        window.location.href = window.location.href+'&uid='+user.id;
      });
    }, 100); */
    setTimeout(function() {
    window.location.href = window.location.href+'&uid=6';
    }, 100);
    <?php
    } ?>
});
</script>

So now when I click on New Ticket, the “Internal Ticket” user is auto-filled for me.
osticket_new_ticket_autofill

Posted in General Nonsense | Leave a comment

YAC Caller ID Server for Asterisk

I recently upgraded the firmware of the IP phones in a small office using my Grandstream HTTP configuration pusher. One of the users complained that the Caller ID display under the new firmware was too small to be legible. I’m not convinced that the size of the font actually changed, but I wanted to offer some kind of solution. The ever helpful (although often outdated) voip-info.org wiki lists several options for call notifications under asterisk (the PBX in use in the office):

http://www.voip-info.org/wiki/view/Asterisk+call+notification

I liked the look of YAC: Yet Another Caller ID Program, by Jensen Harris the best. It is intended for use with a Caller ID capable modem, but works fine for my purpose as well. YAC has two pieces, a YAC listener, which runs on workstations that want to see incoming Caller ID, and a YAC server which collects Caller ID and sends to the listener(s). I’m using just the listener side and have written my own YAC server portion that collects its information through the Asterisk Management Interface. I used the SiComponents Resource Builder 3 resource editor to replace the yak graphic normally shown in YAC with the office’s logo inside of the yak.exe binary (a fake example is shown below).

yac_sample

Here is my YAC Caller ID server for Asterisk:

#!/bin/bash

extensions=(1100[192.168.1.100] 1101[192.168.1.101] 1102[192.168.1.102])

ami_user="admin"
ami_pass="elastix456"
server="127.0.0.1"
port="5038"

if [ "$1" == "--detach" ] ; then
        $0 >/dev/null &
        exit
fi

exec 3<>/dev/tcp/$server/$port

ami_write() {
        echo "$@" >&3
}

ami_read() {
        read -t1 server_out  <&3
        # strip CR 0x0d line terminator
        server_out="${server_out%$'\x0d'*}"
        echo "$server_out"

}

ami_get_response() {
        while [ 1 ]
        do
                response="$(ami_read)"
                if [ "${response:0:10}" == "Response: " ]; then
                        response="${response:10}"
                        echo "$response"
                        break
                fi
        done
}

ami_logout() {
        if [ -n "$connected" ]; then
                ami_write "Action: Logoff"
                ami_write ""
                if [ "$(ami_get_response)" == "Goodbye" ]; then
                        echo "Logged out."
                fi
        fi
}

trap "ami_logout; exit" EXIT SIGTERM

ami_login() {
        ami_write "Action: Login"
        ami_write "Username: $ami_user"
        ami_write "Secret: $ami_pass"
        ami_write ""
        if [ "$(ami_get_response)" != "Success" ]; then
                echo "Login failed." >&2
                exit
        else
                echo "Logged in."
                connected=1
        fi
}

ami_login

echo "Waiting for calls..."

while [ 1 ];
do
        line="$(ami_read)"

        if [ "${line:0:11}" == "Event: Dial" ]; then
                while [ -n "$line" ]
                do
                        line="$(ami_read)"
                        if [ "${line:0:13}" == "CallerIDNum: " ]; then
                                callerid="~${line:13}"
                        fi
                        if [ "${line:0:14}" == "CallerIDName: " ]; then
                                callerid="${line:14} $callerid"
                        fi
                        if [ "${line:0:12}" == "Dialstring: " ]; then
                                called_extension="${line:12}"
                        fi
                done
        fi

        if [ -n "$called_extension" ] && [ -n "$callerid" ]; then
                for extension in ${extensions[@]}
                do
                        ip="${extension##*'['}"
                        ip="${ip//]/}"
                        extension="${extension%%'['*}"
                        if [ "$extension" == "$called_extension" ]; then
                                echo "New call to $extension from $callerid"
                                exec 4<>/dev/tcp/$ip/10629
                                echo "@CALL$callerid" >&4
                                exec 4>&-
                        fi

                done
                unset called_extension
                unset callerid
        fi
done

exec 3>&-
echo "Quit."

You’ll need to replace the server, port, user and password with the correct information for your AMI setup. The “extensions” variable includes the internal extension and the IP address of the associated desktop/workstation that is running the YAC listener. The format is 1100[192.168.1.100] where 1100 is the extension, and 192.168.1.100 is the This way people see the Caller ID destined for their extension on their desktop. In environments with dynamically assigned desktop IP addresses this will require some additional effort to keep updated. Ideally I’d like to see something like YAC that logs in to a SIP server to monitor calls that way, seems like less to deal with, but many offerings like that included too many other features for my liking (click to call functionality, dial pad, etc).

The server captures SIGTERM and tries to logoff the AMI server before exiting

[root@phone ~]# ./yac-d.sh
Logged in.
Waiting for calls...
New call to 1100 from WIRELESS CALLER ~5551212"
^C
Logged out.

You can start the script into the background by using the –detach switch.

[root@phone ~]# ./yac-d.sh --detach
Posted in Telephony | Tagged , , | Leave a comment