]> mj.ucw.cz Git - pciutils.git/blob - lib/names-net.c
Call res_init() only once.
[pciutils.git] / lib / names-net.c
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>
11
12 #include "internal.h"
13 #include "names.h"
14
15 #ifdef PCI_USE_DNS
16
17 #include <netinet/in.h>
18 #include <arpa/nameser.h>
19 #include <resolv.h>
20
21 char
22 *pci_id_net_lookup(struct pci_access *a, int cat, int id1, int id2, int id3, int id4)
23 {
24   static int resolver_inited;
25   char name[256], dnsname[256], txt[256], *domain;
26   byte answer[4096];
27   const byte *data;
28   int res, i, j, dlen;
29   ns_msg m;
30   ns_rr rr;
31
32   domain = pci_get_param(a, "net.domain");
33   if (!domain || !domain[0])
34     return NULL;
35
36   switch (cat)
37     {
38     case ID_VENDOR:
39       sprintf(name, "%04x", id1);
40       break;
41     case ID_DEVICE:
42       sprintf(name, "%04x.%04x", id2, id1);
43       break;
44     case ID_SUBSYSTEM:
45       sprintf(name, "%04x.%04x.%04x.%04x", id4, id3, id2, id1);
46       break;
47     case ID_GEN_SUBSYSTEM:
48       sprintf(name, "%04x.%04x.s", id2, id1);
49       break;
50     case ID_CLASS:
51       sprintf(name, "%02x.c", id1);
52       break;
53     case ID_SUBCLASS:
54       sprintf(name, "%02x.%02x.c", id2, id1);
55       break;
56     case ID_PROGIF:
57       sprintf(name, "%02x.%02x.%02x.c", id3, id2, id1);
58       break;
59     default:
60       return NULL;
61     }
62   sprintf(dnsname, "%s.%s", name, domain);
63
64   a->debug("Resolving %s\n", dnsname);
65   if (!resolver_inited)
66     {
67       resolver_inited = 1;
68       res_init();
69     }
70   res = res_query(dnsname, ns_c_in, ns_t_txt, answer, sizeof(answer));
71   if (res < 0)
72     {
73       a->debug("\tfailed, h_errno=%d\n", _res.res_h_errno);
74       return NULL;
75     }
76   if (ns_initparse(answer, res, &m) < 0)
77     {
78       a->debug("\tinitparse failed\n");
79       return NULL;
80     }
81   for (i=0; ns_parserr(&m, ns_s_an, i, &rr) >= 0; i++)
82     {
83       a->debug("\tanswer %d (class %d, type %d)\n", i, ns_rr_class(rr), ns_rr_type(rr));
84       if (ns_rr_class(rr) != ns_c_in || ns_rr_type(rr) != ns_t_txt)
85         continue;
86       data = ns_rr_rdata(rr);
87       dlen = ns_rr_rdlen(rr);
88       j = 0;
89       while (j < dlen && j+1+data[j] <= dlen)
90         {
91           memcpy(txt, &data[j+1], data[j]);
92           txt[data[j]] = 0;
93           j += 1+data[j];
94           a->debug("\t\t%s\n", txt);
95           if (txt[0] == 'i' && txt[1] == '=')
96             return strdup(txt+2);
97         }
98     }
99
100   return NULL;
101 }
102
103 #else
104
105 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)
106 {
107   return NULL;
108 }
109
110 #endif