Custom Squircle Icons!

I edited some squircle-style icons for macOS BigSur (VLC, BBEdit, iTerm, Transmission, Chrome) and I thought I’d post them here in case anyone wants to help make their dock look a little more uniform with everything else.
 
Edit: After some small annoyances, I’ve switched my browser to Firefox and my editor to TextMate — they are better-built apps for macOS! Also added an app icon for Music 🎵
 
Bonus: Dock Spacers!
defaults write com.apple.dock persistent-apps -array-add '{"tile-type"="small-spacer-tile";}' && killall Dock
 

 
 
         
     
     
     
     
     
     
         
 
 
 
 
 
Custom Squircle Icons!

Trying out a modified version of openwrt for my linksys router

So there is modified version of openwrt (called davidc502) that is meant to include a more updated set of wireless drivers for the radios in the linksys wrt32x router. It’s a pretty cool alternative that I’m glad exists which is trying to make the stability and performance better for these devices that are poorly supported by its creators. For example, I recorded the wifi module versions of openwrt vs davidc502 below:
 

# opkg list-installed | grep -i wifi
kmod-mwlwifi - 4.14.195+2019-03-02-31d93860-1
mwlwifi-firmware-88w8864 - 2019-03-02-31d93860-1

# opkg list-installed | grep -i wifi
kmod-mwlwifi - 5.4.42+2020-02-06-a2fd00bb-1
mwlwifi-firmware-88w8864 - 2020-02-06-a2fd00bb-1
mwlwifi-firmware-88w8897 - 2020-02-06-a2fd00bb-1
mwlwifi-firmware-88w8964 - 2020-02-06-a2fd00bb-1

 
However, one thing to note, when I first ran netstat on it I was surprised to see soo many running services listening on all kinds of ports, I had to go through and turn most of them off in the services tab manually:
 

 

Trying out a modified version of openwrt for my linksys router

Trying to block all possible web connections to facebook (with browser extensions)

Update: Firefox has an extension called “REDIRECTOR” and you can enter an extended regex to achieve similar results: https?://[^/]*(fbcdn|facebook)[^/]*\..*

The first extension I always install in Chrome is “uBlock Origin” of course to try and prevent as many wasteful ads as possible but it doesn’t specifically target entire web properties such as all of facebooks sub domains that exist out there (for example, if someone puts a fb image or like button on their site and your browser loads that content, it’s another signal they can use with your information even though I don’t have a fb account).

I found a cool extension for Chrome called “Domain Blocker” which lets you specify wildcard sub domain names in a simple list to block any web requests at the browser level directly (no messy etc/hosts file setups or maintenance needed). For example, you can grab a master list of facebook domain names and place some basic regex in it to produce a nice short list to block automatically:

$ curl -sL 'https://raw.githubusercontent.com/jmdugan/blocklists/master/corporations/facebook/all' | tr '.' ' ' | awk '{ print $(NF-1)"."$NF }' | sort | uniq | awk '{ print $1 ; print "*."$1 }'

facebook.com
*.facebook.com
facebook.de
*.facebook.de
facebook.fr
*.facebook.fr
facebook.net
*.facebook.net
fb.com
*.fb.com
fb.me
*.fb.me
fbcdn.com
*.fbcdn.com
fbcdn.net
*.fbcdn.net
fbsbx.com
*.fbsbx.com
fburl.com
*.fburl.com
foursquare.com
*.foursquare.com
freebasics.com
*.freebasics.com
hootsuite.com
*.hootsuite.com
instagram.com
*.instagram.com
internet.org
*.internet.org
m.me
*.m.me
messenger.com
*.messenger.com
online-metrix.net
*.online-metrix.net
tfbnw.net
*.tfbnw.net
thefacebook.com
*.thefacebook.com
wechat.com
*.wechat.com
whatsapp.com
*.whatsapp.com
whatsapp.net
*.whatsapp.net

This will now produce a blocked message if your browser tries to load any content from any of those domains (links, imgs, scripts, frames, etc.):

www.facebook.com is blocked
Requests to the server have been blocked by an extension.
Try disabling your extensions.
ERR_BLOCKED_BY_CLIENT

Reminder: Also make sure to block third party cookies in Chrome’s settings as well, it will help a lot to keep things clean along the way!

Trying to block all possible web connections to facebook (with browser extensions)

Last piece of relay software needed for my home bridged network

