Commit 4f92450a authored by ju xor's avatar ju xor

New upstream version 0.8.2

parent 06f87bc6
......@@ -5,13 +5,27 @@ python:
- '3.5'
before_install:
- sudo apt update && sudo apt install -y inkscape
- sudo apt update && sudo apt install -y inkscape libdbus-glib-1-dev
# - echo "Python diagnostic Information"
# - env
# - sudo dpkg -l|grep python|grep dev
# - 'which -a python'
# - python --version
# - python-config --includes
# - ls -l ~/virtualenv
install:
- pip install -r requirements_dev.txt
env:
global:
# The dbus-python maintainer hit these bugs on travis, see his comments on the
# travis bug report: https://github.com/travis-ci/travis-ci/issues/6530
# See https://github.com/mitya57/secretstorage/blob/2636a47b45aff51a21dfaf1cbd9f1f3c1347f7f4/.travis.yml for an example workaround
# This is also a known issue and filed on the python bugtracker: https://bugs.python.org/issue7352
- 'PYTHON_LIBS="-L$(python-config --prefix)/lib $(python-config --libs)"'
- PY_ENABLE_SHARD=0
- TOX_ENV=lint
- TOX_ENV=py27,stats
- TOX_ENV=py35,stats
- TOX_ENV=doc
......
......@@ -8,7 +8,7 @@ VERSION = $(shell sh version.sh)
DESTDIR =
THISFILE = $(lastword $(MAKEFILE_LIST))
PYTHON = python
PYTHON = python3
# GNU command variables
# see http://www.gnu.org/prep/standards/html_node/Command-Variables.html
......@@ -34,11 +34,13 @@ mandir = $(datarootdir)/man
man8dir = $(mandir)/man8
# for systemd
tmpfilesdir=$(prefix)/lib/tmpfiles.d
systemunitdir=$(prefix)/lib/systemd/system
tmpfilesdir=/usr/lib/tmpfiles.d
systemunitdir=/lib/systemd/system
# for systemd udev
networkdir=/lib/systemd/network
# for apparmor
apparmordir=$(sysconfdir)/apparmor.d
apparmordir=/etc/apparmor.d
srcdir = .
......@@ -48,6 +50,7 @@ SRC_DOC = README.md LICENSE
SRC_TMPFILES = tmpfiles.d/dhcpcanon.conf
SRC_UNITFILE = systemd/dhcpcanon.service
SRC_APPARMOR = apparmor.d/sbin.dhcpcanon
SRC_LINKFILE = systemd/network/90-dhcpcanon.link
SRC_ALL = $(SRC_SCRIPT) $(SRC_DOC) $(SRC_MAN8)
DST_MAN8 = $(SRC_MAN8)
......@@ -56,6 +59,7 @@ DST_DOC = $(SRC_DOC)
DST_TMPFILES = $(SRC_TMPFILES)
DST_UNITFILE = $(SRC_UNITFILE)
DST_APPARMOR = $(SRC_APPARMOR)
DST_LINKFILE = $(SRC_LINKFILE)
DST_ALL = $(DST_SCRIPT) $(DST_DOC) $(DST_MAN8)
TEST_PY = dhcpcanon-test.py
......@@ -66,17 +70,15 @@ install: all
@echo $@
mkdir -p $(DESTDIR)$(sbindir)
for i in $(DST_SCRIPT); do $(INSTALL_SCRIPT) "$$i" $(DESTDIR)$(sbindir); done
for i in $(DST_SCRIPT); do $(INSTALL_SCRIPT) "$$i" /sbin; done
mkdir -p $(DESTDIR)$(docdir)
for i in $(DST_DOC); do $(INSTALL_DATA) "$$i" $(DESTDIR)$(docdir); done
mkdir -p $(DESTDIR)$(man8dir)
for i in $(DST_MAN8); do $(INSTALL_DATA) "$$i" $(DESTDIR)$(man8dir); done
if [ -z $(DESTDIR) ]; then python setup.py install; else \
python setup.py install --root $(DESTDIR) \
--install-scripts=$(DESTDIR)$(sbindir); fi
$(PYTHON) setup.py install --record installed.txt $(if $(DESTDIR),--root=$(DESTDIR),--install-scripts=/sbin)
if [ -z $(WITH_SYSTEMD)]; then \
if [ -n "$(WITH_SYSTEMD)" ]; then \
adduser --system dhcpcanon; \
mkdir -p $(DESTDIR)$(systemunitdir); \
for i in $(DST_UNITFILE); do $(INSTALL_DATA) "$$i" $(DESTDIR)$(systemunitdir); done; \
......@@ -84,9 +86,16 @@ install: all
for i in $(DST_TMPFILES); do $(INSTALL_DATA) "$$i" $(DESTDIR)$(tmpfilesdir); done; \
systemctl enable $(DESTDIR)$(systemunitdir)/dhcpcanon.service; \
systemd-tmpfiles --create --root=$(DESTDIR)$(tmpfilesdir)/dhcpcanon.conf; \
systemctl start $(DESTDIR)$(systemunitdir)/dhcpcanon.service; \
systemctl status $(DESTDIR)$(systemunitdir)/dhcpcanon.service; \
fi
if [ -z $(WITH_APPARMOR)]; then \
if [ -n "$(WITH_SYSTEMD_UDEV)" ]; then \
mkdir -p $(DESTDIR)$(networkdir); \
for i in $(DST_LINKFILE); do $(INSTALL_DATA) "$$i" $(DESTDIR)$(networkdir); done; \
fi
if [ -n "$(WITH_APPARMOR)" ]; then \
mkdir -p $(DESTDIR)$(apparmordir); \
for i in $(DST_APPARMOR); do $(INSTALL_DATA) "$$i" $(DESTDIR)$(apparmordir); done; \
for i in $(DST_APPARMOR); do aa-complain $(DESTDIR)$(apparmordir)/"$$i"; done; \
......@@ -94,15 +103,16 @@ install: all
uninstall:
@echo $@
for i in $(notdir $(DST_SCRIPT)); do rm $(DESTDIR)$(sbindir)/"$$i"; done
for i in $(notdir $(DST_DOC)); do rm $(DESTDIR)$(docdir)/"$$i"; done
for i in $(notdir $(DST_MAN8)); do rm $(DESTDIR)$(man8dir)/"$$i"; done
for i in $(notdir $(DST_SCRIPT)); do rm -f $(DESTDIR)$(sbindir)/"$$i"; done
for i in $(notdir $(DST_DOC)); do rm -f $(DESTDIR)$(docdir)/"$$i"; done
for i in $(notdir $(DST_MAN8)); do rm -f $(DESTDIR)$(man8dir)/"$$i"; done
# it will only work in the case that the file has not been removed
cat installed.txt | xargs rm -rf
# systemd files
for i in $(notdir $(DST_UNITFILE)); do rm $(DESTDIR)$(systemunitdir)/"$$i"; done
for i in $(notdir $(DST_TMPFILES)); do rm $(DESTDIR)$(tmpfilesdir)/"$$i"; done
for i in $(notdir $(DST_APPARMOR)); do rm $(DESTDIR)$(apparmordir)/"$$i"; done
for i in $(notdir $(DST_UNITFILE)); do rm -f $(DESTDIR)$(systemunitdir)/"$$i"; done
for i in $(notdir $(DST_TMPFILES)); do rm -f $(DESTDIR)$(tmpfilesdir)/"$$i"; done
for i in $(notdir $(DST_APPARMOR)); do rm -f $(DESTDIR)$(apparmordir)/"$$i"; done
for i in $(notdir $(DST_LINKFILE)); do rm -f $(DESTDIR)$(networkdir)/"$$i"; done
clean:
python setup.py clean
......
......@@ -12,7 +12,7 @@ except ImportError:
from setuptools_scm import get_version
version = get_version()
except (ImportError, LookupError):
version = '0.7.2'
version = '0.8.2'
__version__ = version
__author__ = "juga"
......
......@@ -2,4 +2,4 @@
# vim:ts=4:sw=4:expandtab 2
# Copyright 2016, 2017 juga (juga at riseup dot net), MIT license.
version = "0.7.2"
version = "0.8.2"
......@@ -5,6 +5,7 @@
from __future__ import absolute_import, unicode_literals
import logging
import os
import subprocess
import attr
......@@ -33,14 +34,17 @@ class ClientScript(object):
def __attrs_post_init__(self, scriptfile=None, env=None):
"""."""
logger.debug('Modifying ClientScript obj after creating it.')
self.scriptname = scriptfile or SCRIPT_PATH
self.scriptname = self.scriptname or scriptfile or SCRIPT_PATH
if env is None:
self.env = dict.fromkeys(SCRIPT_ENV_KEYS, str(''))
else:
self.env = env
self.env['medium'] = str()
self.env['pid'] = str(os.getpid())
def script_init(self, lease, state, prefix='', medium=''):
"""Initialize environment to pass to the external script."""
logger.debug('self.scriptname %s', self.scriptname)
if self.scriptname is not None:
logger.debug('Modifying ClientScript obj, setting env.')
if isinstance(state, int):
......@@ -48,13 +52,13 @@ class ClientScript(object):
else:
reason = state
self.env['reason'] = str(reason)
self.env['medium'] = str(medium)
# self.env['client'] = str('dhcpcanon')
# self.env['pid'] = str(os.getpid())
self.env['medium'] = self.env.get('medium') or str(medium)
self.env['client'] = str('dhcpcanon')
self.env['pid'] = str(os.getpid())
for k in LEASEATTRS_SAMEAS_ENVKEYS:
self.env[k] = str(lease.__getattribute__(k))
for k, v in LEASEATTRS2ENVKEYS.items():
self.env[k] = str(lease.__getattribute__(v))
self.env[v] = str(lease.__getattribute__(k))
self.env.update(ENV_OPTIONS_REQ)
else:
logger.debug('There is not script path.')
......@@ -64,14 +68,13 @@ class ClientScript(object):
scriptname = self.scriptname or scriptname
if scriptname is not None:
env = self.env or env
logger.debug('Calling script %s', scriptname)
logger.debug('with env %s', env)
sp = None
logger.info('Calling script %s', scriptname)
logger.info('with env %s', env)
proc = subprocess.Popen([scriptname], env=env,
stderr=subprocess.STDOUT)
try:
sp = subprocess.check_output([scriptname],
stderr=subprocess.STDOUT, env=env)
except subprocess.CalledProcessError as e:
sp = e.output
logger.debug('sp err %s', sp)
return sp
return None
(stdout, stderr) = proc.communicate()
return True
except TypeError as e:
logger.error(e)
return False
......@@ -108,7 +108,7 @@ SCRIPT_ENV_KEYS = ['reason', 'medium', 'interface',
'new_broadcast_address', 'new_next_server',
'new_dhcp_server_id']
LEASEATTRS_SAMEAS_ENVKEYS = ['interface', 'reason']
LEASEATTRS_SAMEAS_ENVKEYS = ['interface'] # , 'reason']
# 'client', 'pid',
# these are not set as environment but put in lease file
# , 'rebind', 'renew', 'expiry'
......@@ -210,3 +210,4 @@ PID_PATH = '/var/run/dhcpcanon.pid'
LEASE_PATH = '/var/lib/dhcp/dhcpcanon.leases'
CONF_PATH = '/etc/dhcp/dhcpcanon.conf'
RESOLVCONF = '/sbin/resolvconf'
RESOLVCONF_ADMIN = '/usr/bin/resolvconf-admin'
#!/usr/bin/env python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# vim:ts=4:sw=4:expandtab 2
# Copyright 2016, 2017 juga (juga at riseup dot net), MIT license.
......@@ -8,6 +8,8 @@ import argparse
import logging
import logging.config
from lockfile.pidlockfile import (PIDLockFile, AlreadyLocked,
LockTimeout, LockFailed)
from scapy.config import conf
# in python3 this seems to be the only way to to disable:
......@@ -16,8 +18,7 @@ conf.logLevel = logging.ERROR
from . import __version__
from .conflog import LOGGING
from .constants import (CLIENT_PORT, SERVER_PORT, SCRIPT_PATH, LEASE_PATH,
CONF_PATH, PID_PATH)
from .constants import (CLIENT_PORT, SERVER_PORT, SCRIPT_PATH, PID_PATH)
from .dhcpcapfsm import DHCPCAPFSM
logging.config.dictConfig(LOGGING)
......@@ -31,8 +32,6 @@ def main():
parser.add_argument('-v', '--verbose',
help='Set logging level to debug',
action='store_true')
parser.add_argument('-l', '--lease', help='custom lease time',
default=None)
parser.add_argument('--version', action='version',
help='version',
version='%(prog)s ' + __version__)
......@@ -44,42 +43,20 @@ def main():
'-sf', metavar='script-file', nargs='?',
const=SCRIPT_PATH,
help='Path to the network configuration script invoked by '
'dhclient when it gets a lease. If unspecified, the '
'default /sbin/dhcpcanon-script is used. See '
'dhclient-script(8) for a description of this file.')
'dhcpcanon when it gets a lease. Without this option '
'dhcpcanon will configure the network by itself.'
'If unspecified, the '
'default /sbin/dhcpcanon-script is used, which is a copy of'
'dhclient-script(8) for a description of this file.'
'If dhcpcanon is running with NetworkManager, it will'
'be called with the script nm-dhcp-helper.')
parser.add_argument(
'-pf', metavar='pid-file', nargs='?',
const=PID_PATH,
help='Path to the process ID file. If unspecified, the'
'default /var/run/dhclient.pid is used')
parser.add_argument(
'-lf', metavar='lease-file', nargs='?',
const=LEASE_PATH,
help='Path to the lease database file. If unspecified, the'
'default /var/lib/dhcp/dhclient.leases is used. See '
'dhclient.leases(5) for a description of this file.')
parser.add_argument(
'-cf', metavar='config-file', nargs='?',
const=CONF_PATH,
help='Path to the client configuration file. If unspecified,'
'the default /etc/dhcp/dhclient.conf is used. See '
'dhclient.conf(5) for a description of this file.')
parser.add_argument(
'-d',
action='store_true',
help='Force dhclient to run as a foreground process. '
'Normally the DHCP client will run in the foreground '
'until is has configured an interface at which time it '
'will revert to running in the background. This '
'option is useful when running the client under a '
'debugger, or when running it out of inittab on System V'
' systems. This implies -v.')
parser.add_argument('-q',
action='store_true',
help='Be quiet at startup, this is the default.')
parser.add_argument('-N', action='store_true')
parser.add_argument('-6', action='store_true')
parser.add_argument('-4', action='store_true')
'default /var/run/dhcpcanon.pid is used. '
'This option is used by NetworkManager to check whether '
'dhcpcanon is already running.')
args = parser.parse_args()
logger.debug('args %s', args)
......@@ -90,20 +67,20 @@ def main():
if args.verbose:
logger.setLevel(logging.DEBUG)
logger.debug('args %s', args)
if args.lease is not None:
# TODO
pass
if args.interface:
conf.iface = args.interface
logger.debug('interface %s' % conf.iface)
# FIXME: disabled for now
# if args.pf is not None:
# import daemon
# from daemon import pidfile
# pf = pidfile.TimeoutPIDLockFile(args.pf)
# logger.debug('using pid file %s', pf)
# context = daemon.DaemonContext(pidfile=pf)
# # FIXME: it does not get daemonized
if args.pf is not None:
# This is only needed for nm
pf = PIDLockFile(args.pf, timeout=5)
try:
pf.acquire()
logger.debug('using pid file %s', pf)
except AlreadyLocked as e:
pf.break_lock()
pf.acquire()
except (LockTimeout, LockFailed) as e:
logger.error(e)
dhcpcap = DHCPCAPFSM(iface=conf.iface,
server_port=SERVER_PORT,
client_port=CLIENT_PORT,
......
......@@ -366,9 +366,9 @@ class DHCPCAPFSM(Automaton):
else:
try:
set_net(self.client.lease)
except:
logger.error('Can not set IP')
raise self.END()
except Exception as e:
logger.error('Can not set IP', exc_info=True)
# raise self.END()
# TODO: go daemon?
@ATMT.state()
......
......@@ -4,12 +4,14 @@
"""Netowrk utils for the DHCP client implementation of the Anonymity Profile
([:rfc:`7844`])."""
import logging
import os.path
import subprocess
from dbus import SystemBus, Interface, DBusException
from pyroute2 import IPRoute
from pyroute2.netlink import NetlinkError
from .constants import RESOLVCONF
from .constants import RESOLVCONF, RESOLVCONF_ADMIN
logger = logging.getLogger(__name__)
......@@ -21,7 +23,6 @@ def set_net(lease):
except IndexError as e:
logger.error('Interface %s not found, can not set IP.',
lease.interface)
exit(1)
try:
ipr.addr('add', index, address=lease.address,
mask=int(lease.subnet_mask_cidr))
......@@ -47,14 +48,84 @@ def set_net(lease):
else:
logger.debug('Default gateway set to %s', lease.router)
ipr.close()
cmd = [RESOLVCONF, '-a', lease.interface]
proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
set_dns(lease)
def set_dns(lease):
if systemd_resolved_status() is True:
set_dns_systemd_resolved(lease)
elif os.path.exists(RESOLVCONF_ADMIN):
set_dns_resolvconf_admin(lease)
elif os.path.exists(RESOLVCONF):
set_dns_resolvconf(lease)
def set_dns_resolvconf_admin(lease):
cmd = [RESOLVCONF_ADMIN, 'add', lease.interface, lease.name_server]
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdin = '\n'.join(['nameserver ' + nm for nm in lease.name_server.split()])
try:
(stdout, stderr) = proc.communicate()
return True
except TypeError as e:
logger.error(e)
return False
def set_dns_resolvconf(lease):
cmd = [RESOLVCONF, '-a', lease.interface]
proc = subprocess.Popen(cmd, stdin=subprocess.PIPE,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdin = '\n'.join(['nameserver ' + nm for nm in
lease.name_server.split()])
stdin = str.encode(stdin)
try:
(stdout, stderr) = proc.communicate(stdin)
return True
except TypeError as e:
logger.error(e)
logger.debug('result %s, stdout %s, stderr %s', proc.returncode, stdout,
stderr)
return False
def set_dns_systemd_resolved(lease):
# NOTE: if systemd-resolved is not already running, we might not want to
# run it in case there's specific system configuration for other resolvers
ipr = IPRoute()
index = ipr.link_lookup(ifname=lease.interface)[0]
# Construct the argument to pass to DBUS.
# the equivalent argument for:
# busctl call org.freedesktop.resolve1 /org/freedesktop/resolve1 \
# org.freedesktop.resolve1.Manager SetLinkDNS 'ia(iay)' 2 1 2 4 1 2 3 4
# is SetLinkDNS(2, [(2, [8, 8, 8, 8])]_
iay = [(2, [int(b) for b in ns.split('.')])
for ns in lease.name_server.split()]
# if '.' in ns
# else (10, [ord(x) for x in
# socket.inet_pton(socket.AF_INET6, ns)])
bus = SystemBus()
resolved = bus.get_object('org.freedesktop.resolve1',
'/org/freedesktop/resolve1')
manager = Interface(resolved,
dbus_interface='org.freedesktop.resolve1.Manager')
try:
manager.SetLinkDNS(index, iay)
return True
except DBusException as e:
logger.error(e)
return False
def systemd_resolved_status():
bus = SystemBus()
systemd = bus.get_object('org.freedesktop.systemd1',
'/org/freedesktop/systemd1')
manager = Interface(systemd,
dbus_interface='org.freedesktop.systemd1.Manager')
unit = manager.LoadUnit('sytemd-resolved.service')
proxy = bus.get_object('org.freedesktop.systemd1', str(unit))
r = proxy.Get('org.freedesktop.systemd1.Unit',
'ActiveState',
dbus_interface='org.freedesktop.DBus.Properties')
if str(r) == 'active':
return True
return False
......@@ -83,7 +83,7 @@ clean:
.PHONY: html
html:
$(FSMSVG)
$(UMLSVG)
#$(UMLSVG)
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
......@@ -163,7 +163,7 @@ epub3:
.PHONY: latex
latex:
$(FSMSVG)
$(UMLSVG)
#$(UMLSVG)
$(PDFs)
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
......@@ -174,7 +174,7 @@ latex:
.PHONY: latexpdf
latexpdf:
$(FSMSVG)
$(UMLSVG)
#$(UMLSVG)
$(PDFs)
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
......
......@@ -88,6 +88,8 @@ Documentation for developers
:ref:`implementation`
:ref:`install_run_cases`
:ref:`privileges`
:ref:`integration`
......@@ -102,6 +104,8 @@ Recommended documentation not included in this repository:
:ref:`RFC7844 comments and summary <rfc7844comm>`
`Main Website <http://dhcpap.github.io>`__
License
-------
......
This diff is collapsed.
This diff is collapsed.
......@@ -15,6 +15,7 @@ Contents:
install
download
running
install_run_cases
todo
contributing
soa
......
......@@ -14,15 +14,20 @@ It can be installed with a package manager or in command line::
The main script will be installed in ``/sbin/dhcpcanon``, a systemd service
will be enabled and run by default, so there is no need to run anything manually.
Installation from source code
==============================
**Important**: when running ``dhcpcanon`` the hardware address
(`MAC <https://en.wikipedia.org/wiki/MAC_address>`__) should be randomized.
You can use `macchanger <https://github.com/alobbs/macchanger>`__,
`macouflage <https://github.com/subgraph/macouflage>`__ or other.
Installation from source code in Debian/Ubuntu
===============================================
In case you would like to have a newer version or it is not packaged for your
distribution, you can install it from the source code.
Install system dependencies, in Debian/Ubuntu::
sudo apt install python-dev
sudo apt install python3-dev
Obtain the source code::
......@@ -30,6 +35,16 @@ Obtain the source code::
Install ``dhcpcanon`` and system files::
sudo ./install.sh
for advanced users
--------------------
Follow the two first steps in the previous paragraph.
To install ``dhcpcanon`` and the ``systemd`` service::
sudo make install WITH_SYSTEMD=true
In Debian this will install all the required files under ``/usr/local``.
......@@ -37,8 +52,15 @@ In Debian this will install all the required files under ``/usr/local``.
systemctl start dhcpcanon
for advanced users
--------------------
It's possible to also install support for udev::
sudo apt install sudo make install WITH_SYSTEMD=true
sudo make install WITH_SYSTEMD=true WITH_SYSTEMD_UDEV=true
And apparmor profile::
sudo apt install apparmor
sudo make install WITH_APPARMOR=true
In the case that you would like to install without root privileges,
you can install it without the systemd service and you can specify
......@@ -50,11 +72,18 @@ Note however that without systemd ``dhcpcanon`` will need to be run with root
privileges, while the systemd service drop ``dhcpcanon`` root privileges and
only keeps the required network capabilities.
You would also need to install
`resolvconf-admin <https://github.com/dkg/resolvoconf-admin>`_
to be able to run it as non root user and set up DNS servers provided by the DHCP server.
It will be possible to set up DNS servers with ``systemd`` too soon.
An alternative to do not run ``dhcpcanon`` with root privileges nor systemd,
is to use `ambient-rs wrapper <https://github.com/infinity0/ambient-rs>`
is to use `ambient-rs wrapper <https://github.com/infinity0/ambient-rs>`_
and run::
RUST_BACKTRACE=1 ./target/debug/ambient -c NET_RAW,NET_ADMIN,NET_BIND_SERVICE /usr/bin/python3 -m dhcpcanon.dhcpcanon -v
RUST_BACKTRACE=1 ./target/debug/ambient \
-c NET_RAW,NET_ADMIN,NET_BIND_SERVICE \
/usr/bin/python3 -m dhcpcanon.dhcpcanon -v
Installation with pip
==========================
......@@ -63,7 +92,7 @@ The pip package does not install either system files and it can be installed
without root, but it still needs to be run as root, as commented in the last
section.::
pip install dhcpcanon
pip3 install dhcpcanon
In Debian this will install the files in ``/home/youruser/.local``
Note also that if you install it in a virtualenv, when executing ``dhcpcanon``
......@@ -78,12 +107,12 @@ It is recommended to install ``dhcpcanon`` in a python virtual environment.
Check https://virtualenv.pypa.io/en/latest/installation.html. In Debian::
sudo apt install python-virtualenv
sudo apt install python3-virtualenv
Create a virtual environment::
mkdir ~/.virtualenvs
virtualenv ~/.virtualenvs/dhcpcanonenv
virtualenv ~/.virtualenvs/dhcpcanonenv -p /usr/bin/python3
source ~/.virtualenvs/dhcpcanonenv/bin/activate
Get the sources::
......@@ -91,4 +120,4 @@ Get the sources::
Install it::
pip install -e .
pip3 install -e .
.. _install_run_cases:
Installation and running cases
===================================
system files
-------------
sbin/dhcpcanon-script
systemd/dhcpcanon.service
tmpfiles.d/dhcpcanon.conf
systemd/network/90-dhcpcanon.link
console_scripts -> /sbin/dhcpcanon
run cases
----------
1. standalone without systemd, using -sp sbin/dhcpcanon-script
2. standalone without systemd, using resolvconf
3. standalone without systemd, using resolvconf-admin
4. launched with a wrapper, using -sp sbin/dhcpcanon-script
5. launched with a wrapper, sing resolvconf
6. launched with a wrapper, using resolvconf-admin
7. launched as systemd service, using systemd-resolved
install from
-------------
* setup.py: dhcpcanon-scriptresolvconf, resolvconf-admin and/or systemd
need to be installed manually
* pip: dhcpcanon-scriptresolvconf, resolvconf-admin and/or systemd
need to be installed manually
* Makefile
* Debian
......@@ -17,11 +17,11 @@ TODO
[X] create systemd service
[won't fix] create init.d daemon
[X] create init.d daemon: Won't fix.
[X] limit privileges
[ ] include MAC anonymization module
[X] include MAC anonymization module: Debian package suggest it.
[X] create apparmor profile
......
#!/bin/bash
mkdir -p /sbin
for i in sbin/dhcpcanon-script; do install "$i" /sbin; done
mkdir -p /share/doc/dhcpcanon
for i in README.md LICENSE; do install -m 644 "$i" /share/doc/dhcpcanon; done
mkdir -p /share/man/man8
for i in man/dhcpcanon.8; do install -m 644 "$i" /share/man/man8; done
python3 setup.py install --record installed.txt --install-scripts=/sbin
adduser --system dhcpcanon
mkdir -p /lib/systemd/system
cp systemd/dhcpcanon.service /lib/systemd/system/dhcpcanon.service
mkdir -p /lib/tmpfiles.d
for i in tmpfiles.d/dhcpcanon.conf; do install -m 644 "$i" /lib/tmpfiles.d; done
systemctl enable /lib/systemd/system/dhcpcanon.service
systemd-tmpfiles --create --root=/lib/tmpfiles.d/dhcpcanon.conf
mkdir -p /lib/systemd/network
for i in systemd/network/90-dhcpcanon.link; do install -m 644 "$i" /lib/systemd/network; done
mkdir -p /etc/apparmor.d
for i in apparmor.d/sbin.dhcpcanon; do install -m 644 "$i" /etc/apparmor.d; done
for i in apparmor.d/sbin.dhcpcanon; do aa-complain /etc/apparmor.d/"$i"; done
......@@ -57,12 +57,14 @@ setup(
packages=find_packages(exclude=['contrib', 'docs', 'tests*']),
install_requires=[
"attrs>=16.3",
"dbus-python>=1.2",
"netaddr>=0.7",
"lockfile>=0.12",
"pip>=8.1",
"pyroute2>=0.3",
'scapy>=2.2";python_version<="2.7"',
'scapy-python3>=0.20;python_version>="3.4"',
'scapy-python3>=0.20',
],
python_requires=">=3.5",
extras_require={
'dev': ['ipython', 'pyflakes', 'pep8'],
'test': ['coverage', 'coveralls', 'codecov', 'tox', 'pytest'],
......@@ -88,7 +90,6 @@ setup(
'Intended Audience :: Developers',
'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent',
'Programming Language :: Python :: 2',
'Programming Language :: Python :: 3',
'Topic :: System :: Networking',
],
......
[Link]
MacAddressPolicy=random
[tox]
envlist = clean, lint, py27, py35, stats
envlist = clean, lint, py35, stats
#doc{py27,py35}-{pinned,unpinned}, stats
[testenv:clean]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment