Make authentication of SNPs work correctly - ie. conditionally like it is in
IOS.
diff --git a/isisd/ChangeLog b/isisd/ChangeLog
index 2145307..0893e6f 100644
--- a/isisd/ChangeLog
+++ b/isisd/ChangeLog
@@ -1,3 +1,8 @@
+2005-01-01 Hasso Tepper <hasso at quagga.net>
+
+	* isis_common.h, isisd.c, isis_pdu.c: Implement authentication in
+	  SNPs correctly - ie. make it conditional like it is in IOS.
+
 2004-12-29 Hasso Tepper <hasso at quagga.net>
 
 	* isis_circuit.c, isis_csm.c, isis_zebra.c: Don't crash during
diff --git a/isisd/isis_common.h b/isisd/isis_common.h
index 7a0768a..2633855 100644
--- a/isisd/isis_common.h
+++ b/isisd/isis_common.h
@@ -37,6 +37,10 @@
 #define ISIS_PASSWD_TYPE_CLEARTXT 1
 #define ISIS_PASSWD_TYPE_PRIVATE  255
   u_char type;
+  /* Authenticate SNPs? */
+#define SNP_AUTH_SEND   0x01
+#define SNP_AUTH_RECV   0x02
+  u_char snp_auth;
   u_char passwd[255];
 };
 
diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c
index bac903a..0e0a832 100644
--- a/isisd/isis_pdu.c
+++ b/isisd/isis_pdu.c
@@ -1270,10 +1270,7 @@
   struct listnode *node, *node2;
   struct tlvs tlvs;
   struct list *lsp_list = NULL;
-  /* TODO: Implement SNP authentication. */
-#if 0
   struct isis_passwd *passwd;
-#endif
 
   if (snp_type == ISIS_SNP_CSNP_FLAG)
     {
@@ -1398,27 +1395,25 @@
       return retval;
     }
 
-  /* FIXME: Authentication in LSPs does not mean authentication in SNPs...
-   * In fact by default IOS only deals with LSPs authentication!!
-   * To force authentication in SNPs, one must specify the 'authenticate
-   * snp' command after 'area-password WORD' or 'domain-password WORD'.
-   * This command is not supported for the moment.
-   */
-#if 0
-  (level == 1) ? (passwd = &circuit->area->area_passwd) :
-    (passwd = &circuit->area->domain_passwd);
-  if (passwd->type)
+  if (level == 1)
+    passwd = &circuit->area->area_passwd;
+  else
+    passwd = &circuit->area->domain_passwd;
+
+  if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_RECV))
     {
-      if (!(found & TLVFLAG_AUTH_INFO) ||
-	  authentication_check (passwd, &tlvs.auth_info))
+      if (passwd->type)
 	{
-	  isis_event_auth_failure (circuit->area->area_tag,
-				   "SNP authentication" " failure",
-				   phdr ? phdr->source_id : chdr->source_id);
-	  return ISIS_OK;
+	  if (!(found & TLVFLAG_AUTH_INFO) ||
+	      authentication_check (passwd, &tlvs.auth_info))
+	    {
+	      isis_event_auth_failure (circuit->area->area_tag,
+				       "SNP authentication" " failure",
+				       phdr ? phdr->source_id : chdr->source_id);
+	      return ISIS_OK;
+	    }
 	}
     }
-#endif /* 0 */
 
   /* debug isis snp-packets */
   if (isis->debugs & DEBUG_SNP_PACKETS)
@@ -2155,9 +2150,10 @@
   else
     passwd = &circuit->area->domain_passwd;
 
-  if (passwd->type)
-    retval = tlv_add_authinfo (passwd->type, passwd->len,
-			       passwd->passwd, circuit->snd_stream);
+  if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND))
+    if (passwd->type)
+      retval = tlv_add_authinfo (passwd->type, passwd->len,
+				 passwd->passwd, circuit->snd_stream);
 
   if (!retval && lsps)
     {
@@ -2305,9 +2301,10 @@
   else
     passwd = &circuit->area->domain_passwd;
 
-  if (passwd->type)
-    retval = tlv_add_authinfo (passwd->type, passwd->len,
-			       passwd->passwd, circuit->snd_stream);
+  if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND))
+    if (passwd->type)
+      retval = tlv_add_authinfo (passwd->type, passwd->len,
+				 passwd->passwd, circuit->snd_stream);
 
   if (!retval && lsps)
     {
diff --git a/isisd/isisd.c b/isisd/isisd.c
index f920453..e4d73c3 100644
--- a/isisd/isisd.c
+++ b/isisd/isisd.c
@@ -1049,9 +1049,33 @@
   area->area_passwd.type = ISIS_PASSWD_TYPE_CLEARTXT;
   strncpy ((char *)area->area_passwd.passwd, argv[0], 255);
 
+  if (argc > 1)
+    {
+      SET_FLAG(area->area_passwd.snp_auth, SNP_AUTH_SEND);
+      if (strncmp(argv[1], "v", 1) == 0)
+	SET_FLAG(area->area_passwd.snp_auth, SNP_AUTH_RECV);
+      else
+	UNSET_FLAG(area->area_passwd.snp_auth, SNP_AUTH_RECV);
+    }
+  else
+    {
+      UNSET_FLAG(area->area_passwd.snp_auth, SNP_AUTH_SEND);
+      UNSET_FLAG(area->area_passwd.snp_auth, SNP_AUTH_RECV);
+    }
+
   return CMD_SUCCESS;
 }
 
