Skip to content

Conversation

@hakansa
Copy link

@hakansa hakansa commented Apr 17, 2025

This PR adds support for building and running wgctrl on 32-bit FreeBSD systems.

On 32-bit FreeBSD, size_t and ulong are 32 bits under the ILP32 model, whereas on 64-bit FreeBSD they are 64 bits under LP64. The Go code was previously using uint64 (8 bytes) for WGDataIO.Size (which the C struct expects to be 4 bytes on ILP32), C.ulong to pass buffer lengths to nvlist_unpack, and C.ulong to pass numeric values to nvlist_add_number (which expects a uint64_t). These mismatches cause build failures on ILP32.

Changes

  1. In client_freebsd.go, update WGDataIO.Size from uint64(sz) to uint32(sz). On ILP32 this writes a 32-bit size, matching the C struct. On LP64, uint32(sz) zero-extends appropriately.
  2. In decode.go, change sz := C.ulong(len(d)) to sz := C.size_t(len(d)) so nvlist_unpack always receives exactly a size_t.
  3. In encode.go, change C.nvlist_add_number(nvl, ckey, C.ulong(value)) to C.nvlist_add_number(nvl, ckey, C.uint64_t(value)), ensuring 64-bit numbers are passed correctly on ILP32 and LP64.

@hakansa hakansa changed the title FreeBSD add 32-bit build support FreeBSD 32-bit build support Apr 17, 2025
Name: dname,
Data: mem,
Size: uint64(sz),
Size: uint32(sz),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think an explanation on why these changes are needed would be helpful in the commit message + PR description. Why do 32 bit builds not work without this and does this impact 64 bit builds at all?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jrife thanks for the feedback, I've updated the PR description and added a commit. You can find the details in the PR description, 32-bit builds doesn't work because of type mismatches. These change has no impact to 64-bit builds since 64 bit builds still use data types that has "64 bits". It is tested with both 32-bit and 64-bit machines.

Name: dname,
Data: mem,
Size: uint64(sz),
Size: uint32(sz),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does C.size_t work here?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it doesn't since WGDataIO type uses C.struct_wg_data_io

type WGDataIO C.struct_wg_data_io

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uint32 here makes the build fail on 64 bit systems. Tried this on my freebsd box:

root@freebsd:~/wgctrl-go # go test . -v
# golang.zx2c4.com/wireguard/wgctrl/internal/wgfreebsd
internal/wgfreebsd/client_freebsd.go:197:9: cannot use uint32(sz) (value of type uint32) as uint64 value in struct literal
FAIL	golang.zx2c4.com/wireguard/wgctrl [build failed]
FAIL
root@freebsd:~/wgctrl-go # 

This seems to fix it:

--- a/internal/wgfreebsd/client_freebsd.go
+++ b/internal/wgfreebsd/client_freebsd.go
@@ -194,7 +194,7 @@ func (c *Client) ConfigureDevice(name string, cfg wgtypes.Config) error {
        data := wgh.WGDataIO{
                Name: dname,
                Data: mem,
-               Size: uint32(sz),
+               Size: wgh.SizeT(sz),
        }
 
        if err := c.ioctlWGDataIO(wgh.SIOCSWG, &data); err != nil {
diff --git a/internal/wgfreebsd/internal/wgh/defs.go b/internal/wgfreebsd/internal/wgh/defs.go
index ccd593e..8f63dfb 100644
--- a/internal/wgfreebsd/internal/wgh/defs.go
+++ b/internal/wgfreebsd/internal/wgh/defs.go
@@ -49,3 +49,7 @@ type Ifgroupreq C.struct_go_ifgroupreq
 type Ifgreq C.struct_ifg_req
 
 type WGDataIO C.struct_wg_data_io
+
+func SizeT(i int) C.size_t {
+       return C.size_t(i)
+}

You can run wgctrl-go/internal/wgfreebsd/internal/wgh/generate.sh to regenerate all the defs_*.go files and will add a SizeT helper to each filling in the appropriate type for C.size_t:

diff --git a/internal/wgfreebsd/internal/wgh/defs_freebsd_amd64.go b/internal/wgfreebsd/internal/wgh/defs_freebsd_amd64.go
index 2b8aaa4..2be005a 100644
--- a/internal/wgfreebsd/internal/wgh/defs_freebsd_amd64.go
+++ b/internal/wgfreebsd/internal/wgh/defs_freebsd_amd64.go
@@ -30,3 +30,7 @@ type WGDataIO struct {
        Data *byte
        Size uint64
 }
+
+func SizeT(i int) uint64 {
+       return uint64(i)
+}

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jrife thanks! committed the changes and seems it is compling file both with 32-bit and 64-bit. (tested on arm arch.)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. LGTM.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to get this PR merged?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hakansa Unfortunately, I don't have merge privileges, but cc @mdlayher @zx2c4 who may be able to get this merged.

mdlayher and others added 3 commits June 24, 2025 11:23
Signed-off-by: Matt Layher <[email protected]>
Signed-off-by: Hakan Sariman <[email protected]>
Ensure WGDataIO.Size uses uint32 on ILP32 to match C struct.
Use C.size_t for nvlist_unpack and C.uint64_t for nvlist_add_number
to avoid build failures from size_t/ulong mismatches.

Signed-off-by: Hakan Sariman <[email protected]>
go test -c .
doas bash -c 'WGCTRL_INTEGRATION=yesreallydoit ./wgctrl.test -test.v -test.run TestIntegration'
# TODO: re-enable once Go 1.19 is available in openbsd/latest and wireguard-go can be built
exit 0
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this change necessary? Seems unrelated to the purpose of the PR?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont remember that I've committed these changes, @mdlayher might have the answer


# Set up wireguard-go on all OSes.
git clone git://git.zx2c4.com/wireguard-go
git clone https://git.zx2c4.com/wireguard-go
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same, is this a local change you made that snuck in?


require (
github.com/google/go-cmp v0.5.9
github.com/google/go-cmp v0.6.0
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is go.mod getting updated?

@jrife
Copy link

jrife commented Jul 18, 2025

@hakansa you have a commit, go.mod: bump dependencies, adjust CI builds, that seems to have been added later on. Should this be included in this PR? What's the purpose?

@billf
Copy link

billf commented Sep 5, 2025

@jrife

@hakansa you have a commit, go.mod: bump dependencies, adjust CI builds, that seems to have been added later on. Should this be included in this PR? What's the purpose?

it's part of master: a9ab227

likely when @hakansa committed the requested changes (e.g. #155 (comment) wgh.SizeT), rather than amending them to their existing commit or making a new commit, they were amended to an unrelated commit at the HEAD of master. cleaning this up with rebase and push --force is left as an exercise to the reader...

@hakansa
Copy link
Author

hakansa commented Sep 8, 2025

is there anythng that i can do the make this pr merged? We have some customers waiting for 32-bit support 👐

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants