cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

names.c (10679B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *      names.c  --  USB name database manipulation routines
      4 *
      5 *      Copyright (C) 1999, 2000  Thomas Sailer (sailer@ife.ee.ethz.ch)
      6 *
      7 *	Copyright (C) 2005 Takahiro Hirofuchi
      8 *		- names_deinit() is added.
      9 */
     10
     11#include <sys/types.h>
     12#include <sys/stat.h>
     13#include <fcntl.h>
     14#include <dirent.h>
     15#include <string.h>
     16#include <errno.h>
     17#include <stdlib.h>
     18#include <unistd.h>
     19#include <stdio.h>
     20#include <ctype.h>
     21
     22#include "names.h"
     23#include "usbip_common.h"
     24
     25struct vendor {
     26	struct vendor *next;
     27	u_int16_t vendorid;
     28	char name[1];
     29};
     30
     31struct product {
     32	struct product *next;
     33	u_int16_t vendorid, productid;
     34	char name[1];
     35};
     36
     37struct class {
     38	struct class *next;
     39	u_int8_t classid;
     40	char name[1];
     41};
     42
     43struct subclass {
     44	struct subclass *next;
     45	u_int8_t classid, subclassid;
     46	char name[1];
     47};
     48
     49struct protocol {
     50	struct protocol *next;
     51	u_int8_t classid, subclassid, protocolid;
     52	char name[1];
     53};
     54
     55struct genericstrtable {
     56	struct genericstrtable *next;
     57	unsigned int num;
     58	char name[1];
     59};
     60
     61
     62#define HASH1  0x10
     63#define HASH2  0x02
     64#define HASHSZ 16
     65
     66static unsigned int hashnum(unsigned int num)
     67{
     68	unsigned int mask1 = HASH1 << 27, mask2 = HASH2 << 27;
     69
     70	for (; mask1 >= HASH1; mask1 >>= 1, mask2 >>= 1)
     71		if (num & mask1)
     72			num ^= mask2;
     73	return num & (HASHSZ-1);
     74}
     75
     76
     77static struct vendor *vendors[HASHSZ] = { NULL, };
     78static struct product *products[HASHSZ] = { NULL, };
     79static struct class *classes[HASHSZ] = { NULL, };
     80static struct subclass *subclasses[HASHSZ] = { NULL, };
     81static struct protocol *protocols[HASHSZ] = { NULL, };
     82
     83const char *names_vendor(u_int16_t vendorid)
     84{
     85	struct vendor *v;
     86
     87	v = vendors[hashnum(vendorid)];
     88	for (; v; v = v->next)
     89		if (v->vendorid == vendorid)
     90			return v->name;
     91	return NULL;
     92}
     93
     94const char *names_product(u_int16_t vendorid, u_int16_t productid)
     95{
     96	struct product *p;
     97
     98	p = products[hashnum((vendorid << 16) | productid)];
     99	for (; p; p = p->next)
    100		if (p->vendorid == vendorid && p->productid == productid)
    101			return p->name;
    102	return NULL;
    103}
    104
    105const char *names_class(u_int8_t classid)
    106{
    107	struct class *c;
    108
    109	c = classes[hashnum(classid)];
    110	for (; c; c = c->next)
    111		if (c->classid == classid)
    112			return c->name;
    113	return NULL;
    114}
    115
    116const char *names_subclass(u_int8_t classid, u_int8_t subclassid)
    117{
    118	struct subclass *s;
    119
    120	s = subclasses[hashnum((classid << 8) | subclassid)];
    121	for (; s; s = s->next)
    122		if (s->classid == classid && s->subclassid == subclassid)
    123			return s->name;
    124	return NULL;
    125}
    126
    127const char *names_protocol(u_int8_t classid, u_int8_t subclassid,
    128			   u_int8_t protocolid)
    129{
    130	struct protocol *p;
    131
    132	p = protocols[hashnum((classid << 16) | (subclassid << 8)
    133			      | protocolid)];
    134	for (; p; p = p->next)
    135		if (p->classid == classid && p->subclassid == subclassid &&
    136		    p->protocolid == protocolid)
    137			return p->name;
    138	return NULL;
    139}
    140
    141/* add a cleanup function by takahiro */
    142struct pool {
    143	struct pool *next;
    144	void *mem;
    145};
    146
    147static struct pool *pool_head;
    148
    149static void *my_malloc(size_t size)
    150{
    151	struct pool *p;
    152
    153	p = calloc(1, sizeof(struct pool));
    154	if (!p)
    155		return NULL;
    156
    157	p->mem = calloc(1, size);
    158	if (!p->mem) {
    159		free(p);
    160		return NULL;
    161	}
    162
    163	p->next = pool_head;
    164	pool_head = p;
    165
    166	return p->mem;
    167}
    168
    169void names_free(void)
    170{
    171	struct pool *pool;
    172
    173	if (!pool_head)
    174		return;
    175
    176	for (pool = pool_head; pool != NULL; ) {
    177		struct pool *tmp;
    178
    179		if (pool->mem)
    180			free(pool->mem);
    181
    182		tmp = pool;
    183		pool = pool->next;
    184		free(tmp);
    185	}
    186}
    187
    188static int new_vendor(const char *name, u_int16_t vendorid)
    189{
    190	struct vendor *v;
    191	unsigned int h = hashnum(vendorid);
    192
    193	v = vendors[h];
    194	for (; v; v = v->next)
    195		if (v->vendorid == vendorid)
    196			return -1;
    197	v = my_malloc(sizeof(struct vendor) + strlen(name));
    198	if (!v)
    199		return -1;
    200	strcpy(v->name, name);
    201	v->vendorid = vendorid;
    202	v->next = vendors[h];
    203	vendors[h] = v;
    204	return 0;
    205}
    206
    207static int new_product(const char *name, u_int16_t vendorid,
    208		       u_int16_t productid)
    209{
    210	struct product *p;
    211	unsigned int h = hashnum((vendorid << 16) | productid);
    212
    213	p = products[h];
    214	for (; p; p = p->next)
    215		if (p->vendorid == vendorid && p->productid == productid)
    216			return -1;
    217	p = my_malloc(sizeof(struct product) + strlen(name));
    218	if (!p)
    219		return -1;
    220	strcpy(p->name, name);
    221	p->vendorid = vendorid;
    222	p->productid = productid;
    223	p->next = products[h];
    224	products[h] = p;
    225	return 0;
    226}
    227
    228static int new_class(const char *name, u_int8_t classid)
    229{
    230	struct class *c;
    231	unsigned int h = hashnum(classid);
    232
    233	c = classes[h];
    234	for (; c; c = c->next)
    235		if (c->classid == classid)
    236			return -1;
    237	c = my_malloc(sizeof(struct class) + strlen(name));
    238	if (!c)
    239		return -1;
    240	strcpy(c->name, name);
    241	c->classid = classid;
    242	c->next = classes[h];
    243	classes[h] = c;
    244	return 0;
    245}
    246
    247static int new_subclass(const char *name, u_int8_t classid, u_int8_t subclassid)
    248{
    249	struct subclass *s;
    250	unsigned int h = hashnum((classid << 8) | subclassid);
    251
    252	s = subclasses[h];
    253	for (; s; s = s->next)
    254		if (s->classid == classid && s->subclassid == subclassid)
    255			return -1;
    256	s = my_malloc(sizeof(struct subclass) + strlen(name));
    257	if (!s)
    258		return -1;
    259	strcpy(s->name, name);
    260	s->classid = classid;
    261	s->subclassid = subclassid;
    262	s->next = subclasses[h];
    263	subclasses[h] = s;
    264	return 0;
    265}
    266
    267static int new_protocol(const char *name, u_int8_t classid, u_int8_t subclassid,
    268			u_int8_t protocolid)
    269{
    270	struct protocol *p;
    271	unsigned int h = hashnum((classid << 16) | (subclassid << 8)
    272				 | protocolid);
    273
    274	p = protocols[h];
    275	for (; p; p = p->next)
    276		if (p->classid == classid && p->subclassid == subclassid
    277		    && p->protocolid == protocolid)
    278			return -1;
    279	p = my_malloc(sizeof(struct protocol) + strlen(name));
    280	if (!p)
    281		return -1;
    282	strcpy(p->name, name);
    283	p->classid = classid;
    284	p->subclassid = subclassid;
    285	p->protocolid = protocolid;
    286	p->next = protocols[h];
    287	protocols[h] = p;
    288	return 0;
    289}
    290
    291static void parse(FILE *f)
    292{
    293	char buf[512], *cp;
    294	unsigned int linectr = 0;
    295	int lastvendor = -1;
    296	int lastclass = -1;
    297	int lastsubclass = -1;
    298	int lasthut = -1;
    299	int lastlang = -1;
    300	unsigned int u;
    301
    302	while (fgets(buf, sizeof(buf), f)) {
    303		linectr++;
    304		/* remove line ends */
    305		cp = strchr(buf, '\r');
    306		if (cp)
    307			*cp = 0;
    308		cp = strchr(buf, '\n');
    309		if (cp)
    310			*cp = 0;
    311		if (buf[0] == '#' || !buf[0])
    312			continue;
    313		cp = buf;
    314		if (buf[0] == 'P' && buf[1] == 'H' && buf[2] == 'Y' &&
    315		    buf[3] == 'S' && buf[4] == 'D' &&
    316		    buf[5] == 'E' && buf[6] == 'S' && /*isspace(buf[7])*/
    317		    buf[7] == ' ') {
    318			continue;
    319		}
    320		if (buf[0] == 'P' && buf[1] == 'H' &&
    321		    buf[2] == 'Y' && /*isspace(buf[3])*/ buf[3] == ' ') {
    322			continue;
    323		}
    324		if (buf[0] == 'B' && buf[1] == 'I' && buf[2] == 'A' &&
    325		    buf[3] == 'S' && /*isspace(buf[4])*/ buf[4] == ' ') {
    326			continue;
    327		}
    328		if (buf[0] == 'L' && /*isspace(buf[1])*/ buf[1] == ' ') {
    329			lasthut = lastclass = lastvendor = lastsubclass = -1;
    330			/*
    331			 * set 1 as pseudo-id to indicate that the parser is
    332			 * in a `L' section.
    333			 */
    334			lastlang = 1;
    335			continue;
    336		}
    337		if (buf[0] == 'C' && /*isspace(buf[1])*/ buf[1] == ' ') {
    338			/* class spec */
    339			cp = buf+2;
    340			while (isspace(*cp))
    341				cp++;
    342			if (!isxdigit(*cp)) {
    343				err("Invalid class spec at line %u", linectr);
    344				continue;
    345			}
    346			u = strtoul(cp, &cp, 16);
    347			while (isspace(*cp))
    348				cp++;
    349			if (!*cp) {
    350				err("Invalid class spec at line %u", linectr);
    351				continue;
    352			}
    353			if (new_class(cp, u))
    354				err("Duplicate class spec at line %u class %04x %s",
    355				    linectr, u, cp);
    356			dbg("line %5u class %02x %s", linectr, u, cp);
    357			lasthut = lastlang = lastvendor = lastsubclass = -1;
    358			lastclass = u;
    359			continue;
    360		}
    361		if (buf[0] == 'A' && buf[1] == 'T' && isspace(buf[2])) {
    362			/* audio terminal type spec */
    363			continue;
    364		}
    365		if (buf[0] == 'H' && buf[1] == 'C' && buf[2] == 'C'
    366		    && isspace(buf[3])) {
    367			/* HID Descriptor bCountryCode */
    368			continue;
    369		}
    370		if (isxdigit(*cp)) {
    371			/* vendor */
    372			u = strtoul(cp, &cp, 16);
    373			while (isspace(*cp))
    374				cp++;
    375			if (!*cp) {
    376				err("Invalid vendor spec at line %u", linectr);
    377				continue;
    378			}
    379			if (new_vendor(cp, u))
    380				err("Duplicate vendor spec at line %u vendor %04x %s",
    381				    linectr, u, cp);
    382			dbg("line %5u vendor %04x %s", linectr, u, cp);
    383			lastvendor = u;
    384			lasthut = lastlang = lastclass = lastsubclass = -1;
    385			continue;
    386		}
    387		if (buf[0] == '\t' && isxdigit(buf[1])) {
    388			/* product or subclass spec */
    389			u = strtoul(buf+1, &cp, 16);
    390			while (isspace(*cp))
    391				cp++;
    392			if (!*cp) {
    393				err("Invalid product/subclass spec at line %u",
    394				    linectr);
    395				continue;
    396			}
    397			if (lastvendor != -1) {
    398				if (new_product(cp, lastvendor, u))
    399					err("Duplicate product spec at line %u product %04x:%04x %s",
    400					    linectr, lastvendor, u, cp);
    401				dbg("line %5u product %04x:%04x %s", linectr,
    402				    lastvendor, u, cp);
    403				continue;
    404			}
    405			if (lastclass != -1) {
    406				if (new_subclass(cp, lastclass, u))
    407					err("Duplicate subclass spec at line %u class %02x:%02x %s",
    408					    linectr, lastclass, u, cp);
    409				dbg("line %5u subclass %02x:%02x %s", linectr,
    410				    lastclass, u, cp);
    411				lastsubclass = u;
    412				continue;
    413			}
    414			if (lasthut != -1) {
    415				/* do not store hut */
    416				continue;
    417			}
    418			if (lastlang != -1) {
    419				/* do not store langid */
    420				continue;
    421			}
    422			err("Product/Subclass spec without prior Vendor/Class spec at line %u",
    423			    linectr);
    424			continue;
    425		}
    426		if (buf[0] == '\t' && buf[1] == '\t' && isxdigit(buf[2])) {
    427			/* protocol spec */
    428			u = strtoul(buf+2, &cp, 16);
    429			while (isspace(*cp))
    430				cp++;
    431			if (!*cp) {
    432				err("Invalid protocol spec at line %u",
    433				    linectr);
    434				continue;
    435			}
    436			if (lastclass != -1 && lastsubclass != -1) {
    437				if (new_protocol(cp, lastclass, lastsubclass,
    438						 u))
    439					err("Duplicate protocol spec at line %u class %02x:%02x:%02x %s",
    440					    linectr, lastclass, lastsubclass,
    441					    u, cp);
    442				dbg("line %5u protocol %02x:%02x:%02x %s",
    443				    linectr, lastclass, lastsubclass, u, cp);
    444				continue;
    445			}
    446			err("Protocol spec without prior Class and Subclass spec at line %u",
    447			    linectr);
    448			continue;
    449		}
    450		if (buf[0] == 'H' && buf[1] == 'I' &&
    451		    buf[2] == 'D' && /*isspace(buf[3])*/ buf[3] == ' ') {
    452			continue;
    453		}
    454		if (buf[0] == 'H' && buf[1] == 'U' &&
    455		    buf[2] == 'T' && /*isspace(buf[3])*/ buf[3] == ' ') {
    456			lastlang = lastclass = lastvendor = lastsubclass = -1;
    457			/*
    458			 * set 1 as pseudo-id to indicate that the parser is
    459			 * in a `HUT' section.
    460			 */
    461			lasthut = 1;
    462			continue;
    463		}
    464		if (buf[0] == 'R' && buf[1] == ' ')
    465			continue;
    466
    467		if (buf[0] == 'V' && buf[1] == 'T')
    468			continue;
    469
    470		err("Unknown line at line %u", linectr);
    471	}
    472}
    473
    474
    475int names_init(char *n)
    476{
    477	FILE *f;
    478
    479	f = fopen(n, "r");
    480	if (!f)
    481		return errno;
    482
    483	parse(f);
    484	fclose(f);
    485	return 0;
    486}