+ALIAS (area_passwd,
+       area_passwd_snpauth_cmd,
+       "area-password WORD authenticate snp (send-only|validate)",
+       "Configure the authentication password for an area\n"
+       "Area password\n"
+       "Authentication\n"
+       "SNP PDUs\n"
+       "Send but do not check PDUs on receiving\n"
+       "Send and check PDUs on receiving\n");
+
 DEFUN (no_area_passwd,
        no_area_passwd_cmd,
        "no area-password",
@@ -1100,9 +1124,33 @@
   area->domain_passwd.type = ISIS_PASSWD_TYPE_CLEARTXT;
   strncpy ((char *)area->domain_passwd.passwd, argv[0], 255);
 
+  if (argc > 1)
+    {
+      SET_FLAG(area->domain_passwd.snp_auth, SNP_AUTH_SEND);
+      if (strncmp(argv[1], "v", 1) == 0)
+	SET_FLAG(area->domain_passwd.snp_auth, SNP_AUTH_RECV);
+      else
+	UNSET_FLAG(area->domain_passwd.snp_auth, SNP_AUTH_RECV);
+    }
+  else
+    {
+      UNSET_FLAG(area->domain_passwd.snp_auth, SNP_AUTH_SEND);
+      UNSET_FLAG(area->domain_passwd.snp_auth, SNP_AUTH_RECV);
+    }
+
   return CMD_SUCCESS;
 }
 
+ALIAS (domain_passwd,
+       domain_passwd_snpauth_cmd,
+       "domain-password WORD authenticate snp (send-only|validate)",
+       "Set the authentication password for a routing domain\n"
+       "Routing domain password\n"
+       "Authentication\n"
+       "SNP PDUs\n"
+       "Send but do not check PDUs on receiving\n"
+       "Send and check PDUs on receiving\n");
+
 DEFUN (no_domain_passwd,
        no_domain_passwd_cmd,
        "no domain-password WORD",
@@ -1904,14 +1952,30 @@
 	/* Authentication passwords. */
 	if (area->area_passwd.len > 0)
 	  {
-	    vty_out(vty, " area-password %s%s",
-		    area->area_passwd.passwd, VTY_NEWLINE);
+	    vty_out(vty, " area-password %s", area->area_passwd.passwd);
+	    if (CHECK_FLAG(area->area_passwd.snp_auth, SNP_AUTH_SEND))
+	      {
+		vty_out(vty, " authenticate snp ");
+		if (CHECK_FLAG(area->area_passwd.snp_auth, SNP_AUTH_RECV))
+		  vty_out(vty, "validate");
+		else
+		  vty_out(vty, "send-only");
+	      }
+	    vty_out(vty, "%s", VTY_NEWLINE);
 	    write++; 
 	  }  
 	if (area->domain_passwd.len > 0)
 	  {
-	    vty_out(vty, " domain-password %s%s",
-		    area->domain_passwd.passwd, VTY_NEWLINE);
+	    vty_out(vty, " domain-password %s", area->domain_passwd.passwd);
+	    if (CHECK_FLAG(area->domain_passwd.snp_auth, SNP_AUTH_SEND))
+	      {
+		vty_out(vty, " authenticate snp ");
+		if (CHECK_FLAG(area->domain_passwd.snp_auth, SNP_AUTH_RECV))
+		  vty_out(vty, "validate");
+		else
+		  vty_out(vty, "send-only");
+	      }
+	    vty_out(vty, "%s", VTY_NEWLINE);
 	    write++;
 	  }
 #ifdef TOPOLOGY_GENERATE
@@ -2028,9 +2092,11 @@
   install_element (ISIS_NODE, &no_is_type_cmd);
 
   install_element (ISIS_NODE, &area_passwd_cmd);
+  install_element (ISIS_NODE, &area_passwd_snpauth_cmd);
   install_element (ISIS_NODE, &no_area_passwd_cmd);
 
   install_element (ISIS_NODE, &domain_passwd_cmd);
+  install_element (ISIS_NODE, &domain_passwd_snpauth_cmd);
   install_element (ISIS_NODE, &no_domain_passwd_cmd);
 
   install_element (ISIS_NODE, &lsp_gen_interval_cmd);