Commit 2c3f7f20 authored by Nawasan Wisitsingkhon's avatar Nawasan Wisitsingkhon

save state

parent 9de005e8
pub enum EtherType {
IP = 0x0800,
ARP = 0x0806,
TEB = 0x6558,
VLAN = 0x8100,
IPV6 = 0x86dd,
SLOW = 0x8809,
MPLS = 0x8847,
SVLAN = 0x88a8,
LLDP = 0x88cc,
PBB = 0x88e7,
IEEE802_3 = 0x05dc,
CFM = 0x8902,
NSH = 0x894f,
}
use crate::etherparser::ether_type::EtherType;
use std::io::{BufRead, Cursor};
use byteorder::{BigEndian, ReadBytesExt};
use super::packet::IP;
struct EthernetFrame {
mac_des: u64,
mac_src: u64,
vlan: Option<u16>,
vlan_pcp: u8,
valn_dei: bool,
vlan_vid: u16,
}
impl EthernetFrame {
fn parse(payload: &Vec<u8>) {
let mut bytes = Cursor::new(*payload);
let mut mac_des = vec![0u8; 6];
let mut mac_src = vec![0u8; 6];
for i in 0..6 {
mac_des[i] = bytes.read_u8().unwrap();
}
for i in 0..6 {
mac_src[i] = bytes.read_u8().unwrap();
}
// check 802.1q tag tpid
let typ = bytes.read_u16::<BigEndian>().unwrap();
let (pcp, dei, vid, typ) = match typ {
tp if tp == EtherType::VLAN as u16 => {
let tci = bytes.read_u16::<BigEndian>().unwrap();
let pcp = tci >> 13;
let dei = (tci & 0x1000) > 0;
let vid = tci & 0xfff;
(pcp as u8, dei, Some(vid), typ)
}
_ => (0x0, false, None, typ),
};
let ip_header = match typ {
tp if tp == EtherType::IP as u16 => {
let ip = IP::parse(&mut bytes);
if ip.is_some() {
Network::IP(ip.unwrap())
} else {
Network::Unparsable(typ, bytes.fill_buf().unwrap().to_vec())
}
}
// tp if tp == (EtherType::ARP as u16) => {
// }
_ => Network::Unparsable(typ, bytes.fill_buf().unwrap().to_vec()),
};
}
}
pub enum Network {
IP(IP),
Unparsable(u16, Vec<u8>),
}
pub mod ether_type;
pub mod ethernet;
pub mod packet;
pub mod tools;
\ No newline at end of file
use std::io::{BufRead, Cursor};
use byteorder::{BigEndian, ReadBytesExt};
pub struct ICMP {
pub typ: u8,
pub code: u8,
pub checksum: u16,
pub payload: Vec<u8>,
}
impl ICMP {
pub fn size_of() -> usize {
4
}
pub fn parse(bytes: &mut Cursor<Vec<u8>>) -> Option<ICMP> {
if bytes.get_ref().len() < 4 {
return None;
}
let typ = bytes.read_u8().unwrap();
let code = bytes.read_u8().unwrap();
let checksum = bytes.read_u16::<BigEndian>().unwrap();
let payload = bytes.fill_buf().unwrap().to_vec();
Some(ICMP {
typ,
code,
checksum,
payload,
})
}
}
use super::{tcp::TCP, udp::UDP, ICMP};
use byteorder::{BigEndian, ReadBytesExt};
use std::io::{BufRead, Cursor, Read};
struct Flags {
dont_flagment: bool,
more_fragments: bool,
}
pub struct IP {
pub version: u8,
pub ihl: u8,
pub tos: u8,
pub length: u16,
pub ident: u16,
pub flags: Flags,
pub fragment: u16,
pub ttl: u8,
pub protocol: u8,
pub checksum: u16,
pub src: u32,
pub des: u32,
pub options: Vec<u8>,
}
pub enum IpProtocol {
ICMP = 0x01,
TCP = 0x06,
UDP = 0x11,
}
impl IP {
pub fn parse(bytes: &mut Cursor<Vec<u8>>) -> Option<IP> {
if bytes.get_ref().len() < 20 {
return None;
}
let version_ihl = bytes.read_u8().unwrap();
let version = version_ihl >> 4;
if version != 4 {
return None;
}
let ihl = version_ihl & 0x0f;
let tos = bytes.read_u8().unwrap();
let length = bytes.read_u16::<BigEndian>().unwrap();
let ident = bytes.read_u16::<BigEndian>().unwrap();
let fragment = bytes.read_u16::<BigEndian>().unwrap();
let flags = Flags {
dont_flagment: (fragment & 0x8000) > 0,
more_fragments: (fragment >> 0x4000) > 0,
};
let ttl = bytes.read_u8().unwrap();
let protocol = bytes.read_u8().unwrap();
let checksum = bytes.read_u16::<BigEndian>().unwrap();
let src = bytes.read_u32::<BigEndian>().unwrap();
let des = bytes.read_u32::<BigEndian>().unwrap();
let option_len = (ihl * 4) as usize - 20;
let mut options = vec![0u8; option_len];
bytes.read_exact(&mut options).unwrap();
let ptcol = match protocol {
ptc if ptc == (IpProtocol::ICMP as u8) => {
let icmp = ICMP::parse(bytes);
match icmp {
Some(v) => EtherData::ICMP(v),
None => EtherData::Unparse(protocol, bytes.fill_buf().unwrap().to_vec()),
}
}
ptc if ptc == (IpProtocol::TCP as u8) => {
let tcp = TCP::parser(bytes);
if tcp.is_some() {
EtherData::TCP(tcp.unwrap())
} else {
EtherData::Unparse(protocol, bytes.fill_buf().unwrap().to_vec())
}
}
ptc if ptc == (IpProtocol::UDP as u8) => {
let udp = UDP::parser(bytes);
if udp.is_some() {
EtherData::UDP(udp.unwrap())
} else {
EtherData::Unparse(protocol, bytes.fill_buf().unwrap().to_vec())
}
}
_ => EtherData::Unparse(protocol, bytes.fill_buf().unwrap().to_vec()),
};
Some(IP {
version,
ihl,
length,
protocol,
tos,
ident,
flags,
fragment,
ttl,
checksum,
src,
des,
options,
})
}
}
pub enum EtherData {
ICMP(ICMP),
TCP(TCP),
UDP(UDP),
Unparse(u8, Vec<u8>),
}
pub mod icmp;
pub use icmp::ICMP;
pub mod tcp;
pub use tcp::TCP;
pub mod udp;
pub mod ipv4;
pub use ipv4::{IP, EtherData, IpProtocol};
\ No newline at end of file
use crate::etherparser::tools::bits::bit_bool;
use byteorder::{BigEndian, ReadBytesExt};
use std::io::{BufRead, Cursor};
pub struct TCP {
pub src_port: u16,
pub des_port: u16,
pub seq: u32,
pub ack: u32,
pub offset: u8,
pub flags: TcpFlags,
pub window: u16,
pub checksum: u16,
pub urgent: u16,
pub payload: Vec<u8>,
}
impl TCP {
pub fn size_of() -> usize {
20
}
pub fn parser(bytes: &mut Cursor<Vec<u8>>) -> Option<TCP> {
if bytes.get_ref().len() < TCP::size_of() {
return None;
}
let src_port = bytes.read_u16::<BigEndian>().unwrap();
let des_port = bytes.read_u16::<BigEndian>().unwrap();
let seq = bytes.read_u32::<BigEndian>().unwrap();
let ack = bytes.read_u32::<BigEndian>().unwrap();
let dataoff_reserv_flags = bytes.read_u16::<BigEndian>().unwrap();
let flags = TcpFlags::parser(dataoff_reserv_flags);
let offset = (dataoff_reserv_flags >> 12) as u8 & 0x0f;
let window = bytes.read_u16::<BigEndian>().unwrap();
let checksum = bytes.read_u16::<BigEndian>().unwrap();
let urgent = bytes.read_u16::<BigEndian>().unwrap();
let payload = bytes.fill_buf().unwrap().to_vec();
Some(TCP {
src_port,
des_port,
seq,
ack,
offset,
flags,
window,
checksum,
urgent,
payload,
})
}
}
pub struct TcpFlags {
pub ns: bool,
pub cwr: bool,
pub ece: bool,
pub urg: bool,
pub ack: bool,
pub psh: bool,
pub rst: bool,
pub syn: bool,
pub fin: bool,
}
impl TcpFlags {
pub fn parser(bytes: u16) -> TcpFlags {
TcpFlags {
ns: bit_bool(0, bytes),
cwr: bit_bool(1, bytes),
ece: bit_bool(2, bytes),
urg: bit_bool(3, bytes),
ack: bit_bool(4, bytes),
psh: bit_bool(5, bytes),
rst: bit_bool(6, bytes),
syn: bit_bool(7, bytes),
fin: bit_bool(8, bytes),
}
}
}
use std::io::{BufRead, Cursor};
use byteorder::{BigEndian, ReadBytesExt};
pub struct UDP {
pub src_port: u16,
pub des_port: u16,
pub checksum: u16,
pub payload: Vec<u8>,
}
impl UDP {
pub fn sizeof() -> usize {
8
}
pub fn parser(bytes: &mut Cursor<Vec<u8>>) -> Option<UDP> {
if bytes.get_ref().len() < UDP::sizeof() {
return None;
}
let src_port = bytes.read_u16::<BigEndian>().unwrap();
let des_port = bytes.read_u16::<BigEndian>().unwrap();
let checksum = bytes.read_u16::<BigEndian>().unwrap();
let payload = bytes.fill_buf().unwrap().to_vec();
Some(UDP {
src_port,
des_port,
checksum,
payload,
})
}
}
pub fn bit_bool(position: u16, byte: u16) -> bool {
(byte >> position) & 1 == 1
}
pub mod bits;
\ No newline at end of file
pub mod openflow;
pub mod etherparser;
\ No newline at end of file
......@@ -40,6 +40,7 @@ fn main() -> Result<(), std::io::Error> {
println!("Hello event");
}
Msg::PacketIn(b) => {
controller.packetIn(xid, &payload, &mut stream);
println!("PacketIn event");
}
_ => {
......
use std::{io::Write, mem::size_of, net::TcpStream};
use byteorder::{BigEndian, WriteBytesExt};
use etherparse::SlicedPacket;
use super::OfpHeader;
......@@ -27,6 +28,16 @@ impl Controller {
stream.write_all(&bytes).unwrap();
}
pub fn packetIn(&self, xid: u32, payload: &Vec<u8>, stream: &mut TcpStream) {
match SlicedPacket::from_ethernet(&payload) {
Ok(value) => {
println!("vlan {:?}", value.vlan);
println!("net {:?}", value.net);
},
Err(_) => println!("Error"),
}
}
pub fn send(&self, xid: u32, message: u8, payload: &Vec<u8>, stream: &mut TcpStream) {
let length = size_of::<OfpHeader>() + payload.len();
let header = OfpHeader::new(self.version, message, length as u16, xid);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment