k3xec.com/patty: Go bindings to patty

Paul Tagliamonte 2022-04-11 project

AX.25 is a tough protocol to use on UNIX systems. A lot of the support in Linux, specifically, is pretty hard to use, and tends to be built into the reptilian brain of the kernel. xan built a userland AX.25 stack called patty, for which I have now built some Go bindings on top of.

Code needed to create AX.25 Sockets via Go can be found at github.com/k3xec/go-patty, and imported by Go source as k3xec.com/patty.


Clint patty programs (including consumers of this Go library) work by communicating with a userland daemon (pattyd) via a UNIX named socket. That daemon will communicate with a particular radio using a KISS TNC serial device.

The Go bindings implement as many standard Go library interfaces as is practical, allowing for the “plug and play” use of patty (and AX.25) in places where you would expect a network socket (such as TCP) to work, such as Go’s http library.


package main

import (


func main() {
    callsign := "N0CALL-10"

	client, err := patty.Open("patty.sock")
	if err != nil {

	l, err := client.Listen("ax25", callsign)
	if err != nil {

	for {
		log.Printf("Listening for requests to %s", l.Addr())
		conn, err := l.Accept()
		if err != nil {
			log.Printf("Error accepting: %s", err)

		go handle(conn)

func handle(c net.Conn) error {
	defer c.Close()
	log.Printf("New connection from %s (local: %s)", c.RemoteAddr(), c.LocalAddr())

	fmt.Fprintf(c, `

Hello! This is Paul's experimental %s node. Feel free
to poke around. Let me know if you spot anything funny.

Five pings are to follow!

`, c.LocalAddr())

	for i := 0; i < 5; i++ {
		time.Sleep(time.Second * 5)
		fmt.Fprintf(c, "Ping!\n")

	return nil