Add detection of the ovpn kernel module type: if a backported
(out-of-tree) version is loaded, the MODULE_VERSION string is read from
sysfs; otherwise, for the in-tree module, the function reports the
kernel release and version.
Change-Id: I7fc033a7ffee73045316763356a95d75ef23f5ad
Signed-off-by: Ralf Lici <ralf@mandelbit.com>
Acked-by: Gert Doering <gert@greenie.muc.de>
Message-Id: <20250515150038.30097-1-gert@greenie.muc.de>
URL: https://www.mail-archive.com/openvpn-devel@lists.sourceforge.net/msg31652.html
Signed-off-by: Gert Doering <gert@greenie.muc.de>
| ... | ... |
@@ -1117,10 +1117,77 @@ dco_available(int msglevel) |
| 1117 | 1117 |
return true; |
| 1118 | 1118 |
} |
| 1119 | 1119 |
|
| 1120 |
+/** |
|
| 1121 |
+ * There's no version indicator in the ovpn in-tree module, so we return a |
|
| 1122 |
+ * string containing info about the kernel version and release. |
|
| 1123 |
+ */ |
|
| 1124 |
+static const char * |
|
| 1125 |
+dco_version_string_in_tree(struct gc_arena *gc) |
|
| 1126 |
+{
|
|
| 1127 |
+ struct buffer buf = alloc_buf_gc(256, gc); |
|
| 1128 |
+ struct utsname system; |
|
| 1129 |
+ |
|
| 1130 |
+ if (uname(&system)) |
|
| 1131 |
+ {
|
|
| 1132 |
+ return "ERR"; |
|
| 1133 |
+ } |
|
| 1134 |
+ |
|
| 1135 |
+ buf_puts(&buf, system.release); |
|
| 1136 |
+ buf_puts(&buf, " "); |
|
| 1137 |
+ buf_puts(&buf, system.version); |
|
| 1138 |
+ return BSTR(&buf); |
|
| 1139 |
+} |
|
| 1140 |
+ |
|
| 1141 |
+/** |
|
| 1142 |
+ * When the module is loaded, the backports version of ovpn has a version file |
|
| 1143 |
+ * in sysfs. Read it and return the string. |
|
| 1144 |
+ * |
|
| 1145 |
+ * The caller is responsible for closing the file pointer. |
|
| 1146 |
+ */ |
|
| 1147 |
+static const char * |
|
| 1148 |
+dco_version_string_backports(FILE *fp, struct gc_arena *gc) |
|
| 1149 |
+{
|
|
| 1150 |
+ char *str = gc_malloc(PATH_MAX, false, gc); |
|
| 1151 |
+ |
|
| 1152 |
+ if (!fgets(str, PATH_MAX, fp)) |
|
| 1153 |
+ {
|
|
| 1154 |
+ return "ERR"; |
|
| 1155 |
+ } |
|
| 1156 |
+ |
|
| 1157 |
+ /* remove potential newline at the end of the string */ |
|
| 1158 |
+ char *nl = strchr(str, '\n'); |
|
| 1159 |
+ if (nl) |
|
| 1160 |
+ {
|
|
| 1161 |
+ *nl = '\0'; |
|
| 1162 |
+ } |
|
| 1163 |
+ |
|
| 1164 |
+ return str; |
|
| 1165 |
+} |
|
| 1166 |
+ |
|
| 1120 | 1167 |
const char * |
| 1121 | 1168 |
dco_version_string(struct gc_arena *gc) |
| 1122 | 1169 |
{
|
| 1123 |
- return "Unknown"; |
|
| 1170 |
+ const char *version; |
|
| 1171 |
+ struct stat sb; |
|
| 1172 |
+ FILE *fp; |
|
| 1173 |
+ |
|
| 1174 |
+ if (stat("/sys/module/ovpn", &sb) != 0 || !S_ISDIR(sb.st_mode))
|
|
| 1175 |
+ {
|
|
| 1176 |
+ return "N/A"; |
|
| 1177 |
+ } |
|
| 1178 |
+ |
|
| 1179 |
+ /* now that we know for sure that the module is loaded, if there's no |
|
| 1180 |
+ * version file it means we're dealing with the in-tree version, otherwise |
|
| 1181 |
+ * it's backports */ |
|
| 1182 |
+ fp = fopen("/sys/module/ovpn/version", "r");
|
|
| 1183 |
+ if (!fp) |
|
| 1184 |
+ {
|
|
| 1185 |
+ return dco_version_string_in_tree(gc); |
|
| 1186 |
+ } |
|
| 1187 |
+ version = dco_version_string_backports(fp, gc); |
|
| 1188 |
+ |
|
| 1189 |
+ fclose(fp); |
|
| 1190 |
+ return version; |
|
| 1124 | 1191 |
} |
| 1125 | 1192 |
|
| 1126 | 1193 |
void |