// // Created by xajhuang on 2022/5/10. // #include #include #include #include "pppoe_session.h" #include "netif/rawif.h" #include "netif/ppp/ppp.h" #include "netif/ppp/pppoe.h" #include "netif/pppoeif.h" #include "misc.h" #include "user_errno.h" #include "netif/ppp/pppapi.h" #include "config.h" 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; static void pppLinkStatusCallback(ppp_pcb *pcb, int errCode, void *ctx) { struct netif *pppif = ppp_netif(pcb); struct pppoe_softc *sc = (struct pppoe_softc *)pcb->link_ctx_cb; PUSER_INFO_CONTEXT pUser = (PUSER_INFO_CONTEXT)ctx; switch (errCode) { case PPPERR_NONE: { /* No error. */ dzlog_info("<%p> PPPoE user(%05d:%s) connect server succeeded[%08X], Session: %04X\n", pcb, pUser->userid, pUser->user_info.pppoe_user, pcb->lcp_gotoptions.magicnumber, sc->sc_session); #if LWIP_IPV4 dzlog_info(" our_ipaddr = %s\n", ip4addr_ntoa(netif_ip4_addr(pppif))); dzlog_info(" his_ipaddr = %s\n", ip4addr_ntoa(netif_ip4_gw(pppif))); dzlog_info(" netmask = %s\n", ip4addr_ntoa(netif_ip4_netmask(pppif))); #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 */ pUser->session.status = STATUS_TASK_CONNECTED; break; } 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; } break; case PPPERR_USER: dzlog_info("User(%05d:%s) disconnect\n", pUser->userid, pUser->user_info.pppoe_user); break; 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; } break; default: { printf("<%p> pppLinkStatusCallback: unknown errCode %d\n", pcb, errCode); break; } } } _Noreturn void sessionCalcCb(void *UNUSED(pArg)) { PUSER_INFO_CONTEXT pUserList = get_all_user(); do { PUSER_INFO_CONTEXT pUser, pTmp; uv_rwlock_rdlock(get_user_lock()); HASH_ITER(hh, pUserList, pUser, pTmp) { 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; } break; #endif default: break; } } uv_rwlock_rdunlock(get_user_lock()); uv_sleep(1000); } while (TRUE); } int pppoe_session_init() { static uv_thread_t uvThread; g_rawSocketIf = bind_rawsocket_if(config_get_nic_name()); if (g_rawSocketIf) { dzlog_info("Create Raw Socket netif: <%p>\n", (void *)g_rawSocketIf); } // 启动Session状态机线程 uv_thread_create(&uvThread, sessionCalcCb, NULL); 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; } 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; }