@@ -328,8 +328,7 @@ static int parse_address(const char *s, int *family, union in_addr_union *addres
328328 return 0 ;
329329}
330330
331- static int resolve_record (sd_bus * bus , const char * name ) {
332-
331+ static int resolve_record (sd_bus * bus , const char * name , uint16_t class , uint16_t type ) {
333332 _cleanup_ (sd_bus_message_unrefp ) sd_bus_message * req = NULL , * reply = NULL ;
334333 _cleanup_ (sd_bus_error_free ) sd_bus_error error = SD_BUS_ERROR_NULL ;
335334 char ifname [IF_NAMESIZE ] = "" ;
@@ -343,7 +342,7 @@ static int resolve_record(sd_bus *bus, const char *name) {
343342 if (arg_ifindex > 0 && !if_indextoname (arg_ifindex , ifname ))
344343 return log_error_errno (errno , "Failed to resolve interface name for index %i: %m" , arg_ifindex );
345344
346- log_debug ("Resolving %s %s %s (interface %s)." , name , dns_class_to_string (arg_class ), dns_type_to_string (arg_type ), isempty (ifname ) ? "*" : ifname );
345+ log_debug ("Resolving %s %s %s (interface %s)." , name , dns_class_to_string (class ), dns_type_to_string (type ), isempty (ifname ) ? "*" : ifname );
347346
348347 r = sd_bus_message_new_method_call (
349348 bus ,
@@ -355,7 +354,7 @@ static int resolve_record(sd_bus *bus, const char *name) {
355354 if (r < 0 )
356355 return bus_log_create_error (r );
357356
358- r = sd_bus_message_append (req , "isqqt" , arg_ifindex , name , arg_class , arg_type , arg_flags );
357+ r = sd_bus_message_append (req , "isqqt" , arg_ifindex , name , class , type , arg_flags );
359358 if (r < 0 )
360359 return bus_log_create_error (r );
361360
@@ -442,6 +441,127 @@ static int resolve_record(sd_bus *bus, const char *name) {
442441 return 0 ;
443442}
444443
444+ static int resolve_rfc4501 (sd_bus * bus , const char * name ) {
445+ uint16_t type = 0 , class = 0 ;
446+ const char * p , * q , * n ;
447+ int r ;
448+
449+ assert (bus );
450+ assert (name );
451+ assert (startswith (name , "dns:" ));
452+
453+ /* Parse RFC 4501 dns: URIs */
454+
455+ p = name + 4 ;
456+
457+ if (p [0 ] == '/' ) {
458+ const char * e ;
459+
460+ if (p [1 ] != '/' )
461+ goto invalid ;
462+
463+ e = strchr (p + 2 , '/' );
464+ if (!e )
465+ goto invalid ;
466+
467+ if (e != p + 2 )
468+ log_warning ("DNS authority specification not supported; ignoring specified authority." );
469+
470+ p = e + 1 ;
471+ }
472+
473+ q = strchr (p , '?' );
474+ if (q ) {
475+ n = strndupa (p , q - p );
476+ q ++ ;
477+
478+ for (;;) {
479+ const char * f ;
480+
481+ f = startswith_no_case (q , "class=" );
482+ if (f ) {
483+ _cleanup_free_ char * t = NULL ;
484+ const char * e ;
485+
486+ if (class != 0 ) {
487+ log_error ("DNS class specified twice." );
488+ return - EINVAL ;
489+ }
490+
491+ e = strchrnul (f , ';' );
492+ t = strndup (f , e - f );
493+ if (!t )
494+ return log_oom ();
495+
496+ r = dns_class_from_string (t );
497+ if (r < 0 ) {
498+ log_error ("Unknown DNS class %s." , t );
499+ return - EINVAL ;
500+ }
501+
502+ class = r ;
503+
504+ if (* e == ';' ) {
505+ q = e + 1 ;
506+ continue ;
507+ }
508+
509+ break ;
510+ }
511+
512+ f = startswith_no_case (q , "type=" );
513+ if (f ) {
514+ _cleanup_free_ char * t = NULL ;
515+ const char * e ;
516+
517+ if (type != 0 ) {
518+ log_error ("DNS type specified twice." );
519+ return - EINVAL ;
520+ }
521+
522+ e = strchrnul (f , ';' );
523+ t = strndup (f , e - f );
524+ if (!t )
525+ return log_oom ();
526+
527+ r = dns_type_from_string (t );
528+ if (r < 0 ) {
529+ log_error ("Unknown DNS type %s." , t );
530+ return - EINVAL ;
531+ }
532+
533+ type = r ;
534+
535+ if (* e == ';' ) {
536+ q = e + 1 ;
537+ continue ;
538+ }
539+
540+ break ;
541+ }
542+
543+ goto invalid ;
544+ }
545+ } else
546+ n = p ;
547+
548+ if (type == 0 )
549+ type = arg_type ;
550+ if (type == 0 )
551+ type = DNS_TYPE_A ;
552+
553+ if (class == 0 )
554+ class = arg_class ;
555+ if (class == 0 )
556+ class = DNS_CLASS_IN ;
557+
558+ return resolve_record (bus , n , class , type );
559+
560+ invalid :
561+ log_error ("Invalid DNS URI: %s" , name );
562+ return - EINVAL ;
563+ }
564+
445565static int resolve_service (sd_bus * bus , const char * name , const char * type , const char * domain ) {
446566 const char * canonical_name , * canonical_type , * canonical_domain ;
447567 _cleanup_ (sd_bus_message_unrefp ) sd_bus_message * req = NULL , * reply = NULL ;
@@ -1009,6 +1129,9 @@ static int parse_argv(int argc, char *argv[]) {
10091129 if (arg_type != 0 && arg_class == 0 )
10101130 arg_class = DNS_CLASS_IN ;
10111131
1132+ if (arg_class != 0 && arg_type == 0 )
1133+ arg_type = DNS_TYPE_A ;
1134+
10121135 return 1 /* work to do */ ;
10131136}
10141137
@@ -1042,11 +1165,15 @@ int main(int argc, char **argv) {
10421165 int family , ifindex , k ;
10431166 union in_addr_union a ;
10441167
1045- k = parse_address (argv [optind ], & family , & a , & ifindex );
1046- if (k >= 0 )
1047- k = resolve_address (bus , family , & a , ifindex );
1048- else
1049- k = resolve_host (bus , argv [optind ]);
1168+ if (startswith (argv [optind ], "dns:" ))
1169+ k = resolve_rfc4501 (bus , argv [optind ]);
1170+ else {
1171+ k = parse_address (argv [optind ], & family , & a , & ifindex );
1172+ if (k >= 0 )
1173+ k = resolve_address (bus , family , & a , ifindex );
1174+ else
1175+ k = resolve_host (bus , argv [optind ]);
1176+ }
10501177
10511178 if (r == 0 )
10521179 r = k ;
@@ -1065,7 +1192,7 @@ int main(int argc, char **argv) {
10651192 while (argv [optind ]) {
10661193 int k ;
10671194
1068- k = resolve_record (bus , argv [optind ]);
1195+ k = resolve_record (bus , argv [optind ], arg_class , arg_type );
10691196 if (r == 0 )
10701197 r = k ;
10711198
0 commit comments