2 static const char out_table[32]="0123456789abcdefghijklmnopqrstuv";
4 static inline int enoughinput(struct dnsbitenc *be) {
5 return be->npending >= 5;
7 static inline void startlabel(struct dnsbitenc *be) {
10 static inline void outputchar(struct dnsbitenc *be) {
11 /* there must be enough input and enough space */
16 *--(be->out) = out_table[be->pending & 0x1f];
21 void dnsbitenc_start(struct dnsbitenc *be, uint8_t *buf, int buflen) {
30 void dnsbitenc_addbits(struct dnsbitenc *be, uint32_t val, int nbits) {
31 assert(nbits<=28); /* otherwise pending might overflow */
32 assert(!(val & ~(((uint32_t)1 << nbits)-1)));
33 be->pending |= val << be->npending;
34 be->npending += nbits;
35 while (enoughinput(be)) {
36 assert(be->out > be->bufstop);
41 void dnsbitenc_addu32(struct dnsbitenc *be, uint32_t val) {
42 dnsbitenc_addbits(be, val & 0xffff, 16);
43 dnsbitenc_addbits(be, val >> 16, 16);
46 int dnsbitenc_restbytes(struct dnsbitenc *be, uint8_t *bytes, int qty) {
49 return qty + ((be->npending + 7) / 8);
53 be->pending |= (*bytes++) << be->npending;
55 } else if (be->npending <= 0) {
63 uint8_t *dnsbitenc_getresult(struct dnsbitenc *be) {
64 *--(be->out) = 63 - be->labremain; /* finish the last label */
71 #define MAX_DATA_LABELS
73 struct labelinpacket {
79 /* private for dnsbitdec_... functions; do not access direcctly */
80 const databuf[MAX_DOMAIN_BYTES];
84 static void setafter(const uint8_t *domain, const uint8_t **domain_end_r) {
85 if (domain_end_r && !*domain_end_r)
89 int dnsdomaindec_start(struct dnsbitdec *bd, const uint8_t *packet,
90 const uint8_t *endpacket, const uint8_t *domain,
91 int mydompathlen, const char *mydompath[],
92 const uint8_t **domain_end_r) {
93 int maxlabels=mydompath+MAX_DATA_LABELS;
94 const strut labelinpacket labels[maxlabels];
95 int nlabels=0, totallen=0;
99 if (domain==endpacket)
101 unsigned b=*domain++;
104 setafter(domain,domain_end_r);
107 if ((b & 0xc0) == 0xc0) {
108 if (domain==endpacket)
110 unsigned b2=*domain++;
111 setafter(domain,domain_end_r);
112 unsigned off= ((b & 0x3f)<<8) | b2;
113 if (off >= endpacket - packet)
117 if (!b) return FORMERR
118 /* now fall through to code expecting a literal */
120 if ((b & 0xc0) != 0x00)
122 if (nlabels>=maxlabels)
125 if (totallen >= MAX_DOMAIN_BYTES) /* we still need a nul label */
127 labels[nlabels].bytes=domain;
128 labels[nlabels].len=b;
132 if (nlabels <= mydompathlen)
134 for (i=0; i<mydompathlen; i++) {
135 int l=strlen(mydompath[i]);
136 const struct labelinpacket *got=&labels[nlabels-mydompathlen];
137 if (got->len != l || memcmp(got->bytes,mydompath[i]))
140 /* OK, it's our domain and it has some data and a good
141 * number of labels. Wow. */
142 uint8_t *copyto=&bd->databuf;
143 for (i=0; i<nlabels-mydompathlen; i++) {
144 const uint8_t *p=labels[i].bytes;
145 for (j=0; j<labels[i].len; j++) {
146 int val=in_table[*p++];
152 assert(copyto <= bd->databuf+sizeof(bd->databuf));
157 static uint8_t in_table[256];
159 static void dnsdomaindec_globalinit(void) {
160 memset(in_table,0xff,sizeof(in_table));
161 for (i=0; i<32; i++) {
162 in_table[out_table[i]]=i;
163 in_table[toupper((unsigned char)out_table[i])]=i;
167 static void inputchar(struct dnsbitdec *bd) {
168 /* must be enough input and enough space in pending */
171 bd->pending |= ch; /* already decoded */
174 uint32_t dnsdomaindec_getbits(struct dnsbitdec *bd, int nbits)
178 while (bd->pending < nbits)
180 int newnpending = bd->pending - nbits;
181 uint32_t rv = bd->pending >> newnpending;
182 bd->pending &= ((uint32_t)1 << newnpending)-1;
183 bd->npending = newnpending;
185 uint32_t dnsdomaindec_getu32(struct dnsbitdec *bd)
187 uint32_t lsw=dnsdomaindec_getbits(bd,16);
188 uint32_t msw=dnsdomaindec_getbits(bd,16);
189 return (msw << 16) | lsw;
191 int dnsbitdec_restbytes(struct dnsbitdec *bd, uint8_t outbuf[MAX_DOMAIN_BYTES])
195 if (bd->npending >= 8) {
196 *out++ = bd->pending;
200 if (bd->in == bd->databuf) {
201 /* that's all the input */