Quick and dirty Powershell + Growl host watch

Needing a quick and dirty growl notification to know when a person restarted their computer, so I wrote up this originally one line script.

. '\libs\growl\Send-Growl 3.1.ps1';	#http://poshcode.org/1464
					#Might need to modify the file a little.

$str = @("down", "up");
$last_ds = $false;
while(1) {
	$new_ds = Test-Connection TargetHost -Quiet -Count 2;
	if($new_ds -ne $last_ds) {
		Send-Growl -Caption "Watchtower" -Message ("TargetHost is {0}" -f $str[$new_ds]);
	$last_ds = $new_ds;
	sleep 5;

Just copy and paste in ISE, modify and away you go!

Bonus points protip: Run in the background.

start-process powershell @("Hidden", "-File" "\path\to\above\script.ps1") -WindowStyle Hidden

poshttpd: PowerShell based scripting for the web

For a while now I’ve wanted to make use of PowerShell to do things like what you would use PHP for with Apache, but nothing I found worked, not even cgi-bin stuff. So I figured, why not just build my own? By using stuff like HttpListener, it’s pretty easy to get started and worry more about what the daemon will do with requests then how to handle the conversations.

Git logs and such can be found here and you can get the code by git cloning http://plan.snoj.us/repo/poshttpd.git

First commit comments

*Two “engines”.
**One passthru for static files like images and html.
**The second is for PowerShell scripts.

To build, you must first edit the rootDir variables in main.cs as well as the BG.prefix (if you desire), run buildntest.ps1. It will build main.cs and start poshttpd.exe.

After it’s built and running, open your brower (default: http://localhost:81) and run your PowerShell script. There is an example script in /sites/.

Hurricane Electric 6in4 Windows startup script

Updates HE public IP records for your tunnel (for instance at the coffee shop), finds the first available interface that is connected and creates a v6v4tunnel using that IP.

See script for where you need to edit.

function fastpingtest {
    $ping = New-Object System.Net.NetworkInformation.Ping;
    $ping.Send("", 1000).status -eq "success";
$endtime = [datetime]::Now.AddMinutes(1);
$mapipv6 = $false; 
while([datetime]::Now -lt $endtime) {
    if(fastpingtest) { $mapipv6 = $true; break; }

if($mapipv6) {
    $wc = New-Object net.webclient;
    $url= "https://ipv4.tunnelbroker.net/ipv4_end.php?ip=AUTO&pass={1}&apikey={0}&tid={2}";

    $wc.DownloadString(($url -f $values));
    #get connected interface
    $interface = netsh interface ipv4 show interface | findstr /c:" connected" | ?{!$_.contains("Loopback");} | %{[regex]::Split($_, "( )+") | ?{$_.trim().length -gt 0} | %{$_.trim()}; }
    $interface_ip = (netsh interface ipv4 show address $interface[0] | findstr /c:"IP Address" | select -First 1).split(":")[1].trim()
    netsh interface teredo set state disabled
    netsh interface ipv6 add v6v4tunnel IP6Tunnel $interface_ip HEIPv4ENDPOINT
    netsh interface ipv6 add address IP6Tunnel YOURIPv6ADDRESS
    netsh interface ipv6 add route ::/0 IP6Tunnel HEIPv6ADDRESS

IPv6 range/subnet calculater for powershell

From what I can tell, there aren’t many…if any, IPv6 address range calculators. While I read it is recommended that you use the entire /64 block, I don’t think it’s always necessary to do so. Besides, what happens when you want to route only a portion of the block to one place?

Example usage:

ipv6range.ps1 2001:470:1f10:60::10 64 | ft ipaddress*
ipv6range.ps1 2003:5:1f:fa0::10 104 | ft ipaddress* #ipv4 /8 equivalent
ipv6range.ps1 2003:5:1f:fa0::10 112 | ft ipaddress* #ipv4 /16 equivalent
ipv6range.ps1 2003:5:1f:fa0::10 120 | ft ipaddress* #ipv4 /24 equivalent
ipv6range.ps1 2003:5:1f:fa0::10 124 | ft ipaddress* #ipv4 /28 equivalent

….and the code….

    [int]$netmask = 64,


if($Addr.AddressFamily -ne 'InterNetworkV6') { throw "`$Addr must be a valid IPv6 address."; }

Create a subnet mask based on a CIDR input.
function subnet {

    if($netmask -gt 128) { throw "`$netmask cannot be greater than 128"; }

    $mask = (@($true) * $netmask) + (@($false) * (128-$netmask));
    return New-Object Collections.BitArray @(,$mask);

Convert a BitArray into a byte array for easy conversion into an IPAddress.
function bit2byte {

    for($i = 0; $i -lt $bitArray.length; $i+=8) {
        [convert]::ToByte([string]::Join("", ([string[]][byte[]]($bitArray[$i..($i+7)]))), 2)

convert an ip into a BitArray for easy bitwise operations.
function ip2bit {

    $b = $addr.GetAddressBytes();
    $bits = @();
    foreach($a in $b) {
        $t = [convert]::ToString($a,2).padleft(8,"0") #[7..0];
        $bits += [string]::join("",$t);
    $nbits = ($bits | %{[char[]]$_} | %{[bool]::Parse("$_".replace("1","true").replace("0","false"))});
    return New-Object collections.bitarray @(,$nbits)

Increment an ipv6 address.
function inc {

    $b = $addr.GetAddressBytes();

    for($i = $b.length-1; $i -ge 0; $i--) {
        if($b[$i] -gt 254) { continue; }
    New-Object net.ipaddress @(,$b);

Decrement an ipv6 address.
function dec {

    $b = $addr.GetAddressBytes();

    for($i = $b.length-1; $i -ge 0; $i--) {
        if($b[$i] -eq 0) { continue; }
    New-Object net.ipaddress @(,$b);

$ipArr = new-object collections.bitarray @(,(ip2bit $Addr.GetAddressBytes()))

$netBits = New-Object collections.bitarray @(,(subnet $netmask))
$hostBits = (New-Object collections.bitarray $netBits).Xor((New-Object collections.bitarray 128, $true)) #.xor((New-Object collections.bitarray 128, $true))

$netId = New-Object net.ipaddress @(, (bit2byte (New-Object collections.bitarray $ipArr).And($netBits)));
$netBcast = New-Object net.ipaddress @(, (bit2byte (New-Object collections.bitarray $ipArr).Or($hostBits)));

$numHosts = [math]::Pow(2, ($hostBits | ?{$_} | measure).count)

if($numHosts -gt 256 -and !$ForceListing.ispresent) {
    #well, if we have more than this, just output the (ipv4 equivalent) network id and broadcast address.
} else {
    Add-Member -PassThru -Force -InputObject $netId -MemberType NoteProperty -Name IsUsable -Value $false;
    try {
        $lastAddr = $netId;
        for($i = 0; $i -lt $numHosts-2; $i ++) {
            $lastAddr = inc $lastAddr
            Add-Member -PassThru -Force -InputObject $lastAddr -MemberType NoteProperty -Name IsUsable -Value $true;
    } catch {}
    Add-Member -PassThru -Force -InputObject $netBcast -MemberType NoteProperty -Name IsUsable -Value $false;


  • Not commented well. RTCFA (read the code for answers)! >:(
  • Only increments despite there being a decrement function.
  • If the number of host addresses is less then 256, it will always display the complete listing.

Favorite .NET library not a 4.0?

Recently I made some configuration changes to Powershell so I could use the latest .Net version (4.0), but it caused errors with a project. The problem turned out to be that the library was trying to load an older version of mscorelib. This is pretty easily fixed thanks to Microsoft packaging a compiler with .NET.

#download your library source and extract if necessary
cd \path\to\source\code

#If your target is x64, use "Framework64" instead
C:\Windows\Microsoft.NET\Framework\v4.0.30319\v4.0.30319\MSBuild.exe .\project.csproj


Now you have a version of your library compiled as a .NET 4.0 DLL. You could of course use Visual Studio to do this, but who would want to deal with it when you’re only a couple commands away?

Powershell: Wake up on Lan 0.3

Nick asked, “This script looks good. Would you mind adding comments to it to describe its logic? Also, it doesn’t appear to like having colons in MAC addresses even though colons is pretty standard. Thanks for sharing your script!” (link).

Well Nick, here you are! I hope it helps!

param (
        Mandatory = $true,
        HelpMessage="Wake up a machine by known mac address.")]
        mandatory = $true,
        HelpMessage="Wake up a machine by last known IP address.")]
    $network = [net.ipaddress]::Broadcast,
    $subnet = [net.ipaddress]::Broadcast

try {
    #Convert -network and -subnet to Net.IPAddress objects if necessary.
    if($network.gettype().equals([string])) {
        $network = [net.ipaddress]::Parse($network);
    if($subnet.gettype().equals([string])) {
        $subnet = [net.ipaddress]::Parse($subnet);
    #find the broadcast address for the -network
    #eg. the broadcast address for the ip is
    $broadcast = new-object net.ipaddress (([system.net.ipaddress]::parse("").address -bxor $subnet.address -bor $network.address))
    #attempt to figure out if the first value is an ip or mac address.
    #if we do this: wol.ps1
    #instead of this: wol.ps1 -targetIP
    try {
        $targetIP = [net.ipaddress]::Parse($targetMac.toupper()).tostring() # | Out-Null;
    } catch {
        try {
            [Net.NetworkInformation.PhysicalAddress]::Parse($targetMac.toupper().replace(".","").replace(":","").replace("-","")) | Out-Null;
        } catch {
    #Find our target mac address.
    #$targetIP isn't set in the above try..catch if it's a mac address.
    if($targetIP) {
        try {
            $nmac = (arp -a $targetIP | ? {$_ -imatch $targetIP}).split(" ") | ? {$_.trim().length -gt 0;} | %{ $_.trim(); };
            $targetMac = $nmac[1];
            throw "IP address is unknown.";
    $mac = [Net.NetworkInformation.PhysicalAddress]::Parse($targetMac.toupper().replace(".","").replace(":","").replace("-",""))
    <#"targetmac: " + $targetMac;
    "targetip: " + $targetip;
    "mac: " + $mac;#>
    #Setup 3 different endpoints for the common WOL ports.
    $u = New-Object net.sockets.udpclient
    $ep = New-Object net.ipendpoint $broadcast, 0
    $ep2 = New-Object net.ipendpoint $broadcast, 7
    $ep3 = New-Object net.ipendpoint $broadcast, 9
    #setup the payload.
    #6 bytes of 255 followed by the target mac 16 times.
    $payload = [byte[]]@(255,255,255,255,255,255);
    $payload += ($mac.GetAddressBytes()*16)
    #send it out a few times.
    for($i = 0; $i -lt 10; $i++) {
        $u.Send($payload, $payload.Length, $ep) | Out-Null
        $u.Send($payload, $payload.Length, $ep2) | Out-Null
        $u.Send($payload, $payload.Length, $ep3) | Out-Null
        "$(date) - WOL payload $($i+1)/10 sent to $targetMac on $broadcast/$subnet" | Write-Debug;
        sleep -Milliseconds 10;
} catch {
    $_ | Write-Error;

SnojNS 0.2: Still has a lame name

After many an hour pouring over the code and running tests galore, I think I’ve resolved some of the major issues from version 0.1. Like how it would just randomly crash when the forward lookup hosts decided they had had enough. Now it’ll recover from it and chug along.

There is now some simple compression. So now instead of having 6 “google.com” entires, we now have 1 with references to that first occurrence. Down the road, I plan on adding better compression so that parts of domains can be compressed. For instance “someSubdomain.josherickson.org” becomes “someSubdomain.{reference to first josherickson.org}”.

Commit comments:

fixed: non-coded types returned empty from outside sources.
fixed: crash when socket was interupted.
added: m attribute to tags. <a m="somehost" ip="" />
added: beginning dns compression...I think. at least it appears to work.
notes: improved xml lookups. now can easily add xpath based lookups.
notes+: might need to improve this further to allow other filter types.
notes: rm attributes will likely wait until xpath fn:matches function is available.


I’ve noticed while using HE’s IPv6 Tunnel Broker service, that I can’t surf IPv6 sites while using snojns. Not sure why this is, but I wonder if there needs to be an IPv6 socket listener as well.


If you’re smart enough to run this, you’ll know which you’ll want to get.

snojns 0.2.0: Release, Debug, Source.

Traceroute with starting TTLs

Tracing stuff with tracert or traceroute you can’t specify a starting TTL. So there will always be routers that show up and waste time.

This code is pretty rudimentary. Hopefully I’ll be able to expand on it to include ipv6 and make it faster.

    $BeginHop = 1,
    $EndHop = 30,
    $timeout = 1000,

$addrtype = [System.Net.Sockets.AddressFamily]::InterNetwork;
if($v6.ispresent) {
    $addrtype = [System.Net.Sockets.AddressFamily]::InterNetworkV6;

$targetIPActual = $null;
if(![net.ipaddress]::TryParse($targetIP, [ref]$targetIPActual)) {
    $target = [net.dns]::GetHostEntry($targetIP);
    $targetIPActual = $target.addresslist | where {$_.addressfamily -eq $addrtype} | select -First 1
} else {
    $target = New-Object psobject -Property @{"HostName" = $targetIP.tostring()}

for($i = $BeginHop; $i -lt $EndHop; $i++) {
    $ping = new-object System.Net.NetworkInformation.ping;
    $pingo = new-object System.Net.NetworkInformation.PingOptions $i, $true;
    $sendbytes = @([byte][char]'a'..[byte][char]'z');
    $pr = $ping.Send($targetIPActual, $timeout, $sendbytes, $pingo);
    try {
        $rtn = New-Object psobject -Property @{
            "IP" = $pr.Address;
            "RoundtripTime" = $pr.RoundtripTime;
            "Status" = $pr.Status;
    } catch {
        $rtn = New-Object psobject -Property @{
            "IP" = "*";
            "RoundtripTime" = $pr.RoundtripTime;
            "Status" = $pr.Status;
    try {
        if($GetHostname.ispresent) {
            Add-Member -InputObject $rtn -MemberType NoteProperty -Name Hostname -Value ([net.dns]::GetHostEntry($pr.Address).hostname)
    } catch{}
    try { 
        if($pr.Address.tostring() -eq $targetIPActual) { break; }
    } catch{}

Its a mnemonic kind of thing, a dns kind of thing

Hosts files are great, you can specify any host to IP combination, overriding anything.

But what about other types of records? Hosts files can’t do service, text, pointer records, etc? So what to do if you want to test these record types? You could setup your own DNS server, create a new zone, add the records to test, while mail, chat, and other services fail left and right on your machine. Or you could use SnojNS.

SnojNS sits between you and your current DNS server. It can add or change domains much like the hosts file, but it can do so much more, like CNAME, PTR, or SRV record types. I’m hoping to add more at later dates, but not to worry, when it comes across a request it doesn’t understand, it just forwards it and relays the info back so you’re never without internet access.

Running it:

Unzip it or compile, edit the hosts.config, open a command prompt, and run. Or if you’re feeling brave, double click to run it and forget about logging any errors that pop up.

sample output of snojns.


Seems to have an issue when there is a lot of requests. That is…it’ll crash. Though the data suggests that it has to do with the forward lookup rejecting udp connections and we can’t yet recover from the error.


If you’re smart enough to run this, you’ll know which you’ll want to get.

snojns 0.1.0: ReleaseDebugSource


  • define a, cname, ptr, and srv resource records
  • forward lookups for undefined domains and unknown resource record types
  • define forward lookups based on requested domain
    • somehost.com can use google’s servers ( while someotherhost.com uses opendns’ (
  • a lot of unused code and commented out sections.

Features Road map:

Not all may happen, but ideas I’d like to explore.

  • config file watch: try reloading the hosts file after a save operation so there’s no need to restart.
  • more record types: like AAAA (ipv6), TXT, and MX.
  • separate dns packet parsing into its own dll
  • create an actual windows service?
  • cache! need that cache.
  • ttl definitions for local records?
  • plugin system to introduce new record types and classes (though who would use anything other than IN?)
  • TCP
  • lookups over ssh: ‘cuz we can’t trust the transit (I’m looking at you Hak5, with your pineapple).
  • load balancing round robins for both answers and forward lookups.



Also, if someone comes up with a better name than “SnojNS” that I like, I’ll buy you $10-15 something from woot.com or amazon as thanks….so thanks! Just post it in the comments or something, as long as I get your email and address.