Hi all,

I got tired of configuring my wifi every time I had to move my laptop.
Here's a script a whipped up. It scans the wifi for known networks and
writes the strongest one to /etc/hostname.if. Then it runs netstart.
Easy to use, simple config file, no arguments needed, perfect
for /etc/apm/resume.

Oh, and it uses pledge for good measure.

I hope this is helpful!

Ray



wifind(8)                   System Manager's Manual
wifind(8)

NAME
     wifind – connect to known wifi networks

SYNOPSIS
     wifind

DESCRIPTION
     The wifind utility scans for the strongest recognized wifi networks,
     writes an appropriate hostname.if(5) file, and starts the network with
     /etc/netstart(8).

FILES
     /etc/wifind.conf

EXIT STATUS
     Exits 0 on success, 1 if no network found.

EXAMPLES
     Add the following line to your /etc/apm/resume:

     wifind

SEE ALSO
     hostname.if(5)

HISTORY
     I got really tired of editing hostname.if(5) every time I moved my
     laptop.

AUTHORS
     Ray Lai <r...@raylai.com>

CAVEATS
     Please avoid nwid or wpakey with quotes, dollar signs, or backslashes.

     I'm sorry if you dislike Perl, but it comes stock with OpenBSD.

OpenBSD 6.0                      June 3, 2016                      OpenBSD
6.0

======
wifind
======
#!/usr/bin/env perl
# Written by Ray Lai <r...@raylai.com>.
# Public domain.

use JSON::PP;
use OpenBSD::Pledge;
use strict;
use warnings;

my $ifconfig = '/sbin/ifconfig';
my $tmp = "/etc/wifind.tmp";
my $head = "lladdr random\n" .
    "-chan -bssid -wpakey\n";
my $tail = "dhcp\n";

sub slurp
{
        my $file = shift;
        open F, '<', $file or die "Can't read $file: $!";
        local $/;       # enable slurp mode, locally.
        my $data = <F>;
        close F;
        $data;
}

sub write_hostname_if
{
        my ($if, $ap) = @_;
        my $hostname_if = "/etc/hostname.$if";

        umask 077;
        open TMP, '>', $tmp or die "Unable to open $tmp: $!";

        print TMP $head;
        # set nwid, bssid, chan
        printf TMP 'nwid "%s"', $ap->{nwid};
        printf TMP ' bssid "%s"', $ap->{bssid} if $ap->{bssid};
        printf TMP ' chan "%s"', $ap->{chan} if $ap->{chan};
        print TMP "\n";
        # wpa needs to be set after nwid
        printf TMP "wpakey \"%s\"\n", $ap->{wpakey} if $ap->{wpakey};
        print TMP $tail;
        close TMP;

        rename $hostname_if, "$hostname_if.orig" or die "rename failed: $!";
        rename $tmp, $hostname_if or die "rename failed: $!";

        print STDERR "found $ap->{nwid}, wrote $hostname_if\n";
}

# we only need rpath to read config file
pledge(qw( rpath wpath cpath proc exec )) || die "Unable to pledge: $!";

my $conf = decode_json(slurp '/etc/wifind.conf');
my $wlan = $conf->{wlan};
my $if = $conf->{if};

# initial scan
open L, '-|', $ifconfig, $if, 'scan' or die "Can't open pipe: $!";

pledge(qw( rpath wpath cpath exec )) || die "Unable to pledge: $!";
for (<L>) {
        if (/^\s+nwid (.+) chan (\d+) bssid ([0-9a-f:]+) (-\d+)dBm ([\w-]+)
([\w,-]+)\s*$/) {
                my ($nwid, $chan, $bssid, $dbm, $mystery, $csv) =
                    ($1, $2, $3, $4, $5, $6);
                my %cap = map { $_ => 1 } split(/,/, $csv);

                # remove quotes from nwid, if any
                $nwid =~ s/^"(.*)"$/$1/;

                # reject hostile characters
                if ($nwid =~ /["\\\$]/) {
                        print STDERR "malformed nwid: $nwid\n";
                        next;
                }
                # check for recognized access points
                # i assume we will match the strongest signal first
                for my $ap (@$wlan) {
                        next if $ap->{nwid} ne $nwid ||
                            ($ap->{bssid} && $ap->{bssid} ne $bssid) ||
                            ($ap->{chan} && $ap->{chan} ne $chan) ||
                            ($ap->{wpakey} && !$cap{wpa2});

                        # reject hostile characters
                        if ($ap->{wpakey} =~ /["\\\$]/) {
                                print STDERR "malformed wpakey\n";
                                next;
                        }

                        write_hostname_if $if, $ap;
                        exec '/bin/sh', '/etc/netstart', $if
                            or die "exec failed: $!";
                }
        }
}

print STDERR "no network found\n";
exit 1;


=============
wifind.conf.5
=============
.\"     $OpenBSD$
.\"
.\" Written by Ray Lai <r...@raylai.com>.
.\" Public domain.
.\"
.Dd $Mdocdate$
.Dt WIFIND.CONF 5
.Os
.Sh NAME
.Nm wifind.conf
.Nd wifind configuration file
.Sh SYNOPSIS
.Nm /etc/wifind.conf
.Sh DESCRIPTION
The
.Nm
file contains details of wifi networks to connect to
(for example, nwid, bssid, chan, wpakey).
It also specifies the interface with which to scan and connect.
.Sh EXAMPLES
.Bd -literal -offset indent
{
   "if" : "iwn0",
   "wlan" : [
      {
         "nwid" : "openwireless.org"
      },
      {
         "nwid" : "Corporate Network",
         "bssid" : "f8:03:0d:72:9e:f0",
         "chan" : "1",
         "wpakey" : "j839fzjieJrRjf"
      }
   ]
}
.Ed
.Sh SEE ALSO
.Xr wifind 8
.Sh HISTORY
Ray was really tired of editing
.Xr hostname.if 5
and running
.Xr netstart 8
every time he resumed my laptop.
.Sh AUTHORS
Ray Lai <r...@raylai.com> wrote
.Xr wifind 8 ,
but he did not invent JSON.
.Sh CAVEATS
Please avoid nwid or wpakey with quotes, dollar signs, or backslashes.
.Pp
I'm sorry if you dislike JSON, but it comes stock with Perl.



========
wifind.8
========
.\"     $OpenBSD$
.\"
.\" Written by Ray Lai <r...@raylai.com>.
.\" Public domain.
.\"
.Dd $Mdocdate$
.Dt wifind 8
.Os
.Sh NAME
.Nm wifind
.Nd connect to known wifi networks
.Sh SYNOPSIS
.Nm wifind
.Sh DESCRIPTION
The
.Nm
utility scans for the strongest recognized wifi networks,
writes an appropriate
.Xr hostname.if 5
file,
and starts the network with
.Xr /etc/netstart 8 .
.Sh FILES
.Pa /etc/wifind.conf
.Sh EXIT STATUS
Exits 0 on success, 1 if no network found.
.Sh EXAMPLES
Add the following line to your /etc/apm/resume:
.Pp
wifind
.Sh SEE ALSO
.Xr hostname.if 5
.Sh HISTORY
I got really tired of editing
.Xr hostname.if 5
every time I moved my laptop.
.Sh AUTHORS
Ray Lai <r...@raylai.com>
.Sh CAVEATS
Please avoid nwid or wpakey with quotes, dollar signs, or backslashes.
.Pp
I'm sorry if you dislike Perl, but it comes stock with
.Ox .

Reply via email to