Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

x/net/ipv4: calling SetTOS and SetTTL doesn't work as expected on MacOS #67421

Open
eelcocramer opened this issue May 16, 2024 · 1 comment
Open
Labels
NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. OS-Darwin
Milestone

Comments

@eelcocramer
Copy link

eelcocramer commented May 16, 2024

Go version

go version go1.22.3 darwin/arm64

Output of go env in your module/workspace:

GO111MODULE=''
GOARCH='arm64'
GOBIN='/Users/gopher/go/bin'
GOCACHE='/Users/gopher/Library/Caches/go-build'
GOENV='/Users/gopher/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMODCACHE='/Users/gopher/go/pkg/mod'
GOOS='darwin'
GOPATH='/Users/gopher/go'
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/opt/homebrew/Cellar/go/1.22.3/libexec'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/opt/homebrew/Cellar/go/1.22.3/libexec/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.22.3'
GCCGO='gccgo'
AR='ar'
CC='cc'
CXX='c++'
CGO_ENABLED='1'
GOMOD='/Users/gopher/reproduce/go.mod'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/68/ch3mzzs55bz8x9mzk1dsd35c0000gn/T/go-build1659040423=/tmp/go-build -gno-record-gcc-switches -fno-common'

What did you do?

package main

import (
	"flag"
	"log"
	"net"

	"golang.org/x/net/ipv4"
)

func main() {
	name := flag.String("i", "eth0", "interface name")
	flag.Parse()

	iface, err := net.InterfaceByName(*name)
	if err != nil {
		log.Fatalf("%v", err)
	}

	group := &net.UDPAddr{IP: net.ParseIP("224.0.0.1"), Port: 1234}
	conn, err := net.ListenPacket("udp4", "224.0.0.1:1234")
	if err != nil {
		log.Fatalf("%v", err)
	}

	p := ipv4.NewPacketConn(conn)
	p.SetMulticastTTL(30)
	p.SetMulticastInterface(iface)

	if err := p.JoinGroup(iface, &net.UDPAddr{IP: group.IP}); err != nil {
		log.Fatalf("%v", err)
	}

	err = p.SetTOS(0x0)
	if err != nil {
		log.Fatalf("%v", err)
	}
	_, err = p.WriteTo([]byte("test1"), nil, group)
	if err != nil {
		log.Fatalf("%v", err)
	}
	err = p.SetTOS(0x20)
	if err != nil {
		log.Fatalf("%v", err)
	}
	_, err = p.WriteTo([]byte("test2"), nil, group)
	if err != nil {
		log.Fatalf("%v", err)
	}
	p.SetMulticastTTL(33)
	err = p.SetTOS(0x40)
	if err != nil {
		log.Fatalf("%v", err)
	}
	_, err = p.WriteTo([]byte("test3"), nil, group)
	if err != nil {
		log.Fatalf("%v", err)
	}
}

What did you see happen?

tcpdump: listening on utun6, link-type NULL (BSD loopback), snapshot length 524288 bytes
09:28:12.021211 IP (tos 0x40, ttl 33, id 32412, offset 0, flags [none], proto UDP (17), length 33)
    139.63.127.166.1234 > 224.0.0.1.1234: [udp sum ok] UDP, length 5
	0x0000:  4540 0021 7e9c 0000 2111 3009 8b3f 7fa6  E@.!~...!.0..?..
	0x0010:  e000 0001 04d2 04d2 000d f26e 7465 7374  ...........ntest
	0x0020:  31                                       1
09:28:12.021339 IP (tos 0x40, ttl 33, id 64306, offset 0, flags [none], proto UDP (17), length 33)
    139.63.127.166.1234 > 224.0.0.1.1234: [udp sum ok] UDP, length 5
	0x0000:  4540 0021 fb32 0000 2111 b372 8b3f 7fa6  E@.!.2..!..r.?..
	0x0010:  e000 0001 04d2 04d2 000d f16e 7465 7374  ...........ntest
	0x0020:  32                                       2
09:28:12.021513 IP (tos 0x40, ttl 33, id 9938, offset 0, flags [none], proto UDP (17), length 33)
    139.63.127.166.1234 > 224.0.0.1.1234: [udp sum ok] UDP, length 5
	0x0000:  4540 0021 26d2 0000 2111 87d3 8b3f 7fa6  E@.!&...!....?..
	0x0010:  e000 0001 04d2 04d2 000d f06e 7465 7374  ...........ntest
	0x0020:  33                                       3

What did you expect to see?

According to the documentation of SetMulticastTTL and SetTOS new values will be applied to "future outgoing multicast packets". However on MacOS the last set value is applied on all outgoing packets that are still in the buffer ((that is an assumption from my side). When I add delays between the subsequent WriteTo calls the tcpdump output shows the correct values for tos and ttl. However, without these delays setting the ToS and TTL could affect previously sent packets.

On Linux the results are as expected from the documentation.

@gopherbot gopherbot added this to the Unreleased milestone May 16, 2024
@dmitshur dmitshur added OS-Darwin NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. labels May 16, 2024
@dmitshur
Copy link
Contributor

CC @golang/darwin, @ianlancetaylor.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
NeedsInvestigation Someone must examine and confirm this is a valid issue and not a duplicate of an existing one. OS-Darwin
Projects
None yet
Development

No branches or pull requests

3 participants