Index: /branches/rel_avx_2_7_2/src/backend/sys_cmd.c
===================================================================
--- /branches/rel_avx_2_7_2/src/backend/sys_cmd.c	(revision 8849)
+++ /branches/rel_avx_2_7_2/src/backend/sys_cmd.c	(working copy)
@@ -40,6 +40,7 @@
 #include <time.h>
 #include <unistd.h>
 #include <inttypes.h>
+#include <stdint.h>
 #include <poll.h>
 #include <sys/ioctl.h>
 #include <termios.h>
@@ -7017,3 +7018,186 @@
 }
 
 #undef AVX_IF_DESC_CMD_LENGTH
+
+#define _AVX_EXAUTH_STR_LEN 64
+
+enum {
+    AVX_EXAUTH_OFF = 0,
+    AVX_EXAUTH_ON,
+};
+
+enum {
+    AVX_EXAUTH_UNIX = 0,
+    AVX_EXAUTH_RADIUS,
+};
+
+typedef struct {
+    uint8_t status;
+    uint8_t type;
+    char host[_AVX_EXAUTH_STR_LEN];
+    uint16_t port;
+    char secret[_AVX_EXAUTH_STR_LEN];
+} __avx_exauth_conf_t;
+
+static __avx_exauth_conf_t exauth_conf = {
+    .status = AVX_EXAUTH_OFF,
+    .type = AVX_EXAUTH_UNIX,
+    .host = "",
+    .port = 0,
+    .secret = "",
+};
+
+#define AVX_NSS_CONF "/etc/nsswitch.conf"
+
+/* The PAM stacks with
+ * RADIUS authentication enabled appear like the following:
+ *
+ *     <type> [success=done default=ignore] pam_radius_auth.so
+ *     <type> [success=done default=bad] pam_unix.so
+ *
+ * With this setting, PAM will run the following flow:
+ *     1. First check RADIUS users.
+ *         - If user is met in RADIUS, return to the application
+ *           (done by "success=done").
+ *         - If not, go to the next step (done by "default=ignore").
+ *     2. Check UNIX users.
+ *         - It user is met in UNIX, return to the application.
+ *         - If not, abort the whole PAM authentication
+ *           (done by "default=bad").
+ *
+ * As a counterpart, the PAM stacks with RADIUS authentication
+ * disabled appear like the following:
+ *
+ *     <type> [success=done default=bad] pam_unix.so
+ */
+
+#define AVX_AUTH_PAM "/etc/pam.d/array-common-auth.pam"
+#define AVX_ACCT_PAM "/etc/pam.d/array-common-acct.pam"
+#define _AVX_PAM_FIRST_PASS "[success=done default=ignore]"
+#define _AVX_PAM_LAST_PASS "[success=done default=bad]"
+#define _AVX_PAM_USE_RADIUS "pam_radius_auth.so"
+#define _AVX_PAM_USE_UNIX "pam_unix.so"
+
+#define _AVX_WRITE_PAM_CONF(conf, type, BODY)                                  \
+    do {                                                                       \
+        FILE *fp = fopen(conf, "w");                                           \
+        if (!fp) {                                                             \
+            printf("Cannot open %s PAM conf\n", type);                         \
+            return -1;                                                         \
+        }                                                                      \
+        BODY fclose(fp);                                                       \
+    } while (0)
+
+#define _AVX_WRITE_PASS(type, ctrl, mod)                                       \
+    fprintf(fp, "%s %s %s", type, ctrl, mod)
+
+#define _AVX_WRITE_LF fprintf(fp, "\n")
+
+int exauth_on() {
+	_AVX_WRITE_PAM_CONF(
+        AVX_AUTH_PAM, "auth",
+        _AVX_WRITE_PASS("auth", _AVX_PAM_FIRST_PASS, _AVX_PAM_USE_RADIUS);
+        _AVX_WRITE_LF;
+        _AVX_WRITE_PASS("auth", _AVX_PAM_LAST_PASS, _AVX_PAM_USE_UNIX););
+
+    _AVX_WRITE_PAM_CONF(
+        AVX_ACCT_PAM, "account",
+        _AVX_WRITE_PASS("account", _AVX_PAM_FIRST_PASS, _AVX_PAM_USE_RADIUS);
+        _AVX_WRITE_LF;
+        _AVX_WRITE_PASS("account", _AVX_PAM_LAST_PASS, _AVX_PAM_USE_UNIX););
+
+    /* Activate NSS of RADIUS users */
+    system("sed -i '/^passwd:/s/$/ ato/' " AVX_NSS_CONF);
+    system("sed -i '/^shadow:/s/$/ ato/' " AVX_NSS_CONF);
+
+    sleep(1);
+
+    exauth_conf.status = AVX_EXAUTH_ON;
+
+    return 0;
+}
+
+int exauth_off() {
+    _AVX_WRITE_PAM_CONF(
+        AVX_AUTH_PAM, "auth",
+        _AVX_WRITE_PASS("auth", _AVX_PAM_LAST_PASS, _AVX_PAM_USE_UNIX););
+
+    _AVX_WRITE_PAM_CONF(
+        AVX_ACCT_PAM, "account",
+        _AVX_WRITE_PASS("account", _AVX_PAM_LAST_PASS, _AVX_PAM_USE_UNIX););
+
+    /* Deactivate NSS of RADIUS user */
+    system("sed -i '/^passwd:/s/ ato//g' " AVX_NSS_CONF);
+    system("sed -i '/^shadow:/s/ ato//g' " AVX_NSS_CONF);
+
+    sleep(1);
+
+    exauth_conf.status =AVX_EXAUTH_OFF;
+
+    return 0;
+}
+
+#define AVX_RADIUS_CONF "/etc/pam_radius.conf"
+#define _AVX_RADIUS_TIMEOUT 3
+#define _AVX_EXAUTH_SET_ATTR(h, p, s) \
+    do { \
+        strncpy(exauth_conf.host, h, _AVX_EXAUTH_STR_LEN); \
+        exauth_conf.port = p; \
+        strncpy(exauth_conf.secret, s, _AVX_EXAUTH_STR_LEN); \
+    } while(0)
+
+int set_radius_server(
+    char *host,
+    uint16_t port,
+    char *secret
+) {
+    FILE *fp = fopen(AVX_RADIUS_CONF, "w");
+    if(!fp) {
+        printf("Cannot open RADIUS server config\n");
+        return -1;
+    }
+
+    fprintf(fp, "%s:%d %s %d", host, port, secret, _AVX_RADIUS_TIMEOUT);
+
+    fclose(fp);
+
+    sleep(1);
+
+    _AVX_EXAUTH_SET_ATTR(host, port, secret);
+
+    printf(
+        "host: %s, port: %d, secret: %s\n",
+        exauth_conf.host,
+        exauth_conf.port,
+        exauth_conf.secret
+    );
+
+    return 0;
+}
+
+int unset_radius_server() {
+    system("rm -rf " AVX_RADIUS_CONF);
+
+    sleep(1);
+
+    const char *EMPTY_STR = "";
+
+    _AVX_EXAUTH_SET_ATTR(EMPTY_STR, 0, EMPTY_STR);
+
+    printf(
+        "host: %s, port: %d, secret: %s\n",
+        exauth_conf.host,
+        exauth_conf.port,
+        exauth_conf.secret
+    );
+
+    return 0;
+}
+
+char *write_exauth_conf(void) {
+    return NULL;
+}
+
+int show_exauth_all(void) {
+    return 0;
+}
Index: /branches/rel_avx_2_7_2/src/backend/sys_tool.h
===================================================================
--- /branches/rel_avx_2_7_2/src/backend/sys_tool.h	(revision 8849)
+++ /branches/rel_avx_2_7_2/src/backend/sys_tool.h	(working copy)
@@ -72,6 +72,10 @@
 extern char* write_system_interactive(void);
 extern char* write_if_shutdown(void);
 extern char* write_if_description(void);
