asn1-parser: Fix CHOICE parsing
Fixes: CVE-2017-9023
This commit is contained in:
@@ -1,8 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2006 Martin Will
|
* Copyright (C) 2006 Martin Will
|
||||||
* Copyright (C) 2000-2008 Andreas Steffen
|
* Copyright (C) 2000-2017 Andreas Steffen
|
||||||
*
|
* HSR Hochschule fuer Technik Rapperswil
|
||||||
* Hochschule fuer Technik Rapperswil
|
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by the
|
* under the terms of the GNU General Public License as published by the
|
||||||
@@ -76,12 +75,18 @@ struct private_asn1_parser_t {
|
|||||||
* Current parsing pointer for each level
|
* Current parsing pointer for each level
|
||||||
*/
|
*/
|
||||||
chunk_t blobs[ASN1_MAX_LEVEL + 2];
|
chunk_t blobs[ASN1_MAX_LEVEL + 2];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parsing a CHOICE on the current level ?
|
||||||
|
*/
|
||||||
|
bool choice[ASN1_MAX_LEVEL + 2];
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
METHOD(asn1_parser_t, iterate, bool,
|
METHOD(asn1_parser_t, iterate, bool,
|
||||||
private_asn1_parser_t *this, int *objectID, chunk_t *object)
|
private_asn1_parser_t *this, int *objectID, chunk_t *object)
|
||||||
{
|
{
|
||||||
chunk_t *blob, *blob1;
|
chunk_t *blob, *blob1, blob_ori;
|
||||||
u_char *start_ptr;
|
u_char *start_ptr;
|
||||||
u_int level;
|
u_int level;
|
||||||
asn1Object_t obj;
|
asn1Object_t obj;
|
||||||
@@ -97,7 +102,7 @@ METHOD(asn1_parser_t, iterate, bool,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (obj.flags & ASN1_END) /* end of loop or option found */
|
if (obj.flags & ASN1_END) /* end of loop or choice or option found */
|
||||||
{
|
{
|
||||||
if (this->loopAddr[obj.level] && this->blobs[obj.level+1].len > 0)
|
if (this->loopAddr[obj.level] && this->blobs[obj.level+1].len > 0)
|
||||||
{
|
{
|
||||||
@@ -106,13 +111,42 @@ METHOD(asn1_parser_t, iterate, bool,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this->loopAddr[obj.level] = 0; /* exit loop or option*/
|
this->loopAddr[obj.level] = 0; /* exit loop */
|
||||||
|
|
||||||
|
if (obj.flags & ASN1_CHOICE) /* end of choices */
|
||||||
|
{
|
||||||
|
if (this->choice[obj.level+1])
|
||||||
|
{
|
||||||
|
DBG1(DBG_ASN, "L%d - %s: incorrect choice encoding",
|
||||||
|
this->level0 + obj.level, obj.name);
|
||||||
|
this->success = FALSE;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obj.flags & ASN1_CH) /* end of choice */
|
||||||
|
{
|
||||||
|
/* parsed a valid choice */
|
||||||
|
this->choice[obj.level] = FALSE;
|
||||||
|
|
||||||
|
/* advance to end of choices */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
this->line++;
|
||||||
|
}
|
||||||
|
while (!((this->objects[this->line].flags & ASN1_END) &&
|
||||||
|
(this->objects[this->line].flags & ASN1_CHOICE) &&
|
||||||
|
(this->objects[this->line].level == obj.level-1)));
|
||||||
|
this->line--;
|
||||||
|
}
|
||||||
|
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
level = this->level0 + obj.level;
|
level = this->level0 + obj.level;
|
||||||
blob = this->blobs + obj.level;
|
blob = this->blobs + obj.level;
|
||||||
|
blob_ori = *blob;
|
||||||
blob1 = blob + 1;
|
blob1 = blob + 1;
|
||||||
start_ptr = blob->ptr;
|
start_ptr = blob->ptr;
|
||||||
|
|
||||||
@@ -129,7 +163,6 @@ METHOD(asn1_parser_t, iterate, bool,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* handle ASN.1 options */
|
/* handle ASN.1 options */
|
||||||
|
|
||||||
if ((obj.flags & ASN1_OPT)
|
if ((obj.flags & ASN1_OPT)
|
||||||
&& (blob->len == 0 || *start_ptr != obj.type))
|
&& (blob->len == 0 || *start_ptr != obj.type))
|
||||||
{
|
{
|
||||||
@@ -144,7 +177,6 @@ METHOD(asn1_parser_t, iterate, bool,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* an ASN.1 object must possess at least a tag and length field */
|
/* an ASN.1 object must possess at least a tag and length field */
|
||||||
|
|
||||||
if (blob->len < 2)
|
if (blob->len < 2)
|
||||||
{
|
{
|
||||||
DBG1(DBG_ASN, "L%d - %s: ASN.1 object smaller than 2 octets",
|
DBG1(DBG_ASN, "L%d - %s: ASN.1 object smaller than 2 octets",
|
||||||
@@ -167,8 +199,16 @@ METHOD(asn1_parser_t, iterate, bool,
|
|||||||
blob->ptr += blob1->len;
|
blob->ptr += blob1->len;
|
||||||
blob->len -= blob1->len;
|
blob->len -= blob1->len;
|
||||||
|
|
||||||
/* return raw ASN.1 object without prior type checking */
|
/* handle ASN.1 choice without explicit context encoding */
|
||||||
|
if ((obj.flags & ASN1_CHOICE) && obj.type == ASN1_EOC)
|
||||||
|
{
|
||||||
|
DBG2(DBG_ASN, "L%d - %s:", level, obj.name);
|
||||||
|
this->choice[obj.level+1] = TRUE;
|
||||||
|
*blob1 = blob_ori;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return raw ASN.1 object without prior type checking */
|
||||||
if (obj.flags & ASN1_RAW)
|
if (obj.flags & ASN1_RAW)
|
||||||
{
|
{
|
||||||
DBG2(DBG_ASN, "L%d - %s:", level, obj.name);
|
DBG2(DBG_ASN, "L%d - %s:", level, obj.name);
|
||||||
@@ -209,6 +249,18 @@ METHOD(asn1_parser_t, iterate, bool,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* In case of a "CHOICE" start to scan for exactly one valid choice */
|
||||||
|
if (obj.flags & ASN1_CHOICE)
|
||||||
|
{
|
||||||
|
if (blob1->len == 0)
|
||||||
|
{
|
||||||
|
DBG1(DBG_ASN, "L%d - %s: contains no choice", level, obj.name);
|
||||||
|
this->success = FALSE;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
this->choice[obj.level+1] = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
if (obj.flags & ASN1_OBJ)
|
if (obj.flags & ASN1_OBJ)
|
||||||
{
|
{
|
||||||
object->ptr = start_ptr;
|
object->ptr = start_ptr;
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2006 Martin Will
|
* Copyright (C) 2006 Martin Will
|
||||||
* Copyright (C) 2000-2008 Andreas Steffen
|
* Copyright (C) 2000-2017 Andreas Steffen
|
||||||
*
|
* HSR Hochschule fuer Technik Rapperswil
|
||||||
* Hochschule fuer Technik Rapperswil
|
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by the
|
* under the terms of the GNU General Public License as published by the
|
||||||
@@ -32,15 +31,17 @@
|
|||||||
/**
|
/**
|
||||||
* Definition of ASN.1 flags
|
* Definition of ASN.1 flags
|
||||||
*/
|
*/
|
||||||
#define ASN1_NONE 0x00
|
#define ASN1_NONE 0x0000
|
||||||
#define ASN1_DEF 0x01
|
#define ASN1_DEF 0x0001
|
||||||
#define ASN1_OPT 0x02
|
#define ASN1_OPT 0x0002
|
||||||
#define ASN1_LOOP 0x04
|
#define ASN1_LOOP 0x0004
|
||||||
#define ASN1_END 0x08
|
#define ASN1_CHOICE 0x0008
|
||||||
#define ASN1_OBJ 0x10
|
#define ASN1_CH 0x0010
|
||||||
#define ASN1_BODY 0x20
|
#define ASN1_END 0x0020
|
||||||
#define ASN1_RAW 0x40
|
#define ASN1_OBJ 0x0040
|
||||||
#define ASN1_EXIT 0x80
|
#define ASN1_BODY 0x0080
|
||||||
|
#define ASN1_RAW 0x0100
|
||||||
|
#define ASN1_EXIT 0x0200
|
||||||
|
|
||||||
typedef struct asn1Object_t asn1Object_t;
|
typedef struct asn1Object_t asn1Object_t;
|
||||||
|
|
||||||
@@ -51,7 +52,7 @@ struct asn1Object_t{
|
|||||||
u_int level;
|
u_int level;
|
||||||
const u_char *name;
|
const u_char *name;
|
||||||
asn1_t type;
|
asn1_t type;
|
||||||
u_char flags;
|
uint16_t flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct asn1_parser_t asn1_parser_t;
|
typedef struct asn1_parser_t asn1_parser_t;
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
* Copyright (C) 2000 Andreas Hess, Patric Lichtsteiner, Roger Wegmann
|
* Copyright (C) 2000 Andreas Hess, Patric Lichtsteiner, Roger Wegmann
|
||||||
* Copyright (C) 2001 Marco Bertossa, Andreas Schleiss
|
* Copyright (C) 2001 Marco Bertossa, Andreas Schleiss
|
||||||
* Copyright (C) 2002 Mario Strasser
|
* Copyright (C) 2002 Mario Strasser
|
||||||
* Copyright (C) 2000-2006 Andreas Steffen
|
* Copyright (C) 2000-2017 Andreas Steffen
|
||||||
* Copyright (C) 2006-2009 Martin Willi
|
* Copyright (C) 2006-2009 Martin Willi
|
||||||
* Copyright (C) 2008 Tobias Brunner
|
* Copyright (C) 2008 Tobias Brunner
|
||||||
* Hochschule fuer Technik Rapperswil
|
* HSR Hochschule fuer Technik Rapperswil
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify it
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
* under the terms of the GNU General Public License as published by the
|
* under the terms of the GNU General Public License as published by the
|
||||||
@@ -812,20 +812,20 @@ static bool parse_extendedKeyUsage(chunk_t blob, int level0,
|
|||||||
* ASN.1 definition of crlDistributionPoints
|
* ASN.1 definition of crlDistributionPoints
|
||||||
*/
|
*/
|
||||||
static const asn1Object_t crlDistributionPointsObjects[] = {
|
static const asn1Object_t crlDistributionPointsObjects[] = {
|
||||||
{ 0, "crlDistributionPoints", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
|
{ 0, "crlDistributionPoints", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
|
||||||
{ 1, "DistributionPoint", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */
|
{ 1, "DistributionPoint", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */
|
||||||
{ 2, "distributionPoint", ASN1_CONTEXT_C_0, ASN1_OPT|ASN1_LOOP }, /* 2 */
|
{ 2, "distributionPoint", ASN1_CONTEXT_C_0, ASN1_OPT|ASN1_CHOICE }, /* 2 */
|
||||||
{ 3, "fullName", ASN1_CONTEXT_C_0, ASN1_OPT|ASN1_OBJ }, /* 3 */
|
{ 3, "fullName", ASN1_CONTEXT_C_0, ASN1_OPT|ASN1_OBJ }, /* 3 */
|
||||||
{ 3, "end choice", ASN1_EOC, ASN1_END }, /* 4 */
|
{ 3, "end choice", ASN1_EOC, ASN1_END|ASN1_CH }, /* 4 */
|
||||||
{ 3, "nameRelToCRLIssuer",ASN1_CONTEXT_C_1, ASN1_OPT|ASN1_BODY }, /* 5 */
|
{ 3, "nameRelToCRLIssuer",ASN1_CONTEXT_C_1, ASN1_OPT|ASN1_BODY }, /* 5 */
|
||||||
{ 3, "end choice", ASN1_EOC, ASN1_END }, /* 6 */
|
{ 3, "end choice", ASN1_EOC, ASN1_END|ASN1_CH }, /* 6 */
|
||||||
{ 2, "end opt", ASN1_EOC, ASN1_END }, /* 7 */
|
{ 2, "end opt/choices", ASN1_EOC, ASN1_END|ASN1_CHOICE }, /* 7 */
|
||||||
{ 2, "reasons", ASN1_CONTEXT_C_1, ASN1_OPT|ASN1_BODY }, /* 8 */
|
{ 2, "reasons", ASN1_CONTEXT_C_1, ASN1_OPT|ASN1_BODY }, /* 8 */
|
||||||
{ 2, "end opt", ASN1_EOC, ASN1_END }, /* 9 */
|
{ 2, "end opt", ASN1_EOC, ASN1_END }, /* 9 */
|
||||||
{ 2, "crlIssuer", ASN1_CONTEXT_C_2, ASN1_OPT|ASN1_OBJ }, /* 10 */
|
{ 2, "crlIssuer", ASN1_CONTEXT_C_2, ASN1_OPT|ASN1_OBJ }, /* 10 */
|
||||||
{ 2, "end opt", ASN1_EOC, ASN1_END }, /* 11 */
|
{ 2, "end opt", ASN1_EOC, ASN1_END }, /* 11 */
|
||||||
{ 0, "end loop", ASN1_EOC, ASN1_END }, /* 12 */
|
{ 0, "end loop", ASN1_EOC, ASN1_END }, /* 12 */
|
||||||
{ 0, "exit", ASN1_EOC, ASN1_EXIT }
|
{ 0, "exit", ASN1_EOC, ASN1_EXIT }
|
||||||
};
|
};
|
||||||
#define CRL_DIST_POINTS 1
|
#define CRL_DIST_POINTS 1
|
||||||
#define CRL_DIST_POINTS_FULLNAME 3
|
#define CRL_DIST_POINTS_FULLNAME 3
|
||||||
@@ -997,25 +997,27 @@ end:
|
|||||||
* ASN.1 definition of a certificatePolicies extension
|
* ASN.1 definition of a certificatePolicies extension
|
||||||
*/
|
*/
|
||||||
static const asn1Object_t certificatePoliciesObject[] = {
|
static const asn1Object_t certificatePoliciesObject[] = {
|
||||||
{ 0, "certificatePolicies", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
|
{ 0, "certificatePolicies", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
|
||||||
{ 1, "policyInformation", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */
|
{ 1, "policyInformation", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */
|
||||||
{ 2, "policyId", ASN1_OID, ASN1_BODY }, /* 2 */
|
{ 2, "policyId", ASN1_OID, ASN1_BODY }, /* 2 */
|
||||||
{ 2, "qualifiers", ASN1_SEQUENCE, ASN1_OPT|ASN1_LOOP }, /* 3 */
|
{ 2, "qualifiers", ASN1_SEQUENCE, ASN1_OPT|ASN1_LOOP }, /* 3 */
|
||||||
{ 3, "qualifierInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 4 */
|
{ 3, "qualifierInfo", ASN1_SEQUENCE, ASN1_NONE }, /* 4 */
|
||||||
{ 4, "qualifierId", ASN1_OID, ASN1_BODY }, /* 5 */
|
{ 4, "qualifierId", ASN1_OID, ASN1_BODY }, /* 5 */
|
||||||
{ 4, "cPSuri", ASN1_IA5STRING, ASN1_OPT|ASN1_BODY }, /* 6 */
|
{ 4, "qualifier", ASN1_EOC, ASN1_CHOICE }, /* 6 */
|
||||||
{ 4, "end choice", ASN1_EOC, ASN1_END }, /* 7 */
|
{ 5, "cPSuri", ASN1_IA5STRING, ASN1_OPT|ASN1_BODY }, /* 7 */
|
||||||
{ 4, "userNotice", ASN1_SEQUENCE, ASN1_OPT|ASN1_BODY }, /* 8 */
|
{ 5, "end choice", ASN1_EOC, ASN1_END|ASN1_CH }, /* 8 */
|
||||||
{ 5, "explicitText", ASN1_EOC, ASN1_RAW }, /* 9 */
|
{ 5, "userNotice", ASN1_SEQUENCE, ASN1_OPT|ASN1_BODY }, /* 9 */
|
||||||
{ 4, "end choice", ASN1_EOC, ASN1_END }, /* 10 */
|
{ 6, "explicitText", ASN1_EOC, ASN1_RAW }, /* 10 */
|
||||||
{ 2, "end opt/loop", ASN1_EOC, ASN1_END }, /* 12 */
|
{ 5, "end choice", ASN1_EOC, ASN1_END|ASN1_CH }, /* 11 */
|
||||||
{ 0, "end loop", ASN1_EOC, ASN1_END }, /* 13 */
|
{ 4, "end choices", ASN1_EOC, ASN1_END|ASN1_CHOICE }, /* 12 */
|
||||||
{ 0, "exit", ASN1_EOC, ASN1_EXIT }
|
{ 2, "end opt/loop", ASN1_EOC, ASN1_END }, /* 13 */
|
||||||
|
{ 0, "end loop", ASN1_EOC, ASN1_END }, /* 14 */
|
||||||
|
{ 0, "exit", ASN1_EOC, ASN1_EXIT }
|
||||||
};
|
};
|
||||||
#define CERT_POLICY_ID 2
|
#define CERT_POLICY_ID 2
|
||||||
#define CERT_POLICY_QUALIFIER_ID 5
|
#define CERT_POLICY_QUALIFIER_ID 5
|
||||||
#define CERT_POLICY_CPS_URI 6
|
#define CERT_POLICY_CPS_URI 7
|
||||||
#define CERT_POLICY_EXPLICIT_TEXT 9
|
#define CERT_POLICY_EXPLICIT_TEXT 10
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse certificatePolicies
|
* Parse certificatePolicies
|
||||||
@@ -1180,27 +1182,31 @@ static bool parse_policyConstraints(chunk_t blob, int level0,
|
|||||||
* ASN.1 definition of ipAddrBlocks according to RFC 3779
|
* ASN.1 definition of ipAddrBlocks according to RFC 3779
|
||||||
*/
|
*/
|
||||||
static const asn1Object_t ipAddrBlocksObjects[] = {
|
static const asn1Object_t ipAddrBlocksObjects[] = {
|
||||||
{ 0, "ipAddrBlocks", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
|
{ 0, "ipAddrBlocks", ASN1_SEQUENCE, ASN1_LOOP }, /* 0 */
|
||||||
{ 1, "ipAddressFamily", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */
|
{ 1, "ipAddressFamily", ASN1_SEQUENCE, ASN1_NONE }, /* 1 */
|
||||||
{ 2, "addressFamily", ASN1_OCTET_STRING, ASN1_BODY }, /* 2 */
|
{ 2, "addressFamily", ASN1_OCTET_STRING, ASN1_BODY }, /* 2 */
|
||||||
{ 2, "inherit", ASN1_NULL, ASN1_OPT|ASN1_NONE }, /* 3 */
|
{ 2, "ipAddressChoice", ASN1_EOC, ASN1_CHOICE }, /* 3 */
|
||||||
{ 2, "end choice", ASN1_EOC, ASN1_END }, /* 4 */
|
{ 3, "inherit", ASN1_NULL, ASN1_OPT }, /* 4 */
|
||||||
{ 2, "addressesOrRanges", ASN1_SEQUENCE, ASN1_OPT|ASN1_LOOP }, /* 5 */
|
{ 3, "end choice", ASN1_EOC, ASN1_END|ASN1_CH }, /* 5 */
|
||||||
{ 3, "addressPrefix", ASN1_BIT_STRING, ASN1_OPT|ASN1_BODY }, /* 6 */
|
{ 3, "addressesOrRanges", ASN1_SEQUENCE, ASN1_OPT|ASN1_LOOP }, /* 6 */
|
||||||
{ 3, "end choice", ASN1_EOC, ASN1_END }, /* 7 */
|
{ 4, "addressOrRange", ASN1_EOC, ASN1_CHOICE }, /* 7 */
|
||||||
{ 3, "addressRange", ASN1_SEQUENCE, ASN1_OPT|ASN1_NONE }, /* 8 */
|
{ 5, "addressPrefix", ASN1_BIT_STRING, ASN1_OPT|ASN1_BODY }, /* 8 */
|
||||||
{ 4, "min", ASN1_BIT_STRING, ASN1_BODY }, /* 9 */
|
{ 5, "end choice", ASN1_EOC, ASN1_END|ASN1_CH }, /* 9 */
|
||||||
{ 4, "max", ASN1_BIT_STRING, ASN1_BODY }, /* 10 */
|
{ 5, "addressRange", ASN1_SEQUENCE, ASN1_OPT }, /* 10 */
|
||||||
{ 3, "end choice", ASN1_EOC, ASN1_END }, /* 11 */
|
{ 6, "min", ASN1_BIT_STRING, ASN1_BODY }, /* 11 */
|
||||||
{ 2, "end opt/loop", ASN1_EOC, ASN1_END }, /* 12 */
|
{ 6, "max", ASN1_BIT_STRING, ASN1_BODY }, /* 12 */
|
||||||
{ 0, "end loop", ASN1_EOC, ASN1_END }, /* 13 */
|
{ 5, "end choice", ASN1_EOC, ASN1_END|ASN1_CH }, /* 13 */
|
||||||
{ 0, "exit", ASN1_EOC, ASN1_EXIT }
|
{ 4, "end choices", ASN1_EOC, ASN1_END|ASN1_CHOICE }, /* 14 */
|
||||||
|
{ 3, "end loop/choice", ASN1_EOC, ASN1_END|ASN1_CH }, /* 15 */
|
||||||
|
{ 2, "end choices", ASN1_EOC, ASN1_END|ASN1_CHOICE }, /* 16 */
|
||||||
|
{ 0, "end loop", ASN1_EOC, ASN1_END }, /* 17 */
|
||||||
|
{ 0, "exit", ASN1_EOC, ASN1_EXIT }
|
||||||
};
|
};
|
||||||
#define IP_ADDR_BLOCKS_FAMILY 2
|
#define IP_ADDR_BLOCKS_FAMILY 2
|
||||||
#define IP_ADDR_BLOCKS_INHERIT 3
|
#define IP_ADDR_BLOCKS_INHERIT 4
|
||||||
#define IP_ADDR_BLOCKS_PREFIX 6
|
#define IP_ADDR_BLOCKS_PREFIX 8
|
||||||
#define IP_ADDR_BLOCKS_MIN 9
|
#define IP_ADDR_BLOCKS_MIN 11
|
||||||
#define IP_ADDR_BLOCKS_MAX 10
|
#define IP_ADDR_BLOCKS_MAX 12
|
||||||
|
|
||||||
static bool check_address_object(ts_type_t ts_type, chunk_t object)
|
static bool check_address_object(ts_type_t ts_type, chunk_t object)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user