Skip to content
This repository was archived by the owner on Nov 6, 2022. It is now read-only.

Commit 7d75dd7

Browse files
tatsuhiro-tindutny
authored andcommitted
src: support IPv6 Zone ID as per RFC 6874
IPv6 scoped address contains Zone ID, which is appended to IPv6 address after '%' separator. RFC 6874 says that Zone ID after '%' must consist of 1*(unreserved or pct-encoded). This commit adds this IPv6 Zone ID support. PR-URL: #253 Reviewed-By: Fedor Indutny <fedor@indutny.com>
1 parent ab0b162 commit 7d75dd7

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

http_parser.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,8 @@ enum http_host_state
400400
, s_http_host
401401
, s_http_host_v6
402402
, s_http_host_v6_end
403+
, s_http_host_v6_zone_start
404+
, s_http_host_v6_zone
403405
, s_http_host_port_start
404406
, s_http_host_port
405407
};
@@ -2211,6 +2213,23 @@ http_parse_host_char(enum http_host_state s, const char ch) {
22112213
return s_http_host_v6;
22122214
}
22132215

2216+
if (s == s_http_host_v6 && ch == '%') {
2217+
return s_http_host_v6_zone_start;
2218+
}
2219+
break;
2220+
2221+
case s_http_host_v6_zone:
2222+
if (ch == ']') {
2223+
return s_http_host_v6_end;
2224+
}
2225+
2226+
/* FALLTHROUGH */
2227+
case s_http_host_v6_zone_start:
2228+
/* RFC 6874 Zone ID consists of 1*( unreserved / pct-encoded) */
2229+
if (IS_ALPHANUM(ch) || ch == '%' || ch == '.' || ch == '-' || ch == '_' ||
2230+
ch == '~') {
2231+
return s_http_host_v6_zone;
2232+
}
22142233
break;
22152234

22162235
case s_http_host_port:
@@ -2261,6 +2280,11 @@ http_parse_host(const char * buf, struct http_parser_url *u, int found_at) {
22612280
u->field_data[UF_HOST].len++;
22622281
break;
22632282

2283+
case s_http_host_v6_zone_start:
2284+
case s_http_host_v6_zone:
2285+
u->field_data[UF_HOST].len++;
2286+
break;
2287+
22642288
case s_http_host_port:
22652289
if (s != s_http_host_port) {
22662290
u->field_data[UF_PORT].off = p - buf;
@@ -2290,6 +2314,8 @@ http_parse_host(const char * buf, struct http_parser_url *u, int found_at) {
22902314
case s_http_host_start:
22912315
case s_http_host_v6_start:
22922316
case s_http_host_v6:
2317+
case s_http_host_v6_zone_start:
2318+
case s_http_host_v6_zone:
22932319
case s_http_host_port_start:
22942320
case s_http_userinfo:
22952321
case s_http_userinfo_start:

test.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2918,6 +2918,59 @@ const struct url_test url_tests[] =
29182918
,.rv=1 /* s_dead */
29192919
}
29202920

2921+
, {.name="ipv6 address with Zone ID"
2922+
,.url="http://[fe80::a%25eth0]/"
2923+
,.is_connect=0
2924+
,.u=
2925+
{.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH)
2926+
,.port=0
2927+
,.field_data=
2928+
{{ 0, 4 } /* UF_SCHEMA */
2929+
,{ 8, 14 } /* UF_HOST */
2930+
,{ 0, 0 } /* UF_PORT */
2931+
,{ 23, 1 } /* UF_PATH */
2932+
,{ 0, 0 } /* UF_QUERY */
2933+
,{ 0, 0 } /* UF_FRAGMENT */
2934+
,{ 0, 0 } /* UF_USERINFO */
2935+
}
2936+
}
2937+
,.rv=0
2938+
}
2939+
2940+
, {.name="ipv6 address with Zone ID, but '%' is not percent-encoded"
2941+
,.url="http://[fe80::a%eth0]/"
2942+
,.is_connect=0
2943+
,.u=
2944+
{.field_set= (1<<UF_SCHEMA) | (1<<UF_HOST) | (1<<UF_PATH)
2945+
,.port=0
2946+
,.field_data=
2947+
{{ 0, 4 } /* UF_SCHEMA */
2948+
,{ 8, 12 } /* UF_HOST */
2949+
,{ 0, 0 } /* UF_PORT */
2950+
,{ 21, 1 } /* UF_PATH */
2951+
,{ 0, 0 } /* UF_QUERY */
2952+
,{ 0, 0 } /* UF_FRAGMENT */
2953+
,{ 0, 0 } /* UF_USERINFO */
2954+
}
2955+
}
2956+
,.rv=0
2957+
}
2958+
2959+
, {.name="ipv6 address ending with '%'"
2960+
,.url="http://[fe80::a%]/"
2961+
,.rv=1 /* s_dead */
2962+
}
2963+
2964+
, {.name="ipv6 address with Zone ID including bad character"
2965+
,.url="http://[fe80::a%$HOME]/"
2966+
,.rv=1 /* s_dead */
2967+
}
2968+
2969+
, {.name="just ipv6 Zone ID"
2970+
,.url="http://[%eth0]/"
2971+
,.rv=1 /* s_dead */
2972+
}
2973+
29212974
#if HTTP_PARSER_STRICT
29222975

29232976
, {.name="tab in URL"

0 commit comments

Comments
 (0)