parent
05f86faa59
commit
b5883a2036
|
@ -101,7 +101,7 @@ application:
|
|||
# mac_filter = ["00:01:02:03:04:07", "00:01:02:03:04:01"];
|
||||
# IP地址池配置
|
||||
range_set: (
|
||||
{ dhcp_range = "192.168.101.2-192.168.101.4";
|
||||
{ dhcp_range = "192.168.101.0-192.168.101.4";
|
||||
subnet_mask = "255.255.255.0";
|
||||
domain_server = "114.114.114.114,8.8.8.8";
|
||||
gateway = "192.168.101.1";
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define DHCP_SVR_PORT (67)
|
||||
#define DHCP_CLI_PORT (68)
|
||||
|
||||
/**
|
||||
* Message op code / message type
|
||||
* Request Message
|
||||
|
@ -21,6 +24,7 @@ extern "C" {
|
|||
#define BOOTP_REPLY 2
|
||||
|
||||
#define DHCP_MSG_NONE 0
|
||||
|
||||
/**
|
||||
* DHCP客户端在请求IP地址时并不知道DHCP服务器的位置,
|
||||
* 因此DHCP客户端会在本地网络内以广播方式发送Discover请求报文,以发现网络中的DHCP服务器。
|
||||
|
@ -28,6 +32,7 @@ extern "C" {
|
|||
* DHCP客户端据此可以知道网络中存在的DHCP服务器的位置
|
||||
*/
|
||||
#define DHCP_MSG_DISCOVER 1
|
||||
|
||||
/**
|
||||
* DHCP服务器收到Discover报文后,就会在所配置的地址池中查找一个合适的IP地址,
|
||||
* 加上相应的租约期限和其他配置信息(如网关、DNS服务器等),构造一个Offer报文,
|
||||
|
@ -35,6 +40,7 @@ extern "C" {
|
|||
* 最终还需要客户端通过ARP来检测该IP地址是否重复
|
||||
*/
|
||||
#define DHCP_MSG_OFFER 2
|
||||
|
||||
/**
|
||||
* DHCP客户端可能会收到很多Offer请求报文,所以必须在这些应答中选择一个。
|
||||
* 通常是选择第一个Offer应答报文的服务器作为自己的目标服务器,
|
||||
|
@ -44,28 +50,33 @@ extern "C" {
|
|||
* 如果没有收到ACK报文,在租期达到87.5%时,会再次发送广播的Request请求报文以请求续延租约
|
||||
*/
|
||||
#define DHCP_MSG_REQUEST 3
|
||||
|
||||
/**
|
||||
* DHCP客户端收到DHCP服务器ACK应答报文后,
|
||||
* 通过地址冲突检测发现服务器分配的地址冲突或者由于其他原因导致不能使用,
|
||||
* 则会向DHCP服务器发送Decline请求报文,通知服务器所分配的IP地址不可用,以期获得新的IP地址
|
||||
*/
|
||||
#define DHCP_MSG_DECLINE 4
|
||||
|
||||
/**
|
||||
* DHCP服务器收到Request请求报文后,根据Request报文中携带的用户MAC来查找有没有相应的租约记录,
|
||||
* 如果有则发送ACK应答报文,通知用户可以使用分配的IP地址
|
||||
*/
|
||||
#define DHCP_MSG_ACK 5
|
||||
|
||||
/**
|
||||
* 如果DHCP服务器收到Request请求报文后,没有发现有相应的租约记录或者由于某些原因无法正常分配IP地址,
|
||||
* 则向DHCP客户端发送NAK应答报文,通知用户无法分配合适的IP地址
|
||||
*/
|
||||
#define DHCP_MSG_NAK 6
|
||||
|
||||
/**
|
||||
* 当DHCP客户端不再需要使用分配IP地址时(一般出现在客户端关机、下线等状况)
|
||||
* 就会主动向DHCP服务器发送RELEASE请求报文,告知服务器用户不再需要分配IP地址,
|
||||
* 请求DHCP服务器释放对应的IP地址
|
||||
*/
|
||||
#define DHCP_MSG_RELEASE 7
|
||||
|
||||
/**
|
||||
* DHCP客户端如果需要从DHCP服务器端获取更为详细的配置信息,
|
||||
* 则向DHCP服务器发送Inform请求报文;DHCP服务器在收到该报文后,
|
||||
|
|
|
@ -17,6 +17,7 @@ AUX_SOURCE_DIRECTORY(json C_SRC)
|
|||
AUX_SOURCE_DIRECTORY(args C_SRC)
|
||||
AUX_SOURCE_DIRECTORY(init C_SRC)
|
||||
AUX_SOURCE_DIRECTORY(misc C_SRC)
|
||||
AUX_SOURCE_DIRECTORY(bitset C_SRC)
|
||||
AUX_SOURCE_DIRECTORY(banner C_SRC)
|
||||
AUX_SOURCE_DIRECTORY(configure C_SRC)
|
||||
AUX_SOURCE_DIRECTORY(network C_SRC)
|
||||
|
|
|
@ -0,0 +1,382 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "bitset/bitset.h"
|
||||
|
||||
/* Create a new bitset. Return NULL in case of failure. */
|
||||
bitset_t *bitset_create() {
|
||||
bitset_t *bitset = NULL;
|
||||
/* Allocate the bitset itself. */
|
||||
if ((bitset = (bitset_t *)malloc(sizeof(bitset_t))) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
bitset->array = NULL;
|
||||
bitset->arraysize = 0;
|
||||
bitset->capacity = 0;
|
||||
return bitset;
|
||||
}
|
||||
|
||||
/* Create a new bitset able to contain size bits. Return NULL in case of failure. */
|
||||
bitset_t *bitset_create_with_capacity(size_t size) {
|
||||
bitset_t *bitset = NULL;
|
||||
/* Allocate the bitset itself. */
|
||||
if ((bitset = (bitset_t *)malloc(sizeof(bitset_t))) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
bitset->arraysize = (size + sizeof(uint64_t) * 8 - 1) / (sizeof(uint64_t) * 8);
|
||||
bitset->capacity = bitset->arraysize;
|
||||
if ((bitset->array = (uint64_t *)calloc(bitset->arraysize, sizeof(uint64_t))) == NULL) {
|
||||
free(bitset);
|
||||
return NULL;
|
||||
}
|
||||
return bitset;
|
||||
}
|
||||
|
||||
/* Create a copy */
|
||||
bitset_t *bitset_copy(const bitset_t *bitset) {
|
||||
bitset_t *copy = NULL;
|
||||
/* Allocate the bitset itself. */
|
||||
if ((copy = (bitset_t *)malloc(sizeof(bitset_t))) == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
memcpy(copy, bitset, sizeof(bitset_t));
|
||||
copy->capacity = copy->arraysize;
|
||||
if ((copy->array = (uint64_t *)malloc(sizeof(uint64_t) * bitset->arraysize)) == NULL) {
|
||||
free(copy);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(copy->array, bitset->array, sizeof(uint64_t) * bitset->arraysize);
|
||||
return copy;
|
||||
}
|
||||
|
||||
void bitset_clear(bitset_t *bitset) {
|
||||
memset(bitset->array, 0, sizeof(uint64_t) * bitset->arraysize);
|
||||
}
|
||||
|
||||
void bitset_shift_left(bitset_t *bitset, size_t s) {
|
||||
size_t extra_words = s / 64;
|
||||
int inword_shift = (int)(s % 64);
|
||||
size_t as = bitset->arraysize;
|
||||
if (inword_shift == 0) {
|
||||
bitset_resize(bitset, as + extra_words, FALSE);
|
||||
// could be done with a memmove
|
||||
for (size_t i = as + extra_words; i > extra_words; i--) {
|
||||
bitset->array[i - 1] = bitset->array[i - 1 - extra_words];
|
||||
}
|
||||
} else {
|
||||
bitset_resize(bitset, as + extra_words + 1, TRUE);
|
||||
bitset->array[as + extra_words] = bitset->array[as - 1] >> (64 - inword_shift);
|
||||
for (size_t i = as + extra_words; i >= extra_words + 2; i--) {
|
||||
bitset->array[i - 1] = (bitset->array[i - 1 - extra_words] << inword_shift) |
|
||||
(bitset->array[i - 2 - extra_words] >> (64 - inword_shift));
|
||||
}
|
||||
bitset->array[extra_words] = bitset->array[0] << inword_shift;
|
||||
}
|
||||
for (size_t i = 0; i < extra_words; i++) {
|
||||
bitset->array[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void bitset_shift_right(bitset_t *bitset, size_t s) {
|
||||
size_t extra_words = s / 64;
|
||||
int inword_shift = (int)(s % 64);
|
||||
size_t as = bitset->arraysize;
|
||||
if (inword_shift == 0) {
|
||||
// could be done with a memmove
|
||||
for (size_t i = 0; i < as - extra_words; i++) {
|
||||
bitset->array[i] = bitset->array[i + extra_words];
|
||||
}
|
||||
bitset_resize(bitset, as - extra_words, FALSE);
|
||||
|
||||
} else {
|
||||
for (size_t i = 0; i + extra_words + 1 < as; i++) {
|
||||
bitset->array[i] = (bitset->array[i + extra_words] >> inword_shift) |
|
||||
(bitset->array[i + extra_words + 1] << (64 - inword_shift));
|
||||
}
|
||||
bitset->array[as - extra_words - 1] = (bitset->array[as - 1] >> inword_shift);
|
||||
bitset_resize(bitset, as - extra_words, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free memory. */
|
||||
void bitset_free(bitset_t *bitset) {
|
||||
free(bitset->array);
|
||||
free(bitset);
|
||||
}
|
||||
|
||||
/* Resize the bitset so that it can support newarraysize * 64 bits. Return TRUE in case of success, FALSE for failure. */
|
||||
int bitset_resize(bitset_t *bitset, size_t newarraysize, int padwithzeroes) {
|
||||
size_t smallest = newarraysize < bitset->arraysize ? newarraysize : bitset->arraysize;
|
||||
if (bitset->capacity < newarraysize) {
|
||||
uint64_t *newarray;
|
||||
bitset->capacity = newarraysize * 2;
|
||||
if ((newarray = (uint64_t *)realloc(bitset->array, sizeof(uint64_t) * bitset->capacity)) == NULL) {
|
||||
free(bitset->array);
|
||||
return FALSE;
|
||||
}
|
||||
bitset->array = newarray;
|
||||
}
|
||||
if (padwithzeroes && (newarraysize > smallest)) {
|
||||
memset(bitset->array + smallest, 0, sizeof(uint64_t) * (newarraysize - smallest));
|
||||
}
|
||||
bitset->arraysize = newarraysize;
|
||||
return TRUE; // success!
|
||||
}
|
||||
|
||||
size_t bitset_count(const bitset_t *bitset) {
|
||||
size_t card = 0;
|
||||
size_t k = 0;
|
||||
// assumes that long long is 8 bytes
|
||||
for (; k + 7 < bitset->arraysize; k += 8) {
|
||||
card += __builtin_popcountll(bitset->array[k]);
|
||||
card += __builtin_popcountll(bitset->array[k + 1]);
|
||||
card += __builtin_popcountll(bitset->array[k + 2]);
|
||||
card += __builtin_popcountll(bitset->array[k + 3]);
|
||||
card += __builtin_popcountll(bitset->array[k + 4]);
|
||||
card += __builtin_popcountll(bitset->array[k + 5]);
|
||||
card += __builtin_popcountll(bitset->array[k + 6]);
|
||||
card += __builtin_popcountll(bitset->array[k + 7]);
|
||||
}
|
||||
for (; k + 3 < bitset->arraysize; k += 4) {
|
||||
card += __builtin_popcountll(bitset->array[k]);
|
||||
card += __builtin_popcountll(bitset->array[k + 1]);
|
||||
card += __builtin_popcountll(bitset->array[k + 2]);
|
||||
card += __builtin_popcountll(bitset->array[k + 3]);
|
||||
}
|
||||
for (; k < bitset->arraysize; k++) {
|
||||
card += __builtin_popcountll(bitset->array[k]);
|
||||
}
|
||||
return card;
|
||||
}
|
||||
|
||||
int bitset_inplace_union(bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2) {
|
||||
size_t minlength = b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize;
|
||||
for (size_t k = 0; k < minlength; ++k) {
|
||||
b1->array[k] |= b2->array[k];
|
||||
}
|
||||
if (b2->arraysize > b1->arraysize) {
|
||||
size_t oldsize = b1->arraysize;
|
||||
if (!bitset_resize(b1, b2->arraysize, FALSE)) {
|
||||
return FALSE;
|
||||
}
|
||||
memcpy(b1->array + oldsize, b2->array + oldsize, (b2->arraysize - oldsize) * sizeof(uint64_t));
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
size_t bitset_minimum(const bitset_t *bitset) {
|
||||
for (size_t k = 0; k < bitset->arraysize; k++) {
|
||||
uint64_t w = bitset->array[k];
|
||||
if (w != 0) {
|
||||
return __builtin_ctzll(w) + k * 64;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t bitset_maximum(const bitset_t *bitset) {
|
||||
for (size_t k = bitset->arraysize; k > 0; k--) {
|
||||
uint64_t w = bitset->array[k - 1];
|
||||
if (w != 0) {
|
||||
return 63 - __builtin_clzll(w) + (k - 1) * 64;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns TRUE if bitsets share no common elements, FALSE otherwise.
|
||||
*
|
||||
* Performs early-out if common element found. */
|
||||
int bitsets_disjoint(const bitset_t *b1, const bitset_t *b2) {
|
||||
size_t minlength = b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize;
|
||||
|
||||
for (size_t k = 0; k < minlength; k++) {
|
||||
if ((b1->array[k] & b2->array[k]) != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* Returns TRUE if bitsets contain at least 1 common element, FALSE if they are
|
||||
* disjoint.
|
||||
*
|
||||
* Performs early-out if common element found. */
|
||||
int bitsets_intersect(const bitset_t *b1, const bitset_t *b2) {
|
||||
size_t minlength = b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize;
|
||||
|
||||
for (size_t k = 0; k < minlength; k++) {
|
||||
if ((b1->array[k] & b2->array[k]) != 0) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Returns TRUE if b has any bits set in or after b->array[starting_loc]. */
|
||||
static int any_bits_set(const bitset_t *b, size_t starting_loc) {
|
||||
if (starting_loc >= b->arraysize) {
|
||||
return FALSE;
|
||||
}
|
||||
for (size_t k = starting_loc; k < b->arraysize; k++) {
|
||||
if (b->array[k] != 0) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Returns TRUE if b1 has all of b2's bits set.
|
||||
*
|
||||
* Performs early out if a bit is found in b2 that is not found in b1. */
|
||||
int bitset_contains_all(const bitset_t *b1, const bitset_t *b2) {
|
||||
for (size_t k = 0; k < b1->arraysize; k++) {
|
||||
if ((b1->array[k] & b2->array[k]) != b2->array[k]) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
if (b2->arraysize > b1->arraysize) {
|
||||
/* Need to check if b2 has any bits set beyond b1's array */
|
||||
return !any_bits_set(b2, b1->arraysize);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
size_t bitset_union_count(const bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2) {
|
||||
size_t answer = 0;
|
||||
size_t minlength = b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize;
|
||||
size_t k = 0;
|
||||
for (; k + 3 < minlength; k += 4) {
|
||||
answer += __builtin_popcountll(b1->array[k] | b2->array[k]);
|
||||
answer += __builtin_popcountll(b1->array[k + 1] | b2->array[k + 1]);
|
||||
answer += __builtin_popcountll(b1->array[k + 2] | b2->array[k + 2]);
|
||||
answer += __builtin_popcountll(b1->array[k + 3] | b2->array[k + 3]);
|
||||
}
|
||||
for (; k < minlength; ++k) {
|
||||
answer += __builtin_popcountll(b1->array[k] | b2->array[k]);
|
||||
}
|
||||
if (b2->arraysize > b1->arraysize) {
|
||||
//k = b1->arraysize;
|
||||
for (; k + 3 < b2->arraysize; k += 4) {
|
||||
answer += __builtin_popcountll(b2->array[k]);
|
||||
answer += __builtin_popcountll(b2->array[k + 1]);
|
||||
answer += __builtin_popcountll(b2->array[k + 2]);
|
||||
answer += __builtin_popcountll(b2->array[k + 3]);
|
||||
}
|
||||
for (; k < b2->arraysize; ++k) {
|
||||
answer += __builtin_popcountll(b2->array[k]);
|
||||
}
|
||||
} else {
|
||||
//k = b2->arraysize;
|
||||
for (; k + 3 < b1->arraysize; k += 4) {
|
||||
answer += __builtin_popcountll(b1->array[k]);
|
||||
answer += __builtin_popcountll(b1->array[k + 1]);
|
||||
answer += __builtin_popcountll(b1->array[k + 2]);
|
||||
answer += __builtin_popcountll(b1->array[k + 3]);
|
||||
}
|
||||
for (; k < b1->arraysize; ++k) {
|
||||
answer += __builtin_popcountll(b1->array[k]);
|
||||
}
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
void bitset_inplace_intersection(bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2) {
|
||||
size_t minlength = b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize;
|
||||
size_t k = 0;
|
||||
for (; k < minlength; ++k) {
|
||||
b1->array[k] &= b2->array[k];
|
||||
}
|
||||
for (; k < b1->arraysize; ++k) {
|
||||
b1->array[k] = 0; // memset could, maybe, be a tiny bit faster
|
||||
}
|
||||
}
|
||||
|
||||
size_t bitset_intersection_count(const bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2) {
|
||||
size_t answer = 0;
|
||||
size_t minlength = b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize;
|
||||
for (size_t k = 0; k < minlength; ++k) {
|
||||
answer += __builtin_popcountll(b1->array[k] & b2->array[k]);
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
void bitset_inplace_difference(bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2) {
|
||||
size_t minlength = b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize;
|
||||
size_t k = 0;
|
||||
for (; k < minlength; ++k) {
|
||||
b1->array[k] &= ~(b2->array[k]);
|
||||
}
|
||||
}
|
||||
|
||||
size_t bitset_difference_count(const bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2) {
|
||||
size_t minlength = b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize;
|
||||
size_t k = 0;
|
||||
size_t answer = 0;
|
||||
for (; k < minlength; ++k) {
|
||||
answer += __builtin_popcountll(b1->array[k] & ~(b2->array[k]));
|
||||
}
|
||||
for (; k < b1->arraysize; ++k) {
|
||||
answer += __builtin_popcountll(b1->array[k]);
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
int bitset_inplace_symmetric_difference(bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2) {
|
||||
size_t minlength = b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize;
|
||||
size_t k = 0;
|
||||
for (; k < minlength; ++k) {
|
||||
b1->array[k] ^= b2->array[k];
|
||||
}
|
||||
if (b2->arraysize > b1->arraysize) {
|
||||
size_t oldsize = b1->arraysize;
|
||||
if (!bitset_resize(b1, b2->arraysize, FALSE)) {
|
||||
return FALSE;
|
||||
}
|
||||
memcpy(b1->array + oldsize, b2->array + oldsize, (b2->arraysize - oldsize) * sizeof(uint64_t));
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
size_t bitset_symmetric_difference_count(const bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2) {
|
||||
size_t minlength = b1->arraysize < b2->arraysize ? b1->arraysize : b2->arraysize;
|
||||
size_t k = 0;
|
||||
size_t answer = 0;
|
||||
for (; k < minlength; ++k) {
|
||||
answer += __builtin_popcountll(b1->array[k] ^ b2->array[k]);
|
||||
}
|
||||
if (b2->arraysize > b1->arraysize) {
|
||||
for (; k < b2->arraysize; ++k) {
|
||||
answer += __builtin_popcountll(b2->array[k]);
|
||||
}
|
||||
} else {
|
||||
for (; k < b1->arraysize; ++k) {
|
||||
answer += __builtin_popcountll(b1->array[k]);
|
||||
}
|
||||
}
|
||||
return answer;
|
||||
}
|
||||
|
||||
int bitset_trim(bitset_t *bitset) {
|
||||
size_t newsize = bitset->arraysize;
|
||||
while (newsize > 0) {
|
||||
if (bitset->array[newsize - 1] == 0) {
|
||||
newsize -= 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bitset->capacity == newsize) {
|
||||
return TRUE; // nothing to do
|
||||
}
|
||||
bitset->capacity = newsize;
|
||||
bitset->arraysize = newsize;
|
||||
uint64_t *newarray;
|
||||
if ((newarray = (uint64_t *)realloc(bitset->array, sizeof(uint64_t) * bitset->capacity)) == NULL) {
|
||||
free(bitset->array);
|
||||
return FALSE;
|
||||
}
|
||||
bitset->array = newarray;
|
||||
return TRUE;
|
||||
}
|
|
@ -0,0 +1,271 @@
|
|||
//
|
||||
// Created by xajhuang on 2023/4/6.
|
||||
//
|
||||
|
||||
#ifndef VCPE_BITSET_H
|
||||
#define VCPE_BITSET_H
|
||||
#include <common.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
// For compatibility with MSVC with the use of `restrict`
|
||||
#if (__STDC_VERSION__ >= 199901L) || (defined(__GNUC__) && defined(__STDC_VERSION__))
|
||||
#define CBITSET_RESTRICT restrict
|
||||
#else
|
||||
#define CBITSET_RESTRICT
|
||||
#endif // (__STDC_VERSION__ >= 199901L) || (defined(__GNUC__) && defined(__STDC_VERSION__ ))
|
||||
|
||||
struct bitset_s {
|
||||
uint64_t *CBITSET_RESTRICT array;
|
||||
size_t arraysize;
|
||||
size_t capacity;
|
||||
};
|
||||
|
||||
typedef struct bitset_s bitset_t;
|
||||
|
||||
/* Create a new bitset. Return NULL in case of failure. */
|
||||
bitset_t *bitset_create(void);
|
||||
|
||||
/* Create a new bitset able to contain size bits. Return NULL in case of failure. */
|
||||
bitset_t *bitset_create_with_capacity(size_t size);
|
||||
|
||||
/* Free memory. */
|
||||
void bitset_free(bitset_t *bitset);
|
||||
|
||||
/* Set all bits to zero. */
|
||||
void bitset_clear(bitset_t *bitset);
|
||||
|
||||
/* Create a copy */
|
||||
bitset_t *bitset_copy(const bitset_t *bitset);
|
||||
|
||||
/* Resize the bitset. Return TRUE in case of success, FALSE for failure. Pad with zeroes new buffer areas if requested. */
|
||||
int bitset_resize(bitset_t *bitset, size_t newarraysize, int padwithzeroes);
|
||||
|
||||
/* returns how many bytes of memory the backend buffer uses */
|
||||
static inline size_t bitset_size_in_bytes(const bitset_t *bitset) {
|
||||
return bitset->arraysize * sizeof(uint64_t);
|
||||
}
|
||||
|
||||
/* returns how many bits can be accessed */
|
||||
static inline size_t bitset_size_in_bits(const bitset_t *bitset) {
|
||||
return bitset->arraysize * 64;
|
||||
}
|
||||
|
||||
/* returns how many words (64-bit) of memory the backend buffer uses */
|
||||
static inline size_t bitset_size_in_words(const bitset_t *bitset) {
|
||||
return bitset->arraysize;
|
||||
}
|
||||
|
||||
/* Grow the bitset so that it can support newarraysize * 64 bits with padding. Return TRUE in case of success, FALSE for failure. */
|
||||
static inline int bitset_grow(bitset_t *bitset, size_t newarraysize) {
|
||||
if (bitset->capacity < newarraysize) {
|
||||
uint64_t *newarray;
|
||||
bitset->capacity = newarraysize * 2;
|
||||
if ((newarray = (uint64_t *)realloc(bitset->array, sizeof(uint64_t) * bitset->capacity)) == NULL) {
|
||||
free(bitset->array);
|
||||
return FALSE;
|
||||
}
|
||||
bitset->array = newarray;
|
||||
}
|
||||
memset(bitset->array + bitset->arraysize, 0, sizeof(uint64_t) * (newarraysize - bitset->arraysize));
|
||||
bitset->arraysize = newarraysize;
|
||||
return TRUE; // success!
|
||||
}
|
||||
|
||||
/* attempts to recover unused memory, return FALSE in case of reallocation failure */
|
||||
int bitset_trim(bitset_t *bitset);
|
||||
|
||||
/* shifts all bits by 's' positions so that the bitset representing values 1,2,10 would represent values 1+s, 2+s, 10+s */
|
||||
void bitset_shift_left(bitset_t *bitset, size_t s);
|
||||
|
||||
/* shifts all bits by 's' positions so that the bitset representing values 1,2,10 would represent values 1-s, 2-s, 10-s, negative values are deleted */
|
||||
void bitset_shift_right(bitset_t *bitset, size_t s);
|
||||
|
||||
/* Set the ith bit. Attempts to resize the bitset if needed (may silently fail) */
|
||||
static inline void bitset_set(bitset_t *bitset, size_t i) {
|
||||
size_t shiftedi = i >> 6;
|
||||
if (shiftedi >= bitset->arraysize) {
|
||||
if (!bitset_grow(bitset, shiftedi + 1)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
bitset->array[shiftedi] |= ((uint64_t)1) << (i % 64);
|
||||
}
|
||||
|
||||
/* Set the ith bit to the specified value. Attempts to resize the bitset if needed (may silently fail) */
|
||||
static inline void bitset_set_to_value(bitset_t *bitset, size_t i, int flag) {
|
||||
size_t shiftedi = i >> 6;
|
||||
uint64_t mask = ((uint64_t)1) << (i % 64);
|
||||
uint64_t dynmask = ((uint64_t)flag) << (i % 64);
|
||||
if (shiftedi >= bitset->arraysize) {
|
||||
if (!bitset_grow(bitset, shiftedi + 1)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
uint64_t w = bitset->array[shiftedi];
|
||||
w &= ~mask;
|
||||
w |= dynmask;
|
||||
bitset->array[shiftedi] = w;
|
||||
}
|
||||
|
||||
static inline void bitset_cls_bit(bitset_t *bitset, size_t i) {
|
||||
bitset_set_to_value(bitset, i, 0);
|
||||
}
|
||||
|
||||
/* Get the value of the ith bit. */
|
||||
static inline int bitset_get(const bitset_t *bitset, size_t i) {
|
||||
size_t shiftedi = i >> 6;
|
||||
if (shiftedi >= bitset->arraysize) {
|
||||
return FALSE;
|
||||
}
|
||||
return (bitset->array[shiftedi] & (((uint64_t)1) << (i % 64))) != 0;
|
||||
}
|
||||
|
||||
/* Count number of bits set. */
|
||||
size_t bitset_count(const bitset_t *bitset);
|
||||
|
||||
/* Find the index of the first bit set. */
|
||||
size_t bitset_minimum(const bitset_t *bitset);
|
||||
|
||||
/* Find the index of the last bit set. */
|
||||
size_t bitset_maximum(const bitset_t *bitset);
|
||||
|
||||
/* compute the union in-place (to b1), returns TRUE if successful, to generate a new bitset first call bitset_copy */
|
||||
int bitset_inplace_union(bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2);
|
||||
|
||||
/* report the size of the union (without materializing it) */
|
||||
size_t bitset_union_count(const bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2);
|
||||
|
||||
/* compute the intersection in-place (to b1), to generate a new bitset first call bitset_copy */
|
||||
void bitset_inplace_intersection(bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2);
|
||||
|
||||
/* report the size of the intersection (without materializing it) */
|
||||
size_t bitset_intersection_count(const bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2);
|
||||
|
||||
/* returns TRUE if the bitsets contain no common elements */
|
||||
int bitsets_disjoint(const bitset_t *b1, const bitset_t *b2);
|
||||
|
||||
/* returns TRUE if the bitsets contain any common elements */
|
||||
int bitsets_intersect(const bitset_t *b1, const bitset_t *b2);
|
||||
|
||||
/* returns TRUE if b1 contains all the set bits of b2 */
|
||||
int bitset_contains_all(const bitset_t *b1, const bitset_t *b2);
|
||||
|
||||
/* compute the difference in-place (to b1), to generate a new bitset first call bitset_copy */
|
||||
void bitset_inplace_difference(bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2);
|
||||
|
||||
/* compute the size of the difference */
|
||||
size_t bitset_difference_count(const bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2);
|
||||
|
||||
/* compute the symmetric difference in-place (to b1), return TRUE if successful, to generate a new bitset first call bitset_copy */
|
||||
int bitset_inplace_symmetric_difference(bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2);
|
||||
|
||||
/* compute the size of the symmetric difference */
|
||||
size_t bitset_symmetric_difference_count(const bitset_t *CBITSET_RESTRICT b1, const bitset_t *CBITSET_RESTRICT b2);
|
||||
|
||||
/* iterate over the set bits
|
||||
like so :
|
||||
for(size_t i = 0; nextSetBit(b,&i) ; i++) {
|
||||
//.....
|
||||
}
|
||||
*/
|
||||
static inline int nextSetBit(const bitset_t *bitset, size_t *i) {
|
||||
size_t x = *i >> 6;
|
||||
if (x >= bitset->arraysize) {
|
||||
return FALSE;
|
||||
}
|
||||
uint64_t w = bitset->array[x];
|
||||
w >>= (*i & 63);
|
||||
if (w != 0) {
|
||||
*i += __builtin_ctzll(w);
|
||||
return TRUE;
|
||||
}
|
||||
x++;
|
||||
while (x < bitset->arraysize) {
|
||||
w = bitset->array[x];
|
||||
if (w != 0) {
|
||||
*i = x * 64 + __builtin_ctzll(w);
|
||||
return TRUE;
|
||||
}
|
||||
x++;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Iterate over the set bits
|
||||
like so :
|
||||
size_t buffer[256];
|
||||
size_t howmany = 0;
|
||||
for(size_t startfrom = 0; (howmany = nextSetBits(b,buffer,256, &startfrom)) > 0 ; startfrom++) {
|
||||
//.....
|
||||
}
|
||||
*/
|
||||
static inline size_t nextSetBits(const bitset_t *bitset, size_t *buffer, size_t capacity, size_t *startfrom) {
|
||||
if (capacity == 0) {
|
||||
return 0; // sanity check
|
||||
}
|
||||
size_t x = *startfrom >> 6;
|
||||
if (x >= bitset->arraysize) {
|
||||
return 0; // nothing more to iterate over
|
||||
}
|
||||
uint64_t w = bitset->array[x];
|
||||
w >>= (*startfrom & 63);
|
||||
size_t howmany = 0;
|
||||
size_t base = x << 6;
|
||||
while (howmany < capacity) {
|
||||
while (w != 0) {
|
||||
uint64_t t = w & (~w + 1);
|
||||
int r = __builtin_ctzll(w);
|
||||
buffer[howmany++] = r + base;
|
||||
if (howmany == capacity) {
|
||||
goto end;
|
||||
}
|
||||
w ^= t;
|
||||
}
|
||||
x += 1;
|
||||
if (x == bitset->arraysize) {
|
||||
break;
|
||||
}
|
||||
base += 64;
|
||||
w = bitset->array[x];
|
||||
}
|
||||
end:
|
||||
if (howmany > 0) {
|
||||
*startfrom = buffer[howmany - 1];
|
||||
}
|
||||
return howmany;
|
||||
}
|
||||
|
||||
typedef int (*bitset_iterator)(size_t value, void *param);
|
||||
|
||||
// return TRUE if uninterrupted
|
||||
static inline int bitset_for_each(const bitset_t *b, bitset_iterator iterator, void *ptr) {
|
||||
size_t base = 0;
|
||||
for (size_t i = 0; i < b->arraysize; ++i) {
|
||||
uint64_t w = b->array[i];
|
||||
while (w != 0) {
|
||||
uint64_t t = w & (~w + 1);
|
||||
int r = __builtin_ctzll(w);
|
||||
if (!iterator(r + base, ptr)) {
|
||||
return FALSE;
|
||||
}
|
||||
w ^= t;
|
||||
}
|
||||
base += 64;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//static inline void bitset_print(const bitset_t *b) {
|
||||
// printf("{");
|
||||
// for (size_t i = 0; nextSetBit(b, &i); i++) {
|
||||
// printf("%zu, ", i);
|
||||
// }
|
||||
// printf("}");
|
||||
//}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif //VCPE_BITSET_H
|
|
@ -11,6 +11,26 @@ extern "C" {
|
|||
#define _STR(s) #s
|
||||
#define STR(s) _STR(s)
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) \
|
||||
({ \
|
||||
typeof(a) __min1__ = (a); \
|
||||
typeof(b) __min2__ = (b); \
|
||||
(void)(&__min1__ == &__min2__); \
|
||||
__min1__ < __min2__ ? __min1__ : __min2__; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a, b) \
|
||||
({ \
|
||||
typeof(a) __max1__ = (a); \
|
||||
typeof(b) __max2__ = (b); \
|
||||
(void)(&__max1__ == &__max2__); \
|
||||
__max1__ < __max2__ ? __max1__ : __max2__; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
//#ifdef __cplusplus
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
@ -48,11 +68,10 @@ typedef unsigned char U8;
|
|||
typedef unsigned short U16;
|
||||
typedef unsigned int U32;
|
||||
typedef unsigned long long U64;
|
||||
|
||||
typedef char S8;
|
||||
typedef short S16;
|
||||
typedef int S32;
|
||||
typedef long long S64;
|
||||
typedef char S8;
|
||||
typedef short S16;
|
||||
typedef int S32;
|
||||
typedef long long S64;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -4,10 +4,13 @@
|
|||
|
||||
#ifndef VCPE_IPADDR_H
|
||||
#define VCPE_IPADDR_H
|
||||
#include "common.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
U32 ipv4_get_network_addr(U32 ipAddr, U32 netmask);
|
||||
U32 ipv4_get_boardcast_addr(U32 ipAddr, U32 netmask);
|
||||
U32 ipv4_network_total_addr(U32 netmask);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -67,6 +67,8 @@ extern "C" {
|
|||
ERR_CODE(ERR_HTTP_UNSUP_PAGE, "找不到 HTTP 服务") \
|
||||
ERR_CODE(ERR_PROTO_DECODE, "HTTP 协议解析失败") \
|
||||
ERR_CODE(ERR_MSG_CONTENT, "msgContent内容不正确") \
|
||||
ERR_CODE(ERR_DHCP_NO_POOL, "找不到可用地址池") \
|
||||
ERR_CODE(ERR_DHCP_NO_ADDR, "找不到可用IP地址") \
|
||||
ERR_CODE(ERR_SOCK_CREATE, "创建套接字失败") \
|
||||
ERR_CODE(ERR_SOCK_SETOPT, "设置套接字参数失败")
|
||||
|
||||
|
|
|
@ -1,4 +1,16 @@
|
|||
//
|
||||
// Created by xajhuang on 2023/3/21.
|
||||
//
|
||||
#include "ipaddr.h"
|
||||
#include "ipaddr.h"
|
||||
|
||||
U32 ipv4_get_network_addr(U32 ipAddr, U32 netmask) {
|
||||
return (ipAddr & netmask);
|
||||
}
|
||||
|
||||
U32 ipv4_get_boardcast_addr(U32 ipAddr, U32 netmask) {
|
||||
return (ipAddr | netmask);
|
||||
}
|
||||
|
||||
U32 ipv4_network_total_addr(U32 netmask) {
|
||||
return (~netmask) + 1;
|
||||
}
|
|
@ -141,6 +141,24 @@ void dhcp_option_cfg_init() {
|
|||
}
|
||||
}
|
||||
|
||||
void dhcp_add_number_option(U8 *pBegin, int opt, U8 value, U8 nSize) {
|
||||
*pBegin = opt;
|
||||
pBegin++;
|
||||
*pBegin = nSize;
|
||||
pBegin++;
|
||||
memcpy(pBegin, &value, nSize);
|
||||
pBegin += nSize;
|
||||
}
|
||||
|
||||
void dhcp_add_buf_option(U8 *pBegin, int opt, U8 *buf, U8 nSize) {
|
||||
*pBegin = opt;
|
||||
pBegin++;
|
||||
*pBegin = nSize;
|
||||
pBegin++;
|
||||
memcpy(pBegin, buf, nSize);
|
||||
pBegin += nSize;
|
||||
}
|
||||
|
||||
int dhcp_get_option(int opt, U8 *pOptData, U32 nSize, PDHCP_OPT pVal) {
|
||||
U8 *p = pOptData;
|
||||
|
||||
|
|
|
@ -18,17 +18,26 @@
|
|||
#include "network/vlan.h"
|
||||
#include "dhcp_options.h"
|
||||
#include "config.h"
|
||||
#include "misc.h"
|
||||
#include "user_mgr.h"
|
||||
|
||||
#define PKG_MMAP_BLOCKSIZ (1 << 22)
|
||||
#define PKG_MMAP_FRAMESIZ (1 << 11)
|
||||
#define PKG_MMAP_BLOCKNUM (64)
|
||||
#define PKG_MMAP_BLOCKSIZ (1 << 22)
|
||||
#define PKG_MMAP_FRAMESIZ (1 << 11)
|
||||
#define PKG_MMAP_BLOCKNUM (64)
|
||||
#define MAX_DHCP_PKG_SIZE (512)
|
||||
|
||||
#define MIN_IPADDR (0xC0A80202)
|
||||
#define DHCP_NETMASK (0xFFFF0000)
|
||||
#define GW_IPADDR (0xC0A80201)
|
||||
#define MASTER_DNS (0x08080808)
|
||||
#define SALVE_DNS (0x72727272)
|
||||
#define MAC_TO_STR(mac, str) sprintf(str, "%02X:%02X:%02X:%02X:%02X:%02X", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5])
|
||||
|
||||
typedef struct {
|
||||
U8 unicast;
|
||||
U8 cliMac[ETH_ALEN];
|
||||
U32 xid;
|
||||
U32 reqIpAddr;
|
||||
U32 leaseTime;
|
||||
char clientId[256];
|
||||
char vendorClassId[256];
|
||||
char hostName[256];
|
||||
} DHCP_REQ, *PDHCP_REQ;
|
||||
|
||||
typedef struct {
|
||||
struct iovec *rd;
|
||||
|
@ -36,6 +45,14 @@ typedef struct {
|
|||
struct tpacket_req3 req;
|
||||
} PACKET_MMAP_RING, *PPACKET_MMAP_RING;
|
||||
|
||||
typedef struct {
|
||||
char *pIfName;
|
||||
U32 ipAddr;
|
||||
U32 netmask;
|
||||
U8 macAddr[ETH_ALEN];
|
||||
S8 hostname[MAX_PATH];
|
||||
} NIC_INFO, *PNIC_INFO;
|
||||
|
||||
struct block_desc {
|
||||
uint32_t version;
|
||||
uint32_t offset_to_priv;
|
||||
|
@ -62,6 +79,7 @@ typedef struct {
|
|||
} PKG_MSG, *PPKG_MSG;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
/*
|
||||
TORs (Top of Rack switch) at Facebook run DHCP relayers, these relayers are
|
||||
responsible for relaying broadcast DHCP traffic (DISCOVERY and SOLICIT
|
||||
|
@ -69,7 +87,8 @@ messages) originating within their racks to anycast VIPs, one DHCPv4 and one
|
|||
for DHCPv6.
|
||||
*/
|
||||
static struct sock_filter g_filterCode[] = {
|
||||
#ifdef UDP_DHCP_FILTER // create by: tcpdump "udp and port 67 and port 68" -dd
|
||||
#ifdef UDP_DHCP_FILTER
|
||||
// create by: tcpdump "udp and port 67 and port 68" -dd
|
||||
{0x28, 0, 0, 0x0000000c},
|
||||
{0x15, 0, 9, 0x000086dd},
|
||||
{0x30, 0, 0, 0x00000014},
|
||||
|
@ -181,6 +200,7 @@ static struct sock_filter g_filterCode[] = {
|
|||
};
|
||||
|
||||
static PACKET_MMAP_RING g_pkgRing;
|
||||
static NIC_INFO g_nicInfo;
|
||||
|
||||
#define VLAN_VNI_ID(x) ntohs((x))
|
||||
#define DHCP_XID(x) ntohl((x))
|
||||
|
@ -190,17 +210,110 @@ static struct sock_fprog bpf = {
|
|||
.filter = g_filterCode,
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
U8 unicast;
|
||||
U8 cliMac[ETH_ALEN];
|
||||
U32 xid;
|
||||
U32 reqIpAddr;
|
||||
U32 leaseTime;
|
||||
char *clientId;
|
||||
char *vendorClassId;
|
||||
} DHCP_REQ, *PDHCP_REQ;
|
||||
static int dhcp_resp_offer(PDHCP_PACKAGE pReq, PIPPOOL_INFO pIpInfo, U32 ip) {
|
||||
PDHCP_PACKAGE pRsp = (PDHCP_PACKAGE)malloc(MAX_DHCP_PKG_SIZE);
|
||||
U8 *pOpt = pRsp->dhcp.options;
|
||||
|
||||
if (pRsp == NULL) {
|
||||
LOG_MOD(error, ZLOG_MOD_DHCPD, "Malloc memory error: %u\n", MAX_DHCP_PKG_SIZE);
|
||||
return -ERR_MALLOC_MEMORY;
|
||||
}
|
||||
|
||||
memset(pRsp, 0, MAX_DHCP_PKG_SIZE);
|
||||
|
||||
// 二层头
|
||||
// 目的IP地址
|
||||
memset(pRsp->vlan_hdr.eth.h_dest, 0xFF, ETH_ALEN);
|
||||
// 源 IP 地址
|
||||
memcpy(pRsp->vlan_hdr.eth.h_source, g_nicInfo.macAddr, ETH_ALEN);
|
||||
// protol
|
||||
pRsp->vlan_hdr.eth.h_proto = pReq->vlan_hdr.eth.h_proto;
|
||||
|
||||
// QinQ 隧道
|
||||
pRsp->vlan_hdr.vlan.id = pReq->vlan_hdr.vlan.id;
|
||||
pRsp->vlan_hdr.vlan.type = pReq->vlan_hdr.vlan.type;
|
||||
// TODO 可能的二层QinQ隧道
|
||||
|
||||
// IP 头
|
||||
memcpy(&pRsp->vlan_hdr.ip, &pReq->vlan_hdr.ip, sizeof(struct iphdr));
|
||||
// 更新源IP
|
||||
pRsp->vlan_hdr.ip.saddr = htonl(g_nicInfo.ipAddr);
|
||||
// 更新目的IP地址,广播255.255.255.255
|
||||
pRsp->vlan_hdr.ip.daddr = 0xFFFFFFFF;
|
||||
|
||||
// UDP 头
|
||||
// 目的端口
|
||||
pRsp->vlan_hdr.udp.dest = pReq->vlan_hdr.udp.source;
|
||||
// 源端口
|
||||
pRsp->vlan_hdr.udp.source = pReq->vlan_hdr.udp.dest;
|
||||
|
||||
//DHCP 协议
|
||||
// 返回类型
|
||||
pRsp->dhcp.op = BOOTP_REPLY;
|
||||
// 地址类型长度
|
||||
pRsp->dhcp.htype = pReq->dhcp.htype;
|
||||
// 地址长度
|
||||
pRsp->dhcp.hlen = pReq->dhcp.hlen;
|
||||
// xid
|
||||
pRsp->dhcp.xid = pReq->dhcp.xid;
|
||||
// 分配的 IP 地址
|
||||
pRsp->dhcp.yiaddr = htonl(ip);
|
||||
// 客户端 MAC 地址
|
||||
memcpy(pRsp->dhcp.chaddr, pReq->dhcp.chaddr, ETH_ALEN);
|
||||
// DHCP服务端主机名
|
||||
memcpy(pRsp->dhcp.sname, g_nicInfo.hostname, MIN(64, strlen(g_nicInfo.hostname)));
|
||||
// Magic Cookie: DHCP
|
||||
memcpy(&pRsp->dhcp.cookie, "DHCP", 4);
|
||||
pRsp->dhcp.hops = 0;
|
||||
pRsp->dhcp.secs = 0;
|
||||
pRsp->dhcp.flags = 0;
|
||||
pRsp->dhcp.ciaddr = 0;
|
||||
pRsp->dhcp.siaddr = 0;
|
||||
pRsp->dhcp.giaddr = 0;
|
||||
|
||||
// DHCP Options
|
||||
// DHCP 消息类型
|
||||
dhcp_add_number_option(pOpt, OPT_MESSAGETYPE, DHCP_MSG_OFFER, 1);
|
||||
pOpt += 3;
|
||||
// 子网掩码
|
||||
dhcp_add_number_option(pOpt, OPT_NETMASK, pIpInfo->netMask, 4);
|
||||
pOpt += 6;
|
||||
// 租约
|
||||
dhcp_add_number_option(pOpt, OPT_IPADDRLEASE, htonl(pIpInfo->leaseTime), 4);
|
||||
pOpt += 6;
|
||||
// DHCP Server
|
||||
dhcp_add_number_option(pOpt, OPT_SERVERID, g_nicInfo.ipAddr, 4);
|
||||
pOpt += 6;
|
||||
// DNS
|
||||
if (pIpInfo->primeDNS != 0) {
|
||||
if (pIpInfo->salveDNS == 0) {
|
||||
dhcp_add_number_option(pOpt, OPT_DNS, pIpInfo->primeDNS, 4);
|
||||
pOpt += 6;
|
||||
} else {
|
||||
dhcp_add_buf_option(pOpt, OPT_DNS, (U8 *)&pIpInfo->primeDNS, 8);
|
||||
pOpt += 10;
|
||||
}
|
||||
}
|
||||
// 网关
|
||||
if (pIpInfo->gwAddr != 0) {
|
||||
dhcp_add_number_option(pOpt, OPT_ROUTER, pIpInfo->gwAddr, 4);
|
||||
pOpt += 6;
|
||||
}
|
||||
// DHCP 主机名
|
||||
dhcp_add_buf_option(pOpt, OPT_DOMAINNAME, (U8 *)g_nicInfo.hostname, strlen(g_nicInfo.hostname));
|
||||
pOpt += strlen(g_nicInfo.hostname) + 2;
|
||||
|
||||
*pOpt = OPT_END;
|
||||
|
||||
LOG_MSG_HEX(debug, pRsp, 256);
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
static void on_sock_recv(uv_work_t *req) {
|
||||
char macStr[20] = {0};
|
||||
U32 ip;
|
||||
PIPPOOL_INFO pIpInfo;
|
||||
DHCP_REQ reqDhcp;
|
||||
DHCP_OPT optMsg, opt;
|
||||
int ret;
|
||||
|
@ -208,6 +321,8 @@ static void on_sock_recv(uv_work_t *req) {
|
|||
PDHCP_PACKAGE pkg = (PDHCP_PACKAGE)pWork->pPkgBase;
|
||||
U32 optSize = pWork->nSize - sizeof(DHCP_PACKAGE);
|
||||
|
||||
sprintf(macStr, "%02X:%02X:%02X:%02X:%02X:%02X", macStr[0], macStr[1], macStr[2], macStr[3], macStr[4], macStr[5]);
|
||||
|
||||
// Check op flag
|
||||
if (pkg->dhcp.op != BOOTP_REQUEST) {
|
||||
LOG_MOD(error, ZLOG_MOD_DHCPD, "Error message op code %d\n", pkg->dhcp.op);
|
||||
|
@ -240,12 +355,33 @@ static void on_sock_recv(uv_work_t *req) {
|
|||
|
||||
ret = dhcp_get_option(OPT_CLIENTID, pkg->dhcp.options, optSize, &opt);
|
||||
if (ret == ERR_SUCCESS) {
|
||||
reqDhcp.clientId = (char *)opt.pValue;
|
||||
strncpy(reqDhcp.clientId, (char *)opt.pValue, MIN((int)opt.len, 256));
|
||||
}
|
||||
|
||||
ret = dhcp_get_option(OPT_VENDORCLASSID, pkg->dhcp.options, optSize, &opt);
|
||||
if (ret == ERR_SUCCESS) {
|
||||
reqDhcp.vendorClassId = (char *)opt.pValue;
|
||||
strncpy(reqDhcp.vendorClassId, (char *)opt.pValue, MIN((int)opt.len, 256));
|
||||
}
|
||||
|
||||
ret = dhcp_get_option(OPT_HOSTNAME, pkg->dhcp.options, optSize, &opt);
|
||||
if (ret == ERR_SUCCESS) {
|
||||
strncpy(reqDhcp.hostName, (char *)opt.pValue, MIN((int)opt.len, 256));
|
||||
}
|
||||
|
||||
MAC_TO_STR(reqDhcp.cliMac, macStr);
|
||||
ret = pre_alloc_dhcp_res(VLAN_VNI_ID(pkg->vlan_hdr.vlan.id), macStr, &ip, &pIpInfo);
|
||||
|
||||
if (ret == ERR_SUCCESS) {
|
||||
LOG_MOD(trace,
|
||||
ZLOG_MOD_DHCPD,
|
||||
"DHCP prepare assign ipaddress: [%s(%s)] --> %s\n",
|
||||
macStr,
|
||||
reqDhcp.hostName,
|
||||
u32_to_str_ip(ntohl(ip)));
|
||||
|
||||
ret = dhcp_resp_offer(pkg, pIpInfo, ip);
|
||||
} else {
|
||||
//LOG_MOD(error, ZLOG_MOD_DHCPD, );
|
||||
}
|
||||
break;
|
||||
case DHCP_MSG_REQUEST:
|
||||
|
@ -416,7 +552,7 @@ static int create_udp_socket() {
|
|||
#endif
|
||||
// 6. bind socket
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sll_ifindex = (int)if_nametoindex(config_get_dhcp_nic_name());
|
||||
addr.sll_ifindex = (int)if_nametoindex(g_nicInfo.pIfName);
|
||||
addr.sll_family = AF_PACKET;
|
||||
addr.sll_protocol = htons(ETH_P_ALL);
|
||||
addr.sll_hatype = 0;
|
||||
|
@ -434,8 +570,16 @@ static int create_udp_socket() {
|
|||
int dhcpd_init() {
|
||||
static uv_udp_t uvRaw;
|
||||
static uv_poll_t uvSocket;
|
||||
int sock;
|
||||
size_t size = MAX_PATH;
|
||||
|
||||
int sock = create_udp_socket();
|
||||
memset(&g_nicInfo, 0, sizeof(NIC_INFO));
|
||||
g_nicInfo.pIfName = (char *)config_get_dhcp_nic_name();
|
||||
uv_os_gethostname(g_nicInfo.hostname, &size);
|
||||
|
||||
get_nic_info(g_nicInfo.pIfName, &g_nicInfo.ipAddr, &g_nicInfo.netmask, NULL, g_nicInfo.macAddr);
|
||||
|
||||
sock = create_udp_socket();
|
||||
|
||||
if (sock <= 0) {
|
||||
return sock;
|
||||
|
|
|
@ -141,6 +141,8 @@ typedef struct {
|
|||
U8 len;
|
||||
} DHCP_OPT, *PDHCP_OPT;
|
||||
|
||||
void dhcp_add_number_option(U8 *pBegin, int opt, U8 value, U8 nSize);
|
||||
void dhcp_add_buf_option(U8 *pBegin, int opt, U8 *buf, U8 nSize);
|
||||
int dhcp_get_option(int opt, U8 *pOptData, U32 nSize, PDHCP_OPT pVal);
|
||||
void dhcp_option_cfg_init();
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#define VCPE_IP_POOL_H
|
||||
#include <uthash/uthash.h>
|
||||
#include <common.h>
|
||||
#include <bitset/bitset.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -18,7 +20,7 @@ extern "C" {
|
|||
#define MAX_POOL_HASH_KEY (18)
|
||||
|
||||
typedef struct {
|
||||
S8 poolKey[MAX_POOL_HASH_KEY];
|
||||
U32 poolKey;
|
||||
U32 minAddr;
|
||||
U32 maxAddr;
|
||||
U32 netMask;
|
||||
|
@ -26,6 +28,7 @@ typedef struct {
|
|||
U32 primeDNS;
|
||||
U32 salveDNS;
|
||||
U32 leaseTime;
|
||||
bitset_t *assignPool;
|
||||
UT_hash_handle hh;
|
||||
} IPPOOL_INFO, *PIPPOOL_INFO;
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <uthash/uthash.h>
|
||||
#include <linux/if_ether.h>
|
||||
#include <common.h>
|
||||
#include "ip_pool.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -25,6 +26,7 @@ typedef struct {
|
|||
} LEASE_CACHE, *PLEASE_CACHE;
|
||||
|
||||
int dhcp_lease_init();
|
||||
int pre_alloc_dhcp_res(U32 uid, const char *pMac, U32 *pOutIp, PIPPOOL_INFO *pOutPool);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -20,8 +20,9 @@ typedef struct {
|
|||
UT_hash_handle hh;
|
||||
} DHCP_USER_INFO, *PDHCP_USER_INFO;
|
||||
|
||||
int user_add_ip_pool(U32 uId, PIPPOOL_INFO pPool);
|
||||
int dhcp_user_mgr_init();
|
||||
int user_add_ip_pool(U32 uId, PIPPOOL_INFO pPool);
|
||||
int dhcp_user_mgr_init();
|
||||
PIPPOOL_INFO user_get_pool(U32 uId);
|
||||
#ifdef HTTPSERVER_ON
|
||||
int user_init_httpd();
|
||||
#endif
|
||||
|
|
|
@ -8,8 +8,7 @@
|
|||
#include "user_errno.h"
|
||||
#include "zlog_module.h"
|
||||
#include "user_mgr.h"
|
||||
|
||||
#define GEN_IP_POOL_HASH_KEY(p) (sprintf((p)->poolKey, "%08X-%08X", (p)->minAddr, (p)->maxAddr))
|
||||
#include "ipaddr.h"
|
||||
|
||||
static PIPPOOL_INFO g_defPool = NULL;
|
||||
|
||||
|
@ -34,6 +33,8 @@ void init_default_pool() {
|
|||
continue;
|
||||
}
|
||||
|
||||
memset(p, 0, sizeof(IPPOOL_INFO));
|
||||
|
||||
if (strlen(pRange->rangAddr) == 0) {
|
||||
LOG_MOD(error, ZLOG_MOD_OPENDHCPD, "Error ip pool configure of address\n");
|
||||
free(p);
|
||||
|
@ -61,7 +62,7 @@ void init_default_pool() {
|
|||
free(p);
|
||||
continue;
|
||||
} else {
|
||||
p->minAddr = addr.s_addr;
|
||||
p->minAddr = ntohl(addr.s_addr);
|
||||
}
|
||||
|
||||
if (inet_aton(pSecIp, &addr) == 0) {
|
||||
|
@ -69,30 +70,48 @@ void init_default_pool() {
|
|||
free(p);
|
||||
continue;
|
||||
} else {
|
||||
p->maxAddr = addr.s_addr;
|
||||
p->maxAddr = ntohl(addr.s_addr);
|
||||
}
|
||||
|
||||
// 填充POOL Hash Key
|
||||
GEN_IP_POOL_HASH_KEY(p);
|
||||
} else {
|
||||
LOG_MOD(error, ZLOG_MOD_DHCPD, "Bad DHCP range format: %s\n", tmpStr);
|
||||
free(p);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strlen(pRange->subnet) > 0) {
|
||||
if (inet_aton(pRange->subnet, &addr) == 0) {
|
||||
LOG_MOD(error, ZLOG_MOD_DHCPD, "Convert ip ERROR: %s\n", pRange->subnet);
|
||||
} else {
|
||||
p->netMask = ntohl(addr.s_addr);
|
||||
}
|
||||
} else {
|
||||
// 当前网络默认IP地址池
|
||||
if (inet_aton("255.255.255.0", &addr) == 0) {
|
||||
LOG_MOD(error, ZLOG_MOD_DHCPD, "Convert ip ERROR: %s\n", pRange->subnet);
|
||||
} else {
|
||||
p->netMask = ntohl(addr.s_addr);
|
||||
}
|
||||
}
|
||||
|
||||
// 填充POOL Hash Key
|
||||
p->poolKey = ipv4_get_network_addr(p->minAddr, p->netMask);
|
||||
p->assignPool = bitset_create_with_capacity(ipv4_network_total_addr(p->netMask));
|
||||
|
||||
if (!p->assignPool) {
|
||||
LOG_MOD(error,
|
||||
ZLOG_MOD_DHCPD,
|
||||
"Create address pool bitset ERROR: 0x%08X total address %u\n",
|
||||
htonl(p->netMask),
|
||||
ipv4_network_total_addr(p->netMask));
|
||||
free(p);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strlen(pRange->gateway) > 0) {
|
||||
if (inet_aton(pRange->gateway, &addr) == 0) {
|
||||
LOG_MOD(error, ZLOG_MOD_DHCPD, "Convert ip ERROR: %s\n", pRange->gateway);
|
||||
} else {
|
||||
p->gwAddr = addr.s_addr;
|
||||
}
|
||||
}
|
||||
|
||||
if (strlen(pRange->subnet) > 0) {
|
||||
if (inet_aton(pRange->subnet, &addr) == 0) {
|
||||
LOG_MOD(error, ZLOG_MOD_DHCPD, "Convert ip ERROR: %s\n", pRange->subnet);
|
||||
} else {
|
||||
p->netMask = addr.s_addr;
|
||||
p->gwAddr = ntohl(addr.s_addr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,19 +128,19 @@ void init_default_pool() {
|
|||
if (inet_aton(tmpStr, &addr) == 0) {
|
||||
LOG_MOD(error, ZLOG_MOD_DHCPD, "Convert ip ERROR: %s of %s\n", tmpStr, pRange->dnsSvr);
|
||||
} else {
|
||||
p->primeDNS = addr.s_addr;
|
||||
p->primeDNS = ntohl(addr.s_addr);
|
||||
}
|
||||
|
||||
if (inet_aton(pSecIp, &addr) == 0) {
|
||||
LOG_MOD(error, ZLOG_MOD_DHCPD, "Convert ip ERROR: %s of %s\n", pSecIp, pRange->dnsSvr);
|
||||
} else {
|
||||
p->salveDNS = addr.s_addr;
|
||||
p->salveDNS = ntohl(addr.s_addr);
|
||||
}
|
||||
} else {
|
||||
if (inet_aton(pRange->dnsSvr, &addr) == 0) {
|
||||
LOG_MOD(error, ZLOG_MOD_DHCPD, "Convert ip ERROR: %s of %s\n", tmpStr, pRange->dnsSvr);
|
||||
} else {
|
||||
p->primeDNS = addr.s_addr;
|
||||
p->primeDNS = ntohl(addr.s_addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,15 +2,28 @@
|
|||
// Created by xajhuang on 2023/3/23.
|
||||
//
|
||||
|
||||
#include <time.h>
|
||||
#include "lease.h"
|
||||
#include "user_errno.h"
|
||||
#include "zlog_module.h"
|
||||
#include "database.h"
|
||||
#include "user_mgr.h"
|
||||
|
||||
#define LEASE_DB_NAME ("lease")
|
||||
#define LEASE_DB_NAME ("lease")
|
||||
#define PREALLOC_IP_TIMEOUT (60)
|
||||
|
||||
static PMAC_FILTER g_allowTbl = NULL;
|
||||
static PMAC_FILTER g_blackListTbl = NULL;
|
||||
typedef struct {
|
||||
U32 ipAddr;
|
||||
char macAddr[20];
|
||||
U32 bitset;
|
||||
PIPPOOL_INFO pCtx;
|
||||
U32 timeStamp;
|
||||
UT_hash_handle hh;
|
||||
} PRE_ALLOC_IP, *PPRE_ALLOC_IP;
|
||||
|
||||
//static PMAC_FILTER g_allowTbl = NULL;
|
||||
//static PMAC_FILTER g_blackListTbl = NULL;
|
||||
static PPRE_ALLOC_IP g_pPreAllocIp = NULL;
|
||||
|
||||
#define CREATE_LEASE_TABLE(name) \
|
||||
"CREATE TABLE IF NOT EXISTS " #name \
|
||||
|
@ -19,7 +32,7 @@ static PMAC_FILTER g_blackListTbl = NULL;
|
|||
" mac CHAR(20) NOT NULL," \
|
||||
" ip INTEGER NOT NULL," \
|
||||
" lease INTEGER NOT NULL," \
|
||||
" create INTEGER NOT NULL," \
|
||||
" createTm INTEGER NOT NULL," \
|
||||
" netmask INTEGER," \
|
||||
" gateway INTEGER," \
|
||||
" dns1 INTEGER," \
|
||||
|
@ -30,10 +43,117 @@ static PMAC_FILTER g_blackListTbl = NULL;
|
|||
");" \
|
||||
"CREATE INDEX IF NOT EXISTS " #name "_index ON " #name " (uid, mac);"
|
||||
|
||||
int pre_alloc_dhcp_res(U32 uid, const char *pMac, U32 *pOutIp, PIPPOOL_INFO *pOutPool) {
|
||||
PIPPOOL_INFO pPool, pTemp;
|
||||
PPRE_ALLOC_IP pNewIp, pTmp, pCache = NULL;
|
||||
PIPPOOL_INFO pUserPool;
|
||||
|
||||
if (pOutIp == NULL || pOutPool == NULL) {
|
||||
LOG_MOD(error, ZLOG_MOD_DHCPD, "Input params error: %p, %p\n", pOutIp, pOutPool);
|
||||
return -ERR_INPUT_PARAMS;
|
||||
}
|
||||
|
||||
pUserPool = user_get_pool(uid);
|
||||
if (pUserPool == NULL) {
|
||||
LOG_MOD(error, ZLOG_MOD_DHCPD, "Can't found avaliable address pool\n");
|
||||
return -ERR_DHCP_NO_POOL;
|
||||
}
|
||||
|
||||
// 遍历当前用户所有IP地址池
|
||||
HASH_ITER(hh, pUserPool, pPool, pTemp) {
|
||||
U32 addr;
|
||||
|
||||
// 查看是否预分配过该设备
|
||||
if (pMac && strlen(pMac) > 0) {
|
||||
HASH_ITER(hh, g_pPreAllocIp, pNewIp, pTmp) {
|
||||
if (strcmp(pNewIp->macAddr, pMac) == 0) {
|
||||
*pOutIp = pNewIp->ipAddr;
|
||||
*pOutPool = pPool;
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while ((addr = bitset_minimum(pPool->assignPool)) > 0) {
|
||||
U32 ipAddr = (pPool->minAddr & pPool->netMask) + addr;
|
||||
|
||||
// 查找租约配置文件中是否记录了曾经分配的地址, 如果已经分配则获取下一个
|
||||
// TODO: add process
|
||||
// if (FALSE) {
|
||||
// bitset_set(pPool->assignPool, addr);
|
||||
// continue;
|
||||
// }
|
||||
|
||||
// 查找IP地址是否已经被预分配
|
||||
HASH_FIND_INT(g_pPreAllocIp, &ipAddr, pNewIp);
|
||||
|
||||
if (pNewIp == NULL) {
|
||||
pNewIp = (PPRE_ALLOC_IP)malloc(sizeof(PRE_ALLOC_IP));
|
||||
|
||||
if (!pNewIp) {
|
||||
LOG_MOD(error, ZLOG_MOD_DHCPD, "Malloc memory error: %lu\n", sizeof(PRE_ALLOC_IP));
|
||||
continue;
|
||||
}
|
||||
|
||||
memset(pNewIp, 0, sizeof(PRE_ALLOC_IP));
|
||||
|
||||
pNewIp->timeStamp = time(NULL);
|
||||
pNewIp->pCtx = pPool;
|
||||
pNewIp->ipAddr = ipAddr;
|
||||
pNewIp->bitset = addr;
|
||||
if (pMac) {
|
||||
strcpy(pNewIp->macAddr, pMac);
|
||||
}
|
||||
|
||||
HASH_ADD_INT(g_pPreAllocIp, ipAddr, pNewIp);
|
||||
|
||||
*pOutIp = ipAddr;
|
||||
*pOutPool = pPool;
|
||||
|
||||
bitset_cls_bit(pPool->assignPool, addr);
|
||||
return ERR_SUCCESS;
|
||||
} else {
|
||||
if (time(NULL) - pNewIp->timeStamp < PREALLOC_IP_TIMEOUT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
*pOutIp = pNewIp->ipAddr;
|
||||
*pOutPool = pPool;
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有分配到IP,清理过期的预分配IP
|
||||
HASH_ITER(hh, g_pPreAllocIp, pNewIp, pTmp) {
|
||||
if (time(NULL) - pNewIp->timeStamp > PREALLOC_IP_TIMEOUT) {
|
||||
if (pCache == NULL) {
|
||||
pCache = pNewIp;
|
||||
} else {
|
||||
HASH_DEL(g_pPreAllocIp, pNewIp);
|
||||
free(pNewIp);
|
||||
bitset_cls_bit(pNewIp->pCtx->assignPool, pNewIp->bitset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pCache) {
|
||||
*pOutIp = pCache->ipAddr;
|
||||
*pOutPool = pPool;
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
// 没有可预分配的IP,报错
|
||||
LOG_MOD(error, ZLOG_MOD_DHCPD, "No free ipaddress in poll: uid = %u, pool = 0x%08X\n", uid, pUserPool->poolKey);
|
||||
return -ERR_DHCP_NO_ADDR;
|
||||
}
|
||||
|
||||
int dhcp_lease_init() {
|
||||
int rc = 0;
|
||||
|
||||
rc = db_sqlite3_sql_exec(CREATE_LEASE_TABLE(lease), NULL, NULL, NULL);
|
||||
rc = db_sqlite3_sql_exec(CREATE_LEASE_TABLE(LEASE_DB_NAME), NULL, NULL, NULL);
|
||||
|
||||
if (rc != ERR_SUCCESS) {
|
||||
return rc;
|
||||
|
|
|
@ -176,6 +176,7 @@ int user_init_httpd() {
|
|||
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
// endregion
|
||||
#endif
|
||||
|
||||
|
@ -196,7 +197,30 @@ int user_alloc_addr(U32 uId, U8 mac[ETH_ALEN], U32 *pAddr) {
|
|||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
PIPPOOL_INFO user_get_pool(U32 uId) {
|
||||
PDHCP_USER_INFO pUser;
|
||||
|
||||
HASH_FIND_INT(g_dhcpUsrCfg, &uId, pUser);
|
||||
|
||||
if (pUser == NULL) {
|
||||
U32 id = 0;
|
||||
|
||||
HASH_FIND_INT(g_dhcpUsrCfg, &id, pUser);
|
||||
|
||||
if (pUser == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pUser->pPoolMgr;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int user_add_ip_pool(U32 uId, PIPPOOL_INFO pPool) {
|
||||
U32 k;
|
||||
U32 begin;
|
||||
U32 end;
|
||||
PIPPOOL_INFO pPoolCfg;
|
||||
PDHCP_USER_INFO pUserCfg, pTemp;
|
||||
|
||||
|
@ -207,15 +231,24 @@ int user_add_ip_pool(U32 uId, PIPPOOL_INFO pPool) {
|
|||
return ERR_SUCCESS;
|
||||
}
|
||||
|
||||
HASH_FIND_STR(pUserCfg->pPoolMgr, pPool->poolKey, pPoolCfg);
|
||||
HASH_FIND_INT(pUserCfg->pPoolMgr, &pPool->poolKey, pPoolCfg);
|
||||
|
||||
// 改地址池已经存在,提示错误
|
||||
if (pPoolCfg != NULL) {
|
||||
return -ERR_ITEM_EXISTS;
|
||||
free(pPool);
|
||||
} else {
|
||||
// 添加新地址池当前用户配置项中
|
||||
HASH_ADD_INT(pUserCfg->pPoolMgr, poolKey, pPool);
|
||||
pPoolCfg = pPool;
|
||||
}
|
||||
|
||||
// 添加到当前用户配置项中
|
||||
HASH_ADD_STR(pUserCfg->pPoolMgr, poolKey, pPool);
|
||||
// 计算可用的IP
|
||||
begin = ntohl(pPoolCfg->minAddr) & ntohl(~pPoolCfg->netMask);
|
||||
end = ntohl(pPoolCfg->maxAddr) & ntohl(~pPoolCfg->netMask);
|
||||
|
||||
for (k = MAX(begin, 1U); k <= MIN(end, ntohl(~pPoolCfg->netMask) - 1); k++) {
|
||||
bitset_set(pPoolCfg->assignPool, k);
|
||||
}
|
||||
|
||||
return ERR_SUCCESS;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue