github.com/psiphon-labs/goarista@v0.0.0-20160825065156-d002785f4c67/dscp/listen_unix.go (about)

     1  // Copyright (C) 2016  Arista Networks, Inc.
     2  // Use of this source code is governed by the Apache License 2.0
     3  // that can be found in the COPYING file.
     4  
     5  package dscp
     6  
     7  import (
     8  	"net"
     9  	"os"
    10  	"reflect"
    11  
    12  	"golang.org/x/sys/unix"
    13  )
    14  
    15  func listenTCPWithTOS(address *net.TCPAddr, tos byte) (*net.TCPListener, error) {
    16  	lsnr, err := net.ListenTCP("tcp", address)
    17  	if err != nil {
    18  		return nil, err
    19  	}
    20  	// This works for the UNIX implementation of netFD, i.e. not on Windows and Plan9.
    21  	// This kludge is needed until https://github.com/golang/go/issues/9661 is fixed.
    22  	fd := int(reflect.ValueOf(lsnr).Elem().FieldByName("fd").Elem().FieldByName("sysfd").Int())
    23  	var proto, optname int
    24  	if address.IP.To4() != nil {
    25  		proto = unix.IPPROTO_IP
    26  		optname = unix.IP_TOS
    27  	} else {
    28  		proto = unix.IPPROTO_IPV6
    29  		optname = unix.IPV6_TCLASS
    30  	}
    31  	err = unix.SetsockoptInt(fd, proto, optname, int(tos))
    32  	if err != nil {
    33  		lsnr.Close()
    34  		return nil, os.NewSyscallError("setsockopt", err)
    35  	}
    36  
    37  	return lsnr, nil
    38  }