// // Created by dongwenzhe on 2022/10/9. // #include #include using namespace std; #include #include #include #include #include #include #include #include #include #include "opendhcpd.h" #include "s2j/cJSON.h" #include "haywire.h" #include "misc.h" #include extern data2 cfig; extern bool kRunning; extern dhcpMap dhcpCache; extern time_t t; static void sendUserList(data19 *req, const char *pRequest) { char logBuff[512]; dhcpMap::iterator p; printf("Input: %s\n", pRequest); if (pRequest == nullptr || strlen(pRequest) == 0) { sprintf(logBuff, "Requeset Json"); logDHCPMess(logBuff, 1); return; } cJSON *pRoot = cJSON_Parse(pRequest); if (!pRoot) { return; } cJSON *pMsgContent = cJSON_GetObjectItem(pRoot, "msgContent"); if (!pMsgContent) { cJSON_Delete(pRoot); return; } cJSON *pUserMac = cJSON_GetObjectItem(pMsgContent, "userMac"); if (!pUserMac) { cJSON_Delete(pRoot); return; } req->memSize = (int)(2048 + (135 * dhcpCache.size()) + (cfig.dhcpSize * 26)); req->dp = (char *)calloc(1, req->memSize); if (!req->dp) { sprintf(logBuff, "Memory Error"); logDHCPMess(logBuff, 1); return; } cJSON *pRspRoot = cJSON_CreateObject(); cJSON_AddNumberToObject(pRspRoot, "version", 3); cJSON_AddNumberToObject(pRspRoot, "cryptoType", 0); cJSON_AddNumberToObject(pRspRoot, "timeStamp", (unsigned int)time(nullptr)); cJSON *pRspMsg = cJSON_CreateObject(); cJSON *pMsgArray = cJSON_CreateArray(); cJSON_AddItemToObject(pRspMsg, "userInfo", pMsgArray); for (int i = 0; i < cJSON_GetArraySize(pUserMac); i++) { char tempbuff[512]; cJSON *pItem = cJSON_GetArrayItem(pUserMac, i); cJSON *pRspItem = cJSON_CreateObject(); p = dhcpCache.find(pItem->valuestring); cJSON_AddStringToObject(pRspItem, "userMac", pItem->valuestring); if (p != dhcpCache.end()) { data7 *dhcpEntry = p->second; cJSON_AddStringToObject(pRspItem, "ip", IP2String(tempbuff, dhcpEntry->ip)); cJSON_AddStringToObject(pRspItem, "hostname", dhcpEntry->hostname); if (dhcpEntry->display && dhcpEntry->expiry >= t) { tm *ttm = localtime(&dhcpEntry->expiry); strftime(tempbuff, sizeof(tempbuff), "%d-%b-%y %X", ttm); cJSON_AddStringToObject(pRspItem, "leaseExpiry", tempbuff); } else { cJSON_AddStringToObject(pRspItem, "leaseExpiry", "Expiry"); } } else { cJSON_AddStringToObject(pRspItem, "ip", ""); cJSON_AddStringToObject(pRspItem, "hostname", ""); } cJSON_AddItemToArray(pMsgArray, pRspItem); } cJSON_AddItemToObject(pRspRoot, "msgContent", pRspMsg); char *fp = req->dp; //char *maxData = req->dp + (req->memSize - 512); //fp += sprintf(fp, send200, strlen(rspBuf)); fp += sprintf(fp, "%s", cJSON_Print(pRspRoot)); cJSON_Delete(pRoot); cJSON_Delete(pRspRoot); req->bytes = (int)(fp - req->dp); } static void sendAllLists(data19 *req) { char logBuff[512]; data7 *dhcpEntry; dhcpMap::iterator p; req->memSize = (int)(2048 + (135 * dhcpCache.size()) + (cfig.dhcpSize * 26)); req->dp = (char *)calloc(1, req->memSize); if (!req->dp) { sprintf(logBuff, "Memory Error"); logDHCPMess(logBuff, 1); return; } char *fp = req->dp; char *maxData = req->dp + (req->memSize - 512); cJSON *pRspRoot = cJSON_CreateObject(); cJSON_AddNumberToObject(pRspRoot, "version", 3); cJSON_AddNumberToObject(pRspRoot, "cryptoType", 0); cJSON_AddNumberToObject(pRspRoot, "timeStamp", (unsigned int)time(nullptr)); cJSON *pRspMsg = cJSON_CreateObject(); cJSON *pMsgArray = cJSON_CreateArray(); cJSON_AddItemToObject(pRspMsg, "users", pMsgArray); for (p = dhcpCache.begin(); kRunning && p != dhcpCache.end() && fp < maxData; p++) { //cJSON *pRspItem = cJSON_CreateObject(); if ((dhcpEntry = p->second)) { cJSON_AddStringToObject(pMsgArray, "", dhcpEntry->mapname); } //cJSON_AddItemToArray(pMsgArray, pRspItem); } cJSON_AddItemToObject(pRspRoot, "msgContent", pRspMsg); fp += sprintf(fp, "%s", cJSON_Print(pRspRoot)); cJSON_Delete(pRspRoot); req->bytes = (int)(fp - req->dp); } #pragma clang diagnostic push #pragma ide diagnostic ignored "cert-err34-c" int getHwAddr(char *buff, char *mac) { if (buff == nullptr || mac == nullptr) { return -1; } int i; unsigned int p[6]; if (sscanf(mac, "%x:%x:%x:%x:%x:%x", &p[0], &p[1], &p[2], &p[3], &p[4], &p[5]) < 6) { return -1; } for (i = 0; i < 6; i++) { buff[i] = (char)p[i]; } return 0; } #pragma clang diagnostic pop int arpSet(const char *ifname, char *ipStr, char *mac) { if (ifname == nullptr || ipStr == nullptr || mac == nullptr) { printf("para is null.\n"); return -1; } struct arpreq req {}; struct sockaddr_in *sin; int ret; int sock_fd; memset(&req, 0, sizeof(struct arpreq)); sin = (struct sockaddr_in *)&req.arp_pa; sin->sin_family = AF_INET; sin->sin_addr.s_addr = inet_addr(ipStr); //arp_dev长度为[16],注意越界 strncpy(req.arp_dev, ifname, 15); req.arp_flags = ATF_PERM | ATF_COM; if (getHwAddr((char *)req.arp_ha.sa_data, mac) < 0) { printf("get mac error.\n"); return -1; } sock_fd = socket(AF_INET, SOCK_DGRAM, 0); if (sock_fd < 0) { printf("get socket error.\n"); return -1; } ret = ioctl(sock_fd, SIOCSARP, &req); if (ret < 0) { printf("ioctl error.\n"); close(sock_fd); return -1; } close(sock_fd); return 0; } sockaddr_in get_cliAddr(char *nicif, char *tempbuff, data9 *req) { arpSet(nicif, IP2String(tempbuff, req->dhcpp.header.bp_yiaddr), req->chaddr); sockaddr_in cliAddr {}; memcpy(&cliAddr, &req->remote, sizeof(sockaddr_in)); cliAddr.sin_addr.s_addr = inet_addr(IP2String(tempbuff, req->dhcpp.header.bp_yiaddr)); return cliAddr; } static void response_complete(void *user_data) { auto *req = (data19 *)user_data; if (req) { if (req->dp) { free(req->dp); } free(req); } } static void opendhcp_http_info(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; auto *req = (data19 *)malloc(sizeof(struct data19)); if(req == nullptr) { hw_http_response_send_error(response, HTTP_STATUS_500, "memory error"); return; } if (request->method != HW_HTTP_GET) { hw_http_response_send_error(response, HTTP_STATUS_405, HTTP_STATUS_405); return; } memset(req, 0, sizeof(struct data19)); SETSTRING(content_type_name, "Content-Type"); SETSTRING(content_type_value, "text/html"); hw_set_response_header(response, &content_type_name, &content_type_value); SETSTRING(status_code, HTTP_STATUS_200); prepareUserHtmlRespStatus(req); 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_get_userinfo(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; auto *req = (data19 *)malloc(sizeof(struct data19)); if(req == nullptr) { hw_http_response_send_error(response, HTTP_STATUS_500, "memory error"); return; } if (request->method != HW_HTTP_POST) { hw_http_response_send_error(response, HTTP_STATUS_405, HTTP_STATUS_405); return; } memset(req, 0, sizeof(struct data19)); SETSTRING(content_type_name, "Content-Type"); SETSTRING(content_type_value, "text/html"); hw_set_response_header(response, &content_type_name, &content_type_value); SETSTRING(status_code, HTTP_STATUS_200); sendUserList(req, request->body->value); 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_get_alluser(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; auto *req = (data19 *)malloc(sizeof(struct data19)); if(req == nullptr) { hw_http_response_send_error(response, HTTP_STATUS_500, "memory error"); return; } if (request->method != HW_HTTP_GET) { hw_http_response_send_error(response, HTTP_STATUS_405, HTTP_STATUS_405); return; } memset(req, 0, sizeof(struct data19)); SETSTRING(content_type_name, "Content-Type"); SETSTRING(content_type_value, "text/html"); hw_set_response_header(response, &content_type_name, &content_type_value); SETSTRING(status_code, HTTP_STATUS_200); sendAllLists(req); 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); } void opendhcp_init_http_server() { hw_http_add_route("/", opendhcp_http_info, nullptr); hw_http_add_route("getuser", opendhcp_http_get_userinfo, nullptr); hw_http_add_route("allusers", opendhcp_http_get_alluser, nullptr); }