changing trunk/trunk to trunk
[iptables.git] / extensions / tos_values.c
1 #include <stdbool.h>
2 #include <stdint.h>
3 #include <stdio.h>
4
5 struct tos_value_mask {
6         uint8_t value, mask;
7 };
8
9 static const struct tos_symbol_info {
10         unsigned char value;
11         const char *name;
12 } tos_symbol_names[] = {
13         {IPTOS_LOWDELAY,    "Minimize-Delay"},
14         {IPTOS_THROUGHPUT,  "Maximize-Throughput"},
15         {IPTOS_RELIABILITY, "Maximize-Reliability"},
16         {IPTOS_MINCOST,     "Minimize-Cost"},
17         {IPTOS_NORMALSVC,   "Normal-Service"},
18         { .name = NULL }
19 };
20
21 /*
22  * tos_parse_numeric - parse sth. like "15/255"
23  *
24  * @s:          input string
25  * @info:       accompanying structure
26  * @bits:       number of bits that are allowed
27  *              (8 for IPv4 TOS field, 4 for IPv6 Priority Field)
28  */
29 static bool tos_parse_numeric(const char *str, struct tos_value_mask *tvm,
30                               unsigned int bits)
31 {
32         const unsigned int max = (1 << bits) - 1;
33         unsigned int value;
34         char *end;
35
36         strtonum(str, &end, &value, 0, max);
37         tvm->value = value;
38         tvm->mask  = max;
39
40         if (*end == '/') {
41                 const char *p = end + 1;
42
43                 if (!strtonum(p, &end, &value, 0, max))
44                         exit_error(PARAMETER_PROBLEM, "Illegal value: \"%s\"",
45                                    str);
46                 tvm->mask = value;
47         }
48
49         if (*end != '\0')
50                 exit_error(PARAMETER_PROBLEM, "Illegal value: \"%s\"", str);
51         return true;
52 }
53
54 static bool tos_parse_symbolic(const char *str, struct tos_value_mask *tvm,
55     unsigned int def_mask)
56 {
57         const unsigned int max = 255;
58         const struct tos_symbol_info *symbol;
59
60         if (strtonum(str, NULL, NULL, 0, max))
61                 return tos_parse_numeric(str, tvm, max);
62
63         /* Do not consider ECN bits */
64         tvm->mask = def_mask;
65         for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol)
66                 if (strcasecmp(str, symbol->name) == 0) {
67                         tvm->value = symbol->value;
68                         return true;
69                 }
70
71         exit_error(PARAMETER_PROBLEM, "Symbolic name \"%s\" is unknown", str);
72         return false;
73 }
74
75 static bool tos_try_print_symbolic(const char *prefix,
76     u_int8_t value, u_int8_t mask)
77 {
78         const struct tos_symbol_info *symbol;
79
80         if (mask != 0x3F)
81                 return false;
82
83         for (symbol = tos_symbol_names; symbol->name != NULL; ++symbol)
84                 if (value == symbol->value) {
85                         printf("%s%s ", prefix, symbol->name);
86                         return true;
87                 }
88
89         return false;
90 }