Proposal: net/ipv4 package, IP-level socket options for IPv4

555 views
Skip to the first unread message

Mikio Hara

unread,
3 Aug 2012, 12:35:2003/08/2012
to golang-dev
Hi,

IIRC, we discussed a bit how to implement IP-level socket options
just before Go 1 release. At that point we didn't have much time but
now two Go 1 maintenance releases has been shipped. It seems like
a suitable time to propose something remaining to be done.

So here is my proposal for a package that handles IP-level socket
options for IPv4.

--
package ipv4
import "net/ipv4"
Package ipv4 implements IP-level socket options for IPv4.

type Control struct {
// contains filtered or unexported fields
}

func ConnControl(c net.Conn) (*Control, error)
ConnControl returns the IPv4 protocol control knob for the given network
connection.

func PacketConnControl(c net.PacketConn) (*Control, error)
PacketConnControl returns the IPv4 protocol control knob for the given
network connection.

Both ConnControl and PacketConnControl call net.(Conn, PacketConn).File()
to acquire the socket descriptor.

func (c *Control) SetTOS(tos int) error
func (c *Control) SetTTL(ttl int) error
func (c *Control) SetMulticastTTL(ttl int) error
func (c *Control) SetMulticastLoopback(on bool) error
func (c *Control) SetMulticastInterface(ifi *net.Interface) error

We implements socket sticky, affects all transmitted packets,
options as methods by default.

The other way to specify options that using ancillary data for
each packet,

type Ancillaries map[string]interface{}
Ancillaries maps a string key to a value. It is used to control IPv4
ancillary data reception, transmission between net.Conn, net.PacketConn
and the IPv4 protocol stack.

func (c *Control) Query() (Ancillaries, error)

we set ancillaries like:
anc["ttl"] = true
anc["header"] = false

then apply ancillary settings to the socket.

func (c *Control) SetReadAncillaries() (err error)
SetReadAncillaries sets the IPv4 ancillary settings to the network
connection for future net.ReadMsg calls

func (c *Control) SetWriteAncillaries() (err error)
SetWriteAncillaries sets the IPv4 ancillary settings to the network
connection for future net.WriteMsg calls.

Of course we need net.WriteMsg/ReadMsg support too.
http://codereview.appspot.com/6426047/

func ParseAncillaries(b []byte) (Ancillaries, error)
ParseAncillaries parses the given b as IPv4 ancillaries.
--

Comments welcome.

-- Mikio
P.S. net/ipv6 too.

Russ Cox

unread,
3 Aug 2012, 15:46:1003/08/2012
to Mikio Hara, golang-dev
What do people do with all these options? It just feels like I'm
drowning in buttons and knobs.

Russ

Albert Strasheim

unread,
4 Aug 2012, 03:31:4304/08/2012
to golan...@googlegroups.com, Mikio Hara
Hello

We've found uses for

func (c *Control) SetMulticastLoopback(on bool) error 
func (c *Control) SetMulticastInterface(ifi *net.Interface) error

in a distributed service locator we've built.

It would have been fine to not have an API in the standard library for this, but the fact that calling File() breaks your socket leads to gruesome code when you need to get at the file descriptor inside your socket to set this kind of stuff.

Regards

Albert

Ingo Oeser

unread,
4 Aug 2012, 05:37:0804/08/2012
to golan...@googlegroups.com, Mikio Hara
TTL setting is required for writing tools like traceroute and anything else, which likes to measure hop count.


On Friday, August 3, 2012 9:46:10 PM UTC+2, rsc wrote:

Mikio Hara

unread,
7 Aug 2012, 10:51:5107/08/2012
to Russ Cox, golang-dev
On Sat, Aug 4, 2012 at 4:46 AM, Russ Cox <r...@golang.org> wrote:

> What do people do with all these options? It just feels like I'm
> drowning in buttons and knobs.

Yup, they are toggles for controlling IP control plane stuff.

Unfortunately there's no joystick-like smart control interface
therefore we need those toggles to create joystick-like smart
interface such as routing/signaling protocols, OAM tools.

Mikio Hara

unread,
22 Aug 2012, 07:34:5222/08/2012
to golang-dev
Hi,

Here is a revised API proposal and mock code.
<http://codereview.appspot.com/6474044/>

I added a few network I/O methods, had tests on linux, freebsd, darwin,
addressed issues should be fixed and added test codes especially IP
multicast stuff.

Comments welcome.

-- Mikio

package ipv4
import "net/ipv4"

Package ipv4 implements IP-level socket options for the Internet
Protocol version 4.

CONSTANTS

const (
ProtocolVersion = 4 // protocol version
HeaderLen = 20 // header length without extension headers

)


TYPES

type Conn struct {
// contains filtered or unexported fields
}
A Conn represents a network endpoint that uses IPv4 transport. It allows
to set basic IP-level socket options such as TOS and TTL.

