Example #1
0
func benchmarkReadWriteIPv4UDP(b *testing.B, p *ipv4.PacketConn, wb, rb []byte, dst net.Addr, ifi *net.Interface) {
	cm := ipv4.ControlMessage{TTL: 1}
	if ifi != nil {
		cm.IfIndex = ifi.Index
	}
	if n, err := p.WriteTo(wb, &cm, dst); err != nil {
		b.Fatal(err)
	} else if n != len(wb) {
		b.Fatalf("got %v; want %v", n, len(wb))
	}
	if _, _, _, err := p.ReadFrom(rb); err != nil {
		b.Fatal(err)
	}
}
Example #2
0
func TestPacketConnConcurrentReadWriteUnicastUDP(t *testing.T) {
	switch runtime.GOOS {
	case "nacl", "plan9", "windows":
		t.Skipf("not supported on %s", runtime.GOOS)
	}

	c, err := net.ListenPacket("udp4", "127.0.0.1:0")
	if err != nil {
		t.Fatal(err)
	}
	defer c.Close()
	p := ipv4.NewPacketConn(c)
	defer p.Close()

	dst, err := net.ResolveUDPAddr("udp4", c.LocalAddr().String())
	if err != nil {
		t.Fatal(err)
	}

	ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback)
	cf := ipv4.FlagTTL | ipv4.FlagSrc | ipv4.FlagDst | ipv4.FlagInterface
	wb := []byte("HELLO-R-U-THERE")

	if err := p.SetControlMessage(cf, true); err != nil { // probe before test
		if nettest.ProtocolNotSupported(err) {
			t.Skipf("not supported on %s", runtime.GOOS)
		}
		t.Fatal(err)
	}

	var wg sync.WaitGroup
	reader := func() {
		defer wg.Done()
		rb := make([]byte, 128)
		if n, cm, _, err := p.ReadFrom(rb); err != nil {
			t.Error(err)
			return
		} else if !bytes.Equal(rb[:n], wb) {
			t.Errorf("got %v; want %v", rb[:n], wb)
			return
		} else {
			s := cm.String()
			if strings.Contains(s, ",") {
				t.Errorf("should be space-separated values: %s", s)
			}
		}
	}
	writer := func(toggle bool) {
		defer wg.Done()
		cm := ipv4.ControlMessage{
			Src: net.IPv4(127, 0, 0, 1),
		}
		if ifi != nil {
			cm.IfIndex = ifi.Index
		}
		if err := p.SetControlMessage(cf, toggle); err != nil {
			t.Error(err)
			return
		}
		if n, err := p.WriteTo(wb, &cm, dst); err != nil {
			t.Error(err)
			return
		} else if n != len(wb) {
			t.Errorf("short write: %v", n)
			return
		}
	}

	const N = 10
	wg.Add(N)
	for i := 0; i < N; i++ {
		go reader()
	}
	wg.Add(2 * N)
	for i := 0; i < 2*N; i++ {
		go writer(i%2 != 0)
	}
	wg.Add(N)
	for i := 0; i < N; i++ {
		go reader()
	}
	wg.Wait()
}
Example #3
0
func (s *Server) ListenAndServeUDPv4() {
	ipAddr := &net.IPAddr{IP: net.IPv4zero}
	conn, err := net.ListenIP("ip4:udp", ipAddr)
	if err != nil {
		l.Info(err.Error())
		return
	}
	defer conn.Close()
	if err = bindToDevice(conn, "tap"+s.name); err != nil {
		l.Info(err.Error())
		return
	}

	s.Lock()
	s.ipv4conn, err = ipv4.NewRawConn(conn)
	s.Unlock()
	if err != nil {
		l.Info(err.Error())
		return
	}

	if err = s.ipv4conn.SetControlMessage(ipv4.FlagDst, true); err != nil {
		l.Warning(err.Error())
		return
	}

	buffer := make([]byte, 1500)

	var gw net.IP
	for _, addr := range s.metadata.Network.IP {
		if addr.Family == "ipv4" && addr.Host == "true" && addr.Gateway == "true" {
			gw = net.ParseIP(addr.Address)
		}
	}
	iface, err := net.InterfaceByName("tap" + s.name)
	if err != nil {
		l.Info(fmt.Sprintf("failed to get iface: %s", err.Error()))
		return
	}

	for {
		select {
		case <-s.done:
			return
		default:
			s.ipv4conn.SetReadDeadline(time.Now().Add(time.Second))
			hdr, _, _, err := s.ipv4conn.ReadFrom(buffer)
			if err != nil {
				switch v := err.(type) {
				case *net.OpError:
					if v.Timeout() {
						continue
					}
				case *net.AddrError:
					if v.Timeout() {
						continue
					}
				case *net.UnknownNetworkError:
					if v.Timeout() {
						continue
					}
				default:
					l.Warning(err.Error())
					return
				}
			}
			var ip4 layers.IPv4
			var udp layers.UDP
			var dhcp4req layers.DHCPv4
			parser := gopacket.NewDecodingLayerParser(layers.LayerTypeIPv4, &ip4, &udp, &dhcp4req)
			decoded := []gopacket.LayerType{}
			err = parser.DecodeLayers(buffer, &decoded)
			for _, layerType := range decoded {
				switch layerType {
				case layers.LayerTypeDHCPv4:
					if dhcp4req.Operation == layers.DHCP_MSG_REQ {
						dhcp4res, err := s.ServeUDPv4(&dhcp4req)
						if err != nil {
							l.Warning(err.Error())
							continue
						}
						if dhcp4res == nil {
							// ignore empty dhcp packets
							continue
						}

						buf := gopacket.NewSerializeBuffer()
						opts := gopacket.SerializeOptions{true, true}
						gopacket.SerializeLayers(buf, opts,
							&layers.UDP{SrcPort: 67, DstPort: 68},
							dhcp4res)

						wcm := ipv4.ControlMessage{TTL: 255}
						wcm.Dst = net.IPv4bcast.To4()
						wcm.Src = gw.To4()
						wcm.IfIndex = iface.Index
						err = s.ipv4conn.WriteTo(&ipv4.Header{Len: 20, TOS: hdr.TOS, TotalLen: 20 + int(len(buf.Bytes())), FragOff: 0, TTL: 255, Protocol: int(layers.IPProtocolUDP), Src: gw.To4(), Dst: net.IPv4bcast.To4()}, buf.Bytes(), &wcm)
						if err != nil {
							l.Warning(err.Error())
							continue
						}
					} else {
						continue
					}
				}
			}
		}
	}
}