summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--isisd/isis_lsp.c20
-rw-r--r--isisd/isis_lsp.h1
-rw-r--r--isisd/isis_pdu.c225
-rw-r--r--isisd/isis_pdu.h32
4 files changed, 116 insertions, 162 deletions
diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c
index 40c6141ab8..1bea8c8c94 100644
--- a/isisd/isis_lsp.c
+++ b/isisd/isis_lsp.c
@@ -468,7 +468,6 @@ static void lsp_update_data(struct isis_lsp *lsp, struct stream *stream,
lsp->pdu = stream_dup(stream);
/* setting pointers to the correct place */
- lsp->isis_header = (struct isis_fixed_hdr *)(STREAM_DATA(lsp->pdu));
lsp->lsp_header = (struct isis_link_state_hdr *)(STREAM_DATA(lsp->pdu)
+ ISIS_FIXED_HDR_LEN);
lsp->area = area;
@@ -580,6 +579,8 @@ struct isis_lsp *lsp_new(struct isis_area *area, u_char *lsp_id,
u_int8_t lsp_bits, u_int16_t checksum, int level)
{
struct isis_lsp *lsp;
+ uint8_t pdu_type =
+ (level == IS_LEVEL_1) ? L1_LINK_STATE : L2_LINK_STATE;
lsp = XCALLOC(MTYPE_ISIS_LSP, sizeof(struct isis_lsp));
lsp->area = area;
@@ -587,16 +588,13 @@ struct isis_lsp *lsp_new(struct isis_area *area, u_char *lsp_id,
lsp->pdu = stream_new(LLC_LEN + area->lsp_mtu);
if (LSP_FRAGMENT(lsp_id) == 0)
lsp->lspu.frags = list_new();
- lsp->isis_header = (struct isis_fixed_hdr *)(STREAM_DATA(lsp->pdu));
- lsp->lsp_header = (struct isis_link_state_hdr *)(STREAM_DATA(lsp->pdu)
- + ISIS_FIXED_HDR_LEN);
- /* at first we fill the FIXED HEADER */
- (level == IS_LEVEL_1) ? fill_fixed_hdr(lsp->isis_header, L1_LINK_STATE)
- : fill_fixed_hdr(lsp->isis_header, L2_LINK_STATE);
+ fill_fixed_hdr(pdu_type, lsp->pdu);
/* now for the LSP HEADER */
/* Minimal LSP PDU size */
+ lsp->lsp_header = (struct isis_link_state_hdr *)(STREAM_DATA(lsp->pdu)
+ + ISIS_FIXED_HDR_LEN);
lsp->lsp_header->pdu_len = htons(ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN);
memcpy(lsp->lsp_header->lsp_id, lsp_id, ISIS_SYS_ID_LEN + 2);
lsp->lsp_header->checksum = checksum; /* Provided in network order */
@@ -2972,6 +2970,8 @@ void lsp_purge_non_exist(int level, struct isis_link_state_hdr *lsp_hdr,
struct isis_area *area)
{
struct isis_lsp *lsp;
+ uint8_t pdu_type =
+ (level == IS_LEVEL_1) ? L1_LINK_STATE : L2_LINK_STATE;
/*
* We need to create the LSP to be purged
@@ -2980,10 +2980,8 @@ void lsp_purge_non_exist(int level, struct isis_link_state_hdr *lsp_hdr,
lsp->area = area;
lsp->level = level;
lsp->pdu = stream_new(LLC_LEN + area->lsp_mtu);
- lsp->isis_header = (struct isis_fixed_hdr *)STREAM_DATA(lsp->pdu);
- fill_fixed_hdr(lsp->isis_header,
- (lsp->level == IS_LEVEL_1) ? L1_LINK_STATE
- : L2_LINK_STATE);
+ fill_fixed_hdr(pdu_type, lsp->pdu);
+
lsp->lsp_header = (struct isis_link_state_hdr *)(STREAM_DATA(lsp->pdu)
+ ISIS_FIXED_HDR_LEN);
memcpy(lsp->lsp_header, lsp_hdr, ISIS_LSP_HDR_LEN);
diff --git a/isisd/isis_lsp.h b/isisd/isis_lsp.h
index 7bec162719..f149b68964 100644
--- a/isisd/isis_lsp.h
+++ b/isisd/isis_lsp.h
@@ -29,7 +29,6 @@
* We will have to split the header into two parts, and for readability
* sake it should better be avoided */
struct isis_lsp {
- struct isis_fixed_hdr *isis_header; /* normally equals pdu */
struct isis_link_state_hdr *lsp_header; /* pdu + isis_header_len */
struct stream *pdu; /* full pdu lsp */
union {
diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c
index a3706179a6..937bd3bbe8 100644
--- a/isisd/isis_pdu.c
+++ b/isisd/isis_pdu.c
@@ -1888,59 +1888,103 @@ static int process_psnp(int level, struct isis_circuit *circuit,
return process_snp(ISIS_SNP_PSNP_FLAG, level, circuit, ssnpa);
}
+static int pdu_size(uint8_t pdu_type, uint8_t *size)
+{
+ switch (pdu_type) {
+ case L1_LAN_HELLO:
+ case L2_LAN_HELLO:
+ *size = ISIS_LANHELLO_HDRLEN;
+ break;
+ case P2P_HELLO:
+ *size = ISIS_P2PHELLO_HDRLEN;
+ break;
+ case L1_LINK_STATE:
+ case L2_LINK_STATE:
+ *size = ISIS_LSP_HDR_LEN;
+ break;
+ case L1_COMPLETE_SEQ_NUM:
+ case L2_COMPLETE_SEQ_NUM:
+ *size = ISIS_CSNP_HDRLEN;
+ break;
+ case L1_PARTIAL_SEQ_NUM:
+ case L2_PARTIAL_SEQ_NUM:
+ *size = ISIS_PSNP_HDRLEN;
+ break;
+ default:
+ return 1;
+ }
+ *size += ISIS_FIXED_HDR_LEN;
+ return 0;
+}
+
/*
* PDU Dispatcher
*/
static int isis_handle_pdu(struct isis_circuit *circuit, u_char *ssnpa)
{
- struct isis_fixed_hdr *hdr;
-
int retval = ISIS_OK;
- /*
- * Let's first read data from stream to the header
- */
- hdr = (struct isis_fixed_hdr *)STREAM_DATA(circuit->rcv_stream);
+ /* Verify that at least the 8 bytes fixed header have been received */
+ if (stream_get_endp(circuit->rcv_stream) < ISIS_FIXED_HDR_LEN) {
+ zlog_err("PDU is too short to be IS-IS.");
+ return ISIS_ERROR;
+ }
- if ((hdr->idrp != ISO10589_ISIS) && (hdr->idrp != ISO9542_ESIS)) {
- zlog_err("Not an IS-IS or ES-IS packet IDRP=%02x", hdr->idrp);
+ uint8_t idrp = stream_getc(circuit->rcv_stream);
+ uint8_t length = stream_getc(circuit->rcv_stream);
+ uint8_t version1 = stream_getc(circuit->rcv_stream);
+ uint8_t id_len = stream_getc(circuit->rcv_stream);
+ uint8_t pdu_type = stream_getc(circuit->rcv_stream)
+ & 0x1f; /* bits 6-8 are reserved */
+ uint8_t version2 = stream_getc(circuit->rcv_stream);
+ stream_forward_getp(circuit->rcv_stream, 1); /* reserved */
+ uint8_t max_area_addrs = stream_getc(circuit->rcv_stream);
+
+ if (idrp == ISO9542_ESIS) {
+ zlog_err("No support for ES-IS packet IDRP=%" PRIx8, idrp);
return ISIS_ERROR;
}
- /* now we need to know if this is an ISO 9542 packet and
- * take real good care of it, waaa!
- */
- if (hdr->idrp == ISO9542_ESIS) {
- zlog_err("No support for ES-IS packet IDRP=%02x", hdr->idrp);
+ if (idrp != ISO10589_ISIS) {
+ zlog_err("Not an IS-IS packet IDRP=%" PRIx8, idrp);
return ISIS_ERROR;
}
- stream_set_getp(circuit->rcv_stream, ISIS_FIXED_HDR_LEN);
- /*
- * and then process it
- */
+ if (version1 != 1) {
+ zlog_warn("Unsupported ISIS version %" PRIu8, version1);
+ return ISIS_WARNING;
+ }
- if (hdr->length < ISIS_MINIMUM_FIXED_HDR_LEN) {
- zlog_err("Fixed header length = %d", hdr->length);
+ if (id_len != 0 && id_len != ISIS_SYS_ID_LEN) {
+ zlog_err(
+ "IDFieldLengthMismatch: ID Length field in a received PDU %" PRIu8
+ ", while the parameter for this IS is %u",
+ id_len, ISIS_SYS_ID_LEN);
return ISIS_ERROR;
}
- if (hdr->version1 != 1) {
- zlog_warn("Unsupported ISIS version %u", hdr->version1);
+ uint8_t expected_length;
+ if (pdu_size(pdu_type, &expected_length)) {
+ zlog_warn("Unsupported ISIS PDU %" PRIu8, pdu_type);
return ISIS_WARNING;
}
- /* either 6 or 0 */
- if ((hdr->id_len != 0) && (hdr->id_len != ISIS_SYS_ID_LEN)) {
+
+ if (length != expected_length) {
+ zlog_err("Exepected fixed header length = %" PRIu8
+ " but got %" PRIu8,
+ expected_length, length);
+ return ISIS_ERROR;
+ }
+
+ if (stream_get_endp(circuit->rcv_stream) < length) {
zlog_err(
- "IDFieldLengthMismatch: ID Length field in a received PDU %u, "
- "while the parameter for this IS is %u",
- hdr->id_len, ISIS_SYS_ID_LEN);
+ "PDU is too short to contain fixed header of given PDU type.");
return ISIS_ERROR;
}
- if (hdr->version2 != 1) {
- zlog_warn("Unsupported ISIS version %u", hdr->version2);
+ if (version2 != 1) {
+ zlog_warn("Unsupported ISIS PDU version %" PRIu8, version2);
return ISIS_WARNING;
}
@@ -1951,16 +1995,15 @@ static int isis_handle_pdu(struct isis_circuit *circuit, u_char *ssnpa)
}
/* either 3 or 0 */
- if ((hdr->max_area_addrs != 0)
- && (hdr->max_area_addrs != isis->max_area_addrs)) {
+ if (max_area_addrs != 0 && max_area_addrs != isis->max_area_addrs) {
zlog_err(
- "maximumAreaAddressesMismatch: maximumAreaAdresses in a "
- "received PDU %u while the parameter for this IS is %u",
- hdr->max_area_addrs, isis->max_area_addrs);
+ "maximumAreaAddressesMismatch: maximumAreaAdresses in a received PDU %" PRIu8
+ " while the parameter for this IS is %u",
+ max_area_addrs, isis->max_area_addrs);
return ISIS_ERROR;
}
- switch (hdr->pdu_type) {
+ switch (pdu_type) {
case L1_LAN_HELLO:
retval = process_lan_hello(ISIS_LEVEL1, circuit, ssnpa);
break;
@@ -2025,68 +2068,28 @@ int isis_receive(struct thread *thread)
return retval;
}
-/* filling of the fixed isis header */
-void fill_fixed_hdr(struct isis_fixed_hdr *hdr, u_char pdu_type)
-{
- memset(hdr, 0, sizeof(struct isis_fixed_hdr));
-
- hdr->idrp = ISO10589_ISIS;
-
- switch (pdu_type) {
- case L1_LAN_HELLO:
- case L2_LAN_HELLO:
- hdr->length = ISIS_LANHELLO_HDRLEN;
- break;
- case P2P_HELLO:
- hdr->length = ISIS_P2PHELLO_HDRLEN;
- break;
- case L1_LINK_STATE:
- case L2_LINK_STATE:
- hdr->length = ISIS_LSP_HDR_LEN;
- break;
- case L1_COMPLETE_SEQ_NUM:
- case L2_COMPLETE_SEQ_NUM:
- hdr->length = ISIS_CSNP_HDRLEN;
- break;
- case L1_PARTIAL_SEQ_NUM:
- case L2_PARTIAL_SEQ_NUM:
- hdr->length = ISIS_PSNP_HDRLEN;
- break;
- default:
- zlog_warn("fill_fixed_hdr(): unknown pdu type %d", pdu_type);
- return;
- }
- hdr->length += ISIS_FIXED_HDR_LEN;
- hdr->pdu_type = pdu_type;
- hdr->version1 = 1;
- hdr->id_len = 0; /* ISIS_SYS_ID_LEN - 0==6 */
- hdr->version2 = 1;
- hdr->max_area_addrs = 0; /* isis->max_area_addrs - 0==3 */
-}
-
/*
* SEND SIDE
*/
-static void fill_fixed_hdr_andstream(struct isis_fixed_hdr *hdr,
- u_char pdu_type, struct stream *stream)
+void fill_fixed_hdr(uint8_t pdu_type, struct stream *stream)
{
- fill_fixed_hdr(hdr, pdu_type);
-
- stream_putc(stream, hdr->idrp);
- stream_putc(stream, hdr->length);
- stream_putc(stream, hdr->version1);
- stream_putc(stream, hdr->id_len);
- stream_putc(stream, hdr->pdu_type);
- stream_putc(stream, hdr->version2);
- stream_putc(stream, hdr->reserved);
- stream_putc(stream, hdr->max_area_addrs);
-
- return;
+ uint8_t length;
+
+ if (pdu_size(pdu_type, &length))
+ assert(!"Unknown PDU Type");
+
+ stream_putc(stream, ISO10589_ISIS); /* IDRP */
+ stream_putc(stream, length); /* Length of fixed header */
+ stream_putc(stream, 1); /* Version/Protocol ID Extension 1 */
+ stream_putc(stream, 0); /* ID Length, 0 => 6 */
+ stream_putc(stream, pdu_type);
+ stream_putc(stream, 1); /* Subversion */
+ stream_putc(stream, 0); /* Reserved */
+ stream_putc(stream, 0); /* Max Area Addresses 0 => 3 */
}
int send_hello(struct isis_circuit *circuit, int level)
{
- struct isis_fixed_hdr fixed_hdr;
struct isis_lan_hello_hdr hello_hdr;
struct isis_p2p_hello_hdr p2p_hello_hdr;
unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE];
@@ -2104,16 +2107,14 @@ int send_hello(struct isis_circuit *circuit, int level)
isis_circuit_stream(circuit, &circuit->snd_stream);
+ uint8_t pdu_type;
+
if (circuit->circ_type == CIRCUIT_T_BROADCAST)
- if (level == IS_LEVEL_1)
- fill_fixed_hdr_andstream(&fixed_hdr, L1_LAN_HELLO,
- circuit->snd_stream);
- else
- fill_fixed_hdr_andstream(&fixed_hdr, L2_LAN_HELLO,
- circuit->snd_stream);
+ pdu_type = (level == IS_LEVEL_1) ? L1_LAN_HELLO : L2_LAN_HELLO;
else
- fill_fixed_hdr_andstream(&fixed_hdr, P2P_HELLO,
- circuit->snd_stream);
+ pdu_type = P2P_HELLO;
+
+ fill_fixed_hdr(pdu_type, circuit->snd_stream);
/*
* Fill LAN Level 1 or 2 Hello PDU header
@@ -2369,22 +2370,18 @@ int send_p2p_hello(struct thread *thread)
static int build_csnp(int level, u_char *start, u_char *stop, struct list *lsps,
struct isis_circuit *circuit)
{
- struct isis_fixed_hdr fixed_hdr;
struct isis_passwd *passwd;
unsigned long lenp;
u_int16_t length;
unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE];
unsigned long auth_tlv_offset = 0;
int retval = ISIS_OK;
+ uint8_t pdu_type = (level == IS_LEVEL_1) ? L1_COMPLETE_SEQ_NUM
+ : L2_COMPLETE_SEQ_NUM;
isis_circuit_stream(circuit, &circuit->snd_stream);
- if (level == IS_LEVEL_1)
- fill_fixed_hdr_andstream(&fixed_hdr, L1_COMPLETE_SEQ_NUM,
- circuit->snd_stream);
- else
- fill_fixed_hdr_andstream(&fixed_hdr, L2_COMPLETE_SEQ_NUM,
- circuit->snd_stream);
+ fill_fixed_hdr(pdu_type, circuit->snd_stream);
/*
* Fill Level 1 or 2 Complete Sequence Numbers header
@@ -2682,7 +2679,6 @@ int send_l2_csnp(struct thread *thread)
static int build_psnp(int level, struct isis_circuit *circuit,
struct list *lsps)
{
- struct isis_fixed_hdr fixed_hdr;
unsigned long lenp;
u_int16_t length;
struct isis_lsp *lsp;
@@ -2691,15 +2687,12 @@ static int build_psnp(int level, struct isis_circuit *circuit,
unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE];
unsigned long auth_tlv_offset = 0;
int retval = ISIS_OK;
+ uint8_t pdu_type =
+ (level == IS_LEVEL_1) ? L1_PARTIAL_SEQ_NUM : L2_PARTIAL_SEQ_NUM;
isis_circuit_stream(circuit, &circuit->snd_stream);
- if (level == IS_LEVEL_1)
- fill_fixed_hdr_andstream(&fixed_hdr, L1_PARTIAL_SEQ_NUM,
- circuit->snd_stream);
- else
- fill_fixed_hdr_andstream(&fixed_hdr, L2_PARTIAL_SEQ_NUM,
- circuit->snd_stream);
+ fill_fixed_hdr(pdu_type, circuit->snd_stream);
/*
* Fill Level 1 or 2 Partial Sequence Numbers header
@@ -3033,18 +3026,12 @@ int ack_lsp(struct isis_link_state_hdr *hdr, struct isis_circuit *circuit,
unsigned long lenp;
int retval;
u_int16_t length;
- struct isis_fixed_hdr fixed_hdr;
+ uint8_t pdu_type =
+ (level == IS_LEVEL_1) ? L1_PARTIAL_SEQ_NUM : L2_PARTIAL_SEQ_NUM;
isis_circuit_stream(circuit, &circuit->snd_stream);
- // fill_llc_hdr (stream);
- if (level == IS_LEVEL_1)
- fill_fixed_hdr_andstream(&fixed_hdr, L1_PARTIAL_SEQ_NUM,
- circuit->snd_stream);
- else
- fill_fixed_hdr_andstream(&fixed_hdr, L2_PARTIAL_SEQ_NUM,
- circuit->snd_stream);
-
+ fill_fixed_hdr(pdu_type, circuit->snd_stream);
lenp = stream_get_endp(circuit->snd_stream);
stream_putw(circuit->snd_stream, 0); /* PDU length */
diff --git a/isisd/isis_pdu.h b/isisd/isis_pdu.h
index fa8006cda0..985fc56adf 100644
--- a/isisd/isis_pdu.h
+++ b/isisd/isis_pdu.h
@@ -65,36 +65,6 @@ struct esis_fixed_hdr {
#define ISH_PDU 4
#define RD_PDU 5
-/*
- * IS to IS Fixed Header
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | Intradomain Routeing Protocol Discriminator |
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | Length Indicator |
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | Version/Protocol ID extension |
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | R | R | R | PDU Type |
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | Version |
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | Reserved |
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- * | Maximum Area Addresses |
- * +-------+-------+-------+-------+-------+-------+-------+-------+
- */
-
-struct isis_fixed_hdr {
- u_char idrp;
- u_char length;
- u_char version1;
- u_char id_len;
- u_char pdu_type;
- u_char version2;
- u_char reserved;
- u_char max_area_addrs;
-} __attribute__((packed));
-
#define ISIS_FIXED_HDR_LEN 8
/*
@@ -261,7 +231,7 @@ int send_l2_psnp(struct thread *thread);
int send_lsp(struct thread *thread);
int ack_lsp(struct isis_link_state_hdr *hdr, struct isis_circuit *circuit,
int level);
-void fill_fixed_hdr(struct isis_fixed_hdr *hdr, u_char pdu_type);
+void fill_fixed_hdr(uint8_t pdu_type, struct stream *stream);
int send_hello(struct isis_circuit *circuit, int level);
#endif /* _ZEBRA_ISIS_PDU_H */