]> git.pld-linux.org Git - packages/choparp.git/commitdiff
Initial, works
authorMariusz Mazur <mmazur@axeos.com>
Fri, 20 Mar 2015 14:03:05 +0000 (14:03 +0000)
committerMariusz Mazur <mmazur@axeos.com>
Fri, 20 Mar 2015 14:05:11 +0000 (14:05 +0000)
Just point it at an interface, give it a few ips and it'll answer to
arp requests for those ips.

README.md [new file with mode: 0644]
choparp-service-generator [new file with mode: 0644]
choparp.8 [new file with mode: 0644]
choparp.c [new file with mode: 0644]
choparp.spec [new file with mode: 0644]
choparp.sysconfig [new file with mode: 0644]
choparp.target [new file with mode: 0644]
choparp@.service [new file with mode: 0644]
sample.conf [new file with mode: 0644]

diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..ddf657d
--- /dev/null
+++ b/README.md
@@ -0,0 +1,77 @@
+choparp
+=======
+
+  * Copyright (c) 1997 Takamichi Tateoka (tree@mma.club.uec.ac.jp)
+  * Copyright (c) 2002-2015 Thomas Quinot (thomas@cuivre.fr.eu.org)
+
+Changes and original English man page from the FreeBSD port by
+Jun-ichiro itojun Hagino <itojun@freebsd.org>.
+
+Changes from the NetBSD package by Darrin B. Jewell <dbj@netbsd.org>.
+
+Introduction
+------------
+
+choparp is a proxy ARP daemon. It listens for ARP requests on a
+network interface, and sends ARP replies with a specified MAC
+addresses when the requested IP addresses matches a user-provided
+list.
+
+Build instructions
+------------------
+
+Requires libpcap.
+
+`gcc -o choparp choparp.c -lpcap`
+
+Usage example
+-------------
+
+For example, assume following VLSM subnet.  R1 and H1 must have
+routing entry for subnet B (172.21.139.32/28).
+
+```
+  +----+                            +----+
+  | R1 |                            | H1 |
+  +-+--+                            +----+
+    | 172.21.139.1                    | 172.21.139.96
+    |                                 |
+  --+--------+------------------------+--------------- subnet A
+             |                                   172.21.139.0/24
+             | 172.21.139.2
+           +----+
+           | R2 |
+           +----+
+             | 172.21.139.33
+             |
+       ------+-----------------+---------------------- subnet B
+                               |                 172.21.139.32/28
+                               | 172.21.139.33
+                             +----+
+                             | H2 |
+                             +----+
+```
+
+If you can not set such routing entry, R1 and H1 treat hosts on the
+subnet B as on the subnet A.  In this case, H1 broadcast ARP request
+for H2 to send a message for H2.  This request will fail since this
+request can not reach to subnet B (and H2), thus H1 cannot tail with
+H2.
+
+choparp running on R2 replies for ARP request, which is looking for
+MAC address of H2, as R2 is H2 on subnet A.  Hosts on subnet A send
+packets for H2 to R2 (because R2 replies H2 is R2), and R2 can forward
+the packets to R2 with ordinary way.  As a result, H1 and H2 can talk
+each other.  You can *chop* subnet B from subnet A without any routing
+modification on subnet A.
+
+This is a same way as proxy ARP described in RFC1027.
+
+For above example, you should run choparp on R2, set if_name parameter
+as the interface on 172.21.139.2, network parameter as
+172.21.139.32/255.255.255.240 (or 172.21.139.32/28).  You should not
+use 172.21.139.32 and 172.21.139.47 as IP address for hosts because
+they are used as network address and broadcast address for subnet B.
+
+Enjoy!
+
diff --git a/choparp-service-generator b/choparp-service-generator
new file mode 100644 (file)
index 0000000..09355b1
--- /dev/null
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+destunitdir=${1:-/tmp}
+
+# Do nothing if target is disabled
+[ -e /etc/systemd/system/multi-user.target.wants/choparp.target ] || exit 0
+
+[ -f /etc/sysconfig/choparp ] && . /etc/sysconfig/choparp
+
+if [ -d $destunitdir/choparp.target.wants ]; then
+       rm -f $destunitdir/choparp.target.wants/choparp@*.service
+else
+       mkdir -p $destunitdir/choparp.target.wants
+fi
+
+for iface in $INTERFACES; do
+       [ -L $destunitdir/choparp.target.wants/choparp@$iface.service ] && \
+               continue
+       ln -s /lib/systemd/system/choparp@.service \
+               $destunitdir/choparp.target.wants/choparp@$iface.service
+done
diff --git a/choparp.8 b/choparp.8
new file mode 100644 (file)
index 0000000..3921ceb
--- /dev/null
+++ b/choparp.8
@@ -0,0 +1,111 @@
+.\" Copyright (c) 1997 by Takamichi Tateoka.  All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\"    must display the following acknowledgement:
+.\"    This product includes software developed by Takamichi Tateoka.
+.\" 4. Neither the name of the author may be used to endorse or promote
+.\"    products derived from this software without specific prior
+.\"    written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY TAKAMICHI TATEOKA ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd November 20, 2014
+.Dt CHOPARP 8
+.Os
+.Sh NAME
+.Nm choparp
+.Nd cheap and omitted proxy ARP
+.Sh SYNOPSIS
+.Nm chpoarp
+.Ar if_name mac_addr
+.Oo Fl Oc Ns Ar net_addr Ns
+.Op / Ns Ar net_mask
+.Ar ...
+.Sh DESCRIPTION
+.Pp
+.Nm choparp 
+is a easy-to-use proxy ARP daemon.
+It watches ARP request packets visible on the interface specified by argument
+.Ar if_name ,
+and sends proxy ARP reply to the sender if the ARP request queries the
+MAC address
+.Pq ethernet hardware address
+for the network specified by
+.Ar net_addr Ns / Ar net_mask .
+.Pp
+.Ar mac_addr
+is th MAC address to be published for the specified hosts.
+It is normally the address of
+.Ar if_name .
+The format of
+.Ar mac_addr
+must be 6 colon-separated bytes of hexadecimal value, such as
+.Ad 00:00:01:01:14:46 .
+The keyword
+.Ad auto
+can also be used to use the address of
+.Ar if_name
+from the system configuration.
+.Pp
+A
+.Xr carp 4
+virtual router address can be specified as
+.Ad vhid:<hex>
+.
+.Pp
+.Ar net_addr
+must be in dotted quad notation
+.Pq for example Ad 133.138.1.134
+or be a 32 bit hexadecimal value starting with
+.Dq 0x
+.Pq for example Ad 0x858a0186 .
+.Ar net_mask
+can likewise be speficied as a dotted quad or hexadecimal value,
+or alternatively as a mask length. The following address specifications
+are therefore equivalent:
+.Bl -item -offset indent
+.It
+.Ad 192.168.98.0/255.255.254.0
+.It
+.Ad 192.168.98.0/0xfffffe00
+.It
+.Ad 192.168.98.0/23
+.El
+.Pp
+Multiple addresses can be specified.
+Addresses can be
+.Em excluded
+by preceding them with
+.Fl
+.Sh EXAMPLES
+If you have network interface
+.Dq ne0
+with MAC address
+.Dq 00:00:01:01:14:16 ,
+and would like to send proxy ARP reply for 192.168.0.64/26,
+the argument would be as follows:
+.Bd -literal -offset indent
+choparp ne0 00:00:01:01:14:46 192.168.0.64/255.255.255.192
+.Ed
+.Sh BUGS
+Supports Ethernet interfaces only.
+Handles single interface at a time.
+.Pq you can start multiple Nm choparp No for multiple interfaces, though .
diff --git a/choparp.c b/choparp.c
new file mode 100644 (file)
index 0000000..8cb90d6
--- /dev/null
+++ b/choparp.c
@@ -0,0 +1,339 @@
+/*
+   choparp - cheap & omitted proxy arp
+
+   Copyright (c) 1997 Takamichi Tateoka (tree@mma.club.uec.ac.jp)
+   Copyright (c) 2002-2015 Thomas Quinot (thomas@cuivre.fr.eu.org)
+   
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+   1. Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+   2. Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+   3. Neither the name of the authors nor the names of their contributors
+      may be used to endorse or promote products derived from this software
+      without specific prior written permission.
+   
+   THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+   ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+   FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+   OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+   LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+   OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+   SUCH DAMAGE.
+
+
+   History:
+   17 Jun 1997 Creation (tate)
+   7  Oct 1997 fix some comments (tate)
+   19 Jun 1998  fix read result as ssize_t (tate / pointed by msaitoh)
+
+*/
+
+#define _GNU_SOURCE /* asprintf */
+
+#include <pcap.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <net/if.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+
+#ifndef __linux__
+#include <ifaddrs.h>
+#include <net/if_dl.h>
+#endif
+
+/* ARP Header                                      */ 
+#define ARP_REQUEST 1   /* ARP Request             */ 
+#define ARP_REPLY 2     /* ARP Reply               */ 
+
+struct cidr {
+       struct cidr *next;
+       struct in_addr addr;            /* addr and mask are host order */
+       struct in_addr mask;
+};
+
+struct cidr *targets = NULL, *excludes = NULL;
+char errbuf[PCAP_ERRBUF_SIZE];
+u_char target_mac[ETHER_ADDR_LEN];     /* target MAC address */
+
+char* cidr_to_str(struct cidr *a) {
+    char buf[64];
+    char *res = NULL;
+    int res_alloc, res_len;
+    int len;
+
+    while (a) {
+        if (a->mask.s_addr == INADDR_NONE) {
+            len = snprintf(buf, sizeof buf, "dst host %s", inet_ntoa(a->addr));
+        } else {
+            len = snprintf(buf, sizeof buf, "dst net %s mask ", inet_ntoa(a->addr));
+            len += snprintf(buf + len, sizeof buf - len, "%s", inet_ntoa(a->mask));
+        }
+
+        if (!res) {
+            res_alloc = 1024;
+            res = malloc(res_alloc);
+            strncpy(res, buf, res_alloc);
+            res_len = len;
+
+        } else {
+            if (res_len + len + 5 > res_alloc) {
+                res_alloc *= 2;
+                res = realloc(res, res_alloc);
+            }
+            strncat(res, " or ", res_alloc - res_len - 1);
+            res_len += 4;
+            strncat(res, buf, res_alloc - res_len - 1);
+            res_len += len;
+        }
+
+        a = a->next;
+    }
+    return res;
+}
+
+pcap_t *
+open_pcap(char *ifname, char *filter_str) {
+    pcap_t *pc = NULL;
+    struct bpf_program filter;
+
+    /* Set up PCAP */
+    if ((pc = pcap_open_live(ifname, 128, 0,  512, errbuf))==NULL){
+       fprintf(stderr, "pcap_open_live failed: %s\n", errbuf);
+       exit(1);
+    }
+    
+    /* Compiles the filter expression */ 
+    if (pcap_compile(pc, &filter, filter_str, 1, PCAP_NETMASK_UNKNOWN) == -1){
+       fprintf(stderr, "pcap_compile failed: %s\n", pcap_geterr(pc) );
+       exit(1);
+    }
+
+    /* Set filter program */ 
+    if (pcap_setfilter(pc, &filter) == -1){
+       fprintf(stderr, "pcap_setfilter failed: %s\n", pcap_geterr(pc));
+       exit(1);
+    }
+
+    pcap_freecode(&filter);
+    return pc;
+}
+
+void
+gen_arpreply(u_char *buf) {
+    struct ether_arp *arp;
+    struct in_addr ipbuf;
+
+    /* set ethernet dst/src address */
+    memcpy(buf, buf+ETHER_ADDR_LEN, ETHER_ADDR_LEN);
+    memcpy(buf+ETHER_ADDR_LEN, target_mac, ETHER_ADDR_LEN);
+
+    /* set result of ARP request */
+    arp = (struct ether_arp *)(buf + ETHER_HDR_LEN);
+    memcpy((char*) &ipbuf, arp->arp_tpa, sizeof(ipbuf));       /* save protocol addr */
+    memcpy(arp->arp_tha, arp->arp_sha, sizeof(arp->arp_tha)); /* set target hard addr */
+    memcpy(arp->arp_tpa, arp->arp_spa, sizeof(arp->arp_tpa)); /* set target proto addr */
+    memcpy(arp->arp_spa, (char *)&ipbuf, sizeof(ipbuf));                     /* set source protocol addr */
+    memcpy(arp->arp_sha, target_mac, ETHER_ADDR_LEN);         /* set source hard addr */
+    arp->arp_op = htons(ARPOP_REPLY);
+}
+
+void
+process_arp(u_char *user, const struct pcap_pkthdr *pkthdr, const u_char *packet) {
+    gen_arpreply((u_char *)packet);
+    pcap_inject((pcap_t *)user, packet, pkthdr->len);
+}
+
+int
+setmac(char *addr, char *ifname){
+    u_int m0, m1, m2, m3, m4, m5;
+
+    if (!strcmp (addr, "auto")) {
+#ifdef __linux__
+        int fd;
+        struct ifreq ifr;
+
+        if ((fd = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
+            perror("socket");
+            return -1;
+        }
+
+        strncpy(ifr.ifr_name, ifname, sizeof ifr.ifr_name);
+
+        if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
+            perror("ioctl(SIOCGIFHWADDR)");
+            return -1;
+        }
+        memcpy(target_mac, ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN);
+        return 0;
+#else
+        struct ifaddrs *ifas, *ifa;
+
+        getifaddrs (&ifas);
+        for (ifa = ifas; ifa != NULL; ifa = ifa->ifa_next) {
+#define SDL ((struct sockaddr_dl *)ifa->ifa_addr)
+            if (strcmp (ifa->ifa_name, ifname)
+              || SDL->sdl_family != AF_LINK
+              || SDL->sdl_alen != ETHER_ADDR_LEN)
+                continue;
+            memcpy (target_mac, SDL->sdl_data + SDL->sdl_nlen, ETHER_ADDR_LEN);
+            return 0;
+        }
+#endif
+        fprintf(stderr, "%s: not found\n", ifname);
+        return -1;
+
+    } else if (!strncmp (addr, "vhid:", 4)) {
+        /*
+         * Virtual router mac address
+         * CARP address format: 00:00:5e:00:01:<VHID>
+         */
+        char *vhid = addr + 5;
+        if (!*vhid)
+            return(-1);
+        m0 = 0;
+        m1 = 0;
+        m2 = 0x5e;
+        m3 = 0;
+        m4 = 1;
+        m5 = atoi(vhid);
+    } else if (sscanf(addr, "%x:%x:%x:%x:%x:%x", &m0, &m1, &m2, &m3, &m4, &m5) < 6) {
+        fprintf(stderr, "invalid MAC address: %s", addr);
+        return(-1);
+    }
+    target_mac[0] = (u_char )m0;
+    target_mac[1] = (u_char )m1;
+    target_mac[2] = (u_char )m2;
+    target_mac[3] = (u_char )m3;
+    target_mac[4] = (u_char )m4;
+    target_mac[5] = (u_char )m5;
+    return(0);
+}
+
+int
+atoip(char *buf, u_int32_t *ip_addr){
+    u_int      i0, i1, i2, i3;
+
+    if (sscanf(buf, "%u.%u.%u.%u", &i0, &i1, &i2, &i3) == 4){
+       *ip_addr = (i0 << 24) + (i1 << 16) + (i2 << 8) + i3;
+       return(0);
+    }
+    if (sscanf(buf, "0x%lx", (unsigned long *) ip_addr) == 1)
+       return(0);
+
+    return(-1);        
+}
+
+void
+usage(void){
+    fprintf(stderr,"usage: choparp if_name mac_addr [-]addr/mask...\n");
+    exit(-1);
+}
+
+int
+main(int argc, char **argv){
+    pcap_t *pc;
+    char *ifname;
+    char *filter, *targets_filter, *excludes_filter;
+    struct cidr **targets_tail = &targets, **excludes_tail = &excludes;
+#define APPEND(LIST,ADDR,MASK) \
+    do {                                                       \
+       *(LIST ## _tail) = malloc(sizeof (struct cidr));        \
+       (*(LIST ## _tail))->addr.s_addr = htonl(ADDR);          \
+       (*(LIST ## _tail))->mask.s_addr = htonl(MASK);          \
+       (*(LIST ## _tail))->next = NULL;                        \
+       (LIST ## _tail) = &(*(LIST ## _tail))->next;            \
+    } while (0)
+
+    if (argc < 4)
+       usage();
+
+    ifname = argv[1];
+    if (setmac(argv[2], ifname)) {
+        exit(1);
+    }
+    argv += 3; argc -= 3;
+
+    while (argc > 0) {
+       u_int32_t addr, mask = ~0;
+        char *slash = strchr (*argv, '/');
+       int exclude = 0;
+
+       if (**argv == '-') {
+           (*argv)++;
+           exclude = 1;
+       }
+       if (slash != NULL)
+           *(slash++) = '\0';
+       if (atoip (*argv, &addr))
+           usage();
+       if (slash != NULL) {
+           char *end;
+           u_int32_t len = strtol (slash, &end, 10);
+           if (*end == '\0')
+               mask <<= (32 - len);
+           else if (atoip (slash, &mask))
+               usage();
+       }
+       if (exclude)
+           APPEND(excludes, addr, mask);
+       else
+           APPEND(targets, addr, mask);
+
+       argv++, argc--;
+    }
+
+#ifdef DEBUG
+#define SHOW(LIST) \
+    do {                                                       \
+       struct cidr *t;                                         \
+       fprintf (stderr, #LIST ":\n");                          \
+       for (t = LIST; t; t = t->next) {                        \
+           fprintf (stderr, "  %s", inet_ntoa (t->addr));      \
+           fprintf (stderr, "/%s\n", inet_ntoa (t->mask));     \
+       }                                                       \
+    } while (0)
+
+    SHOW(targets);
+    SHOW(excludes);
+    exit (0);
+#endif
+
+    targets_filter = cidr_to_str(targets);
+    excludes_filter = cidr_to_str(excludes);
+
+#define TMPL_FILTER "arp[2:2] == 0x0800 " /* Protocol: IPv4 */       \
+                    "and arp[4] == 6 "    /* Hw addr length: 6 */    \
+                    "and arp[5] == 4 "    /* Proto addr length: 4 */ \
+                    "and arp[6:2] == 1 "  /* Operation: Request */   \
+                    "and (%s)"
+
+#define EXCL_FILTER TMPL_FILTER " and not (%s)"
+    if (excludes_filter == NULL)
+        asprintf (&filter, TMPL_FILTER, targets_filter);
+    else
+        asprintf (&filter, EXCL_FILTER, targets_filter, excludes_filter);
+
+#ifdef DEBUG
+        fprintf(stderr, "Filter on %s: %s\n", ifname, filter);
+#endif
+    if ((pc = open_pcap(ifname, filter)) < 0)
+       exit(1);
+    free(filter);
+    pcap_loop(pc, 0, process_arp, (u_char*)pc);
+    exit(1);
+}
diff --git a/choparp.spec b/choparp.spec
new file mode 100644 (file)
index 0000000..b3fb667
--- /dev/null
@@ -0,0 +1,81 @@
+Summary:       proxy ARP daemon
+Name:          choparp
+Version:       0
+#Rel:       YYMM.#
+Release:    1503.1
+License:       BSD
+Group:         Applications/Networking
+Source0:       choparp.c
+Source1:       README.md
+Source2:       choparp.8
+Source3:    sample.conf
+Source4:    choparp.sysconfig
+Source5:    choparp-service-generator
+Source6:    choparp.target
+Source7:    choparp@.service
+URL:           https://github.com/quinot/choparp
+BuildRequires: libpcap-devel
+BuildRoot:     %{tmpdir}/%{name}-%{version}-root-%(id -u -n)
+
+%description
+choparp is a proxy ARP daemon. It listens for ARP requests on a
+network interface, and sends ARP replies with a specified MAC
+addresses when the requested IP addresses matches a user-provided
+list.
+
+%prep
+%setup -qcT
+install %{SOURCE0} .
+install %{SOURCE1} .
+
+%build
+gcc -o choparp choparp.c -lpcap
+
+%install
+rm -rf $RPM_BUILD_ROOT
+install -d $RPM_BUILD_ROOT{%{_sbindir},%{_mandir}/man8/} \
+           $RPM_BUILD_ROOT%{_docdir}/%{name}-%{version} \
+           $RPM_BUILD_ROOT/etc/{sysconfig,%{name}} \
+           $RPM_BUILD_ROOT{%{systemdtmpfilesdir},%{systemdunitdir}} \
+           $RPM_BUILD_ROOT/lib/systemd/system-generators
+
+install choparp $RPM_BUILD_ROOT%{_sbindir}
+
+install %{SOURCE2} $RPM_BUILD_ROOT%{_mandir}/man8/
+
+install %{SOURCE3} $RPM_BUILD_ROOT%{_sysconfdir}/%{name}/eth0.conf
+install %{SOURCE4} $RPM_BUILD_ROOT/etc/sysconfig/%{name}
+
+install -p %{SOURCE5} $RPM_BUILD_ROOT/lib/systemd/system-generators/%{name}-service-generator
+install -p %{SOURCE6} $RPM_BUILD_ROOT%{systemdunitdir}/%{name}.target
+install -p %{SOURCE7} $RPM_BUILD_ROOT%{systemdunitdir}/%{name}@.service
+
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%post
+%service %{name} restart
+%systemd_post %{name}.target
+
+%preun
+if [ "$1" = "0" ]; then
+    %service %{name} stop
+fi
+%systemd_preun %{name}.target
+
+%postun
+%systemd_reload
+
+%files
+%defattr(644,root,root,755)
+%doc README.md
+%attr(755,root,root) %{_sbindir}/*
+%config(noreplace) %verify(not md5 mtime size) /etc/sysconfig/%{name}
+%attr(755,root,root) /lib/systemd/system-generators/%{name}-service-generator
+%{systemdunitdir}/%{name}.target
+%{systemdunitdir}/%{name}@.service
+%attr(770,root,root) %dir %{_sysconfdir}/%{name}
+%config(noreplace) %verify(not md5 mtime size) %{_sysconfdir}/%{name}/eth0.conf
+%{_mandir}/man8/*
+
diff --git a/choparp.sysconfig b/choparp.sysconfig
new file mode 100644 (file)
index 0000000..53318e2
--- /dev/null
@@ -0,0 +1,2 @@
+# list of interfaces
+#INTERFACES="ech0 eno1 eno2"
diff --git a/choparp.target b/choparp.target
new file mode 100644 (file)
index 0000000..841f274
--- /dev/null
@@ -0,0 +1,7 @@
+[Unit]
+Description=Start choparp sessions
+After=network.target
+Wants=network.target
+
+[Install]
+WantedBy=multi-user.target
diff --git a/choparp@.service b/choparp@.service
new file mode 100644 (file)
index 0000000..1934397
--- /dev/null
@@ -0,0 +1,14 @@
+[Unit]
+Description=choparp on iface %I
+Requires=choparp.target
+After=choparp.target
+
+[Service]
+Type=simple
+Restart=on-failure
+Environment="IFACE=%i" "MAC=auto"
+EnvironmentFile=/etc/choparp/%i.conf
+ExecStart=/usr/sbin/choparp ${IFACE} ${MAC} $IPS
+
+[Install]
+WantedBy=choparp.target
diff --git a/sample.conf b/sample.conf
new file mode 100644 (file)
index 0000000..886f5c3
--- /dev/null
@@ -0,0 +1,6 @@
+# options for choparp instance
+
+#IFACE=eth0     # if not set, cfg file name is used
+#MAC=auto       # defaults to 'auto' in which case choparp uses the iface's mac
+IPS="192.168.5.2 192.168.4.0/24"
+
This page took 0.11517 seconds and 4 git commands to generate.