想把zdclient融合到n14u的路由器当中,原因你懂的,坑爹的神州数码!
首先来看看zdclient的输出(成功登录)
######## ZDClient ver. 0.12 $Revision: 93 $ #########
Device:
MAC: 00:12:34:56:78:9b
IP: 0.0.0.0
MASK: 0.0.0.0
Gateway: 0.0.0.0
DNS: 0.0.0.0
Client ver: 3.5.04.1110fk
##################################################
>>Protocol: SEND EAPOL-Start
>>Protocol: REQUEST EAP-Identity
>>Protocol: EAP_SUCCESS
&&Info: Authorized Access to Network.
在N14U的TTL console看到了几个关键的信息:
根据这几个关键字,8021x-md5,stop_auth。还是利用grep,找到了router/rc目录。value lan_ipaddr=192.168.1.1 value lan_netmask=255.255.255.0 value dhcpc_mode=1 value wan_unit=0 value wan_enable=1 value wan_proto=dhcp value wan_nat_x=1 value wan_dhcpenable_x=1 value wan_dnsenable_x=1 value wan_heartbeat_x= value wan_hostname= value wan_hwaddr_x=00:11:22:33:44:55 value wan_auth_x=8021x-md5 value wan_pppoe_username=uuuuuuuuuu value wan_pppoe_passwd=xxxxxx value wan_upnp_enable=1 value wan_vpndhcp=1
_ifconfig: name=vlan2 flags=1043 IFUP addr=0.0.0.0 netmask=(null) wan_down(vlan2) wan_down(vlan2): . stop_auth:: done route_manip: cmd=DEL name=vlan2 addr=0.0.0.0 netmask=0.0.0.0 gateway=(null) metric=0 update_wan_state(wan0_, 3, 0) update_wan_state(wan0_, 4, 3)
里面的auth.c包含了主要认证过程代码,代码不长,全部粘贴出来:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <bcmnvram.h>
#include <netconf.h>
#include <shutils.h>
#include <rc.h>
#include <shared.h>
#ifdef RTCONFIG_EAPOL
static int
start_wpa_supplicant(int unit, int restart)
{
FILE *fp;
char tmp[100];
char prefix[] = "wanXXXXXXXXXX_";
char options[sizeof("/etc/wpa_supplicantXXXXXXXXXX.conf")];
char pidfile[sizeof("/var/run/wpa_supplicantXXXXXXXXXX.pid")];
char *wpa_argv[] = {"/usr/sbin/wpa_supplicant",
"-B", "-W",
"-i", NULL, /* interface */
"-D", "wired",
"-c", options,
"-P", pidfile,
NULL
};
char *cli_argv[] = {"/usr/sbin/wpa_cli",
"-B",
"-i", NULL, /* interface */
"-a", "/tmp/wpa_cli",
NULL};
int ret;
snprintf(prefix, sizeof(prefix), "wan%d_", unit);
snprintf(options, sizeof(options), "/etc/wpa_supplicant%d.conf", unit);
snprintf(pidfile, sizeof(pidfile), "/var/run/wpa_supplicant%d.pid", unit);
if (restart && pids("wpa_supplicant"))
return kill_pidfile_s(pidfile, SIGUSR2);
/* Get interface */
wpa_argv[4] = nvram_safe_get(strcat_r(prefix, "ifname", tmp));
cli_argv[3] = wpa_argv[4];
/* Get driver, wired default */
#ifndef RTCONFIG_RALINK /* Both BCM 5.x and 6.x */
if (get_switch() == SWITCH_BCM5325)
wpa_argv[6] = "roboswitch";
#endif
/* Generate options file */
if ((fp = fopen(options, "w")) == NULL) {
perror(options);
return -1;
}
fprintf(fp,
"ctrl_interface=/var/run/wpa_supplicant\n"
"ap_scan=0\n"
"fast_reauth=1\n"
"network={\n"
" key_mgmt=IEEE8021X\n"
" eap=MD5\n"
" identity=\"%s\"\n"
" password=\"%s\"\n"
" eapol_flags=0\n"
"}\n",
nvram_safe_get(strcat_r(prefix, "pppoe_username", tmp)),
nvram_safe_get(strcat_r(prefix, "pppoe_passwd", tmp)));
fclose(fp);
/* Start supplicant & monitor */
ret = _eval(wpa_argv, NULL, 0, NULL);
if (ret == 0)
_eval(cli_argv, NULL, 0, NULL);
return 0;
}
static int
stop_wpa_supplicant(int unit)
{
char pidfile[sizeof("/var/run/wpa_supplicantXXXXXXXXXX.pid")];
snprintf(pidfile, sizeof(pidfile), "/var/run/wpa_supplicant%d.pid", unit);
kill_pidfile_tk(pidfile);
/* It dies automagicaly after the supplicant is gone,
if (pids("wpa_cli"))
killall_tk("wpa_cli"); */
return 0;
}
int
wpacli_main(int argc, char **argv)
{
char tmp[100];
char prefix[] = "wanXXXXXXXXXX_";
int unit;
if (argc < 3 || (unit = wan_ifunit(argv[1])) < 0)
return EINVAL;
snprintf(prefix, sizeof(prefix), "wan%d_", unit);
if (!nvram_match(strcat_r(prefix, "auth_x", tmp), "8021x-md5"))
return 0;
if (strncmp(argv[2], "CONNECTED", sizeof("CONNECTED")) == 0)
{
/* Called only once, no action */
}
if (strncmp(argv[2], "EAP-SUCCESS", sizeof("EAP-SUCCESS")) == 0)
{
/* Called multiple times on success (re)auth */
logmessage("802.1x client", "authenticated");
/* TODO: refresh dhcp? */
} else
if (strncmp(argv[2], "EAP-FAILURE", sizeof("EAP-FAILURE")) == 0)
{
/* Called every/multiple times on (re)auth fail and/or timeout */
if (nvram_get_int(strcat_r(prefix, "state_t", tmp)) != WAN_STATE_STOPPED)
logmessage("802.1x client", "authentication failed");
/* Reuse auth-fail state */
update_wan_state(prefix, WAN_STATE_STOPPED, WAN_STOPPED_REASON_PPP_AUTH_FAIL);
}
if (strncmp(argv[2], "DISCONNECTED", sizeof("DISCONNECTED")) == 0)
{
/* Called only once, no action */
}
return 0;
}
#endif
int
start_auth(int unit, int wan_up)
{
char tmp[100];
char prefix[] = "wanXXXXXXXXXX_";
char *wan_proto, *wan_auth;
int ret = -1;
snprintf(prefix, sizeof(prefix), "wan%d_", unit);
wan_proto = nvram_safe_get(strcat_r(prefix, "proto", tmp));
if (strcmp(wan_proto, "static") != 0 &&
strcmp(wan_proto, "dhcp") != 0)
return -1;
wan_auth = nvram_safe_get(strcat_r(prefix, "auth_x", tmp));
#ifdef RTCONFIG_EAPOL
if (strcmp(wan_auth, "8021x-md5") == 0 && !wan_up)
ret = start_wpa_supplicant(unit, 0);
#endif
_dprintf("%s:: done\n", __func__);
return ret;
}
int
stop_auth(int unit, int wan_down)
{
char tmp[100];
char prefix[] = "wanXXXXXXXXXX_";
char *wan_proto;
int ret = -1;
snprintf(prefix, sizeof(prefix), "wan%d_", unit);
wan_proto = nvram_safe_get(strcat_r(prefix, "proto", tmp));
if (strcmp(wan_proto, "static") != 0 &&
strcmp(wan_proto, "dhcp") != 0)
return -1;
#ifdef RTCONFIG_EAPOL
if (!wan_down)
ret = stop_wpa_supplicant(unit);
#endif
_dprintf("%s:: done\n", __func__);
return ret;
}
int
restart_auth(int unit)
{
char tmp[100];
char prefix[] = "wanXXXXXXXXXX_";
char *wan_proto, *wan_auth;
int ret = -1;
snprintf(prefix, sizeof(prefix), "wan%d_", unit);
wan_proto = nvram_safe_get(strcat_r(prefix, "proto", tmp));
if (strcmp(wan_proto, "static") != 0 &&
strcmp(wan_proto, "dhcp") != 0)
return -1;
wan_auth = nvram_safe_get(strcat_r(prefix, "auth_x", tmp));
#ifdef RTCONFIG_EAPOL
if (strcmp(wan_auth, "8021x-md5") == 0)
ret = start_wpa_supplicant(unit, 1);
#endif
_dprintf("%s:: done\n", __func__);
return ret;
}
关键的代码在start_wpa_supplicant中,实际上是调用了/usr/sbin/wpa_supplicant认证程序和/usr/sbin/wpa_cli监控程序(我的描述是否正确?)
那么,接下来,就要研究如何把zdclient加入到package中,然后再来个“狸猫换太子”,把wpa_supplicant替换成我们的zdclient。