-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit f55ebe8
Showing
24 changed files
with
1,483 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
*.d | ||
*.o | ||
*.a | ||
*.pc | ||
.gdb_history | ||
|
||
# C extensions | ||
*.so* | ||
*.out |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
|
||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
|
||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
PROJECT = inet46i | ||
|
||
MULTIARCH ?= $(shell $(CC) --print-multiarch) | ||
|
||
PREFIX ?= /usr | ||
INCLUDEDIR ?= /include | ||
LIBDIR ?= /lib/$(MULTIARCH) | ||
|
||
DEBUG ?= 1 | ||
ifeq ($(DEBUG), 1) | ||
RELEASE ?= 0 | ||
else | ||
RELEASE ?= 1 | ||
endif | ||
|
||
# default | ||
CPPFLAGS ?= -fdiagnostics-color=always | ||
ifeq ($(RELEASE), 0) | ||
CFLAGS ?= -Os -fPIC | ||
else | ||
CFLAGS ?= -O2 -fPIC | ||
endif | ||
LDFLAGS ?= | ||
|
||
# debug | ||
ifeq ($(DEBUG), 1) | ||
CFLAGS += -g | ||
endif | ||
ifeq ($(RELEASE), 0) | ||
CPPFLAGS += -DDEBUG | ||
endif | ||
|
||
# hardening | ||
CPPFLAGS += -D_FORTIFY_SOURCE=2 | ||
CFLAGS += -fstack-protector-strong | ||
LDFLAGS += -Wl,-z,relro | ||
|
||
# diagnosis | ||
CWARN ?= -Wall -Wextra -Wpedantic -Werror=format-security \ | ||
-Wno-cast-function-type -Wno-missing-field-initializers | ||
ifeq ($(DEBUG), 1) | ||
CWARN += -fanalyzer | ||
endif | ||
CFLAGS += $(CWARN) | ||
|
||
# program flags | ||
CPPFLAGS += -D_DEFAULT_SOURCE | ||
CFLAGS += -std=c2x -fms-extensions | ||
LDFLAGS += -Wl,--gc-sections -flto=auto -fwhole-program | ||
|
||
HEADERS := $(wildcard inet46i/*.h) | ||
SOURCES := $(wildcard inet46i/*.c) | ||
OBJS := $(sort $(SOURCES:.c=.o)) | ||
PREREQUISITES := $(SOURCES:.c=.d) | ||
THIS_MAKEFILE_LIST := $(MAKEFILE_LIST) | ||
|
||
LIB_NAME := lib$(PROJECT).so | ||
SO_NAME := $(LIB_NAME).0 | ||
REAL_NAME := $(LIB_NAME).0.0 | ||
|
||
ARLIB := lib$(PROJECT).a | ||
SHLIB := $(SO_NAME) | ||
PCFILE := $(PROJECT).pc | ||
|
||
.PHONY: all | ||
all: $(ARLIB) $(SHLIB) $(PCFILE) | ||
|
||
.PHONY: clean | ||
clean: | ||
rm -f $(ARLIB) $(SHLIB) $(OBJS) $(PCFILE) $(PREREQUISITES) | ||
|
||
%.d: %.c | ||
$(CC) -M $(CPPFLAGS) $< | sed 's,.*\.o *:,$(<:.c=.o) $@: $(THIS_MAKEFILE_LIST),' > $@ | ||
|
||
-include $(PREREQUISITES) | ||
|
||
$(ARLIB): $(OBJS) | ||
$(AR) rcs $@ $^ | ||
|
||
$(SHLIB): $(OBJS) | ||
$(CC) -shared -Wl,-soname,$(SO_NAME) $(LDFLAGS) -o $@ $^ | ||
|
||
$(PCFILE): $(PCFILE).in | ||
sed 's|@prefix@|$(PREFIX)|; s|@libdir@|$(LIBDIR)|; s|@includedir@|$(INCLUDEDIR)|' $< > $@ | ||
|
||
.PHONY: install-shared | ||
install-shared: $(SHLIB) | ||
install -d $(DESTDIR)$(PREFIX)$(LIBDIR) || true | ||
install -m 0644 $< $(DESTDIR)$(PREFIX)$(LIBDIR)/$(REAL_NAME) | ||
rm -f $(DESTDIR)$(PREFIX)$(LIBDIR)/$(SO_NAME) | ||
ln -s $(REAL_NAME) $(DESTDIR)$(PREFIX)$(LIBDIR)/$(SO_NAME) | ||
rm -f $(DESTDIR)$(PREFIX)$(LIBDIR)/$(LIB_NAME) | ||
ln -s $(SO_NAME) $(DESTDIR)$(PREFIX)$(LIBDIR)/$(LIB_NAME) | ||
|
||
.PHONY: install-static | ||
install-static: $(ARLIB) | ||
install -d $(DESTDIR)$(PREFIX)$(LIBDIR) || true | ||
install -m 0644 $< $(DESTDIR)$(PREFIX)$(LIBDIR)/$(ARLIB) | ||
|
||
.PHONY: install-header | ||
install-header: $(HEADERS) $(PCFILE) | ||
install -d $(DESTDIR)$(PREFIX)$(INCLUDEDIR)/$(PROJECT) || true | ||
install -m 0644 $(HEADERS) $(DESTDIR)$(PREFIX)$(INCLUDEDIR)/$(PROJECT)/ | ||
install -d $(DESTDIR)$(PREFIX)$(LIBDIR)/pkgconfig || true | ||
install -m 0644 $(PCFILE) $(DESTDIR)$(PREFIX)$(LIBDIR)/pkgconfig | ||
|
||
.PHONY: install | ||
install: install-shared install-static install-header |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# libinet46i | ||
|
||
Use the same code to process sockets of IPv4 (`AF_INET`), IPv6 (`AF_INET6`) and the interface name (`SO_BINDTODEVICE`). | ||
|
||
Docs to be added. Feel free to ask for it. | ||
|
||
## Why there is a policy-based socket routing? | ||
|
||
You may want to 'listen' to a specific interface as if an IP address, however Linux won't allow you to open two sockets binding to 0.0.0.0 listening to the same port. Routing must be done in user programs. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
prefix=@prefix@ | ||
libdir=${prefix}@libdir@ | ||
includedir=${prefix}@includedir@ | ||
|
||
Name: inet46i | ||
Description: AF_INET + AF_INET6 + SO_BINDTODEVICE | ||
Version: @version@ | ||
URL: https://github.com/yangfl/libinet46i | ||
Libs: -L${libdir} -linet46i | ||
Cflags: -I${includedir}/inet46i |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
#ifndef INET46I_ENDIAN_H | ||
#define INET46I_ENDIAN_H | ||
|
||
|
||
#define __inet46i_move_byte(type, x, from, to) \ | ||
((((type) (x) >> ((from) * 8)) & 0xff) << ((to) * 8)) | ||
#if __BYTE_ORDER == __BIG_ENDIAN | ||
#define lhtons(x) (x) | ||
#define lhtonl(x) (x) | ||
#endif | ||
#if __BYTE_ORDER == __LITTLE_ENDIAN | ||
#define lhtons(x) ( \ | ||
__inet46i_move_byte(uint16_t, x, 0, 1) | \ | ||
__inet46i_move_byte(uint16_t, x, 1, 0) \ | ||
) | ||
#define lhtonl(x) ( \ | ||
__inet46i_move_byte(uint32_t, x, 0, 3) | \ | ||
__inet46i_move_byte(uint32_t, x, 1, 2) | \ | ||
__inet46i_move_byte(uint32_t, x, 2, 1) | \ | ||
__inet46i_move_byte(uint32_t, x, 3, 0) \ | ||
) | ||
#endif | ||
|
||
|
||
#endif /* INET46I_ENDIAN_H */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#include <netinet/in.h> | ||
|
||
#include "in46.h" | ||
|
||
|
||
extern inline int in6_normalize (struct in6_addr *addr); | ||
extern inline int in_to6 (void *addr); | ||
extern inline int in6_to4 (void *addr); | ||
extern inline int in46_is_addr_unspecified (int af, void *addr); | ||
extern inline int in64_set (int af, void *dst, const void *src); | ||
extern inline void *in64_get (int af, const void *addr); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
#ifndef INET46I_IN46_H | ||
#define INET46I_IN46_H | ||
|
||
#include <errno.h> | ||
#include <stddef.h> | ||
#include <net/if.h> | ||
#include <netinet/in.h> | ||
|
||
#include "endian.h" | ||
|
||
|
||
#define IN6_SET_ADDR_V4MAPPED(a) ( \ | ||
((struct in6_addr *) (a))->s6_addr32[0] = 0, \ | ||
((struct in6_addr *) (a))->s6_addr32[1] = 0, \ | ||
((struct in6_addr *) (a))->s6_addr32[2] = lhtonl(0xffff) \ | ||
) | ||
#define IN6_IS_ADDR_V4OK(a) ( \ | ||
((struct in6_addr *) (a))->s6_addr32[0] == 0 && \ | ||
((struct in6_addr *) (a))->s6_addr32[1] == 0 && \ | ||
(((struct in6_addr *) (a))->s6_addr32[2] == 0 || \ | ||
((struct in6_addr *) (a))->s6_addr32[2] == lhtonl(0xffff)) \ | ||
) | ||
|
||
__attribute__((nonnull)) | ||
inline int in6_normalize (struct in6_addr *addr) { | ||
if (IN6_IS_ADDR_V4COMPAT(addr)) { | ||
addr->s6_addr32[2] = lhtonl(0xffff); | ||
} | ||
if (IN6_IS_ADDR_V4MAPPED(addr)) { | ||
if (addr->s6_addr32[3] == lhtonl(0)) { | ||
addr->s6_addr32[2] = 0; | ||
return 1; | ||
} | ||
if ((addr->s6_addr32[3] & lhtonl(IN_CLASSA_NET)) == | ||
lhtonl(INADDR_LOOPBACK & IN_CLASSA_NET)) { | ||
addr->s6_addr32[2] = 0; | ||
addr->s6_addr32[3] = lhtonl(1); | ||
return 1; | ||
} | ||
} | ||
return 0; | ||
} | ||
|
||
|
||
union in46_addr { | ||
struct in_addr v4; | ||
struct in6_addr v6; | ||
}; | ||
|
||
__attribute__((nonnull)) | ||
inline int in_to6 (void *addr) { | ||
((struct in6_addr *) addr)->s6_addr32[3] = ((struct in_addr *) addr)->s_addr; | ||
IN6_SET_ADDR_V4MAPPED(addr); | ||
return 0; | ||
} | ||
|
||
__attribute__((nonnull)) | ||
inline int in6_to4 (void *addr) { | ||
if (IN6_IS_ADDR_LOOPBACK(addr)) { | ||
((struct in_addr *) addr)->s_addr = lhtonl(INADDR_LOOPBACK); | ||
return 0; | ||
} | ||
if (IN6_IS_ADDR_V4OK(addr)) { | ||
((struct in_addr *) addr)->s_addr = | ||
((struct in6_addr *) addr)->s6_addr32[3]; | ||
return 0; | ||
} | ||
return 1; | ||
} | ||
|
||
__attribute__((nonnull)) | ||
inline int in46_is_addr_unspecified (int af, void *addr) { | ||
return af == AF_INET ? | ||
((struct in_addr *) addr)->s_addr == 0 : IN6_IS_ADDR_UNSPECIFIED(addr); | ||
} | ||
|
||
|
||
struct in46i_addr { | ||
union { | ||
struct in_addr v4; | ||
struct in6_addr v6; | ||
uint32_t scope_id; | ||
}; | ||
sa_family_t sa_family; | ||
}; | ||
|
||
#define IN46I_UNSPEC {.sa_family = AF_UNSPEC} | ||
#define IN46I_IS_UNSPEC(addr) ((addr)->sa_family == AF_UNSPEC) | ||
|
||
|
||
struct in64_addr { | ||
union { | ||
struct in6_addr addr6; | ||
struct { | ||
uint32_t __u32_addr_padding[3]; | ||
struct in_addr addr; | ||
}; | ||
}; | ||
uint32_t scope_id; | ||
}; | ||
|
||
#define IN64_IS_ADDR_UNSPECIFIED(a) ( \ | ||
IN6_IS_ADDR_V4OK(a) && ((struct in6_addr *) (a))->s6_addr32[3] == 0) | ||
|
||
__attribute__((nonnull, access(write_only, 2), access(read_only, 3))) | ||
inline int in64_set (int af, void *dst, const void *src) { | ||
switch (af) { | ||
case AF_INET: | ||
((struct in64_addr *) dst)->addr.s_addr = *(in_addr_t *) src; | ||
IN6_SET_ADDR_V4MAPPED(dst); | ||
break; | ||
case AF_INET6: { | ||
struct in6_addr *dst_ = dst; | ||
const struct in6_addr *src_ = src; | ||
dst_->s6_addr32[0] = src_->s6_addr32[0]; | ||
dst_->s6_addr32[1] = src_->s6_addr32[1]; | ||
dst_->s6_addr32[2] = src_->s6_addr32[2]; | ||
dst_->s6_addr32[3] = src_->s6_addr32[3]; | ||
break; | ||
} | ||
default: | ||
errno = EAFNOSUPPORT; | ||
} | ||
return 0; | ||
} | ||
|
||
__attribute__((nonnull, access(read_only, 2))) | ||
inline void *in64_get (int af, const void *addr) { | ||
return af == AF_INET ? | ||
(void *) &((struct in64_addr *) addr)->addr : (void *) addr; | ||
} | ||
|
||
|
||
#endif /* INET46I_IN46_H */ |
Oops, something went wrong.