2 * The PCI Library -- Resolving ID's via DNS
4 * Copyright (c) 2007--2008 Martin Mares <mj@ucw.cz>
6 * Can be freely distributed and used under the terms of the GNU GPL v2+.
8 * SPDX-License-Identifier: GPL-2.0-or-later
21 * Our definition of BYTE_ORDER confuses arpa/nameser_compat.h on
22 * Solaris so we must undef it before including arpa/nameser.h.
28 #include <netinet/in.h>
29 #include <arpa/nameser.h>
34 * Unfortunately, there are no portable functions for DNS RR parsing,
35 * so we will do the bit shuffling with our own bare hands.
38 #define GET16(x) do { if (p+2 > end) goto err; x = (p[0] << 8) | p[1]; p += 2; } while (0)
39 #define GET32(x) do { if (p+4 > end) goto err; x = (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; p += 4; } while (0)
50 u16 counts[DNS_NUM_SECTIONS];
51 byte *sections[DNS_NUM_SECTIONS+1];
52 byte *sec_ptr, *sec_end;
54 /* Result of dns_parse_rr(): */
63 dns_skip_name(byte *p, byte *end)
67 unsigned int x = *p++;
72 case 0: /* Uncompressed: x = length */
75 case 0xc0: /* Indirection: 1 byte more for offset */
77 return (p < end) ? p : NULL;
86 dns_parse_packet(struct dns_state *s, byte *p, unsigned int plen)
89 unsigned int i, j, len;
90 unsigned int UNUSED x;
94 for (i=0; i<plen; i++)
96 if (!(i%16)) printf("%04x:", i);
97 printf(" %02x", p[i]);
98 if ((i%16)==15 || i==plen-1) putchar('\n');
102 GET32(x); /* ID and flags are ignored */
103 for (i=0; i<DNS_NUM_SECTIONS; i++)
105 for (i=0; i<DNS_NUM_SECTIONS; i++)
108 for (j=0; j < s->counts[i]; j++)
110 p = dns_skip_name(p, end); /* Name */
113 GET32(x); /* Type and class */
114 if (i != DNS_SEC_QUESTION)
117 GET16(len); /* Length of data */
132 dns_init_section(struct dns_state *s, int i)
134 s->sec_ptr = s->sections[i];
135 s->sec_end = s->sections[i+1];
139 dns_parse_rr(struct dns_state *s)
141 byte *p = s->sec_ptr;
142 byte *end = s->sec_end;
146 p = dns_skip_name(p, end);
154 s->sec_ptr = p + s->rr_len;
162 *pci_id_net_lookup(struct pci_access *a, int cat, int id1, int id2, int id3, int id4)
164 static int resolver_inited;
165 char name[256], dnsname[256], txt[256], *domain;
171 domain = pci_get_param(a, "net.domain");
172 if (!domain || !domain[0])
178 sprintf(name, "%04x", id1);
181 sprintf(name, "%04x.%04x", id2, id1);
184 sprintf(name, "%04x.%04x.%04x.%04x", id4, id3, id2, id1);
186 case ID_GEN_SUBSYSTEM:
187 sprintf(name, "%04x.%04x.s", id2, id1);
190 sprintf(name, "%02x.c", id1);
193 sprintf(name, "%02x.%02x.c", id2, id1);
196 sprintf(name, "%02x.%02x.%02x.c", id3, id2, id1);
201 sprintf(dnsname, "%.100s.%.100s", name, domain);
203 a->debug("Resolving %s\n", dnsname);
204 if (!resolver_inited)
209 res = res_query(dnsname, ns_c_in, ns_t_txt, answer, sizeof(answer));
212 a->debug("\tfailed, h_errno=%d\n", h_errno);
215 if (dns_parse_packet(&ds, answer, res) < 0)
217 a->debug("\tMalformed DNS packet received\n");
220 dns_init_section(&ds, DNS_SEC_ANSWER);
221 while (dns_parse_rr(&ds) > 0)
223 if (ds.rr_class != ns_c_in || ds.rr_type != ns_t_txt)
225 a->debug("\tUnexpected RR in answer: class %d, type %d\n", ds.rr_class, ds.rr_type);
231 while (j < dlen && j+1+data[j] <= dlen)
233 memcpy(txt, &data[j+1], data[j]);
236 a->debug("\t\"%s\"\n", txt);
237 if (txt[0] == 'i' && txt[1] == '=')
238 return strdup(txt+2);
247 char *pci_id_net_lookup(struct pci_access *a UNUSED, int cat UNUSED, int id1 UNUSED, int id2 UNUSED, int id3 UNUSED, int id4 UNUSED)