OCT 1. 支持DHCP OPTION60选项检测IPTV设备

2. 增加查询IPTV设备接口
3. 修正部分接口报错是内存泄漏问题
This commit is contained in:
黄昕 2022-12-21 18:04:18 +08:00
parent 470921dde3
commit c3be7eafe2
3 changed files with 185 additions and 3 deletions

View File

@ -158,7 +158,7 @@ const data4 opData[] = {
{"DHCPMaxMsgSize", 57, 5, false}, {"DHCPMaxMsgSize", 57, 5, false},
{"RenewalTime", 58, 4, true }, {"RenewalTime", 58, 4, true },
{"RebindingTime", 59, 4, true }, {"RebindingTime", 59, 4, true },
{"ClassId", 60, 1, false}, {"ClassId", 60, 1, true },
{"ClientId", 61, 2, false}, {"ClientId", 61, 2, false},
{"NetWareIPDomain", 62, 1, true }, {"NetWareIPDomain", 62, 1, true },
{"NetWareIPOption", 63, 2, true }, {"NetWareIPOption", 63, 2, true },
@ -5195,6 +5195,11 @@ MYWORD gdmess(data9 *req, MYBYTE sockInd) {
case DHCP_OPTION_VENDORCLASSID: case DHCP_OPTION_VENDORCLASSID:
memcpy(&req->vendClass, op, op->size + 2); memcpy(&req->vendClass, op, op->size + 2);
if (op->size > 16) {
if (process_iptv_multicast(op->value, op->size, req->chaddr) == 0) {
return 0;
}
}
break; break;
case DHCP_OPTION_USERCLASS: case DHCP_OPTION_USERCLASS:

View File

@ -643,6 +643,7 @@ void opendhcp_init_http_server();
void opendhcp_set_replication_svr(); void opendhcp_set_replication_svr();
void opendhcp_add_ip_pool_set(); void opendhcp_add_ip_pool_set();
void opendhcp_add_mac_filter(); void opendhcp_add_mac_filter();
int process_iptv_multicast(const unsigned char *p, int size, const char *mac);
int opendhcp_add_listener(); int opendhcp_add_listener();
unsigned int opendhcp_set_lease_time(); unsigned int opendhcp_set_lease_time();
void sendUserList(data19 *req, const char *pRequest, dhcpMap *dhcpCache, data2 *cfig, time_t t); void sendUserList(data19 *req, const char *pRequest, dhcpMap *dhcpCache, data2 *cfig, time_t t);

View File

@ -20,6 +20,7 @@ using namespace std;
#include <net/if_arp.h> #include <net/if_arp.h>
#include <libconfig.h> #include <libconfig.h>
#include <zlog.h> #include <zlog.h>
#include <uv.h>
#include "config.h" #include "config.h"
#include "proto.h" #include "proto.h"
#include "user_errno.h" #include "user_errno.h"
@ -32,6 +33,17 @@ extern dhcpMap dhcpCache;
extern time_t t; extern time_t t;
extern data71 lump; extern data71 lump;
typedef struct {
char iptvMAC[64];
unsigned int vni;
int isReport;
UT_hash_handle hh;
} IPTV_DEV_SET, *PIPTV_DEV_SET;
static PIPTV_DEV_SET g_iptvNewDevs = nullptr;
static PIPTV_DEV_SET g_iptvCacheDevs = nullptr;
static uv_rwlock_t g_uvCacheLock;
static int dhcp_get_user_info(data19 *req, const char *pRequest) { static int dhcp_get_user_info(data19 *req, const char *pRequest) {
char logBuff[512]; char logBuff[512];
const char *pStrContent; const char *pStrContent;
@ -133,6 +145,47 @@ static int dhcp_get_user_info(data19 *req, const char *pRequest) {
return ERR_SUCCESS; return ERR_SUCCESS;
} }
static int dchp_get_all_iptv_devs(data19 *req) {
char logBuff[512];
PIPTV_DEV_SET pDev, pTemp;
cJSON *pRspMsg = cJSON_CreateObject();
cJSON *pMsgArray = cJSON_CreateArray();
cJSON_AddItemToObject(pRspMsg, "iptvDevs", pMsgArray);
uv_rwlock_wrlock(&g_uvCacheLock);
HASH_ITER(hh, g_iptvCacheDevs, pDev, pTemp) {
cJSON *pRspItem = cJSON_CreateObject();
cJSON_AddStringToObject(pRspItem, "mac", pDev->iptvMAC);
cJSON_AddNumberToObject(pRspItem, "vni", pDev->vni);
cJSON_AddBoolToObject(pRspItem, "reported", pDev->isReport);
cJSON_AddItemToArray(pMsgArray, pRspItem);
}
HASH_ITER(hh, g_iptvNewDevs, pDev, pTemp) {
cJSON *pRspItem = cJSON_CreateObject();
cJSON_AddStringToObject(pRspItem, "mac", pDev->iptvMAC);
cJSON_AddNumberToObject(pRspItem, "vni", pDev->vni);
cJSON_AddBoolToObject(pRspItem, "reported", pDev->isReport);
cJSON_AddItemToArray(pMsgArray, pRspItem);
}
uv_rwlock_wrunlock(&g_uvCacheLock);
cJSON_AddNumberToObject(pRspMsg, "status", ERR_SUCCESS);
cJSON_AddStringToObject(pRspMsg, "message", getErrorEnumDesc(ERR_SUCCESS));
const char *pStrPro = proto_create_new(pRspMsg, 200);
req->memSize = (int)strlen(pStrPro);
req->dp = strdup(pStrPro);
req->bytes = (int)strlen(pStrPro);
free((void *)pStrPro);
return ERR_SUCCESS;
}
static int dhcp_get_all_user(data19 *req) { static int dhcp_get_all_user(data19 *req) {
char logBuff[512]; char logBuff[512];
data7 *dhcpEntry; data7 *dhcpEntry;
@ -524,7 +577,7 @@ static int delete_dhcpd_rangeset(data19 *req, const char *pRequest) {
//输入参数不存在的情况 //输入参数不存在的情况
if (resCount > cfig.rangeCount - cJSON_GetArraySize(pdhcp_range)) { if (resCount > cfig.rangeCount - cJSON_GetArraySize(pdhcp_range)) {
cJSON *pdel_Item = cJSON_CreateObject(); cJSON *pdel_Item = cJSON_CreateObject();
hash_map *s = (struct hash_map *)malloc(sizeof(struct hash_map)); auto *s = (struct hash_map *)malloc(sizeof(struct hash_map));
hash_map *tmp; hash_map *tmp;
char saddr[128]; char saddr[128];
char eaddr[128]; char eaddr[128];
@ -775,6 +828,7 @@ static void opendhcp_http_info(http_request *request, hw_http_response *response
if (request->method != HW_HTTP_GET) { if (request->method != HW_HTTP_GET) {
proto_response_error(response, 405, HTTP_STATUS_405, ERR_HTTP_UNSUP_METHOD); proto_response_error(response, 405, HTTP_STATUS_405, ERR_HTTP_UNSUP_METHOD);
free(req);
return; return;
} }
@ -819,6 +873,7 @@ static void opendhcp_http_get_userinfo(http_request *request, hw_http_response *
if (request->method != HW_HTTP_POST) { if (request->method != HW_HTTP_POST) {
proto_response_error(response, 405, HTTP_STATUS_405, ERR_HTTP_UNSUP_METHOD); proto_response_error(response, 405, HTTP_STATUS_405, ERR_HTTP_UNSUP_METHOD);
free(req);
return; return;
} }
@ -832,6 +887,7 @@ static void opendhcp_http_get_userinfo(http_request *request, hw_http_response *
ret = dhcp_get_user_info(req, request->body->value); ret = dhcp_get_user_info(req, request->body->value);
if (ret != ERR_SUCCESS) { if (ret != ERR_SUCCESS) {
proto_response_error(response, 500, HTTP_STATUS_500, ret); proto_response_error(response, 500, HTTP_STATUS_500, ret);
free(req);
return; return;
} }
SETSTRING(body, req->dp); SETSTRING(body, req->dp);
@ -866,6 +922,7 @@ static void opendhcp_http_get_alluser(http_request *request, hw_http_response *r
if (request->method != HW_HTTP_GET) { if (request->method != HW_HTTP_GET) {
proto_response_error(response, 405, HTTP_STATUS_405, ERR_HTTP_UNSUP_METHOD); proto_response_error(response, 405, HTTP_STATUS_405, ERR_HTTP_UNSUP_METHOD);
free(req);
return; return;
} }
@ -879,6 +936,7 @@ static void opendhcp_http_get_alluser(http_request *request, hw_http_response *r
ret = dhcp_get_all_user(req); ret = dhcp_get_all_user(req);
if (ret != ERR_SUCCESS) { if (ret != ERR_SUCCESS) {
proto_response_error(response, 500, HTTP_STATUS_500, ret); proto_response_error(response, 500, HTTP_STATUS_500, ret);
free(req);
return; return;
} }
SETSTRING(body, req->dp); SETSTRING(body, req->dp);
@ -913,6 +971,7 @@ static void opendhcp_http_add_rangeset(http_request *request, hw_http_response *
if (request->method != HW_HTTP_POST) { if (request->method != HW_HTTP_POST) {
proto_response_error(response, 405, HTTP_STATUS_405, ERR_HTTP_UNSUP_METHOD); proto_response_error(response, 405, HTTP_STATUS_405, ERR_HTTP_UNSUP_METHOD);
free(req);
return; return;
} }
@ -925,6 +984,7 @@ static void opendhcp_http_add_rangeset(http_request *request, hw_http_response *
ret = add_dhcpd_rangeset(req, request->body->value); ret = add_dhcpd_rangeset(req, request->body->value);
if (ret != ERR_SUCCESS) { if (ret != ERR_SUCCESS) {
proto_response_error(response, 500, HTTP_STATUS_500, ret); proto_response_error(response, 500, HTTP_STATUS_500, ret);
free(req);
return; return;
} }
@ -960,6 +1020,7 @@ static void opendhcp_http_delete_rangeset(http_request *request, hw_http_respons
if (request->method != HW_HTTP_POST) { if (request->method != HW_HTTP_POST) {
proto_response_error(response, 405, HTTP_STATUS_405, ERR_HTTP_UNSUP_METHOD); proto_response_error(response, 405, HTTP_STATUS_405, ERR_HTTP_UNSUP_METHOD);
free(req);
return; return;
} }
@ -972,6 +1033,7 @@ static void opendhcp_http_delete_rangeset(http_request *request, hw_http_respons
ret = delete_dhcpd_rangeset(req, request->body->value); ret = delete_dhcpd_rangeset(req, request->body->value);
if (ret != ERR_SUCCESS) { if (ret != ERR_SUCCESS) {
proto_response_error(response, 500, HTTP_STATUS_500, ret); proto_response_error(response, 500, HTTP_STATUS_500, ret);
free(req);
return; return;
} }
@ -990,6 +1052,55 @@ static void opendhcp_http_delete_rangeset(http_request *request, hw_http_respons
hw_http_response_send(response, req, response_complete); hw_http_response_send(response, req, response_complete);
} }
static void opendhcp_http_query_iptv_devs(http_request *request, hw_http_response *response, void *UNUSED(user_data)) {
hw_string status_code;
hw_string content_type_name;
hw_string content_type_value;
hw_string body;
hw_string keep_alive_name;
hw_string keep_alive_value;
int ret;
auto *req = (data19 *)malloc(sizeof(struct data19));
if (req == nullptr) {
proto_response_error(response, 500, HTTP_STATUS_500, ERR_MALLOC_MEMORY);
return;
}
if (request->method != HW_HTTP_GET) {
proto_response_error(response, 405, HTTP_STATUS_405, ERR_HTTP_UNSUP_METHOD);
response_complete(req);
return;
}
memset(req, 0, sizeof(struct data19));
SETSTRING(content_type_name, "Content-Type");
SETSTRING(content_type_value, "application/json");
hw_set_response_header(response, &content_type_name, &content_type_value);
SETSTRING(status_code, HTTP_STATUS_200);
ret = dchp_get_all_iptv_devs(req);
if (ret != ERR_SUCCESS) {
proto_response_error(response, 500, HTTP_STATUS_500, ret);
response_complete(req);
return;
}
SETSTRING(body, req->dp);
hw_set_body(response, &body);
hw_set_response_status_code(response, &status_code);
if (request->keep_alive) {
SETSTRING(keep_alive_name, "Connection");
SETSTRING(keep_alive_value, "close");
hw_set_response_header(response, &keep_alive_name, &keep_alive_value);
} else {
hw_set_http_version(response, 1, 0);
}
hw_http_response_send(response, req, response_complete);
}
static void opendhcp_http_query_rangeset(http_request *request, hw_http_response *response, void *UNUSED(user_data)) { static void opendhcp_http_query_rangeset(http_request *request, hw_http_response *response, void *UNUSED(user_data)) {
hw_string status_code; hw_string status_code;
hw_string content_type_name; hw_string content_type_name;
@ -1007,6 +1118,7 @@ static void opendhcp_http_query_rangeset(http_request *request, hw_http_response
if (request->method != HW_HTTP_GET) { if (request->method != HW_HTTP_GET) {
proto_response_error(response, 405, HTTP_STATUS_405, ERR_HTTP_UNSUP_METHOD); proto_response_error(response, 405, HTTP_STATUS_405, ERR_HTTP_UNSUP_METHOD);
free(req);
return; return;
} }
@ -1019,6 +1131,7 @@ static void opendhcp_http_query_rangeset(http_request *request, hw_http_response
ret = query_dhcpd_rangeset(req); ret = query_dhcpd_rangeset(req);
if (ret != ERR_SUCCESS) { if (ret != ERR_SUCCESS) {
proto_response_error(response, 500, HTTP_STATUS_500, ret); proto_response_error(response, 500, HTTP_STATUS_500, ret);
free(req);
return; return;
} }
@ -1060,11 +1173,40 @@ int opendhcp_add_listener() {
return i; return i;
} }
void iptvCacheCb(void *UNUSED(pArg)) {
do {
PIPTV_DEV_SET pDev, pTmp = nullptr;
uv_rwlock_wrlock(&g_uvCacheLock);
HASH_ITER(hh, g_iptvNewDevs, pDev, pTmp) {
PIPTV_DEV_SET pTemp;
const char *pDevMac = strdup(pDev->iptvMAC);
HASH_FIND_STR(g_iptvCacheDevs, pDevMac, pTemp);
// 新发现设备没有被上报过
if (!pTemp) {
auto pCacheDev = (PIPTV_DEV_SET)malloc(sizeof(IPTV_DEV_SET));
memcpy(pCacheDev, pDev, sizeof(IPTV_DEV_SET));
// Report new IPTV device MAC
pCacheDev->isReport = 1;
// 添加到缓存列表供后续查询
HASH_ADD_STR(g_iptvCacheDevs, iptvMAC, pCacheDev);
dzlog_debug("Add IPTV device %s vni %d to cache\n", pCacheDev->iptvMAC, pCacheDev->vni);
}
HASH_DEL(g_iptvNewDevs, pDev);
free(pDev);
free((void *)pDevMac);
}
uv_rwlock_wrunlock(&g_uvCacheLock);
uv_sleep(10);
} while (true);
}
/** /**
* DHCP Server HTTP服务接口 * DHCP Server HTTP服务接口
*/ */
void opendhcp_init_http_server() { void opendhcp_init_http_server() {
static int added = FALSE; static int added = FALSE;
static uv_thread_t uvThread;
if (!added) { if (!added) {
hw_http_add_route("/", opendhcp_http_info, nullptr); hw_http_add_route("/", opendhcp_http_info, nullptr);
@ -1073,6 +1215,11 @@ void opendhcp_init_http_server() {
hw_http_add_route("dhcp/config/rangeset", opendhcp_http_add_rangeset, nullptr); hw_http_add_route("dhcp/config/rangeset", opendhcp_http_add_rangeset, nullptr);
hw_http_add_route("dhcp/delete/rangeset", opendhcp_http_delete_rangeset, nullptr); hw_http_add_route("dhcp/delete/rangeset", opendhcp_http_delete_rangeset, nullptr);
hw_http_add_route("dhcp/query/rangeset", opendhcp_http_query_rangeset, nullptr); hw_http_add_route("dhcp/query/rangeset", opendhcp_http_query_rangeset, nullptr);
hw_http_add_route("dhcp/query/iptvdevice", opendhcp_http_query_iptv_devs, nullptr);
uv_rwlock_init(&g_uvCacheLock);
uv_thread_create(&uvThread, iptvCacheCb, nullptr);
added = TRUE; added = TRUE;
} }
} }
@ -1106,6 +1253,35 @@ void opendhcp_add_ip_pool_set() {
} }
} }
int process_iptv_multicast(const unsigned char *p, int size, const char *mac) {
char ipTvId[16] = {0};
memcpy(ipTvId, &p[4], 10);
if (strcmp(ipTvId, "JSCMCC-OTT") == 0) {
PIPTV_DEV_SET pTmp;
HASH_FIND_STR(g_iptvNewDevs, mac, pTmp);
if (!pTmp) {
auto pDev = (PIPTV_DEV_SET)malloc(sizeof(IPTV_DEV_SET));
if (pDev) {
memset(pDev, 0, sizeof(IPTV_DEV_SET));
strcpy(pDev->iptvMAC, mac);
pDev->vni = 0;
pDev->isReport = 0;
uv_rwlock_wrlock(&g_uvCacheLock);
HASH_ADD_STR(g_iptvNewDevs, iptvMAC, pDev);
uv_rwlock_wrunlock(&g_uvCacheLock);
}
}
dzlog_debug("Found IPTV %s\n", mac);
return 0;
}
return 1;
}
/** /**
* MAC地址黑名单 * MAC地址黑名单
*/ */