Envoy/Downloads/GoNetDev-master/Protocols/IPV4.go

148 lines
4.2 KiB
Go

package Protocols
import (
"encoding/binary"
"fmt"
"github.com/sabouaram/GoNetDev/Protocols/Const_Fields"
"github.com/sabouaram/GoNetDev/Protocols/Utils"
"math"
"net"
"strconv"
)
// RFC 791 INTERNET PROTOCOL VERSION 4
/* Developer: Salim BOU ARAM, e-mail: salimbouaram12@gmail.com */
type IP struct {
Version_HL []byte
DS []byte
Total_Length []byte
Identification []byte
Flags []byte
TTL []byte
Protocol []byte
Header_checksum []byte
Src_address []byte
Dst_address []byte
}
type Packet struct {
IPH *IP
Data []byte
}
func NewIpv4Header() (header *IP) {
return &IP{}
}
func (Ip *IP) BuildIPV4Header(IPsrc string, IPdest string, Protocol uint8) {
IPheader := []byte{Const_Fields.Version_Hl_IPV4, Const_Fields.DS, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, Const_Fields.TTL, Protocol, 0x00, 0x00}
Ip.Version_HL = IPheader[0:1]
Ip.DS = IPheader[1:2]
Ip.Total_Length = IPheader[2:4]
Ip.Identification = IPheader[4:6]
Ip.Flags = IPheader[6:8]
Ip.TTL = IPheader[8:9]
Ip.Protocol = IPheader[9:10]
Ip.Header_checksum = IPheader[10:12]
Ip.Src_address = net.ParseIP(IPsrc).To4()
Ip.Dst_address = net.ParseIP(IPdest).To4()
Ip.HeaderChecksum()
}
func (Header *IP) IPV4Bytes() []byte {
return Utils.ConcatAppend([][]byte{Header.Version_HL, Header.DS, Header.Total_Length, Header.Identification, Header.Flags, Header.TTL, Header.Protocol, Header.Header_checksum, Header.Src_address, Header.Dst_address})
}
func Fragment(data []byte, MTU int, Protocol uint8, IPsrc string, IPdest string) (Packets map[int]Packet) {
results := make(map[int]Packet)
data_size := len(data)
fragment_count := int(math.Ceil(float64(data_size) / float64(MTU)))
offset := 0
Identification_bits := uint16(0x0000) // Initialize Identification_bits
for k := 0; k < fragment_count; k++ {
IP := NewIpv4Header()
IP.BuildIPV4Header(IPsrc, IPdest, Protocol)
IP.SetSRC(IPsrc)
IP.SetDST(IPdest)
Total_Length := 20
var flags_hex uint16
if k < fragment_count-1 {
IP.Total_Length = []byte{uint8(uint16(Total_Length+MTU-34) >> 8), uint8(uint16(Total_Length+MTU-34) & 0xff)}
IP.Identification = []byte{uint8(Identification_bits >> 8), uint8(Identification_bits & 0xff)}
flags_hex = uint16(0x2000) // More fragments
Identification_bits++
} else {
IP.Total_Length = []byte{uint8(uint16(Total_Length+data_size-offset) >> 8), uint8(uint16(Total_Length+data_size-offset) & 0xff)}
IP.Identification = []byte{uint8(Identification_bits >> 8), uint8(Identification_bits & 0xff)}
flags_hex = uint16(0x0000) // Last fragment
}
IP.Flags = []byte{uint8(flags_hex >> 8), uint8(flags_hex & 0xff)}
IP.HeaderChecksum()
fragmentSize := MTU - 34
if k == fragment_count-1 {
fragmentSize = data_size - offset
}
results[k] = Packet{IP, data[offset : offset+fragmentSize]}
offset += fragmentSize
}
return results
}
func (Header *IP) HeaderChecksum() {
intsum := int64(0)
header_bytes := Header.IPV4Bytes()
for i := 0; i <= 18; i += 2 {
hex_string_2 := fmt.Sprintf("%x", header_bytes[i:i+2])
uintsumf, _ := strconv.ParseUint(hex_string_2, 16, 16)
intsum += int64(uintsumf)
if intsum > 65536 {
intsum -= 65536
}
}
header_cheksum := uint16(intsum) ^ 0xffff
binary.BigEndian.PutUint16(Header.Header_checksum, header_cheksum)
}
func (Header *IP) SetSRC(ipstring string) {
Header.Src_address = []byte{}
Header.Src_address = net.ParseIP(ipstring).To4()
}
func (Header *IP) SetDST(ipstring string) {
Header.Dst_address = []byte{}
Header.Dst_address = net.ParseIP(ipstring).To4()
}
func (Header *IP) ReverseSrc() {
ipdst := Header.Dst_address
Header.Dst_address = Header.Src_address
Header.Src_address = ipdst
}
func (Header *IP) GetProtocol() uint8 {
return Header.Protocol[0]
}
func (Header *IP) SetDS(label uint8) {
Header.DS = []byte{}
Header.DS = append(Header.DS, label)
}
func (Header *IP) ParseIPV4(byte_slice []byte) {
Header.Version_HL = byte_slice[0:1]
Header.DS = byte_slice[1:2]
Header.Total_Length = byte_slice[2:4]
Header.Identification = byte_slice[4:6]
Header.Flags = byte_slice[6:8]
Header.TTL = byte_slice[8:9]
Header.Protocol = byte_slice[9:10]
Header.Header_checksum = byte_slice[10:12]
Header.Src_address = byte_slice[12:16]
Header.Dst_address = byte_slice[16:20]
}