diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..cf9e3e5 --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,67 @@ +name: CI +on: + pull_request: + push: + branches: + - "master" + workflow_dispatch: +jobs: + build: + runs-on: ubuntu-20.04 + name: Build on ${{ matrix.arch }} using ${{ matrix.cc }} + + strategy: + matrix: + cc: + - "gcc" + - "clang" + arch: + - "amd64" + - "aarch64" + - "ppc64le" + steps: + - uses: actions/checkout@v2 + - uses: uraimo/run-on-arch-action@v2.1.1 + if: ${{ matrix.arch != 'amd64' }} + name: Build and test + with: + arch: ${{ matrix.arch }} + distro: ubuntu20.04 + + githubToken: ${{ github.token }} + + env: | + CC: ${{ matrix.cc }} + + install: | + apt-get update -y -q + apt-get install -q -y \ + build-essential \ + clang \ + debhelper \ + libtool \ + liblua5.1-dev + + run: | + # Build the package. + (cd pkg && make deb) + # Compile and run the tests. + (cd src && make clean && DEBUG=1 make tests) + + - name: Build and test + if: ${{ matrix.arch == 'amd64' }} + env: + CC: ${{ matrix.cc }} + + run: | + sudo apt-get install -q -y \ + build-essential \ + clang \ + debhelper \ + libtool \ + liblua5.1-dev + + # Build the package. + (cd pkg && make deb) + # Compile and run the tests. + (cd src && make clean && DEBUG=1 make tests) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2f00dca --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +build +pkg/BUILD +pkg/BUILDROOT +pkg/RPMS +pkg/SOURCES +pkg/SRPMS diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index bf038d5..0000000 --- a/.travis.yml +++ /dev/null @@ -1,36 +0,0 @@ -language: c - -compiler: - - gcc - - clang - -dist: bionic - -matrix: - include: - - os: linux - arch: amd64 - - os: linux - arch: arm64 - - os: linux - arch: ppc64le - -addons: - apt: - update: true - packages: - - build-essential - - fakeroot - - debhelper - - libtool - - libtool-bin - - liblua5.1-dev - - lua5.1 - -script: - # Build the package. - - (cd pkg && make deb) - # Compile and run the tests. - - (cd src && make clean && DEBUG=1 make tests) - # Install the DEB packages and run the Lua tests. - #- (sudo dpkg -i *.deb && cd src/lua && lua ./t_lpm.lua) diff --git a/pkg/SPECS/liblpm.spec b/pkg/SPECS/liblpm.spec index fa81b46..b83dad0 100644 --- a/pkg/SPECS/liblpm.spec +++ b/pkg/SPECS/liblpm.spec @@ -4,7 +4,7 @@ Name: liblpm Version: %{version} -Release: 3%{?dist} +Release: 4%{?dist} Summary: Longest Prefix Match (LPM) library Group: System Environment/Libraries License: BSD diff --git a/src/Makefile b/src/Makefile index d140512..e502e5d 100644 --- a/src/Makefile +++ b/src/Makefile @@ -40,44 +40,49 @@ else CFLAGS+= -DNDEBUG endif +# Build outside src/ so artifacts never end up in the source tarball. +OUTDIR?= ../build + # C library INCS= lpm.h -OBJS= lpm.o +OBJS= $(OUTDIR)/lpm.o LIB= liblpm -$(LIB).la: LDFLAGS+= -rpath $(LIBDIR) -version-info 1:0:0 +$(OUTDIR)/$(LIB).la: LDFLAGS+= -rpath $(LIBDIR) -version-info 1:0:0 install/%.la: ILIBDIR= $(DESTDIR)/$(LIBDIR) install: IINCDIR= $(DESTDIR)/$(INCDIR)/ #install: IMANDIR= $(DESTDIR)/$(MANDIR)/man3/ obj: $(OBJS) -lib: $(LIB).la +lib: $(OUTDIR)/$(LIB).la + +$(OUTDIR): + mkdir -p $@ -%.o: %.c - $(CC) $(CFLAGS) -c $< +$(OUTDIR)/%.o: %.c | $(OUTDIR) + $(CC) $(CFLAGS) -c $< -o $@ -%.lo: %.c - libtool --mode=compile --tag CC $(CC) $(CFLAGS) -fPIC -c $< +$(OUTDIR)/%.lo: %.c | $(OUTDIR) + libtool --mode=compile --tag CC $(CC) $(CFLAGS) -fPIC -c $< -o $@ -$(LIB).la: $(shell echo $(OBJS) | sed 's/\.o/\.lo/g') - libtool --mode=link --tag CC $(CC) $(LDFLAGS) -o $@ $(notdir $^) +$(OUTDIR)/$(LIB).la: $(OUTDIR)/lpm.lo + libtool --mode=link --tag CC $(CC) $(LDFLAGS) -o $@ $^ -install/%.la: %.la +install/%.la: $(OUTDIR)/%.la mkdir -p $(ILIBDIR) - libtool --mode=install install -c $(notdir $@) $(ILIBDIR)/$(notdir $@) + libtool --mode=install install -c $< $(ILIBDIR)/$(notdir $@) install: $(addprefix install/,$(LIB).la) libtool --mode=finish $(LIBDIR) mkdir -p $(IINCDIR) && install -c $(INCS) $(IINCDIR) #mkdir -p $(IMANDIR) && install -c $(MANS) $(IMANDIR) -tests: $(OBJS) t_$(PROJ).o - $(CC) $(CFLAGS) $^ -o t_$(PROJ) - MALLOC_CHECK_=3 ./t_$(PROJ) +tests: $(OBJS) $(OUTDIR)/t_$(PROJ).o + $(CC) $(CFLAGS) $^ -o $(OUTDIR)/t_$(PROJ) + MALLOC_CHECK_=3 $(OUTDIR)/t_$(PROJ) clean: - libtool --mode=clean rm - rm -rf .libs *.so *.o *.lo *.la t_$(PROJ) + rm -rf $(OUTDIR) .libs *.so *.o *.lo *.la t_$(PROJ) .PHONY: all obj lib install tests clean diff --git a/src/jni/Makefile b/src/jni/Makefile index d60fee1..9bd46a8 100644 --- a/src/jni/Makefile +++ b/src/jni/Makefile @@ -22,7 +22,7 @@ JAVA_HOME?= /usr/lib/jvm/java/ CFLAGS+= -I.. -I$(JAVA_HOME)/include # Sadly, jni_md.h location is OS dependent -CFLAGS+= -I$(shell dirname $(shell find -L $(JAVA_HOME) -name jni_md.h)) +CFLAGS+= -I$(shell dirname $(shell find -L $(JAVA_HOME) -name jni_md.h | head -1)) OBJS= org_netbsd_liblpm_LPM.o ../lpm.o LIB= org_netbsd_liblpm_LPM diff --git a/src/jni/org/netbsd/liblpm/LPM.java b/src/jni/org/netbsd/liblpm/LPM.java index a898a30..61e5f80 100644 --- a/src/jni/org/netbsd/liblpm/LPM.java +++ b/src/jni/org/netbsd/liblpm/LPM.java @@ -45,6 +45,8 @@ public class LPM { private native int insert(long lpm, byte[] address, int prefixLength, T value); private native T lookup(long lpm, String addr); private native T lookup(long lpm, byte[] address); + private native T lookupPrefix(long lpm, String cidr); + private native T lookupPrefix(long lpm, byte[] address, int prefixLength); private native int remove(long lpm, String cidr); private native int remove(long lpm, byte[] address, int prefixLength); private native void clear(long lpm); @@ -106,6 +108,24 @@ public T lookup(byte[] address) { return lookup(lpm, address); } + public T lookupPrefix(String cidr) { + if (cidr == null) { + throw new IllegalArgumentException( + "cidr must not be null"); + } + + return lookupPrefix(lpm, cidr); + } + + public T lookupPrefix(InetAddress inet, int prefixLength) { + return lookupPrefix(inet.getAddress(), prefixLength); + } + + public T lookupPrefix(byte[] address, int prefixLength) { + validateCIDR(address, prefixLength); + return lookupPrefix(lpm, address, prefixLength); + } + public boolean remove(String cidr) { if (cidr == null) { throw new IllegalArgumentException( diff --git a/src/jni/org/netbsd/liblpm/LPMTest.java b/src/jni/org/netbsd/liblpm/LPMTest.java index ceefa7e..7939e54 100644 --- a/src/jni/org/netbsd/liblpm/LPMTest.java +++ b/src/jni/org/netbsd/liblpm/LPMTest.java @@ -45,6 +45,24 @@ private static void basicTest() throws Exception { } catch(IllegalArgumentException e) { } + assertEqual(lpm.lookupPrefix("10.0.0.0/9"), null); + assertEqual(lpm.lookupPrefix(InetAddress.getByName("10.0.0.0"), 9), null); + assertEqual(lpm.lookupPrefix(new byte[]{10, 0, 0, 0}, 9), null); + assertEqual(lpm.lookupPrefix("2001:db8::1/65"), null); + assertEqual(lpm.lookupPrefix(InetAddress.getByName("2001:db8::1"), 65), null); + assertEqual(lpm.lookupPrefix(new byte[]{ + 127, 0, 0, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 0, 0 + }, 67), null); + + assertEqual(lpm.lookupPrefix("10.0.0.0/8"), "foo"); + assertEqual(lpm.lookupPrefix(InetAddress.getByName("10.0.0.0"), 8), "foo"); + assertEqual(lpm.lookupPrefix(new byte[]{10, 0, 0, 0}, 8), "foo"); + assertEqual(lpm.lookupPrefix("2001:db8::1/64"), "baz"); + assertEqual(lpm.lookupPrefix(InetAddress.getByName("2001:db8::1"), 64), "baz"); + assertEqual(lpm.lookupPrefix(new byte[]{ + 127, 0, 0, 0, 0, 0, 0, 0, 127, 0, 0, 0, 0, 0, 0, 0 + }, 66), "raw6"); + assertEqual(lpm.lookup("10.0.1.2"), "foo"); assertEqual(lpm.lookup("10.10.3.4"), "bar"); assertEqual(lpm.lookup("11.10.3.4"), null); diff --git a/src/jni/org_netbsd_liblpm_LPM.c b/src/jni/org_netbsd_liblpm_LPM.c index 8bb51d3..069549f 100644 --- a/src/jni/org_netbsd_liblpm_LPM.c +++ b/src/jni/org_netbsd_liblpm_LPM.c @@ -158,6 +158,54 @@ Java_org_netbsd_liblpm_LPM_lookup__J_3B(JNIEnv *env, jobject obj, return ret; } +JNIEXPORT jobject JNICALL +Java_org_netbsd_liblpm_LPM_lookupPrefix__JLjava_lang_String_2 + (JNIEnv *env, jobject obj, jlong lpm_ref, jstring cidr) +{ + lpm_t *lpm = (lpm_t *)lpm_ref; + const char *cidr_s; + uint32_t addr[4]; + size_t len; + unsigned pref; + int ret; + + cidr_s = (*env)->GetStringUTFChars(env, cidr, NULL); + if (cidr_s == NULL) { + return NULL; + } + ret = lpm_strtobin(cidr_s, addr, &len, &pref); + (*env)->ReleaseStringUTFChars(env, cidr, cidr_s); + if (ret != 0) { + return NULL; + } + + return lpm_lookup_prefix(lpm, addr, len, pref); +} + +JNIEXPORT jobject JNICALL +Java_org_netbsd_liblpm_LPM_lookupPrefix__J_3BI + (JNIEnv *env, jobject obj, jlong lpm_ref, jbyteArray addr_ref, jint pref) +{ + lpm_t *lpm = (lpm_t *)lpm_ref; + jbyte *addr; + size_t len; + void *ret; + + len = (*env)->GetArrayLength(env, addr_ref); + assert(len == 16 || len == 4); + + addr = (*env)->GetByteArrayElements(env, addr_ref, NULL); + if (addr == NULL) { + return NULL; + } + + ret = lpm_lookup_prefix(lpm, addr, len, pref); + + (*env)->ReleaseByteArrayElements(env, addr_ref, addr, JNI_ABORT); + + return ret; +} + JNIEXPORT jint JNICALL Java_org_netbsd_liblpm_LPM_remove__JLjava_lang_String_2(JNIEnv *env, jobject obj, jlong lpm_ref, jstring addr) diff --git a/src/lua/Makefile b/src/lua/Makefile index d9fa8f8..8239b66 100644 --- a/src/lua/Makefile +++ b/src/lua/Makefile @@ -36,27 +36,33 @@ LUA_CFLAGS?= $(shell pkg-config --cflags lua) LUA_LDFLAGS?= $(shell pkg-config --cflags --libs lua) CFLAGS+= $(LUA_CFLAGS) -I.. -fPIC LDFLAGS+= $(LUA_LDFLAGS) -LDFLAGS+= -L../.libs -llpm +# Build outside src/ so artifacts never end up in the source tarball. +OUTDIR?= ../../build/lua +LIBLPM_OUTDIR?= ../../build +LDFLAGS+= -L$(LIBLPM_OUTDIR)/.libs -llpm -OBJS= lpm_lua.o +OBJS= $(OUTDIR)/lpm_lua.o LIB= lpm install: LUA_ILIBDIR= $(DESTDIR)/$(LUA_LIBDIR)/ obj: $(OBJS) -lib: $(LIB).so +lib: $(OUTDIR)/$(LIB).so -%.o: %.c - $(CC) $(CFLAGS) -c $< +$(OUTDIR): + mkdir -p $@ -$(LIB).so: $(OBJS) - $(CC) $(LDFLAGS) -fPIC -shared -o $@ $(notdir $^) +$(OUTDIR)/%.o: %.c | $(OUTDIR) + $(CC) $(CFLAGS) -c $< -o $@ + +$(OUTDIR)/$(LIB).so: $(OBJS) + $(CC) $(LDFLAGS) -fPIC -shared -o $@ $^ install: - mkdir -p $(LUA_ILIBDIR) && install -c lpm.so $(LUA_ILIBDIR) + mkdir -p $(LUA_ILIBDIR) && install -c $(OUTDIR)/lpm.so $(LUA_ILIBDIR) clean: - rm -rf .libs *.so *.o *.lo *.la t_$(PROJ) + rm -rf $(OUTDIR) .libs *.so *.o *.lo *.la t_$(PROJ) .PHONY: all obj lib install clean