Vidyashree Rama
Committed by Gerrit Code Review

[ONOS-2596] BGP Open message validation

Change-Id: I2da98830159ed57e3727aae8d02af9f438586815
...@@ -28,8 +28,8 @@ public final class BGPErrorType { ...@@ -28,8 +28,8 @@ public final class BGPErrorType {
28 public static final byte OPEN_MESSAGE_ERROR = 2; 28 public static final byte OPEN_MESSAGE_ERROR = 2;
29 public static final byte UPDATE_MESSAGE_ERROR = 3; 29 public static final byte UPDATE_MESSAGE_ERROR = 3;
30 public static final byte HOLD_TIMER_EXPIRED = 4; 30 public static final byte HOLD_TIMER_EXPIRED = 4;
31 - public static final byte FINITE_STATE_MACHINE_ERROR = 4; 31 + public static final byte FINITE_STATE_MACHINE_ERROR = 5;
32 - public static final byte CEASE = 5; 32 + public static final byte CEASE = 6;
33 33
34 //Message Header Error subcodes 34 //Message Header Error subcodes
35 public static final byte CONNECTION_NOT_SYNCHRONIZED = 1; 35 public static final byte CONNECTION_NOT_SYNCHRONIZED = 1;
...@@ -42,6 +42,7 @@ public final class BGPErrorType { ...@@ -42,6 +42,7 @@ public final class BGPErrorType {
42 public static final byte BAD_BGP_IDENTIFIER = 3; 42 public static final byte BAD_BGP_IDENTIFIER = 3;
43 public static final byte UNSUPPORTED_OPTIONAL_PARAMETER = 4; 43 public static final byte UNSUPPORTED_OPTIONAL_PARAMETER = 4;
44 public static final byte UNACCEPTABLE_HOLD_TIME = 5; 44 public static final byte UNACCEPTABLE_HOLD_TIME = 5;
45 + public static final byte UNSUPPORTED_CAPABILITY = 7;
45 46
46 //UPDATE Message Error subcodes 47 //UPDATE Message Error subcodes
47 public static final byte MALFORMED_ATTRIBUTE_LIST = 1; 48 public static final byte MALFORMED_ATTRIBUTE_LIST = 1;
......
...@@ -17,14 +17,20 @@ ...@@ -17,14 +17,20 @@
17 package org.onosproject.bgp.controller.impl; 17 package org.onosproject.bgp.controller.impl;
18 18
19 import java.io.IOException; 19 import java.io.IOException;
20 +import java.net.InetAddress;
20 import java.net.InetSocketAddress; 21 import java.net.InetSocketAddress;
21 import java.net.SocketAddress; 22 import java.net.SocketAddress;
23 +import java.net.UnknownHostException;
22 import java.nio.channels.ClosedChannelException; 24 import java.nio.channels.ClosedChannelException;
23 import java.util.Collections; 25 import java.util.Collections;
24 import java.util.Date; 26 import java.util.Date;
25 import java.util.List; 27 import java.util.List;
28 +import java.util.LinkedList;
29 +import java.util.ListIterator;
26 import java.util.concurrent.RejectedExecutionException; 30 import java.util.concurrent.RejectedExecutionException;
27 31
32 +import org.jboss.netty.buffer.ChannelBuffer;
33 +import org.jboss.netty.buffer.ChannelBuffers;
28 import org.jboss.netty.channel.Channel; 34 import org.jboss.netty.channel.Channel;
29 import org.jboss.netty.channel.ChannelHandlerContext; 35 import org.jboss.netty.channel.ChannelHandlerContext;
30 import org.jboss.netty.channel.ChannelStateEvent; 36 import org.jboss.netty.channel.ChannelStateEvent;
...@@ -47,6 +53,10 @@ import org.onosproject.bgpio.protocol.BGPMessage; ...@@ -47,6 +53,10 @@ import org.onosproject.bgpio.protocol.BGPMessage;
47 import org.onosproject.bgpio.protocol.BGPOpenMsg; 53 import org.onosproject.bgpio.protocol.BGPOpenMsg;
48 import org.onosproject.bgpio.protocol.BGPType; 54 import org.onosproject.bgpio.protocol.BGPType;
49 import org.onosproject.bgpio.protocol.BGPVersion; 55 import org.onosproject.bgpio.protocol.BGPVersion;
56 +import org.onosproject.bgpio.types.BGPErrorType;
57 +import org.onosproject.bgpio.types.BGPValueType;
58 +import org.onosproject.bgpio.types.FourOctetAsNumCapabilityTlv;
59 +import org.onosproject.bgpio.types.MultiProtocolExtnCapabilityTlv;
50 import org.slf4j.Logger; 60 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory; 61 import org.slf4j.LoggerFactory;
52 62
...@@ -56,7 +66,7 @@ import org.slf4j.LoggerFactory; ...@@ -56,7 +66,7 @@ import org.slf4j.LoggerFactory;
56 class BGPChannelHandler extends IdleStateAwareChannelHandler { 66 class BGPChannelHandler extends IdleStateAwareChannelHandler {
57 67
58 private static final Logger log = LoggerFactory.getLogger(BGPChannelHandler.class); 68 private static final Logger log = LoggerFactory.getLogger(BGPChannelHandler.class);
59 - 69 + static final int BGP_MIN_HOLDTIME = 3;
60 static final int BGP_MAX_KEEPALIVE_INTERVAL = 3; 70 static final int BGP_MAX_KEEPALIVE_INTERVAL = 3;
61 private BGPPeer bgpPeer; 71 private BGPPeer bgpPeer;
62 private BGPId thisbgpId; 72 private BGPId thisbgpId;
...@@ -68,6 +78,13 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { ...@@ -68,6 +78,13 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler {
68 private int peerIdentifier; 78 private int peerIdentifier;
69 private BGPPacketStatsImpl bgpPacketStats; 79 private BGPPacketStatsImpl bgpPacketStats;
70 static final int MAX_WRONG_COUNT_PACKET = 5; 80 static final int MAX_WRONG_COUNT_PACKET = 5;
81 + static final byte MULTI_PROTOCOL_EXTN_CAPA_TYPE = 1;
82 + static final byte FOUR_OCTET_AS_NUM_CAPA_TYPE = 65;
83 + static final int AS_TRANS = 23456;
84 + static final int MAX_AS2_NUM = 65535;
85 + static final short AFI = 16388;
86 + static final byte RES = 0;
87 + static final byte SAFI = 71;
71 88
72 // State needs to be volatile because the HandshakeTimeoutHandler 89 // State needs to be volatile because the HandshakeTimeoutHandler
73 // needs to check if the handshake is complete 90 // needs to check if the handshake is complete
...@@ -636,15 +653,197 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler { ...@@ -636,15 +653,197 @@ class BGPChannelHandler extends IdleStateAwareChannelHandler {
636 } 653 }
637 654
638 /** 655 /**
639 - * Open message validation. 656 + * BGP open message validation.
640 * 657 *
641 * @param h channel handler 658 * @param h channel handler
642 - * @param pOpenmsg open message 659 + * @param openMsg open message
643 - * @return true if validation succeed, otherwise false 660 + * @return true if valid message, otherwise false
644 - * @throws BGPParseException when received invalid message 661 + * @throws BGPParseException throw exception
662 + */
663 + public boolean openMsgValidation(BGPChannelHandler h, BGPOpenMsg openMsg) throws BGPParseException {
664 + boolean result;
665 +
666 + // Validate BGP ID
667 + result = bgpIdValidation(openMsg);
668 + if (!result) {
669 + throw new BGPParseException(BGPErrorType.OPEN_MESSAGE_ERROR, BGPErrorType.BAD_BGP_IDENTIFIER, null);
670 + }
671 +
672 + // Validate AS number
673 + result = asNumberValidation(h, openMsg);
674 + if (!result) {
675 + throw new BGPParseException(BGPErrorType.OPEN_MESSAGE_ERROR, BGPErrorType.BAD_PEER_AS, null);
676 + }
677 +
678 + // Validate hold timer
679 + if ((openMsg.getHoldTime() != 0) && (openMsg.getHoldTime() < BGP_MIN_HOLDTIME)) {
680 + throw new BGPParseException(BGPErrorType.OPEN_MESSAGE_ERROR, BGPErrorType.UNACCEPTABLE_HOLD_TIME, null);
681 + }
682 +
683 + // Validate capabilities
684 + result = capabilityValidation(h, openMsg);
685 + return result;
686 + }
687 +
688 + /**
689 + * Capability Validation.
690 + *
691 + * @param h channel handler
692 + * @param openmsg open message
693 + * @return success or failure
694 + * @throws BGPParseException
695 + */
696 + private boolean capabilityValidation(BGPChannelHandler h, BGPOpenMsg openmsg) throws BGPParseException {
697 + log.debug("capabilityValidation");
698 +
699 + boolean isMultiProtocolcapabilityExists = false;
700 + boolean isFourOctetCapabilityExits = false;
701 + int capAsNum = 0;
702 +
703 + List<BGPValueType> capabilityTlv = openmsg.getCapabilityTlv();
704 + ListIterator<BGPValueType> listIterator = capabilityTlv.listIterator();
705 + List<BGPValueType> unSupportedCapabilityTlv = new LinkedList<>();
706 + ListIterator<BGPValueType> unSupportedCaplistIterator = unSupportedCapabilityTlv.listIterator();
707 + BGPValueType tempTlv;
708 + boolean isLargeAsCapabilityCfg = h.bgpconfig.getLargeASCapability();
709 + boolean isLsCapabilityCfg = h.bgpconfig.getLsCapability();
710 +
711 + while (listIterator.hasNext()) {
712 + BGPValueType tlv = listIterator.next();
713 + if (tlv.getType() == MULTI_PROTOCOL_EXTN_CAPA_TYPE) {
714 + isMultiProtocolcapabilityExists = true;
715 + }
716 + if (tlv.getType() == FOUR_OCTET_AS_NUM_CAPA_TYPE) {
717 + isFourOctetCapabilityExits = true;
718 + capAsNum = ((FourOctetAsNumCapabilityTlv) tlv).getInt();
719 + }
720 + }
721 +
722 + if (isFourOctetCapabilityExits) {
723 + if (capAsNum > MAX_AS2_NUM) {
724 + if (openmsg.getAsNumber() != AS_TRANS) {
725 + throw new BGPParseException(BGPErrorType.OPEN_MESSAGE_ERROR, BGPErrorType.BAD_PEER_AS, null);
726 + }
727 + } else {
728 + if (capAsNum != openmsg.getAsNumber()) {
729 + throw new BGPParseException(BGPErrorType.OPEN_MESSAGE_ERROR, BGPErrorType.BAD_PEER_AS, null);
730 + }
731 + }
732 + }
733 +
734 + if ((isLsCapabilityCfg)) {
735 + if (!isMultiProtocolcapabilityExists) {
736 + tempTlv = new MultiProtocolExtnCapabilityTlv(AFI, RES, SAFI);
737 + unSupportedCapabilityTlv.add(tempTlv);
738 + }
739 + }
740 +
741 + if ((isLargeAsCapabilityCfg)) {
742 + if (!isFourOctetCapabilityExits) {
743 + tempTlv = new FourOctetAsNumCapabilityTlv(h.bgpconfig.getAsNumber());
744 + unSupportedCapabilityTlv.add(tempTlv);
745 + }
746 + }
747 +
748 + if (unSupportedCaplistIterator.hasNext()) {
749 + ChannelBuffer buffer = ChannelBuffers.dynamicBuffer();
750 + while (unSupportedCaplistIterator.hasNext()) {
751 + BGPValueType tlv = unSupportedCaplistIterator.next();
752 + tlv.write(buffer);
753 + }
754 + throw new BGPParseException(BGPErrorType.OPEN_MESSAGE_ERROR,
755 + BGPErrorType.UNSUPPORTED_CAPABILITY, buffer);
756 + } else {
757 + return true;
758 + }
759 + }
760 +
761 + /**
762 + * AS Number Validation.
763 + *
764 + * @param h channel Handler
765 + * @param openMsg open message
766 + * @return true or false
767 + */
768 + private boolean asNumberValidation(BGPChannelHandler h, BGPOpenMsg openMsg) {
769 + log.debug("AS Num validation");
770 +
771 + int capAsNum = 0;
772 + boolean isFourOctetCapabilityExits = false;
773 +
774 + BGPPeerCfg peerCfg = h.bgpconfig.displayPeers(peerAddr);
775 + List<BGPValueType> capabilityTlv = openMsg.getCapabilityTlv();
776 + ListIterator<BGPValueType> listIterator = capabilityTlv.listIterator();
777 +
778 + while (listIterator.hasNext()) {
779 + BGPValueType tlv = listIterator.next();
780 + if (tlv.getType() == FOUR_OCTET_AS_NUM_CAPA_TYPE) {
781 + isFourOctetCapabilityExits = true;
782 + capAsNum = ((FourOctetAsNumCapabilityTlv) tlv).getInt();
783 + }
784 + }
785 +
786 + if (peerCfg.getAsNumber() > MAX_AS2_NUM) {
787 + if (openMsg.getAsNumber() != AS_TRANS) {
788 + return false;
789 + }
790 +
791 + if (!isFourOctetCapabilityExits) {
792 + return false;
793 + }
794 +
795 + if (peerCfg.getAsNumber() != capAsNum) {
796 + return false;
797 + }
798 +
799 + isIbgpSession = peerCfg.getIsIBgp();
800 + if (isIbgpSession) {
801 + // IBGP - AS number should be same for Peer and local if it is IBGP
802 + if (h.bgpconfig.getAsNumber() != capAsNum) {
803 + return false;
804 + }
805 + }
806 + } else {
807 +
808 + if (openMsg.getAsNumber() != peerCfg.getAsNumber()) {
809 + return false;
810 + }
811 +
812 + if (isFourOctetCapabilityExits) {
813 + if (capAsNum != peerCfg.getAsNumber()) {
814 + return false;
815 + }
816 + }
817 +
818 + isIbgpSession = peerCfg.getIsIBgp();
819 + if (isIbgpSession) {
820 + // IBGP - AS number should be same for Peer and local if it is IBGP
821 + if (openMsg.getAsNumber() != h.bgpconfig.getAsNumber()) {
822 + return false;
823 + }
824 + }
825 + }
826 + return true;
827 + }
828 +
829 + /**
830 + * Validates BGP ID.
831 + *
832 + * @param openMsg open message
833 + * @return true or false
645 */ 834 */
646 - public boolean openMsgValidation(BGPChannelHandler h, BGPOpenMsg pOpenmsg) throws BGPParseException { 835 + private boolean bgpIdValidation(BGPOpenMsg openMsg) {
647 - // TODO: Open message validation. 836 + String openMsgBgpId = Ip4Address.valueOf(openMsg.getBgpId()).toString();
837 +
838 + InetAddress ipAddress;
839 + try {
840 + ipAddress = InetAddress.getByName(openMsgBgpId);
841 + if (ipAddress.isMulticastAddress()) {
842 + return false;
843 + }
844 + } catch (UnknownHostException e) {
845 + log.debug("InetAddress convertion failed");
846 + }
648 return true; 847 return true;
649 } 848 }
650 } 849 }
......