func NewConn(c net.Conn) *Conn
NewConn returns a new Conn.

func (c *Conn) SetTOS(tos int) error
SetTOS sets the type-of-service field value for future outgoing packets.

func (c *Conn) SetTTL(ttl int) error
SetTTL sets the time-to-live field value for future outgoing packets.

func (c *Conn) TOS() (int, error)
TOS returns the type-of-service field value for outgoing packets.

func (c *Conn) TTL() (int, error)
TTL returns the time-to-live field value for outgoing packets.

type ControlFlags uint

const (
FlagTTL ControlFlags = 1 << iota // pass the TTL on the
received packet
FlagSrc // pass the source address
on the received packet
FlagDst // pass the destination
address on the received packet
FlagInterface // pass the interface index
on the received packet or outgoing packet
)

type ControlMessage struct {
TTL int // time-to-live
Src net.IP // source address
Dst net.IP // destination address
IfIndex int // interface index
}
A ControlMessage represents control information that contains per packet
basis IP-level option data.

func (cm *ControlMessage) String() string

type Header struct {
Version int // protocol version
Len int // header length
TOS int // type-of-service
TotalLen int // packet total length
ID int // identification
FragOff int // fragment offset
TTL int // time-to-live
Protocol int // next protocol
Checksum int // checksum
Src net.IP // source address
Dst net.IP // destination address
Options []byte // options, extension headers
}
A Header represents an IPv4 header.

func ParseHeader(b []byte) (*Header, error)
ParseHeader parses b as an IPv4 header.

func (h *Header) Marshal() ([]byte, error)
Marshal returns the binary encoding of the IPv4 header h.

func (h *Header) String() string

type HeaderField int

const (
TOS HeaderField = 1 // type-of-service
TotalLen = 2 // packet tolal length
ID = 4 // identification
FragOff = 6 // fragment offset
TTL = 8 // time-to-live
Protocol = 9 // next protocol
Checksum = 10 // checksum
Src = 12 // source address
Dst = 16 // destination address
)

func (f HeaderField) String() string

type PacketConn struct {
// contains filtered or unexported fields
}
A PacketConn represents a packet network endpoint that uses IPv4
transport. It allows to set several IP-level socket options that include
the control of multicasting. It also provides datagram based network I/O
methods specific to the IPv4 and higher layer protocols such as UDP.

func NewPacketConn(c net.PacketConn) *PacketConn
NewPacketConn returns a new PacketConn using c for network I/O.

func (c *PacketConn) Close() error
Close closes the endpoint.

func (c *PacketConn) JoinGroup(ifi *net.Interface, group, source net.Addr) error
JoinGroup joins the group address group with the source address source
on the interface ifi. It uses the system assigned multicast interface if
ifi and source is nil.

func (c *PacketConn) LeaveGroup(ifi *net.Interface, group, source
net.Addr) error
LeaveGroup leaves the group address group with the source address source
on the interface ifi.

func (c *PacketConn) MulticastInterface() (*net.Interface, error)
MulticastInterface returns the interface for multicast packet
transmission.

func (c *PacketConn) MulticastLoopback() (bool, error)
MulticastLoopback reports whether transmitted multicast packets should
be copied, sent back to the originator.

func (c *PacketConn) MulticastTTL() (int, error)
MulticastTTL returns the time-to-live field value for outgoing multicast
packets.

func (c *PacketConn) Read(b []byte) (n int, cm *ControlMessage, src
net.Addr, err error)
Read reads a payload of the received IPv4 datagram, from the endpoint c,
copying the payload into b. It returns the number of bytes copied into
b, the control message cm and the source address src on the received
datagram.

func (c *PacketConn) SetControlMessage(cf ControlFlags, on bool) error
SetControlMessage sets the per packet basis IP-level socket options.

func (c *PacketConn) SetMulticastInterface(ifi *net.Interface) error
SetMulticastInterface sets the interface for future multicast packet
transmission.

func (c *PacketConn) SetMulticastLoopback(on bool) error
SetMulticastLoopback sets whether transmitted multicast packets should
be copied, sent back to the originator.

func (c *PacketConn) SetMulticastTTL(ttl int) error
SetMulticastTTL sets the time-to-live field value for future outgoing
multicast packets.

func (c *PacketConn) SetTOS(tos int) error
SetTOS sets the type-of-service field value for future outgoing packets.

func (c *PacketConn) SetTTL(ttl int) error
SetTTL sets the time-to-live field value for future outgoing packets.

func (c *PacketConn) TOS() (int, error)
TOS returns the type-of-service field value for outgoing packets.

func (c *PacketConn) TTL() (int, error)
TTL returns the time-to-live field value for outgoing packets.