If you are running a bridged/relayd network with macs on it you may need to also forward the multicast broadcasts (mDNS related) that allow the devices to automatically discover each other. On the WRT wifi client side, there is a pkg called avahi-daemon and you can configure to operate in “reflector” mode to forward these broadcasts across the specified interfaces. Running this service along with the dhcprb C program which takes care of layer 2 arp requests & dhcp gateway forwarding has been pretty smooth so far!

74:DA:88:8F:50:00  -47 dBm / -89 dBm (SNR 42)  990 ms ago
	RX: 1300.0 MBit/s, VHT-MCS 9, 80MHz, VHT-NSS 3   6413214 Pkts.
	TX: 1170.0 MBit/s, VHT-MCS 8, 80MHz, VHT-NSS 3   3557598 Pkts.

 2570 root       704 S    ./dhcprb br-wan wlan0
# /etc/avahi/avahi-daemon.conf

[server]
allow-interfaces=br-wan,wlan0
use-ipv4=yes
use-ipv6=no
check-response-ttl=no
use-iff-running=no

[publish]
disable-publishing=yes
publish-addresses=no
publish-hinfo=no
publish-workstation=no
publish-domain=no
publish-resolv-conf-dns-servers=no

[reflector]
enable-reflector=yes
reflect-ipv=no

[rlimits]
#rlimit-as=4194304
rlimit-core=0
rlimit-data=4194304
rlimit-fsize=0
rlimit-nofile=30
rlimit-stack=4194304
rlimit-nproc=3
Last piece of relay software needed for my home bridged network

Final version of relayd functionality written in C (arp & dhcp bridging)

So it took me a while to update & re-write the dhcp relayd functionality that I made in python previously. This new C file can relay & rebroadcast both arp and dhcp packets via raw sockets. For DHCP relaying, it has to be able to insert the bridges IP address into the request so that the server replies back to us and then we can forward it on (so we can run only 1 dhcp server total on the network). The last interface specified in the list is designated as the dhcp server interface to send the requests coming in.

Also tried to reduce the number of system calls made by reading both the arp table proc file and routing table file instead (only 1 sys call to replace host route entries on the bridge router).

It’s been a while since I used select with multiple sockets but this compile uses less memory while running versus the python version, although the py version is easier to read and maintain (depends on your needs).

Source Code: https://github.com/stoops/arprb/blob/master/dhcprb.c?ts=4

I’ll run this for a while and see how it performs!

Jon C

Final version of relayd functionality written in C (arp & dhcp bridging)

Last Part Of The WiFi-AP Bridge Setup (DHCP Relay/Forwarder) in Py

I was having troubles getting dnsmasq to be a simple DHCP relay/forwarder/proxy and I didn’t want to add this into the ARP relay C code to keep that as simple as possible so I wrote this little Python script that will basically bridge 2 interfaces together (one that has DHCP clients on it and one that is connected to the DHCP server [1 main server running for the whole network]).

I stored this in the ARP-relay GIT repo I created prior since it is related to the same bridged setup:
https://github.com/stoops/arprb/blob/master/dhcprb.py?ts=4

An example usage & output from running it so far:

root@OpenWRT:~# python dhcprb.py br-wan wlan0
('00:be:ee:ca:fe:00', '192.168.17.51', '<-->', '00:be:ee:ca:fe:ff', '192.168.16.51')
...
request-> ('0.0.0.0', 68) [304] {wlan0}
<-reply ('192.168.16.1', 67) [300] {br-wan:192.168.16.131}
...
request-> ('0.0.0.0', 68) [300] {wlan0}
<-reply ('192.168.16.1', 67) [300] {br-wan:192.168.16.153}
...

Last Part Of The WiFi-AP Bridge Setup (DHCP Relay/Forwarder) in Py

802.11n -> 802.11ac AP-Client Kick-Off Script (Py)

So I have been running multiple APs with the same SSID on separate channels and frequencies and noticed that the clients are really good at switching from a weak 802.11ac signal strength to the stronger but lower speed 802.11n AP station. This is good, however, they don’t seem to be as aggressive in switching back to 802.11ac once they get closer again (unless they turn off or shutdown or restart their network stack since the 802.11n just gets stronger the closer you get). I found an OpenWRT compatible shell script which kicks clients off a given radio depending on their signal strength to the router. I adjusted it to disconnect a client if they start to get too close to the N router as they are likely going to get a good signal strength from the AC AP instead. You can set the AP deauth time (ex 19 seconds), the time between kicking the same client on/off again (ex 31 mins), and it checks for the signal-to-noise ratio to get above a certain amount (ex 45 SNR) before activating on a client!

