1
0

download-macs.sh 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. #!/bin/bash
  2. set -o pipefail
  3. # Целевой файл
  4. TARGET_FILE="/opt/Eye/scripts/utils/mac-oids/manuf.csv"
  5. BACKUP_FILE="/opt/Eye/scripts/utils/mac-oids/manuf.csv.backup"
  6. # Perl скрипт для преобразования формата oui.txt в CSV
  7. convert_oui_to_csv() {
  8. local input_file="$1"
  9. local output_file="$2"
  10. perl -e '
  11. use strict;
  12. use warnings;
  13. my $in_block = 0;
  14. my $hex_code = "";
  15. my $company_name = "";
  16. my @address_lines = ();
  17. my $block_count = 0;
  18. open(my $out, ">", $ARGV[1]) or die "Cannot open output file: $!";
  19. open(my $in, "<", $ARGV[0]) or die "Cannot open input file: $ARGV[0]: $!";
  20. while (my $line = <$in>) {
  21. chomp $line;
  22. # Пропускаем заголовки
  23. next if $line =~ /^OUI\/MA-L/;
  24. next if $line =~ /^company_id/;
  25. next if $line =~ /^Address/;
  26. # Находим строку с hex-кодом (формат: XX-XX-XX (hex) Company Name)
  27. if ($line =~ /^([0-9A-F]{2}-[0-9A-F]{2}-[0-9A-F]{2})\s+\(hex\)\s+(.+)$/) {
  28. save_block() if $in_block && $hex_code && $company_name;
  29. $in_block = 1;
  30. $hex_code = $1;
  31. $company_name = $2;
  32. @address_lines = ();
  33. next;
  34. }
  35. # Находим base16 строку (формат: XXXXXX (base 16) Company Name)
  36. if ($line =~ /^([0-9A-F]{6})\s+\(base 16\)\s+(.+)$/) {
  37. if (!$hex_code) {
  38. my $hex_part = $1;
  39. $hex_code = substr($hex_part, 0, 2) . "-" . substr($hex_part, 2, 2) . "-" . substr($hex_part, 4, 2);
  40. $company_name = $2;
  41. $in_block = 1;
  42. @address_lines = ();
  43. }
  44. next;
  45. }
  46. # Если мы внутри блока и строка не пустая и не начинается с заглавной буквы или цифры (новый блок)
  47. if ($in_block && $line =~ /\S/ && $line !~ /^[A-Z]/ && $line !~ /^[0-9]/) {
  48. push @address_lines, $line;
  49. next;
  50. }
  51. # Конец блока (пустая строка или начало нового блока)
  52. if ($line =~ /^\s*$/ || $line =~ /^[A-Z]/ || $line =~ /^[0-9]/) {
  53. save_block() if $in_block && $hex_code && $company_name;
  54. $in_block = 0;
  55. $hex_code = "";
  56. $company_name = "";
  57. @address_lines = ();
  58. next;
  59. }
  60. }
  61. save_block() if $in_block && $hex_code && $company_name;
  62. close $in;
  63. close $out;
  64. print STDERR "Processed blocks: $block_count\n";
  65. sub save_block {
  66. $block_count++;
  67. # Форматируем MAC адрес
  68. $hex_code =~ s/-/:/g;
  69. # Формируем EXT INFO из адресных строк
  70. my $ext_info = "";
  71. if (@address_lines) {
  72. $ext_info = join(", ", @address_lines);
  73. }
  74. # Очищаем поля
  75. $company_name =~ s/\s+/ /g;
  76. $company_name =~ s/^\s+|\s+$//g;
  77. $company_name =~ s/"/'\''/g;
  78. $ext_info =~ s/\s+/ /g;
  79. $ext_info =~ s/^\s+|\s+$//g;
  80. $ext_info =~ s/"/'\''/g;
  81. # Выводим в формате: MAC Prefix; Org; EXT INFO
  82. print $out "$hex_code;$company_name;$ext_info\n";
  83. # Сбрасываем переменные
  84. $hex_code = "";
  85. $company_name = "";
  86. @address_lines = ();
  87. $in_block = 0;
  88. }
  89. ' "$input_file" "$output_file"
  90. return $?
  91. }
  92. # Perl скрипт для обработки IEEE CSV файлов
  93. convert_ieee_csv() {
  94. local input_file="$1"
  95. local output_file="$2"
  96. perl -e '
  97. use strict;
  98. use warnings;
  99. use Text::ParseWords;
  100. open(my $out, ">>", $ARGV[1]) or die "Cannot open output file: $!";
  101. open(my $in, "<", $ARGV[0]) or do {
  102. warn "Cannot open input file: $ARGV[0]: $!";
  103. exit 0;
  104. };
  105. my $line_count = 0;
  106. while (my $line = <$in>) {
  107. $line_count++;
  108. next if $line_count == 1; # Пропускаем заголовок
  109. chomp $line;
  110. # Разбираем CSV с учетом кавычек
  111. my @fields = parse_line(",", 0, $line);
  112. next unless @fields >= 4;
  113. my ($registry, $assignment, $org_name, $org_address) =
  114. (defined $fields[0] ? $fields[0] : "",
  115. defined $fields[1] ? $fields[1] : "",
  116. defined $fields[2] ? $fields[2] : "",
  117. defined $fields[3] ? $fields[3] : "");
  118. next if $assignment eq "" || $org_name eq "";
  119. # Форматируем MAC адрес
  120. $assignment =~ s/-/:/g;
  121. # Очищаем поля
  122. $org_name =~ s/^\s+|\s+$//g;
  123. $org_name =~ s/\s+/ /g;
  124. $org_name =~ s/"/'\''/g;
  125. $org_address =~ s/^\s+|\s+$//g if defined $org_address;
  126. $org_address = "" unless defined $org_address;
  127. $org_address =~ s/"/'\''/g;
  128. # Выводим
  129. print $out "$assignment;$org_name;$org_address\n";
  130. }
  131. close $in;
  132. close $out;
  133. print STDERR "Processed IEEE records: " . ($line_count - 1) . "\n";
  134. ' "$input_file" "$output_file"
  135. return $?
  136. }
  137. # Функция для загрузки с Wireshark (тоже нужно адаптировать формат)
  138. download_from_wireshark() {
  139. echo "Пробуем скачать данные с Wireshark..."
  140. TEMP_FILE=$(mktemp)
  141. if wget -q -O - https://www.wireshark.org/download/automated/data/manuf 2>/dev/null | \
  142. perl -e '
  143. use strict;
  144. use warnings;
  145. while (my $line = <STDIN>) {
  146. chomp $line;
  147. # Пропускаем комментарии и пустые строки
  148. next if $line =~ /^#/;
  149. next if $line =~ /^\s*$/;
  150. # Формат Wireshark: MAC\tVendor\tComment
  151. my ($mac, $vendor, $comment) = split(/\t/, $line);
  152. # Очищаем MAC адрес (убираем 00:00:00/... если есть)
  153. $mac =~ s/\/.*$//;
  154. $mac =~ s/00:00:00//;
  155. $mac =~ s/^\s+|\s+$//g;
  156. next if $mac eq "";
  157. # Очищаем vendor
  158. $vendor = "" unless defined $vendor;
  159. $vendor =~ s/^\s+|\s+$//g;
  160. $vendor =~ s/"/'\''/g;
  161. # Очищаем comment
  162. $comment = "" unless defined $comment;
  163. $comment =~ s/^\s+|\s+$//g;
  164. $comment =~ s/"/'\''/g;
  165. # Выводим
  166. print "$mac;$vendor;$comment\n";
  167. }
  168. ' > "$TEMP_FILE"
  169. then
  170. if [[ -s "$TEMP_FILE" ]]; then
  171. echo "Данные успешно загружены с Wireshark"
  172. cat "$TEMP_FILE" > "$TARGET_FILE"
  173. rm -f "$TEMP_FILE"
  174. return 0
  175. else
  176. echo "Скачанный файл пуст"
  177. rm -f "$TEMP_FILE"
  178. fi
  179. else
  180. echo "Ошибка загрузки с Wireshark"
  181. rm -f "$TEMP_FILE"
  182. fi
  183. return 1
  184. }
  185. # Функция для проверки и использования альтернативных источников
  186. use_alternative_sources() {
  187. echo "Пробуем альтернативные источники..."
  188. local alternative_sources=(
  189. "/usr/share/hwdata/oui.txt"
  190. "/usr/share/ieee-data/oui.txt"
  191. "/var/lib/ieee-data/oui.txt"
  192. )
  193. for source in "${alternative_sources[@]}"; do
  194. if [[ -f "$source" ]]; then
  195. echo "Найден файл: $source"
  196. echo "Конвертируем формат..."
  197. TEMP_FILE=$(mktemp)
  198. if convert_oui_to_csv "$source" "$TEMP_FILE"; then
  199. if [[ -s "$TEMP_FILE" ]]; then
  200. echo "Конвертация успешна, копируем в $TARGET_FILE"
  201. mv -f "$TEMP_FILE" "$TARGET_FILE"
  202. # Добавляем заголовок
  203. echo "MAC Prefix;Org;EXT INFO" | cat - "$TARGET_FILE" > "${TARGET_FILE}.tmp"
  204. mv -f "${TARGET_FILE}.tmp" "$TARGET_FILE"
  205. echo "Использован файл: $source"
  206. return 0
  207. else
  208. echo "Конвертированный файл пуст"
  209. rm -f "$TEMP_FILE"
  210. fi
  211. else
  212. echo "Ошибка конвертации файла: $source"
  213. rm -f "$TEMP_FILE"
  214. fi
  215. fi
  216. done
  217. echo "Пробуем скачать данные с IEEE..."
  218. IEEE_SOURCES=(
  219. "http://standards-oui.ieee.org/cid/cid.csv"
  220. "http://standards-oui.ieee.org/iab/iab.csv"
  221. "http://standards-oui.ieee.org/oui/oui.csv"
  222. "http://standards-oui.ieee.org/oui28/mam.csv"
  223. "http://standards-oui.ieee.org/oui36/oui36.csv"
  224. )
  225. TEMP_COMBINED=$(mktemp)
  226. for ieee_url in "${IEEE_SOURCES[@]}"; do
  227. echo "Скачиваем: $ieee_url"
  228. TEMP_FILE=$(mktemp)
  229. if wget -q -O "$TEMP_FILE" "$ieee_url" 2>/dev/null; then
  230. if convert_ieee_csv "$TEMP_FILE" "$TEMP_COMBINED"; then
  231. echo " OK"
  232. else
  233. echo " Ошибка обработки"
  234. fi
  235. else
  236. echo " Ошибка загрузки"
  237. fi
  238. rm -f "$TEMP_FILE"
  239. done
  240. if [[ -s "$TEMP_COMBINED" ]]; then
  241. echo "Объединяем и сортируем данные IEEE..."
  242. sort -u "$TEMP_COMBINED" > "$TARGET_FILE"
  243. rm -f "$TEMP_COMBINED"
  244. # Добавляем заголовок
  245. echo "MAC Prefix;Org;EXT INFO" | cat - "$TARGET_FILE" > "${TARGET_FILE}.tmp"
  246. mv -f "${TARGET_FILE}.tmp" "$TARGET_FILE"
  247. echo "Данные IEEE успешно загружены"
  248. return 0
  249. fi
  250. rm -f "$TEMP_COMBINED"
  251. echo "Все альтернативные источники недоступны"
  252. return 1
  253. }
  254. # Основная логика
  255. if [[ -f "$TARGET_FILE" ]]; then
  256. cp -f "$TARGET_FILE" "$BACKUP_FILE"
  257. echo "Создана резервная копия: $BACKUP_FILE"
  258. fi
  259. # 1. пробуем Wireshark
  260. if download_from_wireshark; then
  261. echo "Данные успешно загружены с Wireshark"
  262. [ -e "$BACKUP_FILE" ] && rm -f "$BACKUP_FILE"
  263. echo "Готово"
  264. exit 0
  265. fi
  266. # 2. пробуем альтернативные источники
  267. if use_alternative_sources; then
  268. echo "Данные успешно получены из альтернативных источников"
  269. [ -e "$BACKUP_FILE" ] && rm -f "$BACKUP_FILE"
  270. echo "Готово"
  271. exit 0
  272. fi
  273. # 3. Если ничего не помогло
  274. echo "Не удалось получить данные о MAC-адресах"
  275. if [[ -f "$BACKUP_FILE" ]]; then
  276. echo "Восстанавливаем из резервной копии"
  277. cp -f "$BACKUP_FILE" "$TARGET_FILE"
  278. echo "Используем существующий файл"
  279. fi
  280. [ -e "$BACKUP_FILE" ] && rm -f "$BACKUP_FILE"
  281. echo "Готово"
  282. exit 1