2022-05-10 06:43:27 +00:00
|
|
|
//
|
|
|
|
// Created by xajhuang on 2022/5/10.
|
|
|
|
//
|
|
|
|
#include <zlog.h>
|
2022-06-02 08:18:43 +00:00
|
|
|
#include <uv/unix.h>
|
|
|
|
#include <uv.h>
|
2022-06-06 03:46:09 +00:00
|
|
|
#include <uthash/utlist.h>
|
|
|
|
#include <cjson/cJSON.h>
|
2022-05-10 06:43:27 +00:00
|
|
|
#include "pppoe_session.h"
|
|
|
|
#include "netif/rawif.h"
|
|
|
|
#include "netif/ppp/ppp.h"
|
|
|
|
#include "netif/ppp/pppoe.h"
|
2022-05-30 12:16:50 +00:00
|
|
|
#include "netif/pppoeif.h"
|
2022-06-02 08:18:43 +00:00
|
|
|
#include "misc.h"
|
|
|
|
#include "user_errno.h"
|
|
|
|
#include "netif/ppp/pppapi.h"
|
|
|
|
#include "config.h"
|
2022-06-06 03:46:09 +00:00
|
|
|
#include "msg_queue.h"
|
|
|
|
|
|
|
|
typedef struct PPPOE_CACHE {
|
|
|
|
PPPPOE_SESSION_DATA pSessionData;
|
|
|
|
|
|
|
|
struct PPPOE_CACHE *next, *prev;
|
|
|
|
} PPPOE_CACHE, *PPPPOE_CACHE;
|
2022-06-02 08:18:43 +00:00
|
|
|
|
|
|
|
struct PPPOE_ERR_INFO_ {
|
|
|
|
int errid;
|
|
|
|
const char *errmsg;
|
|
|
|
} g_pppoeErr[] = {
|
|
|
|
{PPPERR_NONE, "No error"},
|
|
|
|
{PPPERR_PARAM, "Invalid parameter"},
|
|
|
|
{PPPERR_OPEN, "Unable to open PPP session"},
|
|
|
|
{PPPERR_DEVICE, "Invalid I/O device for PPP"},
|
|
|
|
{PPPERR_ALLOC, "Unable to allocate resources"},
|
|
|
|
{PPPERR_USER, "User interrupt"},
|
|
|
|
{PPPERR_CONNECT, "Connection lost"},
|
|
|
|
{PPPERR_AUTHFAIL, "Failed authentication challenge"},
|
|
|
|
{PPPERR_PROTOCOL, "Failed to meet protocol"},
|
|
|
|
{PPPERR_PEERDEAD, "Connection timeout"},
|
|
|
|
{PPPERR_IDLETIMEOUT, "Idle Timeout"},
|
|
|
|
{PPPERR_CONNECTTIME, "Max connect time reach max time"},
|
|
|
|
{PPPERR_LOOPBACK, "Loopback detect"},
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct netif *g_rawSocketIf = NULL;
|
2022-06-06 03:46:09 +00:00
|
|
|
static PPPPOE_CACHE g_pPPPCache = NULL;
|
|
|
|
static uv_rwlock_t g_cacheLock;
|
2022-05-10 06:43:27 +00:00
|
|
|
|
|
|
|
static void pppLinkStatusCallback(ppp_pcb *pcb, int errCode, void *ctx) {
|
2022-05-30 12:16:50 +00:00
|
|
|
struct netif *pppif = ppp_netif(pcb);
|
|
|
|
struct pppoe_softc *sc = (struct pppoe_softc *)pcb->link_ctx_cb;
|
2022-06-02 08:18:43 +00:00
|
|
|
PUSER_INFO_CONTEXT pUser = (PUSER_INFO_CONTEXT)ctx;
|
2022-05-10 06:43:27 +00:00
|
|
|
|
|
|
|
switch (errCode) {
|
|
|
|
case PPPERR_NONE: { /* No error. */
|
2022-06-06 03:46:09 +00:00
|
|
|
PPPPOE_CACHE pCache = (PPPPOE_CACHE)malloc(sizeof(PPPOE_CACHE));
|
2022-06-02 08:18:43 +00:00
|
|
|
dzlog_info("<%p> PPPoE user(%05d:%s) connect server succeeded[%08X], Session: %04X\n",
|
2022-05-30 12:16:50 +00:00
|
|
|
pcb,
|
2022-06-06 03:46:09 +00:00
|
|
|
pUser->userid,
|
|
|
|
pUser->user_info.pppoe_user,
|
2022-05-30 12:16:50 +00:00
|
|
|
pcb->lcp_gotoptions.magicnumber,
|
|
|
|
sc->sc_session);
|
2022-05-10 06:43:27 +00:00
|
|
|
#if LWIP_IPV4
|
2022-06-06 03:46:09 +00:00
|
|
|
memset(&pUser->session.data, 0, sizeof(PPPOE_SESSION_DATA));
|
|
|
|
pUser->session.data.sessionId = sc->sc_session;
|
|
|
|
strncpy(pUser->session.data.clientIp, ip4addr_ntoa(netif_ip4_addr(pppif)), MAX_IP_V4_STR);
|
|
|
|
strncpy(pUser->session.data.clientGw, ip4addr_ntoa(netif_ip4_gw(pppif)), MAX_IP_V4_STR);
|
|
|
|
strncpy(pUser->session.data.clientMask, ip4addr_ntoa(netif_ip4_netmask(pppif)), MAX_IP_V4_STR);
|
|
|
|
sprintf(pUser->session.data.clientMac,
|
|
|
|
"%02X:%02X:%02X:%02X:%02X:%02X",
|
|
|
|
pUser->user_info.mac_addr[0],
|
|
|
|
pUser->user_info.mac_addr[1],
|
|
|
|
pUser->user_info.mac_addr[2],
|
|
|
|
pUser->user_info.mac_addr[3],
|
|
|
|
pUser->user_info.mac_addr[4],
|
|
|
|
pUser->user_info.mac_addr[5]);
|
|
|
|
dzlog_info(" our_ipaddr = %s\n", pUser->session.data.clientIp);
|
|
|
|
dzlog_info(" his_ipaddr = %s\n", pUser->session.data.clientGw);
|
|
|
|
dzlog_info(" netmask = %s\n", pUser->session.data.clientMask);
|
2022-05-10 06:43:27 +00:00
|
|
|
#endif /* LWIP_IPV4 */
|
|
|
|
#if LWIP_DNS
|
|
|
|
dzlog_info(" dns1 = %s\n", ipaddr_ntoa(dns_getserver(0)));
|
|
|
|
dzlog_info(" dns2 = %s\n", ipaddr_ntoa(dns_getserver(1)));
|
|
|
|
#endif /* LWIP_DNS */
|
|
|
|
#if PPP_IPV6_SUPPORT
|
|
|
|
dzlog_info(" our6_ipaddr = %s\n", ip6addr_ntoa(netif_ip6_addr(pppif, 0)));
|
|
|
|
#endif /* PPP_IPV6_SUPPORT */
|
2022-06-06 03:46:09 +00:00
|
|
|
|
|
|
|
if (pCache) {
|
|
|
|
pCache->pSessionData = &pUser->session.data;
|
|
|
|
uv_rwlock_wrlock(&g_cacheLock);
|
|
|
|
LL_APPEND(g_pPPPCache, pCache);
|
|
|
|
uv_rwlock_wrunlock(&g_cacheLock);
|
|
|
|
}
|
2022-06-02 08:18:43 +00:00
|
|
|
pUser->session.status = STATUS_TASK_CONNECTED;
|
2022-05-10 06:43:27 +00:00
|
|
|
break;
|
|
|
|
}
|
2022-06-02 08:18:43 +00:00
|
|
|
case PPPERR_PARAM:
|
|
|
|
case PPPERR_AUTHFAIL:
|
|
|
|
case PPPERR_PROTOCOL:
|
|
|
|
dzlog_error("<%p> pppLinkStatusCallback: %s(%d)",
|
|
|
|
pcb,
|
|
|
|
g_pppoeErr[errCode].errmsg,
|
|
|
|
g_pppoeErr[errCode].errid);
|
|
|
|
if (pUser->session.status != STATUS_TASK_DELETE) {
|
|
|
|
pUser->session.status = STATUS_TASK_ERROR;
|
|
|
|
}
|
2022-05-10 06:43:27 +00:00
|
|
|
break;
|
2022-06-02 08:18:43 +00:00
|
|
|
case PPPERR_USER:
|
|
|
|
dzlog_info("User(%05d:%s) disconnect\n", pUser->userid, pUser->user_info.pppoe_user);
|
2022-05-10 06:43:27 +00:00
|
|
|
break;
|
2022-06-02 08:18:43 +00:00
|
|
|
case PPPERR_OPEN:
|
|
|
|
case PPPERR_DEVICE:
|
|
|
|
case PPPERR_ALLOC:
|
|
|
|
case PPPERR_CONNECT:
|
|
|
|
case PPPERR_PEERDEAD:
|
|
|
|
case PPPERR_IDLETIMEOUT:
|
|
|
|
case PPPERR_CONNECTTIME:
|
|
|
|
case PPPERR_LOOPBACK:
|
|
|
|
dzlog_error("<%p> pppLinkStatusCallback: %s(%d)\n",
|
|
|
|
pcb,
|
|
|
|
g_pppoeErr[errCode].errmsg,
|
|
|
|
g_pppoeErr[errCode].errid);
|
|
|
|
if (pUser->session.status != STATUS_TASK_DELETE) {
|
|
|
|
pUser->session.status = STATUS_TASK_DISCONNECTED;
|
|
|
|
}
|
2022-05-10 06:43:27 +00:00
|
|
|
break;
|
|
|
|
default: {
|
|
|
|
printf("<%p> pppLinkStatusCallback: unknown errCode %d\n", pcb, errCode);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-02 08:18:43 +00:00
|
|
|
_Noreturn void sessionCalcCb(void *UNUSED(pArg)) {
|
2022-06-07 03:29:05 +00:00
|
|
|
PUSER_INFO_CONTEXT pUserList = get_all_user_by_id();
|
2022-05-30 12:16:50 +00:00
|
|
|
|
2022-06-02 08:18:43 +00:00
|
|
|
do {
|
|
|
|
PUSER_INFO_CONTEXT pUser, pTmp;
|
|
|
|
|
|
|
|
uv_rwlock_rdlock(get_user_lock());
|
2022-06-06 03:46:09 +00:00
|
|
|
HASH_ITER(hh_id, pUserList, pUser, pTmp) {
|
2022-06-02 08:18:43 +00:00
|
|
|
PPPPOE_SESSION pSession = &pUser->session;
|
|
|
|
|
|
|
|
switch (pSession->status) {
|
|
|
|
case STATUS_TASK_INIT:
|
|
|
|
if (pppoe_session_create(pUser) == ERR_SUCCESS) {
|
|
|
|
dzlog_debug("User(%05d:%s) init pppoe session\n", pUser->userid, pUser->user_info.pppoe_user);
|
|
|
|
pSession->status = STATUS_TASK_DIAL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case STATUS_TASK_DIAL:
|
|
|
|
if (pUser->session.retry.timeout == 0) {
|
|
|
|
dzlog_debug("User(%05d:%s) connect PPPoE server\n", pUser->userid, pUser->user_info.pppoe_user);
|
|
|
|
pppapi_connect(pSession->ppp, 0);
|
|
|
|
pUser->session.retry.timeout = time(NULL) + PPPOE_MAX_TIMEOUT;
|
|
|
|
} else if (time(NULL) > pUser->session.retry.timeout) {
|
|
|
|
pUser->session.retry.timeout = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case STATUS_TASK_ERROR:
|
|
|
|
if (pUser->session.retry.timeout == 0) {
|
|
|
|
dzlog_error("User(%05d:%s) PPPoE dial error Invalid parameter\n",
|
|
|
|
pUser->userid,
|
|
|
|
pUser->user_info.pppoe_user);
|
|
|
|
// 10秒后尝试重新拨号
|
|
|
|
pUser->session.retry.timeout = time(NULL) + (PPPOE_MAX_TIMEOUT / 2);
|
|
|
|
pUser->session.retry.count = 0;
|
|
|
|
} else if (time(NULL) > pUser->session.retry.timeout) {
|
|
|
|
dzlog_warn("User(%05d:%s) retry dial %u times\n",
|
|
|
|
pUser->userid,
|
|
|
|
pUser->user_info.pppoe_user,
|
|
|
|
pUser->session.retry.count);
|
|
|
|
pUser->session.retry.timeout = 0;
|
|
|
|
pUser->session.retry.count++;
|
|
|
|
|
|
|
|
// 下次重新拨号
|
|
|
|
pSession->status = STATUS_TASK_DIAL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATUS_TASK_DISCONNECTED:
|
|
|
|
// 自动重新拨号
|
|
|
|
pSession->status = STATUS_TASK_DIAL;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATUS_TASK_DELETE:
|
|
|
|
if (pUser->session.retry.timeout == 0) {
|
|
|
|
dzlog_debug("User(%05d:%s) PPPoE deleted\n", pUser->userid, pUser->user_info.pppoe_user);
|
|
|
|
pUser->session.retry.timeout = time(NULL);
|
|
|
|
pppapi_free(pUser->session.ppp);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
#if 0
|
|
|
|
case STATUS_TASK_CONNECTED:
|
|
|
|
if (pUser->session.retry.timeout == 0) {
|
|
|
|
pUser->session.retry.timeout = time(NULL) + 30;
|
|
|
|
} else if (time(NULL) > pUser->session.retry.timeout) {
|
|
|
|
dzlog_debug("User(%05d:%s) PPPoE disconnected\n", pUser->userid, pUser->user_info.pppoe_user);
|
|
|
|
pSession->status = STATUS_TASK_DELETE;
|
|
|
|
pppapi_close(pUser->session.ppp, 0);
|
|
|
|
pUser->session.retry.timeout = 0;
|
|
|
|
}
|
2022-06-06 03:46:09 +00:00
|
|
|
|
2022-06-02 08:18:43 +00:00
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
uv_rwlock_rdunlock(get_user_lock());
|
|
|
|
uv_sleep(1000);
|
|
|
|
} while (TRUE);
|
2022-05-30 12:16:50 +00:00
|
|
|
}
|
2022-05-10 06:43:27 +00:00
|
|
|
|
2022-06-06 03:46:09 +00:00
|
|
|
_Noreturn void cacheCalcCb(void *UNUSED(pArg)) {
|
|
|
|
do {
|
|
|
|
PPPPOE_CACHE pCache, pTmp;
|
|
|
|
int count;
|
|
|
|
|
|
|
|
uv_rwlock_rdlock(&g_cacheLock);
|
|
|
|
LL_COUNT(g_pPPPCache, pCache, count);
|
|
|
|
uv_rwlock_rdunlock(&g_cacheLock);
|
|
|
|
|
|
|
|
if (count > 0) {
|
2022-06-07 03:29:05 +00:00
|
|
|
const char *pJsonString;
|
|
|
|
cJSON *pRoot = cJSON_CreateObject();
|
|
|
|
cJSON *pSession = cJSON_CreateArray();
|
2022-06-06 03:46:09 +00:00
|
|
|
cJSON_AddStringToObject(pRoot, "message", "add-ywg-pppoe");
|
|
|
|
|
|
|
|
uv_rwlock_wrlock(&g_cacheLock);
|
|
|
|
LL_FOREACH_SAFE(g_pPPPCache, pCache, pTmp) {
|
|
|
|
cJSON *pItem = cJSON_CreateObject();
|
|
|
|
cJSON_AddNumberToObject(pItem, "sessionId", pCache->pSessionData->sessionId);
|
|
|
|
cJSON_AddStringToObject(pItem, "clientIp", pCache->pSessionData->clientIp);
|
|
|
|
cJSON_AddStringToObject(pItem, "clientGw", pCache->pSessionData->clientGw);
|
|
|
|
cJSON_AddStringToObject(pItem, "clientMask", pCache->pSessionData->clientMask);
|
|
|
|
cJSON_AddStringToObject(pItem, "clientMac", pCache->pSessionData->clientMac);
|
2022-06-07 03:29:05 +00:00
|
|
|
cJSON_AddStringToObject(pItem, "localMac", pCache->pSessionData->svrBaseMac);
|
2022-06-06 03:46:09 +00:00
|
|
|
cJSON_AddItemToArray(pSession, pItem);
|
|
|
|
LL_DELETE(g_pPPPCache, pCache);
|
|
|
|
free(pCache);
|
|
|
|
}
|
|
|
|
uv_rwlock_wrunlock(&g_cacheLock);
|
|
|
|
cJSON_AddItemToObject(pRoot, "params", pSession);
|
2022-06-07 03:29:05 +00:00
|
|
|
pJsonString = cJSON_PrintUnformatted(pRoot);
|
|
|
|
mq_data_send_msg(pJsonString);
|
2022-06-06 03:46:09 +00:00
|
|
|
cJSON_Delete(pRoot);
|
2022-06-07 03:29:05 +00:00
|
|
|
free((void*)pJsonString);
|
2022-06-06 03:46:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
uv_sleep(1000);
|
|
|
|
} while (TRUE);
|
|
|
|
}
|
|
|
|
|
2022-05-10 06:43:27 +00:00
|
|
|
int pppoe_session_init() {
|
2022-06-06 03:46:09 +00:00
|
|
|
static uv_thread_t uvThread, cacheThread;
|
|
|
|
uv_rwlock_init(&g_cacheLock);
|
2022-05-10 06:43:27 +00:00
|
|
|
|
2022-06-02 08:18:43 +00:00
|
|
|
g_rawSocketIf = bind_rawsocket_if(config_get_nic_name());
|
2022-05-30 12:16:50 +00:00
|
|
|
|
2022-06-02 08:18:43 +00:00
|
|
|
if (g_rawSocketIf) {
|
|
|
|
dzlog_info("Create Raw Socket netif: <%p>\n", (void *)g_rawSocketIf);
|
2022-05-30 12:16:50 +00:00
|
|
|
}
|
|
|
|
|
2022-06-02 08:18:43 +00:00
|
|
|
// 启动Session状态机线程
|
|
|
|
uv_thread_create(&uvThread, sessionCalcCb, NULL);
|
2022-06-06 03:46:09 +00:00
|
|
|
uv_thread_create(&cacheThread, cacheCalcCb, NULL);
|
2022-06-02 08:18:43 +00:00
|
|
|
return ERR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
int pppoe_session_create(PUSER_INFO_CONTEXT pUser) {
|
|
|
|
ppp_pcb *ppp;
|
|
|
|
struct netif *netif;
|
|
|
|
struct netif *ppp_netif = (struct netif *)malloc(sizeof(struct netif));
|
|
|
|
|
|
|
|
if (ppp_netif == NULL) {
|
|
|
|
dzlog_error("Malloc %lu bytes memory error\n", sizeof(struct netif));
|
|
|
|
return -ERR_MALLOC_MEMORY;
|
2022-05-10 06:43:27 +00:00
|
|
|
}
|
2022-06-02 08:18:43 +00:00
|
|
|
|
|
|
|
netif = create_pppoe_if(pUser);
|
|
|
|
|
|
|
|
if (netif == NULL) {
|
|
|
|
dzlog_error("Create PPPoE netif error: %u\n", pUser->userid);
|
|
|
|
free((void *)ppp_netif);
|
|
|
|
return -ERR_CREATE_PPPOE_NETIF;
|
|
|
|
}
|
|
|
|
|
|
|
|
pUser->session.nicif = netif;
|
|
|
|
pUser->session.pppif = ppp_netif;
|
|
|
|
|
|
|
|
ppp = pppapi_pppoe_create(pUser->session.pppif, pUser->session.nicif, NULL, NULL, pppLinkStatusCallback, pUser);
|
|
|
|
|
|
|
|
if (ppp == NULL) {
|
|
|
|
dzlog_error("Create PPPoE session error: %u\n", pUser->userid);
|
|
|
|
netif_remove(netif);
|
|
|
|
free((void *)ppp_netif);
|
|
|
|
return -ERR_CREATE_PPP_SESSION;
|
|
|
|
}
|
|
|
|
|
|
|
|
pUser->session.ppp = ppp;
|
|
|
|
|
|
|
|
ppp_set_auth(ppp, PPPAUTHTYPE_ANY, pUser->user_info.pppoe_user, pUser->user_info.pppoe_passwd);
|
|
|
|
|
|
|
|
dzlog_debug("Create PPPoE netif %p: %u(%c%c:%d, %c%c:%d)\n",
|
|
|
|
ppp,
|
|
|
|
pUser->userid,
|
|
|
|
ppp_netif->name[0],
|
|
|
|
ppp_netif->name[1],
|
|
|
|
ppp_netif->num,
|
|
|
|
netif->name[0],
|
|
|
|
netif->name[1],
|
|
|
|
netif->num);
|
|
|
|
|
|
|
|
return ERR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct netif *get_rawsocket_if(void) {
|
|
|
|
return g_rawSocketIf;
|
2022-05-27 07:49:45 +00:00
|
|
|
}
|