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