+extern char* write_exauth_conf(void);
+
+extern int show_exauth_all(void);
+
 extern int clear_nameserver(char *ip);
 extern int clear_iphost(void);
 extern int ui_clear_supportip(void);
Index: /branches/rel_avx_2_7_2/src/backend/sys_tool.c
===================================================================
--- /branches/rel_avx_2_7_2/src/backend/sys_tool.c	(revision 8849)
+++ /branches/rel_avx_2_7_2/src/backend/sys_tool.c	(working copy)
@@ -358,6 +358,11 @@
         CMD_NORMAL | CMD_ARRAYOS | CMD_GLOBAL,
         "#interface description"
     },
+    {
+        write_exauth_conf,
+        CMD_NORMAL | CMD_ARRAYOS | CMD_GLOBAL,
+        "#admin aaa configuration"
+    },
     /*last entry is empty*/
     {
         NULL,
Index: /branches/rel_avx_2_7_2/src/generator/commands.pm
===================================================================
--- /branches/rel_avx_2_7_2/src/generator/commands.pm	(revision 8849)
+++ /branches/rel_avx_2_7_2/src/generator/commands.pm	(working copy)
@@ -7239,6 +7239,145 @@
             optional => "NO",
         }, ],
     },
+    {
+        obj_type => "MENU",
+        name => "admin",
+        parent_menu => ".",
+        uniq_name => "root_admin",
+        cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL",
+        user_level => "CLI_LEVEL_CONFIG",
+        help_string => "Administration configuration",
+    },
+    {
+        obj_type => "MENU",
+        name => "aaa",
+        parent_menu => "root_admin",
+        uniq_name => "root_admin_aaa",
+        cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL",
+        user_level => "CLI_LEVEL_CONFIG",
+        help_string => "External authentication configuration",
+    },
+    {
+        obj_type => "MENU",
+        name => "server",
+        parent_menu => "root_admin_aaa",
+        uniq_name => "root_admin_server_aaa",
+        cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL",
+        user_level => "CLI_LEVEL_CONFIG",
+        help_string => "External authentication server configuration",
+    },
+    {
+        obj_type => "ITEM",
+        name => "es01",
+        menu => "root_admin_server_aaa",
+        help_string => "Configure external RADIUS authentication server",
+        cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL|CMD_GLOBAL|CMD_SPECIAL_LOG",
+        user_level => "CLI_LEVEL_CONFIG",
+        function_name => "set_radius_server",
+        function_args => [
+            {
+                type => "STRING",
+                help_string => "Host name or ip address",
+                optional => "NO",
+            },
+            {
+                type => "U16",
+                help_string => "Port",
+                optional => "NO",
+            },
+            {
+                type => "STRING",
+                help_string => "Secret",
+                optional => "YES",
+                default_value => "\"\"",
+            },
+        ],
+    },
+    {
+        obj_type => "MENU",
+        name => "admin",
+        parent_menu => "root_no",
+        uniq_name => "root_no_admin",
+        cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL",
+        user_level => "CLI_LEVEL_CONFIG",
+        help_string => "Delete administration configurations",
+    },
+	{
+        obj_type => "MENU",
+        name => "aaa",
+        parent_menu => "root_no_admin",
+        uniq_name => "root_no_admin_aaa_server",
+        cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL",
+        user_level => "CLI_LEVEL_ENABLE",
+        help_string => "Delete external authentication configurations",
+    },
+    {
+        obj_type => "MENU",
+        name => "server",
+        parent_menu => "root_no_admin_aaa_server",
+        uniq_name => "root_no_admin_aaa",
+        help_string => "Delete external authentication server",
+        cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL|CMD_GLOBAL",
+        user_level => "CLI_LEVEL_CONFIG",
+    },
+	{
+        obj_type => "ITEM",
+        name => "es01",
+        menu => "root_no_admin_aaa",
+        help_string => "Delete external RADIUS authentication server",
+        cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL|CMD_GLOBAL|CMD_SPECIAL_LOG",
+        user_level => "CLI_LEVEL_CONFIG",
+        function_name => "unset_radius_server",
+        function_args => [],
+    },
+    {
+        obj_type => "ITEM",
+        name => "on",
+        menu => "root_admin_aaa",
+        help_string => "Turn on external authentication",
+        cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL|CMD_GLOBAL",
+        user_level => "CLI_LEVEL_CONFIG",
+        function_name => "exauth_on",
+        function_args => [],
+    },
+    {
+        obj_type => "ITEM",
+        name => "off",
+        menu => "root_admin_aaa",
+        help_string => "Turn off external authentication",
+        cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL|CMD_GLOBAL",
+        user_level => "CLI_LEVEL_CONFIG",
+        function_name => "exauth_off",
+        function_args => [],
+    },
+    {
+        obj_type => "MENU",
+        name => "admin",
+        parent_menu => "root_show",
+        uniq_name => "root_show_admin",
+        cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL",
+        user_level => "CLI_LEVEL_ENABLE",
+        help_string => "Display administration configurations",
+    },
+    {
+        obj_type => "MENU",
+        name => "aaa",
+        parent_menu => "root_show_admin",
+        uniq_name => "root_show_admin_aaa",
+        cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL",
+        user_level => "CLI_LEVEL_ENABLE",
+        help_string => "Display external authentication configurations",
+    },
+    {
+        obj_type => "ITEM",
+        name => "all",
+        menu => "root_show_admin_aaa",
+        help_string => "Display all external authentication configurations",
+        cmd_attribute => "CMD_ARRAYOS|CMD_NORMAL|CMD_GLOBAL",
+        user_level => "CLI_LEVEL_ENABLE",
+        function_name => "show_exauth_all",
+        function_args => [],
+    },
 );
 
 # This method is required to expost the command table to the caller.
