|
|
| version 1.18, 2023/09/26 20:49:06 | version 1.22, 2026/07/19 14:25:42 |
|---|---|
| Line 1 | Line 1 |
| /** @file | /** @file |
| Parser: @b inet parser class. | Parser: @b inet parser class. |
| Copyright (c) 2001-2023 Art. Lebedev Studio (http://www.artlebedev.com) | Copyright (c) 2001-2026 Art. Lebedev Studio (https://www.artlebedev.com) |
| Authors: Konstantin Morshnev <moko@design.ru>, Alexandr Petrosian <paf@design.ru> | Authors: Konstantin Morshnev <moko@design.ru>, Alexandr Petrosian <paf@design.ru> |
| */ | */ |
| Line 127 static void _ip2name(Request& r, MethodP | Line 127 static void _ip2name(Request& r, MethodP |
| } | } |
| } | } |
| // also used in curl.C, returns first address or fills the table if not null | |
| const char *pa_name2ip(const char *name, int family, Table *table, const char *exception_type){ | |
| struct addrinfo hints, *info; | |
| memset(&hints, 0, sizeof(hints)); | |
| hints.ai_family=family; | |
| hints.ai_socktype=SOCK_STREAM; | |
| int error=getaddrinfo(name, NULL, &hints, &info); | |
| if(error) | |
| throw Exception(exception_type, 0, "Can't resolve domain name '%s': %s", name, gai_strerror(error)); | |
| const char *result=0; | |
| char hbuf[INET6_ADDRSTRLEN]; | |
| for(struct addrinfo *cur=info; cur; cur=cur->ai_next) { | |
| if(error=getnameinfo(cur->ai_addr, cur->ai_addrlen, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST)) | |
| throw Exception(exception_type, 0, "Can't translate address: %s", gai_strerror(error)); | |
| if(table){ | |
| Table::element_type row(new ArrayString()); | |
| static const String sv4("4"), sv6("6"), sunknown("unknown"); | |
| *row+=new String(pa_strdup(hbuf), String::L_TAINTED); | |
| *row+=cur->ai_family == AF_INET ? &sv4 : cur->ai_family == AF_INET6 ? &sv6 : &sunknown; | |
| *table+=row; | |
| } else { | |
| result=pa_strdup(hbuf); | |
| break; | |
| } | |
| } | |
| freeaddrinfo(info); | |
| return result; | |
| } | |
| static void _name2ip(Request& r, MethodParams& params){ | static void _name2ip(Request& r, MethodParams& params){ |
| const String sname=params.as_string(0, PARAMETER_MUST_BE_STRING); | const String sname=params.as_string(0, PARAMETER_MUST_BE_STRING); |
| if(sname.is_empty()) | if(sname.is_empty()) |
| Line 134 static void _name2ip(Request& r, MethodP | Line 168 static void _name2ip(Request& r, MethodP |
| const char* name_cstr=pa_idna_encode(sname.cstr(), r.charsets.source()); | const char* name_cstr=pa_idna_encode(sname.cstr(), r.charsets.source()); |
| struct addrinfo hints, *info; | int family=AF_INET; |
| memset(&hints, 0, sizeof(hints)); | |
| hints.ai_family=AF_INET; | |
| hints.ai_socktype=SOCK_STREAM; | |
| Table *table=NULL; | Table *table=NULL; |
| if(params.count() == 2) | if(params.count() == 2) |
| if(HashStringValue* options=params.as_hash(1)){ | if(HashStringValue* options=params.as_hash(1)){ |
| int valid_options=0; | int valid_options=0; |
| if(Value* value=options->get("ipv")){ | if(Value* value=options->get("ipv")){ |
| hints.ai_family=ipv_format(r.process(*value).as_string()); | family=ipv_format(r.process(*value).as_string()); |
| valid_options++; | valid_options++; |
| } | } |
| if(Value* value=options->get("table")){ | if(Value* value=options->get("table")){ |
| Line 161 static void _name2ip(Request& r, MethodP | Line 191 static void _name2ip(Request& r, MethodP |
| throw Exception(PARSER_RUNTIME, 0, CALLED_WITH_INVALID_OPTION); | throw Exception(PARSER_RUNTIME, 0, CALLED_WITH_INVALID_OPTION); |
| } | } |
| int error=getaddrinfo(name_cstr, NULL, &hints, &info); | if(const char *ip=pa_name2ip(name_cstr, family, table, PARSER_RUNTIME)) |
| r.write(*new String(ip, String::L_TAINTED)); | |
| if(error) | |
| throw Exception(PARSER_RUNTIME, 0, "Can't resolve domain name '%s': %s", name_cstr, gai_strerror(error)); | |
| char hbuf[INET6_ADDRSTRLEN]; | |
| for(struct addrinfo *cur=info; cur; cur=cur->ai_next) { | |
| if(error=getnameinfo(cur->ai_addr, cur->ai_addrlen, hbuf, sizeof(hbuf), NULL, 0, NI_NUMERICHOST)) | |
| throw Exception(PARSER_RUNTIME, 0, "Can't translate address: %s", gai_strerror(error)); | |
| String *saddr=new String(pa_strdup(hbuf), String::L_TAINTED); | |
| if(table){ | |
| Table::element_type row(new ArrayString()); | |
| static const String sv4("4"), sv6("6"), sunknown("unknown"); | |
| *row+=saddr; | |
| *row+=cur->ai_family == AF_INET ? &sv4 : cur->ai_family == AF_INET6 ? &sv6 : &sunknown; | |
| *table+=row; | |
| } else { | |
| r.write(*saddr); | |
| break; | |
| } | |
| } | |
| if(table) | if(table) |
| r.write(*new VTable(table)); | r.write(*new VTable(table)); |
| freeaddrinfo(info); | |
| } | } |
| static void _hostname(Request& r, MethodParams& params){ | static void _hostname(Request& r, MethodParams&){ |
| char buf[MAX_STRING]; | char buf[MAX_STRING]; |
| if(gethostname(buf, MAX_STRING)) | if(gethostname(buf, MAX_STRING)) |