Enabling LLDP on ESXi standard vSwitches

I developed this script based on a post by Shanon Olsson and thought it might be helpful for someone:

#!/bin/sh
 
switch=vSwitch0
 
# get the list of ports on the vSwitch
ports=$(vsish -e "ls" "net/portsets/$switch/ports")
 
for p in $ports; do
    # search for the UPLINK flag on the port
    c=$(vsish -e "get" "net/portsets/$switch/ports/${p}status" | grep 'flags:.*UPLINK')
    [ -n "$c" ] && uplinks="$uplinks $p"
done
 
for u in $uplinks; do
    # enable LLDP on all the uplink ports
    vsish -e "set" "net/portsets/$switch/ports/${u}lldp/enable" 1
done

#!/bin/sh switch=vSwitch0 # get the list of ports on the vSwitch ports=$(vsish -e "ls" "net/portsets/$switch/ports") for p in $ports; do # search for the UPLINK flag on the port c=$(vsish -e "get" "net/portsets/$switch/ports/${p}status" | grep 'flags:.*UPLINK') [ -n "$c" ] && uplinks="$uplinks $p" done for u in $uplinks; do # enable LLDP on all the uplink ports vsish -e "set" "net/portsets/$switch/ports/${u}lldp/enable" 1 done

Running FreePBX Node.js services on RHEL 6

This was a bit of a challenge because FreePBX expects certain minimum versions of nodejs, and then tries to build modules that require a C++ version 11 compiler. As usual, tracking down all the info I needed took longer than doing the actual install:

# Get the repo for the C++ compiler and assembler
wget -O /etc/yum.repos.d/slc6-devtoolset.repo http://linuxsoft.cern.ch/cern/devtoolset/slc6-devtoolset.repo
# Install the C++ compiler and assembler
yum -q -y install 'devtoolset-2-gcc-c++' 'devtoolset-2-binutils'
# Ensure the new compiler and assembler are enabled by default
echo 'source scl_source enable devtoolset-2' > /etc/profile.d/devtoolset-2.sh
# Get the repo for Node
wget -qO- https://rpm.nodesource.com/setup_11.x | bash -
# Install Node
yum -q -y install nodejs
# If you've already installed FreePBX 14, you'll need to re-install the UCP module that uses Node
fwconsole ma downloadinstall ucp
# If you've already installed FreePBX 15, you'll need to reinstall the core so the FastAGI server works
fwconsole ma downloadinstall core

# Get the repo for the C++ compiler and assembler wget -O /etc/yum.repos.d/slc6-devtoolset.repo http://linuxsoft.cern.ch/cern/devtoolset/slc6-devtoolset.repo # Install the C++ compiler and assembler yum -q -y install 'devtoolset-2-gcc-c++' 'devtoolset-2-binutils' # Ensure the new compiler and assembler are enabled by default echo 'source scl_source enable devtoolset-2' > /etc/profile.d/devtoolset-2.sh # Get the repo for Node wget -qO- https://rpm.nodesource.com/setup_11.x | bash - # Install Node yum -q -y install nodejs # If you've already installed FreePBX 14, you'll need to re-install the UCP module that uses Node fwconsole ma downloadinstall ucp # If you've already installed FreePBX 15, you'll need to reinstall the core so the FastAGI server works fwconsole ma downloadinstall core

You should be able to confirm everything installed ok like so:

node --version
npm --version
fwconsole pm2 --list

node --version npm --version fwconsole pm2 --list

And you should see something like this:

$ node --version
v11.12.0
$ npm --version
6.7.0
$ fwconsole pm2 --list
+--------------+-------+--------+----------+---------------------+-----+---------+
| Process Name | PID   | Status | Restarts | Uptime              | CPU | Mem     |
+--------------+-------+--------+----------+---------------------+-----+---------+
| core-fastagi | 25667 | online | 1        | 12 hours, 5 minutes | 0%  | 12.09MB |
| ucp          | 25025 | online | 1        | 12 hours, 7 minutes | 0%  | 33.86MB |
+--------------+-------+--------+----------+---------------------+-----+---------+

$ node --version v11.12.0 $ npm --version 6.7.0 $ fwconsole pm2 --list +--------------+-------+--------+----------+---------------------+-----+---------+ | Process Name | PID | Status | Restarts | Uptime | CPU | Mem | +--------------+-------+--------+----------+---------------------+-----+---------+ | core-fastagi | 25667 | online | 1 | 12 hours, 5 minutes | 0% | 12.09MB | | ucp | 25025 | online | 1 | 12 hours, 7 minutes | 0% | 33.86MB | +--------------+-------+--------+----------+---------------------+-----+---------+

