// With an unsafe.Pointer to the block of C memory NewUdpHdr returns a filled in UdpHdr struct. func NewUdpHdr(p unsafe.Pointer) (*UdpHdr, unsafe.Pointer) { udpHead := &UdpHdr{ cptr: (*C.struct_udphdr)(p), } udpHead.Source = uint16(C.ntohs(C.uint16_t(udpHead.cptr.source))) udpHead.Dest = uint16(C.ntohs(C.uint16_t(udpHead.cptr.dest))) udpHead.Len = uint16(C.ntohs(C.uint16_t(udpHead.cptr.len))) udpHead.Check = uint16(C.ntohs(C.uint16_t(udpHead.cptr.check))) udpHead.payload = unsafe.Pointer(uintptr(p) + 8) return udpHead, udpHead.payload }
// With an unsafe.Pointer to the block of C memory NewIp6Hdr returns a filled in Ip6Hdr struct. func NewIp6Hdr(p unsafe.Pointer) (*Ip6Hdr, unsafe.Pointer) { ip6Hdr := &Ip6Hdr{ cptr: (*C.struct_ip6_hdr)(p), // The fixed header of an IPv6 packet consists of its first 40 octets. payload: unsafe.Pointer(uintptr(p) + uintptr(40)), } ip6Hdr.SrcAddr = net.IP(C.GoBytes(unsafe.Pointer(&ip6Hdr.cptr.ip6_src), 16)) ip6Hdr.DstAddr = net.IP(C.GoBytes(unsafe.Pointer(&ip6Hdr.cptr.ip6_dst), 16)) u := (*C.struct_ip6_hdrctl)(unsafe.Pointer(&ip6Hdr.cptr.ip6_ctlun)) ip6Hdr.NextHeader = uint8(u.ip6_un1_nxt) ip6Hdr.PayloadLen = uint16(C.ntohs(u.ip6_un1_plen)) return ip6Hdr, ip6Hdr.payload }
// With an unsafe.Pointer to the block of C memory NewIpHdr returns a filled in IpHdr struct. func NewIpHdr(p unsafe.Pointer) (*IpHdr, unsafe.Pointer) { iphdr := &IpHdr{ cptr: (*C.struct_iphdr)(p), // Since cgo does not provide access to bit fields in a struct // we take the first octet and then mask the unneeded bits. Ihl: *(*byte)(p) & 0x0F, // Since cgo does not provide access to bit fields in a struct // we take the first octet and then shift out the unneeded bits. Version: *(*byte)(p) >> 4, } iphdr.SrcAddr = net.IP(C.GoBytes(unsafe.Pointer(&iphdr.cptr.saddr), 4)) iphdr.DstAddr = net.IP(C.GoBytes(unsafe.Pointer(&iphdr.cptr.daddr), 4)) iphdr.Protocol = uint8(iphdr.cptr.protocol) iphdr.TotLen = uint16(C.ntohs(C.uint16_t(iphdr.cptr.tot_len))) iphdr.PayloadLen = iphdr.TotLen - uint16(iphdr.Ihl*4) iphdr.payload = unsafe.Pointer(uintptr(p) + uintptr(iphdr.Ihl*4)) return iphdr, iphdr.payload }
// With an unsafe.Pointer to the block of C memory NewEthHdr returns a filled in EthHdr struct. func NewEthHdr(p unsafe.Pointer) (*EthHdr, unsafe.Pointer) { ethHdr := &EthHdr{ cptr: (*C.struct_ether_header)(p), } ethHdr.SrcAddr = net.HardwareAddr(C.GoBytes(unsafe.Pointer(ðHdr.cptr.ether_shost), C.ETH_ALEN)) ethHdr.DstAddr = net.HardwareAddr(C.GoBytes(unsafe.Pointer(ðHdr.cptr.ether_dhost), C.ETH_ALEN)) ethHdr.EtherType = uint16(C.ntohs(C.uint16_t(ethHdr.cptr.ether_type))) // When using the Linux "any" device we have to handle cooked headers. // To determine if you could be in this case you can use pcap_datalink() // and check for DLT_LINUX_SLL. //TODO(gavaletz) This is an example of a decision that could be made once // outside the process of decoding packets as if one is like this they // will all be like this. if ethHdr.EtherType == 0 { // The "cooked" headers have an extra two bytes. ethHdr.payload = unsafe.Pointer(uintptr(p) + uintptr(C.ETHER_HDR_LEN) + uintptr(2)) } else { ethHdr.payload = unsafe.Pointer(uintptr(p) + uintptr(C.ETHER_HDR_LEN)) } return ethHdr, ethHdr.payload }
// With an unsafe.Pointer to the block of C memory NewTcpHdr returns a filled in TcpHdr struct. func NewTcpHdr(p unsafe.Pointer) (*TcpHdr, unsafe.Pointer) { tcpHead := &TcpHdr{ cptr: (*C.struct_tcphdr)(p), // Since cgo does not provide access to bit fields in a struct // we index 12 octets in and then shift out the unneeded bits. Doff: *(*byte)(unsafe.Pointer(uintptr(p) + uintptr(12))) >> 4, } tcpHead.Source = uint16(C.ntohs(C.uint16_t(tcpHead.cptr.source))) tcpHead.Dest = uint16(C.ntohs(C.uint16_t(tcpHead.cptr.dest))) tcpHead.Seq = uint32(C.ntohl(C.uint32_t(tcpHead.cptr.seq))) tcpHead.AckSeq = uint32(C.ntohl(C.uint32_t(tcpHead.cptr.ack_seq))) // A this time (and there are no plans to support it) cgo does not // provide access to bit fields in a struct so this is what we are stuck // with. We index 12 octets in and then use a bit mask. tcpHead.Flags = uint16(C.ntohs(C.uint16_t( *(*uint16)(unsafe.Pointer(uintptr(p) + uintptr(12)))))) & uint16(0x01FF) tcpHead.Window = uint16(C.ntohs(C.uint16_t(tcpHead.cptr.window))) tcpHead.Check = uint16(C.ntohs(C.uint16_t(tcpHead.cptr.check))) tcpHead.UrgPtr = uint16(C.ntohs(C.uint16_t(tcpHead.cptr.urg_ptr))) tcpHead.payload = unsafe.Pointer(uintptr(p) + uintptr(tcpHead.Doff*4)) return tcpHead, tcpHead.payload }
// Id returns the identification of the IP flow. func (h *IpHdr) Id() uint16 { return uint16(C.ntohs(C.uint16_t(h.cptr.id))) }