diff options
| author | whitespace / reindent <invalid@invalid.invalid> | 2017-08-09 11:49:42 +0200 | 
|---|---|---|
| committer | whitespace / reindent <invalid@invalid.invalid> | 2017-08-09 12:03:17 +0200 | 
| commit | ac4d0be5874fafd14212d6007fff7495edc9b152 (patch) | |
| tree | 5e2f0d3189de928c849f9983406389ade3b098cb /isisd/isis_pdu.c | |
| parent | 76a86854181c27819e5cf71b12ae1fa5ccd9e02a (diff) | |
*: reindentreindent-3.0-after
indent.py `git ls-files | pcregrep '\.[ch]$' | pcregrep -v '^(ldpd|babeld|nhrpd)/'`
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Diffstat (limited to 'isisd/isis_pdu.c')
| -rw-r--r-- | isisd/isis_pdu.c | 5301 | 
1 files changed, 2600 insertions, 2701 deletions
diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c index a41581ff02..dfb01fc02b 100644 --- a/isisd/isis_pdu.c +++ b/isisd/isis_pdu.c @@ -1,23 +1,23 @@  /* - * IS-IS Rout(e)ing protocol - isis_pdu.c    + * IS-IS Rout(e)ing protocol - isis_pdu.c   *                             PDU processing   *   * Copyright (C) 2001,2002   Sampo Saaristo - *                           Tampere University of Technology       + *                           Tampere University of Technology   *                           Institute of Communications Engineering   * - * This program is free software; you can redistribute it and/or modify it  - * under the terms of the GNU General Public Licenseas published by the Free  - * Software Foundation; either version 2 of the License, or (at your option)  + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public Licenseas published by the Free + * Software Foundation; either version 2 of the License, or (at your option)   * any later version.   * - * This program is distributed in the hope that it will be useful,but WITHOUT  - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or  - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for  + * This program is distributed in the hope that it will be useful,but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for   * more details. - * You should have received a copy of the GNU General Public License along  - * with this program; if not, write to the Free Software Foundation, Inc.,  + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc.,   * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.   */ @@ -62,9 +62,8 @@  #endif /* PNBBY */  /* Utility mask array. */ -static const u_char maskbit[] = { -  0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff -}; +static const u_char maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, +				 0xf8, 0xfc, 0xfe, 0xff};  /*   * HELPER FUNCS @@ -73,23 +72,21 @@ static const u_char maskbit[] = {  /*   * Compares two sets of area addresses   */ -static int -area_match (struct list *left, struct list *right) +static int area_match(struct list *left, struct list *right)  { -  struct area_addr *addr1, *addr2; -  struct listnode *node1, *node2; - -  for (ALL_LIST_ELEMENTS_RO (left, node1, addr1)) -  { -    for (ALL_LIST_ELEMENTS_RO (right, node2, addr2)) -    { -      if (addr1->addr_len == addr2->addr_len && -	  !memcmp (addr1->area_addr, addr2->area_addr, (int) addr1->addr_len)) -	return 1;		/* match */ -    } -  } +	struct area_addr *addr1, *addr2; +	struct listnode *node1, *node2; + +	for (ALL_LIST_ELEMENTS_RO(left, node1, addr1)) { +		for (ALL_LIST_ELEMENTS_RO(right, node2, addr2)) { +			if (addr1->addr_len == addr2->addr_len +			    && !memcmp(addr1->area_addr, addr2->area_addr, +				       (int)addr1->addr_len)) +				return 1; /* match */ +		} +	} -  return 0;			/* mismatch */ +	return 0; /* mismatch */  }  /* @@ -99,29 +96,28 @@ area_match (struct list *left, struct list *right)   * return  0            the IIH's IP is not in the IS's subnetwork   *         1            the IIH's IP is in the IS's subnetwork   */ -static int -ip_same_subnet (struct prefix_ipv4 *ip1, struct in_addr *ip2) +static int ip_same_subnet(struct prefix_ipv4 *ip1, struct in_addr *ip2)  { -  u_char *addr1, *addr2; -  int shift, offset, offsetloop; -  int len; +	u_char *addr1, *addr2; +	int shift, offset, offsetloop; +	int len; -  addr1 = (u_char *) & ip1->prefix.s_addr; -  addr2 = (u_char *) & ip2->s_addr; -  len = ip1->prefixlen; +	addr1 = (u_char *)&ip1->prefix.s_addr; +	addr2 = (u_char *)&ip2->s_addr; +	len = ip1->prefixlen; -  shift = len % PNBBY; -  offsetloop = offset = len / PNBBY; +	shift = len % PNBBY; +	offsetloop = offset = len / PNBBY; -  while (offsetloop--) -    if (addr1[offsetloop] != addr2[offsetloop]) -      return 0; +	while (offsetloop--) +		if (addr1[offsetloop] != addr2[offsetloop]) +			return 0; -  if (shift) -    if (maskbit[shift] & (addr1[offset] ^ addr2[offset])) -      return 0; +	if (shift) +		if (maskbit[shift] & (addr1[offset] ^ addr2[offset])) +			return 0; -  return 1;			/* match  */ +	return 1; /* match  */  }  /* @@ -131,258 +127,240 @@ ip_same_subnet (struct prefix_ipv4 *ip1, struct in_addr *ip2)   * return         0   no match;   *                1   match;   */ -static int -ip_match (struct list *left, struct list *right) +static int ip_match(struct list *left, struct list *right)  { -  struct prefix_ipv4 *ip1; -  struct in_addr *ip2; -  struct listnode *node1, *node2; - -  if ((left == NULL) || (right == NULL)) -    return 0; -   -  for (ALL_LIST_ELEMENTS_RO (left, node1, ip1)) -  { -    for (ALL_LIST_ELEMENTS_RO (right, node2, ip2)) -    { -      if (ip_same_subnet (ip1, ip2)) -	{ -	  return 1;		/* match */ +	struct prefix_ipv4 *ip1; +	struct in_addr *ip2; +	struct listnode *node1, *node2; + +	if ((left == NULL) || (right == NULL)) +		return 0; + +	for (ALL_LIST_ELEMENTS_RO(left, node1, ip1)) { +		for (ALL_LIST_ELEMENTS_RO(right, node2, ip2)) { +			if (ip_same_subnet(ip1, ip2)) { +				return 1; /* match */ +			} +		}  	} -    } - -  } -  return 0; +	return 0;  }  /* - * Checks whether we should accept a PDU of given level  + * Checks whether we should accept a PDU of given level   */ -static int -accept_level (int level, int circuit_t) +static int accept_level(int level, int circuit_t)  { -  int retval = ((circuit_t & level) == level);	/* simple approach */ +	int retval = ((circuit_t & level) == level); /* simple approach */ -  return retval; +	return retval;  }  /*   * Verify authentication information   * Support cleartext and HMAC MD5 authentication   */ -static int -authentication_check (struct isis_passwd *remote, struct isis_passwd *local, -                      struct stream *stream, uint32_t auth_tlv_offset) +static int authentication_check(struct isis_passwd *remote, +				struct isis_passwd *local, +				struct stream *stream, uint32_t auth_tlv_offset)  { -  unsigned char digest[ISIS_AUTH_MD5_SIZE]; - -  /* Auth fail () - passwd type mismatch */ -  if (local->type != remote->type) -    return ISIS_ERROR; - -  switch (local->type) -  { -    /* No authentication required */ -    case ISIS_PASSWD_TYPE_UNUSED: -      break; - -    /* Cleartext (ISO 10589) */ -    case ISIS_PASSWD_TYPE_CLEARTXT: -      /* Auth fail () - passwd len mismatch */ -      if (remote->len != local->len) -        return ISIS_ERROR; -      return memcmp (local->passwd, remote->passwd, local->len); - -    /* HMAC MD5 (RFC 3567) */ -    case ISIS_PASSWD_TYPE_HMAC_MD5: -      /* Auth fail () - passwd len mismatch */ -      if (remote->len != ISIS_AUTH_MD5_SIZE) -        return ISIS_ERROR; -      /* Set the authentication value to 0 before the check */ -      memset (STREAM_DATA (stream) + auth_tlv_offset + 3, 0, -              ISIS_AUTH_MD5_SIZE); -      /* Compute the digest */ -      hmac_md5 (STREAM_DATA (stream), stream_get_endp (stream), -                (unsigned char *) &(local->passwd), local->len, -                (unsigned char *) &digest); -      /* Copy back the authentication value after the check */ -      memcpy (STREAM_DATA (stream) + auth_tlv_offset + 3, -              remote->passwd, ISIS_AUTH_MD5_SIZE); -      return memcmp (digest, remote->passwd, ISIS_AUTH_MD5_SIZE); - -    default: -      zlog_err ("Unsupported authentication type"); -      return ISIS_ERROR; -  } - -  /* Authentication pass when no authentication is configured */ -  return ISIS_OK; +	unsigned char digest[ISIS_AUTH_MD5_SIZE]; + +	/* Auth fail () - passwd type mismatch */ +	if (local->type != remote->type) +		return ISIS_ERROR; + +	switch (local->type) { +	/* No authentication required */ +	case ISIS_PASSWD_TYPE_UNUSED: +		break; + +	/* Cleartext (ISO 10589) */ +	case ISIS_PASSWD_TYPE_CLEARTXT: +		/* Auth fail () - passwd len mismatch */ +		if (remote->len != local->len) +			return ISIS_ERROR; +		return memcmp(local->passwd, remote->passwd, local->len); + +	/* HMAC MD5 (RFC 3567) */ +	case ISIS_PASSWD_TYPE_HMAC_MD5: +		/* Auth fail () - passwd len mismatch */ +		if (remote->len != ISIS_AUTH_MD5_SIZE) +			return ISIS_ERROR; +		/* Set the authentication value to 0 before the check */ +		memset(STREAM_DATA(stream) + auth_tlv_offset + 3, 0, +		       ISIS_AUTH_MD5_SIZE); +		/* Compute the digest */ +		hmac_md5(STREAM_DATA(stream), stream_get_endp(stream), +			 (unsigned char *)&(local->passwd), local->len, +			 (unsigned char *)&digest); +		/* Copy back the authentication value after the check */ +		memcpy(STREAM_DATA(stream) + auth_tlv_offset + 3, +		       remote->passwd, ISIS_AUTH_MD5_SIZE); +		return memcmp(digest, remote->passwd, ISIS_AUTH_MD5_SIZE); + +	default: +		zlog_err("Unsupported authentication type"); +		return ISIS_ERROR; +	} + +	/* Authentication pass when no authentication is configured */ +	return ISIS_OK;  } -static int -lsp_authentication_check (struct stream *stream, struct isis_area *area, -                          int level, struct isis_passwd *passwd) +static int lsp_authentication_check(struct stream *stream, +				    struct isis_area *area, int level, +				    struct isis_passwd *passwd)  { -  struct isis_link_state_hdr *hdr; -  uint32_t expected = 0, found = 0, auth_tlv_offset = 0; -  uint16_t checksum, rem_lifetime, pdu_len; -  struct tlvs tlvs; -  int retval = ISIS_OK; - -  hdr = (struct isis_link_state_hdr *) (STREAM_PNT (stream)); -  pdu_len = ntohs (hdr->pdu_len); -  expected |= TLVFLAG_AUTH_INFO; -  auth_tlv_offset = stream_get_getp (stream) + ISIS_LSP_HDR_LEN; -  retval = parse_tlvs (area->area_tag, STREAM_PNT (stream) + ISIS_LSP_HDR_LEN, -                       pdu_len - ISIS_FIXED_HDR_LEN - ISIS_LSP_HDR_LEN, -                       &expected, &found, &tlvs, &auth_tlv_offset); - -  if (retval != ISIS_OK) -    { -      zlog_err ("ISIS-Upd (%s): Parse failed L%d LSP %s, seq 0x%08x, " -                "cksum 0x%04x, lifetime %us, len %u", -                area->area_tag, level, rawlspid_print (hdr->lsp_id), -                ntohl (hdr->seq_num), ntohs (hdr->checksum), -                ntohs (hdr->rem_lifetime), pdu_len); -      if ((isis->debugs & DEBUG_UPDATE_PACKETS) && -          (isis->debugs & DEBUG_PACKET_DUMP)) -        zlog_dump_data (STREAM_DATA (stream), stream_get_endp (stream)); -      return retval; -    } +	struct isis_link_state_hdr *hdr; +	uint32_t expected = 0, found = 0, auth_tlv_offset = 0; +	uint16_t checksum, rem_lifetime, pdu_len; +	struct tlvs tlvs; +	int retval = ISIS_OK; + +	hdr = (struct isis_link_state_hdr *)(STREAM_PNT(stream)); +	pdu_len = ntohs(hdr->pdu_len); +	expected |= TLVFLAG_AUTH_INFO; +	auth_tlv_offset = stream_get_getp(stream) + ISIS_LSP_HDR_LEN; +	retval = parse_tlvs(area->area_tag, +			    STREAM_PNT(stream) + ISIS_LSP_HDR_LEN, +			    pdu_len - ISIS_FIXED_HDR_LEN - ISIS_LSP_HDR_LEN, +			    &expected, &found, &tlvs, &auth_tlv_offset); + +	if (retval != ISIS_OK) { +		zlog_err( +			"ISIS-Upd (%s): Parse failed L%d LSP %s, seq 0x%08x, " +			"cksum 0x%04x, lifetime %us, len %u", +			area->area_tag, level, rawlspid_print(hdr->lsp_id), +			ntohl(hdr->seq_num), ntohs(hdr->checksum), +			ntohs(hdr->rem_lifetime), pdu_len); +		if ((isis->debugs & DEBUG_UPDATE_PACKETS) +		    && (isis->debugs & DEBUG_PACKET_DUMP)) +			zlog_dump_data(STREAM_DATA(stream), +				       stream_get_endp(stream)); +		return retval; +	} -  if (!(found & TLVFLAG_AUTH_INFO)) -    { -      zlog_err ("No authentication tlv in LSP"); -      return ISIS_ERROR; -    } +	if (!(found & TLVFLAG_AUTH_INFO)) { +		zlog_err("No authentication tlv in LSP"); +		return ISIS_ERROR; +	} -  if (tlvs.auth_info.type != ISIS_PASSWD_TYPE_CLEARTXT && -      tlvs.auth_info.type != ISIS_PASSWD_TYPE_HMAC_MD5) -    { -      zlog_err ("Unknown authentication type in LSP"); -      return ISIS_ERROR; -    } +	if (tlvs.auth_info.type != ISIS_PASSWD_TYPE_CLEARTXT +	    && tlvs.auth_info.type != ISIS_PASSWD_TYPE_HMAC_MD5) { +		zlog_err("Unknown authentication type in LSP"); +		return ISIS_ERROR; +	} -  /* -   * RFC 5304 set checksum and remaining lifetime to zero before -   * verification and reset to old values after verification. -   */ -  checksum = hdr->checksum; -  rem_lifetime = hdr->rem_lifetime; -  hdr->checksum = 0; -  hdr->rem_lifetime = 0; -  retval = authentication_check (&tlvs.auth_info, passwd, stream, -                                 auth_tlv_offset); -  hdr->checksum = checksum; -  hdr->rem_lifetime = rem_lifetime; - -  return retval; +	/* +	 * RFC 5304 set checksum and remaining lifetime to zero before +	 * verification and reset to old values after verification. +	 */ +	checksum = hdr->checksum; +	rem_lifetime = hdr->rem_lifetime; +	hdr->checksum = 0; +	hdr->rem_lifetime = 0; +	retval = authentication_check(&tlvs.auth_info, passwd, stream, +				      auth_tlv_offset); +	hdr->checksum = checksum; +	hdr->rem_lifetime = rem_lifetime; + +	return retval;  }  /*   * Processing helper functions   */ -static void -del_addr (void *val) +static void del_addr(void *val)  { -  XFREE (MTYPE_ISIS_TMP, val); +	XFREE(MTYPE_ISIS_TMP, val);  } -static void -tlvs_to_adj_area_addrs (struct tlvs *tlvs, struct isis_adjacency *adj) +static void tlvs_to_adj_area_addrs(struct tlvs *tlvs, +				   struct isis_adjacency *adj)  { -  struct listnode *node; -  struct area_addr *area_addr, *malloced; +	struct listnode *node; +	struct area_addr *area_addr, *malloced; -  if (adj->area_addrs) -    { -      adj->area_addrs->del = del_addr; -      list_delete (adj->area_addrs); -    } -  adj->area_addrs = list_new (); -  if (tlvs->area_addrs) -    { -      for (ALL_LIST_ELEMENTS_RO (tlvs->area_addrs, node, area_addr)) -      { -	malloced = XMALLOC (MTYPE_ISIS_TMP, sizeof (struct area_addr)); -	memcpy (malloced, area_addr, sizeof (struct area_addr)); -	listnode_add (adj->area_addrs, malloced); -      } -    } +	if (adj->area_addrs) { +		adj->area_addrs->del = del_addr; +		list_delete(adj->area_addrs); +	} +	adj->area_addrs = list_new(); +	if (tlvs->area_addrs) { +		for (ALL_LIST_ELEMENTS_RO(tlvs->area_addrs, node, area_addr)) { +			malloced = XMALLOC(MTYPE_ISIS_TMP, +					   sizeof(struct area_addr)); +			memcpy(malloced, area_addr, sizeof(struct area_addr)); +			listnode_add(adj->area_addrs, malloced); +		} +	}  } -static int -tlvs_to_adj_nlpids (struct tlvs *tlvs, struct isis_adjacency *adj) +static int tlvs_to_adj_nlpids(struct tlvs *tlvs, struct isis_adjacency *adj)  { -  int i; -  struct nlpids *tlv_nlpids; +	int i; +	struct nlpids *tlv_nlpids; -  if (tlvs->nlpids) -    { +	if (tlvs->nlpids) { -      tlv_nlpids = tlvs->nlpids; -      if (tlv_nlpids->count > array_size (adj->nlpids.nlpids)) -        return 1; +		tlv_nlpids = tlvs->nlpids; +		if (tlv_nlpids->count > array_size(adj->nlpids.nlpids)) +			return 1; -      adj->nlpids.count = tlv_nlpids->count; +		adj->nlpids.count = tlv_nlpids->count; -      for (i = 0; i < tlv_nlpids->count; i++) -	{ -	  adj->nlpids.nlpids[i] = tlv_nlpids->nlpids[i]; +		for (i = 0; i < tlv_nlpids->count; i++) { +			adj->nlpids.nlpids[i] = tlv_nlpids->nlpids[i]; +		}  	} -    } -  return 0; +	return 0;  } -static void -tlvs_to_adj_ipv4_addrs (struct tlvs *tlvs, struct isis_adjacency *adj) +static void tlvs_to_adj_ipv4_addrs(struct tlvs *tlvs, +				   struct isis_adjacency *adj)  { -  struct listnode *node; -  struct in_addr *ipv4_addr, *malloced; +	struct listnode *node; +	struct in_addr *ipv4_addr, *malloced; -  if (adj->ipv4_addrs) -    { -      adj->ipv4_addrs->del = del_addr; -      list_delete (adj->ipv4_addrs); -    } -  adj->ipv4_addrs = list_new (); -  if (tlvs->ipv4_addrs) -    { -      for (ALL_LIST_ELEMENTS_RO (tlvs->ipv4_addrs, node, ipv4_addr)) -      { -	malloced = XMALLOC (MTYPE_ISIS_TMP, sizeof (struct in_addr)); -	memcpy (malloced, ipv4_addr, sizeof (struct in_addr)); -	listnode_add (adj->ipv4_addrs, malloced); -      } -    } +	if (adj->ipv4_addrs) { +		adj->ipv4_addrs->del = del_addr; +		list_delete(adj->ipv4_addrs); +	} +	adj->ipv4_addrs = list_new(); +	if (tlvs->ipv4_addrs) { +		for (ALL_LIST_ELEMENTS_RO(tlvs->ipv4_addrs, node, ipv4_addr)) { +			malloced = +				XMALLOC(MTYPE_ISIS_TMP, sizeof(struct in_addr)); +			memcpy(malloced, ipv4_addr, sizeof(struct in_addr)); +			listnode_add(adj->ipv4_addrs, malloced); +		} +	}  } -static void -tlvs_to_adj_ipv6_addrs (struct tlvs *tlvs, struct isis_adjacency *adj) +static void tlvs_to_adj_ipv6_addrs(struct tlvs *tlvs, +				   struct isis_adjacency *adj)  { -  struct listnode *node; -  struct in6_addr *ipv6_addr, *malloced; - -  if (adj->ipv6_addrs) -    { -      adj->ipv6_addrs->del = del_addr; -      list_delete (adj->ipv6_addrs); -    } -  adj->ipv6_addrs = list_new (); -  if (tlvs->ipv6_addrs) -    { -      for (ALL_LIST_ELEMENTS_RO (tlvs->ipv6_addrs, node, ipv6_addr)) -      { -	malloced = XMALLOC (MTYPE_ISIS_TMP, sizeof (struct in6_addr)); -	memcpy (malloced, ipv6_addr, sizeof (struct in6_addr)); -	listnode_add (adj->ipv6_addrs, malloced); -      } -    } +	struct listnode *node; +	struct in6_addr *ipv6_addr, *malloced; +	if (adj->ipv6_addrs) { +		adj->ipv6_addrs->del = del_addr; +		list_delete(adj->ipv6_addrs); +	} +	adj->ipv6_addrs = list_new(); +	if (tlvs->ipv6_addrs) { +		for (ALL_LIST_ELEMENTS_RO(tlvs->ipv6_addrs, node, ipv6_addr)) { +			malloced = XMALLOC(MTYPE_ISIS_TMP, +					   sizeof(struct in6_addr)); +			memcpy(malloced, ipv6_addr, sizeof(struct in6_addr)); +			listnode_add(adj->ipv6_addrs, malloced); +		} +	}  }  /* - *  RECEIVE SIDE                            + *  RECEIVE SIDE   */  /* @@ -391,576 +369,552 @@ tlvs_to_adj_ipv6_addrs (struct tlvs *tlvs, struct isis_adjacency *adj)   * Section 8.2.5 - Receiving point-to-point IIH PDUs   *   */ -static int -process_p2p_hello (struct isis_circuit *circuit) +static int process_p2p_hello(struct isis_circuit *circuit)  { -  int retval = ISIS_OK; -  struct isis_p2p_hello_hdr *hdr; -  struct isis_adjacency *adj; -  u_int32_t expected = 0, found = 0, auth_tlv_offset = 0; -  uint16_t pdu_len; -  struct tlvs tlvs; -  int v4_usable = 0, v6_usable = 0; - -  if (isis->debugs & DEBUG_ADJ_PACKETS) -    { -      zlog_debug ("ISIS-Adj (%s): Rcvd P2P IIH on %s, cirType %s, cirID %u", -                  circuit->area->area_tag, circuit->interface->name, -                  circuit_t2string (circuit->is_type), circuit->circuit_id); -      if (isis->debugs & DEBUG_PACKET_DUMP) -        zlog_dump_data (STREAM_DATA (circuit->rcv_stream), -                        stream_get_endp (circuit->rcv_stream)); -    } - -  if (circuit->circ_type != CIRCUIT_T_P2P) -    { -      zlog_warn ("p2p hello on non p2p circuit"); -      return ISIS_WARNING; -    } - -  if ((stream_get_endp (circuit->rcv_stream) - -       stream_get_getp (circuit->rcv_stream)) < ISIS_P2PHELLO_HDRLEN) -    { -      zlog_warn ("Packet too short"); -      return ISIS_WARNING; -    } +	int retval = ISIS_OK; +	struct isis_p2p_hello_hdr *hdr; +	struct isis_adjacency *adj; +	u_int32_t expected = 0, found = 0, auth_tlv_offset = 0; +	uint16_t pdu_len; +	struct tlvs tlvs; +	int v4_usable = 0, v6_usable = 0; + +	if (isis->debugs & DEBUG_ADJ_PACKETS) { +		zlog_debug( +			"ISIS-Adj (%s): Rcvd P2P IIH on %s, cirType %s, cirID %u", +			circuit->area->area_tag, circuit->interface->name, +			circuit_t2string(circuit->is_type), +			circuit->circuit_id); +		if (isis->debugs & DEBUG_PACKET_DUMP) +			zlog_dump_data(STREAM_DATA(circuit->rcv_stream), +				       stream_get_endp(circuit->rcv_stream)); +	} -  /* 8.2.5.1 PDU acceptance tests */ +	if (circuit->circ_type != CIRCUIT_T_P2P) { +		zlog_warn("p2p hello on non p2p circuit"); +		return ISIS_WARNING; +	} -  /* 8.2.5.1 a) external domain untrue */ -  /* FIXME: not useful at all?         */ +	if ((stream_get_endp(circuit->rcv_stream) +	     - stream_get_getp(circuit->rcv_stream)) +	    < ISIS_P2PHELLO_HDRLEN) { +		zlog_warn("Packet too short"); +		return ISIS_WARNING; +	} -  /* 8.2.5.1 b) ID Length mismatch */ -  /* checked at the handle_pdu     */ +	/* 8.2.5.1 PDU acceptance tests */ -  /* 8.2.5.2 IIH PDU Processing */ +	/* 8.2.5.1 a) external domain untrue */ +	/* FIXME: not useful at all?         */ -  /* 8.2.5.2 a) 1) Maximum Area Addresses */ -  /* Already checked, and can also be ommited */ +	/* 8.2.5.1 b) ID Length mismatch */ +	/* checked at the handle_pdu     */ -  /* -   * Get the header -   */ -  hdr = (struct isis_p2p_hello_hdr *) STREAM_PNT (circuit->rcv_stream); -  pdu_len = ntohs (hdr->pdu_len); +	/* 8.2.5.2 IIH PDU Processing */ -  if (pdu_len < (ISIS_FIXED_HDR_LEN + ISIS_P2PHELLO_HDRLEN) || -      pdu_len > ISO_MTU(circuit) || -      pdu_len > stream_get_endp (circuit->rcv_stream)) -    { -      zlog_warn ("ISIS-Adj (%s): Rcvd P2P IIH from (%s) with " -                 "invalid pdu length %d", -                 circuit->area->area_tag, circuit->interface->name, pdu_len); -      return ISIS_WARNING; -    } +	/* 8.2.5.2 a) 1) Maximum Area Addresses */ +	/* Already checked, and can also be ommited */ -  /* -   * Set the stream endp to PDU length, ignoring additional padding -   * introduced by transport chips. -   */ -  if (pdu_len < stream_get_endp (circuit->rcv_stream)) -    stream_set_endp (circuit->rcv_stream, pdu_len); - -  stream_forward_getp (circuit->rcv_stream, ISIS_P2PHELLO_HDRLEN); - -  /* -   * Lets get the TLVS now -   */ -  expected |= TLVFLAG_AREA_ADDRS; -  expected |= TLVFLAG_AUTH_INFO; -  expected |= TLVFLAG_NLPID; -  expected |= TLVFLAG_IPV4_ADDR; -  expected |= TLVFLAG_IPV6_ADDR; - -  auth_tlv_offset = stream_get_getp (circuit->rcv_stream); -  retval = parse_tlvs (circuit->area->area_tag, -		       STREAM_PNT (circuit->rcv_stream), -		       pdu_len - ISIS_P2PHELLO_HDRLEN - ISIS_FIXED_HDR_LEN, -                       &expected, &found, &tlvs, &auth_tlv_offset); - -  if (retval > ISIS_WARNING) -    { -      zlog_warn ("parse_tlvs() failed"); -      free_tlvs (&tlvs); -      return retval; -    }; +	/* +	 * Get the header +	 */ +	hdr = (struct isis_p2p_hello_hdr *)STREAM_PNT(circuit->rcv_stream); +	pdu_len = ntohs(hdr->pdu_len); -  if (!(found & TLVFLAG_AREA_ADDRS)) -    { -      zlog_warn ("No Area addresses TLV in P2P IS to IS hello"); -      free_tlvs (&tlvs); -      return ISIS_WARNING; -    } - -  if (!(found & TLVFLAG_NLPID)) -    { -      zlog_warn ("No supported protocols TLV in P2P IS to IS hello"); -      free_tlvs (&tlvs); -      return ISIS_WARNING; -    } - -  /* 8.2.5.1 c) Authentication */ -  if (circuit->passwd.type) -    { -      if (!(found & TLVFLAG_AUTH_INFO) || -          authentication_check (&tlvs.auth_info, &circuit->passwd, -                                circuit->rcv_stream, auth_tlv_offset)) -        { -          isis_event_auth_failure (circuit->area->area_tag, -                                   "P2P hello authentication failure", -                                   hdr->source_id); -          free_tlvs (&tlvs); -          return ISIS_OK; -        } -    } - -  /* -   * check if it's own interface ip match iih ip addrs -   */ -  if (found & TLVFLAG_IPV4_ADDR) -    { -      if (ip_match (circuit->ip_addrs, tlvs.ipv4_addrs)) -	v4_usable = 1; -      else -	zlog_warn ("ISIS-Adj: IPv4 addresses present but no overlap " -		   "in P2P IIH from %s\n", circuit->interface->name); -    } -  if (found & TLVFLAG_IPV6_ADDR) -    { -      /* TBA: check that we have a linklocal ourselves? */ -      struct listnode *node; -      struct in6_addr *ip; -      for (ALL_LIST_ELEMENTS_RO (tlvs.ipv6_addrs, node, ip)) -	if (IN6_IS_ADDR_LINKLOCAL (ip)) -	  { -	    v6_usable = 1; -	    break; -	  } - -      if (!v6_usable) -	zlog_warn ("ISIS-Adj: IPv6 addresses present but no link-local " -		   "in P2P IIH from %s\n", circuit->interface->name); -    } - -  if (!(found & (TLVFLAG_IPV4_ADDR | TLVFLAG_IPV6_ADDR))) -    zlog_warn ("ISIS-Adj: neither IPv4 nor IPv6 addr in P2P IIH from %s\n", -	       circuit->interface->name); +	if (pdu_len < (ISIS_FIXED_HDR_LEN + ISIS_P2PHELLO_HDRLEN) +	    || pdu_len > ISO_MTU(circuit) +	    || pdu_len > stream_get_endp(circuit->rcv_stream)) { +		zlog_warn( +			"ISIS-Adj (%s): Rcvd P2P IIH from (%s) with " +			"invalid pdu length %d", +			circuit->area->area_tag, circuit->interface->name, +			pdu_len); +		return ISIS_WARNING; +	} -  if (!v6_usable && !v4_usable) -    { -      free_tlvs (&tlvs); -      return ISIS_WARNING; -    } +	/* +	 * Set the stream endp to PDU length, ignoring additional padding +	 * introduced by transport chips. +	 */ +	if (pdu_len < stream_get_endp(circuit->rcv_stream)) +		stream_set_endp(circuit->rcv_stream, pdu_len); + +	stream_forward_getp(circuit->rcv_stream, ISIS_P2PHELLO_HDRLEN); + +	/* +	 * Lets get the TLVS now +	 */ +	expected |= TLVFLAG_AREA_ADDRS; +	expected |= TLVFLAG_AUTH_INFO; +	expected |= TLVFLAG_NLPID; +	expected |= TLVFLAG_IPV4_ADDR; +	expected |= TLVFLAG_IPV6_ADDR; + +	auth_tlv_offset = stream_get_getp(circuit->rcv_stream); +	retval = parse_tlvs(circuit->area->area_tag, +			    STREAM_PNT(circuit->rcv_stream), +			    pdu_len - ISIS_P2PHELLO_HDRLEN - ISIS_FIXED_HDR_LEN, +			    &expected, &found, &tlvs, &auth_tlv_offset); + +	if (retval > ISIS_WARNING) { +		zlog_warn("parse_tlvs() failed"); +		free_tlvs(&tlvs); +		return retval; +	}; + +	if (!(found & TLVFLAG_AREA_ADDRS)) { +		zlog_warn("No Area addresses TLV in P2P IS to IS hello"); +		free_tlvs(&tlvs); +		return ISIS_WARNING; +	} -  /* -   * it's own p2p IIH PDU - discard -   */ -  if (!memcmp (hdr->source_id, isis->sysid, ISIS_SYS_ID_LEN)) -    { -      zlog_warn ("ISIS-Adj (%s): it's own IIH PDU - discarded", -                  circuit->area->area_tag); -      free_tlvs (&tlvs); -      return ISIS_WARNING; -    } +	if (!(found & TLVFLAG_NLPID)) { +		zlog_warn("No supported protocols TLV in P2P IS to IS hello"); +		free_tlvs(&tlvs); +		return ISIS_WARNING; +	} -  /* -   * My interpertation of the ISO, if no adj exists we will create one for -   * the circuit -   */ -  adj = circuit->u.p2p.neighbor; -  /* If an adjacency exists, check it is with the source of the hello -   * packets */ -  if (adj) -    { -      if (memcmp(hdr->source_id, adj->sysid, ISIS_SYS_ID_LEN)) -	{ -          zlog_debug("hello source and adjacency do not match, set adj down\n"); -          isis_adj_state_change (adj, ISIS_ADJ_DOWN, "adj do not exist"); -          return 0; -        } -    } -  if (!adj || adj->level != hdr->circuit_t) -    { -      if (!adj) -        { -          adj = isis_new_adj (hdr->source_id, NULL, hdr->circuit_t, circuit); -          if (adj == NULL) -            return ISIS_ERROR; -        } -      else -        { -          adj->level = hdr->circuit_t; -        } -      circuit->u.p2p.neighbor = adj; -      /* Build lsp with the new neighbor entry when a new -       * adjacency is formed. Set adjacency circuit type to -       * IIH PDU header circuit type before lsp is regenerated -       * when an adjacency is up. This will result in the new -       * adjacency entry getting added to the lsp tlv neighbor list. -       */ -      adj->circuit_t = hdr->circuit_t; -      isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING, NULL); -      adj->sys_type = ISIS_SYSTYPE_UNKNOWN; -    } +	/* 8.2.5.1 c) Authentication */ +	if (circuit->passwd.type) { +		if (!(found & TLVFLAG_AUTH_INFO) +		    || authentication_check(&tlvs.auth_info, &circuit->passwd, +					    circuit->rcv_stream, +					    auth_tlv_offset)) { +			isis_event_auth_failure( +				circuit->area->area_tag, +				"P2P hello authentication failure", +				hdr->source_id); +			free_tlvs(&tlvs); +			return ISIS_OK; +		} +	} -  /* 8.2.6 Monitoring point-to-point adjacencies */ -  adj->hold_time = ntohs (hdr->hold_time); -  adj->last_upd = time (NULL); +	/* +	 * check if it's own interface ip match iih ip addrs +	 */ +	if (found & TLVFLAG_IPV4_ADDR) { +		if (ip_match(circuit->ip_addrs, tlvs.ipv4_addrs)) +			v4_usable = 1; +		else +			zlog_warn( +				"ISIS-Adj: IPv4 addresses present but no overlap " +				"in P2P IIH from %s\n", +				circuit->interface->name); +	} +	if (found & TLVFLAG_IPV6_ADDR) { +		/* TBA: check that we have a linklocal ourselves? */ +		struct listnode *node; +		struct in6_addr *ip; +		for (ALL_LIST_ELEMENTS_RO(tlvs.ipv6_addrs, node, ip)) +			if (IN6_IS_ADDR_LINKLOCAL(ip)) { +				v6_usable = 1; +				break; +			} + +		if (!v6_usable) +			zlog_warn( +				"ISIS-Adj: IPv6 addresses present but no link-local " +				"in P2P IIH from %s\n", +				circuit->interface->name); +	} -  /* we do this now because the adj may not survive till the end... */ -  tlvs_to_adj_area_addrs (&tlvs, adj); +	if (!(found & (TLVFLAG_IPV4_ADDR | TLVFLAG_IPV6_ADDR))) +		zlog_warn( +			"ISIS-Adj: neither IPv4 nor IPv6 addr in P2P IIH from %s\n", +			circuit->interface->name); -  /* which protocol are spoken ??? */ -  if (tlvs_to_adj_nlpids (&tlvs, adj)) -    { -      free_tlvs (&tlvs); -      return ISIS_WARNING; -    } +	if (!v6_usable && !v4_usable) { +		free_tlvs(&tlvs); +		return ISIS_WARNING; +	} -  /* we need to copy addresses to the adj */ -  if (found & TLVFLAG_IPV4_ADDR) -    tlvs_to_adj_ipv4_addrs (&tlvs, adj); - -  /* Update MPLS TE Remote IP address parameter if possible */ -  if (IS_MPLS_TE(isisMplsTE) && circuit->mtc && IS_CIRCUIT_TE(circuit->mtc)) -    if (adj->ipv4_addrs != NULL && listcount(adj->ipv4_addrs) != 0) -      { -        struct in_addr *ip_addr; -        ip_addr = (struct in_addr *)listgetdata ((struct listnode *)listhead (adj->ipv4_addrs)); -        set_circuitparams_rmt_ipaddr (circuit->mtc, *ip_addr); -      } - -  if (found & TLVFLAG_IPV6_ADDR) -    tlvs_to_adj_ipv6_addrs (&tlvs, adj); - -  /* lets take care of the expiry */ -  THREAD_TIMER_OFF (adj->t_expire); -  THREAD_TIMER_ON (master, adj->t_expire, isis_adj_expire, adj, -		   (long) adj->hold_time); - -  /* 8.2.5.2 a) a match was detected */ -  if (area_match (circuit->area->area_addrs, tlvs.area_addrs)) -    { -      /* 8.2.5.2 a) 2) If the system is L1 - table 5 */ -      if (circuit->area->is_type == IS_LEVEL_1) -	{ -	  switch (hdr->circuit_t) -	    { -	    case IS_LEVEL_1: -	    case IS_LEVEL_1_AND_2: -	      if (adj->adj_state != ISIS_ADJ_UP) -		{ -		  /* (4) adj state up */ -		  isis_adj_state_change (adj, ISIS_ADJ_UP, NULL); -		  /* (5) adj usage level 1 */ -		  adj->adj_usage = ISIS_ADJ_LEVEL1; -		} -	      else if (adj->adj_usage == ISIS_ADJ_LEVEL1) -		{ -		  ;		/* accept */ -		} -	      break; -	    case IS_LEVEL_2: -	      if (adj->adj_state != ISIS_ADJ_UP) -		{ -		  /* (7) reject - wrong system type event */ -		  zlog_warn ("wrongSystemType"); -                  free_tlvs (&tlvs); -		  return ISIS_WARNING;	/* Reject */ -		} -	      else if (adj->adj_usage == ISIS_ADJ_LEVEL1) -		{ -		  /* (6) down - wrong system */ -		  isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System"); -		} -	      break; -	    } +	/* +	 * it's own p2p IIH PDU - discard +	 */ +	if (!memcmp(hdr->source_id, isis->sysid, ISIS_SYS_ID_LEN)) { +		zlog_warn("ISIS-Adj (%s): it's own IIH PDU - discarded", +			  circuit->area->area_tag); +		free_tlvs(&tlvs); +		return ISIS_WARNING;  	} -      /* 8.2.5.2 a) 3) If the system is L1L2 - table 6 */ -      if (circuit->area->is_type == IS_LEVEL_1_AND_2) -	{ -	  switch (hdr->circuit_t) -	    { -	    case IS_LEVEL_1: -	      if (adj->adj_state != ISIS_ADJ_UP) -		{ -		  /* (6) adj state up */ -		  isis_adj_state_change (adj, ISIS_ADJ_UP, NULL); -		  /* (7) adj usage level 1 */ -		  adj->adj_usage = ISIS_ADJ_LEVEL1; -		} -	      else if (adj->adj_usage == ISIS_ADJ_LEVEL1) -		{ -		  ;		/* accept */ -		} -	      else if ((adj->adj_usage == ISIS_ADJ_LEVEL1AND2) || -		       (adj->adj_usage == ISIS_ADJ_LEVEL2)) -		{ -		  /* (8) down - wrong system */ -		  isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System"); -		} -	      break; -	    case IS_LEVEL_2: -	      if (adj->adj_state != ISIS_ADJ_UP) -		{ -		  /* (6) adj state up */ -		  isis_adj_state_change (adj, ISIS_ADJ_UP, NULL); -		  /* (9) adj usage level 2 */ -		  adj->adj_usage = ISIS_ADJ_LEVEL2; -		} -	      else if ((adj->adj_usage == ISIS_ADJ_LEVEL1) || -		       (adj->adj_usage == ISIS_ADJ_LEVEL1AND2)) -		{ -		  /* (8) down - wrong system */ -		  isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System"); -		} -	      else if (adj->adj_usage == ISIS_ADJ_LEVEL2) -		{ -		  ;		/* Accept */ -		} -	      break; -	    case IS_LEVEL_1_AND_2: -	      if (adj->adj_state != ISIS_ADJ_UP) -		{ -		  /* (6) adj state up */ -		  isis_adj_state_change (adj, ISIS_ADJ_UP, NULL); -		  /* (10) adj usage level 1 */ -		  adj->adj_usage = ISIS_ADJ_LEVEL1AND2; -		} -	      else if ((adj->adj_usage == ISIS_ADJ_LEVEL1) || -		       (adj->adj_usage == ISIS_ADJ_LEVEL2)) -		{ -		  /* (8) down - wrong system */ -		  isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System"); +	/* +	 * My interpertation of the ISO, if no adj exists we will create one for +	 * the circuit +	 */ +	adj = circuit->u.p2p.neighbor; +	/* If an adjacency exists, check it is with the source of the hello +	 * packets */ +	if (adj) { +		if (memcmp(hdr->source_id, adj->sysid, ISIS_SYS_ID_LEN)) { +			zlog_debug( +				"hello source and adjacency do not match, set adj down\n"); +			isis_adj_state_change(adj, ISIS_ADJ_DOWN, +					      "adj do not exist"); +			return 0;  		} -	      else if (adj->adj_usage == ISIS_ADJ_LEVEL1AND2) -		{ -		  ;		/* Accept */ +	} +	if (!adj || adj->level != hdr->circuit_t) { +		if (!adj) { +			adj = isis_new_adj(hdr->source_id, NULL, hdr->circuit_t, +					   circuit); +			if (adj == NULL) +				return ISIS_ERROR; +		} else { +			adj->level = hdr->circuit_t;  		} -	      break; -	    } +		circuit->u.p2p.neighbor = adj; +		/* Build lsp with the new neighbor entry when a new +		 * adjacency is formed. Set adjacency circuit type to +		 * IIH PDU header circuit type before lsp is regenerated +		 * when an adjacency is up. This will result in the new +		 * adjacency entry getting added to the lsp tlv neighbor list. +		 */ +		adj->circuit_t = hdr->circuit_t; +		isis_adj_state_change(adj, ISIS_ADJ_INITIALIZING, NULL); +		adj->sys_type = ISIS_SYSTYPE_UNKNOWN;  	} -      /* 8.2.5.2 a) 4) If the system is L2 - table 7 */ -      if (circuit->area->is_type == IS_LEVEL_2) -	{ -	  switch (hdr->circuit_t) -	    { -	    case IS_LEVEL_1: -	      if (adj->adj_state != ISIS_ADJ_UP) -		{ -		  /* (5) reject - wrong system type event */ -		  zlog_warn ("wrongSystemType"); -                  free_tlvs (&tlvs); -		  return ISIS_WARNING;	/* Reject */ -		} -	      else if ((adj->adj_usage == ISIS_ADJ_LEVEL1AND2) || -		       (adj->adj_usage == ISIS_ADJ_LEVEL2)) -		{ -		  /* (6) down - wrong system */ -		  isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System"); -		} -	      break; -	    case IS_LEVEL_1_AND_2: -	    case IS_LEVEL_2: -	      if (adj->adj_state != ISIS_ADJ_UP) -		{ -		  /* (7) adj state up */ -		  isis_adj_state_change (adj, ISIS_ADJ_UP, NULL); -		  /* (8) adj usage level 2 */ -		  adj->adj_usage = ISIS_ADJ_LEVEL2; -		} -	      else if (adj->adj_usage == ISIS_ADJ_LEVEL1AND2) -		{ -		  /* (6) down - wrong system */ -		  isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System"); -		} -	      else if (adj->adj_usage == ISIS_ADJ_LEVEL2) -		{ -		  ;		/* Accept */ -		} -	      break; -	    } +	/* 8.2.6 Monitoring point-to-point adjacencies */ +	adj->hold_time = ntohs(hdr->hold_time); +	adj->last_upd = time(NULL); + +	/* we do this now because the adj may not survive till the end... */ +	tlvs_to_adj_area_addrs(&tlvs, adj); + +	/* which protocol are spoken ??? */ +	if (tlvs_to_adj_nlpids(&tlvs, adj)) { +		free_tlvs(&tlvs); +		return ISIS_WARNING;  	} -    } -  /* 8.2.5.2 b) if no match was detected */ -  else if (listcount (circuit->area->area_addrs) > 0) -    { -      if (circuit->area->is_type == IS_LEVEL_1) -	{ -	  /* 8.2.5.2 b) 1) is_type L1 and adj is not up */ -	  if (adj->adj_state != ISIS_ADJ_UP) -	    { -	      isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Area Mismatch"); -	      /* 8.2.5.2 b) 2)is_type L1 and adj is up */ -	    } -	  else -	    { -	      isis_adj_state_change (adj, ISIS_ADJ_DOWN, -				     "Down - Area Mismatch"); -	    } -	} -      /* 8.2.5.2 b 3 If the system is L2 or L1L2 - table 8 */ -      else -	{ -	  switch (hdr->circuit_t) -	    { -	    case IS_LEVEL_1: -	      if (adj->adj_state != ISIS_ADJ_UP) -		{ -		  /* (6) reject - Area Mismatch event */ -		  zlog_warn ("AreaMismatch"); -                  free_tlvs (&tlvs); -		  return ISIS_WARNING;	/* Reject */ -		} -	      else if (adj->adj_usage == ISIS_ADJ_LEVEL1) -		{ -		  /* (7) down - area mismatch */ -		  isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Area Mismatch"); +	/* we need to copy addresses to the adj */ +	if (found & TLVFLAG_IPV4_ADDR) +		tlvs_to_adj_ipv4_addrs(&tlvs, adj); + +	/* Update MPLS TE Remote IP address parameter if possible */ +	if (IS_MPLS_TE(isisMplsTE) && circuit->mtc +	    && IS_CIRCUIT_TE(circuit->mtc)) +		if (adj->ipv4_addrs != NULL +		    && listcount(adj->ipv4_addrs) != 0) { +			struct in_addr *ip_addr; +			ip_addr = (struct in_addr *)listgetdata( +				(struct listnode *)listhead(adj->ipv4_addrs)); +			set_circuitparams_rmt_ipaddr(circuit->mtc, *ip_addr);  		} -	      else if ((adj->adj_usage == ISIS_ADJ_LEVEL1AND2) || -		       (adj->adj_usage == ISIS_ADJ_LEVEL2)) -		{ -		  /* (7) down - wrong system */ -		  isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System"); + +	if (found & TLVFLAG_IPV6_ADDR) +		tlvs_to_adj_ipv6_addrs(&tlvs, adj); + +	/* lets take care of the expiry */ +	THREAD_TIMER_OFF(adj->t_expire); +	THREAD_TIMER_ON(master, adj->t_expire, isis_adj_expire, adj, +			(long)adj->hold_time); + +	/* 8.2.5.2 a) a match was detected */ +	if (area_match(circuit->area->area_addrs, tlvs.area_addrs)) { +		/* 8.2.5.2 a) 2) If the system is L1 - table 5 */ +		if (circuit->area->is_type == IS_LEVEL_1) { +			switch (hdr->circuit_t) { +			case IS_LEVEL_1: +			case IS_LEVEL_1_AND_2: +				if (adj->adj_state != ISIS_ADJ_UP) { +					/* (4) adj state up */ +					isis_adj_state_change(adj, ISIS_ADJ_UP, +							      NULL); +					/* (5) adj usage level 1 */ +					adj->adj_usage = ISIS_ADJ_LEVEL1; +				} else if (adj->adj_usage == ISIS_ADJ_LEVEL1) { +					; /* accept */ +				} +				break; +			case IS_LEVEL_2: +				if (adj->adj_state != ISIS_ADJ_UP) { +					/* (7) reject - wrong system type event +					 */ +					zlog_warn("wrongSystemType"); +					free_tlvs(&tlvs); +					return ISIS_WARNING; /* Reject */ +				} else if (adj->adj_usage == ISIS_ADJ_LEVEL1) { +					/* (6) down - wrong system */ +					isis_adj_state_change(adj, +							      ISIS_ADJ_DOWN, +							      "Wrong System"); +				} +				break; +			}  		} -	      break; -	    case IS_LEVEL_1_AND_2: -	    case IS_LEVEL_2: -	      if (adj->adj_state != ISIS_ADJ_UP) -		{ -		  /* (8) adj state up */ -		  isis_adj_state_change (adj, ISIS_ADJ_UP, NULL); -		  /* (9) adj usage level 2 */ -		  adj->adj_usage = ISIS_ADJ_LEVEL2; + +		/* 8.2.5.2 a) 3) If the system is L1L2 - table 6 */ +		if (circuit->area->is_type == IS_LEVEL_1_AND_2) { +			switch (hdr->circuit_t) { +			case IS_LEVEL_1: +				if (adj->adj_state != ISIS_ADJ_UP) { +					/* (6) adj state up */ +					isis_adj_state_change(adj, ISIS_ADJ_UP, +							      NULL); +					/* (7) adj usage level 1 */ +					adj->adj_usage = ISIS_ADJ_LEVEL1; +				} else if (adj->adj_usage == ISIS_ADJ_LEVEL1) { +					; /* accept */ +				} else if ((adj->adj_usage +					    == ISIS_ADJ_LEVEL1AND2) +					   || (adj->adj_usage +					       == ISIS_ADJ_LEVEL2)) { +					/* (8) down - wrong system */ +					isis_adj_state_change(adj, +							      ISIS_ADJ_DOWN, +							      "Wrong System"); +				} +				break; +			case IS_LEVEL_2: +				if (adj->adj_state != ISIS_ADJ_UP) { +					/* (6) adj state up */ +					isis_adj_state_change(adj, ISIS_ADJ_UP, +							      NULL); +					/* (9) adj usage level 2 */ +					adj->adj_usage = ISIS_ADJ_LEVEL2; +				} else if ((adj->adj_usage == ISIS_ADJ_LEVEL1) +					   || (adj->adj_usage +					       == ISIS_ADJ_LEVEL1AND2)) { +					/* (8) down - wrong system */ +					isis_adj_state_change(adj, +							      ISIS_ADJ_DOWN, +							      "Wrong System"); +				} else if (adj->adj_usage == ISIS_ADJ_LEVEL2) { +					; /* Accept */ +				} +				break; +			case IS_LEVEL_1_AND_2: +				if (adj->adj_state != ISIS_ADJ_UP) { +					/* (6) adj state up */ +					isis_adj_state_change(adj, ISIS_ADJ_UP, +							      NULL); +					/* (10) adj usage level 1 */ +					adj->adj_usage = ISIS_ADJ_LEVEL1AND2; +				} else if ((adj->adj_usage == ISIS_ADJ_LEVEL1) +					   || (adj->adj_usage +					       == ISIS_ADJ_LEVEL2)) { +					/* (8) down - wrong system */ +					isis_adj_state_change(adj, +							      ISIS_ADJ_DOWN, +							      "Wrong System"); +				} else if (adj->adj_usage +					   == ISIS_ADJ_LEVEL1AND2) { +					; /* Accept */ +				} +				break; +			}  		} -	      else if (adj->adj_usage == ISIS_ADJ_LEVEL1) -		{ -		  /* (7) down - wrong system */ -		  isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System"); + +		/* 8.2.5.2 a) 4) If the system is L2 - table 7 */ +		if (circuit->area->is_type == IS_LEVEL_2) { +			switch (hdr->circuit_t) { +			case IS_LEVEL_1: +				if (adj->adj_state != ISIS_ADJ_UP) { +					/* (5) reject - wrong system type event +					 */ +					zlog_warn("wrongSystemType"); +					free_tlvs(&tlvs); +					return ISIS_WARNING; /* Reject */ +				} else if ((adj->adj_usage +					    == ISIS_ADJ_LEVEL1AND2) +					   || (adj->adj_usage +					       == ISIS_ADJ_LEVEL2)) { +					/* (6) down - wrong system */ +					isis_adj_state_change(adj, +							      ISIS_ADJ_DOWN, +							      "Wrong System"); +				} +				break; +			case IS_LEVEL_1_AND_2: +			case IS_LEVEL_2: +				if (adj->adj_state != ISIS_ADJ_UP) { +					/* (7) adj state up */ +					isis_adj_state_change(adj, ISIS_ADJ_UP, +							      NULL); +					/* (8) adj usage level 2 */ +					adj->adj_usage = ISIS_ADJ_LEVEL2; +				} else if (adj->adj_usage +					   == ISIS_ADJ_LEVEL1AND2) { +					/* (6) down - wrong system */ +					isis_adj_state_change(adj, +							      ISIS_ADJ_DOWN, +							      "Wrong System"); +				} else if (adj->adj_usage == ISIS_ADJ_LEVEL2) { +					; /* Accept */ +				} +				break; +			}  		} -	      else if (adj->adj_usage == ISIS_ADJ_LEVEL1AND2) -		{ -		  if (hdr->circuit_t == IS_LEVEL_2) -		    { -		      /* (7) down - wrong system */ -		      isis_adj_state_change (adj, ISIS_ADJ_DOWN, -					     "Wrong System"); -		    } -		  else -		    { -		      /* (7) down - area mismatch */ -		      isis_adj_state_change (adj, ISIS_ADJ_DOWN, -					     "Area Mismatch"); -		    } +	} +	/* 8.2.5.2 b) if no match was detected */ +	else if (listcount(circuit->area->area_addrs) > 0) { +		if (circuit->area->is_type == IS_LEVEL_1) { +			/* 8.2.5.2 b) 1) is_type L1 and adj is not up */ +			if (adj->adj_state != ISIS_ADJ_UP) { +				isis_adj_state_change(adj, ISIS_ADJ_DOWN, +						      "Area Mismatch"); +				/* 8.2.5.2 b) 2)is_type L1 and adj is up */ +			} else { +				isis_adj_state_change(adj, ISIS_ADJ_DOWN, +						      "Down - Area Mismatch"); +			}  		} -	      else if (adj->adj_usage == ISIS_ADJ_LEVEL2) -		{ -		  ;		/* Accept */ +		/* 8.2.5.2 b 3 If the system is L2 or L1L2 - table 8 */ +		else { +			switch (hdr->circuit_t) { +			case IS_LEVEL_1: +				if (adj->adj_state != ISIS_ADJ_UP) { +					/* (6) reject - Area Mismatch event */ +					zlog_warn("AreaMismatch"); +					free_tlvs(&tlvs); +					return ISIS_WARNING; /* Reject */ +				} else if (adj->adj_usage == ISIS_ADJ_LEVEL1) { +					/* (7) down - area mismatch */ +					isis_adj_state_change(adj, +							      ISIS_ADJ_DOWN, +							      "Area Mismatch"); + +				} else if ((adj->adj_usage +					    == ISIS_ADJ_LEVEL1AND2) +					   || (adj->adj_usage +					       == ISIS_ADJ_LEVEL2)) { +					/* (7) down - wrong system */ +					isis_adj_state_change(adj, +							      ISIS_ADJ_DOWN, +							      "Wrong System"); +				} +				break; +			case IS_LEVEL_1_AND_2: +			case IS_LEVEL_2: +				if (adj->adj_state != ISIS_ADJ_UP) { +					/* (8) adj state up */ +					isis_adj_state_change(adj, ISIS_ADJ_UP, +							      NULL); +					/* (9) adj usage level 2 */ +					adj->adj_usage = ISIS_ADJ_LEVEL2; +				} else if (adj->adj_usage == ISIS_ADJ_LEVEL1) { +					/* (7) down - wrong system */ +					isis_adj_state_change(adj, +							      ISIS_ADJ_DOWN, +							      "Wrong System"); +				} else if (adj->adj_usage +					   == ISIS_ADJ_LEVEL1AND2) { +					if (hdr->circuit_t == IS_LEVEL_2) { +						/* (7) down - wrong system */ +						isis_adj_state_change( +							adj, ISIS_ADJ_DOWN, +							"Wrong System"); +					} else { +						/* (7) down - area mismatch */ +						isis_adj_state_change( +							adj, ISIS_ADJ_DOWN, +							"Area Mismatch"); +					} +				} else if (adj->adj_usage == ISIS_ADJ_LEVEL2) { +					; /* Accept */ +				} +				break; +			}  		} -	      break; -	    } +	} else { +		/* down - area mismatch */ +		isis_adj_state_change(adj, ISIS_ADJ_DOWN, "Area Mismatch"); +	} +	/* 8.2.5.2 c) if the action was up - comparing circuit IDs */ +	/* FIXME - Missing parts */ + +	/* some of my own understanding of the ISO, why the heck does +	 * it not say what should I change the system_type to... +	 */ +	switch (adj->adj_usage) { +	case ISIS_ADJ_LEVEL1: +		adj->sys_type = ISIS_SYSTYPE_L1_IS; +		break; +	case ISIS_ADJ_LEVEL2: +		adj->sys_type = ISIS_SYSTYPE_L2_IS; +		break; +	case ISIS_ADJ_LEVEL1AND2: +		adj->sys_type = ISIS_SYSTYPE_L2_IS; +		break; +	case ISIS_ADJ_NONE: +		adj->sys_type = ISIS_SYSTYPE_UNKNOWN; +		break;  	} -    } -  else -    { -      /* down - area mismatch */ -      isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Area Mismatch"); -    } -  /* 8.2.5.2 c) if the action was up - comparing circuit IDs */ -  /* FIXME - Missing parts */ - -  /* some of my own understanding of the ISO, why the heck does -   * it not say what should I change the system_type to... -   */ -  switch (adj->adj_usage) -    { -    case ISIS_ADJ_LEVEL1: -      adj->sys_type = ISIS_SYSTYPE_L1_IS; -      break; -    case ISIS_ADJ_LEVEL2: -      adj->sys_type = ISIS_SYSTYPE_L2_IS; -      break; -    case ISIS_ADJ_LEVEL1AND2: -      adj->sys_type = ISIS_SYSTYPE_L2_IS; -      break; -    case ISIS_ADJ_NONE: -      adj->sys_type = ISIS_SYSTYPE_UNKNOWN; -      break; -    } -  if (isis->debugs & DEBUG_ADJ_PACKETS) -    { -      zlog_debug ("ISIS-Adj (%s): Rcvd P2P IIH from (%s), cir type %s," -		  " cir id %02d, length %d", -		  circuit->area->area_tag, circuit->interface->name, -		  circuit_t2string (circuit->is_type), -		  circuit->circuit_id, pdu_len); -    } +	if (isis->debugs & DEBUG_ADJ_PACKETS) { +		zlog_debug( +			"ISIS-Adj (%s): Rcvd P2P IIH from (%s), cir type %s," +			" cir id %02d, length %d", +			circuit->area->area_tag, circuit->interface->name, +			circuit_t2string(circuit->is_type), circuit->circuit_id, +			pdu_len); +	} -  free_tlvs (&tlvs); +	free_tlvs(&tlvs); -  return retval; +	return retval;  }  /*   * Process IS-IS LAN Level 1/2 Hello PDU   */ -static int -process_lan_hello (int level, struct isis_circuit *circuit, const u_char *ssnpa) +static int process_lan_hello(int level, struct isis_circuit *circuit, +			     const u_char *ssnpa)  { -  int retval = ISIS_OK; -  struct isis_lan_hello_hdr hdr; -  struct isis_adjacency *adj; -  u_int32_t expected = 0, found = 0, auth_tlv_offset = 0; -  struct tlvs tlvs; -  u_char *snpa; -  struct listnode *node; -  int v4_usable = 0, v6_usable = 0; - -  if (isis->debugs & DEBUG_ADJ_PACKETS) -    { -      zlog_debug ("ISIS-Adj (%s): Rcvd L%d LAN IIH on %s, cirType %s, " -                  "cirID %u", -                  circuit->area->area_tag, level, circuit->interface->name, -                  circuit_t2string (circuit->is_type), circuit->circuit_id); -      if (isis->debugs & DEBUG_PACKET_DUMP) -        zlog_dump_data (STREAM_DATA (circuit->rcv_stream), -                        stream_get_endp (circuit->rcv_stream)); -    } +	int retval = ISIS_OK; +	struct isis_lan_hello_hdr hdr; +	struct isis_adjacency *adj; +	u_int32_t expected = 0, found = 0, auth_tlv_offset = 0; +	struct tlvs tlvs; +	u_char *snpa; +	struct listnode *node; +	int v4_usable = 0, v6_usable = 0; + +	if (isis->debugs & DEBUG_ADJ_PACKETS) { +		zlog_debug( +			"ISIS-Adj (%s): Rcvd L%d LAN IIH on %s, cirType %s, " +			"cirID %u", +			circuit->area->area_tag, level, +			circuit->interface->name, +			circuit_t2string(circuit->is_type), +			circuit->circuit_id); +		if (isis->debugs & DEBUG_PACKET_DUMP) +			zlog_dump_data(STREAM_DATA(circuit->rcv_stream), +				       stream_get_endp(circuit->rcv_stream)); +	} -  if (circuit->circ_type != CIRCUIT_T_BROADCAST) -    { -      zlog_warn ("lan hello on non broadcast circuit"); -      return ISIS_WARNING; -    } +	if (circuit->circ_type != CIRCUIT_T_BROADCAST) { +		zlog_warn("lan hello on non broadcast circuit"); +		return ISIS_WARNING; +	} -  if ((stream_get_endp (circuit->rcv_stream) - -       stream_get_getp (circuit->rcv_stream)) < ISIS_LANHELLO_HDRLEN) -    { -      zlog_warn ("Packet too short"); -      return ISIS_WARNING; -    } +	if ((stream_get_endp(circuit->rcv_stream) +	     - stream_get_getp(circuit->rcv_stream)) +	    < ISIS_LANHELLO_HDRLEN) { +		zlog_warn("Packet too short"); +		return ISIS_WARNING; +	} -  if (circuit->ext_domain) -    { -      zlog_debug ("level %d LAN Hello received over circuit with " -		  "externalDomain = true", level); -      return ISIS_WARNING; -    } +	if (circuit->ext_domain) { +		zlog_debug( +			"level %d LAN Hello received over circuit with " +			"externalDomain = true", +			level); +		return ISIS_WARNING; +	} -  if (!accept_level (level, circuit->is_type)) -    { -      if (isis->debugs & DEBUG_ADJ_PACKETS) -	{ -	  zlog_debug ("ISIS-Adj (%s): Interface level mismatch, %s", -		      circuit->area->area_tag, circuit->interface->name); +	if (!accept_level(level, circuit->is_type)) { +		if (isis->debugs & DEBUG_ADJ_PACKETS) { +			zlog_debug( +				"ISIS-Adj (%s): Interface level mismatch, %s", +				circuit->area->area_tag, +				circuit->interface->name); +		} +		return ISIS_WARNING;  	} -      return ISIS_WARNING; -    }  #if 0    /* Cisco's debug message compatability */ @@ -974,313 +928,301 @@ process_lan_hello (int level, struct isis_circuit *circuit, const u_char *ssnpa)        return ISIS_WARNING;      }  #endif -  /* -   * Fill the header -   */ -  hdr.circuit_t = stream_getc (circuit->rcv_stream); -  stream_get (hdr.source_id, circuit->rcv_stream, ISIS_SYS_ID_LEN); -  hdr.hold_time = stream_getw (circuit->rcv_stream); -  hdr.pdu_len = stream_getw (circuit->rcv_stream); -  hdr.prio = stream_getc (circuit->rcv_stream); -  stream_get (hdr.lan_id, circuit->rcv_stream, ISIS_SYS_ID_LEN + 1); - -  if (hdr.pdu_len < (ISIS_FIXED_HDR_LEN + ISIS_LANHELLO_HDRLEN) || -      hdr.pdu_len > ISO_MTU(circuit) || -      hdr.pdu_len > stream_get_endp (circuit->rcv_stream)) -    { -      zlog_warn ("ISIS-Adj (%s): Rcvd LAN IIH from (%s) with " -                 "invalid pdu length %d", -                 circuit->area->area_tag, circuit->interface->name, -                 hdr.pdu_len); -      return ISIS_WARNING; -    } +	/* +	 * Fill the header +	 */ +	hdr.circuit_t = stream_getc(circuit->rcv_stream); +	stream_get(hdr.source_id, circuit->rcv_stream, ISIS_SYS_ID_LEN); +	hdr.hold_time = stream_getw(circuit->rcv_stream); +	hdr.pdu_len = stream_getw(circuit->rcv_stream); +	hdr.prio = stream_getc(circuit->rcv_stream); +	stream_get(hdr.lan_id, circuit->rcv_stream, ISIS_SYS_ID_LEN + 1); + +	if (hdr.pdu_len < (ISIS_FIXED_HDR_LEN + ISIS_LANHELLO_HDRLEN) +	    || hdr.pdu_len > ISO_MTU(circuit) +	    || hdr.pdu_len > stream_get_endp(circuit->rcv_stream)) { +		zlog_warn( +			"ISIS-Adj (%s): Rcvd LAN IIH from (%s) with " +			"invalid pdu length %d", +			circuit->area->area_tag, circuit->interface->name, +			hdr.pdu_len); +		return ISIS_WARNING; +	} -  /* -   * Set the stream endp to PDU length, ignoring additional padding -   * introduced by transport chips. -   */ -  if (hdr.pdu_len < stream_get_endp (circuit->rcv_stream)) -    stream_set_endp (circuit->rcv_stream, hdr.pdu_len); - -  if (hdr.circuit_t != IS_LEVEL_1 && -      hdr.circuit_t != IS_LEVEL_2 && -      hdr.circuit_t != IS_LEVEL_1_AND_2 && -      (level & hdr.circuit_t) == 0) -    { -      zlog_err ("Level %d LAN Hello with Circuit Type %d", level, -                hdr.circuit_t); -      return ISIS_ERROR; -    } +	/* +	 * Set the stream endp to PDU length, ignoring additional padding +	 * introduced by transport chips. +	 */ +	if (hdr.pdu_len < stream_get_endp(circuit->rcv_stream)) +		stream_set_endp(circuit->rcv_stream, hdr.pdu_len); + +	if (hdr.circuit_t != IS_LEVEL_1 && hdr.circuit_t != IS_LEVEL_2 +	    && hdr.circuit_t != IS_LEVEL_1_AND_2 +	    && (level & hdr.circuit_t) == 0) { +		zlog_err("Level %d LAN Hello with Circuit Type %d", level, +			 hdr.circuit_t); +		return ISIS_ERROR; +	} -  /* -   * Then get the tlvs -   */ -  expected |= TLVFLAG_AUTH_INFO; -  expected |= TLVFLAG_AREA_ADDRS; -  expected |= TLVFLAG_LAN_NEIGHS; -  expected |= TLVFLAG_NLPID; -  expected |= TLVFLAG_IPV4_ADDR; -  expected |= TLVFLAG_IPV6_ADDR; - -  auth_tlv_offset = stream_get_getp (circuit->rcv_stream); -  retval = parse_tlvs (circuit->area->area_tag, -                       STREAM_PNT (circuit->rcv_stream), -                       hdr.pdu_len - ISIS_LANHELLO_HDRLEN - ISIS_FIXED_HDR_LEN, -                       &expected, &found, &tlvs, -                       &auth_tlv_offset); - -  if (retval > ISIS_WARNING) -    { -      zlog_warn ("parse_tlvs() failed"); -      goto out; -    } +	/* +	 * Then get the tlvs +	 */ +	expected |= TLVFLAG_AUTH_INFO; +	expected |= TLVFLAG_AREA_ADDRS; +	expected |= TLVFLAG_LAN_NEIGHS; +	expected |= TLVFLAG_NLPID; +	expected |= TLVFLAG_IPV4_ADDR; +	expected |= TLVFLAG_IPV6_ADDR; + +	auth_tlv_offset = stream_get_getp(circuit->rcv_stream); +	retval = parse_tlvs( +		circuit->area->area_tag, STREAM_PNT(circuit->rcv_stream), +		hdr.pdu_len - ISIS_LANHELLO_HDRLEN - ISIS_FIXED_HDR_LEN, +		&expected, &found, &tlvs, &auth_tlv_offset); + +	if (retval > ISIS_WARNING) { +		zlog_warn("parse_tlvs() failed"); +		goto out; +	} -  if (!(found & TLVFLAG_AREA_ADDRS)) -    { -      zlog_warn ("No Area addresses TLV in Level %d LAN IS to IS hello", -		 level); -      retval = ISIS_WARNING; -      goto out; -    } +	if (!(found & TLVFLAG_AREA_ADDRS)) { +		zlog_warn( +			"No Area addresses TLV in Level %d LAN IS to IS hello", +			level); +		retval = ISIS_WARNING; +		goto out; +	} -  if (!(found & TLVFLAG_NLPID)) -    { -      zlog_warn ("No supported protocols TLV in Level %d LAN IS to IS hello", -		 level); -      retval = ISIS_WARNING; -      goto out; -    } +	if (!(found & TLVFLAG_NLPID)) { +		zlog_warn( +			"No supported protocols TLV in Level %d LAN IS to IS hello", +			level); +		retval = ISIS_WARNING; +		goto out; +	} -  /* Verify authentication, either cleartext of HMAC MD5 */ -  if (circuit->passwd.type) -    { -      if (!(found & TLVFLAG_AUTH_INFO) || -          authentication_check (&tlvs.auth_info, &circuit->passwd, -                                circuit->rcv_stream, auth_tlv_offset)) -        { -          isis_event_auth_failure (circuit->area->area_tag, -                                   "LAN hello authentication failure", -                                   hdr.source_id); -          retval = ISIS_WARNING; -          goto out; -        } -    } +	/* Verify authentication, either cleartext of HMAC MD5 */ +	if (circuit->passwd.type) { +		if (!(found & TLVFLAG_AUTH_INFO) +		    || authentication_check(&tlvs.auth_info, &circuit->passwd, +					    circuit->rcv_stream, +					    auth_tlv_offset)) { +			isis_event_auth_failure( +				circuit->area->area_tag, +				"LAN hello authentication failure", +				hdr.source_id); +			retval = ISIS_WARNING; +			goto out; +		} +	} -  if (!memcmp (hdr.source_id, isis->sysid, ISIS_SYS_ID_LEN)) -    { -      zlog_warn ("ISIS-Adj (%s): duplicate system ID on interface %s", -		 circuit->area->area_tag, circuit->interface->name); -      return ISIS_WARNING; -    } +	if (!memcmp(hdr.source_id, isis->sysid, ISIS_SYS_ID_LEN)) { +		zlog_warn("ISIS-Adj (%s): duplicate system ID on interface %s", +			  circuit->area->area_tag, circuit->interface->name); +		return ISIS_WARNING; +	} -  /* -   * Accept the level 1 adjacency only if a match between local and -   * remote area addresses is found -   */ -  if (listcount (circuit->area->area_addrs) == 0 || -      (level == IS_LEVEL_1 && -       area_match (circuit->area->area_addrs, tlvs.area_addrs) == 0)) -    { -      if (isis->debugs & DEBUG_ADJ_PACKETS) -	{ -	  zlog_debug ("ISIS-Adj (%s): Area mismatch, level %d IIH on %s", -		      circuit->area->area_tag, level, -		      circuit->interface->name); +	/* +	 * Accept the level 1 adjacency only if a match between local and +	 * remote area addresses is found +	 */ +	if (listcount(circuit->area->area_addrs) == 0 +	    || (level == IS_LEVEL_1 +		&& area_match(circuit->area->area_addrs, tlvs.area_addrs) +			   == 0)) { +		if (isis->debugs & DEBUG_ADJ_PACKETS) { +			zlog_debug( +				"ISIS-Adj (%s): Area mismatch, level %d IIH on %s", +				circuit->area->area_tag, level, +				circuit->interface->name); +		} +		retval = ISIS_OK; +		goto out;  	} -      retval = ISIS_OK; -      goto out; -    } -  /*  -   * it's own IIH PDU - discard silently  -   */ -  if (!memcmp (circuit->u.bc.snpa, ssnpa, ETH_ALEN)) -    { -      zlog_debug ("ISIS-Adj (%s): it's own IIH PDU - discarded", -		  circuit->area->area_tag); +	/* +	 * it's own IIH PDU - discard silently +	 */ +	if (!memcmp(circuit->u.bc.snpa, ssnpa, ETH_ALEN)) { +		zlog_debug("ISIS-Adj (%s): it's own IIH PDU - discarded", +			   circuit->area->area_tag); -      retval = ISIS_OK; -      goto out; -    } +		retval = ISIS_OK; +		goto out; +	} -  /* -   * check if it's own interface ip match iih ip addrs -   */ -  if (found & TLVFLAG_IPV4_ADDR) -    { -      if (ip_match (circuit->ip_addrs, tlvs.ipv4_addrs)) -	v4_usable = 1; -      else -	zlog_warn ("ISIS-Adj: IPv4 addresses present but no overlap " -		   "in LAN IIH from %s\n", circuit->interface->name); -    } -  if (found & TLVFLAG_IPV6_ADDR) -    { -      /* TBA: check that we have a linklocal ourselves? */ -      struct listnode *node; -      struct in6_addr *ip; -      for (ALL_LIST_ELEMENTS_RO (tlvs.ipv6_addrs, node, ip)) -	if (IN6_IS_ADDR_LINKLOCAL (ip)) -	  { -	    v6_usable = 1; -	    break; -	  } - -      if (!v6_usable) -	zlog_warn ("ISIS-Adj: IPv6 addresses present but no link-local " -		   "in LAN IIH from %s\n", circuit->interface->name); -    } +	/* +	 * check if it's own interface ip match iih ip addrs +	 */ +	if (found & TLVFLAG_IPV4_ADDR) { +		if (ip_match(circuit->ip_addrs, tlvs.ipv4_addrs)) +			v4_usable = 1; +		else +			zlog_warn( +				"ISIS-Adj: IPv4 addresses present but no overlap " +				"in LAN IIH from %s\n", +				circuit->interface->name); +	} +	if (found & TLVFLAG_IPV6_ADDR) { +		/* TBA: check that we have a linklocal ourselves? */ +		struct listnode *node; +		struct in6_addr *ip; +		for (ALL_LIST_ELEMENTS_RO(tlvs.ipv6_addrs, node, ip)) +			if (IN6_IS_ADDR_LINKLOCAL(ip)) { +				v6_usable = 1; +				break; +			} + +		if (!v6_usable) +			zlog_warn( +				"ISIS-Adj: IPv6 addresses present but no link-local " +				"in LAN IIH from %s\n", +				circuit->interface->name); +	} -  if (!(found & (TLVFLAG_IPV4_ADDR | TLVFLAG_IPV6_ADDR))) -    zlog_warn ("ISIS-Adj: neither IPv4 nor IPv6 addr in LAN IIH from %s\n", -	       circuit->interface->name); +	if (!(found & (TLVFLAG_IPV4_ADDR | TLVFLAG_IPV6_ADDR))) +		zlog_warn( +			"ISIS-Adj: neither IPv4 nor IPv6 addr in LAN IIH from %s\n", +			circuit->interface->name); -  if (!v6_usable && !v4_usable) -    { -      free_tlvs (&tlvs); -      return ISIS_WARNING; -    } +	if (!v6_usable && !v4_usable) { +		free_tlvs(&tlvs); +		return ISIS_WARNING; +	} -  adj = isis_adj_lookup (hdr.source_id, circuit->u.bc.adjdb[level - 1]); -  if ((adj == NULL) || (memcmp(adj->snpa, ssnpa, ETH_ALEN)) || -      (adj->level != level)) -    { -      if (!adj) -        { -          /* -           * Do as in 8.4.2.5 -           */ -          adj = isis_new_adj (hdr.source_id, ssnpa, level, circuit); -          if (adj == NULL) -            { -              retval = ISIS_ERROR; -              goto out; -            } -        } -      else -        { -          if (ssnpa) { -            memcpy (adj->snpa, ssnpa, 6); -          } else { -            memset (adj->snpa, ' ', 6); -          } -          adj->level = level; -        } -      isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING, NULL); - -      if (level == IS_LEVEL_1) -          adj->sys_type = ISIS_SYSTYPE_L1_IS; -      else -          adj->sys_type = ISIS_SYSTYPE_L2_IS; -      list_delete_all_node (circuit->u.bc.lan_neighs[level - 1]); -      isis_adj_build_neigh_list (circuit->u.bc.adjdb[level - 1], -                                 circuit->u.bc.lan_neighs[level - 1]); -    } +	adj = isis_adj_lookup(hdr.source_id, circuit->u.bc.adjdb[level - 1]); +	if ((adj == NULL) || (memcmp(adj->snpa, ssnpa, ETH_ALEN)) +	    || (adj->level != level)) { +		if (!adj) { +			/* +			 * Do as in 8.4.2.5 +			 */ +			adj = isis_new_adj(hdr.source_id, ssnpa, level, +					   circuit); +			if (adj == NULL) { +				retval = ISIS_ERROR; +				goto out; +			} +		} else { +			if (ssnpa) { +				memcpy(adj->snpa, ssnpa, 6); +			} else { +				memset(adj->snpa, ' ', 6); +			} +			adj->level = level; +		} +		isis_adj_state_change(adj, ISIS_ADJ_INITIALIZING, NULL); -  if(adj->dis_record[level-1].dis==ISIS_IS_DIS) -    switch (level) -      { -      case 1: -	if (memcmp (circuit->u.bc.l1_desig_is, hdr.lan_id, ISIS_SYS_ID_LEN + 1)) -	  { -            thread_add_event (master, isis_event_dis_status_change, circuit, 0); -	    memcpy (&circuit->u.bc.l1_desig_is, hdr.lan_id, -		    ISIS_SYS_ID_LEN + 1); -	  } -	break; -      case 2: -	if (memcmp (circuit->u.bc.l2_desig_is, hdr.lan_id, ISIS_SYS_ID_LEN + 1)) -	  { -            thread_add_event (master, isis_event_dis_status_change, circuit, 0); -	    memcpy (&circuit->u.bc.l2_desig_is, hdr.lan_id, -		    ISIS_SYS_ID_LEN + 1); -	  } -	break; -      } - -  adj->hold_time = hdr.hold_time; -  adj->last_upd = time (NULL); -  adj->prio[level - 1] = hdr.prio; - -  memcpy (adj->lanid, hdr.lan_id, ISIS_SYS_ID_LEN + 1); - -  tlvs_to_adj_area_addrs (&tlvs, adj); - -  /* which protocol are spoken ??? */ -  if (tlvs_to_adj_nlpids (&tlvs, adj)) -    { -      retval = ISIS_WARNING; -      goto out; -    } +		if (level == IS_LEVEL_1) +			adj->sys_type = ISIS_SYSTYPE_L1_IS; +		else +			adj->sys_type = ISIS_SYSTYPE_L2_IS; +		list_delete_all_node(circuit->u.bc.lan_neighs[level - 1]); +		isis_adj_build_neigh_list(circuit->u.bc.adjdb[level - 1], +					  circuit->u.bc.lan_neighs[level - 1]); +	} -  /* we need to copy addresses to the adj */ -  if (found & TLVFLAG_IPV4_ADDR) -    tlvs_to_adj_ipv4_addrs (&tlvs, adj); +	if (adj->dis_record[level - 1].dis == ISIS_IS_DIS) +		switch (level) { +		case 1: +			if (memcmp(circuit->u.bc.l1_desig_is, hdr.lan_id, +				   ISIS_SYS_ID_LEN + 1)) { +				thread_add_event(master, +						 isis_event_dis_status_change, +						 circuit, 0); +				memcpy(&circuit->u.bc.l1_desig_is, hdr.lan_id, +				       ISIS_SYS_ID_LEN + 1); +			} +			break; +		case 2: +			if (memcmp(circuit->u.bc.l2_desig_is, hdr.lan_id, +				   ISIS_SYS_ID_LEN + 1)) { +				thread_add_event(master, +						 isis_event_dis_status_change, +						 circuit, 0); +				memcpy(&circuit->u.bc.l2_desig_is, hdr.lan_id, +				       ISIS_SYS_ID_LEN + 1); +			} +			break; +		} -  if (found & TLVFLAG_IPV6_ADDR) -    tlvs_to_adj_ipv6_addrs (&tlvs, adj); +	adj->hold_time = hdr.hold_time; +	adj->last_upd = time(NULL); +	adj->prio[level - 1] = hdr.prio; -  adj->circuit_t = hdr.circuit_t; +	memcpy(adj->lanid, hdr.lan_id, ISIS_SYS_ID_LEN + 1); -  /* lets take care of the expiry */ -  THREAD_TIMER_OFF (adj->t_expire); -  THREAD_TIMER_ON (master, adj->t_expire, isis_adj_expire, adj, -                   (long) adj->hold_time); +	tlvs_to_adj_area_addrs(&tlvs, adj); -  /* -   * If the snpa for this circuit is found from LAN Neighbours TLV -   * we have two-way communication -> adjacency can be put to state "up" -   */ +	/* which protocol are spoken ??? */ +	if (tlvs_to_adj_nlpids(&tlvs, adj)) { +		retval = ISIS_WARNING; +		goto out; +	} -  if (found & TLVFLAG_LAN_NEIGHS) -  { -    if (adj->adj_state != ISIS_ADJ_UP) -    { -      for (ALL_LIST_ELEMENTS_RO (tlvs.lan_neighs, node, snpa)) -      { -        if (!memcmp (snpa, circuit->u.bc.snpa, ETH_ALEN)) -        { -          isis_adj_state_change (adj, ISIS_ADJ_UP, -                                 "own SNPA found in LAN Neighbours TLV"); -        } -      } -    } -    else -    { -      int found = 0; -      for (ALL_LIST_ELEMENTS_RO (tlvs.lan_neighs, node, snpa)) -        if (!memcmp (snpa, circuit->u.bc.snpa, ETH_ALEN)) -        { -          found = 1; -          break; -        } -      if (found == 0) -        isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING, -                               "own SNPA not found in LAN Neighbours TLV"); -    } -  } -  else if (adj->adj_state == ISIS_ADJ_UP) -  { -    isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING, -                           "no LAN Neighbours TLV found"); -  } +	/* we need to copy addresses to the adj */ +	if (found & TLVFLAG_IPV4_ADDR) +		tlvs_to_adj_ipv4_addrs(&tlvs, adj); + +	if (found & TLVFLAG_IPV6_ADDR) +		tlvs_to_adj_ipv6_addrs(&tlvs, adj); + +	adj->circuit_t = hdr.circuit_t; + +	/* lets take care of the expiry */ +	THREAD_TIMER_OFF(adj->t_expire); +	THREAD_TIMER_ON(master, adj->t_expire, isis_adj_expire, adj, +			(long)adj->hold_time); + +	/* +	 * If the snpa for this circuit is found from LAN Neighbours TLV +	 * we have two-way communication -> adjacency can be put to state "up" +	 */ + +	if (found & TLVFLAG_LAN_NEIGHS) { +		if (adj->adj_state != ISIS_ADJ_UP) { +			for (ALL_LIST_ELEMENTS_RO(tlvs.lan_neighs, node, +						  snpa)) { +				if (!memcmp(snpa, circuit->u.bc.snpa, +					    ETH_ALEN)) { +					isis_adj_state_change( +						adj, ISIS_ADJ_UP, +						"own SNPA found in LAN Neighbours TLV"); +				} +			} +		} else { +			int found = 0; +			for (ALL_LIST_ELEMENTS_RO(tlvs.lan_neighs, node, snpa)) +				if (!memcmp(snpa, circuit->u.bc.snpa, +					    ETH_ALEN)) { +					found = 1; +					break; +				} +			if (found == 0) +				isis_adj_state_change( +					adj, ISIS_ADJ_INITIALIZING, +					"own SNPA not found in LAN Neighbours TLV"); +		} +	} else if (adj->adj_state == ISIS_ADJ_UP) { +		isis_adj_state_change(adj, ISIS_ADJ_INITIALIZING, +				      "no LAN Neighbours TLV found"); +	}  out: -  if (isis->debugs & DEBUG_ADJ_PACKETS) -    { -      zlog_debug ("ISIS-Adj (%s): Rcvd L%d LAN IIH from %s on %s, cirType %s, " -		  "cirID %u, length %zd", -		  circuit->area->area_tag, -		  level, snpa_print (ssnpa), circuit->interface->name, -		  circuit_t2string (circuit->is_type), -		  circuit->circuit_id, -		  stream_get_endp (circuit->rcv_stream)); -    } +	if (isis->debugs & DEBUG_ADJ_PACKETS) { +		zlog_debug( +			"ISIS-Adj (%s): Rcvd L%d LAN IIH from %s on %s, cirType %s, " +			"cirID %u, length %zd", +			circuit->area->area_tag, level, snpa_print(ssnpa), +			circuit->interface->name, +			circuit_t2string(circuit->is_type), circuit->circuit_id, +			stream_get_endp(circuit->rcv_stream)); +	} -  free_tlvs (&tlvs); +	free_tlvs(&tlvs); -  return retval; +	return retval;  }  /* @@ -1288,363 +1230,361 @@ out:   * ISO - 10589   * Section 7.3.15.1 - Action on receipt of a link state PDU   */ -static int -process_lsp (int level, struct isis_circuit *circuit, const u_char *ssnpa) +static int process_lsp(int level, struct isis_circuit *circuit, +		       const u_char *ssnpa)  { -  struct isis_link_state_hdr *hdr; -  struct isis_adjacency *adj = NULL; -  struct isis_lsp *lsp, *lsp0 = NULL; -  int retval = ISIS_OK, comp = 0; -  u_char lspid[ISIS_SYS_ID_LEN + 2]; -  struct isis_passwd *passwd; -  uint16_t pdu_len; -  int lsp_confusion; - -  if (isis->debugs & DEBUG_UPDATE_PACKETS) -    { -      zlog_debug ("ISIS-Upd (%s): Rcvd L%d LSP on %s, cirType %s, cirID %u", -                  circuit->area->area_tag, level, circuit->interface->name, -                  circuit_t2string (circuit->is_type), circuit->circuit_id); -      if (isis->debugs & DEBUG_PACKET_DUMP) -        zlog_dump_data (STREAM_DATA (circuit->rcv_stream), -                        stream_get_endp (circuit->rcv_stream)); -    } - -  if ((stream_get_endp (circuit->rcv_stream) - -       stream_get_getp (circuit->rcv_stream)) < ISIS_LSP_HDR_LEN) -    { -      zlog_warn ("Packet too short"); -      return ISIS_WARNING; -    } +	struct isis_link_state_hdr *hdr; +	struct isis_adjacency *adj = NULL; +	struct isis_lsp *lsp, *lsp0 = NULL; +	int retval = ISIS_OK, comp = 0; +	u_char lspid[ISIS_SYS_ID_LEN + 2]; +	struct isis_passwd *passwd; +	uint16_t pdu_len; +	int lsp_confusion; + +	if (isis->debugs & DEBUG_UPDATE_PACKETS) { +		zlog_debug( +			"ISIS-Upd (%s): Rcvd L%d LSP on %s, cirType %s, cirID %u", +			circuit->area->area_tag, level, +			circuit->interface->name, +			circuit_t2string(circuit->is_type), +			circuit->circuit_id); +		if (isis->debugs & DEBUG_PACKET_DUMP) +			zlog_dump_data(STREAM_DATA(circuit->rcv_stream), +				       stream_get_endp(circuit->rcv_stream)); +	} -  /* Reference the header   */ -  hdr = (struct isis_link_state_hdr *) STREAM_PNT (circuit->rcv_stream); -  pdu_len = ntohs (hdr->pdu_len); +	if ((stream_get_endp(circuit->rcv_stream) +	     - stream_get_getp(circuit->rcv_stream)) +	    < ISIS_LSP_HDR_LEN) { +		zlog_warn("Packet too short"); +		return ISIS_WARNING; +	} -  /* lsp length check */ -  if (pdu_len < (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN) || -      pdu_len > ISO_MTU(circuit) || -      pdu_len > stream_get_endp (circuit->rcv_stream)) -    { -      zlog_debug ("ISIS-Upd (%s): LSP %s invalid LSP length %d", -		  circuit->area->area_tag, -		  rawlspid_print (hdr->lsp_id), pdu_len); +	/* Reference the header   */ +	hdr = (struct isis_link_state_hdr *)STREAM_PNT(circuit->rcv_stream); +	pdu_len = ntohs(hdr->pdu_len); -      return ISIS_WARNING; -    } - -  /* -   * Set the stream endp to PDU length, ignoring additional padding -   * introduced by transport chips. -   */ -  if (pdu_len < stream_get_endp (circuit->rcv_stream)) -    stream_set_endp (circuit->rcv_stream, pdu_len); +	/* lsp length check */ +	if (pdu_len < (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN) +	    || pdu_len > ISO_MTU(circuit) +	    || pdu_len > stream_get_endp(circuit->rcv_stream)) { +		zlog_debug("ISIS-Upd (%s): LSP %s invalid LSP length %d", +			   circuit->area->area_tag, rawlspid_print(hdr->lsp_id), +			   pdu_len); -  if (isis->debugs & DEBUG_UPDATE_PACKETS) -    { -      zlog_debug ("ISIS-Upd (%s): Rcvd L%d LSP %s, seq 0x%08x, cksum 0x%04x, " -		  "lifetime %us, len %u, on %s", -		  circuit->area->area_tag, -		  level, -		  rawlspid_print (hdr->lsp_id), -		  ntohl (hdr->seq_num), -		  ntohs (hdr->checksum), -		  ntohs (hdr->rem_lifetime), -		  pdu_len, -		  circuit->interface->name); -    } - -  /* lsp is_type check */ -  if ((hdr->lsp_bits & IS_LEVEL_1_AND_2) != IS_LEVEL_1 && -      (hdr->lsp_bits & IS_LEVEL_1_AND_2) != IS_LEVEL_1_AND_2) -    { -      zlog_debug ("ISIS-Upd (%s): LSP %s invalid LSP is type %x", -		  circuit->area->area_tag, -		  rawlspid_print (hdr->lsp_id), hdr->lsp_bits); -      /* continue as per RFC1122 Be liberal in what you accept, and -       * conservative in what you send */ -    } - -  /* Checksum sanity check - FIXME: move to correct place */ -  /* 12 = sysid+pdu+remtime */ -  if (iso_csum_verify (STREAM_PNT (circuit->rcv_stream) + 4, -		       pdu_len - 12, &hdr->checksum)) -    { -      zlog_debug ("ISIS-Upd (%s): LSP %s invalid LSP checksum 0x%04x", -		  circuit->area->area_tag, -		  rawlspid_print (hdr->lsp_id), ntohs (hdr->checksum)); +		return ISIS_WARNING; +	} -      return ISIS_WARNING; -    } +	/* +	 * Set the stream endp to PDU length, ignoring additional padding +	 * introduced by transport chips. +	 */ +	if (pdu_len < stream_get_endp(circuit->rcv_stream)) +		stream_set_endp(circuit->rcv_stream, pdu_len); + +	if (isis->debugs & DEBUG_UPDATE_PACKETS) { +		zlog_debug( +			"ISIS-Upd (%s): Rcvd L%d LSP %s, seq 0x%08x, cksum 0x%04x, " +			"lifetime %us, len %u, on %s", +			circuit->area->area_tag, level, +			rawlspid_print(hdr->lsp_id), ntohl(hdr->seq_num), +			ntohs(hdr->checksum), ntohs(hdr->rem_lifetime), pdu_len, +			circuit->interface->name); +	} -  /* 7.3.15.1 a) 1 - external domain circuit will discard lsps */ -  if (circuit->ext_domain) -    { -      zlog_debug -	("ISIS-Upd (%s): LSP %s received at level %d over circuit with " -	 "externalDomain = true", circuit->area->area_tag, -	 rawlspid_print (hdr->lsp_id), level); +	/* lsp is_type check */ +	if ((hdr->lsp_bits & IS_LEVEL_1_AND_2) != IS_LEVEL_1 +	    && (hdr->lsp_bits & IS_LEVEL_1_AND_2) != IS_LEVEL_1_AND_2) { +		zlog_debug("ISIS-Upd (%s): LSP %s invalid LSP is type %x", +			   circuit->area->area_tag, rawlspid_print(hdr->lsp_id), +			   hdr->lsp_bits); +		/* continue as per RFC1122 Be liberal in what you accept, and +		 * conservative in what you send */ +	} -      return ISIS_WARNING; -    } +	/* Checksum sanity check - FIXME: move to correct place */ +	/* 12 = sysid+pdu+remtime */ +	if (iso_csum_verify(STREAM_PNT(circuit->rcv_stream) + 4, pdu_len - 12, +			    &hdr->checksum)) { +		zlog_debug("ISIS-Upd (%s): LSP %s invalid LSP checksum 0x%04x", +			   circuit->area->area_tag, rawlspid_print(hdr->lsp_id), +			   ntohs(hdr->checksum)); -  /* 7.3.15.1 a) 2,3 - manualL2OnlyMode not implemented */ -  if (!accept_level (level, circuit->is_type)) -    { -      zlog_debug ("ISIS-Upd (%s): LSP %s received at level %d over circuit of" -		  " type %s", -		  circuit->area->area_tag, -		  rawlspid_print (hdr->lsp_id), -		  level, circuit_t2string (circuit->is_type)); +		return ISIS_WARNING; +	} -      return ISIS_WARNING; -    } +	/* 7.3.15.1 a) 1 - external domain circuit will discard lsps */ +	if (circuit->ext_domain) { +		zlog_debug( +			"ISIS-Upd (%s): LSP %s received at level %d over circuit with " +			"externalDomain = true", +			circuit->area->area_tag, rawlspid_print(hdr->lsp_id), +			level); -  /* 7.3.15.1 a) 4 - need to make sure IDLength matches */ +		return ISIS_WARNING; +	} -  /* 7.3.15.1 a) 5 - maximum area match, can be ommited since we only use 3 */ +	/* 7.3.15.1 a) 2,3 - manualL2OnlyMode not implemented */ +	if (!accept_level(level, circuit->is_type)) { +		zlog_debug( +			"ISIS-Upd (%s): LSP %s received at level %d over circuit of" +			" type %s", +			circuit->area->area_tag, rawlspid_print(hdr->lsp_id), +			level, circuit_t2string(circuit->is_type)); -  /* 7.3.15.1 a) 7 - password check */ -  (level == IS_LEVEL_1) ? (passwd = &circuit->area->area_passwd) : -                          (passwd = &circuit->area->domain_passwd); -  if (passwd->type) -    { -      if (lsp_authentication_check (circuit->rcv_stream, circuit->area, -                                    level, passwd)) -	{ -	  isis_event_auth_failure (circuit->area->area_tag, -				   "LSP authentication failure", hdr->lsp_id); -	  return ISIS_WARNING; +		return ISIS_WARNING;  	} -    } -  /* Find the LSP in our database and compare it to this Link State header */ -  lsp = lsp_search (hdr->lsp_id, circuit->area->lspdb[level - 1]); -  if (lsp) -    comp = lsp_compare (circuit->area->area_tag, lsp, hdr->seq_num, -			hdr->checksum, hdr->rem_lifetime); -  if (lsp && (lsp->own_lsp)) -    goto dontcheckadj; - -  /* 7.3.15.1 a) 6 - Must check that we have an adjacency of the same level  */ -  /* for broadcast circuits, snpa should be compared */ - -  if (circuit->circ_type == CIRCUIT_T_BROADCAST) -    { -      adj = isis_adj_lookup_snpa (ssnpa, circuit->u.bc.adjdb[level - 1]); -      if (!adj) -	{ -	  zlog_debug ("(%s): DS ======= LSP %s, seq 0x%08x, cksum 0x%04x, " -		      "lifetime %us on %s", -		      circuit->area->area_tag, -		      rawlspid_print (hdr->lsp_id), -		      ntohl (hdr->seq_num), -		      ntohs (hdr->checksum), -		      ntohs (hdr->rem_lifetime), circuit->interface->name); -	  return ISIS_WARNING;	/* Silently discard */ + +	/* 7.3.15.1 a) 4 - need to make sure IDLength matches */ + +	/* 7.3.15.1 a) 5 - maximum area match, can be ommited since we only use +	 * 3 */ + +	/* 7.3.15.1 a) 7 - password check */ +	(level == IS_LEVEL_1) ? (passwd = &circuit->area->area_passwd) +			      : (passwd = &circuit->area->domain_passwd); +	if (passwd->type) { +		if (lsp_authentication_check(circuit->rcv_stream, circuit->area, +					     level, passwd)) { +			isis_event_auth_failure(circuit->area->area_tag, +						"LSP authentication failure", +						hdr->lsp_id); +			return ISIS_WARNING; +		}  	} -    } -  /* for non broadcast, we just need to find same level adj */ -  else -    { -      /* If no adj, or no sharing of level */ -      if (!circuit->u.p2p.neighbor) -	{ -	  return ISIS_OK;	/* Silently discard */ +	/* Find the LSP in our database and compare it to this Link State header +	 */ +	lsp = lsp_search(hdr->lsp_id, circuit->area->lspdb[level - 1]); +	if (lsp) +		comp = lsp_compare(circuit->area->area_tag, lsp, hdr->seq_num, +				   hdr->checksum, hdr->rem_lifetime); +	if (lsp && (lsp->own_lsp)) +		goto dontcheckadj; + +	/* 7.3.15.1 a) 6 - Must check that we have an adjacency of the same +	 * level  */ +	/* for broadcast circuits, snpa should be compared */ + +	if (circuit->circ_type == CIRCUIT_T_BROADCAST) { +		adj = isis_adj_lookup_snpa(ssnpa, +					   circuit->u.bc.adjdb[level - 1]); +		if (!adj) { +			zlog_debug( +				"(%s): DS ======= LSP %s, seq 0x%08x, cksum 0x%04x, " +				"lifetime %us on %s", +				circuit->area->area_tag, +				rawlspid_print(hdr->lsp_id), +				ntohl(hdr->seq_num), ntohs(hdr->checksum), +				ntohs(hdr->rem_lifetime), +				circuit->interface->name); +			return ISIS_WARNING; /* Silently discard */ +		}  	} -      else -	{ -	  if (((level == IS_LEVEL_1) && -	       (circuit->u.p2p.neighbor->adj_usage == ISIS_ADJ_LEVEL2)) || -	      ((level == IS_LEVEL_2) && -	       (circuit->u.p2p.neighbor->adj_usage == ISIS_ADJ_LEVEL1))) -	    return ISIS_WARNING;	/* Silently discard */ +	/* for non broadcast, we just need to find same level adj */ +	else { +		/* If no adj, or no sharing of level */ +		if (!circuit->u.p2p.neighbor) { +			return ISIS_OK; /* Silently discard */ +		} else { +			if (((level == IS_LEVEL_1) +			     && (circuit->u.p2p.neighbor->adj_usage +				 == ISIS_ADJ_LEVEL2)) +			    || ((level == IS_LEVEL_2) +				&& (circuit->u.p2p.neighbor->adj_usage +				    == ISIS_ADJ_LEVEL1))) +				return ISIS_WARNING; /* Silently discard */ +		}  	} -    }  dontcheckadj: -  /* 7.3.15.1 a) 7 - Passwords for level 1 - not implemented  */ - -  /* 7.3.15.1 a) 8 - Passwords for level 2 - not implemented  */ - -  /* 7.3.15.1 a) 9 - OriginatingLSPBufferSize - not implemented  FIXME: do it */ - -  /* 7.3.16.2 - If this is an LSP from another IS with identical seq_num but -   *            wrong checksum, initiate a purge. */ -  if (lsp -      && (lsp->lsp_header->seq_num == hdr->seq_num) -      && (lsp->lsp_header->checksum != hdr->checksum)) -    { -      zlog_warn("ISIS-Upd (%s): LSP %s seq 0x%08x with confused checksum received.", -                circuit->area->area_tag, rawlspid_print(hdr->lsp_id), -                ntohl(hdr->seq_num)); -      hdr->rem_lifetime = 0; -      lsp_confusion = 1; -    } -  else -    lsp_confusion = 0; - -  /* 7.3.15.1 b) - If the remaining life time is 0, we perform 7.3.16.4 */ -  if (hdr->rem_lifetime == 0) -    { -      if (!lsp) -	{ -	  /* 7.3.16.4 a) 1) No LSP in db -> send an ack, but don't save */ -	  /* only needed on explicit update, eg - p2p */ -	  if (circuit->circ_type == CIRCUIT_T_P2P) -	    ack_lsp (hdr, circuit, level); -	  return retval;	/* FIXME: do we need a purge? */ -	} -      else -	{ -	  if (memcmp (hdr->lsp_id, isis->sysid, ISIS_SYS_ID_LEN)) -	    { -	      /* LSP by some other system -> do 7.3.16.4 b) */ -	      /* 7.3.16.4 b) 1)  */ -	      if (comp == LSP_NEWER) -		{ -                  lsp_update (lsp, circuit->rcv_stream, circuit->area, level); -		  /* ii */ -                  lsp_set_all_srmflags (lsp); -		  /* v */ -		  ISIS_FLAGS_CLEAR_ALL (lsp->SSNflags);	/* FIXME: OTHER than c */ - -		  /* For the case of lsp confusion, flood the purge back to its -		   * originator so that it can react. Otherwise, don't reflood -		   * through incoming circuit as usual */ -		  if (!lsp_confusion) -		    { -		      /* iii */ -		      ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); -		      /* iv */ -		      if (circuit->circ_type != CIRCUIT_T_BROADCAST) -		        ISIS_SET_FLAG (lsp->SSNflags, circuit); -		    } -		}		/* 7.3.16.4 b) 2) */ -	      else if (comp == LSP_EQUAL) -		{ -		  /* i */ -		  ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); -		  /* ii */ -		  if (circuit->circ_type != CIRCUIT_T_BROADCAST) -		    ISIS_SET_FLAG (lsp->SSNflags, circuit); -		}		/* 7.3.16.4 b) 3) */ -	      else -		{ -		  ISIS_SET_FLAG (lsp->SRMflags, circuit); -		  ISIS_CLEAR_FLAG (lsp->SSNflags, circuit); +	/* 7.3.15.1 a) 7 - Passwords for level 1 - not implemented  */ + +	/* 7.3.15.1 a) 8 - Passwords for level 2 - not implemented  */ + +	/* 7.3.15.1 a) 9 - OriginatingLSPBufferSize - not implemented  FIXME: do +	 * it */ + +	/* 7.3.16.2 - If this is an LSP from another IS with identical seq_num +	 * but +	 *            wrong checksum, initiate a purge. */ +	if (lsp && (lsp->lsp_header->seq_num == hdr->seq_num) +	    && (lsp->lsp_header->checksum != hdr->checksum)) { +		zlog_warn( +			"ISIS-Upd (%s): LSP %s seq 0x%08x with confused checksum received.", +			circuit->area->area_tag, rawlspid_print(hdr->lsp_id), +			ntohl(hdr->seq_num)); +		hdr->rem_lifetime = 0; +		lsp_confusion = 1; +	} else +		lsp_confusion = 0; + +	/* 7.3.15.1 b) - If the remaining life time is 0, we perform 7.3.16.4 */ +	if (hdr->rem_lifetime == 0) { +		if (!lsp) { +			/* 7.3.16.4 a) 1) No LSP in db -> send an ack, but don't +			 * save */ +			/* only needed on explicit update, eg - p2p */ +			if (circuit->circ_type == CIRCUIT_T_P2P) +				ack_lsp(hdr, circuit, level); +			return retval; /* FIXME: do we need a purge? */ +		} else { +			if (memcmp(hdr->lsp_id, isis->sysid, ISIS_SYS_ID_LEN)) { +				/* LSP by some other system -> do 7.3.16.4 b) */ +				/* 7.3.16.4 b) 1)  */ +				if (comp == LSP_NEWER) { +					lsp_update(lsp, circuit->rcv_stream, +						   circuit->area, level); +					/* ii */ +					lsp_set_all_srmflags(lsp); +					/* v */ +					ISIS_FLAGS_CLEAR_ALL( +						lsp +							->SSNflags); /* FIXME: +									OTHER +									than c +									*/ + +					/* For the case of lsp confusion, flood +					 * the purge back to its +					 * originator so that it can react. +					 * Otherwise, don't reflood +					 * through incoming circuit as usual */ +					if (!lsp_confusion) { +						/* iii */ +						ISIS_CLEAR_FLAG(lsp->SRMflags, +								circuit); +						/* iv */ +						if (circuit->circ_type +						    != CIRCUIT_T_BROADCAST) +							ISIS_SET_FLAG( +								lsp->SSNflags, +								circuit); +					} +				} /* 7.3.16.4 b) 2) */ +				else if (comp == LSP_EQUAL) { +					/* i */ +					ISIS_CLEAR_FLAG(lsp->SRMflags, circuit); +					/* ii */ +					if (circuit->circ_type +					    != CIRCUIT_T_BROADCAST) +						ISIS_SET_FLAG(lsp->SSNflags, +							      circuit); +				} /* 7.3.16.4 b) 3) */ +				else { +					ISIS_SET_FLAG(lsp->SRMflags, circuit); +					ISIS_CLEAR_FLAG(lsp->SSNflags, circuit); +				} +			} else if (lsp->lsp_header->rem_lifetime != 0) { +				/* our own LSP -> 7.3.16.4 c) */ +				if (comp == LSP_NEWER) { +					lsp_inc_seqnum(lsp, +						       ntohl(hdr->seq_num)); +					lsp_set_all_srmflags(lsp); +				} else { +					ISIS_SET_FLAG(lsp->SRMflags, circuit); +					ISIS_CLEAR_FLAG(lsp->SSNflags, circuit); +				} +				if (isis->debugs & DEBUG_UPDATE_PACKETS) +					zlog_debug( +						"ISIS-Upd (%s): (1) re-originating LSP %s new " +						"seq 0x%08x", +						circuit->area->area_tag, +						rawlspid_print(hdr->lsp_id), +						ntohl(lsp->lsp_header +							      ->seq_num)); +			}  		} -	    } -          else if (lsp->lsp_header->rem_lifetime != 0) -            { -              /* our own LSP -> 7.3.16.4 c) */ -              if (comp == LSP_NEWER) -                { -                  lsp_inc_seqnum (lsp, ntohl (hdr->seq_num)); -                  lsp_set_all_srmflags (lsp); -                } -              else -                { -                  ISIS_SET_FLAG (lsp->SRMflags, circuit); -                  ISIS_CLEAR_FLAG (lsp->SSNflags, circuit); -                } -              if (isis->debugs & DEBUG_UPDATE_PACKETS) -                zlog_debug ("ISIS-Upd (%s): (1) re-originating LSP %s new " -                            "seq 0x%08x", circuit->area->area_tag, -                            rawlspid_print (hdr->lsp_id), -                            ntohl (lsp->lsp_header->seq_num)); -            } -	} -      return retval; -    } -  /* 7.3.15.1 c) - If this is our own lsp and we don't have it initiate a  -   * purge */ -  if (memcmp (hdr->lsp_id, isis->sysid, ISIS_SYS_ID_LEN) == 0) -    { -      if (!lsp) -	{ -	  /* 7.3.16.4: initiate a purge */ -	  lsp_purge_non_exist(level, hdr, circuit->area); -	  return ISIS_OK; +		return retval;  	} -      /* 7.3.15.1 d) - If this is our own lsp and we have it */ - -      /* In 7.3.16.1, If an Intermediate system R somewhere in the domain -       * has information that the current sequence number for source S is -       * "greater" than that held by S, ... */ - -      if (ntohl (hdr->seq_num) > ntohl (lsp->lsp_header->seq_num)) -	{ -	  /* 7.3.16.1  */ -          lsp_inc_seqnum (lsp, ntohl (hdr->seq_num)); -	  if (isis->debugs & DEBUG_UPDATE_PACKETS) -	    zlog_debug ("ISIS-Upd (%s): (2) re-originating LSP %s new seq " -			"0x%08x", circuit->area->area_tag, -			rawlspid_print (hdr->lsp_id), -			ntohl (lsp->lsp_header->seq_num)); -	} -      /* If the received LSP is older or equal, -       * resend the LSP which will act as ACK */ -      lsp_set_all_srmflags (lsp); -    } -  else -    { -      /* 7.3.15.1 e) - This lsp originated on another system */ - -      /* 7.3.15.1 e) 1) LSP newer than the one in db or no LSP in db */ -      if ((!lsp || comp == LSP_NEWER)) -	{ -	  /* -	   * If this lsp is a frag, need to see if we have zero lsp present -	   */ -	  if (LSP_FRAGMENT (hdr->lsp_id) != 0) -	    { -	      memcpy (lspid, hdr->lsp_id, ISIS_SYS_ID_LEN + 1); -	      LSP_FRAGMENT (lspid) = 0; -	      lsp0 = lsp_search (lspid, circuit->area->lspdb[level - 1]); -	      if (!lsp0) -		{ -		  zlog_debug ("Got lsp frag, while zero lsp not in database"); -		  return ISIS_OK; +	/* 7.3.15.1 c) - If this is our own lsp and we don't have it initiate a +	 * purge */ +	if (memcmp(hdr->lsp_id, isis->sysid, ISIS_SYS_ID_LEN) == 0) { +		if (!lsp) { +			/* 7.3.16.4: initiate a purge */ +			lsp_purge_non_exist(level, hdr, circuit->area); +			return ISIS_OK; +		} +		/* 7.3.15.1 d) - If this is our own lsp and we have it */ + +		/* In 7.3.16.1, If an Intermediate system R somewhere in the +		 * domain +		 * has information that the current sequence number for source S +		 * is +		 * "greater" than that held by S, ... */ + +		if (ntohl(hdr->seq_num) > ntohl(lsp->lsp_header->seq_num)) { +			/* 7.3.16.1  */ +			lsp_inc_seqnum(lsp, ntohl(hdr->seq_num)); +			if (isis->debugs & DEBUG_UPDATE_PACKETS) +				zlog_debug( +					"ISIS-Upd (%s): (2) re-originating LSP %s new seq " +					"0x%08x", +					circuit->area->area_tag, +					rawlspid_print(hdr->lsp_id), +					ntohl(lsp->lsp_header->seq_num)); +		} +		/* If the received LSP is older or equal, +		 * resend the LSP which will act as ACK */ +		lsp_set_all_srmflags(lsp); +	} else { +		/* 7.3.15.1 e) - This lsp originated on another system */ + +		/* 7.3.15.1 e) 1) LSP newer than the one in db or no LSP in db +		 */ +		if ((!lsp || comp == LSP_NEWER)) { +			/* +			 * If this lsp is a frag, need to see if we have zero +			 * lsp present +			 */ +			if (LSP_FRAGMENT(hdr->lsp_id) != 0) { +				memcpy(lspid, hdr->lsp_id, ISIS_SYS_ID_LEN + 1); +				LSP_FRAGMENT(lspid) = 0; +				lsp0 = lsp_search( +					lspid, circuit->area->lspdb[level - 1]); +				if (!lsp0) { +					zlog_debug( +						"Got lsp frag, while zero lsp not in database"); +					return ISIS_OK; +				} +			} +			/* i */ +			if (!lsp) { +				lsp = lsp_new_from_stream_ptr( +					circuit->rcv_stream, pdu_len, lsp0, +					circuit->area, level); +				lsp_insert(lsp, +					   circuit->area->lspdb[level - 1]); +			} else /* exists, so we overwrite */ +			{ +				lsp_update(lsp, circuit->rcv_stream, +					   circuit->area, level); +			} +			/* ii */ +			lsp_set_all_srmflags(lsp); +			/* iii */ +			ISIS_CLEAR_FLAG(lsp->SRMflags, circuit); + +			/* iv */ +			if (circuit->circ_type != CIRCUIT_T_BROADCAST) +				ISIS_SET_FLAG(lsp->SSNflags, circuit); +			/* FIXME: v) */ +		} +		/* 7.3.15.1 e) 2) LSP equal to the one in db */ +		else if (comp == LSP_EQUAL) { +			ISIS_CLEAR_FLAG(lsp->SRMflags, circuit); +			lsp_update(lsp, circuit->rcv_stream, circuit->area, +				   level); +			if (circuit->circ_type != CIRCUIT_T_BROADCAST) +				ISIS_SET_FLAG(lsp->SSNflags, circuit); +		} +		/* 7.3.15.1 e) 3) LSP older than the one in db */ +		else { +			ISIS_SET_FLAG(lsp->SRMflags, circuit); +			ISIS_CLEAR_FLAG(lsp->SSNflags, circuit);  		} -	    } -	  /* i */ -	  if (!lsp) -            { -	      lsp = lsp_new_from_stream_ptr (circuit->rcv_stream, -                                             pdu_len, lsp0, -                                             circuit->area, level); -              lsp_insert (lsp, circuit->area->lspdb[level - 1]); -            } -          else /* exists, so we overwrite */ -            { -              lsp_update (lsp, circuit->rcv_stream, circuit->area, level); -            } -	  /* ii */ -          lsp_set_all_srmflags (lsp); -	  /* iii */ -	  ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); - -	  /* iv */ -	  if (circuit->circ_type != CIRCUIT_T_BROADCAST) -	    ISIS_SET_FLAG (lsp->SSNflags, circuit); -	  /* FIXME: v) */ -	} -      /* 7.3.15.1 e) 2) LSP equal to the one in db */ -      else if (comp == LSP_EQUAL) -	{ -	  ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); -	  lsp_update (lsp, circuit->rcv_stream, circuit->area, level); -	  if (circuit->circ_type != CIRCUIT_T_BROADCAST) -	    ISIS_SET_FLAG (lsp->SSNflags, circuit); -	} -      /* 7.3.15.1 e) 3) LSP older than the one in db */ -      else -	{ -	  ISIS_SET_FLAG (lsp->SRMflags, circuit); -	  ISIS_CLEAR_FLAG (lsp->SSNflags, circuit);  	} -    } -  return retval; +	return retval;  }  /* @@ -1653,1535 +1593,1494 @@ dontcheckadj:   * Section 7.3.15.2 - Action on receipt of a sequence numbers PDU   */ -static int -process_snp (int snp_type, int level, struct isis_circuit *circuit, -	     const u_char *ssnpa) +static int process_snp(int snp_type, int level, struct isis_circuit *circuit, +		       const u_char *ssnpa)  { -  int retval = ISIS_OK; -  int cmp, own_lsp; -  char typechar = ' '; -  uint16_t pdu_len; -  struct isis_adjacency *adj; -  struct isis_complete_seqnum_hdr *chdr = NULL; -  struct isis_partial_seqnum_hdr *phdr = NULL; -  uint32_t found = 0, expected = 0, auth_tlv_offset = 0; -  struct isis_lsp *lsp; -  struct lsp_entry *entry; -  struct listnode *node, *nnode; -  struct listnode *node2, *nnode2; -  struct tlvs tlvs; -  struct list *lsp_list = NULL; -  struct isis_passwd *passwd; - -  if (snp_type == ISIS_SNP_CSNP_FLAG) -    { -      /* getting the header info */ -      typechar = 'C'; -      chdr = -	(struct isis_complete_seqnum_hdr *) STREAM_PNT (circuit->rcv_stream); -      stream_forward_getp (circuit->rcv_stream, ISIS_CSNP_HDRLEN); -      pdu_len = ntohs (chdr->pdu_len); -      if (pdu_len < (ISIS_FIXED_HDR_LEN + ISIS_CSNP_HDRLEN) || -          pdu_len > ISO_MTU(circuit) || -          pdu_len > stream_get_endp (circuit->rcv_stream)) -	{ -	  zlog_warn ("Received a CSNP with bogus length %d", pdu_len); -	  return ISIS_WARNING; -	} -    } -  else -    { -      typechar = 'P'; -      phdr = -	(struct isis_partial_seqnum_hdr *) STREAM_PNT (circuit->rcv_stream); -      stream_forward_getp (circuit->rcv_stream, ISIS_PSNP_HDRLEN); -      pdu_len = ntohs (phdr->pdu_len); -      if (pdu_len < (ISIS_FIXED_HDR_LEN + ISIS_PSNP_HDRLEN) || -          pdu_len > ISO_MTU(circuit) || -          pdu_len > stream_get_endp (circuit->rcv_stream)) -	{ -	  zlog_warn ("Received a PSNP with bogus length %d", pdu_len); -	  return ISIS_WARNING; +	int retval = ISIS_OK; +	int cmp, own_lsp; +	char typechar = ' '; +	uint16_t pdu_len; +	struct isis_adjacency *adj; +	struct isis_complete_seqnum_hdr *chdr = NULL; +	struct isis_partial_seqnum_hdr *phdr = NULL; +	uint32_t found = 0, expected = 0, auth_tlv_offset = 0; +	struct isis_lsp *lsp; +	struct lsp_entry *entry; +	struct listnode *node, *nnode; +	struct listnode *node2, *nnode2; +	struct tlvs tlvs; +	struct list *lsp_list = NULL; +	struct isis_passwd *passwd; + +	if (snp_type == ISIS_SNP_CSNP_FLAG) { +		/* getting the header info */ +		typechar = 'C'; +		chdr = (struct isis_complete_seqnum_hdr *)STREAM_PNT( +			circuit->rcv_stream); +		stream_forward_getp(circuit->rcv_stream, ISIS_CSNP_HDRLEN); +		pdu_len = ntohs(chdr->pdu_len); +		if (pdu_len < (ISIS_FIXED_HDR_LEN + ISIS_CSNP_HDRLEN) +		    || pdu_len > ISO_MTU(circuit) +		    || pdu_len > stream_get_endp(circuit->rcv_stream)) { +			zlog_warn("Received a CSNP with bogus length %d", +				  pdu_len); +			return ISIS_WARNING; +		} +	} else { +		typechar = 'P'; +		phdr = (struct isis_partial_seqnum_hdr *)STREAM_PNT( +			circuit->rcv_stream); +		stream_forward_getp(circuit->rcv_stream, ISIS_PSNP_HDRLEN); +		pdu_len = ntohs(phdr->pdu_len); +		if (pdu_len < (ISIS_FIXED_HDR_LEN + ISIS_PSNP_HDRLEN) +		    || pdu_len > ISO_MTU(circuit) +		    || pdu_len > stream_get_endp(circuit->rcv_stream)) { +			zlog_warn("Received a PSNP with bogus length %d", +				  pdu_len); +			return ISIS_WARNING; +		}  	} -    } -  /* -   * Set the stream endp to PDU length, ignoring additional padding -   * introduced by transport chips. -   */ -  if (pdu_len < stream_get_endp (circuit->rcv_stream)) -    stream_set_endp (circuit->rcv_stream, pdu_len); +	/* +	 * Set the stream endp to PDU length, ignoring additional padding +	 * introduced by transport chips. +	 */ +	if (pdu_len < stream_get_endp(circuit->rcv_stream)) +		stream_set_endp(circuit->rcv_stream, pdu_len); -  /* 7.3.15.2 a) 1 - external domain circuit will discard snp pdu */ -  if (circuit->ext_domain) -    { - -      zlog_debug ("ISIS-Snp (%s): Rcvd L%d %cSNP on %s, " -		  "skipping: circuit externalDomain = true", -		  circuit->area->area_tag, -		  level, typechar, circuit->interface->name); +	/* 7.3.15.2 a) 1 - external domain circuit will discard snp pdu */ +	if (circuit->ext_domain) { -      return ISIS_OK; -    } +		zlog_debug( +			"ISIS-Snp (%s): Rcvd L%d %cSNP on %s, " +			"skipping: circuit externalDomain = true", +			circuit->area->area_tag, level, typechar, +			circuit->interface->name); -  /* 7.3.15.2 a) 2,3 - manualL2OnlyMode not implemented */ -  if (!accept_level (level, circuit->is_type)) -    { - -      zlog_debug ("ISIS-Snp (%s): Rcvd L%d %cSNP on %s, " -		  "skipping: circuit type %s does not match level %d", -		  circuit->area->area_tag, -		  level, -		  typechar, -		  circuit->interface->name, -		  circuit_t2string (circuit->is_type), level); - -      return ISIS_OK; -    } - -  /* 7.3.15.2 a) 4 - not applicable for CSNP  only PSNPs on broadcast */ -  if ((snp_type == ISIS_SNP_PSNP_FLAG) && -      (circuit->circ_type == CIRCUIT_T_BROADCAST) && -      (!circuit->u.bc.is_dr[level - 1])) -    { -      zlog_debug ("ISIS-Snp (%s): Rcvd L%d %cSNP from %s on %s, " -                  "skipping: we are not the DIS", -                  circuit->area->area_tag, -                  level, -                  typechar, snpa_print (ssnpa), circuit->interface->name); - -      return ISIS_OK; -    } +		return ISIS_OK; +	} -  /* 7.3.15.2 a) 5 - need to make sure IDLength matches - already checked */ +	/* 7.3.15.2 a) 2,3 - manualL2OnlyMode not implemented */ +	if (!accept_level(level, circuit->is_type)) { -  /* 7.3.15.2 a) 6 - maximum area match, can be ommited since we only use 3 -   * - already checked */ +		zlog_debug( +			"ISIS-Snp (%s): Rcvd L%d %cSNP on %s, " +			"skipping: circuit type %s does not match level %d", +			circuit->area->area_tag, level, typechar, +			circuit->interface->name, +			circuit_t2string(circuit->is_type), level); -  /* 7.3.15.2 a) 7 - Must check that we have an adjacency of the same level  */ -  /* for broadcast circuits, snpa should be compared */ -  /* FIXME : Do we need to check SNPA? */ -  if (circuit->circ_type == CIRCUIT_T_BROADCAST) -    { -      if (snp_type == ISIS_SNP_CSNP_FLAG) -	{ -	  adj = -	    isis_adj_lookup (chdr->source_id, circuit->u.bc.adjdb[level - 1]); -	} -      else -	{ -	  /* a psnp on a broadcast, how lovely of Juniper :) */ -	  adj = -	    isis_adj_lookup (phdr->source_id, circuit->u.bc.adjdb[level - 1]); +		return ISIS_OK;  	} -      if (!adj) -	return ISIS_OK;		/* Silently discard */ -    } -  else -    { -      if (!circuit->u.p2p.neighbor) -      { -        zlog_warn ("no p2p neighbor on circuit %s", circuit->interface->name); -        return ISIS_OK;		/* Silently discard */ -      } -    } - -  /* 7.3.15.2 a) 8 - Passwords for level 1 - not implemented  */ -  /* 7.3.15.2 a) 9 - Passwords for level 2 - not implemented  */ +	/* 7.3.15.2 a) 4 - not applicable for CSNP  only PSNPs on broadcast */ +	if ((snp_type == ISIS_SNP_PSNP_FLAG) +	    && (circuit->circ_type == CIRCUIT_T_BROADCAST) +	    && (!circuit->u.bc.is_dr[level - 1])) { +		zlog_debug( +			"ISIS-Snp (%s): Rcvd L%d %cSNP from %s on %s, " +			"skipping: we are not the DIS", +			circuit->area->area_tag, level, typechar, +			snpa_print(ssnpa), circuit->interface->name); + +		return ISIS_OK; +	} -  memset (&tlvs, 0, sizeof (struct tlvs)); +	/* 7.3.15.2 a) 5 - need to make sure IDLength matches - already checked +	 */ + +	/* 7.3.15.2 a) 6 - maximum area match, can be ommited since we only use +	 * 3 +	 * - already checked */ + +	/* 7.3.15.2 a) 7 - Must check that we have an adjacency of the same +	 * level  */ +	/* for broadcast circuits, snpa should be compared */ +	/* FIXME : Do we need to check SNPA? */ +	if (circuit->circ_type == CIRCUIT_T_BROADCAST) { +		if (snp_type == ISIS_SNP_CSNP_FLAG) { +			adj = isis_adj_lookup(chdr->source_id, +					      circuit->u.bc.adjdb[level - 1]); +		} else { +			/* a psnp on a broadcast, how lovely of Juniper :) */ +			adj = isis_adj_lookup(phdr->source_id, +					      circuit->u.bc.adjdb[level - 1]); +		} +		if (!adj) +			return ISIS_OK; /* Silently discard */ +	} else { +		if (!circuit->u.p2p.neighbor) { +			zlog_warn("no p2p neighbor on circuit %s", +				  circuit->interface->name); +			return ISIS_OK; /* Silently discard */ +		} +	} -  /* parse the SNP */ -  expected |= TLVFLAG_LSP_ENTRIES; -  expected |= TLVFLAG_AUTH_INFO; +	/* 7.3.15.2 a) 8 - Passwords for level 1 - not implemented  */ -  auth_tlv_offset = stream_get_getp (circuit->rcv_stream); -  retval = parse_tlvs (circuit->area->area_tag, -		       STREAM_PNT (circuit->rcv_stream), -		       pdu_len - stream_get_getp (circuit->rcv_stream), -		       &expected, &found, &tlvs, &auth_tlv_offset); +	/* 7.3.15.2 a) 9 - Passwords for level 2 - not implemented  */ -  if (retval > ISIS_WARNING) -    { -      zlog_warn ("something went very wrong processing SNP"); -      free_tlvs (&tlvs); -      return retval; -    } +	memset(&tlvs, 0, sizeof(struct tlvs)); -  if (level == IS_LEVEL_1) -    passwd = &circuit->area->area_passwd; -  else -    passwd = &circuit->area->domain_passwd; +	/* parse the SNP */ +	expected |= TLVFLAG_LSP_ENTRIES; +	expected |= TLVFLAG_AUTH_INFO; -  if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_RECV)) -    { -      if (passwd->type) -        { -          if (!(found & TLVFLAG_AUTH_INFO) || -              authentication_check (&tlvs.auth_info, passwd, -                                    circuit->rcv_stream, auth_tlv_offset)) -            { -              isis_event_auth_failure (circuit->area->area_tag, -                                       "SNP authentication" " failure", -                                       phdr ? phdr->source_id : -                                       chdr->source_id); -              free_tlvs (&tlvs); -              return ISIS_OK; -            } -        } -    } +	auth_tlv_offset = stream_get_getp(circuit->rcv_stream); +	retval = parse_tlvs(circuit->area->area_tag, +			    STREAM_PNT(circuit->rcv_stream), +			    pdu_len - stream_get_getp(circuit->rcv_stream), +			    &expected, &found, &tlvs, &auth_tlv_offset); -  /* debug isis snp-packets */ -  if (isis->debugs & DEBUG_SNP_PACKETS) -    { -      zlog_debug ("ISIS-Snp (%s): Rcvd L%d %cSNP from %s on %s", -		  circuit->area->area_tag, -		  level, -		  typechar, snpa_print (ssnpa), circuit->interface->name); -      if (tlvs.lsp_entries) -	{ -	  for (ALL_LIST_ELEMENTS_RO (tlvs.lsp_entries, node, entry)) -	  { -	    zlog_debug ("ISIS-Snp (%s):         %cSNP entry %s, seq 0x%08x," -			" cksum 0x%04x, lifetime %us", -			circuit->area->area_tag, -			typechar, -			rawlspid_print (entry->lsp_id), -			ntohl (entry->seq_num), -			ntohs (entry->checksum), ntohs (entry->rem_lifetime)); -	  } +	if (retval > ISIS_WARNING) { +		zlog_warn("something went very wrong processing SNP"); +		free_tlvs(&tlvs); +		return retval;  	} -    } -  /* 7.3.15.2 b) Actions on LSP_ENTRIES reported */ -  if (tlvs.lsp_entries) -    { -      for (ALL_LIST_ELEMENTS_RO (tlvs.lsp_entries, node, entry)) -      { -	lsp = lsp_search (entry->lsp_id, circuit->area->lspdb[level - 1]); -	own_lsp = !memcmp (entry->lsp_id, isis->sysid, ISIS_SYS_ID_LEN); -	if (lsp) -	  { -	    /* 7.3.15.2 b) 1) is this LSP newer */ -	    cmp = lsp_compare (circuit->area->area_tag, lsp, entry->seq_num, -			       entry->checksum, entry->rem_lifetime); -	    /* 7.3.15.2 b) 2) if it equals, clear SRM on p2p */ -	    if (cmp == LSP_EQUAL) -	      { -		/* if (circuit->circ_type != CIRCUIT_T_BROADCAST) */ -	        ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); -	      } -	    /* 7.3.15.2 b) 3) if it is older, clear SSN and set SRM */ -	    else if (cmp == LSP_OLDER) -	      { -		ISIS_CLEAR_FLAG (lsp->SSNflags, circuit); -		ISIS_SET_FLAG (lsp->SRMflags, circuit); -	      } -	    /* 7.3.15.2 b) 4) if it is newer, set SSN and clear SRM on p2p */ -	    else -	      { -		if (own_lsp) -		  { -		    lsp_inc_seqnum (lsp, ntohl (entry->seq_num)); -		    ISIS_SET_FLAG (lsp->SRMflags, circuit); -		  } -		else -		  { -		    ISIS_SET_FLAG (lsp->SSNflags, circuit); -		    /* if (circuit->circ_type != CIRCUIT_T_BROADCAST) */ -		    ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); -		  } -	      } -	  } +	if (level == IS_LEVEL_1) +		passwd = &circuit->area->area_passwd;  	else -	  { -	    /* 7.3.15.2 b) 5) if it was not found, and all of those are not 0,  -	     * insert it and set SSN on it */ -	    if (entry->rem_lifetime && entry->checksum && entry->seq_num && -		memcmp (entry->lsp_id, isis->sysid, ISIS_SYS_ID_LEN)) -	      { -		lsp = lsp_new(circuit->area, entry->lsp_id, -			      ntohs(entry->rem_lifetime), -			      0, 0, entry->checksum, level); -		lsp_insert (lsp, circuit->area->lspdb[level - 1]); -		ISIS_FLAGS_CLEAR_ALL (lsp->SRMflags); -		ISIS_SET_FLAG (lsp->SSNflags, circuit); -	      } -	  } -      } -    } +		passwd = &circuit->area->domain_passwd; + +	if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_RECV)) { +		if (passwd->type) { +			if (!(found & TLVFLAG_AUTH_INFO) +			    || authentication_check(&tlvs.auth_info, passwd, +						    circuit->rcv_stream, +						    auth_tlv_offset)) { +				isis_event_auth_failure(circuit->area->area_tag, +							"SNP authentication" +							" failure", +							phdr ? phdr->source_id +							     : chdr->source_id); +				free_tlvs(&tlvs); +				return ISIS_OK; +			} +		} +	} -  /* 7.3.15.2 c) on CSNP set SRM for all in range which were not reported */ -  if (snp_type == ISIS_SNP_CSNP_FLAG) -    { -      /* -       * Build a list from our own LSP db bounded with -       * start_lsp_id and stop_lsp_id -       */ -      lsp_list = list_new (); -      lsp_build_list_nonzero_ht (chdr->start_lsp_id, chdr->stop_lsp_id, -				 lsp_list, circuit->area->lspdb[level - 1]); - -      /* Fixme: Find a better solution */ -      if (tlvs.lsp_entries) -	{ -	  for (ALL_LIST_ELEMENTS (tlvs.lsp_entries, node, nnode, entry)) -	  { -	    for (ALL_LIST_ELEMENTS (lsp_list, node2, nnode2, lsp)) -	    { -	      if (lsp_id_cmp (lsp->lsp_header->lsp_id, entry->lsp_id) == 0) -		{ -		  list_delete_node (lsp_list, node2); -		  break; +	/* debug isis snp-packets */ +	if (isis->debugs & DEBUG_SNP_PACKETS) { +		zlog_debug("ISIS-Snp (%s): Rcvd L%d %cSNP from %s on %s", +			   circuit->area->area_tag, level, typechar, +			   snpa_print(ssnpa), circuit->interface->name); +		if (tlvs.lsp_entries) { +			for (ALL_LIST_ELEMENTS_RO(tlvs.lsp_entries, node, +						  entry)) { +				zlog_debug( +					"ISIS-Snp (%s):         %cSNP entry %s, seq 0x%08x," +					" cksum 0x%04x, lifetime %us", +					circuit->area->area_tag, typechar, +					rawlspid_print(entry->lsp_id), +					ntohl(entry->seq_num), +					ntohs(entry->checksum), +					ntohs(entry->rem_lifetime)); +			}  		} -	    } -	  }  	} -      /* on remaining LSPs we set SRM (neighbor knew not of) */ -      for (ALL_LIST_ELEMENTS_RO (lsp_list, node, lsp)) -	ISIS_SET_FLAG (lsp->SRMflags, circuit); -      /* lets free it */ -      list_delete (lsp_list); -    } +	/* 7.3.15.2 b) Actions on LSP_ENTRIES reported */ +	if (tlvs.lsp_entries) { +		for (ALL_LIST_ELEMENTS_RO(tlvs.lsp_entries, node, entry)) { +			lsp = lsp_search(entry->lsp_id, +					 circuit->area->lspdb[level - 1]); +			own_lsp = !memcmp(entry->lsp_id, isis->sysid, +					  ISIS_SYS_ID_LEN); +			if (lsp) { +				/* 7.3.15.2 b) 1) is this LSP newer */ +				cmp = lsp_compare(circuit->area->area_tag, lsp, +						  entry->seq_num, +						  entry->checksum, +						  entry->rem_lifetime); +				/* 7.3.15.2 b) 2) if it equals, clear SRM on p2p +				 */ +				if (cmp == LSP_EQUAL) { +					/* if (circuit->circ_type != +					 * CIRCUIT_T_BROADCAST) */ +					ISIS_CLEAR_FLAG(lsp->SRMflags, circuit); +				} +				/* 7.3.15.2 b) 3) if it is older, clear SSN and +				   set SRM */ +				else if (cmp == LSP_OLDER) { +					ISIS_CLEAR_FLAG(lsp->SSNflags, circuit); +					ISIS_SET_FLAG(lsp->SRMflags, circuit); +				} +				/* 7.3.15.2 b) 4) if it is newer, set SSN and +				   clear SRM on p2p */ +				else { +					if (own_lsp) { +						lsp_inc_seqnum( +							lsp, +							ntohl(entry->seq_num)); +						ISIS_SET_FLAG(lsp->SRMflags, +							      circuit); +					} else { +						ISIS_SET_FLAG(lsp->SSNflags, +							      circuit); +						/* if (circuit->circ_type != +						 * CIRCUIT_T_BROADCAST) */ +						ISIS_CLEAR_FLAG(lsp->SRMflags, +								circuit); +					} +				} +			} else { +				/* 7.3.15.2 b) 5) if it was not found, and all +				 * of those are not 0, +				 * insert it and set SSN on it */ +				if (entry->rem_lifetime && entry->checksum +				    && entry->seq_num +				    && memcmp(entry->lsp_id, isis->sysid, +					      ISIS_SYS_ID_LEN)) { +					lsp = lsp_new( +						circuit->area, entry->lsp_id, +						ntohs(entry->rem_lifetime), 0, +						0, entry->checksum, level); +					lsp_insert(lsp, +						   circuit->area +							   ->lspdb[level - 1]); +					ISIS_FLAGS_CLEAR_ALL(lsp->SRMflags); +					ISIS_SET_FLAG(lsp->SSNflags, circuit); +				} +			} +		} +	} + +	/* 7.3.15.2 c) on CSNP set SRM for all in range which were not reported +	 */ +	if (snp_type == ISIS_SNP_CSNP_FLAG) { +		/* +		 * Build a list from our own LSP db bounded with +		 * start_lsp_id and stop_lsp_id +		 */ +		lsp_list = list_new(); +		lsp_build_list_nonzero_ht(chdr->start_lsp_id, chdr->stop_lsp_id, +					  lsp_list, +					  circuit->area->lspdb[level - 1]); + +		/* Fixme: Find a better solution */ +		if (tlvs.lsp_entries) { +			for (ALL_LIST_ELEMENTS(tlvs.lsp_entries, node, nnode, +					       entry)) { +				for (ALL_LIST_ELEMENTS(lsp_list, node2, nnode2, +						       lsp)) { +					if (lsp_id_cmp(lsp->lsp_header->lsp_id, +						       entry->lsp_id) +					    == 0) { +						list_delete_node(lsp_list, +								 node2); +						break; +					} +				} +			} +		} +		/* on remaining LSPs we set SRM (neighbor knew not of) */ +		for (ALL_LIST_ELEMENTS_RO(lsp_list, node, lsp)) +			ISIS_SET_FLAG(lsp->SRMflags, circuit); +		/* lets free it */ +		list_delete(lsp_list); +	} -  free_tlvs (&tlvs); -  return retval; +	free_tlvs(&tlvs); +	return retval;  } -static int -process_csnp (int level, struct isis_circuit *circuit, const u_char *ssnpa) +static int process_csnp(int level, struct isis_circuit *circuit, +			const u_char *ssnpa)  { -  if (isis->debugs & DEBUG_SNP_PACKETS) -    { -      zlog_debug ("ISIS-Snp (%s): Rcvd L%d CSNP on %s, cirType %s, cirID %u", -                  circuit->area->area_tag, level, circuit->interface->name, -                  circuit_t2string (circuit->is_type), circuit->circuit_id); -      if (isis->debugs & DEBUG_PACKET_DUMP) -        zlog_dump_data (STREAM_DATA (circuit->rcv_stream), -                        stream_get_endp (circuit->rcv_stream)); -    } +	if (isis->debugs & DEBUG_SNP_PACKETS) { +		zlog_debug( +			"ISIS-Snp (%s): Rcvd L%d CSNP on %s, cirType %s, cirID %u", +			circuit->area->area_tag, level, +			circuit->interface->name, +			circuit_t2string(circuit->is_type), +			circuit->circuit_id); +		if (isis->debugs & DEBUG_PACKET_DUMP) +			zlog_dump_data(STREAM_DATA(circuit->rcv_stream), +				       stream_get_endp(circuit->rcv_stream)); +	} -  /* Sanity check - FIXME: move to correct place */ -  if ((stream_get_endp (circuit->rcv_stream) - -       stream_get_getp (circuit->rcv_stream)) < ISIS_CSNP_HDRLEN) -    { -      zlog_warn ("Packet too short ( < %d)", ISIS_CSNP_HDRLEN); -      return ISIS_WARNING; -    } +	/* Sanity check - FIXME: move to correct place */ +	if ((stream_get_endp(circuit->rcv_stream) +	     - stream_get_getp(circuit->rcv_stream)) +	    < ISIS_CSNP_HDRLEN) { +		zlog_warn("Packet too short ( < %d)", ISIS_CSNP_HDRLEN); +		return ISIS_WARNING; +	} -  return process_snp (ISIS_SNP_CSNP_FLAG, level, circuit, ssnpa); +	return process_snp(ISIS_SNP_CSNP_FLAG, level, circuit, ssnpa);  } -static int -process_psnp (int level, struct isis_circuit *circuit, const u_char *ssnpa) +static int process_psnp(int level, struct isis_circuit *circuit, +			const u_char *ssnpa)  { -  if (isis->debugs & DEBUG_SNP_PACKETS) -    { -      zlog_debug ("ISIS-Snp (%s): Rcvd L%d PSNP on %s, cirType %s, cirID %u", -                  circuit->area->area_tag, level, circuit->interface->name, -                  circuit_t2string (circuit->is_type), circuit->circuit_id); -      if (isis->debugs & DEBUG_PACKET_DUMP) -        zlog_dump_data (STREAM_DATA (circuit->rcv_stream), -                        stream_get_endp (circuit->rcv_stream)); -    } +	if (isis->debugs & DEBUG_SNP_PACKETS) { +		zlog_debug( +			"ISIS-Snp (%s): Rcvd L%d PSNP on %s, cirType %s, cirID %u", +			circuit->area->area_tag, level, +			circuit->interface->name, +			circuit_t2string(circuit->is_type), +			circuit->circuit_id); +		if (isis->debugs & DEBUG_PACKET_DUMP) +			zlog_dump_data(STREAM_DATA(circuit->rcv_stream), +				       stream_get_endp(circuit->rcv_stream)); +	} -  if ((stream_get_endp (circuit->rcv_stream) - -       stream_get_getp (circuit->rcv_stream)) < ISIS_PSNP_HDRLEN) -    { -      zlog_warn ("Packet too short ( < %d)", ISIS_PSNP_HDRLEN); -      return ISIS_WARNING; -    } +	if ((stream_get_endp(circuit->rcv_stream) +	     - stream_get_getp(circuit->rcv_stream)) +	    < ISIS_PSNP_HDRLEN) { +		zlog_warn("Packet too short ( < %d)", ISIS_PSNP_HDRLEN); +		return ISIS_WARNING; +	} -  return process_snp (ISIS_SNP_PSNP_FLAG, level, circuit, ssnpa); +	return process_snp(ISIS_SNP_PSNP_FLAG, level, circuit, ssnpa);  }  /*   * PDU Dispatcher   */ -static int -isis_handle_pdu (struct isis_circuit *circuit, u_char * ssnpa) +static int isis_handle_pdu(struct isis_circuit *circuit, u_char *ssnpa)  { -  struct isis_fixed_hdr *hdr; +	struct isis_fixed_hdr *hdr; -  int retval = ISIS_OK; +	int retval = ISIS_OK; -  /* -   * Let's first read data from stream to the header -   */ -  hdr = (struct isis_fixed_hdr *) STREAM_DATA (circuit->rcv_stream); +	/* +	 * Let's first read data from stream to the header +	 */ +	hdr = (struct isis_fixed_hdr *)STREAM_DATA(circuit->rcv_stream); -  if ((hdr->idrp != ISO10589_ISIS) && (hdr->idrp != ISO9542_ESIS)) -    { -      zlog_err ("Not an IS-IS or ES-IS packet IDRP=%02x", hdr->idrp); -      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); +		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); -      return ISIS_ERROR; -    } -  stream_set_getp (circuit->rcv_stream, ISIS_FIXED_HDR_LEN); +	/* 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); +		return ISIS_ERROR; +	} +	stream_set_getp(circuit->rcv_stream, ISIS_FIXED_HDR_LEN); -  /* -   * and then process it -   */ +	/* +	 * and then process it +	 */ -  if (hdr->length < ISIS_MINIMUM_FIXED_HDR_LEN) -    { -      zlog_err ("Fixed header length = %d", hdr->length); -      return ISIS_ERROR; -    } +	if (hdr->length < ISIS_MINIMUM_FIXED_HDR_LEN) { +		zlog_err("Fixed header length = %d", hdr->length); +		return ISIS_ERROR; +	} -  if (hdr->version1 != 1) -    { -      zlog_warn ("Unsupported ISIS version %u", hdr->version1); -      return ISIS_WARNING; -    } -  /* either 6 or 0 */ -  if ((hdr->id_len != 0) && (hdr->id_len != ISIS_SYS_ID_LEN)) -    { -      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); -      return ISIS_ERROR; -    } +	if (hdr->version1 != 1) { +		zlog_warn("Unsupported ISIS version %u", hdr->version1); +		return ISIS_WARNING; +	} +	/* either 6 or 0 */ +	if ((hdr->id_len != 0) && (hdr->id_len != ISIS_SYS_ID_LEN)) { +		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); +		return ISIS_ERROR; +	} -  if (hdr->version2 != 1) -    { -      zlog_warn ("Unsupported ISIS version %u", hdr->version2); -      return ISIS_WARNING; -    } +	if (hdr->version2 != 1) { +		zlog_warn("Unsupported ISIS version %u", hdr->version2); +		return ISIS_WARNING; +	} -  if (circuit->is_passive) -    { -      zlog_warn ("Received ISIS PDU on passive circuit %s", -		 circuit->interface->name); -      return ISIS_WARNING; -    } +	if (circuit->is_passive) { +		zlog_warn("Received ISIS PDU on passive circuit %s", +			  circuit->interface->name); +		return ISIS_WARNING; +	} -  /* either 3 or 0 */ -  if ((hdr->max_area_addrs != 0) -      && (hdr->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); -      return ISIS_ERROR; -    } +	/* either 3 or 0 */ +	if ((hdr->max_area_addrs != 0) +	    && (hdr->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); +		return ISIS_ERROR; +	} -  switch (hdr->pdu_type) -    { -    case L1_LAN_HELLO: -      retval = process_lan_hello (ISIS_LEVEL1, circuit, ssnpa); -      break; -    case L2_LAN_HELLO: -      retval = process_lan_hello (ISIS_LEVEL2, circuit, ssnpa); -      break; -    case P2P_HELLO: -      retval = process_p2p_hello (circuit); -      break; -    case L1_LINK_STATE: -      retval = process_lsp (ISIS_LEVEL1, circuit, ssnpa); -      break; -    case L2_LINK_STATE: -      retval = process_lsp (ISIS_LEVEL2, circuit, ssnpa); -      break; -    case L1_COMPLETE_SEQ_NUM: -      retval = process_csnp (ISIS_LEVEL1, circuit, ssnpa); -      break; -    case L2_COMPLETE_SEQ_NUM: -      retval = process_csnp (ISIS_LEVEL2, circuit, ssnpa); -      break; -    case L1_PARTIAL_SEQ_NUM: -      retval = process_psnp (ISIS_LEVEL1, circuit, ssnpa); -      break; -    case L2_PARTIAL_SEQ_NUM: -      retval = process_psnp (ISIS_LEVEL2, circuit, ssnpa); -      break; -    default: -      return ISIS_ERROR; -    } +	switch (hdr->pdu_type) { +	case L1_LAN_HELLO: +		retval = process_lan_hello(ISIS_LEVEL1, circuit, ssnpa); +		break; +	case L2_LAN_HELLO: +		retval = process_lan_hello(ISIS_LEVEL2, circuit, ssnpa); +		break; +	case P2P_HELLO: +		retval = process_p2p_hello(circuit); +		break; +	case L1_LINK_STATE: +		retval = process_lsp(ISIS_LEVEL1, circuit, ssnpa); +		break; +	case L2_LINK_STATE: +		retval = process_lsp(ISIS_LEVEL2, circuit, ssnpa); +		break; +	case L1_COMPLETE_SEQ_NUM: +		retval = process_csnp(ISIS_LEVEL1, circuit, ssnpa); +		break; +	case L2_COMPLETE_SEQ_NUM: +		retval = process_csnp(ISIS_LEVEL2, circuit, ssnpa); +		break; +	case L1_PARTIAL_SEQ_NUM: +		retval = process_psnp(ISIS_LEVEL1, circuit, ssnpa); +		break; +	case L2_PARTIAL_SEQ_NUM: +		retval = process_psnp(ISIS_LEVEL2, circuit, ssnpa); +		break; +	default: +		return ISIS_ERROR; +	} -  return retval; +	return retval;  } -int -isis_receive (struct thread *thread) +int isis_receive(struct thread *thread)  { -  struct isis_circuit *circuit; -  u_char ssnpa[ETH_ALEN]; -  int retval; +	struct isis_circuit *circuit; +	u_char ssnpa[ETH_ALEN]; +	int retval; -  /* -   * Get the circuit  -   */ -  circuit = THREAD_ARG (thread); -  assert (circuit); +	/* +	 * Get the circuit +	 */ +	circuit = THREAD_ARG(thread); +	assert(circuit); -  circuit->t_read = NULL; +	circuit->t_read = NULL; -  isis_circuit_stream(circuit, &circuit->rcv_stream); +	isis_circuit_stream(circuit, &circuit->rcv_stream); -  retval = circuit->rx (circuit, ssnpa); +	retval = circuit->rx(circuit, ssnpa); -  if (retval == ISIS_OK) -    retval = isis_handle_pdu (circuit, ssnpa); +	if (retval == ISIS_OK) +		retval = isis_handle_pdu(circuit, ssnpa); -  /*  -   * prepare for next packet.  -   */ -  if (!circuit->is_passive) -    isis_circuit_prepare (circuit); +	/* +	 * prepare for next packet. +	 */ +	if (!circuit->is_passive) +		isis_circuit_prepare(circuit); -  return retval; +	return retval;  } - /* filling of the fixed isis header */ -void -fill_fixed_hdr (struct isis_fixed_hdr *hdr, u_char pdu_type) +/* 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 */ +	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                              + * SEND SIDE   */ -static void -fill_fixed_hdr_andstream (struct isis_fixed_hdr *hdr, u_char pdu_type, -			  struct stream *stream) +static void fill_fixed_hdr_andstream(struct isis_fixed_hdr *hdr, +				     u_char 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; +	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;  } -int -send_hello (struct isis_circuit *circuit, int level) +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]; -  size_t len_pointer, length, auth_tlv_offset = 0; -  u_int32_t interval; -  int retval; - -  if (circuit->is_passive) -    return ISIS_OK; - -  if (circuit->interface->mtu == 0) -    { -      zlog_warn ("circuit has zero MTU"); -      return ISIS_WARNING; -    } - -  isis_circuit_stream(circuit, &circuit->snd_stream); - -  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); -  else -    fill_fixed_hdr_andstream (&fixed_hdr, P2P_HELLO, circuit->snd_stream); - -  /* -   * Fill LAN Level 1 or 2 Hello PDU header -   */ -  memset (&hello_hdr, 0, sizeof (struct isis_lan_hello_hdr)); -  interval = circuit->hello_multiplier[level - 1] * -    circuit->hello_interval[level - 1]; -  if (interval > USHRT_MAX) -    interval = USHRT_MAX; -  hello_hdr.circuit_t = circuit->is_type; -  memcpy (hello_hdr.source_id, isis->sysid, ISIS_SYS_ID_LEN); -  hello_hdr.hold_time = htons ((u_int16_t) interval); - -  hello_hdr.pdu_len = 0;	/* Update the PDU Length later */ -  len_pointer = stream_get_endp (circuit->snd_stream) + 3 + ISIS_SYS_ID_LEN; - -  /* copy the shared part of the hello to the p2p hello if needed */ -  if (circuit->circ_type == CIRCUIT_T_P2P) -    { -      memcpy (&p2p_hello_hdr, &hello_hdr, 5 + ISIS_SYS_ID_LEN); -      p2p_hello_hdr.local_id = circuit->circuit_id; -      /* FIXME: need better understanding */ -      stream_put (circuit->snd_stream, &p2p_hello_hdr, ISIS_P2PHELLO_HDRLEN); -    } -  else -    { -      hello_hdr.prio = circuit->priority[level - 1]; -      if (level == IS_LEVEL_1) -	{ -	  memcpy (hello_hdr.lan_id, circuit->u.bc.l1_desig_is, -		  ISIS_SYS_ID_LEN + 1); +	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]; +	size_t len_pointer, length, auth_tlv_offset = 0; +	u_int32_t interval; +	int retval; + +	if (circuit->is_passive) +		return ISIS_OK; + +	if (circuit->interface->mtu == 0) { +		zlog_warn("circuit has zero MTU"); +		return ISIS_WARNING;  	} -      else if (level == IS_LEVEL_2) -	{ -	  memcpy (hello_hdr.lan_id, circuit->u.bc.l2_desig_is, -		  ISIS_SYS_ID_LEN + 1); -	} -      stream_put (circuit->snd_stream, &hello_hdr, ISIS_LANHELLO_HDRLEN); -    } - -  /* -   * Then the variable length part. -   */ - -  /* add circuit password */ -  switch (circuit->passwd.type) -  { -    /* Cleartext */ -    case ISIS_PASSWD_TYPE_CLEARTXT: -      if (tlv_add_authinfo (circuit->passwd.type, circuit->passwd.len, -                            circuit->passwd.passwd, circuit->snd_stream)) -        return ISIS_WARNING; -      break; - -    /* HMAC MD5 */ -    case ISIS_PASSWD_TYPE_HMAC_MD5: -      /* Remember where TLV is written so we can later overwrite the MD5 hash */ -      auth_tlv_offset = stream_get_endp (circuit->snd_stream); -      memset(&hmac_md5_hash, 0, ISIS_AUTH_MD5_SIZE); -      if (tlv_add_authinfo (circuit->passwd.type, ISIS_AUTH_MD5_SIZE, -                            hmac_md5_hash, circuit->snd_stream)) -        return ISIS_WARNING; -      break; - -    default: -      break; -  } - -  /*  Area Addresses TLV */ -  if (listcount (circuit->area->area_addrs) == 0) -    return ISIS_WARNING; -  if (tlv_add_area_addrs (circuit->area->area_addrs, circuit->snd_stream)) -    return ISIS_WARNING; - -  /*  LAN Neighbors TLV */ -  if (circuit->circ_type == CIRCUIT_T_BROADCAST) -    { -      if (level == IS_LEVEL_1 && circuit->u.bc.lan_neighs[0] && -          listcount (circuit->u.bc.lan_neighs[0]) > 0) -	if (tlv_add_lan_neighs (circuit->u.bc.lan_neighs[0], -				circuit->snd_stream)) -	  return ISIS_WARNING; -      if (level == IS_LEVEL_2 && circuit->u.bc.lan_neighs[1] && -          listcount (circuit->u.bc.lan_neighs[1]) > 0) -	if (tlv_add_lan_neighs (circuit->u.bc.lan_neighs[1], -				circuit->snd_stream)) -	  return ISIS_WARNING; -    } - -  /* Protocols Supported TLV */ -  if (circuit->nlpids.count > 0) -    if (tlv_add_nlpid (&circuit->nlpids, circuit->snd_stream)) -      return ISIS_WARNING; -  /* IP interface Address TLV */ -  if (circuit->ip_router && circuit->ip_addrs && -      listcount (circuit->ip_addrs) > 0) -    if (tlv_add_ip_addrs (circuit->ip_addrs, circuit->snd_stream)) -      return ISIS_WARNING; -  /* IPv6 Interface Address TLV */ -  if (circuit->ipv6_router && circuit->ipv6_link && -      listcount (circuit->ipv6_link) > 0) -    if (tlv_add_ipv6_addrs (circuit->ipv6_link, circuit->snd_stream)) -      return ISIS_WARNING; +	isis_circuit_stream(circuit, &circuit->snd_stream); -  if (circuit->pad_hellos) -    if (tlv_add_padding (circuit->snd_stream)) -      return ISIS_WARNING; +	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); +	else +		fill_fixed_hdr_andstream(&fixed_hdr, P2P_HELLO, +					 circuit->snd_stream); + +	/* +	 * Fill LAN Level 1 or 2 Hello PDU header +	 */ +	memset(&hello_hdr, 0, sizeof(struct isis_lan_hello_hdr)); +	interval = circuit->hello_multiplier[level - 1] +		   * circuit->hello_interval[level - 1]; +	if (interval > USHRT_MAX) +		interval = USHRT_MAX; +	hello_hdr.circuit_t = circuit->is_type; +	memcpy(hello_hdr.source_id, isis->sysid, ISIS_SYS_ID_LEN); +	hello_hdr.hold_time = htons((u_int16_t)interval); + +	hello_hdr.pdu_len = 0; /* Update the PDU Length later */ +	len_pointer = +		stream_get_endp(circuit->snd_stream) + 3 + ISIS_SYS_ID_LEN; + +	/* copy the shared part of the hello to the p2p hello if needed */ +	if (circuit->circ_type == CIRCUIT_T_P2P) { +		memcpy(&p2p_hello_hdr, &hello_hdr, 5 + ISIS_SYS_ID_LEN); +		p2p_hello_hdr.local_id = circuit->circuit_id; +		/* FIXME: need better understanding */ +		stream_put(circuit->snd_stream, &p2p_hello_hdr, +			   ISIS_P2PHELLO_HDRLEN); +	} else { +		hello_hdr.prio = circuit->priority[level - 1]; +		if (level == IS_LEVEL_1) { +			memcpy(hello_hdr.lan_id, circuit->u.bc.l1_desig_is, +			       ISIS_SYS_ID_LEN + 1); +		} else if (level == IS_LEVEL_2) { +			memcpy(hello_hdr.lan_id, circuit->u.bc.l2_desig_is, +			       ISIS_SYS_ID_LEN + 1); +		} +		stream_put(circuit->snd_stream, &hello_hdr, +			   ISIS_LANHELLO_HDRLEN); +	} -  length = stream_get_endp (circuit->snd_stream); -  /* Update PDU length */ -  stream_putw_at (circuit->snd_stream, len_pointer, (u_int16_t) length); +	/* +	 * Then the variable length part. +	 */ + +	/* add circuit password */ +	switch (circuit->passwd.type) { +	/* Cleartext */ +	case ISIS_PASSWD_TYPE_CLEARTXT: +		if (tlv_add_authinfo(circuit->passwd.type, circuit->passwd.len, +				     circuit->passwd.passwd, +				     circuit->snd_stream)) +			return ISIS_WARNING; +		break; + +	/* HMAC MD5 */ +	case ISIS_PASSWD_TYPE_HMAC_MD5: +		/* Remember where TLV is written so we can later overwrite the +		 * MD5 hash */ +		auth_tlv_offset = stream_get_endp(circuit->snd_stream); +		memset(&hmac_md5_hash, 0, ISIS_AUTH_MD5_SIZE); +		if (tlv_add_authinfo(circuit->passwd.type, ISIS_AUTH_MD5_SIZE, +				     hmac_md5_hash, circuit->snd_stream)) +			return ISIS_WARNING; +		break; + +	default: +		break; +	} -  /* For HMAC MD5 we need to compute the md5 hash and store it */ -  if (circuit->passwd.type == ISIS_PASSWD_TYPE_HMAC_MD5) -    { -      hmac_md5 (STREAM_DATA (circuit->snd_stream), -                stream_get_endp (circuit->snd_stream), -                (unsigned char *) &circuit->passwd.passwd, circuit->passwd.len, -                (unsigned char *) &hmac_md5_hash); -      /* Copy the hash into the stream */ -      memcpy (STREAM_DATA (circuit->snd_stream) + auth_tlv_offset + 3, -              hmac_md5_hash, ISIS_AUTH_MD5_SIZE); -    } +	/*  Area Addresses TLV */ +	if (listcount(circuit->area->area_addrs) == 0) +		return ISIS_WARNING; +	if (tlv_add_area_addrs(circuit->area->area_addrs, circuit->snd_stream)) +		return ISIS_WARNING; + +	/*  LAN Neighbors TLV */ +	if (circuit->circ_type == CIRCUIT_T_BROADCAST) { +		if (level == IS_LEVEL_1 && circuit->u.bc.lan_neighs[0] +		    && listcount(circuit->u.bc.lan_neighs[0]) > 0) +			if (tlv_add_lan_neighs(circuit->u.bc.lan_neighs[0], +					       circuit->snd_stream)) +				return ISIS_WARNING; +		if (level == IS_LEVEL_2 && circuit->u.bc.lan_neighs[1] +		    && listcount(circuit->u.bc.lan_neighs[1]) > 0) +			if (tlv_add_lan_neighs(circuit->u.bc.lan_neighs[1], +					       circuit->snd_stream)) +				return ISIS_WARNING; +	} -  if (isis->debugs & DEBUG_ADJ_PACKETS) -    { -      if (circuit->circ_type == CIRCUIT_T_BROADCAST) -	{ -	  zlog_debug ("ISIS-Adj (%s): Sending L%d LAN IIH on %s, length %zd", -		      circuit->area->area_tag, level, circuit->interface->name, -		      length); +	/* Protocols Supported TLV */ +	if (circuit->nlpids.count > 0) +		if (tlv_add_nlpid(&circuit->nlpids, circuit->snd_stream)) +			return ISIS_WARNING; +	/* IP interface Address TLV */ +	if (circuit->ip_router && circuit->ip_addrs +	    && listcount(circuit->ip_addrs) > 0) +		if (tlv_add_ip_addrs(circuit->ip_addrs, circuit->snd_stream)) +			return ISIS_WARNING; + +	/* IPv6 Interface Address TLV */ +	if (circuit->ipv6_router && circuit->ipv6_link +	    && listcount(circuit->ipv6_link) > 0) +		if (tlv_add_ipv6_addrs(circuit->ipv6_link, circuit->snd_stream)) +			return ISIS_WARNING; + +	if (circuit->pad_hellos) +		if (tlv_add_padding(circuit->snd_stream)) +			return ISIS_WARNING; + +	length = stream_get_endp(circuit->snd_stream); +	/* Update PDU length */ +	stream_putw_at(circuit->snd_stream, len_pointer, (u_int16_t)length); + +	/* For HMAC MD5 we need to compute the md5 hash and store it */ +	if (circuit->passwd.type == ISIS_PASSWD_TYPE_HMAC_MD5) { +		hmac_md5(STREAM_DATA(circuit->snd_stream), +			 stream_get_endp(circuit->snd_stream), +			 (unsigned char *)&circuit->passwd.passwd, +			 circuit->passwd.len, (unsigned char *)&hmac_md5_hash); +		/* Copy the hash into the stream */ +		memcpy(STREAM_DATA(circuit->snd_stream) + auth_tlv_offset + 3, +		       hmac_md5_hash, ISIS_AUTH_MD5_SIZE);  	} -      else -	{ -	  zlog_debug ("ISIS-Adj (%s): Sending P2P IIH on %s, length %zd", -		      circuit->area->area_tag, circuit->interface->name, -		      length); + +	if (isis->debugs & DEBUG_ADJ_PACKETS) { +		if (circuit->circ_type == CIRCUIT_T_BROADCAST) { +			zlog_debug( +				"ISIS-Adj (%s): Sending L%d LAN IIH on %s, length %zd", +				circuit->area->area_tag, level, +				circuit->interface->name, length); +		} else { +			zlog_debug( +				"ISIS-Adj (%s): Sending P2P IIH on %s, length %zd", +				circuit->area->area_tag, +				circuit->interface->name, length); +		} +		if (isis->debugs & DEBUG_PACKET_DUMP) +			zlog_dump_data(STREAM_DATA(circuit->snd_stream), +				       stream_get_endp(circuit->snd_stream));  	} -      if (isis->debugs & DEBUG_PACKET_DUMP) -        zlog_dump_data (STREAM_DATA (circuit->snd_stream), -                        stream_get_endp (circuit->snd_stream)); -    } -  retval = circuit->tx (circuit, level); -  if (retval != ISIS_OK) -    zlog_err ("ISIS-Adj (%s): Send L%d IIH on %s failed", -              circuit->area->area_tag, level, circuit->interface->name); +	retval = circuit->tx(circuit, level); +	if (retval != ISIS_OK) +		zlog_err("ISIS-Adj (%s): Send L%d IIH on %s failed", +			 circuit->area->area_tag, level, +			 circuit->interface->name); -  return retval; +	return retval;  } -int -send_lan_l1_hello (struct thread *thread) +int send_lan_l1_hello(struct thread *thread)  { -  struct isis_circuit *circuit; -  int retval; - -  circuit = THREAD_ARG (thread); -  assert (circuit); -  circuit->u.bc.t_send_lan_hello[0] = NULL; - -  if (!(circuit->area->is_type & IS_LEVEL_1)) -    { -      zlog_warn ("ISIS-Hello (%s): Trying to send L1 IIH in L2-only area", -		 circuit->area->area_tag); -      return 1; -    } +	struct isis_circuit *circuit; +	int retval; + +	circuit = THREAD_ARG(thread); +	assert(circuit); +	circuit->u.bc.t_send_lan_hello[0] = NULL; + +	if (!(circuit->area->is_type & IS_LEVEL_1)) { +		zlog_warn( +			"ISIS-Hello (%s): Trying to send L1 IIH in L2-only area", +			circuit->area->area_tag); +		return 1; +	} -  if (circuit->u.bc.run_dr_elect[0]) -    isis_dr_elect (circuit, 1); +	if (circuit->u.bc.run_dr_elect[0]) +		isis_dr_elect(circuit, 1); -  retval = send_hello (circuit, 1); +	retval = send_hello(circuit, 1); -  /* set next timer thread */ -  THREAD_TIMER_ON (master, circuit->u.bc.t_send_lan_hello[0], -		   send_lan_l1_hello, circuit, -		   isis_jitter (circuit->hello_interval[0], IIH_JITTER)); +	/* set next timer thread */ +	THREAD_TIMER_ON(master, circuit->u.bc.t_send_lan_hello[0], +			send_lan_l1_hello, circuit, +			isis_jitter(circuit->hello_interval[0], IIH_JITTER)); -  return retval; +	return retval;  } -int -send_lan_l2_hello (struct thread *thread) +int send_lan_l2_hello(struct thread *thread)  { -  struct isis_circuit *circuit; -  int retval; +	struct isis_circuit *circuit; +	int retval; -  circuit = THREAD_ARG (thread); -  assert (circuit); -  circuit->u.bc.t_send_lan_hello[1] = NULL; +	circuit = THREAD_ARG(thread); +	assert(circuit); +	circuit->u.bc.t_send_lan_hello[1] = NULL; -  if (!(circuit->area->is_type & IS_LEVEL_2)) -    { -      zlog_warn ("ISIS-Hello (%s): Trying to send L2 IIH in L1 area", -		 circuit->area->area_tag); -      return 1; -    } +	if (!(circuit->area->is_type & IS_LEVEL_2)) { +		zlog_warn("ISIS-Hello (%s): Trying to send L2 IIH in L1 area", +			  circuit->area->area_tag); +		return 1; +	} -  if (circuit->u.bc.run_dr_elect[1]) -    isis_dr_elect (circuit, 2); +	if (circuit->u.bc.run_dr_elect[1]) +		isis_dr_elect(circuit, 2); -  retval = send_hello (circuit, 2); +	retval = send_hello(circuit, 2); -  /* set next timer thread */ -  THREAD_TIMER_ON (master, circuit->u.bc.t_send_lan_hello[1], -		   send_lan_l2_hello, circuit, -		   isis_jitter (circuit->hello_interval[1], IIH_JITTER)); +	/* set next timer thread */ +	THREAD_TIMER_ON(master, circuit->u.bc.t_send_lan_hello[1], +			send_lan_l2_hello, circuit, +			isis_jitter(circuit->hello_interval[1], IIH_JITTER)); -  return retval; +	return retval;  } -int -send_p2p_hello (struct thread *thread) +int send_p2p_hello(struct thread *thread)  { -  struct isis_circuit *circuit; +	struct isis_circuit *circuit; -  circuit = THREAD_ARG (thread); -  assert (circuit); -  circuit->u.p2p.t_send_p2p_hello = NULL; +	circuit = THREAD_ARG(thread); +	assert(circuit); +	circuit->u.p2p.t_send_p2p_hello = NULL; -  send_hello (circuit, 1); +	send_hello(circuit, 1); -  /* set next timer thread */ -  THREAD_TIMER_ON (master, circuit->u.p2p.t_send_p2p_hello, send_p2p_hello, -		   circuit, isis_jitter (circuit->hello_interval[1], -					 IIH_JITTER)); +	/* set next timer thread */ +	THREAD_TIMER_ON(master, circuit->u.p2p.t_send_p2p_hello, send_p2p_hello, +			circuit, +			isis_jitter(circuit->hello_interval[1], IIH_JITTER)); -  return ISIS_OK; +	return ISIS_OK;  } -static int -build_csnp (int level, u_char * start, u_char * stop, struct list *lsps, -	    struct isis_circuit *circuit) +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; - -  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 Level 1 or 2 Complete Sequence Numbers header -   */ - -  lenp = stream_get_endp (circuit->snd_stream); -  stream_putw (circuit->snd_stream, 0);	/* PDU length - when we know it */ -  /* no need to send the source here, it is always us if we csnp */ -  stream_put (circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN); -  /* with zero circuit id - ref 9.10, 9.11 */ -  stream_putc (circuit->snd_stream, 0x00); - -  stream_put (circuit->snd_stream, start, ISIS_SYS_ID_LEN + 2); -  stream_put (circuit->snd_stream, stop, ISIS_SYS_ID_LEN + 2); - -  /* -   * And TLVs -   */ -  if (level == IS_LEVEL_1) -    passwd = &circuit->area->area_passwd; -  else -    passwd = &circuit->area->domain_passwd; - -  if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND)) -  { -    switch (passwd->type) -    { -      /* Cleartext */ -      case ISIS_PASSWD_TYPE_CLEARTXT: -        if (tlv_add_authinfo (ISIS_PASSWD_TYPE_CLEARTXT, passwd->len, -                              passwd->passwd, circuit->snd_stream)) -          return ISIS_WARNING; -        break; - -        /* HMAC MD5 */ -      case ISIS_PASSWD_TYPE_HMAC_MD5: -        /* Remember where TLV is written so we can later overwrite the MD5 hash */ -        auth_tlv_offset = stream_get_endp (circuit->snd_stream); -        memset(&hmac_md5_hash, 0, ISIS_AUTH_MD5_SIZE); -        if (tlv_add_authinfo (ISIS_PASSWD_TYPE_HMAC_MD5, ISIS_AUTH_MD5_SIZE, -                              hmac_md5_hash, circuit->snd_stream)) -          return ISIS_WARNING; -        break; - -      default: -        break; -    } -  } - -  retval = tlv_add_lsp_entries (lsps, circuit->snd_stream); -  if (retval != ISIS_OK) -    return retval; - -  length = (u_int16_t) stream_get_endp (circuit->snd_stream); -  /* Update PU length */ -  stream_putw_at (circuit->snd_stream, lenp, length); +	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; + +	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 Level 1 or 2 Complete Sequence Numbers header +	 */ + +	lenp = stream_get_endp(circuit->snd_stream); +	stream_putw(circuit->snd_stream, 0); /* PDU length - when we know it */ +	/* no need to send the source here, it is always us if we csnp */ +	stream_put(circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN); +	/* with zero circuit id - ref 9.10, 9.11 */ +	stream_putc(circuit->snd_stream, 0x00); + +	stream_put(circuit->snd_stream, start, ISIS_SYS_ID_LEN + 2); +	stream_put(circuit->snd_stream, stop, ISIS_SYS_ID_LEN + 2); + +	/* +	 * And TLVs +	 */ +	if (level == IS_LEVEL_1) +		passwd = &circuit->area->area_passwd; +	else +		passwd = &circuit->area->domain_passwd; + +	if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND)) { +		switch (passwd->type) { +		/* Cleartext */ +		case ISIS_PASSWD_TYPE_CLEARTXT: +			if (tlv_add_authinfo(ISIS_PASSWD_TYPE_CLEARTXT, +					     passwd->len, passwd->passwd, +					     circuit->snd_stream)) +				return ISIS_WARNING; +			break; + +		/* HMAC MD5 */ +		case ISIS_PASSWD_TYPE_HMAC_MD5: +			/* Remember where TLV is written so we can later +			 * overwrite the MD5 hash */ +			auth_tlv_offset = stream_get_endp(circuit->snd_stream); +			memset(&hmac_md5_hash, 0, ISIS_AUTH_MD5_SIZE); +			if (tlv_add_authinfo(ISIS_PASSWD_TYPE_HMAC_MD5, +					     ISIS_AUTH_MD5_SIZE, hmac_md5_hash, +					     circuit->snd_stream)) +				return ISIS_WARNING; +			break; + +		default: +			break; +		} +	} -  /* For HMAC MD5 we need to compute the md5 hash and store it */ -  if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND) && -      passwd->type == ISIS_PASSWD_TYPE_HMAC_MD5) -    { -      hmac_md5 (STREAM_DATA (circuit->snd_stream), -                stream_get_endp(circuit->snd_stream), -                (unsigned char *) &passwd->passwd, passwd->len, -                (unsigned char *) &hmac_md5_hash); -      /* Copy the hash into the stream */ -      memcpy (STREAM_DATA (circuit->snd_stream) + auth_tlv_offset + 3, -              hmac_md5_hash, ISIS_AUTH_MD5_SIZE); -    } +	retval = tlv_add_lsp_entries(lsps, circuit->snd_stream); +	if (retval != ISIS_OK) +		return retval; + +	length = (u_int16_t)stream_get_endp(circuit->snd_stream); +	/* Update PU length */ +	stream_putw_at(circuit->snd_stream, lenp, length); + +	/* For HMAC MD5 we need to compute the md5 hash and store it */ +	if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND) +	    && passwd->type == ISIS_PASSWD_TYPE_HMAC_MD5) { +		hmac_md5(STREAM_DATA(circuit->snd_stream), +			 stream_get_endp(circuit->snd_stream), +			 (unsigned char *)&passwd->passwd, passwd->len, +			 (unsigned char *)&hmac_md5_hash); +		/* Copy the hash into the stream */ +		memcpy(STREAM_DATA(circuit->snd_stream) + auth_tlv_offset + 3, +		       hmac_md5_hash, ISIS_AUTH_MD5_SIZE); +	} -  return retval; +	return retval;  }  /*   * Count the maximum number of lsps that can be accomodated by a given size.   */ -static uint16_t -get_max_lsp_count (uint16_t size) +static uint16_t get_max_lsp_count(uint16_t size)  { -  uint16_t tlv_count; -  uint16_t lsp_count; -  uint16_t remaining_size; +	uint16_t tlv_count; +	uint16_t lsp_count; +	uint16_t remaining_size; -  /* First count the full size TLVs */ -  tlv_count = size / MAX_LSP_ENTRIES_TLV_SIZE; -  lsp_count = tlv_count * (MAX_LSP_ENTRIES_TLV_SIZE / LSP_ENTRIES_LEN); +	/* First count the full size TLVs */ +	tlv_count = size / MAX_LSP_ENTRIES_TLV_SIZE; +	lsp_count = tlv_count * (MAX_LSP_ENTRIES_TLV_SIZE / LSP_ENTRIES_LEN); -  /* The last TLV, if any */ -  remaining_size = size % MAX_LSP_ENTRIES_TLV_SIZE; -  if (remaining_size - 2 >= LSP_ENTRIES_LEN) -    lsp_count += (remaining_size - 2) / LSP_ENTRIES_LEN; +	/* The last TLV, if any */ +	remaining_size = size % MAX_LSP_ENTRIES_TLV_SIZE; +	if (remaining_size - 2 >= LSP_ENTRIES_LEN) +		lsp_count += (remaining_size - 2) / LSP_ENTRIES_LEN; -  return lsp_count; +	return lsp_count;  }  /*   * Calculate the length of Authentication Info. TLV.   */ -static uint16_t -auth_tlv_length (int level, struct isis_circuit *circuit) +static uint16_t auth_tlv_length(int level, struct isis_circuit *circuit)  { -  struct isis_passwd *passwd; -  uint16_t length; - -  if (level == IS_LEVEL_1) -    passwd = &circuit->area->area_passwd; -  else -    passwd = &circuit->area->domain_passwd; - -  /* Also include the length of TLV header */ -  length = AUTH_INFO_HDRLEN; -  if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND)) -  { -    switch (passwd->type) -    { -      /* Cleartext */ -      case ISIS_PASSWD_TYPE_CLEARTXT: -        length += passwd->len; -        break; - -        /* HMAC MD5 */ -      case ISIS_PASSWD_TYPE_HMAC_MD5: -        length += ISIS_AUTH_MD5_SIZE; -        break; - -      default: -        break; -    } -  } +	struct isis_passwd *passwd; +	uint16_t length; + +	if (level == IS_LEVEL_1) +		passwd = &circuit->area->area_passwd; +	else +		passwd = &circuit->area->domain_passwd; + +	/* Also include the length of TLV header */ +	length = AUTH_INFO_HDRLEN; +	if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND)) { +		switch (passwd->type) { +		/* Cleartext */ +		case ISIS_PASSWD_TYPE_CLEARTXT: +			length += passwd->len; +			break; + +		/* HMAC MD5 */ +		case ISIS_PASSWD_TYPE_HMAC_MD5: +			length += ISIS_AUTH_MD5_SIZE; +			break; + +		default: +			break; +		} +	} -  return length; +	return length;  }  /*   * Calculate the maximum number of lsps that can be accomodated in a CSNP/PSNP.   */ -static uint16_t -max_lsps_per_snp (int snp_type, int level, struct isis_circuit *circuit) +static uint16_t max_lsps_per_snp(int snp_type, int level, +				 struct isis_circuit *circuit)  { -  int snp_hdr_len; -  int auth_tlv_len; -  uint16_t lsp_count; - -  snp_hdr_len = ISIS_FIXED_HDR_LEN; -  if (snp_type == ISIS_SNP_CSNP_FLAG) -    snp_hdr_len += ISIS_CSNP_HDRLEN; -  else -    snp_hdr_len += ISIS_PSNP_HDRLEN; - -  auth_tlv_len = auth_tlv_length (level, circuit); -  lsp_count = get_max_lsp_count ( -      stream_get_size (circuit->snd_stream) - snp_hdr_len - auth_tlv_len); -  return lsp_count; +	int snp_hdr_len; +	int auth_tlv_len; +	uint16_t lsp_count; + +	snp_hdr_len = ISIS_FIXED_HDR_LEN; +	if (snp_type == ISIS_SNP_CSNP_FLAG) +		snp_hdr_len += ISIS_CSNP_HDRLEN; +	else +		snp_hdr_len += ISIS_PSNP_HDRLEN; + +	auth_tlv_len = auth_tlv_length(level, circuit); +	lsp_count = get_max_lsp_count(stream_get_size(circuit->snd_stream) +				      - snp_hdr_len - auth_tlv_len); +	return lsp_count;  }  /*   * FIXME: support multiple CSNPs   */ -int -send_csnp (struct isis_circuit *circuit, int level) +int send_csnp(struct isis_circuit *circuit, int level)  { -  u_char start[ISIS_SYS_ID_LEN + 2]; -  u_char stop[ISIS_SYS_ID_LEN + 2]; -  struct list *list = NULL; -  struct listnode *node; -  struct isis_lsp *lsp; -  u_char num_lsps, loop = 1; -  int i, retval = ISIS_OK; +	u_char start[ISIS_SYS_ID_LEN + 2]; +	u_char stop[ISIS_SYS_ID_LEN + 2]; +	struct list *list = NULL; +	struct listnode *node; +	struct isis_lsp *lsp; +	u_char num_lsps, loop = 1; +	int i, retval = ISIS_OK; + +	if (circuit->area->lspdb[level - 1] == NULL +	    || dict_count(circuit->area->lspdb[level - 1]) == 0) +		return retval; + +	memset(start, 0x00, ISIS_SYS_ID_LEN + 2); +	memset(stop, 0xff, ISIS_SYS_ID_LEN + 2); + +	num_lsps = max_lsps_per_snp(ISIS_SNP_CSNP_FLAG, level, circuit); + +	while (loop) { +		list = list_new(); +		lsp_build_list(start, stop, num_lsps, list, +			       circuit->area->lspdb[level - 1]); +		/* +		 * Update the stop lsp_id before encoding this CSNP. +		 */ +		if (listcount(list) < num_lsps) { +			memset(stop, 0xff, ISIS_SYS_ID_LEN + 2); +		} else { +			node = listtail(list); +			lsp = listgetdata(node); +			memcpy(stop, lsp->lsp_header->lsp_id, +			       ISIS_SYS_ID_LEN + 2); +		} -  if (circuit->area->lspdb[level - 1] == NULL || -      dict_count (circuit->area->lspdb[level - 1]) == 0) -    return retval; +		retval = build_csnp(level, start, stop, list, circuit); +		if (retval != ISIS_OK) { +			zlog_err("ISIS-Snp (%s): Build L%d CSNP on %s failed", +				 circuit->area->area_tag, level, +				 circuit->interface->name); +			list_delete(list); +			return retval; +		} -  memset (start, 0x00, ISIS_SYS_ID_LEN + 2); -  memset (stop, 0xff, ISIS_SYS_ID_LEN + 2); +		if (isis->debugs & DEBUG_SNP_PACKETS) { +			zlog_debug( +				"ISIS-Snp (%s): Sending L%d CSNP on %s, length %zd", +				circuit->area->area_tag, level, +				circuit->interface->name, +				stream_get_endp(circuit->snd_stream)); +			for (ALL_LIST_ELEMENTS_RO(list, node, lsp)) { +				zlog_debug( +					"ISIS-Snp (%s):         CSNP entry %s, seq 0x%08x," +					" cksum 0x%04x, lifetime %us", +					circuit->area->area_tag, +					rawlspid_print(lsp->lsp_header->lsp_id), +					ntohl(lsp->lsp_header->seq_num), +					ntohs(lsp->lsp_header->checksum), +					ntohs(lsp->lsp_header->rem_lifetime)); +			} +			if (isis->debugs & DEBUG_PACKET_DUMP) +				zlog_dump_data( +					STREAM_DATA(circuit->snd_stream), +					stream_get_endp(circuit->snd_stream)); +		} -  num_lsps = max_lsps_per_snp (ISIS_SNP_CSNP_FLAG, level, circuit); +		retval = circuit->tx(circuit, level); +		if (retval != ISIS_OK) { +			zlog_err("ISIS-Snp (%s): Send L%d CSNP on %s failed", +				 circuit->area->area_tag, level, +				 circuit->interface->name); +			list_delete(list); +			return retval; +		} -  while (loop) -    { -      list = list_new (); -      lsp_build_list (start, stop, num_lsps, list, -                      circuit->area->lspdb[level - 1]); -      /* -       * Update the stop lsp_id before encoding this CSNP. -       */ -      if (listcount (list) < num_lsps) -        { -          memset (stop, 0xff, ISIS_SYS_ID_LEN + 2); -        } -      else -        { -          node = listtail (list); -          lsp = listgetdata (node); -          memcpy (stop, lsp->lsp_header->lsp_id, ISIS_SYS_ID_LEN + 2); -        } - -      retval = build_csnp (level, start, stop, list, circuit); -      if (retval != ISIS_OK) -        { -          zlog_err ("ISIS-Snp (%s): Build L%d CSNP on %s failed", -                    circuit->area->area_tag, level, circuit->interface->name); -          list_delete (list); -          return retval; -        } - -      if (isis->debugs & DEBUG_SNP_PACKETS) -        { -          zlog_debug ("ISIS-Snp (%s): Sending L%d CSNP on %s, length %zd", -                      circuit->area->area_tag, level, circuit->interface->name, -                      stream_get_endp (circuit->snd_stream)); -          for (ALL_LIST_ELEMENTS_RO (list, node, lsp)) -            { -              zlog_debug ("ISIS-Snp (%s):         CSNP entry %s, seq 0x%08x," -                          " cksum 0x%04x, lifetime %us", -                          circuit->area->area_tag, -                          rawlspid_print (lsp->lsp_header->lsp_id), -                          ntohl (lsp->lsp_header->seq_num), -                          ntohs (lsp->lsp_header->checksum), -                          ntohs (lsp->lsp_header->rem_lifetime)); -            } -          if (isis->debugs & DEBUG_PACKET_DUMP) -            zlog_dump_data (STREAM_DATA (circuit->snd_stream), -                            stream_get_endp (circuit->snd_stream)); -        } - -      retval = circuit->tx (circuit, level); -      if (retval != ISIS_OK) -        { -          zlog_err ("ISIS-Snp (%s): Send L%d CSNP on %s failed", -                    circuit->area->area_tag, level, -                    circuit->interface->name); -          list_delete (list); -          return retval; -        } - -      /* -       * Start lsp_id of the next CSNP should be one plus the -       * stop lsp_id in this current CSNP. -       */ -      memcpy (start, stop, ISIS_SYS_ID_LEN + 2); -      loop = 0; -      for (i = ISIS_SYS_ID_LEN + 1; i >= 0; --i) -        { -          if (start[i] < (u_char)0xff) -            { -              start[i] += 1; -              loop = 1; -              break; -            } -        } -      memset (stop, 0xff, ISIS_SYS_ID_LEN + 2); -      list_delete (list); -    } +		/* +		 * Start lsp_id of the next CSNP should be one plus the +		 * stop lsp_id in this current CSNP. +		 */ +		memcpy(start, stop, ISIS_SYS_ID_LEN + 2); +		loop = 0; +		for (i = ISIS_SYS_ID_LEN + 1; i >= 0; --i) { +			if (start[i] < (u_char)0xff) { +				start[i] += 1; +				loop = 1; +				break; +			} +		} +		memset(stop, 0xff, ISIS_SYS_ID_LEN + 2); +		list_delete(list); +	} -  return retval; +	return retval;  } -int -send_l1_csnp (struct thread *thread) +int send_l1_csnp(struct thread *thread)  { -  struct isis_circuit *circuit; -  int retval = ISIS_OK; +	struct isis_circuit *circuit; +	int retval = ISIS_OK; -  circuit = THREAD_ARG (thread); -  assert (circuit); +	circuit = THREAD_ARG(thread); +	assert(circuit); -  circuit->t_send_csnp[0] = NULL; +	circuit->t_send_csnp[0] = NULL; -  if (circuit->circ_type == CIRCUIT_T_BROADCAST && circuit->u.bc.is_dr[0]) -    { -      send_csnp (circuit, 1); -    } -  /* set next timer thread */ -  THREAD_TIMER_ON (master, circuit->t_send_csnp[0], send_l1_csnp, circuit, -		   isis_jitter (circuit->csnp_interval[0], CSNP_JITTER)); +	if (circuit->circ_type == CIRCUIT_T_BROADCAST +	    && circuit->u.bc.is_dr[0]) { +		send_csnp(circuit, 1); +	} +	/* set next timer thread */ +	THREAD_TIMER_ON(master, circuit->t_send_csnp[0], send_l1_csnp, circuit, +			isis_jitter(circuit->csnp_interval[0], CSNP_JITTER)); -  return retval; +	return retval;  } -int -send_l2_csnp (struct thread *thread) +int send_l2_csnp(struct thread *thread)  { -  struct isis_circuit *circuit; -  int retval = ISIS_OK; +	struct isis_circuit *circuit; +	int retval = ISIS_OK; -  circuit = THREAD_ARG (thread); -  assert (circuit); +	circuit = THREAD_ARG(thread); +	assert(circuit); -  circuit->t_send_csnp[1] = NULL; +	circuit->t_send_csnp[1] = NULL; -  if (circuit->circ_type == CIRCUIT_T_BROADCAST && circuit->u.bc.is_dr[1]) -    { -      send_csnp (circuit, 2); -    } -  /* set next timer thread */ -  THREAD_TIMER_ON (master, circuit->t_send_csnp[1], send_l2_csnp, circuit, -		   isis_jitter (circuit->csnp_interval[1], CSNP_JITTER)); +	if (circuit->circ_type == CIRCUIT_T_BROADCAST +	    && circuit->u.bc.is_dr[1]) { +		send_csnp(circuit, 2); +	} +	/* set next timer thread */ +	THREAD_TIMER_ON(master, circuit->t_send_csnp[1], send_l2_csnp, circuit, +			isis_jitter(circuit->csnp_interval[1], CSNP_JITTER)); -  return retval; +	return retval;  } -static int -build_psnp (int level, struct isis_circuit *circuit, struct list *lsps) +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; -  struct isis_passwd *passwd; -  struct listnode *node; -  unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE]; -  unsigned long auth_tlv_offset = 0; -  int retval = ISIS_OK; - -  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 Level 1 or 2 Partial Sequence Numbers header -   */ -  lenp = stream_get_endp (circuit->snd_stream); -  stream_putw (circuit->snd_stream, 0);	/* PDU length - when we know it */ -  stream_put (circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN); -  stream_putc (circuit->snd_stream, circuit->idx); - -  /* -   * And TLVs -   */ - -  if (level == IS_LEVEL_1) -    passwd = &circuit->area->area_passwd; -  else -    passwd = &circuit->area->domain_passwd; - -  if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND)) -  { -    switch (passwd->type) -    { -      /* Cleartext */ -      case ISIS_PASSWD_TYPE_CLEARTXT: -        if (tlv_add_authinfo (ISIS_PASSWD_TYPE_CLEARTXT, passwd->len, -                              passwd->passwd, circuit->snd_stream)) -          return ISIS_WARNING; -        break; - -        /* HMAC MD5 */ -      case ISIS_PASSWD_TYPE_HMAC_MD5: -        /* Remember where TLV is written so we can later overwrite the MD5 hash */ -        auth_tlv_offset = stream_get_endp (circuit->snd_stream); -        memset(&hmac_md5_hash, 0, ISIS_AUTH_MD5_SIZE); -        if (tlv_add_authinfo (ISIS_PASSWD_TYPE_HMAC_MD5, ISIS_AUTH_MD5_SIZE, -                              hmac_md5_hash, circuit->snd_stream)) -          return ISIS_WARNING; -        break; - -      default: -        break; -    } -  } - -  retval = tlv_add_lsp_entries (lsps, circuit->snd_stream); -  if (retval != ISIS_OK) -    return retval; - -  if (isis->debugs & DEBUG_SNP_PACKETS) -    { -      for (ALL_LIST_ELEMENTS_RO (lsps, node, lsp)) -      { -	zlog_debug ("ISIS-Snp (%s):         PSNP entry %s, seq 0x%08x," -		    " cksum 0x%04x, lifetime %us", -		    circuit->area->area_tag, -		    rawlspid_print (lsp->lsp_header->lsp_id), -		    ntohl (lsp->lsp_header->seq_num), -		    ntohs (lsp->lsp_header->checksum), -		    ntohs (lsp->lsp_header->rem_lifetime)); -      } -    } +	struct isis_fixed_hdr fixed_hdr; +	unsigned long lenp; +	u_int16_t length; +	struct isis_lsp *lsp; +	struct isis_passwd *passwd; +	struct listnode *node; +	unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE]; +	unsigned long auth_tlv_offset = 0; +	int retval = ISIS_OK; + +	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 Level 1 or 2 Partial Sequence Numbers header +	 */ +	lenp = stream_get_endp(circuit->snd_stream); +	stream_putw(circuit->snd_stream, 0); /* PDU length - when we know it */ +	stream_put(circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN); +	stream_putc(circuit->snd_stream, circuit->idx); + +	/* +	 * And TLVs +	 */ + +	if (level == IS_LEVEL_1) +		passwd = &circuit->area->area_passwd; +	else +		passwd = &circuit->area->domain_passwd; + +	if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND)) { +		switch (passwd->type) { +		/* Cleartext */ +		case ISIS_PASSWD_TYPE_CLEARTXT: +			if (tlv_add_authinfo(ISIS_PASSWD_TYPE_CLEARTXT, +					     passwd->len, passwd->passwd, +					     circuit->snd_stream)) +				return ISIS_WARNING; +			break; + +		/* HMAC MD5 */ +		case ISIS_PASSWD_TYPE_HMAC_MD5: +			/* Remember where TLV is written so we can later +			 * overwrite the MD5 hash */ +			auth_tlv_offset = stream_get_endp(circuit->snd_stream); +			memset(&hmac_md5_hash, 0, ISIS_AUTH_MD5_SIZE); +			if (tlv_add_authinfo(ISIS_PASSWD_TYPE_HMAC_MD5, +					     ISIS_AUTH_MD5_SIZE, hmac_md5_hash, +					     circuit->snd_stream)) +				return ISIS_WARNING; +			break; + +		default: +			break; +		} +	} -  length = (u_int16_t) stream_get_endp (circuit->snd_stream); -  /* Update PDU length */ -  stream_putw_at (circuit->snd_stream, lenp, length); +	retval = tlv_add_lsp_entries(lsps, circuit->snd_stream); +	if (retval != ISIS_OK) +		return retval; + +	if (isis->debugs & DEBUG_SNP_PACKETS) { +		for (ALL_LIST_ELEMENTS_RO(lsps, node, lsp)) { +			zlog_debug( +				"ISIS-Snp (%s):         PSNP entry %s, seq 0x%08x," +				" cksum 0x%04x, lifetime %us", +				circuit->area->area_tag, +				rawlspid_print(lsp->lsp_header->lsp_id), +				ntohl(lsp->lsp_header->seq_num), +				ntohs(lsp->lsp_header->checksum), +				ntohs(lsp->lsp_header->rem_lifetime)); +		} +	} -  /* For HMAC MD5 we need to compute the md5 hash and store it */ -  if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND) && -      passwd->type == ISIS_PASSWD_TYPE_HMAC_MD5) -    { -      hmac_md5 (STREAM_DATA (circuit->snd_stream), -                stream_get_endp(circuit->snd_stream), -                (unsigned char *) &passwd->passwd, passwd->len, -                (unsigned char *) &hmac_md5_hash); -      /* Copy the hash into the stream */ -      memcpy (STREAM_DATA (circuit->snd_stream) + auth_tlv_offset + 3, -              hmac_md5_hash, ISIS_AUTH_MD5_SIZE); -    } +	length = (u_int16_t)stream_get_endp(circuit->snd_stream); +	/* Update PDU length */ +	stream_putw_at(circuit->snd_stream, lenp, length); + +	/* For HMAC MD5 we need to compute the md5 hash and store it */ +	if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND) +	    && passwd->type == ISIS_PASSWD_TYPE_HMAC_MD5) { +		hmac_md5(STREAM_DATA(circuit->snd_stream), +			 stream_get_endp(circuit->snd_stream), +			 (unsigned char *)&passwd->passwd, passwd->len, +			 (unsigned char *)&hmac_md5_hash); +		/* Copy the hash into the stream */ +		memcpy(STREAM_DATA(circuit->snd_stream) + auth_tlv_offset + 3, +		       hmac_md5_hash, ISIS_AUTH_MD5_SIZE); +	} -  return ISIS_OK; +	return ISIS_OK;  }  /*   *  7.3.15.4 action on expiration of partial SNP interval   *  level 1   */ -static int -send_psnp (int level, struct isis_circuit *circuit) +static int send_psnp(int level, struct isis_circuit *circuit)  { -  struct isis_lsp *lsp; -  struct list *list = NULL; -  struct listnode *node; -  u_char num_lsps; -  int retval = ISIS_OK; +	struct isis_lsp *lsp; +	struct list *list = NULL; +	struct listnode *node; +	u_char num_lsps; +	int retval = ISIS_OK; -  if (circuit->circ_type == CIRCUIT_T_BROADCAST && -      circuit->u.bc.is_dr[level - 1]) -    return ISIS_OK; +	if (circuit->circ_type == CIRCUIT_T_BROADCAST +	    && circuit->u.bc.is_dr[level - 1]) +		return ISIS_OK; -  if (circuit->area->lspdb[level - 1] == NULL || -      dict_count (circuit->area->lspdb[level - 1]) == 0) -    return ISIS_OK; +	if (circuit->area->lspdb[level - 1] == NULL +	    || dict_count(circuit->area->lspdb[level - 1]) == 0) +		return ISIS_OK; -  if (! circuit->snd_stream) -    return ISIS_ERROR; +	if (!circuit->snd_stream) +		return ISIS_ERROR; -  num_lsps = max_lsps_per_snp (ISIS_SNP_PSNP_FLAG, level, circuit); +	num_lsps = max_lsps_per_snp(ISIS_SNP_PSNP_FLAG, level, circuit); -  while (1) -    { -      list = list_new (); -      lsp_build_list_ssn (circuit, num_lsps, list, -                          circuit->area->lspdb[level - 1]); - -      if (listcount (list) == 0) -        { -          list_delete (list); -          return ISIS_OK; -        } - -      retval = build_psnp (level, circuit, list); -      if (retval != ISIS_OK) -        { -          zlog_err ("ISIS-Snp (%s): Build L%d PSNP on %s failed", -                    circuit->area->area_tag, level, circuit->interface->name); -          list_delete (list); -          return retval; -        } - -      if (isis->debugs & DEBUG_SNP_PACKETS) -        { -          zlog_debug ("ISIS-Snp (%s): Sending L%d PSNP on %s, length %zd", -                      circuit->area->area_tag, level, -                      circuit->interface->name, -                      stream_get_endp (circuit->snd_stream)); -          if (isis->debugs & DEBUG_PACKET_DUMP) -            zlog_dump_data (STREAM_DATA (circuit->snd_stream), -                            stream_get_endp (circuit->snd_stream)); -        } - -      retval = circuit->tx (circuit, level); -      if (retval != ISIS_OK) -        { -          zlog_err ("ISIS-Snp (%s): Send L%d PSNP on %s failed", -                    circuit->area->area_tag, level, -                    circuit->interface->name); -          list_delete (list); -          return retval; -        } - -      /* -       * sending succeeded, we can clear SSN flags of this circuit -       * for the LSPs in list -       */ -      for (ALL_LIST_ELEMENTS_RO (list, node, lsp)) -        ISIS_CLEAR_FLAG (lsp->SSNflags, circuit); -      list_delete (list); -    } +	while (1) { +		list = list_new(); +		lsp_build_list_ssn(circuit, num_lsps, list, +				   circuit->area->lspdb[level - 1]); + +		if (listcount(list) == 0) { +			list_delete(list); +			return ISIS_OK; +		} + +		retval = build_psnp(level, circuit, list); +		if (retval != ISIS_OK) { +			zlog_err("ISIS-Snp (%s): Build L%d PSNP on %s failed", +				 circuit->area->area_tag, level, +				 circuit->interface->name); +			list_delete(list); +			return retval; +		} + +		if (isis->debugs & DEBUG_SNP_PACKETS) { +			zlog_debug( +				"ISIS-Snp (%s): Sending L%d PSNP on %s, length %zd", +				circuit->area->area_tag, level, +				circuit->interface->name, +				stream_get_endp(circuit->snd_stream)); +			if (isis->debugs & DEBUG_PACKET_DUMP) +				zlog_dump_data( +					STREAM_DATA(circuit->snd_stream), +					stream_get_endp(circuit->snd_stream)); +		} + +		retval = circuit->tx(circuit, level); +		if (retval != ISIS_OK) { +			zlog_err("ISIS-Snp (%s): Send L%d PSNP on %s failed", +				 circuit->area->area_tag, level, +				 circuit->interface->name); +			list_delete(list); +			return retval; +		} -  return retval; +		/* +		 * sending succeeded, we can clear SSN flags of this circuit +		 * for the LSPs in list +		 */ +		for (ALL_LIST_ELEMENTS_RO(list, node, lsp)) +			ISIS_CLEAR_FLAG(lsp->SSNflags, circuit); +		list_delete(list); +	} + +	return retval;  } -int -send_l1_psnp (struct thread *thread) +int send_l1_psnp(struct thread *thread)  { -  struct isis_circuit *circuit; -  int retval = ISIS_OK; +	struct isis_circuit *circuit; +	int retval = ISIS_OK; -  circuit = THREAD_ARG (thread); -  assert (circuit); +	circuit = THREAD_ARG(thread); +	assert(circuit); -  circuit->t_send_psnp[0] = NULL; +	circuit->t_send_psnp[0] = NULL; -  send_psnp (1, circuit); -  /* set next timer thread */ -  THREAD_TIMER_ON (master, circuit->t_send_psnp[0], send_l1_psnp, circuit, -		   isis_jitter (circuit->psnp_interval[0], PSNP_JITTER)); +	send_psnp(1, circuit); +	/* set next timer thread */ +	THREAD_TIMER_ON(master, circuit->t_send_psnp[0], send_l1_psnp, circuit, +			isis_jitter(circuit->psnp_interval[0], PSNP_JITTER)); -  return retval; +	return retval;  }  /*   *  7.3.15.4 action on expiration of partial SNP interval   *  level 2   */ -int -send_l2_psnp (struct thread *thread) +int send_l2_psnp(struct thread *thread)  { -  struct isis_circuit *circuit; -  int retval = ISIS_OK; +	struct isis_circuit *circuit; +	int retval = ISIS_OK; -  circuit = THREAD_ARG (thread); -  assert (circuit); +	circuit = THREAD_ARG(thread); +	assert(circuit); -  circuit->t_send_psnp[1] = NULL; +	circuit->t_send_psnp[1] = NULL; -  send_psnp (2, circuit); +	send_psnp(2, circuit); -  /* set next timer thread */ -  THREAD_TIMER_ON (master, circuit->t_send_psnp[1], send_l2_psnp, circuit, -		   isis_jitter (circuit->psnp_interval[1], PSNP_JITTER)); +	/* set next timer thread */ +	THREAD_TIMER_ON(master, circuit->t_send_psnp[1], send_l2_psnp, circuit, +			isis_jitter(circuit->psnp_interval[1], PSNP_JITTER)); -  return retval; +	return retval;  }  /*   * ISO 10589 - 7.3.14.3   */ -int -send_lsp (struct thread *thread) +int send_lsp(struct thread *thread)  { -  struct isis_circuit *circuit; -  struct isis_lsp *lsp; -  struct listnode *node; -  int clear_srm = 1; -  int retval = ISIS_OK; - -  circuit = THREAD_ARG (thread); -  assert (circuit); - -  if (!circuit->lsp_queue) -    return ISIS_OK; - -  node = listhead (circuit->lsp_queue); - -  /* -   * Handle case where there are no LSPs on the queue. This can -   * happen, for instance, if an adjacency goes down before this -   * thread gets a chance to run. -   */ -  if (!node) -    return ISIS_OK; - -  /* -   * Delete LSP from lsp_queue. If it's still in queue, it is assumed -   * as 'transmit pending', but send_lsp may never be called again. -   * Retry will happen because SRM flag will not be cleared. -   */ -  lsp = listgetdata(node); -  list_delete_node (circuit->lsp_queue, node); - -  /* Set the last-cleared time if the queue is empty. */ -  /* TODO: Is is possible that new lsps keep being added to the queue -   * that the queue is never empty? */ -  if (list_isempty (circuit->lsp_queue)) -    circuit->lsp_queue_last_cleared = time (NULL); - -  if (circuit->state != C_STATE_UP || circuit->is_passive == 1) -    goto out; - -  /* -   * Do not send if levels do not match -   */ -  if (!(lsp->level & circuit->is_type)) -    goto out; - -  /* -   * Do not send if we do not have adjacencies in state up on the circuit -   */ -  if (circuit->upadjcount[lsp->level - 1] == 0) -    goto out; - -  /* stream_copy will assert and stop program execution if LSP is larger than -   * the circuit's MTU. So handle and log this case here. */ -  if (stream_get_endp(lsp->pdu) > stream_get_size(circuit->snd_stream)) -    { -      zlog_err("ISIS-Upd (%s): Can't send L%d LSP %s, seq 0x%08x," -               " cksum 0x%04x, lifetime %us on %s. LSP Size is %zu" -               " while interface stream size is %zu.", -               circuit->area->area_tag, lsp->level, -               rawlspid_print(lsp->lsp_header->lsp_id), -               ntohl(lsp->lsp_header->seq_num), -               ntohs(lsp->lsp_header->checksum), -               ntohs(lsp->lsp_header->rem_lifetime), -               circuit->interface->name, -               stream_get_endp(lsp->pdu), -               stream_get_size(circuit->snd_stream)); -      if (isis->debugs & DEBUG_PACKET_DUMP) -        zlog_dump_data(STREAM_DATA(lsp->pdu), stream_get_endp(lsp->pdu)); -      retval = ISIS_ERROR; -      goto out; -    } - -  /* copy our lsp to the send buffer */ -  stream_copy (circuit->snd_stream, lsp->pdu); +	struct isis_circuit *circuit; +	struct isis_lsp *lsp; +	struct listnode *node; +	int clear_srm = 1; +	int retval = ISIS_OK; + +	circuit = THREAD_ARG(thread); +	assert(circuit); + +	if (!circuit->lsp_queue) +		return ISIS_OK; + +	node = listhead(circuit->lsp_queue); + +	/* +	 * Handle case where there are no LSPs on the queue. This can +	 * happen, for instance, if an adjacency goes down before this +	 * thread gets a chance to run. +	 */ +	if (!node) +		return ISIS_OK; + +	/* +	 * Delete LSP from lsp_queue. If it's still in queue, it is assumed +	 * as 'transmit pending', but send_lsp may never be called again. +	 * Retry will happen because SRM flag will not be cleared. +	 */ +	lsp = listgetdata(node); +	list_delete_node(circuit->lsp_queue, node); + +	/* Set the last-cleared time if the queue is empty. */ +	/* TODO: Is is possible that new lsps keep being added to the queue +	 * that the queue is never empty? */ +	if (list_isempty(circuit->lsp_queue)) +		circuit->lsp_queue_last_cleared = time(NULL); + +	if (circuit->state != C_STATE_UP || circuit->is_passive == 1) +		goto out; + +	/* +	 * Do not send if levels do not match +	 */ +	if (!(lsp->level & circuit->is_type)) +		goto out; + +	/* +	 * Do not send if we do not have adjacencies in state up on the circuit +	 */ +	if (circuit->upadjcount[lsp->level - 1] == 0) +		goto out; + +	/* stream_copy will assert and stop program execution if LSP is larger +	 * than +	 * the circuit's MTU. So handle and log this case here. */ +	if (stream_get_endp(lsp->pdu) > stream_get_size(circuit->snd_stream)) { +		zlog_err( +			"ISIS-Upd (%s): Can't send L%d LSP %s, seq 0x%08x," +			" cksum 0x%04x, lifetime %us on %s. LSP Size is %zu" +			" while interface stream size is %zu.", +			circuit->area->area_tag, lsp->level, +			rawlspid_print(lsp->lsp_header->lsp_id), +			ntohl(lsp->lsp_header->seq_num), +			ntohs(lsp->lsp_header->checksum), +			ntohs(lsp->lsp_header->rem_lifetime), +			circuit->interface->name, stream_get_endp(lsp->pdu), +			stream_get_size(circuit->snd_stream)); +		if (isis->debugs & DEBUG_PACKET_DUMP) +			zlog_dump_data(STREAM_DATA(lsp->pdu), +				       stream_get_endp(lsp->pdu)); +		retval = ISIS_ERROR; +		goto out; +	} -  if (isis->debugs & DEBUG_UPDATE_PACKETS) -    { -      zlog_debug -        ("ISIS-Upd (%s): Sending L%d LSP %s, seq 0x%08x, cksum 0x%04x," -         " lifetime %us on %s", circuit->area->area_tag, lsp->level, -         rawlspid_print (lsp->lsp_header->lsp_id), -         ntohl (lsp->lsp_header->seq_num), -         ntohs (lsp->lsp_header->checksum), -         ntohs (lsp->lsp_header->rem_lifetime), -         circuit->interface->name); -      if (isis->debugs & DEBUG_PACKET_DUMP) -        zlog_dump_data (STREAM_DATA (circuit->snd_stream), -                        stream_get_endp (circuit->snd_stream)); -    } +	/* copy our lsp to the send buffer */ +	stream_copy(circuit->snd_stream, lsp->pdu); + +	if (isis->debugs & DEBUG_UPDATE_PACKETS) { +		zlog_debug( +			"ISIS-Upd (%s): Sending L%d LSP %s, seq 0x%08x, cksum 0x%04x," +			" lifetime %us on %s", +			circuit->area->area_tag, lsp->level, +			rawlspid_print(lsp->lsp_header->lsp_id), +			ntohl(lsp->lsp_header->seq_num), +			ntohs(lsp->lsp_header->checksum), +			ntohs(lsp->lsp_header->rem_lifetime), +			circuit->interface->name); +		if (isis->debugs & DEBUG_PACKET_DUMP) +			zlog_dump_data(STREAM_DATA(circuit->snd_stream), +				       stream_get_endp(circuit->snd_stream)); +	} -  clear_srm = 0; -  retval = circuit->tx (circuit, lsp->level); -  if (retval != ISIS_OK) -    { -      zlog_err ("ISIS-Upd (%s): Send L%d LSP on %s failed %s", -                circuit->area->area_tag, lsp->level, -                circuit->interface->name, -                (retval == ISIS_WARNING) ? "temporarily" : "permanently"); -    } +	clear_srm = 0; +	retval = circuit->tx(circuit, lsp->level); +	if (retval != ISIS_OK) { +		zlog_err("ISIS-Upd (%s): Send L%d LSP on %s failed %s", +			 circuit->area->area_tag, lsp->level, +			 circuit->interface->name, +			 (retval == ISIS_WARNING) ? "temporarily" +						  : "permanently"); +	}  out: -  if (clear_srm -      || (retval == ISIS_OK && circuit->circ_type == CIRCUIT_T_BROADCAST) -      || (retval != ISIS_OK && retval != ISIS_WARNING)) -    { -      /* SRM flag will trigger retransmission. We will not retransmit if we -       * encountered a fatal error. -       * On success, they should only be cleared if it's a broadcast circuit. -       * On a P2P circuit, we will wait for the ack from the neighbor to clear -       * the fag. -       */ -      ISIS_CLEAR_FLAG (lsp->SRMflags, circuit); -    } +	if (clear_srm +	    || (retval == ISIS_OK && circuit->circ_type == CIRCUIT_T_BROADCAST) +	    || (retval != ISIS_OK && retval != ISIS_WARNING)) { +		/* SRM flag will trigger retransmission. We will not retransmit +		 * if we +		 * encountered a fatal error. +		 * On success, they should only be cleared if it's a broadcast +		 * circuit. +		 * On a P2P circuit, we will wait for the ack from the neighbor +		 * to clear +		 * the fag. +		 */ +		ISIS_CLEAR_FLAG(lsp->SRMflags, circuit); +	} -  return retval; +	return retval;  } -int -ack_lsp (struct isis_link_state_hdr *hdr, struct isis_circuit *circuit, -	 int level) +int ack_lsp(struct isis_link_state_hdr *hdr, struct isis_circuit *circuit, +	    int level)  { -  unsigned long lenp; -  int retval; -  u_int16_t length; -  struct isis_fixed_hdr fixed_hdr; - -  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); - - -  lenp = stream_get_endp (circuit->snd_stream); -  stream_putw (circuit->snd_stream, 0);	/* PDU length  */ -  stream_put (circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN); -  stream_putc (circuit->snd_stream, circuit->idx); -  stream_putc (circuit->snd_stream, 9);	/* code */ -  stream_putc (circuit->snd_stream, 16);	/* len */ - -  stream_putw (circuit->snd_stream, ntohs (hdr->rem_lifetime)); -  stream_put (circuit->snd_stream, hdr->lsp_id, ISIS_SYS_ID_LEN + 2); -  stream_putl (circuit->snd_stream, ntohl (hdr->seq_num)); -  stream_putw (circuit->snd_stream, ntohs (hdr->checksum)); - -  length = (u_int16_t) stream_get_endp (circuit->snd_stream); -  /* Update PDU length */ -  stream_putw_at (circuit->snd_stream, lenp, length); - -  retval = circuit->tx (circuit, level); -  if (retval != ISIS_OK) -    zlog_err ("ISIS-Upd (%s): Send L%d LSP PSNP on %s failed", -              circuit->area->area_tag, level, -              circuit->interface->name); - -  return retval; +	unsigned long lenp; +	int retval; +	u_int16_t length; +	struct isis_fixed_hdr fixed_hdr; + +	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); + + +	lenp = stream_get_endp(circuit->snd_stream); +	stream_putw(circuit->snd_stream, 0); /* PDU length  */ +	stream_put(circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN); +	stream_putc(circuit->snd_stream, circuit->idx); +	stream_putc(circuit->snd_stream, 9);  /* code */ +	stream_putc(circuit->snd_stream, 16); /* len */ + +	stream_putw(circuit->snd_stream, ntohs(hdr->rem_lifetime)); +	stream_put(circuit->snd_stream, hdr->lsp_id, ISIS_SYS_ID_LEN + 2); +	stream_putl(circuit->snd_stream, ntohl(hdr->seq_num)); +	stream_putw(circuit->snd_stream, ntohs(hdr->checksum)); + +	length = (u_int16_t)stream_get_endp(circuit->snd_stream); +	/* Update PDU length */ +	stream_putw_at(circuit->snd_stream, lenp, length); + +	retval = circuit->tx(circuit, level); +	if (retval != ISIS_OK) +		zlog_err("ISIS-Upd (%s): Send L%d LSP PSNP on %s failed", +			 circuit->area->area_tag, level, +			 circuit->interface->name); + +	return retval;  }  | 
