Mikio Hara | d2e5a12 | 2012-09-26 21:03:09 +0900 | [diff] [blame] | 1 | // 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 | |
| 5 | package ipv4 |
| 6 | |
| 7 | import ( |
| 8 | "net" |
| 9 | "syscall" |
| 10 | ) |
| 11 | |
| 12 | // A payloadHandler represents the IPv4 datagram payload handler. |
| 13 | type payloadHandler struct { |
Mikio Hara | 9d07103 | 2013-06-17 00:37:19 +0900 | [diff] [blame] | 14 | net.PacketConn |
Mikio Hara | d2e5a12 | 2012-09-26 21:03:09 +0900 | [diff] [blame] | 15 | rawOpt |
| 16 | } |
| 17 | |
Mikio Hara | 9d07103 | 2013-06-17 00:37:19 +0900 | [diff] [blame] | 18 | func (c *payloadHandler) ok() bool { return c != nil && c.PacketConn != nil } |
Mikio Hara | d2e5a12 | 2012-09-26 21:03:09 +0900 | [diff] [blame] | 19 | |
Mikio Hara | 0e4f6eb | 2012-12-21 07:30:42 +0900 | [diff] [blame] | 20 | // ReadFrom reads a payload of the received IPv4 datagram, from the |
Mikio Hara | d2e5a12 | 2012-09-26 21:03:09 +0900 | [diff] [blame] | 21 | // 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 Hara | 0e4f6eb | 2012-12-21 07:30:42 +0900 | [diff] [blame] | 24 | func (c *payloadHandler) ReadFrom(b []byte) (n int, cm *ControlMessage, src net.Addr, err error) { |
Mikio Hara | d2e5a12 | 2012-09-26 21:03:09 +0900 | [diff] [blame] | 25 | if !c.ok() { |
| 26 | return 0, nil, nil, syscall.EINVAL |
| 27 | } |
| 28 | oob := newControlMessage(&c.rawOpt) |
| 29 | var oobn int |
Mikio Hara | 9d07103 | 2013-06-17 00:37:19 +0900 | [diff] [blame] | 30 | switch c := c.PacketConn.(type) { |
Mikio Hara | d2e5a12 | 2012-09-26 21:03:09 +0900 | [diff] [blame] | 31 | case *net.UDPConn: |
Mikio Hara | 9d07103 | 2013-06-17 00:37:19 +0900 | [diff] [blame] | 32 | if n, oobn, _, src, err = c.ReadMsgUDP(b, oob); err != nil { |
Mikio Hara | d2e5a12 | 2012-09-26 21:03:09 +0900 | [diff] [blame] | 33 | return 0, nil, nil, err |
| 34 | } |
| 35 | case *net.IPConn: |
Mikio Hara | 6b91bf2 | 2013-02-16 13:02:07 +0900 | [diff] [blame] | 36 | nb := make([]byte, maxHeaderLen+len(b)) |
Mikio Hara | 9d07103 | 2013-06-17 00:37:19 +0900 | [diff] [blame] | 37 | if n, oobn, _, src, err = c.ReadMsgIP(nb, oob); err != nil { |
Mikio Hara | d2e5a12 | 2012-09-26 21:03:09 +0900 | [diff] [blame] | 38 | return 0, nil, nil, err |
| 39 | } |
Mikio Hara | 6b91bf2 | 2013-02-16 13:02:07 +0900 | [diff] [blame] | 40 | hdrlen := int(nb[0]&0x0f) << 2 |
Mikio Hara | d2e5a12 | 2012-09-26 21:03:09 +0900 | [diff] [blame] | 41 | 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 Hara | 0e4f6eb | 2012-12-21 07:30:42 +0900 | [diff] [blame] | 55 | // 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. |
| 61 | func (c *payloadHandler) WriteTo(b []byte, cm *ControlMessage, dst net.Addr) (n int, err error) { |
Mikio Hara | d2e5a12 | 2012-09-26 21:03:09 +0900 | [diff] [blame] | 62 | if !c.ok() { |
| 63 | return 0, syscall.EINVAL |
| 64 | } |
| 65 | oob := marshalControlMessage(cm) |
| 66 | if dst == nil { |
| 67 | return 0, errMissingAddress |
| 68 | } |
Mikio Hara | 9d07103 | 2013-06-17 00:37:19 +0900 | [diff] [blame] | 69 | switch c := c.PacketConn.(type) { |
Mikio Hara | d2e5a12 | 2012-09-26 21:03:09 +0900 | [diff] [blame] | 70 | case *net.UDPConn: |
Mikio Hara | 9d07103 | 2013-06-17 00:37:19 +0900 | [diff] [blame] | 71 | n, _, err = c.WriteMsgUDP(b, oob, dst.(*net.UDPAddr)) |
Mikio Hara | d2e5a12 | 2012-09-26 21:03:09 +0900 | [diff] [blame] | 72 | case *net.IPConn: |
Mikio Hara | 9d07103 | 2013-06-17 00:37:19 +0900 | [diff] [blame] | 73 | n, _, err = c.WriteMsgIP(b, oob, dst.(*net.IPAddr)) |
Mikio Hara | d2e5a12 | 2012-09-26 21:03:09 +0900 | [diff] [blame] | 74 | default: |
| 75 | return 0, errInvalidConnType |
| 76 | } |
| 77 | if err != nil { |
| 78 | return 0, err |
| 79 | } |
| 80 | return |
| 81 | } |