]> git.ipfire.org Git - thirdparty/pciutils.git/blame - lib/names-net.c
Fix whitespace errors
[thirdparty/pciutils.git] / lib / names-net.c
CommitLineData
752d4d9a
MM
1/*
2 * The PCI Library -- Resolving ID's via DNS
3 *
4 * Copyright (c) 2007--2008 Martin Mares <mj@ucw.cz>
5 *
6 * Can be freely distributed and used under the terms of the GNU GPL.
7 */
8
9#include <string.h>
10#include <stdlib.h>
db8e009c 11#include <stdio.h>
752d4d9a
MM
12
13#include "internal.h"
14#include "names.h"
15
94d1b5e0
MM
16#ifdef PCI_USE_DNS
17
18#include <netinet/in.h>
19#include <arpa/nameser.h>
20#include <resolv.h>
a8926d30 21#include <netdb.h>
94d1b5e0 22
b14cda81
MM
23/*
24 * Unfortunately, there are no portable functions for DNS RR parsing,
25 * so we will do the bit shuffling with our own bare hands.
26 */
27
28#define GET16(x) do { if (p+2 > end) goto err; x = (p[0] << 8) | p[1]; p += 2; } while (0)
29#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)
30
31enum dns_section {
32 DNS_SEC_QUESTION,
33 DNS_SEC_ANSWER,
34 DNS_SEC_AUTHORITY,
35 DNS_SEC_ADDITIONAL,
36 DNS_NUM_SECTIONS
37};
38
39struct dns_state {
40 u16 counts[DNS_NUM_SECTIONS];
25cc4350
MM
41 byte *sections[DNS_NUM_SECTIONS+1];
42 byte *sec_ptr, *sec_end;
b14cda81
MM
43
44 /* Result of dns_parse_rr(): */
45 u16 rr_type;
46 u16 rr_class;
47 u32 rr_ttl;
48 u16 rr_len;
25cc4350 49 byte *rr_data;
b14cda81
MM
50};
51
25cc4350
MM
52static byte *
53dns_skip_name(byte *p, byte *end)
b14cda81
MM
54{
55 while (p < end)
56 {
57 unsigned int x = *p++;
58 if (!x)
59 return p;
60 switch (x & 0xc0)
61 {
62 case 0: /* Uncompressed: x = length */
63 p += x;
64 break;
65 case 0xc0: /* Indirection: 1 byte more for offset */
66 p++;
67 return (p < end) ? p : NULL;
68 default: /* RFU */
69 return NULL;
70 }
71 }
72 return NULL;
73}
74
75static int
25cc4350 76dns_parse_packet(struct dns_state *s, byte *p, unsigned int plen)
b14cda81 77{
25cc4350 78 byte *end = p + plen;
31941cb7
MM
79 unsigned int i, j, len;
80 unsigned int UNUSED x;
b14cda81
MM
81
82#if 0
83 /* Dump the packet */
84 for (i=0; i<plen; i++)
85 {
86 if (!(i%16)) printf("%04x:", i);
87 printf(" %02x", p[i]);
88 if ((i%16)==15 || i==plen-1) putchar('\n');
89 }
90#endif
91
92 GET32(x); /* ID and flags are ignored */
93 for (i=0; i<DNS_NUM_SECTIONS; i++)
94 GET16(s->counts[i]);
95 for (i=0; i<DNS_NUM_SECTIONS; i++)
96 {
97 s->sections[i] = p;
98 for (j=0; j < s->counts[i]; j++)
99 {
100 p = dns_skip_name(p, end); /* Name */
101 if (!p)
102 goto err;
103 GET32(x); /* Type and class */
104 if (i != DNS_SEC_QUESTION)
105 {
106 GET32(x); /* TTL */
107 GET16(len); /* Length of data */
108 p += len;
109 if (p > end)
110 goto err;
111 }
112 }
113 }
114 s->sections[i] = p;
115 return 0;
116
117err:
118 return -1;
119}
120
121static void
122dns_init_section(struct dns_state *s, int i)
123{
124 s->sec_ptr = s->sections[i];
125 s->sec_end = s->sections[i+1];
126}
127
128static int
129dns_parse_rr(struct dns_state *s)
130{
131 byte *p = s->sec_ptr;
132 byte *end = s->sec_end;
133
134 if (p == end)
135 return 0;
136 p = dns_skip_name(p, end);
137 if (!p)
138 goto err;
139 GET16(s->rr_type);
140 GET16(s->rr_class);
141 GET32(s->rr_ttl);
142 GET16(s->rr_len);
143 s->rr_data = p;
144 s->sec_ptr = p + s->rr_len;
145 return 1;
146
147err:
148 return -1;
149}
150
752d4d9a
MM
151char
152*pci_id_net_lookup(struct pci_access *a, int cat, int id1, int id2, int id3, int id4)
153{
a14d7f99 154 static int resolver_inited;
98ccf6d6 155 char name[256], dnsname[256], txt[256], *domain;
752d4d9a
MM
156 byte answer[4096];
157 const byte *data;
b14cda81
MM
158 int res, j, dlen;
159 struct dns_state ds;
752d4d9a 160
98ccf6d6
MM
161 domain = pci_get_param(a, "net.domain");
162 if (!domain || !domain[0])
163 return NULL;
164
752d4d9a
MM
165 switch (cat)
166 {
167 case ID_VENDOR:
168 sprintf(name, "%04x", id1);
169 break;
170 case ID_DEVICE:
171 sprintf(name, "%04x.%04x", id2, id1);
172 break;
173 case ID_SUBSYSTEM:
174 sprintf(name, "%04x.%04x.%04x.%04x", id4, id3, id2, id1);
175 break;
176 case ID_GEN_SUBSYSTEM:
177 sprintf(name, "%04x.%04x.s", id2, id1);
178 break;
179 case ID_CLASS:
180 sprintf(name, "%02x.c", id1);
181 break;
182 case ID_SUBCLASS:
183 sprintf(name, "%02x.%02x.c", id2, id1);
184 break;
185 case ID_PROGIF:
186 sprintf(name, "%02x.%02x.%02x.c", id3, id2, id1);
187 break;
188 default:
189 return NULL;
190 }
98ccf6d6 191 sprintf(dnsname, "%s.%s", name, domain);
752d4d9a
MM
192
193 a->debug("Resolving %s\n", dnsname);
a14d7f99
MM
194 if (!resolver_inited)
195 {
196 resolver_inited = 1;
197 res_init();
198 }
752d4d9a
MM
199 res = res_query(dnsname, ns_c_in, ns_t_txt, answer, sizeof(answer));
200 if (res < 0)
201 {
a8926d30 202 a->debug("\tfailed, h_errno=%d\n", h_errno);
752d4d9a
MM
203 return NULL;
204 }
b14cda81 205 if (dns_parse_packet(&ds, answer, res) < 0)
752d4d9a 206 {
b14cda81 207 a->debug("\tMalformed DNS packet received\n");
752d4d9a
MM
208 return NULL;
209 }
b14cda81
MM
210 dns_init_section(&ds, DNS_SEC_ANSWER);
211 while (dns_parse_rr(&ds) > 0)
752d4d9a 212 {
b14cda81
MM
213 if (ds.rr_class != ns_c_in || ds.rr_type != ns_t_txt)
214 {
215 a->debug("\tUnexpected RR in answer: class %d, type %d\n", ds.rr_class, ds.rr_type);
216 continue;
217 }
218 data = ds.rr_data;
219 dlen = ds.rr_len;
752d4d9a
MM
220 j = 0;
221 while (j < dlen && j+1+data[j] <= dlen)
222 {
223 memcpy(txt, &data[j+1], data[j]);
224 txt[data[j]] = 0;
225 j += 1+data[j];
b14cda81 226 a->debug("\t\"%s\"\n", txt);
752d4d9a
MM
227 if (txt[0] == 'i' && txt[1] == '=')
228 return strdup(txt+2);
229 }
230 }
231
232 return NULL;
233}
234
94d1b5e0
MM
235#else
236
237char *pci_id_net_lookup(struct pci_access *a UNUSED, int cat UNUSED, int id1 UNUSED, int id2 UNUSED, int id3 UNUSED, int id4 UNUSED)
238{
239 return NULL;
240}
241
242#endif