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