func main() { ifce, err := water.NewTAP("tap0") fmt.Printf("%v, %v\n\n", err, ifce) buffer := make([]byte, BUFFERSIZE) for { _, err = ifce.Read(buffer) if err != nil { fmt.Printf("err = %v\n", err) break } ethertype := waterutil.MACEthertype(buffer) fmt.Printf("ethertype = %#v\n", ethertype) if ethertype == waterutil.IPv4 { packet := waterutil.MACPayload(buffer) if waterutil.IsIPv4(packet) { fmt.Printf("IPv4 Source: %v [%v]\n", waterutil.MACSource(buffer), waterutil.IPv4Source(packet)) fmt.Printf("IPv4 Destination: %v [%v]\n", waterutil.MACDestination(buffer), waterutil.IPv4Destination(packet)) fmt.Printf("IPv4 Protocol: %v\n\n", waterutil.IPv4Protocol(packet)) } else if waterutil.IsIPv6(packet) { fmt.Printf("IPv6 Source: %v\n", waterutil.MACSource(buffer)) fmt.Printf("IPv6 Destination: %v\n\n", waterutil.MACDestination(buffer)) } else { fmt.Printf("unknow Source: %v\n", waterutil.MACSource(buffer)) fmt.Printf("unknow Destination: %v\n\n", waterutil.MACDestination(buffer)) } } } }
func updateChecksum(datagram []byte) { ipv4_hdr_len := 4 * (datagram[0] & 0x0F) datagram[ipv4_hdr_len+16] = 0 datagram[ipv4_hdr_len+17] = 0 csum := Csum(datagram[ipv4_hdr_len:], IPTo4le(waterutil.IPv4Source(datagram)), IPTo4le(waterutil.IPv4Destination(datagram))) datagram[ipv4_hdr_len+16] = (byte)(csum >> 8) datagram[ipv4_hdr_len+17] = (byte)(csum & 0xFF) }
func TestBroadcast(t *testing.T) { var ( self = net.IPv4(10, 0, 42, 1) mask = net.IPv4Mask(255, 255, 255, 0) brd = net.IPv4(10, 0, 42, 255) ) ifce, err := NewTAP("test") if err != nil { t.Fatalf("creating TAP error: %v\n", err) } setupIfce(t, net.IPNet{IP: self, Mask: mask}, ifce.Name()) startBroadcast(t, brd) dataCh := make(chan []byte, 8) startRead(dataCh, ifce) timeout := time.NewTimer(8 * time.Second).C readFrame: for { select { case buffer := <-dataCh: ethertype := waterutil.MACEthertype(buffer) if ethertype != waterutil.IPv4 { continue readFrame } if !waterutil.IsBroadcast(waterutil.MACDestination(buffer)) { continue readFrame } packet := waterutil.MACPayload(buffer) if !waterutil.IsIPv4(packet) { continue readFrame } if !waterutil.IPv4Source(packet).Equal(self) { continue readFrame } if !waterutil.IPv4Destination(packet).Equal(brd) { continue readFrame } if waterutil.IPv4Protocol(packet) != waterutil.ICMP { continue readFrame } t.Logf("received broadcast frame: %#v\n", buffer) break readFrame case <-timeout: t.Fatal("Waiting for broadcast packet timeout") } } }
func HostProxy() { file, e := ioutil.ReadFile(*config_path) if e != nil { l_err.Printf("Config file open error: %v\n", e) os.Exit(1) } var config Config e_parse := json.Unmarshal(file, &config) if e_parse != nil { l_err.Printf("Config parse error: %v\n", e_parse) os.Exit(1) } // Get interface IP config_interface_ip := config.Proxy.SourceIP raw_sock, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_RAW, syscall.IPPROTO_RAW) if err != nil { panic(err) } err = syscall.SetsockoptInt(raw_sock, syscall.IPPROTO_IP, syscall.IP_HDRINCL, 1) if err != nil { panic(err) } // Length byte order cmd_stdoutQueue := make(chan interface{}, 10) cmd_stdinQueue := make(chan interface{}, 10) SpawnNodeSubprocess(*config_path, cmd_stdoutQueue, cmd_stdinQueue) proxy := NewProxyState() go proxy.doListen(syscall.IPPROTO_TCP) go proxy.doListen(syscall.IPPROTO_UDP) go func() { for { datagram := <-proxy.messages_to_send waterutil.SetIPv4Source(datagram, config_interface_ip) updateChecksum(datagram) destinationIP := waterutil.IPv4Destination(datagram) // Reverse byte order of IP for host byte order destinationIP4 := destinationIP.To4() dstAddrHost := [4]byte{destinationIP4[3], destinationIP4[2], destinationIP4[1], destinationIP4[0]} dstAddr := syscall.SockaddrInet4{Addr: dstAddrHost} // Swap header length byte order, for host byte order { x := datagram[2] datagram[2] = datagram[3] datagram[3] = x } err = syscall.Sendto(raw_sock, datagram, 0, &dstAddr) if err != nil { fmt.Fprintf(os.Stderr, "Error on sendto(): %v\n", err) } } }() // Process messages coming from node for { select { case datagram := <-proxy.messages_received: { local_port := LocalPort{ binary.BigEndian.Uint32(waterutil.IPv4Destination(datagram)), waterutil.IPv4DestinationPort(datagram), // TODO: UDP waterutil.TCP, } fmt.Fprintf(os.Stderr, "Main loop recvd from %v: %v\n", local_port, datagram) if source_port, exists := proxy.source_ports_by_local_ports[local_port]; exists { fmt.Fprintf(os.Stderr, "--- Exists\n") cmd_stdinQueue <- Stdin_SendBack{mesh.MeshMessage{source_port.SendId, source_port.ConnectedPeer, []byte{}}, datagram} } } case msg_out := <-cmd_stdoutQueue: { if reflect.TypeOf(msg_out) == reflect.TypeOf(Stdout_RecvMessage{}) { recv_msg := msg_out.(Stdout_RecvMessage) datagram := recv_msg.Contents protocol := waterutil.IPv4Protocol(datagram) if protocol == waterutil.TCP || protocol == waterutil.UDP { source := SourcePort{ recv_msg.SendId, recv_msg.ConnectedPeer, waterutil.IPv4SourcePort(datagram), binary.BigEndian.Uint32(waterutil.IPv4Source(datagram)), protocol, } port := proxy.portForSource(source) destinationIP := waterutil.IPv4Destination(datagram) fmt.Fprintf(os.Stderr, "\n<<<<<<<<<<< recv from source: %v use port %v dst %s\n", source, port, destinationIP) waterutil.SetIPv4SourcePort(datagram, port.Port) srcIP := make([]byte, 4) binary.LittleEndian.PutUint32(srcIP, port.IP) waterutil.SetIPv4Source(datagram, srcIP) waterutil.ZeroIPv4Checksum(datagram) proxy.messages_to_send <- datagram } } } } } }