Asterisk 11 und Sipgate Basic

Für ältere Asterisk-Versionen hat Sipgate in seinen FAQs passende Einträge für die sip.conf aufgeführt. Unter Asterisk 11 hat sich leider die NAT-Behandlung etwas verändert (nat=yes gibt es nicht mehr), deswegen hier meine funktionierende Konfiguration (SIPID durch die Kundennummer und SIPPWD durch das SIP-Passwort ersetzen):

[sipgate-SIPID]
type=friend
insecure=invite
nat=force_rport
username=SIPID
fromuser=SIPID
fromdomain=sipgate.de
secret=SIPPWD
host=sipgate.de
qualify=yes
canreinvite=no
dtmfmode=rfc2833
context=sipgate-in
callbackextension=SIPID
outboundproxy=sipgate.de
trustrpid=yes
sendrpid=no

In der [global]-Section habe ich außerdem

disallow=all
allow=g722
allow=alaw
allow=ulaw

Erläuterungen zu den Einstellungen, die potentiell problematisch sind:

  • nat: wenn hier was anderes steht, werden eingehende Anrufe nicht immer signalisiert. Unter Asterisk 1.8 und früher ging nat=yes.
  • qualify: sendet regelmäßig SIP-Pakete, um in der NAT-Tabelle des Routers zu bleiben. Wenn das nicht aktiviert ist,w erden eingehende Anrufe nicht immer signalisiert.
  • canreinvite: muss deaktiviert sein, weil sonst der UDP-Port für RTP nach der Anrufannahme noch geändert werden kann. Der Router hat den Port dann nicht in seiner NAT-Tabelle und verwirft die Pakete, dementsprechend wird kein Ton übertragen.
  • callbackextension: hiermit spart man sich eine Zeile wie register => SIPID:SIPPWD@sipgate.de/SIPID in der [global]-Sektion. Wichtig: die lokale Extension (das ist der Wert von callbackextension bzw. der nach dem Schrägstrich in der register-Zeile) muss unbedingt gleich der SIPID sein. Wenn er das nicht ist, wird der erste eingehende Anruf nach einer Wartezeit von ca. 30 Minuten oder mehr zwar signalisiert, aber der Anrufer bekommt auch nach dem Annehmen weiterhin das Freizeichen (ein iPhone im Vodafone-Netz zeigte bei mir nach einige Sekunden nach dem Annehmen dann “Anruf fehlgeschlagen” an) und der Angerufene bekommt keinen Ton. Ich hatte ursprünglich nur register => SIPID:SIPPWD@sipgate.de (entspricht callbackextension=s), was auch ging — nur andere Zahlen, z.B. die eigene Telefonnummer, verursachen das Problem.
  • trustrpid: Bei Sipgate-internen Anrufen steht bei eingehenden Anrufen im From-Feld des SIP-Headers nicht immer die Nummer des Anrufers, sondern z.B. dessen Kundennummer. In dem Fall wird die korrekte Nummer im Feld P-Asserted-Identity mitgesendet und mit dieser Option wird sie später ins From-Feld kopiert.
  • sendrpid: Falls man im Dialplan die CONNECTEDLINE-Funktion benutzt, um bei ausgehenden Anrufen Text im Display des Telefons anzuzeigen (und dafür in [global] den Wert sendrpid=pai gesetzt hat), sollte man es für Sipgate hier deaktivieren.

Mit der obigen Konfiguration landen eingehende Sipgate-Anrufe im Dialplan unter SIPID@sipgate-in. Ausgehende Anrufe bekommt man im Dialplan mit

[outgoing]
exten => _0049X.,1,Goto(0${EXTEN:4},1)
exten => _+49X.,1,Goto(0${EXTEN:3},1)
exten => _+XXX.,1,Goto(00${EXTEN:1},1)
exten => _XXX.,1,Set(CALLERID(number)=SIPID)
same => n,Set(CALLERID(name)=49123456789)
same => Dial(SIP/${EXTEN}@sipgate-SIPID,,rWT)

wobei 49123456789 die gewünschte Absenderrufnummer ist, wenn im Sipgate-Account bei Absenderrufnummer “setzt das Endgerät” ausgewählt ist. Für die Standardnummer kann man diese Zeile auch weglassen.

Asterisk: Change number in To header

