1// Copyright 2009 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 net 6 7import ( 8 "context" 9 "errors" 10 "os" 11 "syscall" 12) 13 14func (c *UDPConn) readFrom(b []byte, addr *UDPAddr) (int, *UDPAddr, error) { 15 buf := make([]byte, udpHeaderSize+len(b)) 16 m, err := c.fd.Read(buf) 17 if err != nil { 18 return 0, nil, err 19 } 20 if m < udpHeaderSize { 21 return 0, nil, errors.New("short read reading UDP header") 22 } 23 buf = buf[:m] 24 25 h, buf := unmarshalUDPHeader(buf) 26 n := copy(b, buf) 27 *addr = UDPAddr{IP: h.raddr, Port: int(h.rport)} 28 return n, addr, nil 29} 30 31func (c *UDPConn) readMsg(b, oob []byte) (n, oobn, flags int, addr *UDPAddr, err error) { 32 return 0, 0, 0, nil, syscall.EPLAN9 33} 34 35func (c *UDPConn) writeTo(b []byte, addr *UDPAddr) (int, error) { 36 if addr == nil { 37 return 0, errMissingAddress 38 } 39 h := new(udpHeader) 40 h.raddr = addr.IP.To16() 41 h.laddr = c.fd.laddr.(*UDPAddr).IP.To16() 42 h.ifcaddr = IPv6zero // ignored (receive only) 43 h.rport = uint16(addr.Port) 44 h.lport = uint16(c.fd.laddr.(*UDPAddr).Port) 45 46 buf := make([]byte, udpHeaderSize+len(b)) 47 i := copy(buf, h.Bytes()) 48 copy(buf[i:], b) 49 if _, err := c.fd.Write(buf); err != nil { 50 return 0, err 51 } 52 return len(b), nil 53} 54 55func (c *UDPConn) writeMsg(b, oob []byte, addr *UDPAddr) (n, oobn int, err error) { 56 return 0, 0, syscall.EPLAN9 57} 58 59func (sd *sysDialer) dialUDP(ctx context.Context, laddr, raddr *UDPAddr) (*UDPConn, error) { 60 fd, err := dialPlan9(ctx, sd.network, laddr, raddr) 61 if err != nil { 62 return nil, err 63 } 64 return newUDPConn(fd), nil 65} 66 67const udpHeaderSize = 16*3 + 2*2 68 69type udpHeader struct { 70 raddr, laddr, ifcaddr IP 71 rport, lport uint16 72} 73 74func (h *udpHeader) Bytes() []byte { 75 b := make([]byte, udpHeaderSize) 76 i := 0 77 i += copy(b[i:i+16], h.raddr) 78 i += copy(b[i:i+16], h.laddr) 79 i += copy(b[i:i+16], h.ifcaddr) 80 b[i], b[i+1], i = byte(h.rport>>8), byte(h.rport), i+2 81 b[i], b[i+1], i = byte(h.lport>>8), byte(h.lport), i+2 82 return b 83} 84 85func unmarshalUDPHeader(b []byte) (*udpHeader, []byte) { 86 h := new(udpHeader) 87 h.raddr, b = IP(b[:16]), b[16:] 88 h.laddr, b = IP(b[:16]), b[16:] 89 h.ifcaddr, b = IP(b[:16]), b[16:] 90 h.rport, b = uint16(b[0])<<8|uint16(b[1]), b[2:] 91 h.lport, b = uint16(b[0])<<8|uint16(b[1]), b[2:] 92 return h, b 93} 94 95func (sl *sysListener) listenUDP(ctx context.Context, laddr *UDPAddr) (*UDPConn, error) { 96 l, err := listenPlan9(ctx, sl.network, laddr) 97 if err != nil { 98 return nil, err 99 } 100 _, err = l.ctl.WriteString("headers") 101 if err != nil { 102 return nil, err 103 } 104 l.data, err = os.OpenFile(l.dir+"/data", os.O_RDWR, 0) 105 if err != nil { 106 return nil, err 107 } 108 fd, err := l.netFD() 109 return newUDPConn(fd), err 110} 111 112func (sl *sysListener) listenMulticastUDP(ctx context.Context, ifi *Interface, gaddr *UDPAddr) (*UDPConn, error) { 113 // Plan 9 does not like announce command with a multicast address, 114 // so do not specify an IP address when listening. 115 l, err := listenPlan9(ctx, sl.network, &UDPAddr{IP: nil, Port: gaddr.Port, Zone: gaddr.Zone}) 116 if err != nil { 117 return nil, err 118 } 119 _, err = l.ctl.WriteString("headers") 120 if err != nil { 121 return nil, err 122 } 123 var addrs []Addr 124 if ifi != nil { 125 addrs, err = ifi.Addrs() 126 if err != nil { 127 return nil, err 128 } 129 } else { 130 addrs, err = InterfaceAddrs() 131 if err != nil { 132 return nil, err 133 } 134 } 135 136 have4 := gaddr.IP.To4() != nil 137 for _, addr := range addrs { 138 if ipnet, ok := addr.(*IPNet); ok && (ipnet.IP.To4() != nil) == have4 { 139 _, err = l.ctl.WriteString("addmulti " + ipnet.IP.String() + " " + gaddr.IP.String()) 140 if err != nil { 141 return nil, &OpError{Op: "addmulti", Net: "", Source: nil, Addr: ipnet, Err: err} 142 } 143 } 144 } 145 l.data, err = os.OpenFile(l.dir+"/data", os.O_RDWR, 0) 146 if err != nil { 147 return nil, err 148 } 149 fd, err := l.netFD() 150 if err != nil { 151 return nil, err 152 } 153 return newUDPConn(fd), nil 154} 155