Index: /branches/rel_apv_10_7_2/usr/click/lib/libca_snmp/snmp_cadmin.c
===================================================================
--- /branches/rel_apv_10_7_2/usr/click/lib/libca_snmp/snmp_cadmin.c	(revision 39136)
+++ /branches/rel_apv_10_7_2/usr/click/lib/libca_snmp/snmp_cadmin.c	(working copy)
@@ -128,6 +128,8 @@
 #include <sys/sysctl.h>
 #include <limits.h>
 #include <errno.h>
+#include <fcntl.h>
+#include <sys/stat.h>
 
 #include "snmpcli.h"
 #include "fastlog.h"
@@ -169,6 +171,109 @@
 
 extern array_model_t array_models[MAX_MODEL];
 
+/* Base64 encoding table */
+static const char b64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+/* Function to get the serial number */
+int get_sr_num(char* serial_num, int slen)
+{
+    size_t len = 0;
+    FILE *fd = NULL;
+    if (slen < SERNUMLEN) {
+        return -1;
+    }
+    memset(serial_num, 0, SERNUMLEN);
+    len = MACLEN;
+    fd = fopen(SRNFN, "r");
+    if (!fd) {
+        if ((u_sysctlbyname("kern.click_id", serial_num, &len, NULL, 0) == -1)) {
+            return -1;
+        } else {
+            serial_num[MACLEN - 1] = '\0';
+        }
+    } else {
+        fscanf(fd, "%s", serial_num);
+        fclose(fd);
+        if ((u_sysctlbyname("kern.click_id", (serial_num + ARRAYIDLEN), &len, NULL, 0) == -1)) {
+            serial_num[ARRAYIDLEN] = '\0';
+        } else {
+            serial_num[SERNUMLEN - 1] = '\0';
+        }
+    }
+    return 0;
+}
+
+/* Simple base64 encoding function */
+static void base64_encode(const unsigned char *in, size_t in_len, char *out, size_t out_len)
+{
+    size_t i, o = 0;
+    unsigned int val = 0;
+    int valb = -6;
+
+    for (i = 0; i < in_len; i++) {
+        val = (val << 8) + in[i];
+        valb += 8;
+        while (valb >= 0) {
+            if (o >= out_len - 1) break; // prevent overflow
+            out[o++] = b64_table[(val >> valb) & 0x3F];
+            valb -= 6;
+        }
+    }
+    if (valb > -6 && o < out_len - 1) {
+        out[o++] = b64_table[((val << 8) >> (valb + 8)) & 0x3F];
+    }
+    while (o % 4 != 0) {
+        if (o >= out_len - 1) break;
+        out[o++] = '=';
+    }
+    out[o] = '\0';
+}
+
+/* Generate SNMP EngineID (20bytes raw, base64 encoded to 27 chars) */
+int generate_snmp_engineID(char *engineID_b64, size_t b64_len)
+{
+    if (b64_len < 28) { // 27 chars + null terminator
+        return -1;
+    }
+
+    unsigned char engineID_raw[20];
+    char serial_num[SERNUMLEN];
+    int ret = get_sr_num(serial_num, SERNUMLEN);
+    if (ret != 0) {
+        return -2; // failed to get serial number
+    }
+
+    /* Compose engineID_raw:
+       Per RFC 3411, engineID can be enterprise-specific:
+        Format: 4 bytes enterprise OID + 1 byte format + 15 bytes unique identifier
+        For example:
+        [0-3]: enterprise OID (e.g., 0x80 0x00 0x1F 0x88 for private enterprise 8072)
+        [4]: format identifier (e.g., 0x00)
+        [5-19]: unique identifier from serial number or MAC
+
+       Example enterprise OID (replace with your enterprise OID) */
+    engineID_raw[0] = 0x80;
+    engineID_raw[1] = 0x00;
+    engineID_raw[2] = 0x1F;
+    engineID_raw[3] = 0x88;
+    engineID_raw[4] = 0x00;
+
+   /* Fill remaining 15bytes with serial number or hash thereof
+	Use first 15bytes of serial number */
+    size_t sn_len = strlen(serial_num);
+    if (sn_len > 15) sn_len = 15;
+    memcpy(&engineID_raw[5], serial_num, sn_len);
+    if (sn_len < 15) {
+        memset(&engineID_raw[5 + sn_len], 0, 15 - sn_len);
+    }
+
+    /* Base64 encode raw engineID (20bytes -> 27chars)*/
+    base64_encode(engineID_raw, sizeof(engineID_raw), engineID_b64, b64_len);
+
+    return 0;
+}
+
+
 /* 
  * get snmpd's pid
  * if it do not running, return 0
@@ -272,13 +377,25 @@
 	char priv_decrypt[PASSWORD_MAXLEN + 1];
 	int ret = 0;
 	int product_id = -1;
-	
+
+	/* Buffer for base64-encoded engineID */
+	char engineID_b64[28]; // 27 chars + null terminator
+
+	/* Generate SNMP engineID */
+	ret = generate_snmp_engineID(engineID_b64, sizeof(engineID_b64));
+        if (ret != 0) {
+            printf("Error: Failed to generate SNMP engineID\n");
+            return -1; // Exit if engineID generation fails
+        }
+
 	conf_fp_tmp = fopen(SNMPD_CONF_FILE_TMP, "w");
 	if (conf_fp_tmp == NULL) {
 		printf("Creat config file error.\n");
 		return -1;
 	}
 
+	/* Write base64-encoded SNMP engineID to configuration */
+        fprintf(conf_fp_tmp, "engineID %s\n", engineID_b64);
 
 	/* Load CA-SNMP-MIB dynamic library */
 #if defined(__linux__)
@@ -1393,6 +1510,19 @@
 
 	pInfo->snmp_version = ver;
 
+       /* Generate and store base64-encoded SNMP engine ID */
+       char engineID_b64[28]; // 27 chars + null terminator
+
+       int ret = generate_snmp_engineID(engineID_b64, sizeof(engineID_b64));
+
+       if (ret != 0) {
+           printf("Error: Failed to generate SNMP engineID\n");
+           snmp_server_unlock();
+           return CA_ERR_SNMP;
+       }
+       strncpy(pInfo->engineID_b64, engineID_b64, sizeof(pInfo->engineID_b64));
+       pInfo->engineID_b64[sizeof(pInfo->engineID_b64) - 1] = '\0';
+
 	snmp_update_snmpd_conf(pInfo);
 
 	if (start_in_sysmon(SNMPD_EXE, SNMPD_PID, 1) != 0) {
@@ -1413,7 +1543,10 @@
 	kern_snmp_on();
 
 	/* give Security advice */
-	if (ver == SNMPCONF_VER_DEFAULT) {
+	if (ver == SNMPCONF_VER_3) {
+           printf("Security Alert: Ensure secure users are configured for SNMPv3.\n");
+           printf("Warning: Changing the engineID may invalidate existing users.\n");
+       } else if (ver == SNMPCONF_VER_DEFAULT) {
 		printf("Warning:  Security Alert! It is strongly recommended to modify "
 				"the default SNMP community string to avoid possible system information interception.\n");
 	}