A long time ago, I wrote about changing the callee ID as seen by the caller using CONNECTEDLINE.
Changing the caller ID as seen by the callee is also pretty obvious using CALLERID.
That leaves two more constellations: changing the caller ID as seen by the caller (which doesn’t make sense because a phone typically doesn’t display its own number on outgoing calls)., and changing the callee ID as seen by the callee, which I’ll talk about here now.

The reason you might want to do this is because you have multiple PSTN phone numbers that ring the same SIP phone. The obvious way to solve this would be to use

exten => _X.,n,SipAddHeader(To: "123456" <sip:123456@server>)
exten => _X.,n,Dial(SIP/${EXTEN})

, but that doesn’t work because SipAddHeader doesn’t overwrite existing headers, it only adds new ones. The Snom forum mentions a hack using the Diversion header, assuming your phone does indeed display that. A much nicer way is the following:

exten => _X.,n,Dial(SIP/${EXTEN}!123456)

. The number after the exclamation mark is simply what Asterisk uses as the local part when it composes the To URI. This features is not well-documented, but from the code I guess it was introduced in Asterisk 1.6. Asterisk 1.8’s (and higher) chan_sip.c gives a short explanation:

 *  SIP Dial string syntax:
 *       SIP/devicename
 *  or   SIP/username@domain (SIP uri)
 * or   SIP/username[:password[:md5secret[:authname[:transport]]]]@host[:port]
 * or   SIP/devicename/extension
 *  or   SIP/devicename/extension/IPorHost
 * or   SIP/username@domain//IPorHost
 * and there is an optional [!dnid] argument you can append to alter the
 *  To: header.

Wifi with WPA/WPA2 mixed mode encryption on Snom phones

When you try to connect a Snom phone to a Wifi network, make sure the network isn’t running in mixed WPA/WPA2 mode. The phone will see the network anyway, but fail to connect at boot. Disabling WPA in favor of WPA2-exclusive operation might be a good idea because WPA’s TKIP encryption isn’t that great and WPA2’s AES is much better. Also, every device sold in the past 8 years supports WPA2, so it’s unlikely you still have anything on your network that doesn’t support it.

Sipura SPA-3000 spontaneous reboots, reason 0x737208f4

I have a 10-year-old Sipura SPA-3000 VoIP phone adapter (SIP to FXS phone) which at some point started rebooting once an hour, even during calls. After enabling remote syslog, I saw that these reboots happen with no prior indication, and after the reboot, I see the following message:

Jun 16 21:15:16 192.0.2.2 logger: <134>System started: ip@192.168.0.101, reboot reason:H737208f4
Jun 16 21:15:16 192.0.2.2 logger: <134>System started: ip@192.168.0.101, reboot reason:H737208f4

These hexadecimal reboot reasons don’t appear to be documented anywhere, the only list I could find appears to refer newer models and doesn’t contain 0x737208f4.

After some trying, I figured out that if I disable DHCP, the reboots don’t happen anymore. My DHCP always assigned the same IP to the device, so I really see no reason why it would have to reboot.

 

CUPS-to-CUPS printing with server-side processing and page_log

Printer sharing on Windows is easy: the client receives the driver from the server, presents the driver GUI and passes on an intermediate format along with the options selected in the driver to the server, which then renders the print job for the printer (usually into PostScript).

In the Unix (Mac OS X in my case, but Linux would be the same) world, CUPS is commonly used for printing. It’s very powerful, but I find the documentation severely lacks details about the exact way something is implemented in the code. Luckily, the code is open-source and Michael Sweet, the developer of CUPS who now works at Apple and still maintains CUPS, managed to create a very structured piece of software with code that’s reasonably easy to understand.

If you just add a CUPS server’s print queue as a new printer on a CUPS client, it will work fine, but you might run into some inconveniences:

Problems

  1. The job might get run through a vendor-supplied filter twice, once on the server and once on the client. This usually works fine, but the print job might significantly increase in size (observed on an HP LaserJet).

  2. The page_log on the server might not contain the number of pages and copies a job consisted of and list 1 for both instead.

  3. The page_log on the server might not contain things like page format, duplex status or attributes you manually added to PrintLogFormat.

Reasons

  1. This happens if the PPD both on the client and on the server contains a line starting with *cupsFilter, which links to a vendor-supplied filter. Such a filter usually produces a MIME type of application/postscript.

  2. This happens if the job does not get run through the pstops filter by CUPS. CUPS bypasses that filter if the client submits the job with a MIME type of application/vnd.cups-postscript, i.e. it was already run through pstops on the client.

  3. This is either caused by the same things as (1) or (2), but I’m not sure which one.