Using cookies with cURL in PHP

I wrote this up for Stack Overflow when they were trying out the concept of “Documentation” for all sorts of things. It didn’t work out, but I thought I’d post this somewhere.

cURL can keep cookies received in responses for use with subsequent requests. For simple session cookie handling in memory, this is achieved with a single line of code:

curl_setopt($ch, CURLOPT_COOKIEFILE, "");

In cases where you are required to keep cookies after the cURL handle is destroyed, you can specify the file to store them in:

curl_setopt($ch, CURLOPT_COOKIEJAR, "/tmp/cookies.txt");

Then, when you want to use them again, pass them as the cookie file:

curl_setopt($ch, CURLOPT_COOKIEFILE, "/tmp/cookies.txt");

Remember, though, that these two steps are not necessary unless you need to carry cookies between different cURL handles. For most use cases, setting CURLOPT_COOKIEFILE to the empty string is all you need.


Cookie handling can be used, for example, to retrieve resources from a web site that requires a login. This is typically a two-step procedure. First, POST to the login page.

<?php

# create a cURL handle
$ch  = curl_init();

# set the URL (this could also be passed to curl_init() if desired)
curl_setopt($ch, CURLOPT_URL, "https://www.example.com/login.php");

# set the HTTP method to POST
curl_setopt($ch, CURLOPT_POST, true);

# setting this option to an empty string enables cookie handling
# but does not load cookies from a file
curl_setopt($ch, CURLOPT_COOKIEFILE, "");

# set the values to be sent
curl_setopt($ch, CURLOPT_POSTFIELDS, [
    "username"=>"joe_bloggs",
    "password"=>"$up3r_$3cr3t",
]);

# return the response body
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

# send the request
$result = curl_exec($ch);

The second step (after standard error checking is done) is usually a simple GET request. The important thing is to reuse the existing cURL handle for the second request. This ensures the cookies from the first response will be automatically included in the second request.

# we are not calling curl_init()

# simply change the URL
curl_setopt($ch, CURLOPT_URL, "https://www.example.com/show_me_the_foo.php");

# change the method back to GET
curl_setopt($ch, CURLOPT_HTTPGET, true);

# send the request
$result = curl_exec($ch);

# finished with cURL
curl_close($ch);

# do stuff with $result...

This is only intended as an example of cookie handling. In real life, things are usually more complicated. Often you must perform an initial GET of the login page to pull a login token that needs to be included in your POST. Other sites might block the cURL client based on its User-Agent string, requiring you to change it.

Using cURL in PHP

Basic Usage (GET Requests)

cURL is a tool for transferring data with URL syntax. It support HTTP, FTP, SCP and many others (when using curl >= 7.19.4). Remember, you need to install and enable the cURL extension to use it.

// a little script to check if the cURL extension is loaded or not
if(!extension_loaded("curl")) {
    die("cURL extension not loaded! Quit Now.");
}
 
// Actual script start
 
// create a new cURL resource
// $curl is the handle of the resource
$curl = curl_init();
 
// set the URL and other options
curl_setopt($curl, CURLOPT_URL, "http://www.example.com");
 
// execute and pass the result to browser
curl_exec($curl);
 
// close the cURL resource
curl_close($curl);

// a little script to check if the cURL extension is loaded or not if(!extension_loaded("curl")) { die("cURL extension not loaded! Quit Now."); } // Actual script start // create a new cURL resource // $curl is the handle of the resource $curl = curl_init(); // set the URL and other options curl_setopt($curl, CURLOPT_URL, "http://www.example.com"); // execute and pass the result to browser curl_exec($curl); // close the cURL resource curl_close($curl);

Using Cookies

cURL can keep cookies received in responses for use with subsequent requests. For simple session cookie handling in memory, this is achieved with a single line of code:

curl_setopt($ch, CURLOPT_COOKIEFILE, "");

curl_setopt($ch, CURLOPT_COOKIEFILE, "");

In cases where you are required to keep cookies after the cURL handle is destroyed, you can specify the file to store them in:

curl_setopt($ch, CURLOPT_COOKIEJAR, "/tmp/cookies.txt");

