diff --git a/Makefile b/Makefile index 05e8d58..243cc04 100644 --- a/Makefile +++ b/Makefile @@ -30,7 +30,7 @@ validns: main.o carp.o mempool.o textparse.o base64.o base32hex.o \ dname.o tlsa.o nid.o l32.o l64.o lp.o \ ipseckey.o cbtree.o mb.o mg.o mr.o minfo.o \ afsdb.o x25.o isdn.o rt.o px.o kx.o \ - dlv.o dhcid.o nsap.o caa.o + dlv.o dhcid.o nsap.o caa.o svcb.o $(CC) $(CFLAGS) $(OPTIMIZE) -o validns \ main.o carp.o mempool.o textparse.o base64.o base32hex.o \ rr.o soa.o a.o cname.o mx.o ns.o \ @@ -41,7 +41,7 @@ validns: main.o carp.o mempool.o textparse.o base64.o base32hex.o \ dname.o tlsa.o nid.o l32.o l64.o lp.o \ ipseckey.o cbtree.o mb.o mg.o mr.o minfo.o \ afsdb.o x25.o isdn.o rt.o px.o kx.o \ - dlv.o dhcid.o nsap.o caa.o \ + dlv.o dhcid.o nsap.o caa.o svcb.o \ -L/usr/local/lib $(EXTRALPATH) \ -lJudy -lcrypto $(EXTRALIBS) $(EXTRALINKING) @@ -56,7 +56,7 @@ clean: -rm -f nid.o l32.o l64.o lp.o ipseckey.o -rm -f cbtree.o mb.o mg.o mr.o minfo.o -rm -f afsdb.o x25.o isdn.o rt.o px.o kx.o - -rm -f dlv.o dhcid.o nsap.o caa.o + -rm -f dlv.o dhcid.o nsap.o caa.o svcb.o -rm -f validns.core core @echo ':-)' @@ -156,6 +156,9 @@ naptr.o: naptr.c common.h textparse.h mempool.h carp.h rr.h srv.o: srv.c common.h textparse.h mempool.h carp.h rr.h $(CC) $(CFLAGS) $(OPTIMIZE) -c -o srv.o srv.c $(INCPATH) +svcb.o: svcb.c common.h textparse.h mempool.h carp.h rr.h + $(CC) $(CFLAGS) $(OPTIMIZE) -c -o svcb.o svcb.c $(INCPATH) + nsec3param.o: nsec3param.c common.h textparse.h mempool.h carp.h rr.h $(CC) $(CFLAGS) $(OPTIMIZE) -c -o nsec3param.o nsec3param.c $(INCPATH) diff --git a/main.c b/main.c index 469c15a..af15c3c 100644 --- a/main.c +++ b/main.c @@ -489,6 +489,7 @@ static void initialize_globals(void) rr_methods[T_DNSKEY] = dnskey_methods; rr_methods[T_DS] = ds_methods; rr_methods[T_HINFO] = hinfo_methods; + rr_methods[T_HTTPS] = svcb_methods; rr_methods[T_IPSECKEY] = ipseckey_methods; rr_methods[T_ISDN] = isdn_methods; rr_methods[T_KX] = kx_methods; @@ -518,6 +519,7 @@ static void initialize_globals(void) rr_methods[T_SPF] = spf_methods; rr_methods[T_SRV] = srv_methods; rr_methods[T_SSHFP] = sshfp_methods; + rr_methods[T_SVCB] = svcb_methods; rr_methods[T_TLSA] = tlsa_methods; rr_methods[T_TXT] = txt_methods; rr_methods[T_X25] = x25_methods; diff --git a/rr.c b/rr.c index c7ab12e..9680722 100644 --- a/rr.c +++ b/rr.c @@ -77,7 +77,10 @@ static char* rdtype2str_map[T_MAX+1] = { 0, 0, 0, 0, 0, "CDS", "CDNSKEY", /* 60 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 70 */ + 0, 0, 0, + "SVCB", + "HTTPS", + 0, 0, 0, 0, 0, /* 70 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 80 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 90 */ 0, 0, 0, 0, 0, 0, 0, 0, @@ -531,6 +534,8 @@ int str2rdtype(char *rdtype, int *is_generic) case 'h': if (strcmp(rdtype, "hinfo") == 0) { return T_HINFO; + } else if (strcmp(rdtype, "https") == 0) { + return T_HTTPS; } break; case 'i': @@ -613,6 +618,8 @@ int str2rdtype(char *rdtype, int *is_generic) return T_SSHFP; } else if (strcmp(rdtype, "smimea") == 0) { return T_SMIMEA; + } else if (strcmp(rdtype, "svcb") == 0) { + return T_SVCB; } break; case 't': diff --git a/rr.h b/rr.h index a2d39b2..c712b51 100644 --- a/rr.h +++ b/rr.h @@ -48,6 +48,8 @@ #define T_SMIMEA 53 #define T_CDS 59 #define T_CDNSKEY 60 +#define T_SVCB 64 +#define T_HTTPS 65 #define T_SPF 99 #define T_NID 104 #define T_L32 105 @@ -584,6 +586,16 @@ struct rr_caa }; extern struct rr_methods caa_methods; +struct rr_svcb +{ + struct rr rr; + uint16_t priority; + char *target; + int count; + struct binary_data params[1]; +}; +extern struct rr_methods svcb_methods; + extern struct rr_nsec3 *first_nsec3; extern struct rr_nsec3 *latest_nsec3; diff --git a/svcb.c b/svcb.c new file mode 100644 index 0000000..bba69a1 --- /dev/null +++ b/svcb.c @@ -0,0 +1,119 @@ +/* + * Part of DNS zone file validator `validns`. + * + * Copyright 2011-2017 Anton Berezin + * Modified BSD license. + * (See LICENSE file in the distribution.) + * + */ +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "textparse.h" +#include "mempool.h" +#include "carp.h" +#include "rr.h" + +static struct rr* svcb_parse(char *name, long ttl, int type, char *s) +{ + struct rr_svcb *rr; + int p; + char *t; + struct binary_data params[20]; + int i; + + p = extract_integer(&s, "priority", NULL); + if (p < 0) + return NULL; + if (p > 65536) + return bitch("priority range is not valid"); + + t = extract_name(&s, "target", 0); + if (!t) + return NULL; + + i = 0; + while (*s) { + if (i >= 20) + return bitch("program limit: too many SVC parameters"); + params[i] = extract_text(&s, "SVC parameter"); + if (params[i].length < 0) + return NULL; + if (params[i].length > 255) + return bitch("SVC parameter too long"); + i++; + } + if (p == 0 && i > 0) { + return bitch("non-empty parameters in alias mode"); + } else if (p > 0 && i == 0) { + return bitch("empty parameters in service mode"); + } + + rr = getmem(sizeof(*rr) + sizeof(struct binary_data) * (i-1)); + + rr->priority = p; + rr->target = t; + rr->count = i; + for (i = 0; i < rr->count; i++) { + rr->params[i] = params[i]; + } + + return store_record(type, name, ttl, rr); +} + +static char* svcb_human(struct rr *rrv) +{ + RRCAST(svcb); + char ss[1024]; + int i; + char *s = ss; + int l; + + l = snprintf(ss, 1024, "%hu %s", + rr->priority, rr->target); + s += l; + + for (i = 0; i < rr->count; i++) { + l = snprintf(s, 1024-(s-ss), " %s", rr->params[i].data); + s += l; + } + + return quickstrdup_temp(ss); +} + +static struct binary_data svcb_wirerdata(struct rr *rrv) +{ + RRCAST(svcb); + struct binary_data r, t; + int i; + char param[255]; + char *key; + char *val; + int idx; + int port; + + r = bad_binary_data(); + t.length = 0; + t.data = NULL; + + for (i = 0; i < rr->count; i++) { + strcpy(param, rr->params[i].data); + key = strtok(param, "="); + val = strtok(NULL, "="); + if (strcmp(key, "port") == 0) { + idx = 3; + port = atoi(val); + r = compose_binary_data("d222", 1, t, idx, sizeof(port)/2, port); + } + t = r; + } + r = compose_binary_data("2dd", 1, rr->priority, name2wire_name(rr->target), t); + return r; +} + +struct rr_methods svcb_methods = { svcb_parse, svcb_human, svcb_wirerdata, NULL, NULL };