Solution

Simply add the following lines to the PPD on the client. That way, it passes the job straight to the server for server-side processing.

*cupsFilter: "application/pdf 0 -"
*cupsFilter: "image/* 0 -"
*cupsFilter: "application/postscript 0 -"
*cupsFilter: "application/vnd.cups-postscript 0 -"
*cupsFilter: "application/vnd.cups-command 0 -"

By the way, if you use Mac OS X and let the “Add Printer” wizard automatically add a print queue from a remote CUPS server discovered via Bonjour, this is exactly what it does.

Notes

If you append something like %{SelectColor} to your PageLogFormat because that’s the attribute your printer uses to determine whether it should print in color or grayscale and you’d like to log that, please note that the default value (either as specified by the PPD or as specified by you via lpadmin -d printername -d SelectColor=Grayscale or via the CUPS web interface’s “Set Printer Defaults”) will never be written to the page_log. Only deviations from the default value will be logged. The defaults set on the server-side CUPS do not matter here, this is determined by the client-side CUPS.

Per the filter(7) documentation (italic comments were added by me):

Options passed on the command-line typically do not include the default choices the printer’s PPD file. […] use the ppdMarkDefaults [which sets all options to the defaults specified inside the PPD] and cupsMarkOptions [which sets the options to the values specified in the driver GUI] functions in the CUPS library to use the correct mapping, and ppdFindMarkedChoice [which reads from the options array composed from the defaults and the selected options] to get the user-selected choice.

WordPress Plugins

After I recently set up a blog for a friend, I thought I’d post a list of plugins I use on the various WordPress instances I run for various people and myself.

  • Simple Custom CSS. Allows you to add custom CSS to your blog without having to modify theme files. This makes it easy to update themes in the future without breaking your customizations.
  • Include plus Shortcodes Everywhere. This allows you to create a Text Widget that displays a static page from your blog using a tag like [include id="15"].
  • Category Order. Allows you to reorder the list of categories in the sidebar.
  • KB Easy PicasaWeb. Converts Picasa links into embedded photo galleries.
  • WP Events Calendar. Gives you a simple calendar widget into which you can manually enter events.
  • Jetpack. Enables some useful features like infinite scrolling, custom CSS, sharing links, and mobile theme.
  • Akismet. A must-have spam filter if you allow comments on your blog.
  • Contact Form 7 plus Really Simple CAPTCHA. Highly flexible contact form including CAPTCHAs.
  • WP Permalauts. A must-have if you blog in a language that has accented letters or umlauts. It converts those letters to the non-accented ones in permalinks.
  • WP Hide Post. Lets you selectively hide posts from categories, front page, etc. while they remain accessible through other ways and direct links.
  • BackWPup. Does full backups of your WordPress data and database to a tarball on the server or your Dropbox. Can run on a schedule to automate the backups.

A theme that I quite like is Sunspot. You can display the featured image, title and lead text of two posts next to each other and customize how many posts you want per page in total. It also has enough space for widgets in its sidebars and is responsive. The downloadable version does not currently do infinite scrolling, but I believe hosted WordPress.com has such a version.

Calling the parent constructor in PHP 5

Say you write a PHP class that needs to call the parent constructor. At first sight, this is simple:
function __construct()
{
parent::__construct();
}

Say you want to pass some arguments to the parent constructor:
function __construct($arg1, $arg2)
{
parent::__construct($arg1, $arg2);
}

Now what do you do if you have default arguments?
function __construct($arg1 = NULL, $arg2 = NULL)
{
if ($arg1 == NULL && $arg2 == NULL) parent::__construct();
elseif ($arg2 == NULL) parent::__construct($arg1);
else parent::__construct($arg1, $arg2);
}

Not pretty, especially if you have many possible arguments. The obvious generalization would be
function __construct()
{
call_user_func_array(array('parent','__construct'), func_get_args());
}

However, this actually fails for two reasons on PHP below version 5.3: func_get_args() cannot be used as a function argument, and call_user_func_array does not treat parent correctly.
So here’s the entire constructor I ended up with that does absolutely nothing but calling the parent function:
function __construct()
{
$args = func_get_args();
if (version_compare(PHP_VERSION, '5.3.0') >= 0)
{
call_user_func_array(array('parent','__construct'), $args);
}
else
{
$refl = new ReflectionObject($this);
$method = $refl->getParentClass()->getConstructor();
$method->invokeArgs($this, $args);
}
}

