This is an automated email from the ASF dual-hosted git repository. pkarashchenko pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
The following commit(s) were added to refs/heads/master by this push: new e211437 Add dn resolution function e211437 is described below commit e2114378b9238cfe98d4c10f2f9cf9a2f88b1445 Author: songlinzhang <songlinzh...@xiaomi.com> AuthorDate: Mon Mar 14 15:50:22 2022 +0800 Add dn resolution function Signed-off-by: songlinzhang <songlinzh...@xiaomi.com> --- include/resolv.h | 8 ++ libs/libc/netdb/Make.defs | 2 +- libs/libc/netdb/lib_dn.c | 314 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 323 insertions(+), 1 deletion(-) diff --git a/include/resolv.h b/include/resolv.h index 5ea6dad..47ca8fb 100644 --- a/include/resolv.h +++ b/include/resolv.h @@ -42,6 +42,14 @@ int b64_ntop(FAR const unsigned char *src, size_t srclen, int b64_pton(FAR const char *src, FAR unsigned char *target, size_t targsize); +/* dn resolution */ + +int dn_comp(FAR const char *src, FAR unsigned char *dst, int space, + FAR unsigned char **dnptrs, FAR unsigned char **lastdnptr); + +int dn_expand(FAR const unsigned char *base, FAR const unsigned char *end, + FAR const unsigned char *src, FAR char *dest, int space); + #if defined(__cplusplus) } #endif diff --git a/libs/libc/netdb/Make.defs b/libs/libc/netdb/Make.defs index dfabc3f..5e71b52 100644 --- a/libs/libc/netdb/Make.defs +++ b/libs/libc/netdb/Make.defs @@ -29,7 +29,7 @@ CSRCS += lib_gethostbyaddr.c lib_gethostbyaddrr.c CSRCS += lib_getservbyname.c lib_getservbynamer.c CSRCS += lib_getservbyport.c lib_getservbyportr.c CSRCS += lib_gaistrerror.c lib_freeaddrinfo.c lib_getaddrinfo.c -CSRCS += lib_getnameinfo.c lib_rexec.c +CSRCS += lib_getnameinfo.c lib_rexec.c lib_dn.c # Add host file support diff --git a/libs/libc/netdb/lib_dn.c b/libs/libc/netdb/lib_dn.c new file mode 100644 index 0000000..8e53e5d --- /dev/null +++ b/libs/libc/netdb/lib_dn.c @@ -0,0 +1,314 @@ +/**************************************************************************** + * libs/libc/netdb/lib_dn.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <string.h> +#include <resolv.h> + +/* RFC 1035 message compression */ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/* label start offsets of a compressed domain name s */ + +static int getoffs(FAR short *offs, FAR const unsigned char *base, + FAR const unsigned char *s) +{ + int i = 0; + + for (; ; ) + { + while ((*s & 0xc0) != 0) + { + if ((*s & 0xc0) != 0xc0) + { + return 0; + } + + s = base + ((s[0] & 0x3f) << 8 | s[1]); + } + + if (*s == 0) + { + return i; + } + + if (s - base >= 0x4000) + { + return 0; + } + + offs[i++] = s - base; + s += *s + 1; + } +} + +/* label lengths of an ascii domain name s */ + +static int getlens(FAR unsigned char *lens, FAR const char *s, int l) +{ + int i = 0; + int j = 0; + int k = 0; + + for (; ; ) + { + for (; j < l && s[j] != '.'; j++); + if (j - k - 1 > 62) + { + return 0; + } + + lens[i++] = j - k; + if (j == l) + { + return i; + } + + k = ++j; + } +} + +/* longest suffix match of an ascii domain with a compressed domain name dn */ + +static int match(FAR int *offset, FAR const unsigned char *base, + FAR const unsigned char *dn, FAR const char *end, + FAR const unsigned char *lens, int nlen) +{ + int l; + int o; + int m = 0; + short offs[128]; + int noff = getoffs(offs, base, dn); + + if (noff == 0) + { + return 0; + } + + for (; ; ) + { + l = lens[--nlen]; + o = offs[--noff]; + end -= l; + if (l != base[o] || memcmp(base + o + 1, end, l) != 0) + { + return m; + } + + *offset = o; + m += l; + if (nlen > 0) + { + m++; + } + + if (nlen == 0 || noff == 0) + { + return m; + } + + end--; + } +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +int dn_comp(FAR const char *src, FAR unsigned char *dst, int space, + FAR unsigned char **dnptrs, FAR unsigned char **lastdnptr) +{ + int i; + int j; + int n; + int m = 0; + int offset = 0; + int bestlen = 0; + int bestoff = 0; + unsigned char lens[127]; + FAR unsigned char **p = dnptrs; + FAR const char *end; + size_t l = strnlen(src, 255); + + if (l > 0 && src[l - 1] == '.') + { + l--; + } + + if (l > 253 || space <= 0) + { + return -1; + } + + if (l == 0) + { + *dst = 0; + return 1; + } + + end = src + l; + n = getlens(lens, src, l); + if (n == 0) + { + return -1; + } + + if (dnptrs != NULL && *dnptrs != NULL) + { + for (p = dnptrs + 1 ; *p != NULL; p++) + { + m = match(&offset, *dnptrs, *p, end, lens, n); + if (m > bestlen) + { + bestlen = m; + bestoff = offset; + if (m == l) + { + break; + } + } + } + } + + /* encode unmatched part */ + + if (space < l - bestlen + 2 + (bestlen - 1 < l - 1)) + { + return -1; + } + + memcpy(dst + 1, src, l - bestlen); + for (i = j = 0; i < l - bestlen; i += lens[j++] + 1) + { + dst[i] = lens[j]; + } + + /* add tail */ + + if (bestlen > 0) + { + dst[i++] = 0xc0 | bestoff >> 8; + dst[i++] = bestoff; + } + else + { + dst[i++] = 0; + } + + /* save dst pointer */ + + if (i > 2 && lastdnptr != NULL && dnptrs != NULL && *dnptrs != NULL) + { + while (*p != NULL) + { + p++; + } + + if (p + 1 < lastdnptr) + { + *p++ = dst; + *p = 0; + } + } + + return i; +} + +int dn_expand(FAR const unsigned char *base, FAR const unsigned char *end, + FAR const unsigned char *src, FAR char *dest, int space) +{ + FAR const unsigned char *p = src; + FAR char *dend; + FAR char *dbegin = dest; + int len = -1; + int i; + int j; + + if (p == end || space <= 0) + { + return -1; + } + + dend = dest + (space > 254 ? 254 : space); + + /* detect reference loop using an iteration counter */ + + for (i = 0; i < end - base; i += 2) + { + /* loop invariants: p<end, dest<dend */ + + if ((*p & 0xc0) != 0) + { + if (p + 1 == end) + { + return -1; + } + + j = ((p[0] & 0x3f) << 8) | p[1]; + if (len < 0) + { + len = p + 2 - src; + } + + if (j >= end - base) + { + return -1; + } + + p = base + j; + } + else if (*p) + { + if (dest != dbegin) + { + *dest++ = '.'; + } + + j = *p++; + if (j >= end - p || j >= dend - dest) + { + return -1; + } + + while (j--) + { + *dest++ = *p++; + } + } + else + { + *dest = 0; + if (len < 0) + { + len = p + 1 - src; + } + + return len; + } + } + + return -1; +}