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