python apc.py n 20 40
import os,sys,time

radios = []
mode = sys.argv[1]
secs = (int(sys.argv[2]) * 1000)
macs = {}
band = (int(sys.argv[3]) * 60)

if (mode == "ac"):
	radios = ["wlan0"]

if (mode == "n"):
	radios = ["wlan1"]

while True:
	sec = int(time.time())

	for intf in radios:
		os.system("iwinfo '%s' assoclist | grep 'SNR' | tr '(/)' ' ' | tr -s ' ' > /tmp/apc.log" % (intf))
		f = open("/tmp/apc.log", "r")
		lines = f.readlines()
		f.close()

		for line in lines:
			info = line.strip().split(" ")
			(mac, sig, snr) = (info[0], int(info[1]), abs(int(info[6])))
			print("> %d %d [%s][%s]" % (snr, sig, intf, mac))

			if (secs >= 1000):
				delc = 0 ; kick = "true"
				opts = ("'addr':'%s', 'reason':5, 'deauth':%s, 'ban_time':%s" % (mac, kick, secs))

				if ((mode == "ac") and (sig <= -83)):
					delc = 1

				#if ((mode == "n") and (sig >= -51)):
				#	delc = 1

				if ((mode == "n") and (snr >= 45)):
					delc = 1

				if (delc == 1):
					if (not mac in macs.keys()):
						macs[mac] = 0
					if (sec >= (macs[mac] + band)):
						macs[mac] = sec
						print("* %d %d [%s][%s][%d][%d]" % (macs[mac], sec, mac, intf, sig, snr))
						os.system('ubus call "hostapd.%s" del_client "{%s}"' % (intf, opts))

	for mac in macs.keys():
		if (sec >= (macs[mac] + band)):
			print("x", mac, macs[mac])
			del macs[mac]

	print("")
	time.sleep(9)

802.11n -> 802.11ac AP-Client Kick-Off Script (Py)

Creating a simple relayd replacement in C (compiled for an ARMv7 WRT router)

I’ve been running into different issues with relayd that I tried to manually fix in the framework, for example: not locking host route entries onto a specific interface, better detection for when a host changes interfaces, better arp table & ip routing management, etc.. However, I’ve still been experiencing some flakiness in it’s operation so I made a simple alternative that I can run which duplicates its most essential features needed for layer 2 bridging:

  • Layer 2 server socket to listen for ARP request packets
  • Layer 2 client sockets to send ARP packets with the routers MAC address inserted into the ARP replies for each host and for each bridged interface
  • Layer 3 UDP socket-based pinging for unknown host detection & discovery (auto IP-to-MAC ARP table entry resolution for each bridged interface)
  • Layer 3 IP routing-table host-entry updates related to which bridged interface the client is currently on

The code is just under 300 lines but it seems to be working so far and will keep testing it out to see if it works better than what I was experiencing with relayd!

https://github.com/stoops/arprb/blob/master/arprb.c?ts=4

--
arp req [42] [1544][256] [192.168.17.175][192.168.16.1]
arp reply [wlan0] [00:be:ee:ca:fe:ff][192.168.17.175] <-> [192.168.16.1]
--
arp req [42] [1544][256] [192.168.16.1][192.168.17.175]
arp reply [br-wan] [00:be:ee:ca:fe:00][192.168.16.1] <-> [192.168.17.175]
--
void send_arps(struct intf *relay, char *who_adr, uchar *dst_mac, char *dst_adr) {
	int sock = relay->sock_arp;
	unsigned char *src_mac = relay->mac;
	struct sockaddr ssa = relay->ssa;

	unsigned int psiz = sizeof(struct arp_pkt);
	struct arp_pkt pkt;

	printf("arp reply !! [%s][%s] -> [%s][%s]\n", relay->smac, who_adr, relay->ifn, dst_adr);

	pkt.frame_type = htons(ETH_P_ARP);
	pkt.hw_type    = htons(ETH_HW_TYPE);
	pkt.proto_type = htons(ETH_P_IP);
	pkt.hw_size    = HW_ADDR_LEN;
	pkt.proto_size = IP_ADDR_LEN;
	pkt.op_code    = htons(ARP_OP_REPLY);

	bcopy(src_mac, pkt.sorc_hw, HW_ADDR_LEN); /* src mac */
	bcopy(dst_mac, pkt.dest_hw, HW_ADDR_LEN); /* dst mac */

	bcopy(src_mac, pkt.sndr_hw, HW_ADDR_LEN); /* who mac */
	ipstr(who_adr, pkt.sndr_ip);              /* who ip  */

	bcopy(dst_mac, pkt.rcpt_hw, HW_ADDR_LEN); /* dst mac */
	ipstr(dst_adr, pkt.rcpt_ip);              /* dst ip  */

	sendto(sock, &pkt, psiz, 0, &ssa, sizeof(ssa));
}

