دوستانی که علاقمند به برنامه نویسی پایه پشته tcp/ip می توانند واقعیت پیاده سازی را با استفاده از این کد درک کنند، این کد بخشی از پروژه شبیه سازی شبکه های کامپیوتری که به شکل کد باز در اختیار علاقمندان و من جمله دانشجویان علاقمند قرار می دهم. در ضمن اسناد RFC و لینک هایی که برای کدنویسی از آنها استفاده کردم در بالای کد رفرنس شدند.
پیشنهادات و انتقادات شما باعث دلگرمی بنده خواهد بود.
%redesign of ip layer in tcp/ip stack
% refence:
%1-https://en.wikipedia.org/wiki/List_of_RFCs
%2-https://en.wikipedia.org/wiki/List_of_RFCs
%3-https://www.rfc-editor.org/search/rfc_search_detail.php?page=All&pubstatus[]=Any&pub_date_type=any&sortkey=Number&sorting=ASC
%4-http://www.tcpipguide.com/free/t_ARPMessageFormat.htm
%5- https://www.colasoft.com/help/7.1/appe_codes_ethernet.html
%5-Packet Tracer help
% Warning: all code we used here are decimals not hex! but all are Imitation from hex valus!!
classdef link
properties
% internetLayerAgent= tcpIp.internet
broadMac
end
methods
function ap=link()
global maxMac;
ap.broadMac=maxMac;
end
function pdu=linkProt(linkLayer,pdu,netObj)
if isfield(pdu,'ethernet')
%means that pdu is incomming pdu
inProcPortIndex=netObj.QueueinProcPortIndex(end);
inProcPortName=netObj.ports(inProcPortIndex).name;
switch netObj.typeDevice
case 1
%PcObj
if isfield(pdu,'arp')
if strcmp(pdu.arp.SPA,pdu.arp.TPA) && strcmp(pdu.ethernet.destnation,'FF:FF:FF:FF:FF:FF')
%update arp message
srcIndex=find(strcmp(netObj.ARP_Table.hardWareAddress, pdu.arp.SHA ), 1);
if ~isempty(srcIndex)
netObj.ARP_Table{srcIndex,:}={pdu.arp.SPA ,pdu.ethernet.source,inProcPortName};
netObj.ioControlFlag(2)=1;
else
netObj.ioControlFlag(1)=1;
end
else
if strcmp(pdu.arp.TPA,netObj.ports(inProcPortIndex).ip) && strcmp(pdu.ethernet.destnation,'FF:FF:FF:FF:FF:FF')
packet=[];
packet.HRD=1;%packetDat.HRD;%defaultt=1, hardware type 1= Ethernet , 6=IEEE 802 Network, 7=ARCNET, 15=Frame Relay, 16= Asynchronous Transfer Mode(ATM, 17= HDLC ,18=Fibr Channel, 20=serialLine
packet.PRO=800;%packetDat.PRO;%defaultt=8 as ip4;Protocol Type: This field is the complement of the Hardware Type field, specifying the type of layer three addresses used in the message. For IPv4 addresses, this value is 2048 (0800 hex), which corresponds to the EtherType code for the Internet Protocol.
packet.HLN=6;%packetDat.HLN;%defaultt=6 ,Hardware Address Length: Specifies how long hardware addresses are in this message. For Ethernet or other networks using IEEE 802 MAC addresses, the value is 6.
packet.PLN=4;%packetDat.PLN;%defaultt=4 ,Protocol Address Length: Again, the complement of the preceding field; specifies how long protocol (layer three) addresses are in this message. For IP(v4) addresses this value is of course 4.
packet.OP=2;%defaultt=1 ,op code,1= arp request, 2= arp reply,3=RARP request, 4= RARP reply, 5=DRARP request, 6= DRARP reply,7= DRARP error,8= inARP request,9= inARP reply
packet.SHA=netObj.ports(inProcPortIndex).mac;%Sender Hardware Address: The hardware (layer two) address of the device sending this message (which is the IP datagram source device on a request, and the IP datagram destination on a reply, as discussed in the topic on ARP operation).
packet.SPA=netObj.ports(inProcPortIndex).ip ;%Sender Protocol Address: The IP address of the device sending this message.
packet.THA=pdu.arp.SHA;%Target hardware Address: The hardware (layer two) address of the device this message is being sent to. This is the IP datagram destination device on a request, and the IP datagram source on a reply)
packet.TPA=pdu.arp.SPA;%Target Protocol Address: The IP address of the device this message is being sent to.
newpdu.arp=packet;
packet=[];
packet.destnation=pdu.ethernet.source;%This is 6-Byte field which contains the MAC address of machine for which data is destined.
packet.source=netObj.ports(inProcPortIndex).mac;%his is a 6-Byte field which contains the MAC address of source machine. As Source Address is always an individual address (Unicast), the least significant bit of first byte is always 0.
packet.type=pdu.ethernet.type;% typ: arp =806 ,ipV4=800 for most code Go to the refrence 5 at the beginig
newpdu.ethernet=packet;
srcIndex=find(strcmp(netObj.ARP_Table.ipAddress, pdu.arp.SPA ), 1);
if isempty(srcIndex)
netObj.ARP_Table=[netObj.ARP_Table;{pdu.arp.SPA ,pdu.ethernet.source,inProcPortName}];
end
pdu=newpdu;
netObj.ioControlFlag(3)=1;
elseif compareIp(pdu.arp.TPA, netObj.ports(inProcPortIndex).ip)
srcIndex=find(strcmp(netObj.ARP_Table.ipAddress, pdu.arp.SPA ), 1);
if isempty(srcIndex)
netObj.ARP_Table=[netObj.ARP_Table;{pdu.arp.SPA ,pdu.ethernet.source,inProcPortName}];
end
netObj.ioControlFlag(2)=1;
else
netObj.ioControlFlag(1)=1;
end
end
else
if strcmp(pdu.ethernet.destnation,netObj.ports(inProcPortIndex).mac) || strcmp(pdu.ethernet.destnation,'FF:FF:FF:FF:FF:FF')
internetLayerAgent= tcpIp.internet;
if (isfield(pdu,'rip') || isfield(pdu,'eigrp') || isfield(pdu,'ospf') ) % only for router
netObj.ioControlFlag(1)=1;
else
newpdu=rmfield(pdu,'ethernet');
newpdu=internetLayerAgent.internetPort(newpdu,netObj);
if strcmp(pdu.ethernet.destnation,macAddAloc('max')) % but not arp
if isfield(pdu,'dhcp') && isfield(newpdu,'packetDat')
if sum([2,5,10]==newpdu.packetDat.option.dhcp) % the current netobj is server, when dhcp code is even
packet=[];
packet.destnation=macAddAloc('max') ;%This is 6-Byte field which contains the MAC address of machine for which data is destined.
packet.source=netObj.ports(inProcPortIndex).mac;%his is a 6-Byte field which contains the MAC address of source machine. As Source Address is always an individual address (Unicast), the least significant bit of first byte is always 0.
elseif sum([1,3,8,12]==newpdu.packetDat.option.dhcp) % the current netobj is cliend, when dhcp code is odd
packet=[];
packet.destnation=macAddAloc('max') ;%This is 6-Byte field which contains the MAC address of machine for which data is destined.
packet.source=netObj.ports(inProcPortIndex).mac;%his is a 6-Byte field which contains the MAC address of source machine. As Source Address is always an individual address (Unicast), the least significant bit of first byte is always 0.
end
else
packet=[];
packet.destnation=pdu.ethernet.source;%This is 6-Byte field which contains the MAC address of machine for which data is destined.
packet.source=netObj.ports(inProcPortIndex).mac;%his is a 6-Byte field which contains the MAC address of source machine. As Source Address is always an individual address (Unicast), the least significant bit of first byte is always 0.
end
else
packet=[];
packet.destnation=pdu.ethernet.source ;%This is 6-Byte field which contains the MAC address of machine for which data is destined.
packet.source=pdu.ethernet.destnation;%his is a 6-Byte field which contains the MAC address of source machine. As Source Address is always an individual address (Unicast), the least significant bit of first byte is always 0.
end
packet.type=pdu.ethernet.type;% typ: arp =806 ,ipV4=800 for most code Go to the refrence 5 at the beginig
newpdu.ethernet=packet;
pdu=newpdu;
% this section behavior with recived frame will determined by application or upper layer protocols
end
else
netObj.ioControlFlag(1)=1;
end
end
case 2
%PcServerObj
if isfield(pdu,'arp')
if strcmp(pdu.arp.SPA,pdu.arp.TPA) && strcmp(pdu.ethernet.destnation,'FF:FF:FF:FF:FF:FF')
%update arp message
srcIndex=find(strcmp(netObj.ARP_Table.hardWareAddress, pdu.arp.SHA ), 1);
if ~isempty(srcIndex)
netObj.ARP_Table{srcIndex,:}={pdu.arp.SPA ,pdu.ethernet.source,inProcPortName};
netObj.ioControlFlag(2)=1;
else
netObj.ioControlFlag(1)=1;
end
else
if strcmp(pdu.arp.TPA,netObj.ports(inProcPortIndex).ip) && strcmp(pdu.ethernet.destnation,'FF:FF:FF:FF:FF:FF')
packet=[];
packet.HRD=1;%packetDat.HRD;%defaultt=1, hardware type 1= Ethernet , 6=IEEE 802 Network, 7=ARCNET, 15=Frame Relay, 16= Asynchronous Transfer Mode(ATM, 17= HDLC ,18=Fibr Channel, 20=serialLine
packet.PRO=800;%packetDat.PRO;%defaultt=8 as ip4;Protocol Type: This field is the complement of the Hardware Type field, specifying the type of layer three addresses used in the message. For IPv4 addresses, this value is 2048 (0800 hex), which corresponds to the EtherType code for the Internet Protocol.
packet.HLN=6;%packetDat.HLN;%defaultt=6 ,Hardware Address Length: Specifies how long hardware addresses are in this message. For Ethernet or other networks using IEEE 802 MAC addresses, the value is 6.
packet.PLN=4;%packetDat.PLN;%defaultt=4 ,Protocol Address Length: Again, the complement of the preceding field; specifies how long protocol (layer three) addresses are in this message. For IP(v4) addresses this value is of course 4.
packet.OP=2;%defaultt=1 ,op code,1= arp request, 2= arp reply,3=RARP request, 4= RARP reply, 5=DRARP request, 6= DRARP reply,7= DRARP error,8= inARP request,9= inARP reply
packet.SHA=netObj.ports(inProcPortIndex).mac;%Sender Hardware Address: The hardware (layer two) address of the device sending this message (which is the IP datagram source device on a request, and the IP datagram destination on a reply, as discussed in the topic on ARP operation).
packet.SPA=netObj.ports(inProcPortIndex).ip ;%Sender Protocol Address: The IP address of the device sending this message.
packet.THA=pdu.arp.SHA;%Target hardware Address: The hardware (layer two) address of the device this message is being sent to. This is the IP datagram destination device on a request, and the IP datagram source on a reply)
packet.TPA=pdu.arp.SPA;%Target Protocol Address: The IP address of the device this message is being sent to.
newpdu.arp=packet;
packet=[];
packet.destnation=pdu.ethernet.source;%This is 6-Byte field which contains the MAC address of machine for which data is destined.
packet.source=netObj.ports(inProcPortIndex).mac;%his is a 6-Byte field which contains the MAC address of source machine. As Source Address is always an individual address (Unicast), the least significant bit of first byte is always 0.
packet.type=pdu.ethernet.type;% typ: arp =806 ,ipV4=800 for most code Go to the refrence 5 at the beginig
newpdu.ethernet=packet;
srcIndex=find(strcmp(netObj.ARP_Table.ipAddress, pdu.arp.SPA ), 1);
if isempty(srcIndex)
netObj.ARP_Table=[netObj.ARP_Table;{pdu.arp.SPA ,pdu.ethernet.source,inProcPortName}];
end
pdu=newpdu;
netObj.ioControlFlag(3)=1;
elseif compareIp(pdu.arp.TPA, netObj.ports(inProcPortIndex).ip)
srcIndex=find(strcmp(netObj.ARP_Table.ipAddress, pdu.arp.SPA ), 1);
if isempty(srcIndex)
netObj.ARP_Table=[netObj.ARP_Table;{pdu.arp.SPA ,pdu.ethernet.source,inProcPortName}];
end
netObj.ioControlFlag(2)=1;
else
netObj.ioControlFlag(1)=1;
end
end
else
if strcmp(pdu.ethernet.destnation,netObj.ports(inProcPortIndex).mac) || strcmp(pdu.ethernet.destnation,'FF:FF:FF:FF:FF:FF')
internetLayerAgent= tcpIp.internet;
if (isfield(pdu,'rip') || isfield(pdu,'eigrp') || isfield(pdu,'ospf') ) % only for router
netObj.ioControlFlag(1)=1;
else
newpdu=rmfield(pdu,'ethernet');
newpdu=internetLayerAgent.internetPort(newpdu,netObj);
if strcmp(pdu.ethernet.destnation,macAddAloc('max')) % but not arp
if isfield(pdu,'dhcp') && isfield(newpdu,'packetDat')
if sum([2,5,10]==newpdu.packetDat.option.dhcp) % the current netobj is server, when dhcp code is even
packet=[];
packet.destnation=macAddAloc('max') ;%This is 6-Byte field which contains the MAC address of machine for which data is destined.
packet.source=netObj.ports(inProcPortIndex).mac;%his is a 6-Byte field which contains the MAC address of source machine. As Source Address is always an individual address (Unicast), the least significant bit of first byte is always 0.
elseif sum([1,3,8,12]==newpdu.packetDat.option.dhcp) % the current netobj is cliend, when dhcp code is odd
packet=[];
packet.destnation=macAddAloc('max') ;%This is 6-Byte field which contains the MAC address of machine for which data is destined.
packet.source=netObj.ports(inProcPortIndex).mac;%his is a 6-Byte field which contains the MAC address of source machine. As Source Address is always an individual address (Unicast), the least significant bit of first byte is always 0.
end
else
packet=[];
packet.destnation=pdu.ethernet.source;%This is 6-Byte field which contains the MAC address of machine for which data is destined.
packet.source=netObj.ports(inProcPortIndex).mac;%his is a 6-Byte field which contains the MAC address of source machine. As Source Address is always an individual address (Unicast), the least significant bit of first byte is always 0.
end
else
packet=[];
packet.destnation=pdu.ethernet.source ;%This is 6-Byte field which contains the MAC address of machine for which data is destined.
packet.source=pdu.ethernet.destnation;%his is a 6-Byte field which contains the MAC address of source machine. As Source Address is always an individual address (Unicast), the least significant bit of first byte is always 0.
end
packet.type=pdu.ethernet.type;% typ: arp =806 ,ipV4=800 for most code Go to the refrence 5 at the beginig
newpdu.ethernet=packet;
pdu=newpdu;
% this section behavior with recived frame will determined by application or upper layer protocols
end
else
netObj.ioControlFlag(1)=1;
end
end
case 3
%smartphone
if isfield(pdu,'arp')
if strcmp(pdu.arp.SPA,pdu.arp.TPA) && strcmp(pdu.ethernet.destnation,'FF:FF:FF:FF:FF:FF')
%update arp message
srcIndex=find(strcmp(netObj.ARP_Table.hardWareAddress, pdu.arp.SHA ), 1);
if ~isempty(srcIndex)
netObj.ARP_Table{srcIndex,:}={pdu.arp.SPA ,pdu.ethernet.source,inProcPortName};
netObj.ioControlFlag(2)=1;
else
netObj.ioControlFlag(1)=1;
end
else
if strcmp(pdu.arp.TPA,netObj.ports(inProcPortIndex).ip) && strcmp(pdu.ethernet.destnation,'FF:FF:FF:FF:FF:FF')
packet=[];
packet.HRD=1;%packetDat.HRD;%defaultt=1, hardware type 1= Ethernet , 6=IEEE 802 Network, 7=ARCNET, 15=Frame Relay, 16= Asynchronous Transfer Mode(ATM, 17= HDLC ,18=Fibr Channel, 20=serialLine
packet.PRO=800;%packetDat.PRO;%defaultt=8 as ip4;Protocol Type: This field is the complement of the Hardware Type field, specifying the type of layer three addresses used in the message. For IPv4 addresses, this value is 2048 (0800 hex), which corresponds to the EtherType code for the Internet Protocol.
packet.HLN=6;%packetDat.HLN;%defaultt=6 ,Hardware Address Length: Specifies how long hardware addresses are in this message. For Ethernet or other networks using IEEE 802 MAC addresses, the value is 6.
packet.PLN=4;%packetDat.PLN;%defaultt=4 ,Protocol Address Length: Again, the complement of the preceding field; specifies how long protocol (layer three) addresses are in this message. For IP(v4) addresses this value is of course 4.
packet.OP=2;%defaultt=1 ,op code,1= arp request, 2= arp reply,3=RARP request, 4= RARP reply, 5=DRARP request, 6= DRARP reply,7= DRARP error,8= inARP request,9= inARP reply
packet.SHA=netObj.ports(inProcPortIndex).mac;%Sender Hardware Address: The hardware (layer two) address of the device sending this message (which is the IP datagram source device on a request, and the IP datagram destination on a reply, as discussed in the topic on ARP operation).
packet.SPA=netObj.ports(inProcPortIndex).ip ;%Sender Protocol Address: The IP address of the device sending this message.
packet.THA=pdu.arp.SHA;%Target hardware Address: The hardware (layer two) address of the device this message is being sent to. This is the IP datagram destination device on a request, and the IP datagram source on a reply)
packet.TPA=pdu.arp.SPA;%Target Protocol Address: The IP address of the device this message is being sent to.
newpdu.arp=packet;
packet=[];
packet.destnation=pdu.ethernet.source;%This is 6-Byte field which contains the MAC address of machine for which data is destined.
packet.source=netObj.ports(inProcPortIndex).mac;%his is a 6-Byte field which contains the MAC address of source machine. As Source Address is always an individual address (Unicast), the least significant bit of first byte is always 0.
packet.type=pdu.ethernet.type;% typ: arp =806 ,ipV4=800 for most code Go to the refrence 5 at the beginig
newpdu.ethernet=packet;
srcIndex=find(strcmp(netObj.ARP_Table.ipAddress, pdu.arp.SPA ), 1);
if isempty(srcIndex)
netObj.ARP_Table=[netObj.ARP_Table;{pdu.arp.SPA ,pdu.ethernet.source,inProcPortName}];
end
pdu=newpdu;
netObj.ioControlFlag(3)=1;
elseif compareIp(pdu.arp.TPA, netObj.ports(inProcPortIndex).ip)
srcIndex=find(strcmp(netObj.ARP_Table.ipAddress, pdu.arp.SPA ), 1);
if isempty(srcIndex)
netObj.ARP_Table=[netObj.ARP_Table;{pdu.arp.SPA ,pdu.ethernet.source,inProcPortName}];
end
netObj.ioControlFlag(2)=1;
else
netObj.ioControlFlag(1)=1;
end
end
else
if strcmp(pdu.ethernet.destnation,netObj.ports(inProcPortIndex).mac) || strcmp(pdu.ethernet.destnation,'FF:FF:FF:FF:FF:FF')
internetLayerAgent= tcpIp.internet;
if (isfield(pdu,'rip') || isfield(pdu,'eigrp') || isfield(pdu,'ospf') ) % only for router
netObj.ioControlFlag(1)=1;
else
newpdu=rmfield(pdu,'ethernet');
newpdu=internetLayerAgent.internetPort(newpdu,netObj);
if strcmp(pdu.ethernet.destnation,macAddAloc('max')) % but not arp
if isfield(pdu,'dhcp') && isfield(newpdu,'packetDat')
if sum([2,5,10]==newpdu.packetDat.option.dhcp) % the current netobj is server, when dhcp code is even
packet=[];
packet.destnation=macAddAloc('max') ;%This is 6-Byte field which contains the MAC address of machine for which data is destined.
packet.source=netObj.ports(inProcPortIndex).mac;%his is a 6-Byte field which contains the MAC address of source machine. As Source Address is always an individual address (Unicast), the least significant bit of first byte is always 0.
elseif sum([1,3,8,12]==newpdu.packetDat.option.dhcp) % the current netobj is cliend, when dhcp code is odd
packet=[];
packet.destnation=macAddAloc('max') ;%This is 6-Byte field which contains the MAC address of machine for which data is destined.
packet.source=netObj.ports(inProcPortIndex).mac;%his is a 6-Byte field which contains the MAC address of source machine. As Source Address is always an individual address (Unicast), the least significant bit of first byte is always 0.
end
else
packet=[];
packet.destnation=pdu.ethernet.source;%This is 6-Byte field which contains the MAC address of machine for which data is destined.
packet.source=netObj.ports(inProcPortIndex).mac;%his is a 6-Byte field which contains the MAC address of source machine. As Source Address is always an individual address (Unicast), the least significant bit of first byte is always 0.
end
else
packet=[];
packet.destnation=pdu.ethernet.source ;%This is 6-Byte field which contains the MAC address of machine for which data is destined.
packet.source=pdu.ethernet.destnation;%his is a 6-Byte field which contains the MAC address of source machine. As Source Address is always an individual address (Unicast), the least significant bit of first byte is always 0.
end
packet.type=pdu.ethernet.type;% typ: arp =806 ,ipV4=800 for most code Go to the refrence 5 at the beginig
newpdu.ethernet=packet;
pdu=newpdu;
% this section behavior with recived frame will determined by application or upper layer protocols
end
else
netObj.ioControlFlag(1)=1;
end
end
case 4
%HubObj
disp('');
case 5
%SwitchObj: we used switchs as layer 2 device and not set layer 3 configuration type
inProcPortvlan=num2str(netObj.ports(inProcPortIndex).vlanValue);
if isfield(pdu,'arp') %% arp proccess is within network only
if strcmp(pdu.arp.SPA,pdu.arp.TPA) && strcmp(pdu.ethernet.destnation,'FF:FF:FF:FF:FF:FF')%% arp the first type
%update arp message
srcIndex=find(strcmp(netObj.MAC_Table.macAddress, pdu.arp.SHA ), 1);
if ~isempty(srcIndex)
netObj.MAC_Table=[netObj.MAC_Table;{inProcPortvlan,pdu.ethernet.source,inProcPortName}];
end
netObj.ioControlFlag(5)=1;
% % switch need in any condtion broadcast the message unless source and destnation is determined
else %% arp the second typ
srcIndex=find(strcmp(netObj.MAC_Table.macAddress, pdu.ethernet.source ), 1);
dstIndex=find(strcmp(netObj.MAC_Table.macAddress, pdu.ethernet.destnation ), 1);
switch strcmp(pdu.ethernet.destnation,'FF:FF:FF:FF:FF:FF')
case 1 % it is broadcast arp
if isempty(srcIndex)
netObj.MAC_Table=[netObj.MAC_Table;{inProcPortvlan,pdu.ethernet.source,inProcPortName}];
end
netObj.ioControlFlag(5)=1;
case 0 % it is unicast arp
if ~isempty(srcIndex) && ~isempty(dstIndex)
netObj.ioControlFlag(4)=1;%relay
else
netObj.MAC_Table=[netObj.MAC_Table;{inProcPortvlan,pdu.ethernet.source,inProcPortName}];
netObj.ioControlFlag(4)=1;%relay
end
end
end
else % is not arp packet
srcIndex=find(strcmp(netObj.MAC_Table.macAddress, pdu.ethernet.source ), 1);
dstIndex=find(strcmp(netObj.MAC_Table.macAddress, pdu.ethernet.destnation ), 1);
if ~isempty(srcIndex) && ~isempty(dstIndex) %% here this means that the destnation netObject is out of network
netObj.ioControlFlag(4)=1;
elseif isempty(srcIndex) && ~strcmp(pdu.ethernet.destnation, 'FF:FF:FF:FF:FF:FF' )
netObj.MAC_Table=[netObj.MAC_Table;{inProcPortvlan,pdu.ethernet.source,inProcPortName}];
netObj.ioControlFlag(4)=1;
elseif strcmp(pdu.ethernet.destnation, 'FF:FF:FF:FF:FF:FF' )
netObj.ioControlFlag(5)=1;
end
end
case 6
%RoutrrObj
if isfield(pdu,'arp')
if strcmp(pdu.arp.SPA,pdu.arp.TPA) && strcmp(pdu.ethernet.destnation,'FF:FF:FF:FF:FF:FF')
%update arp message
srcIndex=find(strcmp(netObj.ARP_Table.hardWareAddress, pdu.arp.SHA ), 1);
if ~isempty(srcIndex)
netObj.ARP_Table{srcIndex,:}={pdu.arp.SPA ,pdu.ethernet.source,inProcPortName};
netObj.ioControlFlag(2)=1;
else
netObj.ioControlFlag(1)=1;
end
else
if strcmp(pdu.arp.TPA,netObj.ports(inProcPortIndex).ip) && strcmp(pdu.ethernet.destnation,'FF:FF:FF:FF:FF:FF')
packet=[];
packet.HRD=1;%packetDat.HRD;%defaultt=1, hardware type 1= Ethernet , 6=IEEE 802 Network, 7=ARCNET, 15=Frame Relay, 16= Asynchronous Transfer Mode(ATM, 17= HDLC ,18=Fibr Channel, 20=serialLine
packet.PRO=800;%packetDat.PRO;%defaultt=8 as ip4;Protocol Type: This field is the complement of the Hardware Type field, specifying the type of layer three addresses used in the message. For IPv4 addresses, this value is 2048 (0800 hex), which corresponds to the EtherType code for the Internet Protocol.
packet.HLN=6;%packetDat.HLN;%defaultt=6 ,Hardware Address Length: Specifies how long hardware addresses are in this message. For Ethernet or other networks using IEEE 802 MAC addresses, the value is 6.
packet.PLN=4;%packetDat.PLN;%defaultt=4 ,Protocol Address Length: Again, the complement of the preceding field; specifies how long protocol (layer three) addresses are in this message. For IP(v4) addresses this value is of course 4.
packet.OP=2;%defaultt=1 ,op code,1= arp request, 2= arp reply,3=RARP request, 4= RARP reply, 5=DRARP request, 6= DRARP reply,7= DRARP error,8= inARP request,9= inARP reply
packet.SHA=netObj.ports(inProcPortIndex).mac;%Sender Hardware Address: The hardware (layer two) address of the device sending this message (which is the IP datagram source device on a request, and the IP datagram destination on a reply, as discussed in the topic on ARP operation).
packet.SPA=netObj.ports(inProcPortIndex).ip ;%Sender Protocol Address: The IP address of the device sending this message.
packet.THA=pdu.arp.SHA;%Target hardware Address: The hardware (layer two) address of the device this message is being sent to. This is the IP datagram destination device on a request, and the IP datagram source on a reply)
packet.TPA=pdu.arp.SPA;%Target Protocol Address: The IP address of the device this message is being sent to.
newpdu.arp=packet;
packet=[];
packet.destnation=pdu.ethernet.source;%This is 6-Byte field which contains the MAC address of machine for which data is destined.
packet.source=netObj.ports(inProcPortIndex).mac;%his is a 6-Byte field which contains the MAC address of source machine. As Source Address is always an individual address (Unicast), the least significant bit of first byte is always 0.
packet.type=pdu.ethernet.type;% typ: arp =806 ,ipV4=800 for most code Go to the refrence 5 at the beginig
newpdu.ethernet=packet;
srcIndex=find(strcmp(netObj.ARP_Table.ipAddress, pdu.arp.SPA ), 1);
if isempty(srcIndex)
netObj.ARP_Table=[netObj.ARP_Table;{pdu.arp.SPA ,pdu.ethernet.source,inProcPortName}];
end
pdu=newpdu;
netObj.ioControlFlag(3)=1;
elseif compareIp(pdu.arp.TPA, netObj.ports(inProcPortIndex).ip)
srcIndex=find(strcmp(netObj.ARP_Table.ipAddress, pdu.arp.SPA ), 1);
if isempty(srcIndex)
netObj.ARP_Table=[netObj.ARP_Table;{pdu.arp.SPA ,pdu.ethernet.source,inProcPortName}];
end
netObj.ioControlFlag(2)=1;
else
netObj.ioControlFlag(1)=1;
end
end
else
if strcmp(pdu.ethernet.destnation,netObj.ports(inProcPortIndex).mac) || strcmp(pdu.ethernet.destnation,'FF:FF:FF:FF:FF:FF')
internetLayerAgent= tcpIp.internet;
newpdu=rmfield(pdu,'ethernet');
newpdu=internetLayerAgent.internetPort(newpdu,netObj);
if strcmp(pdu.ethernet.destnation,macAddAloc('max')) % but not arp
if isfield(pdu,'dhcp') && isfield(newpdu,'packetDat')
if sum([2,5,10]==newpdu.packetDat.option.dhcp) % the current netobj is server, when dhcp code is even
packet=[];
packet.destnation=macAddAloc('max') ;%This is 6-Byte field which contains the MAC address of machine for which data is destined.
packet.source=netObj.ports(inProcPortIndex).mac;%his is a 6-Byte field which contains the MAC address of source machine. As Source Address is always an individual address (Unicast), the least significant bit of first byte is always 0.
elseif sum([1,3,8,12]==newpdu.packetDat.option.dhcp) % the current netobj is cliend, when dhcp code is odd
packet=[];
packet.destnation=macAddAloc('max') ;%This is 6-Byte field which contains the MAC address of machine for which data is destined.
packet.source=netObj.ports(inProcPortIndex).mac;%his is a 6-Byte field which contains the MAC address of source machine. As Source Address is always an individual address (Unicast), the least significant bit of first byte is always 0.
end
else
packet=[];
packet.destnation=pdu.ethernet.source;%This is 6-Byte field which contains the MAC address of machine for which data is destined.
packet.source=netObj.ports(inProcPortIndex).mac;%his is a 6-Byte field which contains the MAC address of source machine. As Source Address is always an individual address (Unicast), the least significant bit of first byte is always 0.
end
else
packet=[];
packet.destnation=pdu.ethernet.source ;%This is 6-Byte field which contains the MAC address of machine for which data is destined.
packet.source=pdu.ethernet.destnation;%his is a 6-Byte field which contains the MAC address of source machine. As Source Address is always an individual address (Unicast), the least significant bit of first byte is always 0.
end
packet.type=pdu.ethernet.type;% typ: arp =806 ,ipV4=800 for most code Go to the refrence 5 at the beginig
newpdu.ethernet=packet;
pdu=newpdu;
% this section behavior with recived frame will determined by application or upper layer protocols
end
end
case 7
%SnifObj
disp('');
case 8 % board
case 9 % iot
case 10 % cloud
inProcPortvlan=num2str(netObj.ports(inProcPortIndex).vlanValue);
if isfield(pdu,'arp') %% arp proccess is within network only
if strcmp(pdu.arp.SPA,pdu.arp.TPA) && strcmp(pdu.ethernet.destnation,'FF:FF:FF:FF:FF:FF')%% arp the first type
%update arp message
srcIndex=find(strcmp(netObj.MAC_Table.macAddress, pdu.arp.SHA ), 1);
if ~isempty(srcIndex)
netObj.MAC_Table=[netObj.MAC_Table;{inProcPortvlan,pdu.ethernet.source,inProcPortName}];
end
netObj.ioControlFlag(5)=1;
% % switch need in any condtion broadcast the message unless source and destnation is determined
else %% arp the second typ
srcIndex=find(strcmp(netObj.MAC_Table.macAddress, pdu.ethernet.source ), 1);
dstIndex=find(strcmp(netObj.MAC_Table.macAddress, pdu.ethernet.destnation ), 1);
switch strcmp(pdu.ethernet.destnation,'FF:FF:FF:FF:FF:FF')
case 1 % it is broadcast arp
if isempty(srcIndex)
netObj.MAC_Table=[netObj.MAC_Table;{inProcPortvlan,pdu.ethernet.source,inProcPortName}];
end
netObj.ioControlFlag(5)=1;
case 0 % it is unicast arp
if ~isempty(srcIndex) && ~isempty(dstIndex)
netObj.ioControlFlag(4)=1;%relay
else
netObj.MAC_Table=[netObj.MAC_Table;{inProcPortvlan,pdu.ethernet.source,inProcPortName}];
netObj.ioControlFlag(4)=1;%relay
end
end
end
else % is not arp packet
srcIndex=find(strcmp(netObj.MAC_Table.macAddress, pdu.ethernet.source ), 1);
dstIndex=find(strcmp(netObj.MAC_Table.macAddress, pdu.ethernet.destnation ), 1);
if ~isempty(srcIndex) && ~isempty(dstIndex) %% here this means that the destnation netObject is out of network
netObj.ioControlFlag(4)=1;
elseif isempty(srcIndex) && ~strcmp(pdu.ethernet.destnation, 'FF:FF:FF:FF:FF:FF' )
netObj.MAC_Table=[netObj.MAC_Table;{inProcPortvlan,pdu.ethernet.source,inProcPortName}];
netObj.ioControlFlag(4)=1;
elseif strcmp(pdu.ethernet.destnation, 'FF:FF:FF:FF:FF:FF' )
netObj.ioControlFlag(5)=1;
end
end
end
end
end
function pdu=linkOutProt(linkLayer,pdu,netObj)
if isfield(pdu,'ip') && compareIp(pdu.packetDat.sourceIp,pdu.packetDat.destnationIp) % in the future we used this feature as
netObj.ioControlFlag(1)=1;
elseif isfield(pdu,'ip') && strcmp(pdu.packetDat.destnationIp,'255.255.255.255')
pdu.packetDat.destnation=macAddAloc('max');
inUseIntIndex=find([netObj.ports.inUse]==1);
ValidIpindex=find(ismember({netObj.ports(inUseIntIndex).ip}, pdu.packetDat.sourceIp ));
if isempty(ValidIpindex)% for dhcp
pdu.packetDat.source=netObj.ports(1).mac;
else % for rip and other broadcast
pdu.packetDat.source=netObj.ports(ValidIpindex).mac;
end
pdu.packetDat.type=800;
if netObj.typeDevice==6 && (isfield(pdu,'rip') || isfield(pdu,'eigrp') || isfield(pdu,'ospf') ) % only for router
netObj.ioControlFlag(4) = 1;
else
netObj.ioControlFlag(5) = 1;
end
pdu=linkLayer.ethernet( pdu,netObj);
else
inUseIntIndex=find([netObj.ports.inUse]==1);
netObjIpS={netObj.ports(inUseIntIndex).ip};
validList=isvalidIp(netObjIpS);
inUseIntIndex=inUseIntIndex(logical(validList));
netObjIpS={netObj.ports(inUseIntIndex).ip};
destIps=repmat({pdu.packetDat.destnationIp},1,length(netObjIpS));
subnetMaskS={netObj.ports(inUseIntIndex).subnetMask};
[~,netObjSubId,~]=getNet(netObjIpS,subnetMaskS);
[~,destObjSubId,~]=getNet(destIps,subnetMaskS);
destIntIndex=find(ismember(netObjSubId,destObjSubId));
if ~isempty(destIntIndex)% it is in sebnet, that connect to one of curent device ports
srcIndex=find(strcmp(netObj.ARP_Table.ipAddress, ip2IpS_dec(pdu.packetDat.destnationIp,0) ), 1);%
if ~isempty(srcIndex) % if it has a record in arp table
destHwA=table2struct(netObj.ARP_Table(srcIndex,2));
destInFaName=table2struct(netObj.ARP_Table(srcIndex,3));
portNum=ismember({netObj.ports.name},destInFaName.interface);
pdu.packetDat.destnation= destHwA.hardWareAddress;
pdu.packetDat.source= netObj.ports(portNum).mac;
netObj.ioControlFlag(4)=1;
pdu=linkLayer.ethernet( pdu,netObj);
else
%arp parameters
newPdu.packetDat.SHA=netObj.ports(destIntIndex).mac ;
newPdu.packetDat.SPA=pdu.packetDat.sourceIp;%netObj.ports(pInd).mac;
newPdu.packetDat.THA=macAddAloc('min');%Target Hardware Address: 00:00:00:00:00:00 as broadcast
newPdu.packetDat.TPA=pdu.packetDat.destnationIp;%Target Protocol Address: The IP address of the device this message is being sent to.
%ethernet parameters
newPdu.packetDat.destnation=macAddAloc('max');
newPdu.packetDat.source= netObj.ports(destIntIndex).mac;
%arp proccess
netObj.ioControlFlag(5)=1;
sentframe=linkLayer.arp(newPdu,netObj);
reciveframe=netObj.recBuffer;
srcIndex=find(strcmp(netObj.ARP_Table.ipAddress, ip2IpS_dec(pdu.packetDat.destnationIp,0) ), 1);%
if ~isempty(srcIndex) % if it has a record in arp table
destHwA=table2struct(netObj.ARP_Table(srcIndex,2));
destInFaName=table2struct(netObj.ARP_Table(srcIndex,3));
portNum=ismember({netObj.ports.name},destInFaName.interface);
pdu.packetDat.destnation= destHwA.hardWareAddress;
pdu.packetDat.source= netObj.ports(portNum).mac;
netObj.ioControlFlag(4)=1;
pdu=linkLayer.ethernet( pdu,netObj);
else
%
end
end
elseif netObj.typeDevice~=6 && isfield(netObj.ports,'gatWay4') % if frame dont blong to current network and device is not router
inUseIntIndex=find([netObj.ports.inUse]==1);
netObjIpS={netObj.ports(inUseIntIndex).ip};
validList=isvalidIp(netObjIpS);
inUseIntIndex=inUseIntIndex(logical(validList));
netObjIpS={netObj.ports(inUseIntIndex).ip};
destIps=repmat({netObj.ports(1).gatWay4},1,length(netObjIpS));
subnetMaskS={netObj.ports(inUseIntIndex).subnetMask};
[netObjNetId,netObjSubId,~]=getNet(netObjIpS,subnetMaskS);
[destObjNetId,destObjSubId,~]=getNet(destIps,subnetMaskS);
destIntIndex=find(ismember(netObjSubId,destObjSubId));
if ~isempty(destIntIndex)% it is in sebnet, that connect to one of curent device ports
srcIndex=find(strcmp(netObj.ARP_Table.ipAddress, ip2IpS_dec(netObj.ports(1).gatWay4,0) ), 1);%
if ~isempty(srcIndex) % if it has a record in arp table
destHwA=table2struct(netObj.ARP_Table(srcIndex,2));
destInFaName=table2struct(netObj.ARP_Table(srcIndex,3));
portNum=ismember({netObj.ports.name},destInFaName.interface);
pdu.packetDat.destnation= destHwA.hardWareAddress;
pdu.packetDat.source= netObj.ports(portNum).mac;
netObj.ioControlFlag(5) =1;
pdu=linkLayer.ethernet( pdu,netObj);
else
%arp parameters
newPdu.packetDat.SHA=netObj.ports(destIntIndex).mac ;
newPdu.packetDat.SPA=pdu.packetDat.sourceIp;%netObj.ports(pInd).mac;
newPdu.packetDat.THA=macAddAloc('min');%Target Hardware Address: 00:00:00:00:00:00 as broadcast
newPdu.packetDat.TPA=netObj.ports(1).gatWay4;%Target Protocol Address: The IP address of the device this message is being sent to.
%ethernet parameters
newPdu.packetDat.destnation=macAddAloc('max');
newPdu.packetDat.source= netObj.ports(destIntIndex).mac;
%arp proccess
netObj.ioControlFlag(5) =1;
sentframe=linkLayer.arp(newPdu,netObj);
reciveframe=netObj.recBuffer;
srcIndex=find(strcmp(netObj.ARP_Table.ipAddress, ip2IpS_dec(netObj.ports(1).gatWay4,0 ) ), 1);%
compareIp(char(netObj.ARP_Table.ipAddress),netObj.ports(1).gatWay4)
if ~isempty(srcIndex) % if it has a record in arp table
destHwA=table2struct(netObj.ARP_Table(srcIndex,2));
destInFaName=table2struct(netObj.ARP_Table(srcIndex,3));
portNum=ismember({netObj.ports.name},destInFaName.interface);
pdu.packetDat.destnation= destHwA.hardWareAddress;
pdu.packetDat.source= netObj.ports(portNum).mac;
netObj.ioControlFlag(5) =1;
pdu=linkLayer.ethernet( pdu,netObj);
else
netObj.ioControlFlag(1)=1;
end
end
end
%the below section is used when we want to send an icmp or ... other app message! by router
elseif netObj.typeDevice==6 && ~isfield(netObj.ports,'gatWay4') % if frame dont blong to current network and device is a router
inUseIntIndex=find([netObj.ports.inUse]==1);
netObjIpS={netObj.ports(inUseIntIndex).ip};
validList=isvalidIp(netObjIpS);
inUseIntIndex=inUseIntIndex(logical(validList));
netObjIpS={netObj.ports(inUseIntIndex).ip};
portNum=inUseIntIndex(ismember(netObjIpS,pdu.packetDat.sourceIp));
destIps=repmat(pdu.packetDat.destnationIp,1,length(netObjIpS));
subnetMaskS={netObj.ports(inUseIntIndex).subnetMask};
[netObjNetId,netObjSubId,~]=getNet(netObjIpS,subnetMaskS);
[destObjNetId,destObjSubId,~]=getNet(destIps,subnetMaskS);
destIntIndex=find(ismember(netObjSubId,destObjSubId));
% it is in sebnet, that connect to one of curent device ports
srcIndex=find(strcmp(netObj.ARP_Table.ipAddress, ip2IpS_dec(pdu.packetDat.destnationIp,0) ), 1);%
if ~isempty(destIntIndex) && ~isempty(srcIndex) % if it has a record in arp table
destHwA=table2struct(netObj.ARP_Table(srcIndex,2));
destInFaName=table2struct(netObj.ARP_Table(srcIndex,3));
portNum=ismember({netObj.ports.name},destInFaName.interface);
pdu.packetDat.destnation= destHwA.hardWareAddress;
pdu.packetDat.source= netObj.ports(portNum).mac;
pdu=linkLayer.ethernet( pdu,netObj);
else
if isempty(srcIndex)
%arp parameters
newPdu.packetDat.SHA=netObj.ports(portNum).mac ;
newPdu.packetDat.SPA=pdu.packetDat.sourceIp;%netObj.ports(pInd).mac;
newPdu.packetDat.THA=macAddAloc('min');%Target Hardware Address: 00:00:00:00:00:00 as broadcast
newPdu.packetDat.TPA=pdu.packetDat.destnationIp;%Target Protocol Address: The IP address of the device this message is being sent to.
%ethernet parameters
newPdu.packetDat.destnation=macAddAloc('max');
newPdu.packetDat.source= netObj.ports(portNum).mac;% destnation is a pc connetc to switch ,...
%arp proccess
netObj.ioControlFlag(5) =1;
sentframe=linkLayer.arp(newPdu,netObj);
reciveframe=netObj.recBuffer;
end
srcIndex=find(strcmp(netObj.ARP_Table.ipAddress, ip2IpS_dec(pdu.packetDat.destnationIp,0) ), 1);%
if ~isempty(srcIndex) % if it has a record in arp table
destHwA=table2struct(netObj.ARP_Table(srcIndex,2));
destInFaName=table2struct(netObj.ARP_Table(srcIndex,3));
portNum=ismember({netObj.ports.name},destInFaName.interface);
pdu.packetDat.destnation= destHwA.hardWareAddress;
pdu.packetDat.source= netObj.ports(portNum).mac;
pdu=linkLayer.ethernet( pdu,netObj);
else
netObj.ioControlFlag(1)=1;
end
end
else
netObj.ioControlFlag(1)=1;
end
end
end
function pdu=arp(linkLayer,pdu,netObj)
packet.HRD=1;%packetDat.HRD;%defaultt=1, hardware type 1= Ethernet , 6=IEEE 802 Network, 7=ARCNET, 15=Frame Relay, 16= Asynchronous Transfer Mode(ATM, 17= HDLC ,18=Fibr Channel, 20=serialLine
packet.PRO=800;%packetDat.PRO;%defaultt=800 as ip4;Protocol Type: This field is the complement of the Hardware Type field, specifying the type of layer three addresses used in the message. For IPv4 addresses, this value is 2048 (0800 hex), which corresponds to the EtherType code for the Internet Protocol.
packet.HLN=6;%packetDat.HLN;%defaultt=6 ,Hardware Address Length: Specifies how long hardware addresses are in this message. For Ethernet or other networks using IEEE 802 MAC addresses, the value is 6.
packet.PLN=4;%packetDat.PLN;%defaultt=4 ,Protocol Address Length: Again, the complement of the preceding field; specifies how long protocol (layer three) addresses are in this message. For IP(v4) addresses this value is of course 4.
packet.OP=1;%defaultt=1 ,op code,1= arp request, 2= arp reply,3=RARP request, 4= RARP reply, 5=DRARP request, 6= DRARP reply,7= DRARP error,8= inARP request,9= inARP reply
packet.SHA=pdu.packetDat.SHA;%Sender Hardware Address: The hardware (layer two) address of the device sending this message (which is the IP datagram source device on a request, and the IP datagram destination on a reply, as discussed in the topic on ARP operation).
packet.SPA=pdu.packetDat.SPA;%Sender Protocol Address: The IP address of the device sending this message.
packet.THA=pdu.packetDat.THA;%Target Hardware Address: The hardware (layer two) address of the device this message is being sent to. This is the IP datagram destination device on a request, and the IP datagram source on a reply)
packet.TPA=pdu.packetDat.TPA;%Target Protocol Address: The IP address of the device this message is being sent to.
pdu.packetDat.type=806; % as arp
pdu.arp=packet;
pdu=linkLayer.ethernet(pdu,netObj);
end
function pdu=ethernet(linkLayer,pdu,netObj)
packet.destnation=pdu.packetDat.destnation;%This is 6-Byte field which contains the MAC address of machine for which data is destined.
packet.source=pdu.packetDat.source;%his is a 6-Byte field which contains the MAC address of source machine. As Source Address is always an individual address (Unicast), the least significant bit of first byte is always 0.
packet.type=pdu.packetDat.type;% typ: arp =806 ,ipV4=800 for most code Go to the refrence 5 at the beginig
pdu.ethernet=packet;
if netObj.ioControlFlag(5) == 1
netObj.ioControlFlag(5)=0;
pdu=rmfield(pdu,'packetDat');
netObj.onSentFram(pdu);% later i control this section for Possible error
elseif netObj.ioControlFlag(4) == 1
netObj.ioControlFlag(4)=0;
inUseIntIndex=find([netObj.ports.inUse]==1);
netObjIpS={netObj.ports(inUseIntIndex).mac};
portNum=find(ismember(netObjIpS,pdu.ethernet.source));
aimPort=netObj.ports(portNum).outport;
aimObj=netObj.ports(portNum).outObj;
if aimObj.sendListener{aimPort}.Enabled==0
aimObj.sendListener{aimPort}.Enabled=1;
end
conLine.x={[netObj.pos.X,aimObj.pos.X]};
conLine.y={[netObj.pos.Y,aimObj.pos.Y]};
pdu=rmfield(pdu,'packetDat');
uniCast(netObj,aimObj,pdu,conLine,portNum)
%unicast
end
end
end
methods % help Functions
function [aimObj,aimPor,conLine]=netObjectFinder(linkLayer,netObj,dstIndex)
portNum=find(strcmp({netObj.ports.name},netObj.MAC_Table(dstIndex,end).port));
connectLine=[netObj.connectLine{:}];
conObjects= [connectLine.conObjects] ;
thisIndex=[];
thatIndex=[];
conPorts=cell2mat([connectLine.conPorts]);
for conL=1:length(conObjects)
if conObjects{conL}.typeDevice==netObj.typeDevice
thisIndex=[thisIndex,conL];
else
thatIndex=[thatIndex,conL];
end
end
thisport= conPorts(thisIndex);
aimPortIndex= find(thisport==portNum);
aimObj= conObjects{thatIndex(aimPortIndex)};
aimPor=conPorts(thatIndex(aimPortIndex));
aimLine=connectLine(aimPortIndex);
conLine.x= aimLine.handles(1).XData ;
conLine.y= aimLine.handles(1).YData ;
if thatIndex(aimPortIndex)< thisIndex(aimPortIndex)
conLine.x=flip(conLine.x);
conLine.y=flip(conLine.y);
end
conLine.x={ conLine.x};
conLine.y={ conLine.y};
end
end
end