curl_setopt($ch, CURLOPT_COOKIEJAR, "/tmp/cookies.txt");

Then, when you want to use them again, pass them as the cookie file:

curl_setopt($ch, CURLOPT_COOKIEFILE, "/tmp/cookies.txt");

curl_setopt($ch, CURLOPT_COOKIEFILE, "/tmp/cookies.txt");

Remember, though, that these two steps are not necessary unless you need to carry cookies between different cURL handles. For most use cases, setting CURLOPT_COOKIEFILE to the empty string is all you need.


Cookie handling can be used, for example, to retrieve resources from a web site that requires a login. This is typically a two-step procedure. First, POST to the login page.

<?php
 
# create a cURL handle
$ch = curl_init();
 
# set the URL (this could also be passed to curl_init() if desired)
curl_setopt($ch, CURLOPT_URL, "https://www.example.com/login.php");
 
# set the HTTP method to POST
curl_setopt($ch, CURLOPT_POST, true);
 
# setting this option to an empty string enables cookie handling
# but does not load cookies from a file
curl_setopt($ch, CURLOPT_COOKIEFILE, "");
 
# set the values to be sent
curl_setopt($ch, CURLOPT_POSTFIELDS, array(
    "username" => "joe_bloggs",
    "password" => "$up3r_$3cr3t",
));
 
# return the response body
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
 
# send the request
$result = curl_exec($ch);

<?php # create a cURL handle $ch = curl_init(); # set the URL (this could also be passed to curl_init() if desired) curl_setopt($ch, CURLOPT_URL, "https://www.example.com/login.php"); # set the HTTP method to POST curl_setopt($ch, CURLOPT_POST, true); # setting this option to an empty string enables cookie handling # but does not load cookies from a file curl_setopt($ch, CURLOPT_COOKIEFILE, ""); # set the values to be sent curl_setopt($ch, CURLOPT_POSTFIELDS, array( "username" => "joe_bloggs", "password" => "$up3r_$3cr3t", )); # return the response body curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); # send the request $result = curl_exec($ch);

The second step (after standard error checking is done) is usually a simple GET request. The important thing is to reuse the existing cURL handle for the second request. This ensures the cookies from the first response will be automatically included in the second request.

# we are in the same scope, and not calling curl_init()

# simply change the URL
curl_setopt($ch, CURLOPT_URL, "https://www.example.com/show_me_the_foo.php");
 
# change the method back to GET
curl_setopt($ch, CURLOPT_HTTPGET, true);
 
# send the request
$result = curl_exec($ch);
 
# finished with cURL
curl_close($ch);
 
# do stuff with $result...

# we are in the same scope, and not calling curl_init() # simply change the URL curl_setopt($ch, CURLOPT_URL, "https://www.example.com/show_me_the_foo.php"); # change the method back to GET curl_setopt($ch, CURLOPT_HTTPGET, true); # send the request $result = curl_exec($ch); # finished with cURL curl_close($ch); # do stuff with $result...

This is only intended as an example of cookie handling. In real life, things are usually more complicated. Often you must perform an initial GET of the login page to pull a login token that needs to be included in your POST. Other sites might block the cURL client based on its User-Agent string, requiring you to change it.

This content is copied from Stack Overflow Documentation, a beta program which ended in 2017. All content was authored solely by myself. https://web.archive.org/web/20170816194237/https://stackoverflow.com/documentation/php/701/using-curl-in-php#t=201708161942371592047

Implementing DNSSEC on Scientific Linux 6.7

My environment is running BIND in a chroot jail, using the bind-chroot package installed with YUM. This article at DigitalOcean got me started; this documents steps specific to a Scientific Linux (or Centos, RHEL, etc) install.

#change into the zone file directory
cd /var/named/chroot/var/named/
 
#generate a zone signing key
dnssec-keygen -a NSEC3RSASHA1 -b 2048 -n ZONE example.com
 
#generate a key signing key
dnssec-keygen -f KSK -a NSEC3RSASHA1 -b 4096 -n ZONE example.com
 
#append an include to the zone file for both public key files
for key in Kexample*.key; do echo "\$INCLUDE $key" >> db.example.com; done
 
#sign the zone (this needs to be done after each update, and every couple of weeks as well)
dnssec-signzone -A -3 $(head -c 1000 /dev/random | sha1sum | cut -b 1-16) -N INCREMENT -o example.com -f db.example.com.signed db.example.com
 
#make sure bind is looking at the signed zone files
sed -i 's/db.example.com;/db.example.com.signed;/' /var/named/chroot/etc/named.conf
 
#reload bind
rndc reload
 
#these are the DS records that the domain registrar needs
cat dsset-example.com.

#change into the zone file directory cd /var/named/chroot/var/named/ #generate a zone signing key dnssec-keygen -a NSEC3RSASHA1 -b 2048 -n ZONE example.com #generate a key signing key dnssec-keygen -f KSK -a NSEC3RSASHA1 -b 4096 -n ZONE example.com #append an include to the zone file for both public key files for key in Kexample*.key; do echo "\$INCLUDE $key" >> db.example.com; done #sign the zone (this needs to be done after each update, and every couple of weeks as well) dnssec-signzone -A -3 $(head -c 1000 /dev/random | sha1sum | cut -b 1-16) -N INCREMENT -o example.com -f db.example.com.signed db.example.com #make sure bind is looking at the signed zone files sed -i 's/db.example.com;/db.example.com.signed;/' /var/named/chroot/etc/named.conf #reload bind rndc reload #these are the DS records that the domain registrar needs cat dsset-example.com.

Setting up Mac Mail and iPhone for Google mail

I recently had to set up Mac Mail for our company’s Google Apps account (although the same thing likely happens with GMail.) I was seeing strange behaviour which I eventually figured out was due to the weirdness of IMAP and how Google treats labels as folders.

  • deleting a message in Mail would just tag it with a Deleted Items label on the server; it never disappeared from the All Mail folder.
  • Sent messages were tagged with a Sent Messages label and didn’t show up when I went to the Sent Items folder
  • An [Imap]/Drafts label was cluttering things up in Google’s webmail

I pretty quickly figured out that it was just a problem of Mail not knowing what folders on the IMAP server were to be used for a specific function. But it took me a few days to figure out how to give Mail that information.

In Mail, open the [GMail] folder and select the Trash (Bin, Deleted items, etc) mailbox. Once it’s open, go to the Mailbox menu, select Use This Mailbox For, and choose Trash. Repeat this process for [GMail]/Sent Items, [GMail]/Spam, and [GMail]/Drafts. Now you can use the webmail interface to delete the Deleted Items, Sent Messages, and [Imap]/Drafts labels.

A similar problem happens with iPhone when using Exchange ActiveSync instead of IMAP. When you use IMAP, you have an option in your account settings to use Archive or Delete. But with ActiveSync, all deleted messages are archived by default, and stay in the All Mail folder. You can change this behaviour by visiting http://m.google.com/sync where you can change a few settings for each mobile device using ActiveSync, including Delete Email As Trash.

Asterisk voicemail notifications with MP3

I found a lovely script for sending voicemail notifications in MP3 format instead of wav. It’s a bit of a hack, since Asterisk only provides you with an entire, MIME encoded email message as input. Anyway, I improved it somewhat and wanted to share. This version adds call info and an image to the MP3 file, and is more elegant IMHO – e.g. use of pushd/popd or mktemp.
Continue reading “Asterisk voicemail notifications with MP3”

Moving a Subversion repository

From one server to another, no need for file transfers or anything like that. Do this on the new server.

mkdir /foo/bar/new
svnadmin create /foo/bar/new
ssh root@old.host "svnadmin dump /foo/bar/old" | svnadmin load /foo/bar/new

On your working copies you’ll need to say where the new repository location is:

svn switch --relocate https://old.host/svn https://new.host/svn /path/to/working/copy

Change default MySQL password on Ubuntu

When you install the MySQL package on Ubuntu Linux, it does not come with a blank password, as most packages and installations do. The package is set up so you can change the password like so:

sudo dpkg-reconfigure mysql-server-5.1

The top Google hits recommend stopping the service, restarting MySQL with privileges disabled, etc. This is not the way it was meant to be done, according to Ubuntu.

FreePBX hangs at login

Have you ever clicked on your FreePBX link, get prompted for a password, and then sit staring at your browser “connecting to…” your server forever? Restarting Apache doesn’t work, restarting MySQL doesn’t work, even restarting Asterisk doesn’t work. Meanwhile everything else is running just fine, but you need to restart the entire server before FreePBX starts working again.
Continue reading “FreePBX hangs at login”