Creating a simple relayd replacement in C (compiled for an ARMv7 WRT router)

Following along with the OpenWRT subreddit users

There was a post on a subreddit that I follow (OpenWRT) that was asking for peoples router/network setups and how they are using OpenWRT to accomplish that so I decided to try and make a network diagram of the setup I worked on here at my parents home while I’ve been working remotely (needing stable Internet/WiFi!). There are 2 levels that are covered and the Internet comes into the lower level which then gets sent up via a dedicated 802.11ac radio (separate backchannel). That is then rebroadcasted to the rest of the home with another dedicated, separate 802.11ac AP via the middle relay bridge in between. The relay bridge runs the customized app below that I compiled and it all shares one flat network throughout the home (one /20)! There is also 802.11n sent out for better reach and distance just in case as well 🙂

Edit: You can also add guest networks on each of the radios but with different SSIDs and wlan interfaces which will let them act like wifi-vlans that you can section off with dnsmasq & iptables…

Edit-edit (Updated diagram/layout):

I made this network graph with this site: https://www.lucidchart.com/documents#/dashboard

Historical documentation purposes,
Previous setup with semi-ok results:

Following along with the OpenWRT subreddit users

Turning a small stream cipher (ARC4) into a hash function (ARCH)!

$ python hash.py b b
('fd5f1b4640e0f5cdda0368b67601b9077cbe4a4931a94b52fdf46bf1be0c2bf5', '3a4627878dca5c4daeb243a661b56ebbaa03c268f659b6001cd84911051c103b', 'bb', 2)

$ python hash.py b c
('1181834e637bf3519010de1902889807341cd57a1d2e68a281524d91f2f86cf9', '7deadb485c3d329026d04cefadb4b43a9af19536aaf450052a2edce404f6065f', 'bc', 2)

$ python hash.py c b
('2f4802585ed79a61d25c92a3d7af8fa2a16e2e269e9c6fbd21891e6a7bae15ec', '6a25a3b18a93d966d7c878f9263f053d653618782a9f7918db05b06e0fa27787', 'cb', 2)

$ python hash.py c c
('6683682f501fdaa1c4a95e1ec6b7fb5ff49206af34e1729a17ded27fda355ea4', '7f12dc4dd32e3c9b31d03382b9c9af1efc0ea3ba620ba8e27fa9b9d8ebc1a88b', 'cc', 2)
import os,sys

def swap(s, a, b):
	t = s[a] ; s[a] = s[b] ; s[b] = t
	return s

def init(mesg, leng):
	j = 0 ; skey = []
	for i in range(0, 256):
		skey.append(i)
	for i in range(0, 256+leng):
		k = (i % 256) ; m = (i % leng)
		l = (((i + 1 + ord(mesg[m])) * leng) % 256)
		j = ((j + skey[k] + skey[l]) % 256)
		swap(skey, k, j)
	return skey

def arch(skey):
	i = 0 ; j = 0
	l = 0 ; rnds = 4 ; outp = ""
	for z in range(0, 256*rnds):
		i = ((i + 1) % 256)
		j = ((j + skey[i]) % 256)
		swap(skey, i, j)
	for z in range(0, 32):
		i = ((i + 1) % 256)
		j = ((j + skey[i]) % 256)
		swap(skey, i, j)
		k = ((skey[i] + skey[j] + skey[l]) % 256)
		outp += chr(skey[k])
		l = (l ^ ord(outp[z]))
	return outp

def hmac(mesg, mlen, skey, klen):
	inner_pad = 0x36 ; outer_pad = 0x5C
	block_size = 64 ; ikey = "" ; okey = ""
	tkey = skey ; tlen = klen
	if (klen > block_size):
		zkey = init(skey, klen)
		tkey = arch(zkey)
		tlen = len(tkey)
	for x in range(0, block_size):
		c = 0
		if (x < tlen):
			c = ord(tkey[x])
		ikey += chr(inner_pad ^ c)
		okey += chr(outer_pad ^ c)
	zkey = init(ikey+mesg, block_size+mlen)
	ihsh = arch(zkey)
	ilen = len(ihsh)
	zkey = init(okey+ihsh, block_size+ilen)
	ohsh = arch(zkey)
	return ohsh

