|
1 | | -#include <dirent.h> |
2 | 1 | #include <stdlib.h> |
| 2 | +#include <stdbool.h> |
3 | 3 | #include <sys/types.h> |
4 | 4 | #include <sys/stat.h> |
5 | 5 | #include <stdio.h> |
6 | 6 | #include <string.h> |
7 | 7 | #include <regex.h> |
| 8 | +#include <libudev.h> |
8 | 9 | #include "prio.h" |
9 | 10 | #include "debug.h" |
10 | 11 | #include <unistd.h> |
|
20 | 21 | // prio "iet" |
21 | 22 | // prio_args "preferredip=10.11.12.13" |
22 | 23 | // |
23 | | -// Uses /dev/disk/by-path to find the IP of the device. |
24 | 24 | // Assigns prio 20 (high) to the preferred IP and prio 10 (low) to the rest. |
25 | 25 | // |
26 | 26 | // by Olivier Lambert <lambert.olivier.gmail.com> |
27 | 27 | // |
28 | 28 |
|
29 | | -#define dc_log(prio, msg) condlog(prio, "%s: iet prio: " msg, dev) |
| 29 | +#define dc_log(prio, msg) condlog(prio, "%s: iet prio: " msg, sysname) |
| 30 | + |
30 | 31 | // |
31 | 32 | // name: find_regex |
32 | 33 | // @param string: string you want to search into |
33 | 34 | // @param regex: the pattern used |
34 | 35 | // @return result: string found in string with regex, "none" if none |
35 | | -char *find_regex(char * string, char * regex) |
| 36 | +char *find_regex(const char *string, const char *regex) |
36 | 37 | { |
37 | 38 | int err; |
38 | 39 | regex_t preg; |
@@ -73,75 +74,64 @@ char *find_regex(char * string, char * regex) |
73 | 74 | // name: inet_prio |
74 | 75 | // @param |
75 | 76 | // @return prio |
76 | | -int iet_prio(const char *dev, char * args) |
| 77 | +int iet_prio(struct udev_device *udev, char *args) |
77 | 78 | { |
78 | 79 | char preferredip_buff[255] = ""; |
79 | 80 | char *preferredip = &preferredip_buff[0]; |
| 81 | + const char *by_path; |
| 82 | + char *ip; |
| 83 | + static bool arg_logged = false; |
| 84 | + int prio = 10; |
| 85 | + const char *sysname; |
| 86 | + |
| 87 | + if (!udev) |
| 88 | + return 0; |
| 89 | + sysname = udev_device_get_sysname(udev); |
| 90 | + if (!sysname) |
| 91 | + sysname = "UNKNOWN"; |
| 92 | + |
80 | 93 | // Phase 1 : checks. If anyone fails, return prio 0. |
81 | 94 | // check if args exists |
82 | 95 | if (!args) { |
83 | | - dc_log(0, "need prio_args with preferredip set"); |
| 96 | + if (!arg_logged) { |
| 97 | + dc_log(2, "need prio_args with preferredip set"); |
| 98 | + arg_logged = true; |
| 99 | + } |
84 | 100 | return 0; |
85 | 101 | } |
86 | 102 | // check if args format is OK |
87 | | - if (sscanf(args, "preferredip=%254s", preferredip) == 1) { |
88 | | - } else { |
89 | | - dc_log(0, "unexpected prio_args format"); |
| 103 | + if (sscanf(args, "preferredip=%254s", preferredip) != 1) { |
| 104 | + if (!arg_logged) { |
| 105 | + dc_log(2, "unexpected prio_args format"); |
| 106 | + arg_logged = true; |
| 107 | + } |
90 | 108 | return 0; |
91 | 109 | } |
92 | 110 | // check if ip is not too short |
93 | 111 | if (strlen(preferredip) <= 7) { |
94 | | - dc_log(0, "prio args: preferredip too short"); |
| 112 | + if (!arg_logged) { |
| 113 | + dc_log(2, "prio args: preferredip too short"); |
| 114 | + arg_logged = true; |
| 115 | + } |
95 | 116 | return 0; |
96 | 117 | } |
97 | | - // Phase 2 : find device in /dev/disk/by-path to match device/ip |
98 | | - DIR *dir_p; |
99 | | - struct dirent *dir_entry_p; |
100 | | - enum { BUFFERSIZE = 1024 }; |
101 | | - char buffer[BUFFERSIZE]; |
102 | | - char fullpath[BUFFERSIZE] = "/dev/disk/by-path/"; |
103 | | - dir_p = opendir(fullpath); |
104 | | - if (!dir_p) |
105 | | - goto out; |
106 | 118 |
|
107 | | - // loop to find device in /dev/disk/by-path |
108 | | - while( NULL != (dir_entry_p = readdir(dir_p))) { |
109 | | - if (dir_entry_p->d_name[0] != '.') { |
110 | | - char path[BUFFERSIZE] = "/dev/disk/by-path/"; |
111 | | - strcat(path,dir_entry_p->d_name); |
112 | | - ssize_t nchars = readlink(path, buffer, sizeof(buffer)-1); |
113 | | - if (nchars != -1) { |
114 | | - char *device; |
115 | | - buffer[nchars] = '\0'; |
116 | | - device = find_regex(buffer,"(sd[a-z]+)"); |
117 | | - // if device parsed is the right one |
118 | | - if (device!=NULL && strncmp(device, dev, strlen(device)) == 0) { |
119 | | - char *ip; |
120 | | - ip = find_regex(dir_entry_p->d_name,"([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})"); |
121 | | - // if prefferedip and ip fetched matches |
122 | | - if (ip!=NULL && strncmp(ip, preferredip, strlen(ip)) == 0) { |
123 | | - // high prio |
124 | | - free(ip); |
125 | | - free(device); |
126 | | - closedir(dir_p); |
127 | | - return 20; |
128 | | - } |
129 | | - free(ip); |
130 | | - } |
131 | | - free(device); |
132 | | - } |
133 | | - else { |
134 | | - printf("error\n"); |
135 | | - } |
136 | | - } |
| 119 | + by_path = udev_device_get_property_value(udev, "ID_PATH"); |
| 120 | + if (by_path == NULL) { |
| 121 | + dc_log(2, "failed to get BY_PATH property"); |
| 122 | + return 0; |
137 | 123 | } |
138 | | - // nothing found, low prio |
139 | | - closedir(dir_p); |
140 | | -out: |
141 | | - return 10; |
| 124 | + condlog(3, "%s: iet prio: by_path=%s", sysname, by_path); |
| 125 | + ip = find_regex(by_path, |
| 126 | + "([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})"); |
| 127 | + if (ip != NULL && strncmp(ip, preferredip, strlen(ip)) == 0) |
| 128 | + prio = 20; |
| 129 | + |
| 130 | + free(ip); |
| 131 | + return prio; |
142 | 132 | } |
143 | 133 |
|
144 | 134 | int getprio(struct path * pp, char * args) |
145 | 135 | { |
146 | | - return iet_prio(pp->dev, args); |
| 136 | + return iet_prio(pp->udev, args); |
147 | 137 | } |
0 commit comments