-# Messaging over raw Ethernet Packets communication library
-
-MDIR = $(shell pwd)
-
-PACKAGE = morep
-
-IFLAGS += -I. -I../src/debug -I../src/gpio
-OFLAGS = -O4 -minline-all-stringops -fsingle-precision-constant
-#OFLAGS += -msse -msse2
-CFLAGS += -Wall -W -Wextra -g $(OFLAGS) $(IFLAGS) -fpic
-LFLAGS += -g -L$(MDIR) -Wl,-rpath=$(MDIR)
-
-LIBDEP = $(wildcard *.ld)
-NAMES = $(LIBDEP:.ld=)
-DEBIAN = $(addprefix debian-,$(NAMES))
-PACKS = $(addprefix pack-,$(NAMES))
-LIBPRE = lib
-LIBEXT = so
-LIBFUL = $(shell cat $(wildcard *.ld) | sed 's/:.*//')
-LIBNIC = $(shell cat $(wildcard *.ld) | sed 's/\(\.$(LIBEXT)\.[0-9]*\)\..*:.*/\1/')
-LIBNAM = $(shell cat $(wildcard *.ld) | sed 's/\(\.$(LIBEXT)\)\..*:.*/\1/')
-LIBSTA = $(shell cat $(wildcard *.ld) | sed 's/\(\.$(LIBEXT)\)\..*:.*/.a/')
-
-TESTS += $(shell [ "$(wildcard test/*.c)" ] && grep -l '/\* *linker:' test/*.c | sed 's/\.c//g')
+# Default flags
+
+CC = gcc
+
+#INCLUDES = -I../debug -D__MEMORY_ALLOCATION__
+INCLUDES =
+OFLAGS = -O4 -Os
+#OFLAGS = -O4 -ffast-math -finline-functions
+#OFLAGS = -O4 -finline-functions
+#OFLAGS += -mtune=pentium3 -mmmx -msse -msse2 -m3dnow
+#OFLAGS += -minline-all-stringops -fsingle-precision-constant
+#OFLAGS += -malign-double
+CFLAGS += -W -Wall -Wextra -g
+#CFLAGS += -std=c99 -D_XOPEN_SOURCE=500
+CFLAGS += $(OFLAGS) $(INCLUDES) $(OPTIONS)
+LDFLAGS += -g $(LDOPTS) $(OPTIONS)
+
+LDOPT = linker
+MV = mv
+ifneq (, $(findstring linux, $(MAKE_HOST)))
+# Linux
+else ifneq (, $(findstring mingw, $(MAKE_HOST)))
+# Windows MinGw
+CFLAGS += -DWIN32
+#LDLIBS += -lws2_32
+LDOPT = winlnk
+else ifneq (, $(findstring cygwin, $(MAKE_HOST)))
+CFLAGS += -DWIN32
+# Windows CygWin
+LDOPT = winlnk
+else ifneq (, $(findstring msdos, $(MAKE_HOST)))
+# MSDOS
+LDOPT = doslnk
+MV = move
+endif
-TARBALL = $(PACKAGE)_$(shell date +%F).tgz
+# Targets
-ALLDOC = $(wildcard *.3) $(wildcard $(addprefix README.,$(NAMES)))
-ALLHEA = $(wildcard *.h) $(wildcard test/*.h)
-ALLSRC = $(wildcard *.c) $(wildcard test/*.c)
-ALLDEP = $(ALLSRC:.c=.d) $(addprefix $(LIBPRE),$(LIBDEP:.ld=.d))
-ALLTST = $(subst /,_,$(TESTS))
+ALLEXE =
+ALLEXE += morep_valid
SHELL = bash
+#MAKE = mingw32-make
MAKEFLAGS += -s
-
-DEBPKG = ../debian-pkg
-
-# Install
-
-DOCS = $(wildcard $(addprefix README.,$(NAMES))) COPYING makefile
-INCS = $(wildcard *.h)
-LIBS = $(LIBFUL) $(LIBNIC) $(LIBNAM) $(LIBSTA)
-MANS = $(wildcard *.3)
-TESS = $(wildcard test/*.c) $(wildcard test/*.h) test/makefile
-
-ifeq ($(DESTDIR),)
-DESTDIR = /usr/local
-endif
-
-BINDIR = $(DESTDIR)/bin
-LIBDIR = $(DESTDIR)/lib
-INCDIR = $(DESTDIR)/include/thales
-DOCDIR = $(DESTDIR)/share/doc/$(PACKAGE)
-MANDIR = $(DESTDIR)/share/man/man3
-TESDIR = $(DESTDIR)/share/doc/$(PACKAGE)/test
-
-INSTBIN = $(addprefix $(BINDIR)/, $(EXECS))
-INSTDOC = $(addprefix $(DOCDIR)/, $(DOCS))
-INSTINC = $(addprefix $(INCDIR)/, $(INCS))
-INSTLIB = $(addprefix $(LIBDIR)/, $(LIBS))
-INSTMAN = $(addprefix $(MANDIR)/, $(MANS))
-INSTTES = $(addprefix $(DOCDIR)/, $(TESS))
-
-FILES = $(INSTBIN) $(INSTDOC) $(INSTINC) $(INSTLIB) $(INSTMAN) $(INSTTES)
+include $(wildcard .makefile)
# Functions
-TITLE = { tput colors 2>/dev/null | grep -qE '8|256' && echo -en "\033[0;1m$(strip $(1))\033[0;0m:\t" || echo -en "$(strip $(1)):\t"; }
-INFO = { tput colors 2>/dev/null | grep -qE '8|256' && echo -e "\033[1;34m$(strip $(1))\033[0;0m" || echo -e "$(strip $(1))"; }
-PASS = { tput colors 2>/dev/null | grep -qE '8|256' && echo -e "\033[1;32m$(strip $(1))\033[0;0m" || echo -e "$(strip $(1))"; }
-WARN = { tput colors 2>/dev/null | grep -qE '8|256' && echo -e "\033[1;33m$(strip $(1))\033[0;0m" || echo -e "$(strip $(1))"; }
-FAIL = { tput colors 2>/dev/null | grep -qE '8|256' && echo -e "\033[1;31m$(strip $(1))\033[0;0m" || echo -e "$(strip $(1))"; }
-
-_GET = awk '{sub(/\/\/.*/,"")} /\/\* *$(1):.*\*\// { sub(/^.*\/\* *$(1): */, ""); sub(/ *\*\/.*$$/, ""); print }' $(2)
-GET = $(shell $(call _GET,$(1),$(2)))
-# $(shell ./getcomments.pl -p='$(1):\s' -f='%' $(2))
-
-_VER = sed 's/.*\.$(LIBEXT)\.\([0-9.]*\):.*/\1/' $(1)
-VER = $(shell $(call _VER,$(1)))
-PVER = $(shell $(call _VER,$(subst pack-,,$(1).ld)))
+TITLE = echo -en "\033[0;1m$(strip $(1))\033[0;0m:\t"
+PASS = echo -e "\033[1;32m$(strip $(1))\033[0;0m"
+WARN = echo -e "\033[1;33m$(strip $(1))\033[0;0m"
+FAIL = echo -e "\033[1;31m$(strip $(1))\033[0;0m"
MKDIR = mkdir -p $(1) && chmod a+rx,go-w $(1)
-INSTALL = test -d `dirname $(2)` || $(call MKDIR, `dirname $(2)`) && cp -pa $(1) $(2) && { chmod a+rX,go-w -f $(2); true; }
+INSTALL = test -d `dirname $(2)` || $(call MKDIR, `dirname $(2)`) && cp -pa $(1) $(2) && chmod a+rX,go-w $(2)
+
+VALID = $(call TITLE, $(1)) && $(2) && $(call PASS, SUCCESS) || { $(call FAIL, FAILED); test; }
-VALID = $(call TITLE, $(1)) && { $(2); } && $(call PASS, SUCCESS) || { $(call FAIL, FAILED); test; }
+GETCOMMENTS = awk '/\/\*\s*$(1):/,/\*\// { sub(/.*\/\*\s*$(1):/, ""); sub (/\s*\*\/.*/, ""); print } /\/\/\s*$(1):/ {sub (/.*\/\/\s*$(1):/, ""); print }' $(2)
+#GETCOMMENTS = perl -- getcomments.pl -p='$(1):\s' -f='%' $(2)
## Generic rules
all: depends
- make $(LIBNAM) $(LIBNIC) $(LIBSTA) $(TESTS)
-
-archive:
- $(call VALID, "Archiving $(TARBALL)", hg archive $(PACKAGE) && tar cfz ../$(TARBALL) $(PACKAGE); rm -rf $(PACKAGE))
-
-depends: $(ALLDEP)
+ $(MAKE) $(ALLEXE:%=%.exe)
count:
- $(call TITLE, "Counting")
- echo
- wc $(ALLHEA) $(ALLSRC) makefile $(ALLDOC)
+ wc $(wildcard *.c *.h) $(MAKEFILE_LIST)
clean:
$(call TITLE, "Cleaning")
touch clean
- rm -f $(wildcard *.[do] *.ho *~ test/*.[do] test/*.ho test/*~ web/*~ $(TESTS:=.log) $(TESTS:=.test)) clean
+ rm -f clean $(wildcard *.d *.ld *.log *.o *.test *~ .exec_* gmon.out _)
$(call PASS, SUCCESS)
-documentation: doxygen.conf $(wildcard *.[ch])
- $(call TITLE, "Publishing $@")
- doxygen $<; true
- $(call PASS, SUCCESS)
-
-gcov:
- make purge
- CFLAGS="-O0 -fprofile-arcs -ftest-coverage" LDFLAGS="-fprofile-arcs" make
-
-headers: $(ALLHEA:.h=.ho)
+depends: $(patsubst %.c, %.d, $(wildcard *.c)) $(patsubst %, %.ld, $(ALLEXE))
-install: $(FILES)
+gcovs:
+ $(MAKE) $(addprefix gcov_,$(ALLEXE))
-$(INSTBIN):$(BINDIR)/%:%
- $(call VALID, "File [$@]", $(call INSTALL, $<, $@))
-
-$(INSTDOC):$(DOCDIR)/%:%
- $(call VALID, "Documentation [$@]", $(call INSTALL, $<, $@))
-
-$(INSTINC):$(INCDIR)/%:%
- $(call VALID, "Include [$@]", $(call INSTALL, $<, $@))
-
-$(INSTLIB):$(LIBDIR)/%:%
- $(call VALID, "Library [$@]", $(call INSTALL, $<, $@))
-
-$(INSTMAN):$(MANDIR)/%:%
- $(call VALID, "Manpage [$@]", $(call INSTALL, $<, $@))
-
-$(INSTTES):$(TESDIR)/%:test/%
- $(call VALID, "Test file [$@]", $(call INSTALL, $<, $@))
- $(call VALID, "Adapt test [$@]", sed -i 's/"..\/\(.*\)"/<snd\/\1>/;/depend:/ s/: .* /: /' $@)
+gprofs:
+ $(MAKE) $(addprefix gprof_,$(ALLEXE))
purge: clean
$(call TITLE, "Purging")
touch purge
- rm -rf $(TESTS) $(LIBFUL) $(LIBNIC) $(LIBNAM) $(LIBSTA) $(wildcard *.gcda *.gcno *.gcov test/*.gcda test/*.gcno test/*.gcov) documentation purge
+ rm -f purge $(ALLEXE:%=%.exe)
$(call PASS, SUCCESS)
-%.test: %.c makefile
- $(call VALID, "Extracting $@", $(call _GET,test, $<) | sed 's;{};${<:.c=};g' > $@)
-
-test_%: test/%.test test/%
- $(call WARN, "Testing ${@:test_=}");
- IFS=$$'\n'; \
- LOGFILE=${<:.test=.log}; \
- rm -f $$LOGFILE; \
- for test in `cat $<`; do \
- $(call INFO, "=== $$test"); \
- eval $(VALGRIND) $$test 2>>$$LOGFILE; \
- done; \
- [ "`cat $<`" ] || { $(call INFO, "=== ${<:.test=}"); eval $(VALGRIND) ${<:.test=} 2>>$$LOGFILE; }; \
- true
+valgrinds:
+ $(MAKE) all
+ $(MAKE) $(addprefix valgrind_,$(ALLEXE))
-tests: $(ALLTST)
+wipe: purge
+ $(call TITLE, "Wiping")
+ touch wipe
+ rm -f wipe $(wildcard *.gcda *.gcno *.gcov *.glog)
+ $(call PASS, SUCCESS)
-valgrind_%:
- $(call WARN, "Activate valgrind")
- VALGRIND="valgrind -v --leak-check=full --show-reachable=yes --log-fd=2"; \
+tests:
+ -rm -f $(ALLEXE)
+ $(MAKE) all
+ $(MAKE) $(addprefix test_,$(ALLEXE))
+
+## Main rules
+
+include $(wildcard *.d)
+include $(wildcard *.ld)
+
+gcov_%:
+ $(MAKE) purge
+ $(MAKE) depends
+ OPTIONS="-coverage -O0" $(MAKE) ${@:gcov_%=%}.exe
+ $(MAKE) test_$(@:gcov_%=%)
+ gcov `sed -e 's/\.exe:/.c/;s/\.o/.c/g' $(@:gcov_%=%.ld)`
+ touch gcov
+ rm -f gcov $(wildcard *.gcda *.gcno)
+ $(MAKE) purge
+ grep '^ *#####' *.c.gcov || true
+
+gprof_%:
+ $(MAKE) purge
+ $(MAKE) depends
+ OPTIONS="-pg" $(MAKE) ${@:gprof_%=%}.exe
+ $(MAKE) ${@:gprof_%=%}.test
+ IFS=$$'\n'; id=1; \
+ for test in `cat ${@:gprof_%=%}.test | sed 's,${@:gprof_%=%}.exe,./${@:gprof_%=%}.exe,g'`; do \
+ log=${@:gprof_%=%}.prof-$$id.glog; \
+ $(call TITLE, test: $$test); \
+ echo $$test > $$log; \
+ eval $$test >> $$log; \
+ [ $$? -eq 0 ] \
+ && echo -e "\033[1;32mSUCCESS\033[0;0m" \
+ || echo -e "\033[1;31mFAILED\033[0;0m"; \
+ [ -f gmon.out ] && { gprof ${@:gprof_%=%}.exe gmon.out >> $$log; rm gmon.out; }; \
+ let id++; \
+ done;
+ $(MAKE) purge
+
+%.test: %.c
+ $(call TITLE, "Building $@")
+ $(call GETCOMMENTS,test, $<) > $@
+ $(call PASS, SUCCESS)
+ -rm -f _
+
+test_%: %.test %.exe
+ IFS=$$'\n'; RC=0; \
+ for test in `cat $< | sed 's,${<:.test=.exe},$(VALGRIND) ./${<:.test=.exe},g'`; do \
+ echo "=== $$test ==="; \
+ eval $$test; \
+ [ $$? -eq 0 ] && echo -e "\033[1;32mSUCCESS\033[0;0m" \
+ || { echo -e "\033[1;31mFAILED\033[0;0m"; RC=1; }; \
+ test "$$RC" = 1 -a "$(STOP)" = 1 && break; \
+ done; \
+ test "$$RC" -ne 1
+
+valgrind_%: %.exe
+ VALGRIND="valgrind -v --leak-check=full --log-fd=3"; \
export VALGRIND; \
- make ${@:valgrind_%=test_%}
+ $(MAKE) $(@:valgrind_%=test_%) 3>$@.log
%.d: %.c
- $(call VALID, "Creating $@", { \
- $(CC) $(IFLAGS) -MM $< -o - | sed "s;^`basename $(<:.c=.o)`;$(<:.c=.o);"; \
- echo $(call GET,depend, $<) | sed "s;^;$(<:.c=): $(<:.c=.o) ;"; \
- } > $@)
-
-lib%.d: %.ld
- $(call VALID, "Creating $@", sed 's/-l[^ ]*//g;s/\(.*\)\.$(LIBEXT)\.\([0-9]*\)\.\(.*\): \(.*\)/.\1.$(LIBEXT): \4\n\1.a: \4\n\1.$(LIBEXT).\2.\3: .\1.$(LIBEXT)\n\t$$(call VALID, "Assembling $$@", cp -f $$< $$@ \&\& rm $$<)\n\1.$(LIBEXT) \1.$(LIBEXT).\2: \1.$(LIBEXT).\2.\3\n\t$$(call VALID, "Assembling $$@", ln -sf $$< $$@)/' $< > $@)
-
-%.o: %.c
- $(call VALID, "Building $@", $(CC) $(CFLAGS) $(call GET,cflags, $<) -c $< -o $@)
-
-%.ho: %.h
- $(call VALID, "Building $@", $(CC) $(CFLAGS) $(call GET,cflags, $<) -x c -c $< -o $@)
-
-%.a:
- $(call VALID, "Archive $@", $(AR) -rc $@ $^)
-
-.$(LIBPRE)%:
- $(call TITLE, "Linking `echo $@ | sed 's/^\.//'`")
- $(CC) $(LDFLAGS) $$(cat `echo $@ | sed 's/\.$(LIBPRE)\(.*\)\.$(LIBEXT)/\1.ld/'` | sed 's/.*://') -shared -Wl,-soname=$$(cat `echo $@ | sed 's/\.$(LIBPRE)\(.*\)\.$(LIBEXT)/\1.ld/'` | sed 's/^\(.*\.$(LIBEXT)\.[0-9]*\)\..*/\1/') -o $@ || { $(call FAIL, FAILED); test; }
+ $(call TITLE, "Building $@")
+ $(CC) $(INCLUDES) -MM $< -o $@~
+ echo ${<:.c=.o}: $(shell $(call GETCOMMENTS,depends, $<)) >> $@~
+ $(MV) $@~ $@
$(call PASS, SUCCESS)
-$(PACKS):pack-%: %.ld depends
- $(call TITLE, "Packing $@-$(call VER,$<).tgz")
- [ ! -e $@ ] || rm -rf $@
- mkdir $@
- awk 'function alength(A, n, val) { n = 0; for (val in A) n++; return n } function a_sort(A, hold, i, j, n) { n = alength(A); for (i = 2; i <= n ; i++) { hold = A[j = i]; while (A[j-1] > hold) { j--; A[j+1] = A[j] } A[j] = hold } delete A[0 ]; return n } /\.o:/ { sub(/.*: */, ""); gsub (/\.o/, ".d"); t=t" "$$0 } END { split(t, a); a_sort(a); for (k in a) { if (prev != a[k]) print a[k]; prev=a[k] } }' `sed 's/.*://;s/\.o/.d/g;s/-l[^ ]*//' $<` | xargs -i% cp % $@
- cp $< makefile COPYING $(wildcard ${<:.ld=.3} README.${<:.ld=}) $@
- mkdir $@/test
- awk 'function alength(A, n, val) { n = 0; for (val in A) n++; return n } function a_sort(A, hold, i, j, n) { n = alength(A); for (i = 2; i <= n ; i++) { hold = A[j = i]; while (A[j-1] > hold) { j--; A[j+1] = A[j] } A[j] = hold } delete A[0 ]; return n } /$(LIBPRE)$(<:.ld=.$(LIBEXT))/ && ! /^$(LIBPRE)$(<:.ld=.$(LIBEXT))/ { sub(/.*: */, ""); gsub (/\.o/, ".d"); t=t" "$$0 } END { split(t, a); a_sort(a); for (k in a) { if ((prev != a[k]) && (a[k] != "$(LIBPRE)$(<:.ld=.$(LIBEXT))")) print a[k]; prev=a[k] } }' test/*.d | xargs awk 'function alength(A, n, val) { n = 0; for (val in A) n++; return n } function a_sort(A, hold, i, j, n) { n = alength(A); for (i = 2; i <= n ; i++) { hold = A[j = i]; while (A[j-1] > hold) { j--; A[j+1] = A[j] } A[j] = hold } delete A[0 ]; return n } /\.o:/ { sub(/.*: */, ""); gsub (/\.o/, ".d"); t=t" "$$0 } END { split(t, a); a_sort(a); for (k in a) { if ((prev != a[k]) && (a[k] != "\\") && !(a[k] ~ /\.\./)) print a[k]; prev=a[k] } }' | xargs -i% cp % $@/test
- cp test/makefile $@/test
- tar czf $@-$(call VER,$<).tgz $@
- rm -rf $@
+%.ld: %.c
+ $(call TITLE, "Building $@")
+ echo ${<:.c=.exe}: $(shell $(call GETCOMMENTS,$(LDOPT), $<) | awk '{for (i=1;i<=NF;i++) if ($$(i) ~ /.o$$/) printf " %s", $$(i)}') > $@
$(call PASS, SUCCESS)
-packages: $(PACKS)
+%.o: %.c
+ $(call TITLE, "Building $@")
+ $(CC) $(CFLAGS) $(INCLUDES) $(shell $(call GETCOMMENTS,cflags, $<)) -c $< -o $@
+ $(call PASS, SUCCESS)
-$(DEBIAN):debian-%: pack-%
- $(call TITLE, "Debian package: $(<:pack-%=%) "$(call PVER,$<))
- [ -d $(DEBPKG) ] || mkdir $(DEBPKG)
- [ ! -d $(DEBPKG)/$<-$(call PVER,$<) ] || rm -rf $(DEBPKG)/$<-$(call PVER,$<)
- [ ! -d $(DEBPKG)/$(<:pack-%=%)-$(call PVER,$<) ] || rm -rf $(DEBPKG)/$(<:pack-%=%)-$(call PVER,$<)
- tar xfz $<-$(call PVER,$<).tgz -C $(DEBPKG)
- mv $(DEBPKG)/$< $(DEBPKG)/$(<:pack-%=%)-$(call PVER,$<)
- cd $(DEBPKG); tar czf $(<:pack-%=%)_$(call PVER,$<).orig.tar.gz $(<:pack-%=%)-$(call PVER,$<)
- cp -par debian $(DEBPKG)/$(<:pack-%=%)-$(call PVER,$<)
- for f in $(DEBPKG)/$(<:pack-%=%)-$(call PVER,$<)/debian/*.$(<:pack-%=%); do mv $$f $${f/.$(<:pack-%=%)}; done
- cd $(DEBPKG)/$(<:pack-%=%)-$(call PVER,$<) && { echo; debuild; }
-debian: $(DEBIAN)
+%.exe: %.o %.d
+ $(call TITLE, "Building $@")
+ $(CC) $(LDFLAGS) $< $(shell $(call GETCOMMENTS,$(LDOPT), ${<:.o=.c})) $(LDLIBS) -o $@
+ $(call PASS, SUCCESS)
-test/%: test/%.o test/%.d
- $(call VALID, "Linking $@", $(CC) $(LDFLAGS) $(LFLAGS) $< $(call GET,linker, $(<:.o=.c)) -o $@)
+## Phony
-include $(wildcard *.d) $(wildcard test/*.d)
+.PHONY: all clean count depends gcovs purge tests
-## Phony
+## Precious
-.PHONY: all archive clean count depends headers install packages purge
+.PRECIOUS: %.d %.o
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
+
#if WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#define SETBLOCK(fd) fcntl (fd, F_SETFL, 0)
#define SETNOBLK(fd) fcntl (fd, F_SETFL, 0_NONBLOCK)
#endif
+
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include "debug.h"
+#include "verbose.h"
#include "morep.h"
MOREP address structure
*/
typedef struct {
- enum { MOREP_error, MOREP_tx, MOREP_rx } mode;
- char mac_address[17];
+ char mac_address[18];
+ uint16_t ether_type;
uint8_t mac[6];
} MOREP_addr_t;
*/
typedef struct {
int sock;
- struct sockaddr_ll sock_addr;
- uint16_t short tx_seqnum;
- uint16_t short rx_seqnum;
- unsigned char tx_buffer[9014]; // jumbo frame (1514 standard frame)
- unsigned char rx_buffer[9014]; // jumbo frame (1514 standard frame)
- int is_blocking;
+ uint8_t seqnum;
+ uint8_t tx_buffer[9014]; // jumbo frame (1514 standard frame)
+ uint8_t rx_buffer[9014]; // jumbo frame (1514 standard frame)
} MOREP_descriptor_t ;
/**
List of private descriptor associated to each connected MORE.
*/
+
MOREP_descriptor_t *MOREP_list[MAX_MOREP_NUMBER] = { 0 };
/**
}
}
-int _parse_mac (char *hexa_str, MOREP_addr_t *addr)
+int parse_ifname (MOREP_addr_t *addr, char *url)
{
- VERBOSE (morep, TRACE, FPRINTF (stdout, "free_all_moreps\n"));
+ VERBOSE (morep, TRACE, PRINTF ("parse_ifname\n"));
- /* MAC address format: XX:XX:XX:XX:XX:XX */
- if (strlen (hexa_str) != 17) {
- VERBOSE (morep, WARNING, PRINTF ("incorrect mac address format (%s)\n", hexa));
- return -1;
+ char *pt = strchr (url, ':');
+ if ((pt == NULL) || (pt[1] != '/') || (pt[2] != '/')) {
+ VERBOSE (morep, WARNING, PRINTF ("can't parse interface name '%s'(%d) \n", url));
+ return NULL;
}
- int i;
- for (int i = 0; i < 6; i++) {
- char one_byte[3] = "xx";
- char ptr = NULL;
- memcpy (one_byte, hexa + 3 * i, 2);
+ char *ifname = (char *) calloc (pt - url + 1, 1);
+ assert (ifname);
+ strncpy (ifname, url, pt - url);
+
+ return ifname;
+}
+
+int parse_mac (MOREP_addr_t *addr, char *url)
+{
+ VERBOSE (morep, TRACE, PRINTF ("parse_mac\n"));
- mac[i] = strtoul (one_byte, NULL, 16, &ptr);
- if ((ptr != NULL) || ((i < 5) && (hexa[3 * i + 2] != ':'))) {
- VERBOSE (morep, WARNING, PRINTF ("can't parse mac address (%s)\n", hexa));
- return -1;
+ /* MAC address format: XX:XX:XX:XX:XX:XX/... */
+ int i, j;
+ for (i = j = 0; i < 6; i++) {
+ if (url[j] == 0) {
+ break;
+ }
+ mac_address[j] = url[j];
+ j++;
+ if (url[j] == 0) {
+ break;
+ }
+ mac_address[j] = url[j];
+ j++;
+ if (url[j] != (i < 5) ? ':' : '/') {
+ break;
+ }
+ mac_address[j++] = '\0';
+ char ptr = NULL;
+ addr->mac[i] = strtoul (mac_address + 3 * i, &ptr, 16);
+ if (ptr != NULL) {
+ break;
+ }
+ if (i < 5) {
+ mac_address[j - 1] = ':';
}
}
+
+ if (j != 18)
+ VERBOSE (morep, WARNING, PRINTF ("can't parse mac address '%s'(%d) \n", url, j));
+ return -1;
+ }
+
+ return 0;
+}
+
+int parse_ethertype (MOREP_addr_t *addr, char *url)
+{
+ VERBOSE (morep, TRACE, PRINTF ("parse_ethertype\n"));
+
+ /* ETHERTYPE format: XXXXX */
+ char ptr = NULL;
+ addr->ether_type = strtoul (url, &ptr, 16);
+ if (ptr != NULL) {
+ VERBOSE (morep, WARNING, PRINTF ("can't parse ethertype numbe (hexa) '%s'\n", url));
+ return -1;
+ }
return 0;
}
-int _get_interface_index (char *ifname)
+int get_interface_index (char *ifname)
{
- VERBOSE (morep, TRACE, FPRINTF (stdout, "_get_interface_index\n"));
+ VERBOSE (morep, TRACE, PRINTF ("get_interface_index\n"));
struct ifreq ifr = {0};
strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
return ifr.ifr_ifindex;
}
-int _get_mac_address (char *ifname, uint8_t *mac)
+int get_mac_address (char *ifname, uint8_t *mac)
{
- VERBOSE (morep, TRACE, FPRINTF (stdout, "_get_mac_address\n"));
+ VERBOSE (morep, TRACE, PRINTF ("get_mac_address\n"));
struct ifreq ifr = {0};
strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
return -1;
}
- unsigned char *p = (unsigned char *)ifr.ifr_hwaddr.sa_data;
- for (int i = 0; i < 6; i++) {
+ uint8_t *p = (unsigned char *)ifr.ifr_hwaddr.sa_data;
+ int i;
+ for (i = 0; i < 6; i++) {
mac[i] = *p++;
}
return 0;
}
-int MOREP_open (const char *ifname, const char *mac_address, unsigned short EthType)
+void mactoa (char *str, uint8_t *mac)
{
- VERBOSE (morep, TRACE, FPRINTF (stdout, "MOREP_open\n"));
-
- this->mac_address = strdup(mac_address);
-
- parse_mac(mac_address, this->remote_mac);
-
- sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
- if (sock < 0) {
- VERBOSE (VERBOSE_ERROR, printf ("socket(): %s\n", strerror (errno)));
- VERBOSE (VERBOSE_ERROR, printf("Warning: you must be root to have raw access to sockets\n"));
- return -1;
- }
-
- memset(&sock_addr, 0, sizeof (struct sockaddr_ll));
-
- sock_addr.sll_family = PF_PACKET;
- sock_addr.sll_protocol = htons(EthType);
- sock_addr.sll_ifindex = Get_IfaceIndex(ifname);
- if (sock_addr.sll_ifindex < 0) return -1;
- sock_addr.sll_hatype = ARPHRD_ETHER;
- sock_addr.sll_pkttype = PACKET_OTHERHOST;
- sock_addr.sll_halen = ETH_ALEN;
- if (Get_MacAddress(ifname, sock_addr.sll_addr) != 0) {
- printf("Cannot get local mac address for %s\n", ifname);
- return -1;
- }
-
- int res = bind(sock, (struct sockaddr *) & sock_addr, sizeof (sock_addr));
- if (res != 0) {
- VERBOSE (VERBOSE_ERROR, printf ("bind(): %s\n", strerror (errno)));
- return -1;
- }
-
- printf("I/O on %s local=[", ifname);
- for (int i = 0; i < 6; i++) {
- printf("%02x", sock_addr.sll_addr[i]);
- if (i < 5) printf(":");
- } printf("]\n");
-
- eth_type = htons(EthType);
- memset(TxBuf, 0, sizeof (TxBuf));
- memcpy(TxBuf, (void *) remote_mac, 6);
- memcpy(TxBuf + 6, sock_addr.sll_addr, 6);
- memcpy(TxBuf + 12, (void *) & eth_type, 2);
-
- return 0;
-}
-
-
-struct in_addr **addr_list;
- char url_to_parse[256] = { 0 };
-
- strncpy (url_to_parse, ascii_url, sizeof (url_to_parse) - 1);
- if (strncmp (url_to_parse, "udp://", 6) == 0)
- addr->type = SAP_udp;
- else if (strncmp (url_to_parse, "tcp://", 6) == 0)
- addr->type = SAP_tcp;
- else
- return -1;
-
- char *hostname = strtok (url_to_parse + 6, ":");
- char *port = strtok (NULL, ":");
- if ((hostname == NULL) || (port == NULL)) {
- errno = EINVAL;
- return -1;
- }
-
- addr->sockaddr.sin_family = AF_INET;
- addr->sockaddr.sin_port = htons (atoi (port));
-
- VERBOSE (sap, 1, PRINTF ("parse URL %s %s\n", hostname, port));
-
- if (hostname[0] != '*') {
- struct hostent *he = gethostbyname (hostname);
- if (he == NULL) {
- errno = EHOSTUNREACH;
- return -1;
- }
-
- addr_list = (struct in_addr **) he->h_addr_list;
- addr->sockaddr.sin_addr.s_addr = addr_list[0]->s_addr;
- } else {
- addr->sockaddr.sin_addr.s_addr = INADDR_ANY;
+ int i;
+ for (i = 0; i < 6; i++) {
+ int d = mac[i] / 16;
+ str[3 * i] = d + ((d > 9) ? 'A' - 10 : '0');
+ d = mac[i] % 16;
+ str[3 * i + 1] = d + ((d > 9) ? 'A' - 10 : '0');
+ str[3 * i + 2] = ':';
}
-
- return 0;
+ str[17] = '\0';
}
-static inline int sap_create_and_listen (char *local_address, int doListen,
- int port_offset)
+int alloc_morep (int sock)
{
- SAP_addr_t addr;
- int sap;
-
- VERBOSE (sap, 1, PRINTF ("SAP local addr %s\n", local_address));
- int rc = parse_url (local_address, &addr);
-
- addr.sockaddr.sin_port =
- htons (ntohs (addr.sockaddr.sin_port) + port_offset);
- VERBOSE (sap, 1, PRINTF ("local port: %d\n", ntohs (addr.sockaddr.sin_port)));
-
- if (rc < 0) {
- errno = EINVAL;
- return rc;
- }
+ VERBOSE (morep, TRACE, PRINTF ("morep_descriptor_t\n"));
- switch (addr.type) {
- case SAP_tcp:
- sap = socket (PF_INET, SOCK_STREAM, 0);
- if (sap >= 0) {
- int val = 1;
- setsockopt (sap, SOL_SOCKET, SO_REUSEADDR, (OPT_TYPE *)&val, sizeof (val));
- rc = bind (sap, (struct sockaddr *)&addr.sockaddr, sizeof (addr.sockaddr));
- if (rc < 0)
- return rc;
- if (doListen) {
- rc = listen (sap, 5);
- if (rc < 0) return rc;
- }
- }
- break;
- case SAP_udp:
- sap = socket (PF_INET, SOCK_DGRAM, 0);
- if (sap >= 0) {
- int val = 1;
- setsockopt (sap, SOL_SOCKET, SO_REUSEADDR, (OPT_TYPE *)&val, sizeof (val));
- rc = bind (sap, (struct sockaddr *)&addr.sockaddr, sizeof (addr.sockaddr));
- if (rc < 0)
- return rc;
+ int i;
+ for (i = 0; i < MAX_MOREP_NUMBER; i++) {
+ if (MOREP_list[i] == NULL) {
+ break;
}
- break;
- default:
- errno = EINVAL;
+ }
+ if (i == MAX_MOREP_NUMBER) {
+ VERBOSE (morep, WARNING, PRINTF ("can't find avaliable morep descriptor\n"));
return -1;
- break;
}
- SETNOBLK (sap);
-
- return sap;
-}
-
-int SAP_Create (char *local_address)
-{
- return sap_create_and_listen (local_address, 1, 0);
-}
+ MOREP_list[i] = (morep_descriptor_t *) calloc (sizeof (morep_descriptor_t), 1);
+ assert (MOREP_list[i]);
-int SAP_Connect (char *local_address, char * remote_address)
-{
- return SAP_Connect_Offset (local_address, remote_address, 0);
+ return i;
}
-int SAP_Connect_Offset (char *local_address, char *remote_address, int port_offset)
+int MOREP_Connect (char *url)
{
- SAP_addr_t addr;
- int sap;
- int rc = parse_url (remote_address, &addr);
-
- addr.sockaddr.sin_port =
- htons (ntohs (addr.sockaddr.sin_port) + port_offset);
- VERBOSE (sap, 1, PRINTF ("remote port: %d\n", ntohs (addr.sockaddr.sin_port)));
-
- if (rc < 0) {
- errno = EINVAL;
- return rc;
- }
-
- if (local_address) {
- sap = sap_create_and_listen (local_address, 0, port_offset);
- } else {
- switch (addr.type) {
- case SAP_tcp:
- sap = socket (PF_INET, SOCK_STREAM, 0);
- break;
- case SAP_udp:
- sap = socket (PF_INET, SOCK_DGRAM, 0);
- break;
- default:
- errno = EINVAL;
- return -1;
- }
+ VERBOSE (morep, TRACE, PRINTF ("MOREP_Connect\n"));
+
+ /* parse url */
+ MOREP_addr_t addr = {0};
+ char *ifname = parse_ifname (url);
+ if ((ifname == NULL != 0) ||
+ (parse_mac (&addr, url + strlen (url) + 3) != 0) ||
+ (parse_ethertype (&addr, url + strlen (url) + 21) != 0)) {
+ VERBOSE (morep, ERROR, PRINTF ("can't parse url (%s)\n", url));
+ return -1;
}
- if (sap < 0)
- return sap;
- if (sap >= MAX_SAP_NUMBER) {
- errno = ENOMEM;
+ int sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
+ if (sock < 0) {
+ VERBOSE (morep, ERROR, PRINTF ("socket(): %s\n", strerror (errno)));
+ VERBOSE (morep, ERROR, PRINTF ("Warning: you must be root to have raw access to sockets\n"));
return -1;
}
- SETNOBLK (sap);
- rc = connect (sap, (struct sockaddr *)&addr.sockaddr, sizeof (addr.sockaddr));
-
- if (addr.type == SAP_tcp) {
- int val = 1;
- rc = setsockopt (sap, IPPROTO_TCP, TCP_NODELAY, (OPT_TYPE *)&val, sizeof (val));
- if (rc < 0)
- perror ("setsockopt/TCP_NODELAY");
+ /* get local mac address */
+ struct sockaddr_ll sock_addr = {0};
+ sock_addr.sll_family = PF_PACKET;
+ sock_addr.sll_protocol = htons (addr->ethertype);
+ sock_addr.sll_ifindex = get_interface_index (ifname);
+ if (sock_addr.sll_ifindex < 0) {
+ VERBOSE (morep, ERROR, PRINTF ("can't get interface index for '%s': %s\n", ifname, strerror (errno)));
+ free (ifname);
+ return -1;
}
-
- assert (SAP_list[sap] == NULL);
- SAP_list[sap] = (SAP_descriptor_t *) calloc (1, sizeof (SAP_descriptor_t));
- assert (SAP_list[sap]);
- if (__sync_bool_compare_and_swap (&__init, 1, 0))
- atexit (free_saps);
-
- return sap;
-}
-
-int SAP_IsConnected (int sap)
-{
- int sockerr;
- socklen_t rlen = sizeof (sockerr);
-
- int rc = getsockopt (sap, SOL_SOCKET, SO_ERROR, (OPT_TYPE *)&sockerr, &rlen);
- if (rc < 0)
+ sock_addr.sll_hatype = ARPHRD_ETHER;
+ sock_addr.sll_pkttype = PACKET_OTHERHOST;
+ sock_addr.sll_halen = ETH_ALEN;
+ if (get_mac_address(ifname, sock_addr.sll_addr) != 0) {
+ VERBOSE (morep, ERROR, PRINTF ("can't get mac address for '%s'\n", ifname));
+ free (ifname);
return -1;
-
- switch (sockerr) {
- case 0:
- return 1;
- break;
- case EINPROGRESS:
- return 0;
- break;
}
- return -1;
-}
-
-int SAP_Accept (int sap)
-{
- int newsap = accept (sap, NULL, 0);
- if (newsap < 0)
- return newsap;
- if (newsap >= MAX_SAP_NUMBER) {
- errno = ENOMEM;
+ /* bind socket */
+ if (bind (sock, (struct sockaddr *)&sock_addr, sizeof (sock_addr)) != 0) {
+ VERBOSE (morep, ERROR, printf ("can't bind '%s': %s\n", url, strerror (errno)));
+ free (ifname);
return -1;
}
- assert (SAP_list[newsap] == NULL);
-
- SAP_list[newsap] = (SAP_descriptor_t *)calloc (1, sizeof (SAP_descriptor_t));
- assert (SAP_list[newsap]);
- if (__sync_bool_compare_and_swap (&__init, 1, 0))
- atexit (free_saps);
-
- SETNOBLK (newsap);
- int val = 1;
- int rc = setsockopt (newsap, IPPROTO_TCP, TCP_NODELAY, (OPT_TYPE *)&val, sizeof (val));
- if (rc < 0)
- perror ("setsockopt/TCP_NODELAY");
-
- return newsap;
-}
-
-void SAP_Reject (int sap)
-{
- int newsap = accept (sap, NULL, 0);
- close (newsap);
-}
-
-void SAP_Close (int sap)
-{
- if ((sap < 0) || (sap >= MAX_SAP_NUMBER))
- return;
- close (sap);
- if (SAP_list[sap]) {
- free (SAP_list[sap]);
- SAP_list[sap] = NULL;
+ /* info message */
+ char lmac[18] = {0};
+ mactoa (lmac, sock_addr.sll_addr);
+ VERBOSE (morep, INFO, PRINTF ("I/O on %s local=[%s]\n", ifname, lmac));
+ free (ifname);
+
+ /* store connection */
+ int index = alloc_morep ();
+ if (i >= 0) {
+ MOREP_list[i]->sock = sock;
+ memcpy (MOREP_list[i]->tx_buffer, (void *) addr->mac, 6);
+ memcpy (MOREP_list[i]->tx_buffer + 6, sock_addr.sll_addr, 6);
+ uint16_t ether_type = htons (addr->ether_type);
+ memcpy (MOREP_list[i]->tx_buffer + 12, (void *) ðer_type, 2);
}
-}
-void SAP_Set_Blocking (int sap)
-{
- SETBLOCK (sap);
- if (SAP_list[sap])
- SAP_list[sap]->is_blocking = 0;
+ return sock;
}
-int SAP_Send (int sap, unsigned long msgtype, unsigned char *data, int len)
+uint8_t *MOREP_Get_Tx_Buffer (int index)
{
-
- /* Message format is
- * bytes 0-1 : len
- * bytes 2-3 : seqnumber
- * bytes 4-7 : msgtype
- * bytes 8- : data
- */
-
- assert (((data != NULL) && (len > 0)) || ((data == NULL) && (len == 0)));
-
- int msglen = len + 8;
-
- if ((sap < 0) || (sap >= MAX_SAP_NUMBER) || (SAP_list[sap] == NULL)) {
- errno = EBADF;
- return -1;
+ if ((index < 0) || (index >= MAX_MOREP_NUMBER) ||
+ (MOREP_list[index] == NULL)) {
+ VERBOSE (morep, ERROR, PRINTF ("incorrect MOREP descriptor (%d)\n", index));
+ return NULL;
}
- unsigned char *buffer = calloc (1, msglen);
- if (buffer == NULL) {
- errno = ENOBUFS;
- return -1;
- }
-
- *(unsigned short *)buffer = htons (len);
- *(unsigned short *)(buffer + 2) = SAP_list[sap]->tx_seqnum++;
- *(unsigned long *)(buffer + 4) = htonl (msgtype);
- if (len > 0)
- memcpy (buffer + 8, data, len);
-
- int rc = write (sap, buffer, msglen);
- free (buffer);
-
- return (rc >= 0) ? rc - 8 : rc;
+ return MOREP_list[index]->tx_buffer + 18;
}
-int SAP_Send_Raw (int sap, unsigned long msgtype, unsigned char *data, int len)
+int MOREP_Send (int index, uint8_t msgtype, int len)
{
/* Message format is
- * bytes 0-1 : len
- * bytes 2-3 : seqnumber
- * bytes 4-7 : msgtype
- * bytes 8- : data
+ * bytes 0 : msgtype
+ * bytes 1 : seqnumber
+ * bytes 2-3 : len
+ * bytes 4- : data
*/
- int msglen = len + 8;
-
- if ((sap < 0) || (sap >= MAX_SAP_NUMBER) || (SAP_list[sap] == NULL)) {
- errno = EBADF;
- return -1;
- }
-
- unsigned char *buffer = calloc (1, msglen);
- if (buffer == NULL) {
- errno = ENOBUFS;
+ if ((len < 0) || (len > 9014 - 18) ||
+ ((data == NULL) && (len > 0)) ||
+ ((data != NULL) && (len == 0)) ||
+ ((index < 0) || (index >= MAX_MOREP_NUMBER)) ||
+ (MOREP_list[index] == NULL)) {
+ VERBOSE (morep, ERROR, PRINTF ("incorrect MOREP descriptor (%d)\n", index));
return -1;
}
- *(unsigned short *)buffer = htons (len);
- *(unsigned short *)(buffer + 2) = SAP_list[sap]->tx_seqnum++;
- *(unsigned long *)(buffer + 4) = htonl (msgtype);
- memcpy (buffer + 8, data, len);
+ MOREP_descriptor_t *morep = MOREP_list[index];
+ morep->tx_buffer[0] = msgtype;
+ morep->tx_buffer[1] = morep->seqnum++;
+ uint16_t msglen = htons (mlen);
+ memcpy (morep->tx_buffer + 2, (void *) &msglen, 2);
- int rc = write (sap, buffer, msglen);
- free (buffer);
+ int rc = sendto (morep->sock, morep->tx_buffer, nb + 18, 0, NULL, 0);
- return (rc >= 0) ? rc - 8 : rc;
+ return (rc < 18) ? -1 : rc - 18;
}
-int SAP_Receive_timeout (int sap, unsigned long *msgtype, unsigned char *buffer,
- int buflen, int microseconds)
+int MOREP_Receive (int sock)
{
-
- fd_set rfds;
- struct timeval tv = { 0, microseconds };
- FD_ZERO (&rfds);
- FD_SET (sap, &rfds);
-
- int retval = select (sap + 1, &rfds, NULL, NULL, &tv);
- if (retval != 1)
- return retval;
-
- return SAP_Receive (sap, msgtype, buffer, buflen);
+ return -1;
}
-int SAP_Receive (int sap, unsigned long *msgtype, unsigned char *buffer, int buflen)
-{
- int len;
- int closed = 0;
-
- if ((sap < 0) || (sap >= MAX_SAP_NUMBER) || (SAP_list[sap] == NULL)) {
- errno = EBADF;
- return -1;
- }
-
- /* Read has much has possible in our internal buffer */
- /* put received data after remaining data from previous read */
-
- uint8_t *value = SAP_list[sap]->buffer;
- if ((SAP_list[sap]->remain <= 8) ||
- (ntohs (*(uint16_t *)value) > SAP_list[sap]->remain + 8)) {
-
- int rc = read (sap, SAP_list[sap]->buffer + SAP_list[sap]->remain,
- sizeof (SAP_list[sap]->buffer) - SAP_list[sap]->remain);
-
- if (rc == 0)
- closed = -1;
-
- if ((rc < 0) && (errno != EAGAIN))
- return -1;
-
- if (rc > 0)
- SAP_list[sap]->remain += rc;
- }
-
- /* Message header not fully received */
- if (SAP_list[sap]->remain <= 8)
- return closed;
-
- /* Payload of message not fully received */
- len = ntohs (*(unsigned short *)value);
- if (len > SAP_list[sap]->remain + 8)
- return closed;
-
- if (buflen < len) {
- VERBOSE (sap, 0, FPRINTF (stderr, "buflen %d < len %d (0x%X)\n", buflen, len, len));
- return -ENOBUFS;
- }
-
- unsigned short seqnumber =
- ntohs (*(unsigned short *)(SAP_list[sap]->buffer + 2));
- if ((SAP_list[sap]->is_blocking) &&
- (seqnumber != ((SAP_list[sap]->rx_seqnum + 1) & 0xffff)))
- VERBOSE (sap, 0, FPRINTF (stderr, "missing sequence number\n"));
- SAP_list[sap]->rx_seqnum = seqnumber;
-
- *msgtype = ntohl (*(unsigned long *)(SAP_list[sap]->buffer + 4));
- memcpy (buffer, SAP_list[sap]->buffer + 8, len);
-
- /* Move remaining data to begin of private buffer */
- SAP_list[sap]->remain -= len + 8;
- memmove (SAP_list[sap]->buffer, SAP_list[sap]->buffer + 8 + len, SAP_list[sap]->remain);
-
- return len;
-}
/* vi:set tabstop=4 expandtab shiftwidth=4: this line set vi mode*/