func (sender *RawUDPSender) Send(msg []byte) error { payload := gopacket.Payload(msg) sender.udpHeader.DstPort = layers.UDPPort(sender.conn.RemoteUDPAddr().Port) err := gopacket.SerializeLayers(sender.ipBuf, sender.opts, sender.udpHeader, &payload) if err != nil { return err } packet := sender.ipBuf.Bytes() _, err = sender.socket.Write(packet) if err == nil || PosixError(err) != syscall.EMSGSIZE { return err } f, err := sender.socket.File() if err != nil { return err } defer f.Close() fd := int(f.Fd()) log.Println("EMSGSIZE on send, expecting PMTU update (IP packet was", len(packet), "bytes, payload was", len(msg), "bytes)") pmtu, err := syscall.GetsockoptInt(fd, syscall.IPPROTO_IP, syscall.IP_MTU) if err != nil { return err } return MsgTooBigError{PMTU: pmtu} }
func (t *Nat) In(p Packet) (b []byte) { //ioutil.WriteFile("/tmp/b.pkt", pkt.Data(), 0777) var k uint16 var srcPort uint16 if p.tcp != nil { srcPort = uint16(p.tcp.SrcPort) } else { srcPort = uint16(p.udp.SrcPort) } k = t.Hash(p.ip, srcPort) log.Println("socket <<<", p) c, _ := t.table[k] if ((p.tcp != nil && p.tcp.SYN) || p.udp != nil) && c == nil { log.Println("nat new", k) c = &natConn{ Ts: time.Now(), SrcPort: srcPort, SrcIP: p.ip.SrcIP, SrcMAC: p.eth.SrcMAC, DstMAC: p.eth.DstMAC, } t.table[k] = c } p.ip.SrcIP = myip p.eth.SrcMAC = mymac p.eth.DstMAC = gwmac if p.tcp != nil { p.tcp.SrcPort = layers.TCPPort(k) } else { p.udp.SrcPort = layers.UDPPort(k) } UpdatePkt(&p) log.Println("wire >>>", p) return p.data }
func NewRawUDPSender(conn *LocalConnection) (*RawUDPSender, error) { ipSocket, err := dialIP(conn) if err != nil { return nil, err } udpHeader := &layers.UDP{SrcPort: layers.UDPPort(Port)} ipBuf := gopacket.NewSerializeBuffer() opts := gopacket.SerializeOptions{ FixLengths: true, // UDP header is calculated with a phantom IP // header. Yes, it's totally nuts. Thankfully, for UDP // over IPv4, the checksum is optional. It's not // optional for IPv6, but we'll ignore that for // now. TODO ComputeChecksums: false} return &RawUDPSender{ ipBuf: ipBuf, opts: opts, udpHeader: udpHeader, socket: ipSocket, conn: conn}, nil }
func (t *Nat) Out(p Packet) (b []byte) { var k uint16 if p.tcp != nil { k = uint16(p.tcp.DstPort) } else { k = uint16(p.udp.DstPort) } c, _ := t.table[k] if c == nil { return } log.Println("wire <<<", p) p.eth.SrcMAC = c.DstMAC p.eth.DstMAC = c.SrcMAC p.ip.DstIP = c.SrcIP if p.tcp != nil { p.tcp.DstPort = layers.TCPPort(c.SrcPort) if p.tcp.FIN || p.tcp.RST { log.Println("nat del", k) delete(t.table, k) } } else { p.udp.DstPort = layers.UDPPort(c.SrcPort) } UpdatePkt(&p) c.Ts = time.Now() log.Println("socket >>>", p) return p.data }