Revert "smart gateway: install default speed configuration file"
[olsrd.git] / src / gatewaySpeedFile.c
1 #include "gatewaySpeedFile.h"
2
3 #include "log.h"
4 #include <regex.h>
5 #include <sys/stat.h>
6
7 #define LINE_LENGTH 256
8
9 static const char * regexCommentString = "^([[:space:]]*|[[:space:]#]+.*)$";
10 static const char * regexNameValueString =
11                 "^[[:space:]]*([^[:space:]]+)[[:space:]]*=[[:space:]]*([[:digit:]]+)[[:space:]]*$";
12 static const size_t regexNameValuematchCount = 3;
13
14 static regex_t regexComment;
15 static regex_t regexNameValue;
16 static bool started = false;
17
18 typedef struct _CachedStat {
19         struct timespec st_mtim; /* Time of last modification.  */
20 } CachedStat;
21
22 static CachedStat cachedStat;
23
24 /**
25  Read an unsigned long number from a value string
26
27  @param valueName
28  the name of the value
29  @param value
30  the string to convert to a number
31  @param valueNumber
32  a pointer to the location where to store the number upon successful conversion
33
34  @return
35  - true on success
36  - false otherwise
37  */
38 static bool readUL(const char * valueName, const char * value, unsigned long * valueNumber) {
39         char * endPtr = NULL;
40         unsigned long valueNew;
41
42         errno = 0;
43         valueNew = strtoul(value, &endPtr, 10);
44
45         if (!((endPtr != value) && (*value != '\0') && (*endPtr == '\0'))) {
46                 /* invalid conversion */
47                 olsr_syslog(OLSR_LOG_ERR, "Configured %s (%s) could not be converted to a number: %s\n", valueName, value,
48                                 strerror(errno));
49                 return false;
50         }
51
52         *valueNumber = valueNew;
53
54         return true;
55 }
56
57 bool startGatewaySpeedFile(void) {
58         if (started) {
59                 return true;
60         }
61
62         if (regcomp(&regexComment, regexCommentString, REG_EXTENDED)) {
63                 olsr_printf(0, "Could not compile regex \"%s\"\n", regexCommentString);
64                 return false;
65         }
66
67         if (regcomp(&regexNameValue, regexNameValueString, REG_EXTENDED)) {
68                 olsr_printf(0, "Could not compile regex \"%s\"\n", regexNameValueString);
69                 return false;
70         }
71
72         cachedStat.st_mtim.tv_sec = -1;
73         cachedStat.st_mtim.tv_nsec = -1;
74
75         started = true;
76         return true;
77 }
78
79 void stopGatewaySpeedFile(void) {
80         if (started) {
81                 regfree(&regexNameValue);
82                 regfree(&regexComment);
83                 started = false;
84         }
85 }
86
87 static bool regexMatch(regex_t * regex, char * line, size_t nmatch, regmatch_t pmatch[]) {
88         int result = regexec(regex, line, nmatch, pmatch, 0);
89         if (!result) {
90                 return true;
91         }
92
93         if (result == REG_NOMATCH) {
94                 return false;
95         }
96
97         {
98                 char msgbuf[256];
99                 regerror(result, regex, msgbuf, sizeof(msgbuf));
100                 olsr_syslog(OLSR_LOG_ERR, "Regex match failed: %s\n", msgbuf);
101         }
102
103         return false;
104 }
105
106 static char line[LINE_LENGTH];
107
108 void readGatewaySpeedFile(char * fileName) {
109         struct stat statBuf;
110         FILE * fd = NULL;
111         unsigned int lineNumber = 0;
112         char * name = NULL;
113         char * value = NULL;
114         unsigned long uplink = DEF_UPLINK_SPEED;
115         unsigned long downlink = DEF_DOWNLINK_SPEED;
116         bool uplinkSet = false;
117         bool downlinkSet = false;
118
119         if (stat(fileName, &statBuf)) {
120                 /* could not access the file */
121                 goto out;
122         }
123
124         if (!memcmp(&cachedStat.st_mtim, &statBuf.st_mtim, sizeof(cachedStat.st_mtim))) {
125                 /* file did not change since last read */
126                 goto out;
127         }
128
129         fd = fopen(fileName, "r");
130         if (!fd) {
131                 goto out;
132         }
133
134         memcpy(&cachedStat.st_mtim, &statBuf.st_mtim, sizeof(cachedStat.st_mtim));
135
136         while (fgets(line, LINE_LENGTH, fd)) {
137                 regmatch_t pmatch[regexNameValuematchCount];
138
139                 lineNumber++;
140
141                 if (regexMatch(&regexComment, line, 0, NULL)) {
142                         continue;
143                 }
144
145                 if (!regexMatch(&regexNameValue, line, regexNameValuematchCount, pmatch)) {
146                         olsr_syslog(OLSR_LOG_ERR, "Gateway speed file \"%s\", line %d uses invalid syntax: %s\n", fileName, lineNumber,
147                                         line);
148                         goto out;
149                 }
150
151                 /* copy name/value */
152                 name = &line[pmatch[1].rm_so];
153                 line[pmatch[1].rm_eo] = '\0';
154                 value = &line[pmatch[2].rm_so];
155                 line[pmatch[2].rm_eo] = '\0';
156
157                 if (!strncasecmp(GATEWAY_SPEED_UPLINK, name, sizeof(line))) {
158                         if (!readUL(GATEWAY_SPEED_UPLINK, value, &uplink)) {
159                                 goto out;
160                         }
161                         uplinkSet = true;
162                 } else if (!strncasecmp(GATEWAY_SPEED_DOWNLINK, name, sizeof(line))) {
163                         if (!readUL(GATEWAY_SPEED_DOWNLINK, value, &downlink)) {
164                                 goto out;
165                         }
166                         downlinkSet = true;
167                 } else {
168                         olsr_syslog(OLSR_LOG_ERR, "Gateway speed file \"%s\", line %d uses an invalid option \"%s\","
169                                         " valid options are [%s|%s]\n", fileName, lineNumber, name, GATEWAY_SPEED_UPLINK,
170                                         GATEWAY_SPEED_DOWNLINK);
171                         goto out;
172                 }
173         }
174
175         fclose(fd);
176
177         if (uplinkSet) {
178                 olsr_cnf->smart_gw_uplink = uplink;
179         }
180         if (downlinkSet) {
181                 olsr_cnf->smart_gw_downlink = downlink;
182         }
183
184         out: return;
185 }