RT-N14U源码研究之——wpa_supplicant

想把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看到了几个关键的信息:

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)
根据这几个关键字,8021x-md5,stop_auth。还是利用grep,找到了router/rc目录。

里面的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。





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值