def stoh(inpt):
	o = ""
	for c in inpt:
		s = hex(ord(c))[2:]
		if len(s) != 2:
			s = "0" + s
		o += s
	return o

m = sys.argv[1] ; l = len(m)
k = sys.argv[2] ; n = len(k)
z = init(m+k, l+n)
print(stoh(hmac(m, l, k, n)), stoh(arch(z)), m+k, l+n)

Turning a small stream cipher (ARC4) into a hash function (ARCH)!

A simpler improvement to relayd (checking the arp table before expiring)

So instead of running a process heavy static arp broadcaster client/server service, I realized that I could just make relayd a bit smarter in order to properly detect disconnected hosts faster (simply by double checking the arp table). I was also able to compile this software in an Ubuntu VM running in a VirtualBox on OSX for mips & armv7 (archer c7 tplink & wrt1900acs wifi extended setup):

https://github.com/stoops/relayd/compare/master…stoops:moddel

./relayd -I wlan0 -I wlan1 -t 2 -p -1 -B -D -P

With a couple of arp table clean up helper scripts the setup is much simpler with this and less involved in managing the arp table entries!

mode:  ap  |  ssid:  Peppi Place      bmac: 00:be:ee:ca:fe:01  key: psk2+ccmp  |  freq: 2.4GHz  chan:   1  mode:  HT40  |  timeouts: 300 300
mode:  ap  |  ssid:  Peppi Place      bmac: 00:be:ee:ca:fe:11  key: psk2+ccmp  |  freq: 2.4GHz  chan:  11  mode:  HT40  |  timeouts: 300 300
mode:  ap  |  ssid:  Peppi Place      bmac: 00:be:ee:ca:fe:61  key: psk2+ccmp  |  freq: 5.0GHz  chan: 161  mode: VHT80  |  timeouts: 300 300
mode:  ap  |  ssid:  Peppi Place AC   bmac: 00:be:ee:ca:fe:63  key: psk2+ccmp  |  freq: 5.0GHz  chan: 161  mode: VHT80  |  timeouts: 300 300

A simpler improvement to relayd (checking the arp table before expiring)

GIT Rebase with HEAD Conflicts (Auto Accept & Merge the Changes)

I have a bad habit of using git amends (vs commit & squash)
git commit -a --amend --no-edit
but this can cause some future issues when force pulling in the new changes (for example to another branch possibly). I learnt a new way when rebasing to auto accept all of the head changes listed as a conflict:

git checkout --conflict=merge . ; git checkout --ours . ; git add .

GIT Rebase with HEAD Conflicts (Auto Accept & Merge the Changes)

Turning the sdbm hash method into an hmac version

Some small hash loop tweaks and I increased the number of hash rounds from 3 to 4 also:

import os,sys

def tt(ll):
	return (ll & 0xffffffff)

def sdbm(inpt, leng):
	hshs = 0
	for x in range(0, leng):
		hshs = tt(ord(inpt[x]) + tt(hshs << 6) + tt(hshs << 16) - hshs)
	return hshs

def sdbm_hash(inpt, leng):
	mixs = [1, 6, 16, 13, 33, 27, 67, 55, 123]
	hshs = [0, 0, 0, 0, 0, 0, 0, 0, 0]
	more = 0
	mlen = len(hshs) ; rnds = (4 * mlen)
	for x in range(0, mlen+leng):
		hshs[0] = tt(mixs[x%mlen] + ord(inpt[x%leng]) + (hshs[0] << 6) + (hshs[0] << 16) - hshs[0])
		more = (more ^ (hshs[0] >> 16))
		i = ((x % (mlen - 1)) + 1)
		less = ((hshs[i] & 0xffff0000) ^ ((hshs[i] & 0xffff) << 16))
		hshs[i] = (less ^ more)
	for z in range(0, rnds):
		hshs[0] = tt(z + more + (hshs[0] << 6) + (hshs[0] << 16) - hshs[0])
		more = (more ^ (hshs[mlen-1] >> 16))
		for y in range(mlen-1, 0, -1):
			hshs[y] = tt((hshs[y] << 16) | (hshs[y-1] >> 16))
			hshs[y-1] = (hshs[y-1] & 0xffff)
	o = ""
	for h in hshs[1:]:
		for x in range(3, -1, -1):
			o += chr((h >> (x * 8)) & 0xff)
	return o

