mirror of
https://github.com/cesanta/mongoose.git
synced 2026-10-17 10:49:47 +00:00
Add mg_crc16(), make PPP use it
This commit is contained in:
1 parent
03be16803c
commit
7821fb9ab4
7 files changed
+65
-38
No files matched your search
+17
-19
@@ -5948,30 +5948,14 @@ uint8_t *mg_l2_pppoe_header(struct mg_tcpip_if *ifp, enum mg_l2proto proto,
|
||||
s_id, src, dst, frame));
|
||||
}
|
||||
|
||||
// Calculate FCS/CRC for PPP frames. Could be implemented faster using lookup
|
||||
// tables.
|
||||
static uint16_t fcs_do(uint8_t *frame, size_t len) {
|
||||
uint32_t fcs = 0xffff;
|
||||
unsigned int j;
|
||||
for (j = 0; j < len; j++) {
|
||||
unsigned int i;
|
||||
uint8_t x = frame[j];
|
||||
for (i = 0; i < 8; i++) {
|
||||
fcs = ((fcs ^ x) & 1) ? (fcs >> 1) ^ 0x8408 : fcs >> 1;
|
||||
x >>= 1;
|
||||
}
|
||||
}
|
||||
return (uint16_t) (fcs & 0xffff);
|
||||
}
|
||||
|
||||
size_t mg_l2_ppp_trailer(struct mg_tcpip_if *ifp, size_t len, uint8_t *cur) {
|
||||
uint16_t crc;
|
||||
uint8_t *frame;
|
||||
len += sizeof(struct ppp) + sizeof(struct hdlc_);
|
||||
frame = cur - len;
|
||||
crc = fcs_do(frame, len);
|
||||
*cur++ = (uint8_t) ~crc; // add CRC, note the byte order
|
||||
*cur++ = (uint8_t) (~crc >> 8);
|
||||
crc = mg_crc16(0, (const char *) frame, len);
|
||||
*cur++ = (uint8_t) crc; // add CRC, note the byte order
|
||||
*cur++ = (uint8_t) (crc >> 8);
|
||||
// there is no len field in PPP
|
||||
(void) ifp;
|
||||
return len + 2;
|
||||
@@ -26075,6 +26059,20 @@ uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len) {
|
||||
return ~crc;
|
||||
}
|
||||
|
||||
uint16_t mg_crc16(uint16_t crc, const char *buf, size_t len) {
|
||||
static const uint16_t crclut[16] = {
|
||||
// table for polynomial 0x8408 (reflected)
|
||||
0x0000, 0x1081, 0x2102, 0x3183, 0x4204, 0x5285, 0x6306, 0x7387,
|
||||
0x8408, 0x9489, 0xA50A, 0xB58B, 0xC60C, 0xD68D, 0xE70E, 0xF78F};
|
||||
unsigned int c = (unsigned int) ~crc & 0xffff;
|
||||
while (len--) {
|
||||
uint8_t b = *(uint8_t *) buf++;
|
||||
c = crclut[(c ^ b) & 0x0F] ^ (c >> 4);
|
||||
c = crclut[(c ^ (b >> 4)) & 0x0F] ^ (c >> 4);
|
||||
}
|
||||
return (uint16_t) ~c;
|
||||
}
|
||||
|
||||
static int isbyte(int n) {
|
||||
return n >= 0 && n <= 255;
|
||||
}
|
||||
|
||||
@@ -1960,6 +1960,10 @@ char *mg_random_str(char *buf, size_t len);
|
||||
// a new checksum; pass the result of a prior call to extend over more data.
|
||||
uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len);
|
||||
|
||||
// Computes CRC16 (HDLC, polynomial 0x8408) over buf/len. Pass crc=0 to start
|
||||
// a new checksum; pass the result of a prior call to extend over more data.
|
||||
uint16_t mg_crc16(uint16_t crc, const char *buf, size_t len);
|
||||
|
||||
// Returns true if path is safe to serve from the filesystem. Rejects paths
|
||||
// that start with '~' or '..', or contain a '/../' component, to prevent
|
||||
// directory traversal attacks.
|
||||
|
||||
+3
-19
@@ -169,30 +169,14 @@ uint8_t *mg_l2_pppoe_header(struct mg_tcpip_if *ifp, enum mg_l2proto proto,
|
||||
s_id, src, dst, frame));
|
||||
}
|
||||
|
||||
// Calculate FCS/CRC for PPP frames. Could be implemented faster using lookup
|
||||
// tables.
|
||||
static uint16_t fcs_do(uint8_t *frame, size_t len) {
|
||||
uint32_t fcs = 0xffff;
|
||||
unsigned int j;
|
||||
for (j = 0; j < len; j++) {
|
||||
unsigned int i;
|
||||
uint8_t x = frame[j];
|
||||
for (i = 0; i < 8; i++) {
|
||||
fcs = ((fcs ^ x) & 1) ? (fcs >> 1) ^ 0x8408 : fcs >> 1;
|
||||
x >>= 1;
|
||||
}
|
||||
}
|
||||
return (uint16_t) (fcs & 0xffff);
|
||||
}
|
||||
|
||||
size_t mg_l2_ppp_trailer(struct mg_tcpip_if *ifp, size_t len, uint8_t *cur) {
|
||||
uint16_t crc;
|
||||
uint8_t *frame;
|
||||
len += sizeof(struct ppp) + sizeof(struct hdlc_);
|
||||
frame = cur - len;
|
||||
crc = fcs_do(frame, len);
|
||||
*cur++ = (uint8_t) ~crc; // add CRC, note the byte order
|
||||
*cur++ = (uint8_t) (~crc >> 8);
|
||||
crc = mg_crc16(0, (const char *) frame, len);
|
||||
*cur++ = (uint8_t) crc; // add CRC, note the byte order
|
||||
*cur++ = (uint8_t) (crc >> 8);
|
||||
// there is no len field in PPP
|
||||
(void) ifp;
|
||||
return len + 2;
|
||||
|
||||
+14
@@ -128,6 +128,20 @@ uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len) {
|
||||
return ~crc;
|
||||
}
|
||||
|
||||
uint16_t mg_crc16(uint16_t crc, const char *buf, size_t len) {
|
||||
static const uint16_t crclut[16] = {
|
||||
// table for polynomial 0x8408 (reflected)
|
||||
0x0000, 0x1081, 0x2102, 0x3183, 0x4204, 0x5285, 0x6306, 0x7387,
|
||||
0x8408, 0x9489, 0xA50A, 0xB58B, 0xC60C, 0xD68D, 0xE70E, 0xF78F};
|
||||
unsigned int c = (unsigned int) ~crc & 0xffff;
|
||||
while (len--) {
|
||||
uint8_t b = *(uint8_t *) buf++;
|
||||
c = crclut[(c ^ b) & 0x0F] ^ (c >> 4);
|
||||
c = crclut[(c ^ (b >> 4)) & 0x0F] ^ (c >> 4);
|
||||
}
|
||||
return (uint16_t) ~c;
|
||||
}
|
||||
|
||||
static int isbyte(int n) {
|
||||
return n >= 0 && n <= 255;
|
||||
}
|
||||
|
||||
@@ -40,6 +40,10 @@ char *mg_random_str(char *buf, size_t len);
|
||||
// a new checksum; pass the result of a prior call to extend over more data.
|
||||
uint32_t mg_crc32(uint32_t crc, const char *buf, size_t len);
|
||||
|
||||
// Computes CRC16 (HDLC, polynomial 0x8408) over buf/len. Pass crc=0 to start
|
||||
// a new checksum; pass the result of a prior call to extend over more data.
|
||||
uint16_t mg_crc16(uint16_t crc, const char *buf, size_t len);
|
||||
|
||||
// Returns true if path is safe to serve from the filesystem. Rejects paths
|
||||
// that start with '~' or '..', or contain a '/../' component, to prevent
|
||||
// directory traversal attacks.
|
||||
|
||||
@@ -61,6 +61,17 @@ static void *ppp_payload(uint8_t *frame) {
|
||||
return (struct ppp *) ((struct hdlc_ *) frame + 1) + 1;
|
||||
}
|
||||
|
||||
static void test_fcs(void) {
|
||||
struct mg_tcpip_if ifp;
|
||||
uint8_t frame[] = {0xff, 0x03, 0x00, 0x21, 1, 2, 3, 4, 0, 0};
|
||||
uint8_t fcs[] = {0xae, 0x77};
|
||||
init_if(&ifp, MG_TCPIP_L2_PPP);
|
||||
// PPP trailer stores the FCS bytes in the proper order
|
||||
ASSERT(mg_l2_ppp_trailer(&ifp, 4, frame + sizeof(frame) - sizeof(fcs)) ==
|
||||
sizeof(frame));
|
||||
ASSERT(memcmp(frame + sizeof(frame) - sizeof(fcs), fcs, sizeof(fcs)) == 0);
|
||||
}
|
||||
|
||||
static size_t mk_pppoe_disc(uint8_t *buf, uint8_t code, uint16_t id,
|
||||
const void *payload, size_t len) {
|
||||
struct eth *eth = (struct eth *) buf;
|
||||
@@ -385,6 +396,10 @@ static void test_pppoe(void) {
|
||||
printf("HEALTH_DASHBOARD\t\"%s\": %s,\n", x, s_error ? "false" : "true")
|
||||
|
||||
int main(void) {
|
||||
s_error = false;
|
||||
test_fcs();
|
||||
DASHBOARD("fcs");
|
||||
|
||||
s_error = false;
|
||||
test_lcp();
|
||||
DASHBOARD("lcp");
|
||||
|
||||
@@ -3039,6 +3039,13 @@ static void test_crc32(void) {
|
||||
ASSERT(mg_crc32(mg_crc32(0, "ab", 2), "c", 1) == 891568578);
|
||||
}
|
||||
|
||||
static void test_crc16(void) {
|
||||
ASSERT(mg_crc16(0, 0, 0) == 0);
|
||||
ASSERT(mg_crc16(0, "a", 1) == 0x82f7);
|
||||
ASSERT(mg_crc16(0, "abc", 3) == 0x9e25);
|
||||
ASSERT(mg_crc16(mg_crc16(0, "ab", 2), "c", 1) == 0x9e25);
|
||||
}
|
||||
|
||||
static void us(struct mg_connection *c, int ev, void *ev_data) {
|
||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||
if (ev == MG_EV_HTTP_MSG && mg_match(hm->uri, mg_str("/upload"), NULL)) {
|
||||
@@ -5512,6 +5519,7 @@ int main(void) {
|
||||
test_str();
|
||||
test_match();
|
||||
test_crc32();
|
||||
test_crc16();
|
||||
DASHBOARD("misc");
|
||||
|
||||
s_error = false;
|
||||
|
||||
Reference in new issue
Block a user