func (c *PacketConn) Write(b []byte, cm *ControlMessage, dst net.Addr)
(n int, err error)
Write writes a payload of the IPv4 datagram, to the destination address
dst through the endpoint c, copying the payload from b. It returns the
number of bytes written. The control message cm allows to specify the
datagram path, outgoing interface, but currently only Linux supports
that control. The cm could be nil unless the control of the outgoing
datagram is required.

type RawConn struct {
// contains filtered or unexported fields
}
A RawConn represents a packet network endpoint that uses IPv4 transport.
It allows to set several IP-level socket options that include IPv4
header manipulation. It also provides datagram based network I/O methods
specific to the protocols that handle IPv4 datagram directly such as
OSPF, GRE.

func NewRawConn(c net.PacketConn) (*RawConn, error)
NewRawConn returns a new RawConn using c for network I/O.

func (c *RawConn) Close() error
Close closes the endpoint.

func (c *RawConn) JoinGroup(ifi *net.Interface, group, source net.Addr) error
JoinGroup joins the group address group with the source address source
on the interface ifi. It uses the system assigned multicast interface if
ifi and source is nil.

func (c *RawConn) LeaveGroup(ifi *net.Interface, group, source net.Addr) error
LeaveGroup leaves the group address group with the source address source
on the interface ifi.

func (c *RawConn) MulticastInterface() (*net.Interface, error)
MulticastInterface returns the interface for multicast packet
transmission.

func (c *RawConn) MulticastLoopback() (bool, error)
MulticastLoopback reports whether transmitted multicast packets should
be copied, sent back to the originator.

func (c *RawConn) MulticastTTL() (int, error)
MulticastTTL returns the time-to-live field value for outgoing multicast
packets.

func (c *RawConn) Read(b []byte) (h *Header, p []byte, cm
*ControlMessage, err error)
Read reads an IPv4 datagram from the endpoint c, copying the datagram
into b. It returns the receivd datagram as the IPv4 header h, the
payload p and the control message cm.

func (c *RawConn) SetControlMessage(cf ControlFlags, on bool) error
SetControlMessage sets the per packet basis IP-level socket options.

func (c *RawConn) SetMulticastInterface(ifi *net.Interface) error
SetMulticastInterface sets the interface for future multicast packet
transmission.

func (c *RawConn) SetMulticastLoopback(on bool) error
SetMulticastLoopback sets whether transmitted multicast packets should
be copied, sent back to the originator.

func (c *RawConn) SetMulticastTTL(ttl int) error
SetMulticastTTL sets the time-to-live field value for future outgoing
multicast packets.

func (c *RawConn) SetTOS(tos int) error
SetTOS sets the type-of-service field value for future outgoing packets.

func (c *RawConn) SetTTL(ttl int) error
SetTTL sets the time-to-live field value for future outgoing packets.

func (c *RawConn) TOS() (int, error)
TOS returns the type-of-service field value for outgoing packets.

func (c *RawConn) TTL() (int, error)
TTL returns the time-to-live field value for outgoing packets.

func (c *RawConn) Write(h *Header, p []byte, cm *ControlMessage) (err error)
Write writes an IPv4 datagram through the endpoint c, copying the
datagram from the IPv4 header h and the payload p. The control message
cm allows to specify the datagram path, outgoing interface, but
currently only Linux supports that control. The cm could be nil unless
the control of the outgoing datagram is required.

The IPv4 header h must contain appropriate fields that include:

Version = don't care
Len = <must be specified>
TOS = <must be specified>
TotalLen = <must be specified>
ID = platform sets an appropriate value if ID is zero
FragOff = <must be specified>
TTL = <must be specified>
Protocol = <must be specified>
Checksum = platform sets an appropriate value if Checksum is zero
Src = platform sets an appropriate value if Src is nil
Dst = <must be specified>
h.Options = optional

Dave Cheney

unread,
22 Aug 2012, 07:40:2322/08/2012
to Mikio Hara, golang-dev
Hi Mikio,

I haven't finished reading this CL fully so I may have missed
something, but do you think there is a driving reason this pkg needs
to go into the standard library? Could it go into the go.net sub repo
?

Cheers

Dave

Mikio Hara

unread,
22 Aug 2012, 07:55:0222/08/2012
to Dave Cheney, golang-dev
Hi Dave,

On Wed, Aug 22, 2012 at 8:40 PM, Dave Cheney <da...@cheney.net> wrote:

> I haven't finished reading this CL fully so I may have missed
> something, but do you think there is a driving reason this pkg needs
> to go into the standard library? Could it go into the go.net sub repo
> ?

Sure, go.net or wherever we can reach, nice. thanks for your suggestion.
I would like to add go.net/ipv6 package also then remove IP-level option
stuff from net package.

Mikio Hara

unread,
22 Aug 2012, 08:16:5522/08/2012
to golang-dev
> Here is a revised API proposal and mock code.
> <http://codereview.appspot.com/6474044/>

redirects to <http://codereview.appspot.com/6482044/>
Reply all
Reply to author
Forward
0 new messages