def sdbm_hmac(mesg, mlen, skey, klen):
	inner_pad = 0x36 ; outer_pad = 0x5C
	block_size = 64 ; ikey = "" ; okey = ""
	tkey = skey ; tlen = klen
	if (klen > block_size):
		tkey = sdbm_hash(skey, klen)
		tlen = len(tkey)
	for x in range(0, block_size):
		c = 0
		if (x < tlen):
			c = ord(tkey[x])
		ikey += chr(inner_pad ^ c)
		okey += chr(outer_pad ^ c)
	ihsh = sdbm_hash(ikey+mesg, block_size+mlen)
	ilen = len(ihsh)
	ohsh = sdbm_hash(okey+ihsh, block_size+ilen)
	return ohsh

def stoh(s):
	return "".join([hex(ord(c))[2:].rjust(2, '0') for c in s])

m = sys.argv[1] ; l = len(m)
k = sys.argv[2] ; n = len(k)
#print(stoh(sdbm_hash(m, l)), sdbm(m, l), m, l)
print(stoh(sdbm_hmac(m, l, k, n)), sdbm(m, l), m, l, sdbm(k, n), k, n)

$ for x in b c ; do for y in b c ; do python hash.py "$x" "$y" ; echo ; done ; done
('d805c892902cf6ea0c98d1946110a61334a9a1158b430fb7d1c5ba7afb29147d', 98, 'b', 1, 98, 'b', 1)

('6eb38871cc3679cb533f1daeee4ed87ab4f154f953e5ea96d508bda6bb054abd', 98, 'b', 1, 99, 'c', 1)

('0d034f1f7627492fd57bd92a63a8a4f2d977f02c2fdf29b4e49f4b3b21a9e738', 99, 'c', 1, 98, 'b', 1)

('09b2678c7ce46cd7cd112b4a2b6fd05d50c858fe0460d29264c4ea01595968db', 99, 'c', 1, 99, 'c', 1)


$ ./hash "this is a test" "b"
[6b18600ee98449472dd377755dd67cd436c9c143cfc893c9a2181e0567d16cf1] [1655286693] [this is a test] [14] [98] [b] [1]

$ ./hash "this is a test" "c"
[bd3bc1a983e35311e5ea60db5ae8cd28a821386937dfd480eccff95fab8356b9] [1655286693] [this is a test] [14] [99] [c] [1]

$ ./hash "this is a tesu" "b"
[8cddc8b9f5a1a1adf41c78b035bf59b444431e772b9c39824e2cf67e2837d9b0] [1655286694] [this is a tesu] [14] [98] [b] [1]

$ ./hash "this is a tesu" "c"
[2554d7d9ecb47d36b7f62d5e4432a7983490aca1229a91331c16b81567c4edff] [1655286694] [this is a tesu] [14] [99] [c] [1]
#include <stdio.h>
#include <string.h>

unsigned int sdbm(char *inpt, int leng) {
	unsigned int hshs = 0;
	for (int x = 0; x < leng; ++x) {
		hshs = (inpt[x] + (hshs << 6) + (hshs << 16) - hshs);
	}
	return hshs;
}

