/* * Copyright 2015 Open Networking Laboratory * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.onosproject.bgpio.protocol.ver4; import org.jboss.netty.buffer.ChannelBuffer; import org.onosproject.bgpio.exceptions.BGPParseException; import org.onosproject.bgpio.protocol.BGPFactories; import org.onosproject.bgpio.protocol.BGPMessage; import org.onosproject.bgpio.protocol.BGPMessageReader; import org.onosproject.bgpio.types.BGPErrorType; import org.onosproject.bgpio.types.BGPHeader; import org.onosproject.bgpio.util.Validation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Provides BGP messages. */ public abstract class BGPMessageVer4 { protected static final Logger log = LoggerFactory.getLogger(BGPFactories.class); static final byte OPEN_MSG_TYPE = 0x1; static final byte KEEPALIVE_MSG_TYPE = 0x4; static final byte UPDATE_MSG_TYPE = 0x2; static final byte NOTIFICATION_MSG_TYPE = 0x3; static final int MINIMUM_COMMON_HEADER_LENGTH = 19; static final int HEADER_AND_MSG_LEN = 18; static final int MAXIMUM_PACKET_LENGTH = 4096; public static final BGPMessageVer4.Reader READER = new Reader(); /** * Reader class for reading BGP messages from channel buffer. * */ static class Reader implements BGPMessageReader { @Override public BGPMessage readFrom(ChannelBuffer cb, BGPHeader bgpHeader) throws BGPParseException { if (cb.readableBytes() < MINIMUM_COMMON_HEADER_LENGTH) { log.error("Packet should have minimum length."); Validation.validateLen(BGPErrorType.MESSAGE_HEADER_ERROR, BGPErrorType.BAD_MESSAGE_LENGTH, cb.readableBytes()); } if (cb.readableBytes() > MAXIMUM_PACKET_LENGTH) { log.error("Packet length should not exceed {}.", MAXIMUM_PACKET_LENGTH); Validation.validateLen(BGPErrorType.MESSAGE_HEADER_ERROR, BGPErrorType.BAD_MESSAGE_LENGTH, cb.readableBytes()); } try { // fixed value property version == 4 byte[] marker = new byte[BGPHeader.MARKER_LENGTH]; cb.readBytes(marker, 0, BGPHeader.MARKER_LENGTH); bgpHeader.setMarker(marker); for (int i = 0; i < BGPHeader.MARKER_LENGTH; i++) { if (marker[i] != (byte) 0xff) { throw new BGPParseException(BGPErrorType.MESSAGE_HEADER_ERROR, BGPErrorType.CONNECTION_NOT_SYNCHRONIZED, null); } } short length = cb.readShort(); if (length != (cb.readableBytes() + HEADER_AND_MSG_LEN)) { Validation.validateLen(BGPErrorType.MESSAGE_HEADER_ERROR, BGPErrorType.BAD_MESSAGE_LENGTH, length); } bgpHeader.setLength(length); byte type = cb.readByte(); bgpHeader.setType(type); log.debug("Reading update message of type " + type); int len = length - MINIMUM_COMMON_HEADER_LENGTH; switch (type) { case OPEN_MSG_TYPE: log.debug("OPEN MESSAGE is received"); return BGPOpenMsgVer4.READER.readFrom(cb.readBytes(len), bgpHeader); case KEEPALIVE_MSG_TYPE: log.debug("KEEPALIVE MESSAGE is received"); return BGPKeepaliveMsgVer4.READER.readFrom(cb.readBytes(len), bgpHeader); case UPDATE_MSG_TYPE: log.debug("UPDATE MESSAGE is received"); // TODO: Update message version 4 case NOTIFICATION_MSG_TYPE: log.debug("NOTIFICATION MESSAGE is received"); return BGPNotificationMsgVer4.READER.readFrom(cb.readBytes(len), bgpHeader); default: Validation.validateType(BGPErrorType.MESSAGE_HEADER_ERROR, BGPErrorType.BAD_MESSAGE_TYPE, type); return null; } } catch (IndexOutOfBoundsException e) { throw new BGPParseException(BGPErrorType.MESSAGE_HEADER_ERROR, BGPErrorType.BAD_MESSAGE_LENGTH, null); } } } }