Seriously, you have to use reflections for this seemingly simple task?!

VMware ESXi 5.5.0 panics when using Intel AMT VNC

For compatibility with a new guest OS, I upgraded my ESXi  to 5.5 today. During reboot, it crashes after a few seconds (it briefly flashes a message about starting up PCI passthrough on the yellow ESXi boot screen). The purple screen of death (PSOD) I get looks like this:

VMware ESXi 5.5.0 [Releasebuild-1474528 x86_64]
#PF Exception 14 in world 32797:helper1-2 IP 0x4180046f7319 addr 0x410818781760
PTEs:0x10011e023;0x1080d7063;0x0;
cr0=0x8001003d cr2=0x410818781760 cr3=0xb6cd0000 cr4=0x216c
frame=0x41238075dd60 ip=0x4180046f7319 err=0 rflags=0x10206
rax=0x410818781760 rbx=0x41238075deb0 rcx=0x0
rdx=0x0 rbp=0x41238075de50 rsi=0x41238075deb0
rdi=0x1878176 r8=0x0 r9=0x2
r10=0x417fc47b9528 r11=0x41238075df10 r12=0x1878176
r13=0x1878176000 r14=0x41089f07a400 r15=0x6
*PCPU2:32797/heler1-2
PCPU  0: SSSHS
Code start: 0x418004600000 VMK uptime: 0:00:00:05.201
0x41238075de50:[0x4180046f7319]BackMap_Lookup@vmkernel#nover+0x35 stack: 0xffffffff00000000
0x41238075df00:[0x418004669483]IOMMUDoReportFault@vmkernel#nover+0x133 stack: 0x60000010
0x41238075df30:[0x418004669667]IOMMUProcessFaults@vmkernel#nover+0x1f stack:0x0
0x41238075dfd0:[0x418004660f8a]helpFunc@vmkernel#nover+0x6b6 stack: 0x0
0x41238075dff0:[0x418004853372]CpuSched_StartWorld@vmkernel#nover+0xf1 stack:0x0
base fs=0x0 gs=0x418040800000 Kgs=0x0

When rebooting the machine now, it reverts to my previous version, ESXi 5.1-914609.

A bit of playing around revealed: This only happens if I am connected to the Intel AMT VNC server. If I connect after ESXi has booted up, it crashes a fraction of a second after I connect to VNC. Go figure! Apparently it’s not such a good idea to have a VNC server inside the GPU, Intel…

Before I figured this out, I booted up the old ESXi 5.1.0-914609 and even upgraded it to ESXi 5.1.0-1483097.  Looking at dmesg revealed loads of weird errors while connected to the VNC server:

2014-02-13T11:23:15.145Z cpu0:3980)WARNING: IOMMUIntel: 2351: IOMMU Unit #0: R/W=R, Device 00:02.0 Faulting addr = 0x3f9bd6a000 Fault Reason = 0x0c -> Reserved fields set in PTE actively set for Read or Write.
2014-02-13T11:23:15.145Z cpu0:3980)WARNING: IOMMUIntel: 2371: IOMMU context entry dump for 00:02.0 Ctx-Hi = 0x101 Ctx-Lo = 0x10d681003

lspci | grep ’00:02.0 ‘ shows that this is the integrated Intel GPU (which I’m obviously not doing PCI Passthrough on).

So

  • ESXi 5.5 panics when using Intel AMT VNC
  • ESXi 5.1 handles Intel AMT VNC semi-gracefully and only spams the kernel log with dozens of messages per second
  • ESXi 5.0 worked fine (if I remember correctly)

I have no idea what VMware is doing there. From all I can tell, out-of-band management like Intel AMT should be completely invisible to the OS.

Note that this is on a Sandy Bridge generation machine with an Intel C206 chipset and a Xeon E3-1225. The Q67 chipset is almost identical to the C206, so I expect it to occur there as well. Newer chipsets hopefully behave better, perhaps even newer firmware versions help.

Leserbrief “Rentenpaket”

