From e194c8fbe2cc2b1085a3da97ddb94eb329558446 Mon Sep 17 00:00:00 2001
From: chenrufeng <chenrufeng4@huawei.com>
Date: Fri, 5 Jan 2024 10:38:35 +0800
Subject: [PATCH] add support for IDEAUI_ANTI_ATTACK

---
 agent/snmp_agent.c                  |  2 +
 include/net-snmp/library/snmp_api.h |  5 ++
 include/net-snmp/output_api.h       | 18 ++++++++
 include/net-snmp/types.h            |  6 +++
 snmplib/snmp_api.c                  | 72 +++++++++++++++++++++++++++++
 5 files changed, 103 insertions(+)

diff --git a/agent/snmp_agent.c b/agent/snmp_agent.c
index 273b46772..bff663d32 100644
--- a/agent/snmp_agent.c
+++ b/agent/snmp_agent.c
@@ -2214,7 +2214,9 @@ handle_snmp_packet(int op, netsnmp_session * session, int reqid,
      */
     if (pdu->version  == SNMP_VERSION_3 && 
         session->s_snmp_errno == SNMPERR_USM_AUTHENTICATIONFAILURE) {
+#ifndef IDEAUI_ANTI_ATTACK
            send_easy_trap(SNMP_TRAP_AUTHFAIL, 0);
+#endif
            return 1;
     } 
 	
diff --git a/include/net-snmp/library/snmp_api.h b/include/net-snmp/library/snmp_api.h
index 6b4fad6ab..419f44764 100644
--- a/include/net-snmp/library/snmp_api.h
+++ b/include/net-snmp/library/snmp_api.h
@@ -384,6 +384,11 @@ typedef struct request_list {
     NETSNMP_IMPORT
     void            init_snmp(const char *);
 
+#if defined(IDEAUI_ANTI_ATTACK)
+    NETSNMP_IMPORT
+    void            netsnmp_init_antiattack_callback(struct snmp_s_anti_attack* callbacklist);
+#endif
+
     NETSNMP_IMPORT
     int
     snmp_build(u_char ** pkt, size_t * pkt_len, size_t * offset,
diff --git a/include/net-snmp/output_api.h b/include/net-snmp/output_api.h
index 3b142850c..9bce8d704 100644
--- a/include/net-snmp/output_api.h
+++ b/include/net-snmp/output_api.h
@@ -184,4 +184,22 @@ netsnmp_debug_no_dumpsetup(const char *token, const void *buf, size_t len)
 #define ERROR_MSG(string)	snmp_set_detail(string)
 #endif
 
+#if defined(IDEAUI_ANTI_ATTACK)
+typedef struct snmp_s_anti_info {
+    char *userName;
+    char *peerName;
+    int antiRes;
+} snmp_anti_info;
+
+/*
+ * anti attack
+ */
+struct snmp_s_anti_attack {
+    void (*cb_init_attack_info)(void);
+    void (*cb_uninit_attack_info)(void);
+    unsigned int (*cb_add_attack_info) (char *, const char *);
+    void (*cb_clear_attack_info) (char *, const char *);
+    int (*cb_is_attack_lock) (char *, const char *);
+};
+#endif /* IDEAUI_ANTI_ATTACK */
 #endif                          /* NET_SNMP_OUTPUT_API_H */
diff --git a/include/net-snmp/types.h b/include/net-snmp/types.h
index d489f37b1..830d3b93f 100644
--- a/include/net-snmp/types.h
+++ b/include/net-snmp/types.h
@@ -17,6 +17,12 @@
      */
 
 #include <stdio.h>
+#if defined(IDEAUI_OS_ANDROID)
+#include <sys/select.h>
+typedef unsigned long int ulong;
+typedef unsigned short int ushort;
+typedef unsigned int uint;
+#endif
 
 #ifndef NET_SNMP_CONFIG_H
 #error "Please include <net-snmp/net-snmp-config.h> before this file"
diff --git a/snmplib/snmp_api.c b/snmplib/snmp_api.c
index 4042f8046..96e7eeb5b 100644
--- a/snmplib/snmp_api.c
+++ b/snmplib/snmp_api.c
@@ -329,6 +329,13 @@ int             snmp_errno = 0;
  * END MTCRITICAL_RESOURCE
  */
 
+#if defined(IDEAUI_ANTI_ATTACK)
+ /*
+ * anti attack
+ */
+struct snmp_s_anti_attack g_stAntiAttack = {NULL, NULL, NULL, NULL, NULL};
+#endif
+
 /*
  * global error detail storage
  */
@@ -863,6 +870,20 @@ register_default_handlers(void)
     netsnmp_register_service_handlers();
 }
 
+#if defined(IDEAUI_ANTI_ATTACK)
+void netsnmp_init_antiattack_callback(struct snmp_s_anti_attack* callbacklist)
+{
+    if (callbacklist == NULL) {
+        return;
+    }
+    g_stAntiAttack.cb_init_attack_info = callbacklist->cb_init_attack_info;
+    g_stAntiAttack.cb_uninit_attack_info = callbacklist->cb_uninit_attack_info;
+    g_stAntiAttack.cb_add_attack_info = callbacklist->cb_add_attack_info;
+    g_stAntiAttack.cb_clear_attack_info = callbacklist->cb_clear_attack_info;
+    g_stAntiAttack.cb_is_attack_lock = callbacklist->cb_is_attack_lock;
+}
+#endif
+
 static int init_snmp_init_done = 0; /* To prevent double init's. */
 /**
  * Calls the functions to do config file loading and  mib module parsing
@@ -4287,10 +4308,33 @@ _snmp_parse(void *sessp,
     static size_t   ourEngineID_len = sizeof(ourEngineID);
 
     netsnmp_pdu    *pdu2 = NULL;
+#if defined(IDEAUI_ANTI_ATTACK)
+    char* peerName = NULL;
+    const int ipMaxLen = 256;
+    char szRemoteAddr[ipMaxLen] = {0};
+    char unknownPeer[ipMaxLen] = {0};
+    strcpy(unknownPeer, "UnkownHost");
+    snmp_anti_info antiInfo = {0};
+#endif
 
     session->s_snmp_errno = 0;
     session->s_errno = 0;
 
+#if defined(IDEAUI_ANTI_ATTACK)
+    if (pdu->transport_data_length != 0) {
+       struct sockaddr_in *from_in = (struct sockaddr_in *)pdu->transport_data;
+        if (AF_INET6 == from_in->sin_family) {
+            struct sockaddr_in6 *from_in6 = (struct sockaddr_in6 *)pdu->transport_data;
+            inet_ntop(AF_INET6, (void *) &(from_in6->sin6_addr), szRemoteAddr, sizeof(szRemoteAddr));
+            } else {
+           inet_ntop(AF_INET, (void *) &(from_in->sin_addr), szRemoteAddr, sizeof(szRemoteAddr));
+        }
+        peerName = szRemoteAddr;
+    } else {
+        peerName = unknownPeer;
+    }
+#endif
+
     /*
      * Ensure all incoming PDUs have a unique means of identification 
      * (This is not restricted to AgentX handling,
@@ -4391,6 +4435,16 @@ _snmp_parse(void *sessp,
                     snmp_api_errstring(result)));
 
         if (result) {
+#if defined(IDEAUI_ANTI_ATTACK)
+            antiInfo.userName = pdu->securityName;
+            antiInfo.peerName = peerName;
+            antiInfo.antiRes = result;
+            if (g_stAntiAttack.cb_add_attack_info != NULL &&
+                ((pdu->securityLevel == SNMP_SEC_LEVEL_AUTHNOPRIV) ||
+                (pdu->securityLevel == SNMP_SEC_LEVEL_AUTHPRIV))) {
+                g_stAntiAttack.cb_add_attack_info((char *)&antiInfo, (const char*)peerName);
+            }
+#endif
             struct snmp_secmod_def *secmod =
                 find_sec_mod(pdu->securityModel);
             if (!sessp) {
@@ -4408,6 +4462,24 @@ _snmp_parse(void *sessp,
             }
             free_securityStateRef(pdu);
         }
+#if defined(IDEAUI_ANTI_ATTACK)
+        else {
+            if ((g_stAntiAttack.cb_is_attack_lock != NULL) &&
+                ((pdu->securityLevel == SNMP_SEC_LEVEL_AUTHNOPRIV) ||
+                (pdu->securityLevel == SNMP_SEC_LEVEL_AUTHPRIV))) {
+                antiInfo.userName = pdu->securityName;
+                antiInfo.peerName = peerName;
+                antiInfo.antiRes = result;
+                if (g_stAntiAttack.cb_is_attack_lock((char *)&antiInfo, (const char*)peerName) != 0) {
+                    result = SNMPERR_ASN_PARSE_ERR;
+                } else {
+                    if (g_stAntiAttack.cb_clear_attack_info != NULL) {
+                        g_stAntiAttack.cb_clear_attack_info((char *)&antiInfo, (const char*)peerName);
+                    }
+                }
+            }
+        }
+#endif
 
         /* Implement RFC5343 here for two reasons:
            1) From a security perspective it handles this otherwise
