blob: 39efb4c4288ba83265d159631cdd8d9d1e6a7fe3 [file] [log] [blame]
Mikio Harad2e5a122012-09-26 21:03:09 +09001// Copyright 2012 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package ipv4
6
7import (
8 "net"
9 "syscall"
10)
11
12// A payloadHandler represents the IPv4 datagram payload handler.
13type payloadHandler struct {
Mikio Hara9d071032013-06-17 00:37:19 +090014 net.PacketConn
Mikio Harad2e5a122012-09-26 21:03:09 +090015 rawOpt
16}
17
Mikio Hara9d071032013-06-17 00:37:19 +090018func (c *payloadHandler) ok() bool { return c != nil && c.PacketConn != nil }
Mikio Harad2e5a122012-09-26 21:03:09 +090019
Mikio Hara0e4f6eb2012-12-21 07:30:42 +090020// ReadFrom reads a payload of the received IPv4 datagram, from the
Mikio Harad2e5a122012-09-26 21:03:09 +090021// endpoint c, copying the payload into b. It returns the number of
22// bytes copied into b, the control message cm and the source address
23// src of the received datagram.
Mikio Hara0e4f6eb2012-12-21 07:30:42 +090024func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net.Addr, err error) {
Mikio Harad2e5a122012-09-26 21:03:09 +090025 if !c.ok() {
26 return 0, nil, nil, syscall.EINVAL
27 }
28 oob := newControlMessage(&c.rawOpt)
29 var oobn int
Mikio Hara9d071032013-06-17 00:37:19 +090030 switch c := c.PacketConn.(type) {
Mikio Harad2e5a122012-09-26 21:03:09 +090031 case *net.UDPConn:
Mikio Hara9d071032013-06-17 00:37:19 +090032 if n, oobn, _, src, err = c.ReadMsgUDP(b, oob); err != nil {
Mikio Harad2e5a122012-09-26 21:03:09 +090033 return 0, nil, nil, err
34 }
35 case *net.IPConn:
Mikio Hara6b91bf22013-02-16 13:02:07 +090036 nb := make([]byte, maxHeaderLen+len(b))
Mikio Hara9d071032013-06-17 00:37:19 +090037 if n, oobn, _, src, err = c.ReadMsgIP(nb, oob); err != nil {
Mikio Harad2e5a122012-09-26 21:03:09 +090038 return 0, nil, nil, err
39 }
Mikio Hara6b91bf22013-02-16 13:02:07 +090040 hdrlen := int(nb[0]&0x0f) << 2
Mikio Harad2e5a122012-09-26 21:03:09 +090041 copy(b, nb[hdrlen:])
42 n -= hdrlen
43 default:
44 return 0, nil, nil, errInvalidConnType
45 }
46 if cm, err = parseControlMessage(oob[:oobn]); err != nil {
47 return 0, nil, nil, err
48 }
49 if cm != nil {
50 cm.Src = netAddrToIP4(src)
51 }
52 return
53}
54
Mikio Hara0e4f6eb2012-12-21 07:30:42 +090055// WriteTo writes a payload of the IPv4 datagram, to the destination
56// address dst through the endpoint c, copying the payload from b. It
57// returns the number of bytes written. The control message cm allows
58// the datagram path and the outgoing interface to be specified.
59// Currently only Linux supports this. The cm may be nil if control
60// of the outgoing datagram is not required.
61func (c *payloadHandler) WriteTo(b []byte, cm *ControlMessage, dst net.Addr) (n int, err error) {
Mikio Harad2e5a122012-09-26 21:03:09 +090062 if !c.ok() {
63 return 0, syscall.EINVAL
64 }
65 oob := marshalControlMessage(cm)
66 if dst == nil {
67 return 0, errMissingAddress
68 }
Mikio Hara9d071032013-06-17 00:37:19 +090069 switch c := c.PacketConn.(type) {
Mikio Harad2e5a122012-09-26 21:03:09 +090070 case *net.UDPConn:
Mikio Hara9d071032013-06-17 00:37:19 +090071 n, _, err = c.WriteMsgUDP(b, oob, dst.(*net.UDPAddr))
Mikio Harad2e5a122012-09-26 21:03:09 +090072 case *net.IPConn:
Mikio Hara9d071032013-06-17 00:37:19 +090073 n, _, err = c.WriteMsgIP(b, oob, dst.(*net.IPAddr))
Mikio Harad2e5a122012-09-26 21:03:09 +090074 default:
75 return 0, errInvalidConnType
76 }
77 if err != nil {
78 return 0, err
79 }
80 return
81}