Am 29. Januar 2014 beschloss die Bundesregierung die als “Rentenpaket” bekannte Rentenerhöhung. Unmittelbar darauf präsentierte Arbeitsministerin Andrea Nahles eine Werbekampagne dafür; über die am 30. Januar 2014 in der Süddeutschen Zeitung abgedruckte Werbeanzeige ärgerte ich mich so, dass ich einen Leserbrief zu dem Thema verfasste. Dieser wurde am 06. Februar 2014 abgedruckt:

Nachhaltige Politik ist das nicht 

Die Vorgehensweise der Bundesregierung, einen Tag nach dem Kabinettsbeschluss bereits eine Werbekampagne für das Vorhaben zu starten, ist schockierend. Hier wird das Parlament missachtet, das über die Gesetzesvorlage überhaupt erst noch zu befinden hat, und dem Bürger suggeriert, das Rentenpaket sei bereits beschlossene Sache. Ungeklärte Fragen werden einfach beiseitegewischt. Viel schwerer wiegt jedoch, dass der Bürger mit dieser Kampagne gezielt desinformiert wird und ihm eine komfortable Rente versprochen wird, ohne ihn über die massiven finanziellen und gesellschaftlichen Kosten zu informieren. Deren Großteil werden diejenigen tragen, die heute unter dreißig sind oder erst noch geboren werden; ebendie, die aus der gesetzlichen Rentenversicherung eine negative Rendite erzielen werden. Eine langfristige Umstellung vom Umlage- auf das Kapitaldeckungsverfahren wurde in den jüngsten Rentenreformen nicht einmal angedacht. Nachhaltige Politik sieht anders aus, aber an fehlende Nachhaltigkeit werden wir uns angesichts des zunehmenden Durchschnittsalters der Wähler gewöhnen müssen.

Michael Kuron, Frickenhausen 

Inzwischen ist auch bekannt, dass diese Werbekampagne über eine Million Euro kostet. In dem verlinkten Artikel zitiert die SZ u.a. M. Kurth von den Grünen mit “Dieses Vorgehen ist beispiellos […]”, was ich in meinem Leserbrief ebenfalls geschrieben hatte (wenngleich es der redaktionellen Kürzung zum Opfer gefallen ist). Ebenso beklagt der Artikel, dass www.rentenpaket.de kein Wort über die Kosten verliert.

CUPS on OS X hangs after a few days, reports “Internal Server Error”

If you set up CUPS on an OS X Server (version 10.8.5 in my case, but anything from 10.7 (where CUPS introduced sandboxing) through 10.9 (the current version) should exhibit this behavior), i.e. you enable Printer Sharing in System Preferences and run sudo cupsctl WebInterface=yes, and leave the system running for a few days, you’ll eventually run into the situation that http://localhost:631/printers will report “Internal Server Error”, and clients will no longer be able to print to the server.

Digging around CUPS’ debug log, you’ll see something like
D [27/Oct/2013:13:33:52 +0100] [CGI] sandbox_init failed: /private/tmp/05d735269fa67: No such file or directory (No such file or directory)
D [27/Oct/2013:13:33:52 +0100] PID 78980 (/usr/libexec/cups/cgi-bin/printers.cgi) stopped with status 1.

That missing file (named a different 13-digit hexadecimal name upon each restart) is the CUPS daemon’s sandbox profile.

Digging around further reveals that /var/log/daily.out contains exactly this file name:
Sun Oct 27 03:15:01 CET 2013
Removing old temporary files:
/tmp/05d735269fa67
[...]

All we need to do to prevent this from happening in the future is opening /etc/periodic/daily/110.clean-tmps in your favorite text editor and adding the line printed in bold:
set -f noglob
args="-atime +$daily_clean_tmps_days -mtime +$daily_clean_tmps_days"
args="${args} -ctime +$daily_clean_tmps_days"
args="${args} ! -group _lp ! -user _lp"
dargs="-empty -mtime +$daily_clean_tmps_days"
dargs="${dargs} ! -name .vfs_rsrc_streams_*"

Update February 2014: CUPS 1.7.1 is supposed to fix that issue; the release notes mention my reported bug. Now lets see how long it takes until Apple ships the updated CUPS with an OS X update.

Update March 2014: I just upgraded our server to OS X 10.9.2 and got CUPS 1.7.1 with it. Hooray, less than three months between bug reported and fix deployed. The sandbox profile now gets written to /var/spool/cups/tmp. In fact, that’s exactly what was changed in scheduler/conf.c in the CUPS source code: they added setenv("TMPDIR", TempDir, 1);