func TestRawConnUnicastSocketOptions(t *testing.T) { switch runtime.GOOS { case "nacl", "plan9", "solaris": t.Skipf("not supported on %q", runtime.GOOS) } if os.Getuid() != 0 { t.Skip("must be root") } ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback) if ifi == nil { t.Skipf("not available on %q", runtime.GOOS) } c, err := net.ListenPacket("ip4:icmp", "127.0.0.1") if err != nil { t.Fatal(err) } defer c.Close() r, err := ipv4.NewRawConn(c) if err != nil { t.Fatal(err) } testUnicastSocketOptions(t, r) }
func TestRawConnUnicastSocketOptions(t *testing.T) { switch runtime.GOOS { case "nacl", "plan9": t.Skipf("not supported on %s", runtime.GOOS) } if m, ok := nettest.SupportsRawIPSocket(); !ok { t.Skip(m) } ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback) if ifi == nil { t.Skipf("not available on %s", runtime.GOOS) } c, err := net.ListenPacket("ip4:icmp", "127.0.0.1") if err != nil { t.Fatal(err) } defer c.Close() r, err := ipv4.NewRawConn(c) if err != nil { t.Fatal(err) } testUnicastSocketOptions(t, r) }
func TestRawConnMulticastSocketOptions(t *testing.T) { switch runtime.GOOS { case "nacl", "plan9": t.Skipf("not supported on %s", runtime.GOOS) } if m, ok := nettest.SupportsRawIPSocket(); !ok { t.Skip(m) } ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback) if ifi == nil { t.Skipf("not available on %s", runtime.GOOS) } for _, tt := range rawConnMulticastSocketOptionTests { c, err := net.ListenPacket("ip4:icmp", "0.0.0.0") if err != nil { t.Fatal(err) } defer c.Close() r, err := ipv4.NewRawConn(c) if err != nil { t.Fatal(err) } defer r.Close() if tt.src == nil { testMulticastSocketOptions(t, r, ifi, tt.grp) } else { testSourceSpecificMulticastSocketOptions(t, r, ifi, tt.grp, tt.src) } } }
func TestRawConnMulticastSocketOptions(t *testing.T) { switch runtime.GOOS { case "nacl", "plan9", "solaris": t.Skipf("not supported on %q", runtime.GOOS) } if os.Getuid() != 0 { t.Skip("must be root") } ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback) if ifi == nil { t.Skipf("not available on %q", runtime.GOOS) } c, err := net.ListenPacket("ip4:icmp", "0.0.0.0") if err != nil { t.Fatalf("net.ListenPacket failed: %v", err) } defer c.Close() r, err := ipv4.NewRawConn(c) if err != nil { t.Fatalf("ipv4.NewRawConn failed: %v", err) } testMulticastSocketOptions(t, r, ifi, &net.IPAddr{IP: net.IPv4(224, 0, 0, 250)}) /// see RFC 4727 }
func main() { flag.Parse() ip := net.ParseIP(*dst) if ip == nil { log.Fatal("destination not found") } c, err := net.ListenPacket(fmt.Sprintf("ip4:%d", *proto), "0.0.0.0") if err != nil { log.Fatal(err) } defer c.Close() p, err := ipv4.NewRawConn(c) if err != nil { log.Fatal(err) } b := []byte("HELLO-R-U-THERE") h := &ipv4.Header{ Version: ipv4.Version, Len: ipv4.HeaderLen, TotalLen: ipv4.HeaderLen + len(b), Protocol: *proto, Dst: ip.To4(), } if err := p.WriteTo(h, b, nil); err != nil { log.Println(err) } }
func (i *TCPStreamInjector) Init(netInterface string) error { var err error i.packetConn, err = net.ListenPacket("ip4:tcp", netInterface) if err != nil { return err } i.rawConn, err = ipv4.NewRawConn(i.packetConn) return err }
func ExampleRawConn_advertisingOSPFHello() { c, err := net.ListenPacket(fmt.Sprintf("ip4:%d", iana.ProtocolOSPFIGP), "0.0.0.0") // OSPF for IPv4 if err != nil { log.Fatal(err) } defer c.Close() r, err := ipv4.NewRawConn(c) if err != nil { log.Fatal(err) } en0, err := net.InterfaceByName("en0") if err != nil { log.Fatal(err) } allSPFRouters := net.IPAddr{IP: net.IPv4(224, 0, 0, 5)} if err := r.JoinGroup(en0, &allSPFRouters); err != nil { log.Fatal(err) } defer r.LeaveGroup(en0, &allSPFRouters) hello := make([]byte, 24) // fake hello data, you need to implement this ospf := make([]byte, 24) // fake ospf header, you need to implement this ospf[0] = 2 // version 2 ospf[1] = 1 // hello packet ospf = append(ospf, hello...) iph := &ipv4.Header{ Version: ipv4.Version, Len: ipv4.HeaderLen, TOS: iana.DiffServCS6, TotalLen: ipv4.HeaderLen + len(ospf), TTL: 1, Protocol: iana.ProtocolOSPFIGP, Dst: allSPFRouters.IP.To4(), } var cm *ipv4.ControlMessage switch runtime.GOOS { case "darwin", "linux": cm = &ipv4.ControlMessage{IfIndex: en0.Index} default: if err := r.SetMulticastInterface(en0); err != nil { log.Fatal(err) } } if err := r.WriteTo(iph, ospf, cm); err != nil { log.Fatal(err) } }
// Start kicks off the pinging process. It takes the list of IP addresses added by // AddIPs() and sends ICMP ECHO_REQUEST to all of them at the specified Interval. // Results are sent via the returned channel. The caller is expected to read the // channel so it won't get blocked. // // Only a single Start can be called at a time. If the second call to Start is made, // and error will be returned. func (this *Pinger) Start() (<-chan *PingResult, error) { if !atomic.CompareAndSwapInt64(&this.pid, 0, int64(os.Getpid()&0xffff)) { return nil, fmt.Errorf("ping/Start: Pinger already running") } switch runtime.GOOS { case "nacl", "plan9", "solaris", "windows": return nil, fmt.Errorf("ping/Start: Operation not supported on %q", runtime.GOOS) } if os.Getuid() != 0 { return nil, fmt.Errorf("ping/Start: User must be root") } this.updateParams() if len(this.payload) < this.Size { this.payload = make([]byte, this.Size) } else { this.payload = this.payload[:this.Size] } var err error this.pconn, err = net.ListenPacket("ip4:icmp", "0.0.0.0") if err != nil { return nil, err } this.rconn, err = ipv4.NewRawConn(this.pconn) if err != nil { return nil, err } cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface if err := this.rconn.SetControlMessage(cf, true); err != nil { //glog.Errorf("ping/sender: Error setting control message: %v", err) return nil, err } this.wg.Add(1) go this.receiver() this.wg.Add(1) go this.sender() return this.reschan, nil }
func TestIPPerInterfaceSingleRawConnWithSingleGroupListener(t *testing.T) { switch runtime.GOOS { case "nacl", "plan9", "windows": t.Skipf("not supported on %s", runtime.GOOS) } if testing.Short() { t.Skip("to avoid external network") } if m, ok := nettest.SupportsRawIPSocket(); !ok { t.Skip(m) } gaddr := net.IPAddr{IP: net.IPv4(224, 0, 0, 254)} // see RFC 4727 type ml struct { c *ipv4.RawConn ifi *net.Interface } var mlt []*ml ift, err := net.Interfaces() if err != nil { t.Fatal(err) } for i, ifi := range ift { ip, ok := nettest.IsMulticastCapable("ip4", &ifi) if !ok { continue } c, err := net.ListenPacket("ip4:253", ip.String()) // unicast address if err != nil { t.Fatal(err) } defer c.Close() r, err := ipv4.NewRawConn(c) if err != nil { t.Fatal(err) } if err := r.JoinGroup(&ifi, &gaddr); err != nil { t.Fatal(err) } mlt = append(mlt, &ml{r, &ift[i]}) } for _, m := range mlt { if err := m.c.LeaveGroup(m.ifi, &gaddr); err != nil { t.Fatal(err) } } }
func TestIPSingleRawConnWithSingleGroupListener(t *testing.T) { switch runtime.GOOS { case "nacl", "plan9", "windows": t.Skipf("not supported on %s", runtime.GOOS) } if testing.Short() { t.Skip("to avoid external network") } if m, ok := nettest.SupportsRawIPSocket(); !ok { t.Skip(m) } c, err := net.ListenPacket("ip4:icmp", "0.0.0.0") // wildcard address if err != nil { t.Fatal(err) } defer c.Close() r, err := ipv4.NewRawConn(c) if err != nil { t.Fatal(err) } gaddr := net.IPAddr{IP: net.IPv4(224, 0, 0, 254)} // see RFC 4727 var mift []*net.Interface ift, err := net.Interfaces() if err != nil { t.Fatal(err) } for i, ifi := range ift { if _, ok := nettest.IsMulticastCapable("ip4", &ifi); !ok { continue } if err := r.JoinGroup(&ifi, &gaddr); err != nil { t.Fatal(err) } mift = append(mift, &ift[i]) } for _, ifi := range mift { if err := r.LeaveGroup(ifi, &gaddr); err != nil { t.Fatal(err) } } }
func main() { flag.Parse() c, err := net.ListenPacket(fmt.Sprintf("ip4:%d", *proto), "0.0.0.0") if err != nil { log.Fatal(err) } defer c.Close() p, err := ipv4.NewRawConn(c) if err != nil { log.Fatal(err) } p.SetControlMessage(ipv4.FlagTTL|ipv4.FlagSrc|ipv4.FlagDst|ipv4.FlagInterface, true) b := make([]byte, 8192) for { h, pp, cm, err := p.ReadFrom(b) if err != nil { log.Println(err) continue } log.Printf("%d bytes rcvd, %v, %v\n", len(pp), h, cm) } }
func TestRawConnReadWriteUnicastICMP(t *testing.T) { switch runtime.GOOS { case "nacl", "plan9", "windows": t.Skipf("not supported on %s", runtime.GOOS) } if m, ok := nettest.SupportsRawIPSocket(); !ok { t.Skip(m) } ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagLoopback) if ifi == nil { t.Skipf("not available on %s", runtime.GOOS) } c, err := net.ListenPacket("ip4:icmp", "0.0.0.0") if err != nil { t.Fatal(err) } defer c.Close() dst, err := net.ResolveIPAddr("ip4", "127.0.0.1") if err != nil { t.Fatal(err) } r, err := ipv4.NewRawConn(c) if err != nil { t.Fatal(err) } defer r.Close() cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface for i, toggle := range []bool{true, false, true} { wb, err := (&icmp.Message{ Type: ipv4.ICMPTypeEcho, Code: 0, Body: &icmp.Echo{ ID: os.Getpid() & 0xffff, Seq: i + 1, Data: []byte("HELLO-R-U-THERE"), }, }).Marshal(nil) if err != nil { t.Fatal(err) } wh := &ipv4.Header{ Version: ipv4.Version, Len: ipv4.HeaderLen, TOS: i + 1, TotalLen: ipv4.HeaderLen + len(wb), TTL: i + 1, Protocol: 1, Dst: dst.IP, } if err := r.SetControlMessage(cf, toggle); err != nil { if nettest.ProtocolNotSupported(err) { t.Logf("not supported on %s", runtime.GOOS) continue } t.Fatal(err) } if err := r.SetWriteDeadline(time.Now().Add(100 * time.Millisecond)); err != nil { t.Fatal(err) } if err := r.WriteTo(wh, wb, nil); err != nil { t.Fatal(err) } rb := make([]byte, ipv4.HeaderLen+128) loop: if err := r.SetReadDeadline(time.Now().Add(100 * time.Millisecond)); err != nil { t.Fatal(err) } if _, b, _, err := r.ReadFrom(rb); err != nil { switch runtime.GOOS { case "darwin": // older darwin kernels have some limitation on receiving icmp packet through raw socket t.Logf("not supported on %s", runtime.GOOS) continue } t.Fatal(err) } else { m, err := icmp.ParseMessage(iana.ProtocolICMP, b) if err != nil { t.Fatal(err) } if runtime.GOOS == "linux" && m.Type == ipv4.ICMPTypeEcho { // On Linux we must handle own sent packets. goto loop } if m.Type != ipv4.ICMPTypeEchoReply || m.Code != 0 { t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 0) } } } }
func TestRawConnReadWriteMulticastICMP(t *testing.T) { if testing.Short() { t.Skip("to avoid external network") } if m, ok := nettest.SupportsRawIPSocket(); !ok { t.Skip(m) } ifi := nettest.RoutedInterface("ip4", net.FlagUp|net.FlagMulticast|net.FlagLoopback) if ifi == nil { t.Skipf("not available on %s", runtime.GOOS) } for _, tt := range rawConnReadWriteMulticastICMPTests { c, err := net.ListenPacket("ip4:icmp", "0.0.0.0") if err != nil { t.Fatal(err) } defer c.Close() r, err := ipv4.NewRawConn(c) if err != nil { t.Fatal(err) } defer r.Close() if tt.src == nil { if err := r.JoinGroup(ifi, tt.grp); err != nil { t.Fatal(err) } defer r.LeaveGroup(ifi, tt.grp) } else { if err := r.JoinSourceSpecificGroup(ifi, tt.grp, tt.src); err != nil { switch runtime.GOOS { case "freebsd", "linux": default: // platforms that don't support IGMPv2/3 fail here t.Logf("not supported on %s", runtime.GOOS) continue } t.Fatal(err) } defer r.LeaveSourceSpecificGroup(ifi, tt.grp, tt.src) } if err := r.SetMulticastInterface(ifi); err != nil { t.Fatal(err) } if _, err := r.MulticastInterface(); err != nil { t.Fatal(err) } if err := r.SetMulticastLoopback(true); err != nil { t.Fatal(err) } if _, err := r.MulticastLoopback(); err != nil { t.Fatal(err) } cf := ipv4.FlagTTL | ipv4.FlagDst | ipv4.FlagInterface for i, toggle := range []bool{true, false, true} { wb, err := (&icmp.Message{ Type: ipv4.ICMPTypeEcho, Code: 0, Body: &icmp.Echo{ ID: os.Getpid() & 0xffff, Seq: i + 1, Data: []byte("HELLO-R-U-THERE"), }, }).Marshal(nil) if err != nil { t.Fatal(err) } wh := &ipv4.Header{ Version: ipv4.Version, Len: ipv4.HeaderLen, TOS: i + 1, TotalLen: ipv4.HeaderLen + len(wb), Protocol: 1, Dst: tt.grp.IP, } if err := r.SetControlMessage(cf, toggle); err != nil { if nettest.ProtocolNotSupported(err) { t.Logf("not supported on %s", runtime.GOOS) continue } t.Fatal(err) } if err := r.SetDeadline(time.Now().Add(200 * time.Millisecond)); err != nil { t.Fatal(err) } r.SetMulticastTTL(i + 1) if err := r.WriteTo(wh, wb, nil); err != nil { t.Fatal(err) } rb := make([]byte, ipv4.HeaderLen+128) if rh, b, _, err := r.ReadFrom(rb); err != nil { t.Fatal(err) } else { m, err := icmp.ParseMessage(iana.ProtocolICMP, b) if err != nil { t.Fatal(err) } switch { case (rh.Dst.IsLoopback() || rh.Dst.IsLinkLocalUnicast() || rh.Dst.IsGlobalUnicast()) && m.Type == ipv4.ICMPTypeEchoReply && m.Code == 0: // net.inet.icmp.bmcastecho=1 case rh.Dst.IsMulticast() && m.Type == ipv4.ICMPTypeEcho && m.Code == 0: // net.inet.icmp.bmcastecho=0 default: t.Fatalf("got type=%v, code=%v; want type=%v, code=%v", m.Type, m.Code, ipv4.ICMPTypeEchoReply, 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 } } } } } }
//sendPacket generates & sends a packet of arbitrary size to a specific destination. //The size specified should be larger then 40bytes. func sendPacket(sourceIP string, destinationIP string, size int, message string, appID int, chanID int, icmpType layers.ICMPv4TypeCode) []byte { var payloadSize int if size < 28 { //Unable to create smaller packets. payloadSize = 0 } else { payloadSize = size - 28 } //Convert IP to 4bit representation srcIP := net.ParseIP(sourceIP).To4() dstIP := net.ParseIP(destinationIP).To4() //IP Layer ip := layers.IPv4{ SrcIP: srcIP, DstIP: dstIP, Version: 4, TTL: 64, Protocol: layers.IPProtocolICMPv4, } icmp := layers.ICMPv4{ TypeCode: icmpType, } opts := gopacket.SerializeOptions{ FixLengths: true, ComputeChecksums: true, } ipHeaderBuf := gopacket.NewSerializeBuffer() err := ip.SerializeTo(ipHeaderBuf, opts) if err != nil { panic(err) } //Set "Don't Fragment"-Flag in Header ipHeader, err := ipv4.ParseHeader(ipHeaderBuf.Bytes()) ipHeader.Flags |= ipv4.DontFragment if err != nil { panic(err) } payloadBuf := gopacket.NewSerializeBuffer() //Influence the payload size payload := gopacket.Payload(generatePayload(payloadSize, ","+strconv.Itoa(appID)+","+strconv.Itoa(chanID)+","+message+",")) err = gopacket.SerializeLayers(payloadBuf, opts, &icmp, payload) if err != nil { panic(err) } //Send packet var packetConn net.PacketConn var rawConn *ipv4.RawConn packetConn, err = net.ListenPacket("ip4:icmp", srcIP.String()) if err != nil { panic(err) } rawConn, err = ipv4.NewRawConn(packetConn) if err != nil { panic(err) } err = rawConn.WriteTo(ipHeader, payloadBuf.Bytes(), nil) return append(ipHeaderBuf.Bytes(), payloadBuf.Bytes()...) }