Hello community, here is the log from the commit of package arpwatch-ethercodes for openSUSE:Factory checked in at 2020-11-10 13:46:54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/arpwatch-ethercodes (Old) and /work/SRC/openSUSE:Factory/.arpwatch-ethercodes.new.11331 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "arpwatch-ethercodes" Tue Nov 10 13:46:54 2020 rev:765 rq:847429 version:20201026_100149 Changes: -------- --- /work/SRC/openSUSE:Factory/arpwatch-ethercodes/arpwatch-ethercodes.changes 2016-04-12 19:34:28.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.arpwatch-ethercodes.new.11331/arpwatch-ethercodes.changes 2020-11-10 13:53:40.538824782 +0100 @@ -1,0 +2,17 @@ +Tue Nov 10 08:42:20 UTC 2020 - Johannes Segitz <jseg...@suse.com> + +- Removed URL for source0 as this causes issues with our bots + +------------------------------------------------------------------- +Mon Oct 26 10:14:43 UTC 2020 - Hans-Peter Jansen <h...@urpla.net> + +- Update to version 20201026_100149 + +------------------------------------------------------------------- +Wed Sep 26 09:51:54 UTC 2018 - Hans-Peter Jansen <h...@urpla.net> + +- supply a new python3 script, that fetches (in local builds) and + generates ethercodes.dat +- update to version 20180926_160344 + +------------------------------------------------------------------- @@ -4,0 +22,5 @@ + +------------------------------------------------------------------- +Fri Jun 19 12:54:32 UTC 2015 - lmue...@suse.com + +- merge oui data base from 2015-06-19 Old: ---- oui.txt New: ---- fetch_ethercodes.py oui.csv ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ arpwatch-ethercodes.spec ++++++ --- /var/tmp/diff_new_pack.kV8Pvu/_old 2020-11-10 13:53:41.834822332 +0100 +++ /var/tmp/diff_new_pack.kV8Pvu/_new 2020-11-10 13:53:41.834822332 +0100 @@ -1,7 +1,8 @@ # # spec file for package arpwatch-ethercodes # -# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2020 SUSE LLC +# Copyright (c) 2018 LISA GmbH, Bingen, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -12,43 +13,45 @@ # license that conforms to the Open Source Definition (Version 1.9) # published by the Open Source Initiative. -# Please submit bugfixes or comments via http://bugs.opensuse.org/ +# Please submit bugfixes or comments via https://bugs.opensuse.org/ # Name: arpwatch-ethercodes -Version: 2016.03.28 +Version: 20201026_100149 Release: 0 Summary: Ethercodes Data for arpwatch License: BSD-3-Clause Group: Productivity/Networking/Diagnostic -Url: http://standards.ieee.org/regauth/oui/ -Source0: http://standards.ieee.org/regauth/oui/oui.txt -BuildRequires: arpwatch-ethercodes-build -BuildRoot: %{_tmppath}/%{name}-%{version}-build +URL: https://standards.ieee.org/products-services/regauth/index.html +# can't use url as it's not stable and bots will decline submission. Update it +# from here: http://standards-oui.ieee.org/oui/oui.csv +Source0: oui.csv +Source1: fetch_ethercodes.py +BuildRequires: python3 BuildArch: noarch %description -OUI and company ID data as fetched from IEEE.org prepared for arpwatch. +Fetch OUI and company ID data from IEEE.org prepared for arpwatch. %prep +%setup -q -cT +cp -p %{SOURCE0} . +cp -p %{SOURCE1} . %build -pushd %{_datadir}/arpwatch -./massagevendor >${RPM_BUILD_DIR}/ethercodes.dat < %{SOURCE0} -popd -if [ ! -s ethercodes.dat ]; then - echo "File ethercodes.dat is empty!" - exit 1 -fi +# update oui.csv by executing +# python3 fetch_ethercodes.py -vvtp arpwatch-ethercodes.spec +# in a local build + +# (re)generate ethercodes.dat from oui.csv +python3 fetch_ethercodes.py -vvkt %install -mkdir -p \ - %{buildroot}/%{_datadir}/arpwatch -install -m 0444 ethercodes.dat %{buildroot}/%{_datadir}/arpwatch +install -Dm0444 ethercodes.dat %{buildroot}/%{_datadir}/arpwatch/ethercodes.dat %files -%defattr(-,root,root) -%{_datadir}/arpwatch +%dir %{_datadir}/arpwatch +%{_datadir}/arpwatch/ethercodes.dat %changelog ++++++ fetch_ethercodes.py ++++++ #! /usr/bin/env python3 """ Synopsis: Fetch and generate ethercodes data for arpwatch Usage: {appname} [-hVvfkt][-T sec][-O ouifile][-o outfile][-p spec] -h, --help this message -V, --version print version and exit -v, --verbose verbose mode (cumulative) -f, --force force operation -k, --keep keep existing {ouifile} -t, --timestamp print timestamp -T, --deltat sec tolerance in timestamp comparison (default: {deltat} sec.) -O, --ouifile file IEEE.org host (default: {ouifile}) -o, --outfile file arpwatch ethercodes (default: {outfile}) -p, --patch spec patch specfile with updated timestamp Description: Fetch current IEEE MA-L Assignments file (oui.csv) from IEEE.org, and generate ethercodes.dat for arpwatch consumption. Fetch oui.csv only, if the timestamp is newer (unless --force is given). Similar, generate ethercodes.dat only, if the timestamps don't match (again, unless --force is given). Use option --keep to (re)generate ethercodes.dat from an existing oui.csv. Patch replaces a pattern NNNNNNNN_NNNNNN with the current timestamp in the given file. Notes: The timestamps of oui.csv fluctuate in a 2 seconds range(!). Therefore compensate the fluctuation by taking a deltat tolerance factor into account. Copyright: (c)2018 by {author} {email} License: {license} """ # # vim:set et ts=8 sw=4: # __version__ = '0.3' __author__ = 'Hans-Peter Jansen' __email__ = '<h...@urpla.net>' __license__ = 'MIT' import os import re import csv import sys import time import getopt import traceback import email.utils import urllib.error import urllib.parse import urllib.request # avoid encoding issues with print() in locale-less environments os.environ["PYTHONIOENCODING"] = "utf-8" class gpar: """ global parameter class """ appdir, appname = os.path.split(sys.argv[0]) if appdir == '.': appdir = os.getcwd() pid = os.getpid() version = __version__ author = __author__ email = __email__ license = __license__ loglevel = 0 force = False keep = False timestamp = False deltat = 2.5 ouifile = 'http://standards-oui.ieee.org/oui/oui.csv' outfile = 'ethercodes.dat' patchfile = None def vout(lvl, msg): if lvl <= gpar.loglevel: print((msg).format(**gpar.__dict__), file = sys.stdout, flush = True) stderr = lambda *msg: print(*msg, file = sys.stderr, flush = True) def exit(ret = 0, msg = None, usage = False): """ terminate process with optional message and usage """ if msg: stderr('{}: {}'.format(gpar.appname, msg)) if usage: stderr(__doc__.format(**gpar.__dict__)) sys.exit(ret) def cmp_ts(t1, t2): """ compare timestamps while taking a global tolerance factor into account return True, if timestamps match """ return abs(t1 - t2) < gpar.deltat hex = lambda x: int(x, 16) hexstr = lambda h: format(h, 'x') def code_key(val): """ return the colon formated code key, if val is an exact 24 byte hexadecimal string, and None otherwise 000000 -> 0:0:0 ABCDEF -> ab:cd:ef """ if len(val) == 6: return ':'.join((map(hexstr, map(hex, (val[:2], val[2:4], val[4:]))))) def fetch_infile(infile): # check oui.csv parameter vout(1, 'check {ouifile}') req = urllib.request.urlopen(gpar.ouifile) vout(3, 'header info: {}'.format(req.info())) header = req.info() ouisize = int(header['Content-Length']) vout(1, 'oui file size: {}'.format(ouisize)) ouidate = header['Last-Modified'] vout(1, 'oui file date: {}'.format(ouidate)) ouidate = email.utils.parsedate(ouidate) ouitime = time.mktime(ouidate) vout(3, 'parsed oui file date: {} ({})'.format( time.asctime(ouidate), ouitime)) # check, if local oui.csv is outdated fetchoui = False if gpar.force: fetchoui = True elif not os.path.exists(infile): vout(1, 'no local file {infile} found') fetchoui = True elif os.path.getsize(infile) != ouisize: vout(1, 'local file size differs: {} vs. {} remote'.format( os.path.getsize(infile), ouisize)) fetchoui = True elif not cmp_ts(os.stat(infile).st_mtime, ouitime): vout(3, str(os.stat(infile).st_mtime)) vout(3, str(ouitime)) mtime = time.localtime(os.stat(infile).st_mtime) otime = time.localtime(ouitime) vout(1, 'local file date differs: {} vs. {} remote'.format( time.asctime(mtime), time.asctime(otime))) fetchoui = True # fetch oui.csv if fetchoui: vout(1, 'fetch {ouifile}') open(infile, 'wb').write(req.read()) os.utime(infile, (ouitime, ouitime)) return ouidate def parse_csv(infile): vout(1, 'parse {infile}') codes = {} with open(infile, newline = '', encoding = 'utf-8') as f: reader = csv.reader(f) for row in reader: vout(3, str(row)) # generate code = code_key(row[1]) if code: if code in codes and codes[code] != row[2]: vout(1, 'value {} exists already: "{}", "{}"'.format( code, codes[code], row[2])) else: codes[code] = row[2] return codes def patch_file(patchfile, timestamp): vout(1, 'patch {}'.format(patchfile)) with open(patchfile, 'r+', encoding = 'utf-8') as f: content = f.read() patched, count = re.subn('\d{8}_\d{6}', timestamp, content) if count and content != patched: f.seek(0) f.write(patched) vout(1, '{} occurances replaced in {}'.format(count, patchfile)) else: vout(1, '{} unchanged'.format(patchfile)) def fetch_ethercodes(): # extract file argument from URL gpar.infile = os.path.basename(urllib.parse.urlparse(gpar.ouifile).path) # default: oui.csv infile = gpar.infile # default: ethercodes.dat outfile = gpar.outfile if gpar.keep: if os.path.exists(infile): # force generation of ethercodes.dat from existing oui.csv gpar.force = True ouidate = time.localtime(os.stat(infile).st_mtime) else: exit(1, 'keep option selected, but no {infile}') else: ouidate = fetch_infile(infile) ouitime = time.mktime(ouidate) # check, if ethercodes.dat is outdated gencodes = False if gpar.force: gencodes = True elif not os.path.exists(outfile): vout(1, 'no local file {} found'.format(outfile)) gencodes = True elif not cmp_ts(os.stat(outfile).st_mtime, ouitime): vout(3, str(os.stat(outfile).st_mtime)) vout(3, str(ouitime)) mtime = time.localtime(os.stat(outfile).st_mtime) otime = time.localtime(ouitime) vout(2, 'local file date differs: {} vs. {} remote'.format( time.asctime(mtime), time.asctime(otime))) gencodes = True # generate ethercodes.dat if gencodes: codes = parse_csv(infile) gpar.nrcodes = len(codes) vout(1, 'generate {outfile} with {nrcodes} entries') with open(outfile, 'w', newline = '', encoding = 'utf-8') as f: for key in sorted(codes.keys()): f.write('%s\t%s\n' % (key, codes[key])) os.utime(outfile, (ouitime, ouitime)) vout(1, 'successful') else: vout(1, 'code file {outfile} up to date already') timestamp = time.strftime('%Y%m%d_%H%M%S', ouidate) if gpar.timestamp: vout(0, 'timestamp: {}'.format(timestamp)) if gpar.patchfile is not None: patch_file(gpar.patchfile, timestamp) return 0 def main(argv = None): if argv is None: argv = sys.argv[1:] # yeah, oldschool, I know... try: optlist, args = getopt.getopt(argv, 'hVvfktT:O:o:p:', ('help', 'version', 'verbose', 'force', 'keep', 'timestamp', 'deltat', 'ouifile', 'outfile', 'patch') ) except getopt.error as msg: exit(1, msg, True) for opt, par in optlist: if opt in ('-h', '--help'): exit(usage = True) elif opt in ('-V', '--version'): exit(msg = 'version %s' % gpar.version) elif opt in ('-v', '--verbose'): gpar.loglevel += 1 elif opt in ('-f', '--force'): gpar.force = True elif opt in ('-k', '--keep'): gpar.keep = True elif opt in ('-t', '--timestamp'): gpar.timestamp = True elif opt in ('-T', '--deltat'): gpar.deltat = par elif opt in ('-O', '--ouifile'): gpar.ouifile = par elif opt in ('-o', '--outfile'): gpar.outfile = par elif opt in ('-p', '--patch'): gpar.patchfile = par try: fetch_ethercodes() except Exception: exit(2, 'unexpected exception occured:\n%s' % traceback.format_exc()) if __name__ == '__main__': sys.exit(main()) ++++++ oui.csv ++++++ ++++ 28784 lines (skipped)