readme updates
[platform/upstream/crda.git] / daemon / dump.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <sys/mman.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <unistd.h>
7 #include <fcntl.h>
8 #include <arpa/inet.h> /* ntohl */
9
10 #include "regdb.h"
11
12 static void *get_file_ptr(__u8 *db, int dblen, int structlen, __be32 ptr)
13 {
14         __u32 p = ntohl(ptr);
15
16         if (p > dblen - structlen) {
17                 fprintf(stderr, "Invalid database file, bad pointer!\n");
18                 exit(3);
19         }
20
21         return (void *)(db + p);
22 }
23
24 static void print_reg_rule(__u8 *db, int dblen, __be32 ruleptr)
25 {
26         struct regdb_file_reg_rule *rule;
27         struct regdb_file_freq_range *freq;
28         struct regdb_file_power_rule *power;
29
30         rule = get_file_ptr(db, dblen, sizeof(*rule), ruleptr);
31         freq = get_file_ptr(db, dblen, sizeof(*freq), rule->freq_range_ptr);
32         power = get_file_ptr(db, dblen, sizeof(*power), rule->power_rule_ptr);
33
34         printf("\t%d..%d kHz (maxbw: %d kHz, mod: 0x%x, restrict: 0x%x)\n",
35                ntohl(freq->start_freq),
36                ntohl(freq->end_freq),
37                ntohl(freq->max_bandwidth),
38                ntohl(freq->modulation_cap),
39                ntohl(freq->misc_restrictions));
40
41         printf("\t -> env: '%.1s', ag: %d, ir_ptmp: %d, ir_ptp: %d, eirp_pmtp: %d, eirp_ptp: %d\n",
42                &power->environment_cap,
43                ntohl(power->max_antenna_gain),
44                ntohl(power->max_ir_ptmp),
45                ntohl(power->max_ir_ptp),
46                ntohl(power->max_eirp_pmtp),
47                ntohl(power->max_eirp_ptp));
48 }
49
50 int main(int argc, char **argv)
51 {
52         int fd;
53         struct stat stat;
54         __u8 *db;
55         struct regdb_file_header *header;
56         struct regdb_file_reg_country *countries;
57         int dblen, num_countries, i, j;
58
59         if (argc != 2) {
60                 fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
61                 return 2;
62         }
63
64         fd = open(argv[1], O_RDONLY);
65         if (fd < 0) {
66                 perror("failed to open db file");
67                 return 2;
68         }
69
70         if (fstat(fd, &stat)) {
71                 perror("failed to fstat db file");
72                 return 2;
73         }
74
75         dblen = stat.st_size;
76
77         db = mmap(NULL, dblen, PROT_READ, MAP_SHARED, fd, 0);
78         if (db == MAP_FAILED) {
79                 perror("failed to mmap db file");
80                 return 2;
81         }
82
83         header = get_file_ptr(db, dblen, sizeof(*header), 0);
84
85         if (ntohl(header->magic) != REGDB_MAGIC) {
86                 fprintf(stderr, "Invalid database magic\n");
87                 return 2;
88         }
89
90         if (ntohl(header->version) != REGDB_VERSION) {
91                 fprintf(stderr, "Invalid database version\n");
92                 return 2;
93         }
94
95         num_countries = ntohl(header->reg_country_num);
96         countries = get_file_ptr(db, dblen,
97                                  sizeof(struct regdb_file_reg_country) * num_countries,
98                                  header->reg_country_ptr);
99
100         for (i = 0; i < num_countries; i++) {
101                 struct regdb_file_reg_rules_collection *rcoll;
102                 struct regdb_file_reg_country *country = countries + i;
103                 int num_rules;
104
105                 printf("Country %.2s\n", country->alpha2);
106                 rcoll = get_file_ptr(db, dblen, sizeof(*rcoll), country->reg_collection_ptr);
107                 num_rules = ntohl(rcoll->reg_rule_num);
108                 /* re-get pointer with sanity checking for num_rules */
109                 rcoll = get_file_ptr(db, dblen,
110                                      sizeof(*rcoll) + num_rules * sizeof(__be32),
111                                      country->reg_collection_ptr);
112                 for (j = 0; j < num_rules; j++)
113                         print_reg_rule(db, dblen, rcoll->reg_rule_ptrs[j]);
114         }
115
116         return 0;
117 }