Committed by
Gerrit Code Review
[ONOS-2596] BGP Open message validation
Change-Id: I2da98830159ed57e3727aae8d02af9f438586815
Showing
2 changed files
with
209 additions
and
9 deletions
| ... | @@ -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 | ||
| 645 | */ | 695 | */ |
| 646 | - public boolean openMsgValidation(BGPChannelHandler h, BGPOpenMsg pOpenmsg) throws BGPParseException { | 696 | + private boolean capabilityValidation(BGPChannelHandler h, BGPOpenMsg openmsg) throws BGPParseException { |
| 647 | - // TODO: Open message validation. | 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 | ||
| 834 | + */ | ||
| 835 | + private boolean bgpIdValidation(BGPOpenMsg openMsg) { | ||
| 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 | } | ... | ... |
-
Please register or login to post a comment