void sdbm_hash(unsigned char *outp, unsigned char *inpt, int leng) {
	unsigned int mixs[] = {1, 6, 16, 13, 33, 27, 67, 55, 123};
	unsigned int hshs[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
	unsigned int less, more = 0;
	int i, mlen = 9, rnds = (4 * mlen);
	for (int x = 0; x < (mlen+leng); ++x) {
		hshs[0] = (mixs[x%mlen] + inpt[x%leng] + (hshs[0] << 6) + (hshs[0] << 16) - hshs[0]);
		more = (more ^ (hshs[0] >> 16));
		i = ((x % (mlen - 1)) + 1);
		less = ((hshs[i] & 0xffff0000) ^ ((hshs[i] & 0xffff) << 16));
		hshs[i] = (less ^ more);
	}
	for (int z = 0; z < rnds; ++z) {
		hshs[0] = (z + more + (hshs[0] << 6) + (hshs[0] << 16) - hshs[0]);
		more = (more ^ (hshs[mlen-1] >> 16));
		for (int y = mlen-1; y > 0; --y) {
			hshs[y] = ((hshs[y] << 16) | (hshs[y-1] >> 16));
			hshs[y-1] = (hshs[y-1] & 0xffff);
		}
	}
	for (int x = 1, y = 0; x < mlen; ++x) {
		for (int z = 3; z > -1; --z, ++y) { 
			outp[y] = ((hshs[x] >> (z * 8)) & 0xff);
		}
	}
}

void sdbm_hmac(unsigned char *outp, unsigned char *mesg, int mlen, unsigned char *skey, int klen) {
	int block_size = 64, hash_size = 32;
	unsigned char inner_pad = 0x36, outer_pad = 0x5C;
	unsigned char ikey[block_size], okey[block_size], ihsh[hash_size], thsh[hash_size];
	unsigned char buff[block_size+mlen+hash_size];
	unsigned char *tkey = skey; int tlen = klen;
	if (klen > block_size) {
		sdbm_hash(thsh, skey, klen);
		tkey = thsh; tlen = hash_size;
	}
	for (int x = 0; x < block_size; ++x) {
		unsigned char padc = 0;
		if (x < tlen) { padc = tkey[x]; }
		ikey[x] = (inner_pad ^ padc);
		okey[x] = (outer_pad ^ padc);
	}
	bcopy(ikey, buff, block_size);
	bcopy(mesg, buff+block_size, mlen);
	sdbm_hash(ihsh, buff, block_size+mlen);
	bcopy(okey, buff, block_size);
	bcopy(ihsh, buff+block_size, hash_size);
	sdbm_hash(outp, buff, block_size+hash_size);
}

void stoh(char *outp, unsigned char *inpt) {
	char *hexs = "0123456789abcdef";
	for (int x = 0, y = 0; x < 32; ++x) {
		outp[y] = hexs[(inpt[x] >> 4) & 0xf]; ++y;
		outp[y] = hexs[inpt[x] & 0xf]; ++y;
	}
}

int main(int argc, char *argv[]) {
	char *m = argv[1]; int l = strlen(m);
	char *k = argv[2]; int n = strlen(k);
	unsigned char h[32]; char o[65]; bzero(o, 65);
	sdbm_hmac(h, (unsigned char *)m, l, (unsigned char *)k, n); stoh(o, h);
	printf("[%s] [%u] [%s] [%d] [%u] [%s] [%d]\n", o, sdbm(m, l), m, l, sdbm(k, n), k, n);
	return 0;
}

Turning the sdbm hash method into an hmac version

Experiment – Turning the SDBM mixing algorithm into a hash function

From this page: http://www.cse.yorku.ca/~oz/hash.html

import os,sys

def tt(ll):
	return (ll & 0xffffffff)

def sdbm(inpt, leng):
	hshs = 0
	for x in range(0, leng):
		hshs = tt(ord(inpt[x]) + tt(hshs << 6) + tt(hshs << 16) - hshs)
	return hshs

def sdbm_hash(inpt, leng):
	mixs = [1, 6, 16, 13, 33, 27, 67, 55, 123]
	hshs = [0, 0, 0, 0, 0, 0, 0, 0, 0]
	more = 0
	rnds = len(hshs)
	for z in range(0, rnds*3):
		hshs[0] = tt((hshs[0] + mixs[z%rnds]) * mixs[z%rnds])
		for x in range(0, leng):
			hshs[0] = (hshs[0] & 0xffff)
			hshs[0] = tt(ord(inpt[x]) + (hshs[0] << 6) + (hshs[0] << 16) - hshs[0])
			more = (more ^ (hshs[rnds-1] >> 16))
			for y in range(rnds-1, 0, -1):
				hshs[y] = tt((hshs[y] << 16) | (hshs[y-1] >> 16))
				hshs[y-1] = (hshs[y-1] & 0xffff)
			hshs[0] = (hshs[0] ^ more)
	o = ""
	for h in hshs[1:]:
		for x in range(3, -1, -1):
			o += chr((h>>(x*8))&0xff)
	return o

def stoh(s):
	return "".join([hex(ord(c))[2:].rjust(2, '0') for c in s])

m = sys.argv[1] ; l = len(m)
print(stoh(sdbm_hash(m, l)), sdbm(m, l), m, l)

$ python hash.py "b" 
('197f907989061db579beba252025bfbf7f4848a47da0e5a9bc8eb73c6fdb8904', 98, 'b', 1)

$ python hash.py "c" 
('f39b31f66506067376f8f88f620e731cd4292a6aeb71da43d297fffc3f5f92c4', 99, 'c', 1)

$ python hash.py "bb" 
('d427d6ba1edaabab2ba3c6ddd70ccf3d0ceff23fcd6de3d2c0af7d0ac95dd62d', 6428800, 'bb', 2)

$ python hash.py "bc" 
('4bfdd409d3de82913ba7405894f444d8858a539abe98e312d64474abf6b68e3a', 6428801, 'bc', 2)

$ ./hash "this is a test"
[dc053c4426ce396ace93a2817b388c465bb5188336d5f8816384a1cef0a2039d] [1655286693] [this is a test] [14]

$ ./hash "this is a tesu"
[cfbb3301ae39658cf1a1874dd48d8dbf9da4aee0831f781e30066be5f67eb819] [1655286694] [this is a tesu] [14]
#include <stdio.h>
#include <string.h>

unsigned int sdbm(char *inpt, int leng) {
	unsigned int hshs = 0;
	for (int x = 0; x < leng; ++x) {
		hshs = (inpt[x] + (hshs << 6) + (hshs << 16) - hshs);
	}
	return hshs;
}

void sdbm_hash(unsigned char *outp, unsigned char *inpt, int leng) {
	unsigned int mixs[] = {1, 6, 16, 13, 33, 27, 67, 55, 123};
	unsigned int hshs[] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
	unsigned int more = 0;
	int rnds = 9;
	for (int z = 0; z < rnds*3; ++z) {
		hshs[0] = ((hshs[0] + mixs[z%rnds]) * mixs[z%rnds]);
		for (int x = 0; x < leng; ++x) {
			hshs[0] = (hshs[0] & 0xffff);
			hshs[0] = (inpt[x] + (hshs[0] << 6) + (hshs[0] << 16) - hshs[0]);
			more = (more ^ (hshs[rnds-1] >> 16));
			for (int y = rnds-1; y > 0; --y) {
				hshs[y] = ((hshs[y] << 16) | (hshs[y-1] >> 16));
				hshs[y-1] = (hshs[y-1] & 0xffff);
			}
			hshs[0] = (hshs[0] ^ more);
		}
	}
	for (int x = 1, y = 0; x < rnds; ++x) {
		for (int z = 3; z > -1; --z, ++y) { 
			outp[y] = ((hshs[x] >> (z * 8)) & 0xff);
		}
	}
}

void stoh(char *outp, unsigned char *inpt) {
	char *hexs = "0123456789abcdef";
	for (int x = 0, y = 0; x < 32; ++x) {
		outp[y] = hexs[(inpt[x] >> 4) & 0xf]; ++y;
		outp[y] = hexs[inpt[x] & 0xf]; ++y;
	}
}

int main(int argc, char *argv[]) {
	char *m = argv[1]; int l = strlen(m);
	unsigned char h[32]; char o[65]; bzero(o, 65);
	sdbm_hash(h, (unsigned char *)m, l); stoh(o, h);
	printf("[%s] [%u] [%s] [%d]\n", o, sdbm(m, l), m, l);
	return 0;
}

Experiment – Turning the SDBM mixing algorithm into a hash function

Experiment: Running a UDP socket [client/server] ARP broadcaster for each WiFi AP (better client association tracking)

If you are running multiple WiFI APs that are part of the same flat network and bridged together it can be tricky keeping a current list of which client is connected to which AP (sometimes clients can just stop responding on one AP and then wake up and appear on another AP). In addition, the one common question a router needs to know is, is this client connected to me OR are they connected through one of my peer routers and which one is the best one?… I wrote a small service which allows an AP to periodically broadcast out, relay/forward, and receive the current WiFi client associations it has and the best association is chosen to amongst all the APs to be able to keep a common set of ARP entries for each access point! The tables are way cleaner and way more consistent with each other now that I have this thing running. I wrote it in both C and python which are supported on OpenWRT routers and can communicate with each other using a common key/pwd. You simply list which radio interfaces the AP has and the IP address you gave the AP on the flat network and it should be ready to send, forward, & receive ARP related messages. The program will write out a standard file with the following information formatted in it and it can also be used with the relayd service modification post below:

/tmp/arp.txt: [dev] [mac/peer] [ip]
wlan1 00:11:22:dd:ee:ff 192.168.100.123

The code can be found here if you are interested!:

C: https://github.com/stoops/broadarp/blob/init/barp.c
Py2: https://github.com/stoops/broadarp/blob/python/barp.py
relayd-mod: https://github.com/stoops/relayd/compare/master…stoops:merged [blog post]

🙂
Jon C

Experiment: Running a UDP socket [client/server] ARP broadcaster for each WiFi AP (better client association tracking)