int dns_service_split(const char *joined, char **ret_name, char **ret_type, char **ret_domain) {
_cleanup_free_ char *name = NULL, *type = NULL, *domain = NULL;
- const char *p = joined, *q = NULL, *d = NULL;
+ const char *p = joined, *q = NULL, *d = joined;
char a[DNS_LABEL_MAX+1], b[DNS_LABEL_MAX+1], c[DNS_LABEL_MAX+1];
int an, bn, cn, r;
unsigned x = 0;
return bn;
if (bn > 0) {
+ if (!srv_type_label_is_valid(b, bn))
+ goto finish;
+
x++;
/* If there was a second label, try to get the third one */
if (cn < 0)
return cn;
- if (cn > 0)
+ if (cn > 0 && srv_type_label_is_valid(c, cn))
x++;
- } else
- cn = 0;
- } else
- an = 0;
-
- if (x >= 2 && srv_type_label_is_valid(b, bn)) {
+ }
+ }
- if (x >= 3 && srv_type_label_is_valid(c, cn)) {
+ switch (x) {
+ case 2:
+ if (!srv_type_label_is_valid(a, an))
+ break;
- if (dns_service_name_label_is_valid(a, an)) {
- /* OK, got <name> . <type> . <type2> . <domain> */
+ /* OK, got <type> . <type2> . <domain> */
- name = strndup(a, an);
- if (!name)
- return -ENOMEM;
+ name = NULL;
- type = strjoin(b, ".", c);
- if (!type)
- return -ENOMEM;
+ type = strjoin(a, ".", b);
+ if (!type)
+ return -ENOMEM;
- d = p;
- goto finish;
- }
+ d = q;
+ break;
- } else if (srv_type_label_is_valid(a, an)) {
+ case 3:
+ if (!dns_service_name_label_is_valid(a, an))
+ break;
- /* OK, got <type> . <type2> . <domain> */
+ /* OK, got <name> . <type> . <type2> . <domain> */
- name = NULL;
+ name = strndup(a, an);
+ if (!name)
+ return -ENOMEM;
- type = strjoin(a, ".", b);
- if (!type)
- return -ENOMEM;
+ type = strjoin(b, ".", c);
+ if (!type)
+ return -ENOMEM;
- d = q;
- goto finish;
- }
+ d = p;
+ break;
}
- name = NULL;
- type = NULL;
- d = joined;
-
finish:
r = dns_name_normalize(d, 0, &domain);
if (r < 0)