summaryrefslogtreecommitdiff
path: root/src/libstddjb/ip6_scan.c
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2023-11-17 19:50:51 +0000
committerLaurent Bercot <ska@appnovation.com>2023-11-17 19:50:51 +0000
commitd1fe8e1bc2f1dc887a9bedca58d5882dff3477c9 (patch)
treef1b06914ddfacc8d731daec2fddc5f0e1091ae40 /src/libstddjb/ip6_scan.c
parent2ea36ebf726bb3a29ff8c6b12a6ff3df9020859f (diff)
downloadskalibs-d1fe8e1bc2f1dc887a9bedca58d5882dff3477c9.tar.xz
Prepare for 2.14.0.1. Better ip6_scan().
Signed-off-by: Laurent Bercot <ska@appnovation.com>
Diffstat (limited to 'src/libstddjb/ip6_scan.c')
-rw-r--r--src/libstddjb/ip6_scan.c96
1 files changed, 74 insertions, 22 deletions
diff --git a/src/libstddjb/ip6_scan.c b/src/libstddjb/ip6_scan.c
index b0e5b56..d2cdad6 100644
--- a/src/libstddjb/ip6_scan.c
+++ b/src/libstddjb/ip6_scan.c
@@ -1,37 +1,89 @@
/* ISC license. */
-#include <errno.h>
+#include <stdint.h>
#include <skalibs/uint16.h>
#include <skalibs/fmtscan.h>
+
+/* IPv6 scanner
+
+class | 0 1 2 3
+st\ev | other hex : .
+
+START | m
+00 | X LIMB COLON1 X
+
+COLON1 | p
+01 | X X NEW X
+
+NEW | m
+02 | END LIMB X X
+
+LIMB | h h
+03 | END LIMB COLON V4
+
+COLON | m p
+04 | X LIMB NEW X
+
+
+END = 05
+V4 = 06
+X = 07
+
+0x10 m mark
+0x20 p set doublecolon pos
+0x40 h scan hex, next limb
+
+*/
+
size_t ip6_scan (char const *s, char *ip6)
{
- static unsigned char const class[256] = "2222222222222222222222222222222222222222222222220000000000122222200000022222222222222222222222222000000222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222" ;
- static unsigned char const table[5][3] = { "\024#\005", "\024\"\005", "\024\005\006", "\005\002\005", "\024\t\016" } ;
- uint16_t tmp[8] = { 0, 0, 0, 0, 0, 0, 0, 0 } ;
- size_t i = 0 ;
- unsigned int pos = 8, j = 0, state = 0 ;
+ static unsigned char const class[256] = "0000000000000000000000000000000000000000000000301111111111200000011111100000000000000000000000000111111000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" ;
+ static uint8_t const table[5][4] =
+ {
+ { 0x07, 0x13, 0x01, 0x07 },
+ { 0x07, 0x07, 0x22, 0x07 },
+ { 0x05, 0x13, 0x07, 0x07 },
+ { 0x45, 0x03, 0x44, 0x06 },
+ { 0x07, 0x13, 0x22, 0x07 }
+ } ;
+ size_t i = 0, mark = 0 ;
+ uint16_t limb[8] = { 0, 0, 0, 0, 0, 0, 0, 0 } ;
+ uint8_t pos = 8, j = 0, state = 0 ;
- while (state < 5)
+ for (; state < 0x05 ; i++)
{
- unsigned char c = table[state][class[(unsigned char)s[i]] - '0'] ;
- state = c & 7 ;
- if (c & 0x20) { if (pos < 8) state = 5 ; else pos = j ; }
- if (c & 0x10)
+ uint8_t c = table[state][class[(unsigned char)s[i]] - '0'] ;
+ state = c & 0x07 ;
+ if (c & 0x10) mark = i ;
+ if (c & 0x20) { if (pos < 8) state = 0x07 ; else pos = j ; }
+ if (c & 0x40)
+ if (j >= 8 || uint16_xscan(s + mark, limb + j++) != i - mark) state = 0x07 ;
+ }
+
+ switch (state)
+ {
+ case 0x05:
+ if (pos == 8 && j < 8 || (pos < 8 && j > 6)) return 0 ;
+ i-- ;
+ break ;
+ case 0x06:
{
- if (tmp[j] & 0xf000) state = 5 ;
- else tmp[j] = (tmp[j] << 4) + fmtscan_num(s[i], 16) ;
+ uint32_t ip4 ;
+ if (pos == 8 && j != 6 || (pos < 8 && j > 4)) return 0 ;
+ i = ip4_scanu32(s + mark, &ip4) ;
+ if (!i) return 0 ;
+ limb[j++] = ip4 >> 16 ;
+ limb[j++] = ip4 & 0xffff ;
+ i += mark ;
+ break ;
}
- if (c & 0x08) if ((++j > 7) && (state < 5)) state = 5 ;
- i++ ;
+ default : return 0 ;
}
- if (((pos < 8) && (j > 6)) || ((pos == 8) && (j < 8))) state = 5 ;
- if (state == 5) return (errno = EINVAL, 0) ;
- for (state = j ; state > pos ; state--) tmp[state - j + 7] = tmp[state - 1] ;
- for (; state < pos + 8 - j ; state++) tmp[state] = 0 ;
-
- for (j = 0 ; j < 8 ; j++) uint16_pack_big(ip6 + (j<<1), tmp[j]) ;
- return i - 1 ;
+ for (state = j ; state > pos ; state--) limb[state - j + 7] = limb[state - 1] ;
+ for (; state < pos + 8 - j ; state++) limb[state] = 0 ;
+ for (j = 0 ; j < 8 ; j++) uint16_pack_big(ip6 + (j<<1), limb[j]) ;
+ return i ;
}