├── .github └── FUNDING.yml ├── .gitignore ├── .gitmodules ├── AUTHOR ├── LICENSE ├── Makefile ├── README.md ├── VERSION ├── bin └── .gitignore ├── doc ├── docs │ ├── assets │ │ ├── arch-net.png │ │ ├── arch-soft.png │ │ ├── local-statck-recirculation.png │ │ └── logo.png │ ├── images │ │ ├── download.png │ │ ├── favicon-16x16.png │ │ ├── favicon-32x32.png │ │ ├── favicon.ico │ │ └── github.png │ └── index.md └── mkdocs.yml ├── lib ├── Makefile ├── bitops.h ├── buffer.c ├── buffer.h ├── command.c ├── command.h ├── config.h ├── container.h ├── daemon.c ├── daemon.h ├── jhash.h ├── json_reader.c ├── json_reader.h ├── json_writer.c ├── json_writer.h ├── list_head.c ├── list_head.h ├── logger.c ├── logger.h ├── md5.c ├── md5.h ├── memory.c ├── memory.h ├── mpool.c ├── mpool.h ├── pidfile.c ├── pidfile.h ├── pkt_buffer.c ├── pkt_buffer.h ├── prefix.c ├── prefix.h ├── process.c ├── process.h ├── rbtree.c ├── rbtree.h ├── rbtree_api.h ├── rbtree_augmented.h ├── rbtree_types.h ├── rt_table.c ├── rt_table.h ├── scheduler.c ├── scheduler.h ├── signals.c ├── signals.h ├── timer.c ├── timer.h ├── timer_thread.h ├── utils.c ├── utils.h ├── vector.c ├── vector.h ├── vty.c ├── vty.h └── warnings.h └── src ├── Makefile ├── bpf ├── Makefile ├── bpf_sctp.h ├── tc_sctp_nat.c └── xdp_sctp_nat.c ├── dra_arp.c ├── dra_arp_vty.c ├── dra_bpf.c ├── dra_bpf_nat.c ├── dra_bpf_vty.c ├── dra_data.c ├── dra_debug.c ├── dra_debug_vty.c ├── dra_diameter.c ├── dra_disk.c ├── dra_htab.c ├── dra_if.c ├── dra_json.c ├── dra_json_vty.c ├── dra_layer4.c ├── dra_mip.c ├── dra_mip_vty.c ├── dra_pcap.c ├── dra_plugin.c ├── dra_plugin_vty.c ├── dra_route_optim.c ├── dra_sctp.c ├── dra_sctp_proto.c ├── dra_sctp_vty.c ├── dra_vty.c ├── include ├── dra_arp.h ├── dra_arp_vty.h ├── dra_bpf.h ├── dra_bpf_nat.h ├── dra_bpf_vty.h ├── dra_data.h ├── dra_debug.h ├── dra_debug_vty.h ├── dra_diameter.h ├── dra_disk.h ├── dra_guard.h ├── dra_htab.h ├── dra_if.h ├── dra_json.h ├── dra_json_vty.h ├── dra_layer4.h ├── dra_mip.h ├── dra_mip_vty.h ├── dra_pcap.h ├── dra_plugin.h ├── dra_plugin_vty.h ├── dra_route_optim.h ├── dra_sctp.h ├── dra_sctp_proto.h ├── dra_sctp_vty.h ├── dra_vty.h └── main.h └── main.c /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: acassen 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # make and build files 2 | *.o 3 | bin/dra-guard 4 | *.bpf 5 | *.ll 6 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "libbpf"] 2 | path = libbpf 3 | url = https://github.com/libbpf/libbpf.git 4 | -------------------------------------------------------------------------------- /AUTHOR: -------------------------------------------------------------------------------- 1 | Alexandre Cassen, 2 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: AGPL-3.0-or-later 2 | # 3 | # Soft: The main goal of dra-guard is to provide robust and secure 4 | # extensions to DRA feature (Diameter Routing Agent). DRA are 5 | # used in mobile networks to route Diameter traffic between 6 | # mobile network equipments, like at Roaming interconnections. 7 | # DRA-Guard implements a set of features to manipulate and 8 | # analyze Diameter payloads via a Plugin framework and a 9 | # built-in Route-Optimization feature. 10 | # 11 | # Authors: Alexandre Cassen, 12 | # 13 | # This program is free software; you can redistribute it and/or 14 | # modify it under the terms of the GNU Affero General Public 15 | # License Version 3.0 as published by the Free Software Foundation; 16 | # either version 3.0 of the License, or (at your option) any later 17 | # version. 18 | # 19 | # Copyright (C) 2024 Alexandre Cassen, 20 | # 21 | 22 | EXEC = dra-guard 23 | BIN = bin 24 | VERSION := $(shell cat VERSION) 25 | TARBALL = $(EXEC)-$(VERSION).tar.xz 26 | TARFILES = AUTHOR VERSION LICENSE README.md bin src lib Makefile libbpf 27 | 28 | prefix = /usr/local 29 | exec_prefix = ${prefix} 30 | sbindir = ${exec_prefix}/sbin 31 | sysconfdir = ${prefix}/etc 32 | init_script = etc/init.d/gtp-guard.init 33 | conf_file = etc/gtp-guard/gtp-guard.conf 34 | 35 | CC ?= gcc 36 | LDFLAGS = -lpthread -lcrypt -ggdb -lm -lz -lresolv -lelf -lsctp -ldl -lpcap 37 | SUBDIRS = lib src src/bpf 38 | LIBBPF = libbpf 39 | OBJDIR = $(LIBBPF)/src 40 | 41 | all: $(OBJDIR)/libbpf.a 42 | @set -e; \ 43 | for i in $(SUBDIRS); do \ 44 | $(MAKE) -C $$i || exit 1; done && \ 45 | echo "Building $(BIN)/$(EXEC)" && \ 46 | $(CC) -o $(BIN)/$(EXEC) `find $(SUBDIRS) -name '*.[oa]'` $(OBJDIR)/libbpf.a $(LDFLAGS) 47 | # strip $(BIN)/$(EXEC) 48 | @echo "" 49 | @echo "Make complete" 50 | 51 | $(OBJDIR)/libbpf.a: 52 | @$(MAKE) -C $(LIBBPF)/src BUILD_STATIC_ONLY=y NO_PKG_CONFIG=y 53 | @ln -sf ../include/uapi $(OBJDIR) 54 | 55 | clean: 56 | @$(MAKE) -C $(LIBBPF)/src clean 57 | rm -f $(OBJDIR)/uapi 58 | @set -e; \ 59 | for i in $(SUBDIRS); do \ 60 | $(MAKE) -C $$i clean; done 61 | rm -f $(BIN)/$(EXEC) 62 | @echo "" 63 | @echo "Make complete" 64 | 65 | uninstall: 66 | rm -f $(sbindir)/$(EXEC) 67 | 68 | install: 69 | install -d $(prefix) 70 | install -m 700 $(BIN)/$(EXEC) $(sbindir)/$(EXEC)-$(VERSION) 71 | ln -sf $(sbindir)/$(EXEC)-$(VERSION) $(sbindir)/$(EXEC) 72 | 73 | tarball: clean 74 | @mkdir $(EXEC)-$(VERSION) 75 | @cp -a $(TARFILES) $(EXEC)-$(VERSION) 76 | @tar -cJf $(TARBALL) $(EXEC)-$(VERSION) 77 | @rm -rf $(EXEC)-$(VERSION) 78 | @echo $(TARBALL) 79 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DRA Guard: Diameter Routing Agent software 2 | 3 | 4 | DRA-Guard is a routing software written in C. The main goal of this project is to provide robust and secure extensions to DRA feature (Diameter Routing Agent). DRA are used in mobile networks to route Diameter traffic between mobile network equipments, like at Roaming interconnections. DRA-Guard implements a set of features to manipulate and analyze Diameter payloads via a Plugin framework and a built-in Route-Optimization feature. DRA-Guard relies on Linux Kernel XDP & Qdisc frameworks using eBPF for low-level features like transparent mode operations. Administration and user-level interface are available via a standard VTY terminal interface. 5 | 6 | DRA-Guard is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License Version 3.0 as published by the Free Software Foundation. 7 | 8 | # What the hell is this ? 9 | DRA-Guard doesn't aim to replace any DRA product, it rather provides a way to extend its behaviours in order to quickly react or add new features. No product can address all needs, mainly because needs for operators are evolving and new ideas are permanently fast moving. 10 | 11 | Long story short : DRA-Guard is a SCTP proxy offering access to Diameter payload. For each Diameter payload a plugin callback is invoked. You can then perform any packet analysis/mangling operations you may want and conclude by an action (PASS or DROP). A way to plug into your Diameter data-path and gain control of it. 12 | 13 | DRA-Guard is designed for high perf and built around an asynchronous multi-threaded design. Additionnaly it is supporting a transparent mode to simplify its insertion into an existing architecture without the need to reconfigure anything (this is specially useful when you have long list of peers and you need to go fast without wasting time into so called change request). 14 | 15 | DRA-Guard is additionnaly implementing a "Route Optimization" framework, a short static example is offered as an example in this OpenSource version, but way more advanced and dynamic routing decisions can be implemented based on multi-metrics. 16 | 17 | # Network Architecture 18 | If it can be inserted anywhere in your network, it can be useful at interconnection point where you may want to have option to quickly add perf extensions (monitoring, reporting, mitigation, filtering, ...) 19 |

20 | 21 | # Software Architecture 22 | DRA-Guard is articulated around following components : 23 |

24 | 25 | # Local Stack Packet re-circulation 26 | DRA-Guard can operate in transparent mode using state-less operations based on a set of eBPF progs loaded at XDP and Qdisc layers. This design provides fast state-less packet re-circulation into Linux Kernel stack to benefit widely used SCTP stack: 27 |

28 | 29 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 1.0.9 2 | -------------------------------------------------------------------------------- /bin/.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acassen/dra-guard/a5e7adb31f68b428571d66e62248fe031602b7a5/bin/.gitignore -------------------------------------------------------------------------------- /doc/docs/assets/arch-net.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acassen/dra-guard/a5e7adb31f68b428571d66e62248fe031602b7a5/doc/docs/assets/arch-net.png -------------------------------------------------------------------------------- /doc/docs/assets/arch-soft.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acassen/dra-guard/a5e7adb31f68b428571d66e62248fe031602b7a5/doc/docs/assets/arch-soft.png -------------------------------------------------------------------------------- /doc/docs/assets/local-statck-recirculation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acassen/dra-guard/a5e7adb31f68b428571d66e62248fe031602b7a5/doc/docs/assets/local-statck-recirculation.png -------------------------------------------------------------------------------- /doc/docs/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acassen/dra-guard/a5e7adb31f68b428571d66e62248fe031602b7a5/doc/docs/assets/logo.png -------------------------------------------------------------------------------- /doc/docs/images/download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acassen/dra-guard/a5e7adb31f68b428571d66e62248fe031602b7a5/doc/docs/images/download.png -------------------------------------------------------------------------------- /doc/docs/images/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acassen/dra-guard/a5e7adb31f68b428571d66e62248fe031602b7a5/doc/docs/images/favicon-16x16.png -------------------------------------------------------------------------------- /doc/docs/images/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acassen/dra-guard/a5e7adb31f68b428571d66e62248fe031602b7a5/doc/docs/images/favicon-32x32.png -------------------------------------------------------------------------------- /doc/docs/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acassen/dra-guard/a5e7adb31f68b428571d66e62248fe031602b7a5/doc/docs/images/favicon.ico -------------------------------------------------------------------------------- /doc/docs/images/github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/acassen/dra-guard/a5e7adb31f68b428571d66e62248fe031602b7a5/doc/docs/images/github.png -------------------------------------------------------------------------------- /doc/docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | hide: 3 | - navigation 4 | --- 5 | # Welcome to DRA-Guard 6 | 7 | 8 | 9 | DRA-Guard is a routing software written in C. The main goal of this project is to provide robust and secure extensions to **DRA** feature (**Diameter Routing Agent**). DRA are used in mobile networks to route Diameter traffic between mobile network equipments, like at Roaming interconnections. DRA-Guard implements a set of features to manipulate and analyze Diameter payloads via a **Plugin framework** and a built-in **Route-Optimization** feature. DRA-Guard relies on Linux Kernel **XDP** & **Qdisc** frameworks using **eBPF** for low-level features like transparent mode operations. Administration and user-level interface are available via a standard VTY terminal interface. 10 | 11 | DRA-Guard is free software; you can redistribute it and/or modify it under the terms of the GNU Affero General Public License Version 3.0 as published by the Free Software Foundation. 12 | 13 | 14 | [](https://github.com/acassen/dra-guard) 15 | 16 | --- 17 | 18 | # What the hell is this ? 19 | DRA-Guard doesn't aim to replace any DRA product, it rather provides a way to extend its behaviours in order to quickly react or add new features. No product can address all needs, mainly because needs for operators are evolving and new ideas are permanently fast moving. 20 | 21 | Long story short : DRA-Guard is a SCTP proxy offering access to Diameter payload. For each Diameter payload a plugin callback is invoked. You can then perform any packet analysis/mangling operations you may want and conclude by an action (PASS or DROP). A way to plug into your Diameter data-path and gain control of it. 22 | 23 | DRA-Guard is designed for high perf and built around an asynchronous multi-threaded design. Additionnaly it is supporting a transparent mode to simplify its insertion into an existing architecture without the need to reconfigure anything (this is specially useful when you have long list of peers and you need to go fast without wasting time into so called change request). 24 | 25 | DRA-Guard is additionnaly implementing a "Route Optimization" framework, a short static example is offered as an example in this OpenSource version, but way more advanced and dynamic routing decisions can be implemented based on multi-metrics. 26 | 27 | # Network Architecture 28 | If it can be inserted anywhere in your network, it can be useful at interconnection point where you may want to have option to quickly add perf extensions (monitoring, reporting, mitigation, filtering, ...) 29 |

30 | 31 | # Software Architecture 32 | DRA-Guard is articulated around following components : 33 |

34 | 35 | # Transparent mode 36 | DRA-Guard can operate in transparent mode using state-less operations based on a set of eBPF progs loaded at XDP and Qdisc layers. This design provides fast state-less packet re-circulation into Linux Kernel stack to benefit widely used SCTP stack: 37 |

38 | 39 | -------------------------------------------------------------------------------- /doc/mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: DRA-Guard 2 | copyright: Copyright © 2024 Alexandre Cassen 3 | repo_url: https://github.com/acassen/dra-guard 4 | repo_name: DRA-Guard 5 | theme: 6 | name: material 7 | logo: assets/logo.png 8 | favicon: images/favicon.ico 9 | features: 10 | - navigation.tabs 11 | - toc.integrate 12 | - header.autohide 13 | palette: 14 | - scheme: default 15 | primary: orange 16 | toggle: 17 | icon: material/brightness-7 18 | name: Switch to dark mode 19 | icon: 20 | repo: fontawesome/brands/github 21 | extra: 22 | homepage: https://www.dra-guard.org 23 | generator: false 24 | plugins: 25 | - search 26 | - tags 27 | - privacy: 28 | enabled: true 29 | cache: true 30 | cache_dir: .cache/plugins/privacy 31 | assets: true 32 | assets_fetch: true 33 | assets_fetch_dir: assets/external 34 | -------------------------------------------------------------------------------- /lib/Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: AGPL-3.0-or-later 2 | # 3 | # Soft: The main goal of dra-guard is to provide robust and secure 4 | # extensions to DRA feature (Diameter Routing Agent). DRA are 5 | # used in mobile networks to route Diameter traffic between 6 | # mobile network equipments, like at Roaming interconnections. 7 | # DRA-Guard implements a set of features to manipulate and 8 | # analyze Diameter payloads via a Plugin framework and a 9 | # built-in Route-Optimization feature. 10 | # 11 | # Authors: Alexandre Cassen, 12 | # 13 | # This program is free software; you can redistribute it and/or 14 | # modify it under the terms of the GNU Affero General Public 15 | # License Version 3.0 as published by the Free Software Foundation; 16 | # either version 3.0 of the License, or (at your option) any later 17 | # version. 18 | # 19 | # Copyright (C) 2024 Alexandre Cassen, 20 | # 21 | 22 | CC ?= gcc 23 | INCLUDES = -I. 24 | CFLAGS = -g -O2 $(INCLUDES) -Werror -Wall -Wunused -Wstrict-prototypes 25 | #DEFS = -D_DEBUG_ 26 | DEFS = -D_GNU_SOURCE 27 | COMPILE = $(CC) $(CFLAGS) $(DEFS) 28 | 29 | OBJS = memory.o mpool.o utils.o timer.o vector.o rbtree.o daemon.o \ 30 | scheduler.o md5.o list_head.o pidfile.o prefix.o rt_table.o \ 31 | signals.o process.o logger.o buffer.o command.o vty.o \ 32 | pkt_buffer.o json_reader.o json_writer.o 33 | HEADERS = $(OBJS:.o=.h) 34 | 35 | .c.o: 36 | @echo " CC" $@ 37 | @$(COMPILE) -c $< 38 | 39 | all: $(OBJS) 40 | 41 | clean: 42 | rm -f *.a *.o *~ 43 | 44 | distclean: clean 45 | rm -f Makefile 46 | 47 | memory.o: memory.c memory.h 48 | mpool.o: mpool.h memory.h 49 | utils.o: utils.c utils.h 50 | timer.o: timer.c timer.h 51 | vector.o: vector.c vector.h memory.h 52 | daemon.o: daemon.c daemon.h utils.h 53 | pidfile.o: pidfile.c pidfile.h 54 | md5.o: md5.h md5.c 55 | list_head.o: list_head.h list_head.c 56 | prefix.o: prefix.c prefix.h 57 | rt_table.o: rt_table.c rt_table.h prefix.h 58 | logger.o: logger.c logger.h 59 | buffer.o: buffer.c buffer.h memory.h 60 | command.o: command.c command.h vector.h memory.h vty.h timer.h \ 61 | config.h logger.h 62 | vty.o: vty.c vty.h scheduler.h timer.h utils.h command.h logger.h \ 63 | memory.h 64 | -------------------------------------------------------------------------------- /lib/bitops.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _BITOPS_H 23 | #define _BITOPS_H 24 | 25 | #include "config.h" 26 | 27 | #include 28 | #include 29 | 30 | /* Defines */ 31 | #define BIT_PER_LONG (CHAR_BIT * sizeof(unsigned long)) 32 | #define BIT_MASK(idx) (1UL << ((idx) % BIT_PER_LONG)) 33 | #define BIT_WORD(idx) ((idx) / BIT_PER_LONG) 34 | 35 | /* Helpers */ 36 | static inline void __set_bit(unsigned idx, unsigned long *bmap) 37 | { 38 | *bmap |= BIT_MASK(idx); 39 | } 40 | 41 | static inline void __clear_bit(unsigned idx, unsigned long *bmap) 42 | { 43 | *bmap &= ~BIT_MASK(idx); 44 | } 45 | 46 | static inline bool __test_bit(unsigned idx, const unsigned long *bmap) 47 | { 48 | return !!(*bmap & BIT_MASK(idx)); 49 | } 50 | 51 | static inline bool __test_and_set_bit(unsigned idx, unsigned long *bmap) 52 | { 53 | if (__test_bit(idx, bmap)) 54 | return true; 55 | 56 | __set_bit(idx, bmap); 57 | 58 | return false; 59 | } 60 | 61 | static inline bool __test_and_clear_bit(unsigned idx, unsigned long *bmap) 62 | { 63 | if (!__test_bit(idx, bmap)) 64 | return false; 65 | 66 | __clear_bit(idx, bmap); 67 | 68 | return true; 69 | } 70 | 71 | static inline void __set_bit_array(unsigned idx, unsigned long bmap[]) 72 | { 73 | bmap[BIT_WORD(idx)] |= BIT_MASK(idx); 74 | } 75 | 76 | static inline void __clear_bit_array(unsigned idx, unsigned long bmap[]) 77 | { 78 | bmap[BIT_WORD(idx)] &= ~BIT_MASK(idx); 79 | } 80 | 81 | static inline bool __test_bit_array(unsigned idx, const unsigned long bmap[]) 82 | { 83 | return !!(bmap[BIT_WORD(idx)] & BIT_MASK(idx)); 84 | } 85 | 86 | static inline bool __test_and_set_bit_array(unsigned idx, unsigned long bmap[]) 87 | { 88 | if (__test_bit_array(idx, bmap)) 89 | return true; 90 | 91 | __set_bit_array(idx, bmap); 92 | 93 | return false; 94 | } 95 | 96 | /* Bits */ 97 | enum global_bits { 98 | LOG_CONSOLE_BIT, 99 | NO_SYSLOG_BIT, 100 | DONT_FORK_BIT, 101 | DUMP_CONF_BIT, 102 | LOG_DETAIL_BIT, 103 | LOG_EXTRA_DETAIL_BIT, 104 | DONT_RESPAWN_BIT, 105 | #ifdef _MEM_CHECK_ 106 | MEM_CHECK_BIT, 107 | #ifdef _MEM_ERR_DEBUG_ 108 | MEM_ERR_DETECT_BIT, 109 | #endif 110 | #ifdef _MEM_CHECK_LOG_ 111 | MEM_CHECK_LOG_BIT, 112 | #endif 113 | #endif 114 | CONFIG_TEST_BIT, 115 | }; 116 | 117 | #endif 118 | -------------------------------------------------------------------------------- /lib/buffer.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 | /* 3 | * Buffering of output and input. 4 | * Copyright (C) 1998 Kunihiro Ishiguro 5 | */ 6 | 7 | #ifndef _BUFFER_H 8 | #define _BUFFER_H 9 | 10 | /* buffer definition */ 11 | typedef struct _buffer_data { 12 | struct _buffer_data *next; 13 | 14 | size_t cp; /* Location to add new data. */ 15 | size_t sp; /* Pointer to data not yet flushed. */ 16 | unsigned char data[]; /* Actual data stream (variable length). 17 | * real dimension is buffer->size. 18 | */ 19 | } buffer_data_t; 20 | 21 | typedef struct _buffer { 22 | buffer_data_t *head; 23 | buffer_data_t *tail; 24 | 25 | size_t size; /* Size of each buffer_data chunk. */ 26 | } buffer_t; 27 | 28 | typedef enum _buffer_status { 29 | BUFFER_ERROR = -1, /* An I/O error occurred. 30 | * The buffer should be destroyed and the 31 | * file descriptor should be closed. 32 | */ 33 | BUFFER_EMPTY = 0, /* The data was written successfully, 34 | * and the buffer is now empty (there is 35 | * no pending data waiting to be flushed). 36 | */ 37 | BUFFER_PENDING = 1 /* There is pending data in the buffer 38 | * waiting to be flushed. Please try 39 | * flushing the buffer when select 40 | * indicates that the file descriptor 41 | * is writeable. 42 | */ 43 | } buffer_status_t; 44 | 45 | /* Some defines */ 46 | #define BUFFER_SIZE_DEFAULT 4096 47 | 48 | /* Some usefull macros */ 49 | #define ERRNO_IO_RETRY(EN) \ 50 | (((EN) == EAGAIN) || ((EN) == EWOULDBLOCK) || ((EN) == EINTR)) 51 | 52 | /* Prototypes */ 53 | extern buffer_t *buffer_new(size_t); 54 | extern void buffer_reset(buffer_t *); 55 | extern void buffer_free(buffer_t *); 56 | extern void buffer_put(buffer_t *, const void *, size_t); 57 | extern void buffer_putc(buffer_t *, uint8_t); 58 | extern void buffer_putstr(buffer_t *, const char *); 59 | extern char *buffer_getstr(buffer_t *); 60 | extern int buffer_empty(buffer_t *); 61 | extern buffer_status_t buffer_write(buffer_t *, int fd, 62 | const void *, size_t); 63 | extern buffer_status_t buffer_flush_available(buffer_t *, int fd); 64 | extern buffer_status_t buffer_flush_all(buffer_t *, int fd); 65 | extern buffer_status_t buffer_flush_window(buffer_t *, int fd, int width, 66 | int height, int erase, int no_more); 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /lib/config.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _CONFIG_H 23 | #define _CONFIG_H 24 | 25 | #define LOG_FACILITY_MAX 7 26 | #define PROG "dra-guard" 27 | #define PROG_PID_FILE "/var/run/dra-guard.pid" 28 | #define VERSION_STRING PROG " v1.0.9 (2024/10/14)" 29 | #define COPYRIGHT_STRING "Copyright (C) 2024 Alexandre Cassen, " 30 | 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /lib/container.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _CONTAINER_H 23 | #define _CONTAINER_H 24 | 25 | #include "warnings.h" 26 | #include "config.h" 27 | 28 | 29 | #if defined _HAVE_FUNCTION_ATTRIBUTE_ERROR_ && (!defined _HAVE_WARNING_NESTED_EXTERNS_ || defined _HAVE_DIAGNOSTIC_PUSH_POP_PRAGMAS_) 30 | 31 | /* Copied from linux kernel 5.15 source include/linux/{build_bug,compiler_types,compiler_attributes}.h */ 32 | 33 | #define __compiletime_error(message) __attribute__((error(message))) 34 | 35 | # define __compiletime_assert(condition, msg, prefix, suffix) \ 36 | do { \ 37 | RELAX_NESTED_EXTERNS_START \ 38 | RELAX_REDUNDANT_DECLS_START \ 39 | extern void prefix ## suffix(void) __compiletime_error(msg); \ 40 | if (!(condition)) \ 41 | prefix ## suffix(); \ 42 | RELAX_REDUNDANT_DECLS_END \ 43 | RELAX_NESTED_EXTERNS_END \ 44 | } while (0) 45 | 46 | 47 | #define _compiletime_assert(condition, msg, prefix, suffix) \ 48 | __compiletime_assert(condition, msg, prefix, suffix) 49 | 50 | #define compiletime_assert(condition, msg) \ 51 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) 52 | 53 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) 54 | 55 | #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) 56 | 57 | #else 58 | #define BUILD_BUG_ON_MSG(conf, msg) do {} while (0) 59 | #endif 60 | 61 | 62 | /* Copied from linux kernel 5.15 source include/linux/{kernel.h,stddef.h} */ 63 | 64 | #ifndef offsetof 65 | # define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) 66 | #endif 67 | 68 | /* 69 | * container_of - cast a member of a structure out to the containing structure 70 | * 71 | * @ptr: the pointer to the member. 72 | * @type: the type of the container struct this is embedded in. 73 | * @member: the name of the member within the struct. 74 | * 75 | */ 76 | 77 | #ifndef container_of 78 | # define container_of(ptr, type, member) ({ \ 79 | BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \ 80 | !__same_type(*(ptr), void), \ 81 | "pointer type mismatch in container_of()"); \ 82 | typeof( ((type *)0)->member ) *__mptr = (ptr); \ 83 | (type *)( (char *)__mptr - offsetof(type,member) );}) 84 | #endif 85 | 86 | #ifndef container_of_const 87 | # define container_of_const(ptr, type, member) ({ \ 88 | BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \ 89 | !__same_type(*(ptr), void), \ 90 | "pointer type mismatch in container_of()"); \ 91 | const typeof( ((type *)0)->member ) *__mptr = (ptr); \ 92 | (type *)( (const char *)__mptr - offsetof(type,member) );}) 93 | #endif 94 | 95 | #endif 96 | -------------------------------------------------------------------------------- /lib/daemon.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #include 23 | #include "daemon.h" 24 | #include "utils.h" 25 | 26 | /* Daemonization function coming from zebra source code */ 27 | pid_t 28 | xdaemon(int nochdir, int noclose, int exitflag) 29 | { 30 | pid_t pid; 31 | int ret = 0; 32 | 33 | /* In case of fork is error. */ 34 | pid = fork(); 35 | if (pid < 0) { 36 | syslog(LOG_INFO, "xdaemon: fork error"); 37 | return -1; 38 | } 39 | 40 | /* In case of this is parent process. */ 41 | if (pid != 0) { 42 | if (!exitflag) 43 | exit(0); 44 | else 45 | return pid; 46 | } 47 | 48 | /* Become session leader and get pid. */ 49 | pid = setsid(); 50 | if (pid < -1) { 51 | syslog(LOG_INFO, "xdaemon: setsid error"); 52 | return -1; 53 | } 54 | 55 | /* Change directory to root. */ 56 | if (!nochdir) 57 | ret = chdir("/"); 58 | 59 | /* File descriptor close. */ 60 | if (!noclose) { 61 | int fd; 62 | 63 | fd = open("/dev/null", O_RDWR, 0); 64 | if (fd != -1) { 65 | dup2(fd, STDIN_FILENO); 66 | dup2(fd, STDOUT_FILENO); 67 | dup2(fd, STDERR_FILENO); 68 | if (fd > 2) 69 | close(fd); 70 | } 71 | } 72 | 73 | umask(0); 74 | return ret; 75 | } 76 | -------------------------------------------------------------------------------- /lib/daemon.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _DAEMON_H 23 | #define _DAEMON_H 24 | 25 | /* System includes */ 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | /* prototype */ 36 | extern pid_t xdaemon(int, int, int); 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /lib/jhash.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Soft: Jenkins hash support 3 | * 4 | * Author: Bob Jenkins, 7 | */ 8 | 9 | #ifndef _JHASH_H 10 | #define _JHASH_H 11 | 12 | /* Global helpers */ 13 | typedef uint32_t ub4; 14 | typedef uint8_t ub1; 15 | 16 | #define jhashsize(n) ((ub4)1<<(n)) 17 | #define jhashmask(n) (jhashsize(n)-1) 18 | 19 | /* NOTE: Arguments are modified. */ 20 | #define __jhash_mix(a, b, c) \ 21 | { \ 22 | a -= b; a -= c; a ^= (c>>13); \ 23 | b -= c; b -= a; b ^= (a<<8); \ 24 | c -= a; c -= b; c ^= (b>>13); \ 25 | a -= b; a -= c; a ^= (c>>12); \ 26 | b -= c; b -= a; b ^= (a<<16); \ 27 | c -= a; c -= b; c ^= (b>>5); \ 28 | a -= b; a -= c; a ^= (c>>3); \ 29 | b -= c; b -= a; b ^= (a<<10); \ 30 | c -= a; c -= b; c ^= (b>>15); \ 31 | } 32 | 33 | /* The golden ration: an arbitrary value */ 34 | #define JHASH_GOLDEN_RATIO 0x9e3779b9 35 | 36 | /* The most generic version, hashes an arbitrary sequence 37 | * of bytes. No alignment or length assumptions are made about 38 | * the input key. 39 | */ 40 | static inline ub4 41 | jhash(register ub1 *k, register ub4 length, register ub4 initval) 42 | { 43 | register ub4 a, b, c, len; 44 | 45 | len = length; 46 | a = b = JHASH_GOLDEN_RATIO; 47 | c = initval; 48 | 49 | while (len >= 12) { 50 | a += (k[0] + ((ub4) k[1] << 8) + ((ub4) k[2] << 16) + 51 | ((ub4) k[3] << 24)); 52 | b += (k[4] + ((ub4) k[5] << 8) + ((ub4) k[6] << 16) + 53 | ((ub4) k[7] << 24)); 54 | c += (k[8] + ((ub4) k[9] << 8) + ((ub4) k[10] << 16) + 55 | ((ub4) k[11] << 24)); 56 | 57 | __jhash_mix(a, b, c); 58 | 59 | k += 12; 60 | len -= 12; 61 | } 62 | 63 | c += length; 64 | switch (len) { 65 | case 11: 66 | c += ((ub4) k[10] << 24); 67 | case 10: 68 | c += ((ub4) k[9] << 16); 69 | case 9: 70 | c += ((ub4) k[8] << 8); 71 | case 8: 72 | b += ((ub4) k[7] << 24); 73 | case 7: 74 | b += ((ub4) k[6] << 16); 75 | case 6: 76 | b += ((ub4) k[5] << 8); 77 | case 5: 78 | b += k[4]; 79 | case 4: 80 | a += ((ub4) k[3] << 24); 81 | case 3: 82 | a += ((ub4) k[2] << 16); 83 | case 2: 84 | a += ((ub4) k[1] << 8); 85 | case 1: 86 | a += k[0]; 87 | }; 88 | 89 | __jhash_mix(a, b, c); 90 | 91 | return c; 92 | } 93 | 94 | /* A special optimized version that handles 1 or more of ub4s. 95 | * The length parameter here is the number of ub4s in the key. 96 | */ 97 | static inline ub4 98 | jhash2(register ub4 *k, register ub4 length, register ub4 initval) 99 | { 100 | register ub4 a, b, c, len; 101 | 102 | a = b = JHASH_GOLDEN_RATIO; 103 | c = initval; 104 | len = length; 105 | 106 | while (len >= 3) { 107 | a += k[0]; 108 | b += k[1]; 109 | c += k[2]; 110 | __jhash_mix(a, b, c); 111 | k += 3; 112 | len -= 3; 113 | } 114 | 115 | c += length * 4; 116 | 117 | switch (len) { 118 | case 2: 119 | b += k[1]; 120 | case 1: 121 | a += k[0]; 122 | }; 123 | 124 | __jhash_mix(a, b, c); 125 | 126 | return c; 127 | } 128 | 129 | /* A special ultra-optimized versions that knows they are hashing exactly 130 | * 3, 2 or 1 word(s). 131 | * 132 | * NOTE: In partilar the "c += length; __jhash_mix(a,b,c);" normally 133 | * done at the end is not done here. 134 | */ 135 | static inline ub4 136 | jhash_3words(register ub4 a, register ub4 b, 137 | register ub4 c, register ub4 initval) 138 | { 139 | a += JHASH_GOLDEN_RATIO; 140 | b += JHASH_GOLDEN_RATIO; 141 | c += initval; 142 | 143 | __jhash_mix(a, b, c); 144 | 145 | return c; 146 | } 147 | 148 | static inline ub4 149 | jhash_2words(register ub4 a, register ub4 b, register ub4 initval) 150 | { 151 | return jhash_3words(a, b, 0, initval); 152 | } 153 | 154 | static inline ub4 155 | jhash_1word(register ub4 a, register ub4 initval) 156 | { 157 | return jhash_3words(a, 0, 0, initval); 158 | } 159 | 160 | /* One-At-A-Time string hashing */ 161 | static inline ub4 162 | jhash_oaat(register ub1 *k, size_t s) 163 | { 164 | register ub4 hash = JHASH_GOLDEN_RATIO; 165 | const ub1 *cp; 166 | int i = 0; 167 | 168 | for (cp = k; *cp && i < s; cp++, i++) { 169 | hash += *cp; 170 | hash += (hash << 10); 171 | hash ^= (hash >> 6); 172 | } 173 | 174 | hash += (hash << 3); 175 | hash ^= (hash >> 11); 176 | hash += (hash << 15); 177 | return hash; 178 | } 179 | 180 | #endif 181 | -------------------------------------------------------------------------------- /lib/json_reader.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _JSON_READER_H_ 23 | #define _JSON_READER_H_ 24 | 25 | #include 26 | #include 27 | 28 | typedef enum { 29 | JSON_NULL = 0, 30 | JSON_BOOL, 31 | JSON_STRING, 32 | JSON_NUMBER, 33 | JSON_ARRAY, 34 | JSON_OBJECT, 35 | } json_tag_t; 36 | 37 | typedef struct _json_node { 38 | struct _json_node *parent, *prev, *next; 39 | char *key; 40 | json_tag_t tag; 41 | union { 42 | bool bool_value; /* JSON_BOOL */ 43 | char *str_value; /* JSON_STRING */ 44 | double number_value; /* JSON_NUMBER */ 45 | struct { /* JSON_ARRAY|JSON_OBJECT */ 46 | struct _json_node *head, *tail; 47 | } child; 48 | }; 49 | } json_node_t; 50 | 51 | 52 | /* Walk the line */ 53 | extern json_node_t *json_find_member_boolvalue(json_node_t *, const char *, bool *); 54 | extern json_node_t *json_find_member_strvalue(json_node_t *, const char *, char **); 55 | extern json_node_t *json_find_member_numbervalue(json_node_t *, const char *, double *); 56 | extern json_node_t *json_find_member_doublevalue(json_node_t *, const char *, double *); 57 | extern json_node_t *json_find_member_intvalue(json_node_t *, const char *, int *); 58 | extern json_node_t *json_find_member(json_node_t *, const char *); 59 | extern json_node_t *json_first_child(const json_node_t *); 60 | #define json_for_each_node(pos, head) \ 61 | for (pos = json_first_child(head); \ 62 | pos != NULL; \ 63 | pos = pos->next) 64 | 65 | #define json_for_each_node_safe(pos, n, head) \ 66 | for (pos = json_first_child(head), n = pos->next; \ 67 | pos != NULL && (n = pos->next); \ 68 | pos = n, n = (pos->next) ? pos->next : NULL) 69 | 70 | 71 | /* Prototypes */ 72 | extern json_node_t *json_decode(const char *); 73 | extern void json_dump(json_node_t *); 74 | extern void json_destroy(json_node_t *); 75 | 76 | #endif 77 | -------------------------------------------------------------------------------- /lib/json_writer.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _JSON_WRITER_H_ 23 | #define _JSON_WRITER_H_ 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | /* Opaque class structure */ 30 | typedef struct json_writer json_writer_t; 31 | 32 | /* Create a new JSON stream */ 33 | json_writer_t *jsonw_new(FILE *f); 34 | 35 | /* End output to JSON stream */ 36 | void jsonw_destroy(json_writer_t ** const self_p); 37 | 38 | /* Cause output to have pretty whitespace */ 39 | void jsonw_pretty(json_writer_t *self, bool on); 40 | 41 | /* Add property name */ 42 | void jsonw_name(json_writer_t *self, const char *name); 43 | 44 | /* Add value */ 45 | void jsonw_vprintf_enquote(json_writer_t *, const char *, va_list) 46 | __attribute__ ((format(printf, 2, 0))); 47 | void jsonw_printf(json_writer_t *, const char *, ...) 48 | __attribute__ ((format(printf, 2, 3))); 49 | void jsonw_printf_enquote(json_writer_t *, const char *, ...) 50 | __attribute__ ((format(printf, 2, 3))); 51 | void jsonw_string(json_writer_t *self, const char *value); 52 | void jsonw_bool(json_writer_t *self, bool value); 53 | void jsonw_float(json_writer_t *self, double number); 54 | void jsonw_float_fmt(json_writer_t *self, const char *fmt, double num); 55 | void jsonw_uint(json_writer_t *self, uint64_t number); 56 | void jsonw_hu(json_writer_t *self, unsigned short number); 57 | void jsonw_int(json_writer_t *self, int64_t number); 58 | void jsonw_null(json_writer_t *self); 59 | void jsonw_lluint(json_writer_t *self, unsigned long long int num); 60 | 61 | /* Useful Combinations of name and value */ 62 | void jsonw_string_field(json_writer_t *self, const char *prop, const char *val); 63 | void jsonw_string_field_fmt(json_writer_t *self, const char *prop, const char *fmt, ...); 64 | void jsonw_bool_field(json_writer_t *self, const char *prop, bool value); 65 | void jsonw_float_field(json_writer_t *self, const char *prop, double num); 66 | void jsonw_uint_field(json_writer_t *self, const char *prop, uint64_t num); 67 | void jsonw_hu_field(json_writer_t *self, const char *prop, unsigned short num); 68 | void jsonw_int_field(json_writer_t *self, const char *prop, int64_t num); 69 | void jsonw_null_field(json_writer_t *self, const char *prop); 70 | void jsonw_lluint_field(json_writer_t *self, const char *prop, 71 | unsigned long long int num); 72 | void jsonw_float_field_fmt(json_writer_t *self, const char *prop, 73 | const char *fmt, double val); 74 | 75 | /* Collections */ 76 | void jsonw_start_object(json_writer_t *self); 77 | void jsonw_end_object(json_writer_t *self); 78 | 79 | void jsonw_start_array(json_writer_t *self); 80 | void jsonw_end_array(json_writer_t *self); 81 | 82 | /* Override default exception handling */ 83 | typedef void (jsonw_err_handler_fn)(const char *); 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /lib/list_head.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #include "list_head.h" 23 | 24 | void list_sort(struct list_head *head, 25 | int (*cmp)(struct list_head *a, struct list_head *b)) 26 | { 27 | struct list_head *p, *q, *e, *list, *tail, *oldhead; 28 | int insize, nmerges, psize, qsize, i; 29 | 30 | list = head->next; 31 | list_head_del(head); 32 | insize = 1; 33 | 34 | while (1) { 35 | p = oldhead = list; 36 | list = tail = NULL; 37 | nmerges = 0; 38 | 39 | while (p) { 40 | nmerges++; 41 | q = p; 42 | psize = 0; 43 | for (i = 0; i < insize; i++) { 44 | psize++; 45 | q = q->next == oldhead ? NULL : q->next; 46 | if (!q) 47 | break; 48 | } 49 | 50 | qsize = insize; 51 | while (psize > 0 || (qsize > 0 && q)) { 52 | if (!psize) { 53 | e = q; 54 | q = q->next; 55 | qsize--; 56 | if (q == oldhead) 57 | q = NULL; 58 | } else if (!qsize || !q) { 59 | e = p; 60 | p = p->next; 61 | psize--; 62 | if (p == oldhead) 63 | p = NULL; 64 | } else if (cmp(p, q) <= 0) { 65 | e = p; 66 | p = p->next; 67 | psize--; 68 | if (p == oldhead) 69 | p = NULL; 70 | } else { 71 | e = q; 72 | q = q->next; 73 | qsize--; 74 | if (q == oldhead) 75 | q = NULL; 76 | } 77 | if (tail) 78 | tail->next = e; 79 | else 80 | list = e; 81 | e->prev = tail; 82 | tail = e; 83 | } 84 | p = q; 85 | } 86 | 87 | tail->next = list; 88 | list->prev = tail; 89 | 90 | if (nmerges <= 1) 91 | break; 92 | 93 | insize *= 2; 94 | } 95 | 96 | head->next = list; 97 | head->prev = list->prev; 98 | list->prev->next = head; 99 | list->prev = head; 100 | } 101 | -------------------------------------------------------------------------------- /lib/logger.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | /* Boolean flag - send messages to console as well as syslog */ 28 | static bool log_console = false; 29 | 30 | void 31 | enable_console_log(void) 32 | { 33 | log_console = true; 34 | } 35 | 36 | void 37 | log_message(const int facility, const char *format, ...) 38 | { 39 | va_list args; 40 | char buf[256]; 41 | 42 | va_start(args, format); 43 | vsnprintf(buf, sizeof(buf), format, args); 44 | va_end(args); 45 | 46 | if (log_console) { 47 | fprintf(stderr, "%s\n", buf); 48 | } 49 | 50 | syslog(facility, "%s", buf); 51 | } 52 | 53 | void 54 | conf_write(FILE *fp, const char *format, ...) 55 | { 56 | va_list args; 57 | 58 | va_start(args, format); 59 | if (fp) { 60 | vfprintf(fp, format, args); 61 | fprintf(fp, "\n"); 62 | } else 63 | log_message(LOG_INFO, format, args); 64 | 65 | va_end(args); 66 | } 67 | -------------------------------------------------------------------------------- /lib/logger.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _LOGGER_H 23 | #define _LOGGER_H 24 | 25 | #include 26 | 27 | void enable_console_log(void); 28 | void log_message(int, const char * , ...); 29 | void conf_write(FILE *, const char *, ...); 30 | 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /lib/md5.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions 7 | * are met: 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of the project nor the names of its contributors 14 | * may be used to endorse or promote products derived from this software 15 | * without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 18 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 | * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 | * SUCH DAMAGE. 28 | */ 29 | 30 | #ifndef _MD5_H_ 31 | #define _MD5_H_ 32 | 33 | #define MD5_BUFLEN 64 34 | 35 | typedef struct { 36 | union { 37 | uint32_t md5_state32[4]; 38 | uint8_t md5_state8[16]; 39 | } md5_st; 40 | 41 | #define md5_sta md5_st.md5_state32[0] 42 | #define md5_stb md5_st.md5_state32[1] 43 | #define md5_stc md5_st.md5_state32[2] 44 | #define md5_std md5_st.md5_state32[3] 45 | #define md5_st8 md5_st.md5_state8 46 | 47 | union { 48 | uint64_t md5_count64; 49 | uint8_t md5_count8[8]; 50 | } md5_count; 51 | #define md5_n md5_count.md5_count64 52 | #define md5_n8 md5_count.md5_count8 53 | 54 | uint md5_i; 55 | uint8_t md5_buf[MD5_BUFLEN]; 56 | } md5_ctxt; 57 | 58 | extern void md5_init (md5_ctxt *); 59 | extern void md5_loop (md5_ctxt *, const void *, u_int); 60 | extern void md5_pad (md5_ctxt *); 61 | extern void md5_result (uint8_t *, md5_ctxt *); 62 | 63 | /* compatibility */ 64 | #define MD5_CTX md5_ctxt 65 | #define MD5Init(x) md5_init((x)) 66 | #define MD5Update(x, y, z) md5_loop((x), (y), (z)) 67 | #define MD5Final(x, y) \ 68 | do { \ 69 | md5_pad((y)); \ 70 | md5_result((x), (y)); \ 71 | } while (0) 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /lib/memory.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _MEMORY_H 23 | #define _MEMORY_H 24 | 25 | /* system includes */ 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | /* extern types */ 33 | extern unsigned long mem_allocated; 34 | extern void *xalloc(unsigned long); 35 | extern void *zalloc(unsigned long); 36 | extern void *xcalloc(size_t, unsigned long); 37 | extern void xfree(void *); 38 | 39 | /* Global alloc macro */ 40 | #define ALLOC(n) (xalloc(n)) 41 | 42 | /* Local defines */ 43 | #ifdef _DEBUG_ 44 | 45 | #define MAX_ALLOC_LIST 40000 46 | 47 | #define MALLOC(n) ( memory_malloc((n), \ 48 | (__FILE__), (__FUNCTION__), (__LINE__)) ) 49 | #define FREE(b) ( memory_free((b), \ 50 | (__FILE__), (__FUNCTION__), (__LINE__)) ) 51 | #define REALLOC(b,n) ( memory_realloc((b), (n), \ 52 | (__FILE__), (__FUNCTION__), (__LINE__)) ) 53 | 54 | /* Memory debug prototypes defs */ 55 | extern char *memory_malloc(unsigned long, char *, const char *, const int); 56 | extern int memory_free(void *, char *, const char *, const int); 57 | extern void *memory_realloc(void *, unsigned long, char *, const char *, const int); 58 | extern void memory_free_final(char *); 59 | 60 | #else 61 | 62 | #define MALLOC(n) (zalloc(n)) 63 | #define CALLOC(n,s) (xcalloc((n),(s))) 64 | #define FREE(p) (xfree(p)) 65 | #define REALLOC(p,n) (realloc((p),(n))) 66 | 67 | #endif 68 | 69 | /* Common defines */ 70 | #define PMALLOC(p) { p = MALLOC(sizeof(*p)); } 71 | #define FREE_PTR(p) { if (p) { FREE(p);} } 72 | #define FREE_CONST_PTR(p) { if (p) { FREE_CONST(p);} } 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /lib/mpool.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | /* global includes */ 23 | #include 24 | #include 25 | 26 | /* local includes */ 27 | #include "memory.h" 28 | #include "mpool.h" 29 | 30 | 31 | /* 32 | * Dump memory pool 33 | */ 34 | void 35 | mpool_dump(mem_pool_t *mpool) 36 | { 37 | mem_t *mem; 38 | int i = 0; 39 | 40 | printf("mpool size = %d\n", MPOOL_SIZE(mpool)); 41 | 42 | for (mem = mpool->head; mem; mem = mem->next) 43 | printf(" %.2d size=%d offset=%d\n", ++i, mem->size, mem->offset); 44 | } 45 | 46 | /* 47 | * Queue memory element 48 | */ 49 | void 50 | mpool_queue_tail(mem_pool_t *mpool, mem_t *mem) 51 | { 52 | /* Return on empty stuff */ 53 | if (!mpool || !mem) 54 | return; 55 | 56 | /* Queue this mem */ 57 | mem->prev = mpool->tail; 58 | mem->next = NULL; 59 | 60 | if (mpool->head == NULL) 61 | mpool->head = mem; 62 | else 63 | mpool->tail->next = mem; 64 | 65 | mpool->tail = mem; 66 | mpool->count++; 67 | } 68 | 69 | /* 70 | * Dequeue a memory element 71 | */ 72 | mem_t * 73 | mpool_dequeue(mem_pool_t *mpool) 74 | { 75 | mem_t *mem; 76 | 77 | /* Queue is empty */ 78 | if (MPOOL_ISEMPTY(mpool)) 79 | return NULL; 80 | 81 | /* Fetch head */ 82 | mem = mpool->head; 83 | mpool->head = mem->next; 84 | if (mem->next) 85 | mem->next->prev = NULL; 86 | mpool->count--; 87 | 88 | return mem; 89 | } 90 | 91 | /* 92 | * Allocate new memory element 93 | */ 94 | mem_t * 95 | mpool_allocate_mem(int size) 96 | { 97 | mem_t *mem = (mem_t *) MALLOC(sizeof(mem_t)); 98 | mem->data = (char *) MALLOC(size); 99 | mem->size = size; 100 | return mem; 101 | } 102 | 103 | /* 104 | * Create a new memory element 105 | */ 106 | mem_t * 107 | mpool_create_mem(char *buffer, int size) 108 | { 109 | mem_t *mem = (mem_t *) MALLOC(sizeof(mem_t)); 110 | mem->data = (char *) MALLOC(size); 111 | mem->size = mem->offset = size; 112 | memcpy(mem->data, buffer, size); 113 | return mem; 114 | } 115 | 116 | /* 117 | * Duplicate memory element 118 | */ 119 | mem_t * 120 | mpool_dup_mem(mem_t *mem) 121 | { 122 | mem_t *new = (mem_t *) MALLOC(sizeof(mem_t)); 123 | new->data = (char *) MALLOC(mem->size); 124 | new->size = mem->size; 125 | new->offset = mem->offset; 126 | memcpy(new->data, mem->data, mem->offset); 127 | return new; 128 | } 129 | 130 | 131 | /* 132 | * Release a memory element 133 | */ 134 | void 135 | mpool_release_mem(mem_t *mem) 136 | { 137 | FREE(mem->data); 138 | FREE(mem); 139 | } 140 | 141 | /* 142 | * Fill mempool with brand new mem bucket 143 | */ 144 | void 145 | mpool_fill(mem_pool_t *mpool, int count, int size) 146 | { 147 | mem_t *mem; 148 | int i; 149 | 150 | /* Pre-allocate pool element */ 151 | for (i=0; i < count; i++) { 152 | mem = mpool_allocate_mem(size); 153 | mpool_queue_tail(mpool, mem); 154 | } 155 | } 156 | 157 | /* 158 | * Initialize a New memory Pool 159 | */ 160 | mem_pool_t * 161 | mpool_init(void) 162 | { 163 | mem_pool_t *mpool; 164 | 165 | /* Allocate root pool */ 166 | mpool = (mem_pool_t *) MALLOC(sizeof(mem_pool_t)); 167 | mpool->head = mpool->tail = NULL; 168 | 169 | return mpool; 170 | } 171 | 172 | /* 173 | * Destroy a memory pool 174 | */ 175 | void 176 | mpool_destroy(mem_pool_t *mpool) 177 | { 178 | mem_t *mem = NULL; 179 | mem_t *next = NULL; 180 | 181 | if (!mpool) 182 | return; 183 | 184 | for (mem = mpool->head; mem; mem = next) { 185 | next = mem->next; 186 | mpool_release_mem(mem); 187 | } 188 | 189 | FREE(mpool); 190 | } 191 | 192 | /* 193 | * Flush and merge memory pool 194 | */ 195 | void 196 | mpool_move(mem_pool_t *src, mem_pool_t *dst) 197 | { 198 | mem_t *mem = NULL; 199 | 200 | if (!src || MPOOL_ISEMPTY(src)) 201 | return; 202 | 203 | while ((mem = mpool_dequeue(src))) 204 | mpool_queue_tail(dst, mem); 205 | 206 | src->tail = src->head = NULL; 207 | src->count = 0; 208 | } 209 | -------------------------------------------------------------------------------- /lib/mpool.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _MPOOL_H 23 | #define _MPOOL_H 24 | 25 | /* Defines */ 26 | #define MEM_DEFAULT_SIZE 65541 27 | #define MPOOL_DEFAULT_SIZE 10 28 | 29 | /* Types */ 30 | typedef struct _mem { 31 | struct _mem *next; 32 | struct _mem *prev; 33 | 34 | void *data; /* Raw data pointer */ 35 | unsigned int size; /* Raw data size */ 36 | unsigned int offset; /* Offset of data used */ 37 | int type; 38 | } mem_t; 39 | 40 | typedef struct _mem_pool { 41 | mem_t *head; 42 | mem_t *tail; 43 | 44 | unsigned int count; 45 | } mem_pool_t; 46 | 47 | 48 | /* Macros */ 49 | #define MPOOL_SIZE(P) ((P)->count) 50 | #define MPOOL_ISEMPTY(P) ((P)->count == 0) 51 | #define MPOOL_TAIL(P) ((P)->tail) 52 | #define MPOOL_DATA(P) ((P)->data) 53 | 54 | 55 | /* Prototypes */ 56 | extern void mpool_dump(mem_pool_t *); 57 | extern void mpool_queue_tail(mem_pool_t *, mem_t *); 58 | extern mem_t *mpool_dequeue(mem_pool_t *); 59 | extern mem_t *mpool_allocate_mem(int); 60 | extern mem_t *mpool_dup_mem(mem_t *); 61 | extern mem_t *mpool_create_mem(char *, int); 62 | extern void mpool_release_mem(mem_t *); 63 | extern void mpool_fill(mem_pool_t *, int, int); 64 | extern mem_pool_t *mpool_init(void); 65 | extern void mpool_destroy(mem_pool_t *); 66 | extern void mpool_move(mem_pool_t *, mem_pool_t *); 67 | 68 | #endif 69 | -------------------------------------------------------------------------------- /lib/pidfile.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #include "pidfile.h" 23 | 24 | /* Create the runnnig daemon pidfile */ 25 | int 26 | pidfile_write(char *pid_file, int pid) 27 | { 28 | FILE *pidfile = fopen(pid_file, "w"); 29 | 30 | if (!pidfile) { 31 | syslog(LOG_INFO, "pidfile_write : Can not open %s pidfile", 32 | pid_file); 33 | return 0; 34 | } 35 | fprintf(pidfile, "%d\n", pid); 36 | fclose(pidfile); 37 | return 1; 38 | } 39 | 40 | /* Remove the running daemon pidfile */ 41 | void 42 | pidfile_rm(char *pid_file) 43 | { 44 | unlink(pid_file); 45 | } 46 | 47 | /* return the daemon running state */ 48 | int 49 | process_running(char *pid_file) 50 | { 51 | FILE *pidfile = fopen(pid_file, "r"); 52 | pid_t pid; 53 | int ret; 54 | 55 | /* No pidfile */ 56 | if (!pidfile) 57 | return 0; 58 | 59 | ret = fscanf(pidfile, "%d", &pid); 60 | if (ret == EOF) 61 | syslog(LOG_INFO, "Error reading pid file %s (%d)", pid_file, ferror(pidfile)); 62 | fclose(pidfile); 63 | 64 | /* If no process is attached to pidfile, remove it */ 65 | if (kill(pid, 0)) { 66 | syslog(LOG_INFO, "Remove a zombie pid file %s", pid_file); 67 | pidfile_rm(pid_file); 68 | return 0; 69 | } 70 | 71 | return 1; 72 | } 73 | -------------------------------------------------------------------------------- /lib/pidfile.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _PIDFILE_H 23 | #define _PIDFILE_H 24 | 25 | /* system include */ 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | /* Prototypes */ 33 | extern int pidfile_write(char *pid_file, int pid); 34 | extern void pidfile_rm(char *pid_file); 35 | extern int process_running(char *pid_file); 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /lib/pkt_buffer.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _PKT_BUFFER_H 23 | #define _PKT_BUFFER_H 24 | 25 | /* defines */ 26 | #define DEFAULT_PKT_BUFFER_SIZE 4096 27 | 28 | /* pkt related */ 29 | typedef struct _pkt_buffer { 30 | unsigned char *head, 31 | *data; 32 | unsigned char *end; 33 | unsigned char *tail; 34 | } pkt_buffer_t; 35 | 36 | typedef struct _pkt { 37 | pkt_buffer_t *pbuff; 38 | 39 | list_head_t next; 40 | } pkt_t; 41 | 42 | typedef struct _mpkt { 43 | unsigned int vlen; 44 | struct mmsghdr *msgs; 45 | struct iovec *iovecs; 46 | pkt_t **pkt; 47 | } mpkt_t; 48 | 49 | typedef struct _pkt_queue { 50 | pthread_mutex_t mutex; 51 | list_head_t queue; 52 | } pkt_queue_t; 53 | 54 | static inline unsigned int pkt_buffer_len(pkt_buffer_t *b) 55 | { 56 | return b->end - b->head; 57 | } 58 | 59 | static inline unsigned int pkt_buffer_size(pkt_buffer_t *b) 60 | { 61 | return b->tail - b->head; 62 | } 63 | 64 | static inline unsigned int pkt_buffer_headroom(pkt_buffer_t *b) 65 | { 66 | return b->data - b->head; 67 | } 68 | 69 | static inline unsigned int pkt_buffer_tailroom(pkt_buffer_t *b) 70 | { 71 | return b->tail - b->end; 72 | } 73 | 74 | static inline unsigned int pkt_buffer_data_tailroom(pkt_buffer_t *b) 75 | { 76 | return b->end - b->data; 77 | } 78 | 79 | static inline unsigned char *pkt_buffer_end(pkt_buffer_t *b) 80 | { 81 | return b->end; 82 | } 83 | 84 | static inline void pkt_buffer_reset(pkt_buffer_t *b) 85 | { 86 | b->data = b->end = b->head; 87 | } 88 | 89 | static inline void pkt_buffer_reset_data(pkt_buffer_t *b) 90 | { 91 | b->data = b->head; 92 | } 93 | 94 | static inline void pkt_buffer_set_end_pointer(pkt_buffer_t *b, unsigned int offset) 95 | { 96 | b->end = b->head + offset; 97 | } 98 | 99 | static inline void pkt_buffer_set_data_pointer(pkt_buffer_t *b, unsigned int offset) 100 | { 101 | b->data = b->head + offset; 102 | } 103 | 104 | static inline void pkt_buffer_put_data(pkt_buffer_t *b, unsigned int offset) 105 | { 106 | b->data += offset; 107 | } 108 | 109 | static inline void pkt_buffer_put_end(pkt_buffer_t *b, unsigned int offset) 110 | { 111 | b->end += offset; 112 | } 113 | 114 | /* Prototypes */ 115 | extern ssize_t pkt_send(int fd, pkt_queue_t *, pkt_t *); 116 | extern ssize_t pkt_recv(int fd, pkt_t *); 117 | extern int mpkt_recv(int, mpkt_t *); 118 | extern void pkt_queue_run(pkt_queue_t *, int (*run) (pkt_t *, void *), void *); 119 | extern pkt_t *pkt_queue_get(pkt_queue_t *); 120 | extern int __pkt_queue_put(pkt_queue_t *, pkt_t *); 121 | extern int pkt_queue_put(pkt_queue_t *, pkt_t *); 122 | extern int mpkt_init(mpkt_t *, unsigned int); 123 | extern void mpkt_process(mpkt_t *, unsigned int, void (*process) (pkt_t *, void *), void *); 124 | extern void mpkt_destroy(mpkt_t *); 125 | extern void mpkt_reset(mpkt_t *); 126 | extern int __pkt_queue_mget(pkt_queue_t *, mpkt_t *); 127 | extern int pkt_queue_mget(pkt_queue_t *, mpkt_t *); 128 | extern int __pkt_queue_mput(pkt_queue_t *, mpkt_t *); 129 | extern int pkt_queue_mput(pkt_queue_t *, mpkt_t *); 130 | extern int pkt_queue_init(pkt_queue_t *); 131 | extern int pkt_queue_destroy(pkt_queue_t *); 132 | extern ssize_t pkt_buffer_send(int, pkt_buffer_t *, struct sockaddr_storage *); 133 | extern int pkt_buffer_put_zero(pkt_buffer_t *, unsigned int); 134 | extern int pkt_buffer_pad(pkt_buffer_t *, unsigned int); 135 | extern pkt_buffer_t *pkt_buffer_alloc(unsigned int); 136 | extern void pkt_buffer_free(pkt_buffer_t *); 137 | 138 | #endif 139 | -------------------------------------------------------------------------------- /lib/prefix.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 | /* IP prefix implementation 3 | * Copyright (C) 1997 Kunihiro Ishiguro 4 | */ 5 | 6 | #include 7 | #include 8 | #include 9 | #include "memory.h" 10 | #include "utils.h" 11 | #include "prefix.h" 12 | 13 | /* Maskbit. */ 14 | static const uint8_t maskbit[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff}; 15 | 16 | /* Number of bits in prefix type. */ 17 | #ifndef PNBBY 18 | #define PNBBY 8 19 | #endif /* PNBBY */ 20 | 21 | #define MASKBIT(offset) ((0xff << (PNBBY - (offset))) & 0xff) 22 | 23 | 24 | /* 25 | * If n includes p prefix then return 1 else return 0. 26 | */ 27 | int 28 | prefix_match(const prefix_t *n, const prefix_t *p) 29 | { 30 | int offset; 31 | int shift; 32 | const uint8_t *np, *pp; 33 | 34 | /* If n's prefix is longer than p's one return 0. */ 35 | if (n->prefixlen > p->prefixlen) 36 | return 0; 37 | 38 | /* Set both prefix's head pointer. */ 39 | np = (const uint8_t *)&n->u.prefix; 40 | pp = (const uint8_t *)&p->u.prefix; 41 | 42 | offset = n->prefixlen / PNBBY; 43 | shift = n->prefixlen % PNBBY; 44 | 45 | if (shift) { 46 | if (maskbit[shift] & (np[offset] ^ pp[offset])) { 47 | return 0; 48 | } 49 | } 50 | 51 | while (offset--) { 52 | if (np[offset] != pp[offset]) { 53 | return 0; 54 | } 55 | } 56 | 57 | return 1; 58 | } 59 | 60 | /* 61 | * Copy prefix from src to dest. 62 | */ 63 | int 64 | prefix_copy(prefix_t *dest, const prefix_t *src) 65 | { 66 | dest->family = src->family; 67 | dest->prefixlen = src->prefixlen; 68 | 69 | if (src->family == AF_INET) { 70 | dest->u.prefix4 = src->u.prefix4; 71 | } else if (src->family == AF_INET6) { 72 | dest->u.prefix6 = src->u.prefix6; 73 | } else { 74 | return -1; 75 | } 76 | 77 | return 0; 78 | } 79 | 80 | 81 | /* 82 | * Convert a string to a prefix 83 | */ 84 | int 85 | str2prefix_ipv4(const char *str, prefix_ipv4_t *p) 86 | { 87 | int ret, plen; 88 | char *pnt, *cp; 89 | 90 | /* Find slash inside string. */ 91 | pnt = strchr(str, '/'); 92 | 93 | /* String doesn't contail slash. */ 94 | if (pnt == NULL) { 95 | /* Convert string to prefix. */ 96 | ret = inet_aton(str, &p->prefix); 97 | if (ret == 0) 98 | return 0; 99 | 100 | /* If address doesn't contain slash we assume it host address. */ 101 | p->prefixlen = IPV4_MAX_BITLEN; 102 | 103 | return ret; 104 | } else { 105 | cp = MALLOC((pnt - str) + 1); 106 | strncpy(cp, str, pnt - str); 107 | *(cp + (pnt - str)) = '\0'; 108 | ret = inet_aton(cp, &p->prefix); 109 | FREE(cp); 110 | 111 | /* Get prefix length. */ 112 | plen = (u_char) atoi(++pnt); 113 | if (plen > IPV4_MAX_PREFIXLEN) 114 | return 0; 115 | 116 | p->prefixlen = plen; 117 | } 118 | 119 | p->family = AF_INET; 120 | 121 | return ret; 122 | } 123 | 124 | int 125 | str2prefix_ipv6(const char *str, prefix_ipv6_t *p) 126 | { 127 | int ret, plen; 128 | char *pnt, *cp; 129 | 130 | pnt = strchr(str, '/'); 131 | 132 | /* If string doesn't contain `/' treat it as host route. */ 133 | if (pnt == NULL) { 134 | ret = inet_pton(AF_INET6, str, &p->prefix); 135 | if (ret == 0) 136 | return 0; 137 | p->prefixlen = IPV6_MAX_BITLEN; 138 | } else { 139 | cp = MALLOC((pnt - str) + 1); 140 | strncpy (cp, str, pnt - str); 141 | *(cp + (pnt - str)) = '\0'; 142 | ret = inet_pton(AF_INET6, cp, &p->prefix); 143 | FREE(cp); 144 | if (ret == 0) 145 | return 0; 146 | plen = (u_char)atoi (++pnt); 147 | if (plen > 128) 148 | return 0; 149 | p->prefixlen = plen; 150 | } 151 | 152 | p->family = AF_INET6; 153 | 154 | return ret; 155 | } 156 | 157 | int 158 | str2prefix(const char *str, prefix_t *p) 159 | { 160 | int ret; 161 | 162 | /* First we try to convert string to struct prefix_ipv4. */ 163 | ret = str2prefix_ipv4(str, (prefix_ipv4_t *) p); 164 | if (ret) 165 | return ret; 166 | 167 | /* Next we try to convert string to struct prefix_ipv6. */ 168 | ret = str2prefix_ipv6(str, (prefix_ipv6_t *) p); 169 | if (ret) 170 | return ret; 171 | 172 | return 0; 173 | } 174 | 175 | /* 176 | * Convert bytes to prefix 177 | */ 178 | int 179 | ip2prefix_ipv4(const uint32_t ip_address, prefix_t *p) 180 | { 181 | prefix_ipv4_t *prefix_ipv4 = (prefix_ipv4_t *) p; 182 | 183 | prefix_ipv4->family = AF_INET; 184 | prefix_ipv4->prefixlen = IPV4_MAX_BITLEN; 185 | prefix_ipv4->prefix.s_addr = ip_address; 186 | 187 | return 0; 188 | } 189 | 190 | 191 | /* 192 | * Prefix alloc 193 | */ 194 | prefix_t * 195 | prefix_alloc(void) 196 | { 197 | prefix_t *p = (prefix_t *) MALLOC(sizeof(prefix_t)); 198 | return p; 199 | } 200 | 201 | void 202 | prefix_free(prefix_t *p) 203 | { 204 | FREE(p); 205 | } 206 | 207 | void 208 | prefix_dump(prefix_t *p) 209 | { 210 | syslog(LOG_INFO, "prefix : %u.%u.%u.%u/%d" 211 | , NIPQUAD(p->u.prefix4.s_addr) 212 | , p->prefixlen); 213 | } 214 | -------------------------------------------------------------------------------- /lib/prefix.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 | /* IP prefix implementation 3 | * Copyright (C) 1997 Kunihiro Ishiguro 4 | */ 5 | 6 | #ifndef _PREFIX_H 7 | #define _PREFIX_H 8 | 9 | /* system includes */ 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | /* 17 | * IPv4 and IPv6 unified prefix structure 18 | */ 19 | typedef struct _prefix { 20 | uint8_t family; 21 | uint8_t prefixlen; 22 | union { 23 | uint8_t prefix; 24 | struct in_addr prefix4; 25 | struct in6_addr prefix6; 26 | } u __attribute__ ((aligned (8))); 27 | } prefix_t; 28 | 29 | typedef struct _prefix_ipv4 { 30 | uint8_t family; 31 | uint8_t prefixlen; 32 | struct in_addr prefix __attribute__ ((aligned (8))); 33 | } prefix_ipv4_t; 34 | 35 | typedef struct _prefix_ipv6 { 36 | uint8_t family; 37 | uint8_t prefixlen; 38 | struct in6_addr prefix __attribute__ ((aligned (8))); 39 | } prefix_ipv6_t; 40 | 41 | 42 | /* Max bit/byte length of IPv4 address */ 43 | #define IPV4_MAX_BYTELEN 4 44 | #define IPV4_MAX_BITLEN 32 45 | #define IPV4_MAX_PREFIXLEN 32 46 | #define IPV4_ADDR_CMP(D,S) memcmp ((D), (S), IPV4_MAX_BYTELEN) 47 | #define IPV4_ADDR_SAME(D,S) (memcmp ((D), (S), IPV4_MAX_BYTELEN) == 0) 48 | #define IPV4_ADDR_COPY(D,S) memcpy ((D), (S), IPV4_MAX_BYTELEN) 49 | 50 | #define IPV4_NET0(a) ((((uint32_t) (a)) & 0xff000000) == 0x00000000) 51 | #define IPV4_NET127(a) ((((uint32_t) (a)) & 0xff000000) == 0x7f000000) 52 | #define IPV4_LINKLOCAL(a) ((((uint32_t) (a)) & 0xffff0000) == 0xa9fe0000) 53 | 54 | /* Max bit/byte length of IPv6 address */ 55 | #define IPV6_MAX_BYTELEN 16 56 | #define IPV6_MAX_BITLEN 128 57 | #define IPV6_MAX_PREFIXLEN 128 58 | #define IPV6_ADDR_CMP(D,S) memcmp ((D), (S), IPV6_MAX_BYTELEN) 59 | #define IPV6_ADDR_SAME(D,S) (memcmp ((D), (S), IPV6_MAX_BYTELEN) == 0) 60 | #define IPV6_ADDR_COPY(D,S) memcpy ((D), (S), IPV6_MAX_BYTELEN) 61 | 62 | /* Count prefix size from mask length */ 63 | #define PSIZE(a) (((a) + 7) / (8)) 64 | 65 | /* Prefix's family member */ 66 | #define PREFIX_FAMILY(p) ((p)->family) 67 | 68 | /* Check bit of the prefix */ 69 | static inline unsigned int 70 | prefix_bit(const uint8_t *prefix, const uint8_t prefixlen) 71 | { 72 | unsigned int offset = prefixlen / 8; 73 | unsigned int shift = 7 - (prefixlen % 8); 74 | 75 | return (prefix[offset] >> shift) & 1; 76 | } 77 | 78 | static inline unsigned int 79 | prefix6_bit(const struct in6_addr *prefix, const uint8_t prefixlen) 80 | { 81 | return prefix_bit((const u_char *) &prefix->s6_addr, prefixlen); 82 | } 83 | 84 | 85 | /* 86 | * Prototypes 87 | */ 88 | extern int prefix_match(const prefix_t *, const prefix_t *); 89 | extern int prefix_copy(prefix_t *, const prefix_t *); 90 | extern int str2prefix(const char *, prefix_t *); 91 | extern int ip2prefix_ipv4(const uint32_t, prefix_t *); 92 | extern prefix_t *prefix_alloc(void); 93 | extern void prefix_free(prefix_t *); 94 | extern void prefix_dump(prefix_t *); 95 | 96 | #endif 97 | -------------------------------------------------------------------------------- /lib/process.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _PROCESS_H 23 | #define _PROCESS_H 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #define RT_RLIMIT_DEFAULT 10000 30 | 31 | /* The maximum pid is 2^22 - see definition of PID_MAX_LIMIT in kernel source include/linux/threads.h */ 32 | #define PID_MAX_DIGITS 7 33 | 34 | extern long min_auto_priority_delay; 35 | 36 | extern void set_process_priorities(int, int, long, int, int, int); 37 | extern void reset_process_priorities(void); 38 | extern void increment_process_priority(void); 39 | extern unsigned get_cur_priority(void) __attribute__((pure)); 40 | extern unsigned get_cur_rlimit_rttime(void) __attribute__((pure)); 41 | extern int set_process_cpu_affinity(cpu_set_t *, const char *); 42 | extern int get_process_cpu_affinity_string(cpu_set_t *, char *, size_t); 43 | extern void set_child_rlimit(int, const struct rlimit *); 44 | 45 | extern void set_max_file_limit(unsigned); 46 | #endif 47 | -------------------------------------------------------------------------------- /lib/rbtree_api.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _RBTREE_API_H 23 | #define _RBTREE_API_H 24 | 25 | #include "rbtree.h" 26 | 27 | typedef struct rb_node rb_node_t; 28 | typedef struct rb_root rb_root_t; 29 | typedef struct rb_root_cached rb_root_cached_t; 30 | 31 | 32 | /** 33 | * rb_for_each_entry - Iterate over rbtree of given type 34 | * @pos: the type * to use as a loop cursor. 35 | * @root: the rbtree root. 36 | * @member: the name of the rb_node within the struct. 37 | */ 38 | #define rb_for_each_entry(pos, root, member) \ 39 | for (pos = rb_entry_safe(rb_first(root), typeof(*pos), member); \ 40 | pos; pos = rb_entry_safe(rb_next(&pos->member), typeof(*pos), member)) 41 | #define rb_for_each_entry_const(pos, root, member) \ 42 | for (pos = rb_entry_safe_const(rb_first(root), typeof(*pos), member); \ 43 | pos; pos = rb_entry_safe_const(rb_next(&pos->member), typeof(*pos), member)) 44 | 45 | /** 46 | * rb_for_each_entry_safe - Iterate over rbtree of given type safe against removal 47 | * @pos: the type * to use as a loop cursor. 48 | * @root: the rbtree root. 49 | * @member: the name of the rb_node within the struct. 50 | */ 51 | #define rb_for_each_entry_safe(pos, n, root, member) \ 52 | for (pos = rb_entry_safe(rb_first(root), typeof(*pos), member); \ 53 | pos && (n = rb_entry_safe(rb_next(&pos->member), typeof(*n), member), 1); \ 54 | pos = n) 55 | 56 | /** 57 | * rb_for_each_entry_cached - Iterate over cached rbtree of given type 58 | * @pos: the type * to use as a loop cursor. 59 | * @root: the rbtree root. 60 | * @member: the name of the rb_node within the struct. 61 | */ 62 | #define rb_for_each_entry_cached(pos, root, member) \ 63 | for (pos = rb_entry_safe(rb_first_cached(root), typeof(*pos), member); \ 64 | pos; pos = rb_entry_safe(rb_next(&pos->member), typeof(*pos), member)) 65 | #define rb_for_each_entry_cached_const(pos, root, member) \ 66 | for (pos = rb_entry_safe_const(rb_first_cached(root), typeof(*pos), member); \ 67 | pos; pos = rb_entry_safe_const(rb_next(&pos->member), typeof(*pos), member)) 68 | 69 | /** 70 | * rb_for_each_entry_safe_cached - Iterate over cached rbtree of given type 71 | * @pos: the type * to use as a loop cursor. 72 | * @root: the rbtree root. 73 | * @member: the name of the rb_node within the struct. 74 | */ 75 | #define rb_for_each_entry_safe_cached(pos, n, root, member) \ 76 | for (pos = rb_entry_safe(rb_first_cached(root), typeof(*pos), member); \ 77 | pos && (n = rb_entry_safe(rb_next(&pos->member), typeof(*n), member), 1); \ 78 | pos = n) 79 | 80 | /** 81 | * rb_move_cached - Move node to new position in tree 82 | * @node: the node to move. 83 | * @root: the rbtree root. 84 | * @less: the name of the less function to use. 85 | */ 86 | static __always_inline void 87 | rb_move_cached(struct rb_node *node, struct rb_root_cached *tree, 88 | bool (*less)(struct rb_node *, const struct rb_node *)) 89 | { 90 | rb_node_t *prev_node, *next_node; 91 | 92 | prev_node = rb_prev(node); 93 | next_node = rb_next(node); 94 | 95 | if (prev_node || next_node) { 96 | /* If node is between our predecessor and successor, 97 | * it can stay where it is */ 98 | if ((prev_node && less(node, prev_node)) || 99 | (next_node && less(next_node, node))) { 100 | /* Can this be optimised? */ 101 | rb_erase_cached(node, tree); 102 | rb_add_cached(node, tree, less); 103 | } 104 | } 105 | } 106 | 107 | #endif /* _LINUX_RBTREE_H */ 108 | -------------------------------------------------------------------------------- /lib/rbtree_types.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 | #ifndef _LINUX_RBTREE_TYPES_H 3 | #define _LINUX_RBTREE_TYPES_H 4 | 5 | struct rb_node { 6 | unsigned long __rb_parent_color; 7 | struct rb_node *rb_right; 8 | struct rb_node *rb_left; 9 | } __attribute__((aligned(sizeof(long)))); 10 | /* The alignment might seem pointless, but allegedly CRIS needs it */ 11 | 12 | struct rb_root { 13 | struct rb_node *rb_node; 14 | }; 15 | 16 | /* 17 | * Leftmost-cached rbtrees. 18 | * 19 | * We do not cache the rightmost node based on footprint 20 | * size vs number of potential users that could benefit 21 | * from O(1) rb_last(). Just not worth it, users that want 22 | * this feature can always implement the logic explicitly. 23 | * Furthermore, users that want to cache both pointers may 24 | * find it a bit asymmetric, but that's ok. 25 | */ 26 | struct rb_root_cached { 27 | struct rb_root rb_root; 28 | struct rb_node *rb_leftmost; 29 | }; 30 | 31 | #define RB_ROOT (struct rb_root) { NULL, } 32 | #define RB_ROOT_CACHED (struct rb_root_cached) { {NULL, }, NULL } 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /lib/rt_table.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 | /* Routing table implementation 3 | * Copyright (C) 1997 Kunihiro Ishiguro 4 | */ 5 | 6 | #ifndef _RT_TABLE_H 7 | #define _RT_TABLE_H 8 | 9 | /* system includes */ 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | /* Each routing entry */ 17 | struct _rt_table; 18 | typedef struct _rt_node { 19 | /* Actual prefix of this radix */ 20 | prefix_t p; 21 | 22 | /* Tree link */ 23 | struct _rt_table *table; 24 | struct _rt_node *parent; 25 | struct _rt_node *link[2]; 26 | #define l_left link[0] 27 | #define l_right link[1] 28 | 29 | /* Lock of this radix */ 30 | unsigned int lock; 31 | 32 | /* Each node of route */ 33 | void *info; 34 | } rt_node_t; 35 | 36 | /* Routing table top structure */ 37 | typedef struct _rt_table { 38 | rt_node_t *top; 39 | int (*free_info) (void *); 40 | int (*dump_info) (void *); 41 | } rt_table_t; 42 | 43 | 44 | /* 45 | * Prototypes 46 | */ 47 | extern rt_table_t *rt_table_init(int (*free) (void *), int (*dump) (void *)); 48 | extern int rt_table_free(rt_table_t *); 49 | extern int rt_table_dump(rt_table_t *); 50 | extern rt_node_t *rt_node_match(const rt_table_t *, const prefix_t *); 51 | extern rt_node_t *rt_node_match_ipv4(const rt_table_t *, const struct in_addr *); 52 | extern rt_node_t *rt_node_match_ipv6(const rt_table_t *, const struct in6_addr *); 53 | extern rt_node_t *rt_node_lookup(rt_table_t *, prefix_t *); 54 | extern rt_node_t *rt_node_lookup_lpm(rt_table_t *, prefix_t *); 55 | extern rt_node_t *rt_node_get(rt_table_t *, prefix_t *); 56 | extern int rt_node_delete(rt_node_t *); 57 | extern rt_node_t *rt_next(rt_node_t *); 58 | extern rt_node_t *rt_next_until(rt_node_t *, rt_node_t *); 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /lib/signals.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _SIGNALS_H 23 | #define _SIGNALS_H 24 | 25 | #include "config.h" 26 | 27 | #include 28 | #include 29 | 30 | #include "scheduler.h" 31 | 32 | #define SIGJSON (SIGRTMIN + 2) 33 | #ifdef THREAD_DUMP 34 | #define SIGTDUMP (SIGRTMAX) 35 | #endif 36 | #define SIGSTATS_CLEAR (SIGRTMAX - 1) 37 | #ifndef _ONE_PROCESS_DEBUG_ 38 | #endif 39 | 40 | static inline int 41 | sigmask_func(int how, const sigset_t *set, sigset_t *oldset) 42 | { 43 | #ifdef _WITH_PTHREADS_ 44 | return pthread_sigmask(how, set, oldset); 45 | #else 46 | return sigprocmask(how, set, oldset); 47 | #endif 48 | } 49 | 50 | /* Prototypes */ 51 | extern int get_signum(const char *); 52 | extern void signal_set(int, void (*) (void *, int), void *); 53 | extern void signal_ignore(int); 54 | extern int signal_handler_init(void); 55 | extern void signal_handler_destroy(void); 56 | extern void signal_handler_script(void); 57 | extern void add_signal_read_thread(thread_master_t *); 58 | extern void cancel_signal_read_thread(void); 59 | extern void set_sigxcpu_handler(void); 60 | extern void signal_noignore_sigchld(void); 61 | extern void signal_noignore_sig(int); 62 | 63 | #ifdef THREAD_DUMP 64 | extern void register_signal_thread_addresses(void); 65 | #endif 66 | 67 | #endif 68 | -------------------------------------------------------------------------------- /lib/timer.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _TIMER_H 23 | #define _TIMER_H 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | typedef struct timeval timeval_t; 31 | 32 | /* Global vars */ 33 | extern timeval_t time_now; 34 | 35 | /* Some defines */ 36 | #define TIMER_HZ 1000000 37 | #define TIMER_HZ_DIGITS 6 38 | #define TIMER_HZ_FLOAT 1000000.0F 39 | #define TIMER_HZ_DOUBLE ((double)1000000.0F) 40 | #define TIMER_CENTI_HZ 10000 41 | #define TIMER_MAX_SEC 1000U 42 | #define TIMER_NEVER ULONG_MAX /* Used with time intervals in TIMER_HZ units */ 43 | #define TIMER_DISABLED LONG_MIN /* Value in timeval_t tv_sec */ 44 | 45 | #define NSEC_PER_SEC 1000000000 /* nanoseconds per second. Avoids typos by having a definition */ 46 | 47 | #ifdef _TIMER_CHECK_ 48 | #define timer_now() timer_now_r((__FILE__), (__func__), (__LINE__)) 49 | #define set_time_now() set_time_now_r((__FILE__), (__func__), (__LINE__)) 50 | #endif 51 | 52 | #define RB_TIMER_CMP(obj, nnn) \ 53 | static inline int \ 54 | obj##_timer_cmp(const timeval_t *sands, const rb_node_t *a) \ 55 | { \ 56 | const obj##_t *r1 = rb_entry_const(a, obj##_t, nnn); \ 57 | \ 58 | if (sands->tv_sec == TIMER_DISABLED) { \ 59 | if (r1->sands.tv_sec == TIMER_DISABLED) \ 60 | return 0; \ 61 | return 1; \ 62 | } \ 63 | \ 64 | if (r1->sands.tv_sec == TIMER_DISABLED) \ 65 | return -1; \ 66 | \ 67 | if (sands->tv_sec != r1->sands.tv_sec) \ 68 | return sands->tv_sec - r1->sands.tv_sec; \ 69 | \ 70 | return sands->tv_usec - r1->sands.tv_usec; \ 71 | } 72 | 73 | #define RB_TIMER_LESS(obj, nnn) \ 74 | static inline bool \ 75 | obj##_timer_less(rb_node_t *a, const rb_node_t *b) \ 76 | { \ 77 | const obj##_t *r1 = rb_entry_const(a, obj##_t, nnn); \ 78 | const obj##_t *r2 = rb_entry_const(b, obj##_t, nnn); \ 79 | \ 80 | if (r1->sands.tv_sec == TIMER_DISABLED) \ 81 | return false; \ 82 | \ 83 | if (r2->sands.tv_sec == TIMER_DISABLED) \ 84 | return true; \ 85 | \ 86 | if (r1->sands.tv_sec != r2->sands.tv_sec) \ 87 | return r1->sands.tv_sec < r2->sands.tv_sec; \ 88 | \ 89 | return r1->sands.tv_usec < r2->sands.tv_usec; \ 90 | } 91 | 92 | /* timer sub from current time */ 93 | static inline timeval_t 94 | timer_sub_now(timeval_t a) 95 | { 96 | timersub(&a, &time_now, &a); 97 | 98 | return a; 99 | } 100 | 101 | /* timer add to current time */ 102 | static inline timeval_t 103 | timer_add_now(timeval_t a) 104 | { 105 | timeradd(&time_now, &a, &a); 106 | 107 | return a; 108 | } 109 | 110 | /* timer add secs to current time */ 111 | static inline timeval_t 112 | timer_add_now_sec(timeval_t a, time_t sec) 113 | { 114 | a.tv_sec = time_now.tv_sec + sec; 115 | a.tv_usec = time_now.tv_usec; 116 | 117 | return a; 118 | } 119 | 120 | /* Returns true if time a + diff_hz < time_now */ 121 | static inline bool 122 | timer_cmp_now_diff(timeval_t a, unsigned long diff_hz) 123 | { 124 | timeval_t b = { .tv_sec = diff_hz / TIMER_HZ, .tv_usec = diff_hz % TIMER_HZ }; 125 | 126 | timeradd(&b, &a, &b); 127 | 128 | return !!timercmp(&b, &time_now, <); 129 | } 130 | 131 | /* Return time as unsigned long */ 132 | static inline unsigned long 133 | timer_long(timeval_t a) 134 | { 135 | return (unsigned long)a.tv_sec * TIMER_HZ + (unsigned long)a.tv_usec; 136 | } 137 | 138 | /* prototypes */ 139 | extern timeval_t timer_now(void); 140 | extern timeval_t set_time_now(void); 141 | extern struct tm *time_now_to_calendar(struct tm *); 142 | extern timeval_t timer_add_long(timeval_t, unsigned long) __attribute__((const)); 143 | extern timeval_t timer_sub_long(timeval_t, unsigned long) __attribute__((const)); 144 | 145 | #endif 146 | -------------------------------------------------------------------------------- /lib/timer_thread.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _TIMER_THREAD_H 23 | #define _TIMER_THREAD_H 24 | 25 | enum { 26 | TIMER_THREAD_FL_STOP_BIT, 27 | }; 28 | 29 | #define TIMER_THREAD_NAMESIZ 128 30 | typedef struct _timer_thread { 31 | char name[TIMER_THREAD_NAMESIZ]; 32 | rb_root_cached_t timer; 33 | pthread_mutex_t timer_mutex; 34 | pthread_t task; 35 | pthread_cond_t cond; 36 | pthread_mutex_t cond_mutex; 37 | int (*fired) (void *); 38 | 39 | unsigned long flags; 40 | } timer_thread_t; 41 | 42 | typedef struct _timer_node { 43 | int (*to_func) (void *); 44 | void *to_arg; 45 | timeval_t sands; 46 | rb_node_t n; 47 | } timer_node_t; 48 | 49 | 50 | /* prototypes */ 51 | extern void timer_node_expire_now(timer_thread_t *, timer_node_t *); 52 | extern void timer_node_init(timer_node_t *, int (*fn) (void *), void *); 53 | extern void timer_node_add(timer_thread_t *, timer_node_t *, int); 54 | extern int timer_node_pending(timer_node_t *); 55 | extern int timer_node_del(timer_thread_t *, timer_node_t *); 56 | extern int timer_thread_init(timer_thread_t *, const char *, int (*fired) (void *)); 57 | extern int timer_thread_signal(timer_thread_t *); 58 | extern int timer_thread_destroy(timer_thread_t *); 59 | 60 | #endif 61 | -------------------------------------------------------------------------------- /lib/vector.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 | /* Generic vector interface routine 3 | * Copyright (C) 1997 Kunihiro Ishiguro 4 | */ 5 | 6 | #include "vector.h" 7 | #include "utils.h" 8 | #include "memory.h" 9 | 10 | /* 11 | * Initialize vector struct. 12 | * allocalted 'size' slot elements then return vector. 13 | */ 14 | vector_t * 15 | vector_alloc(void) 16 | { 17 | vector_t *v = (vector_t *) MALLOC(sizeof(vector_t)); 18 | return v; 19 | } 20 | 21 | vector_t * 22 | vector_init(unsigned int size) 23 | { 24 | vector_t *v = vector_alloc(); 25 | 26 | /* allocate at least one slot */ 27 | if (size == 0) 28 | size = 1; 29 | 30 | v->allocated = size; 31 | v->active = 0; 32 | v->slot = (void *) MALLOC(sizeof(void *) * size); 33 | return v; 34 | } 35 | 36 | /* allocated one slot */ 37 | void 38 | vector_alloc_slot(vector_t *v) 39 | { 40 | v->allocated += VECTOR_DEFAULT_SIZE; 41 | if (v->slot) 42 | v->slot = REALLOC(v->slot, sizeof (void *) * v->allocated); 43 | else 44 | v->slot = (void *) MALLOC(sizeof (void *) * v->allocated); 45 | } 46 | 47 | /* Insert a value into a specific slot */ 48 | void 49 | vector_insert_slot(vector_t *v, int index, void *value) 50 | { 51 | int i; 52 | 53 | vector_alloc_slot(v); 54 | for (i = (v->allocated / VECTOR_DEFAULT_SIZE) - 2; i >= index; i--) 55 | v->slot[i + 1] = v->slot[i]; 56 | v->slot[index] = value; 57 | } 58 | 59 | /* Copy / dup a vector */ 60 | vector_t * 61 | vector_copy(vector_t *v) 62 | { 63 | unsigned int size; 64 | vector_t *new = vector_alloc(); 65 | 66 | new->active = v->active; 67 | new->allocated = v->allocated; 68 | 69 | size = sizeof(void *) * (v->allocated); 70 | new->slot = (void *) MALLOC(size); 71 | memcpy(new->slot, v->slot, size); 72 | 73 | return new; 74 | } 75 | 76 | /* Check assigned index, and if it runs short double index pointer */ 77 | void 78 | vector_ensure(vector_t *v, unsigned int num) 79 | { 80 | if (v->allocated > num) 81 | return; 82 | 83 | v->slot = REALLOC(v->slot, sizeof(void *) * (v->allocated * 2)); 84 | memset(&v->slot[v->allocated], 0, sizeof (void *) * v->allocated); 85 | v->allocated *= 2; 86 | 87 | if (v->allocated <= num) 88 | vector_ensure(v, num); 89 | } 90 | 91 | /* This function only returns next empty slot index. It dose not mean 92 | * the slot's index memory is assigned, please call vector_ensure() 93 | * after calling this function. 94 | */ 95 | int 96 | vector_empty_slot(vector_t *v) 97 | { 98 | unsigned int i; 99 | 100 | if (v->active == 0) 101 | return 0; 102 | 103 | for (i = 0; i < v->active; i++) { 104 | if (v->slot[i] == 0) { 105 | return i; 106 | } 107 | } 108 | 109 | return i; 110 | } 111 | 112 | /* Set value to the smallest empty slot. */ 113 | int 114 | vector_set(vector_t *v, void *val) 115 | { 116 | unsigned int i; 117 | 118 | i = vector_empty_slot(v); 119 | vector_ensure(v, i); 120 | 121 | v->slot[i] = val; 122 | 123 | if (v->active <= i) 124 | v->active = i + 1; 125 | 126 | return i; 127 | } 128 | 129 | /* Set a vector slot value */ 130 | void 131 | vector_set_slot(vector_t *v, void *value) 132 | { 133 | unsigned int i = v->allocated - 1; 134 | 135 | v->slot[i] = value; 136 | } 137 | 138 | /* Set value to specified index slot. */ 139 | int 140 | vector_set_index(vector_t *v, unsigned int i, const void *val) 141 | { 142 | vector_ensure(v, i); 143 | 144 | v->slot[i] = no_const(void, val); 145 | 146 | if (v->active <= i) 147 | v->active = i + 1; 148 | 149 | return i; 150 | } 151 | 152 | /* Look up vector. */ 153 | void * 154 | vector_lookup(vector_t *v, unsigned int i) 155 | { 156 | if (i >= v->active) 157 | return NULL; 158 | return v->slot[i]; 159 | } 160 | 161 | /* Lookup vector, ensure it. */ 162 | void * 163 | vector_lookup_ensure(vector_t *v, unsigned int i) 164 | { 165 | vector_ensure(v, i); 166 | return v->slot[i]; 167 | } 168 | 169 | /* Unset value at specified index slot. */ 170 | void 171 | vector_unset(vector_t *v, unsigned int i) 172 | { 173 | if (i >= v->allocated) 174 | return; 175 | 176 | v->slot[i] = NULL; 177 | 178 | if (i + 1 == v->active) { 179 | v->active--; 180 | while (i && v->slot[--i] == NULL && v->active--) 181 | ; /* Is this ugly ? */ 182 | } 183 | } 184 | 185 | /* Count the number of not emplty slot. */ 186 | unsigned int 187 | vector_count(vector_t *v) 188 | { 189 | unsigned int i; 190 | unsigned count = 0; 191 | 192 | for (i = 0; i < v->active; i++) { 193 | if (v->slot[i] != NULL) { 194 | count++; 195 | } 196 | } 197 | 198 | return count; 199 | } 200 | 201 | /* Free memory vector allocation */ 202 | void 203 | vector_only_wrapper_free(vector_t *v) 204 | { 205 | FREE(v); 206 | } 207 | 208 | void 209 | vector_only_slot_free(void *slot) 210 | { 211 | FREE(slot); 212 | } 213 | 214 | void 215 | vector_only_index_free(void *slot) 216 | { 217 | vector_only_slot_free(slot); 218 | } 219 | 220 | void 221 | vector_free(vector_t *v) 222 | { 223 | FREE(v->slot); 224 | FREE(v); 225 | } 226 | 227 | /* dump vector slots */ 228 | void 229 | vector_dump(vector_t *v) 230 | { 231 | int i; 232 | 233 | printf("Vector Size : %d (active:%d)\n", v->allocated, v->active); 234 | 235 | for (i = 0; i < v->allocated; i++) { 236 | if (v->slot[i] != NULL) { 237 | printf(" Slot [%d]: %p/%s\n", i, vector_slot(v, i) 238 | , (char *)vector_slot(v, i)); 239 | } 240 | } 241 | } 242 | 243 | /* String vector related */ 244 | void 245 | free_strvec(vector_t *strvec) 246 | { 247 | int i; 248 | char *str; 249 | 250 | if (!strvec) 251 | return; 252 | 253 | for (i = 0; i < vector_size(strvec); i++) { 254 | if ((str = vector_slot(strvec, i)) != NULL) { 255 | FREE(str); 256 | } 257 | } 258 | 259 | vector_free(strvec); 260 | } 261 | 262 | void 263 | dump_strvec(vector_t *strvec) 264 | { 265 | int i; 266 | char *str; 267 | 268 | if (!strvec) 269 | return; 270 | 271 | printf("String Vector : "); 272 | 273 | for (i = 0; i < vector_size(strvec); i++) { 274 | str = vector_slot(strvec, i); 275 | printf("[%i]=%s ", i, str); 276 | } 277 | printf("\n"); 278 | } 279 | -------------------------------------------------------------------------------- /lib/vector.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 | /* Generic vector interface routine 3 | * Copyright (C) 1997 Kunihiro Ishiguro 4 | */ 5 | 6 | #ifndef _VECTOR_H 7 | #define _VECTOR_H 8 | 9 | /* vector definition */ 10 | typedef struct _vector { 11 | unsigned int active; 12 | unsigned int allocated; 13 | void **slot; 14 | } vector_t; 15 | 16 | /* Some defines */ 17 | #define VECTOR_DEFAULT_SIZE 1 18 | 19 | /* Some usefull macros */ 20 | #define vector_slot(V,E) ((V)->slot[(E)]) 21 | #define vector_size(V) ((V)->allocated) 22 | #define vector_active(V) ((V)->active) 23 | #define vector_foreach_slot(v,p,i) \ 24 | for (i = 0; i < (v)->allocated && ((p) = (v)->slot[i]); i++) 25 | 26 | /* Prototypes */ 27 | extern vector_t *vector_alloc(void); 28 | extern vector_t *vector_init(unsigned int); 29 | extern void vector_alloc_slot(vector_t *); 30 | extern void vector_insert_slot(vector_t *, int, void *); 31 | extern vector_t *vector_copy(vector_t *); 32 | extern void vector_ensure(vector_t *, unsigned int); 33 | extern int vector_empty_slot(vector_t *); 34 | extern int vector_set(vector_t *, void *); 35 | extern void vector_set_slot(vector_t *, void *); 36 | extern int vector_set_index(vector_t *, unsigned int, const void *); 37 | extern void *vector_lookup(vector_t *, unsigned int); 38 | extern void *vector_lookup_ensure(vector_t *, unsigned int); 39 | extern void vector_unset(vector_t *, unsigned int); 40 | extern unsigned int vector_count(vector_t *); 41 | extern void vector_only_wrapper_free(vector_t *); 42 | extern void vector_only_index_free(void *); 43 | extern void vector_only_slot_free(void *); 44 | extern void vector_free(vector_t *); 45 | extern void vector_dump(vector_t *); 46 | extern void free_strvec(vector_t *); 47 | extern void dump_strvec(vector_t *); 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /lib/warnings.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _WARNINGS_H 23 | #define _WARNINGS_H 24 | 25 | #ifdef __GNUC__ 26 | #include 27 | #endif 28 | 29 | #include "config.h" 30 | 31 | /* musl does not define __GNUC_PREREQ, so create a dummy definition */ 32 | #ifndef __GNUC_PREREQ 33 | #define __GNUC_PREREQ(maj, min) 0 34 | #endif 35 | 36 | /* GCC allows pragmas in functions, and diagnostic push/pop from version 4.6.0 */ 37 | 38 | /* See https://clang.llvm.org/docs/DiagnosticsReference.html for clang diagnostics 39 | * See https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html for GCC warnings 40 | */ 41 | 42 | #ifdef _HAVE_DIAGNOSTIC_PUSH_POP_PRAGMAS_ 43 | #define RELAX_END \ 44 | _Pragma("GCC diagnostic pop") 45 | #else 46 | #define RELAX_END 47 | #endif 48 | 49 | #if defined _HAVE_DIAGNOSTIC_PUSH_POP_PRAGMAS_ && defined _HAVE_WARNING_STACK_PROTECTOR_ 50 | #define RELAX_STACK_PROTECTOR_START \ 51 | _Pragma("GCC diagnostic push") \ 52 | _Pragma("GCC diagnostic ignored \"-Wstack-protector\"") 53 | #define RELAX_STACK_PROTECTOR_END RELAX_END 54 | #else 55 | #define RELAX_STACK_PROTECTOR_START 56 | #define RELAX_STACK_PROTECTOR_END 57 | #endif 58 | 59 | #if __GNUC__ && !__GNUC_PREREQ(8,0) && defined _HAVE_DIAGNOSTIC_PUSH_POP_PRAGMAS_ && defined _HAVE_WARNING_STRICT_OVERFLOW_ 60 | #ifdef _HAVE_PRAGMA_WARN_STRICT_OVERFLOW_1_ 61 | #define RELAX_STRICT_OVERFLOW_START \ 62 | _Pragma("GCC diagnostic push") \ 63 | _Pragma("GCC diagnostic warning \"-Wstrict-overflow=1\"") 64 | #else 65 | #define RELAX_STRICT_OVERFLOW_START \ 66 | _Pragma("GCC diagnostic push") \ 67 | _Pragma("GCC diagnostic warning \"-Wstrict-overflow\"") 68 | #endif 69 | #define RELAX_STRICT_OVERFLOW_END RELAX_END 70 | #else 71 | #define RELAX_STRICT_OVERFLOW_START 72 | #define RELAX_STRICT_OVERFLOW_END 73 | #endif 74 | 75 | #if defined _HAVE_DIAGNOSTIC_PUSH_POP_PRAGMAS_ && defined _HAVE_WARNING_CAST_QUAL_ 76 | #define RELAX_CAST_QUAL_START \ 77 | _Pragma("GCC diagnostic push") \ 78 | _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") 79 | #define RELAX_CAST_QUAL_END RELAX_END 80 | #else 81 | #define RELAX_CAST_QUAL_START 82 | #define RELAX_CAST_QUAL_END 83 | #endif 84 | 85 | #if defined _HAVE_DIAGNOSTIC_PUSH_POP_PRAGMAS_ && defined _HAVE_WARNING_SUGGEST_ATTRIBUTE_CONST_START_ 86 | #define RELAX_SUGGEST_ATTRIBUTE_CONST_START \ 87 | _Pragma("GCC diagnostic push") \ 88 | _Pragma("GCC diagnostic ignored \"-Wsuggest-attribute=const\"") 89 | #define RELAX_SUGGEST_ATTRIBUTE_CONST_END RELAX_END 90 | #else 91 | #define RELAX_SUGGEST_ATTRIBUTE_CONST_START 92 | #define RELAX_SUGGEST_ATTRIBUTE_CONST_END 93 | #endif 94 | 95 | #if defined _HAVE_DIAGNOSTIC_PUSH_POP_PRAGMAS_ && defined _HAVE_WARNING_STRINGOP_OVERFLOW_ 96 | #define RELAX_STRINGOP_OVERFLOW \ 97 | _Pragma("GCC diagnostic push") \ 98 | _Pragma("GCC diagnostic ignored \"-Wstringop-overflow\"") 99 | #define RELAX_STRINGOP_OVERFLOW_END RELAX_END 100 | #else 101 | #define RELAX_STRINGOP_OVERFLOW 102 | #define RELAX_STRINGOP_OVERFLOW_END 103 | #endif 104 | 105 | #if defined _HAVE_DIAGNOSTIC_PUSH_POP_PRAGMAS_ && defined _HAVE_WARNING_NESTED_EXTERNS_ 106 | # define RELAX_NESTED_EXTERNS_START \ 107 | _Pragma("GCC diagnostic push") \ 108 | _Pragma("GCC diagnostic ignored \"-Wnested-externs\"") 109 | #define RELAX_NESTED_EXTERNS_END RELAX_END 110 | #else 111 | #define RELAX_NESTED_EXTERNS_START 112 | #define RELAX_NESTED_EXTERNS_END 113 | #endif 114 | 115 | #if defined _HAVE_DIAGNOSTIC_PUSH_POP_PRAGMAS_ && defined _HAVE_WARNING_REDUNDANT_DECLS_ 116 | #define RELAX_REDUNDANT_DECLS_START \ 117 | _Pragma("GCC diagnostic push") \ 118 | _Pragma("GCC diagnostic ignored \"-Wredundant-decls\"") 119 | #define RELAX_REDUNDANT_DECLS_END RELAX_END 120 | #else 121 | #define RELAX_REDUNDANT_DECLS_START 122 | #define RELAX_REDUNDANT_DECLS_END 123 | #endif 124 | 125 | #endif 126 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: AGPL-3.0-or-later 2 | # 3 | # Soft: The main goal of dra-guard is to provide robust and secure 4 | # extensions to DRA feature (Diameter Routing Agent). DRA are 5 | # used in mobile networks to route Diameter traffic between 6 | # mobile network equipments, like at Roaming interconnections. 7 | # DRA-Guard implements a set of features to manipulate and 8 | # analyze Diameter payloads via a Plugin framework and a 9 | # built-in Route-Optimization feature. 10 | # 11 | # Authors: Alexandre Cassen, 12 | # 13 | # This program is free software; you can redistribute it and/or 14 | # modify it under the terms of the GNU Affero General Public 15 | # License Version 3.0 as published by the Free Software Foundation; 16 | # either version 3.0 of the License, or (at your option) any later 17 | # version. 18 | # 19 | # Copyright (C) 2024 Alexandre Cassen, 20 | # 21 | 22 | CC ?= gcc 23 | INCLUDES = -Iinclude -I../lib -I../libbpf/src -I../libbpf/src/uapi 24 | CFLAGS = -g -O2 -ggdb $(INCLUDES) -Werror -Wall -Wunused -Wstrict-prototypes -D_GNU_SOURCE 25 | #DEFS = -D_DEBUG_ 26 | DEFS = 27 | COMPILE = $(CC) $(CFLAGS) $(DEFS) 28 | 29 | OBJS = main.o dra_data.o dra_disk.o dra_if.o dra_vty.o dra_htab.o \ 30 | dra_debug.o dra_debug_vty.o dra_bpf.o dra_bpf_nat.o dra_bpf_vty.o \ 31 | dra_mip.o dra_mip_vty.o dra_arp.o dra_arp_vty.o dra_layer4.o \ 32 | dra_sctp.o dra_sctp_proto.o dra_sctp_vty.o dra_diameter.o dra_json.o \ 33 | dra_json_vty.o dra_plugin.o dra_plugin_vty.o dra_pcap.o dra_route_optim.o 34 | 35 | HEADERS = $(OBJS:.o=.h) 36 | 37 | .c.o: 38 | @echo " CC" $@ 39 | @$(COMPILE) -c $< 40 | 41 | all: $(OBJS) 42 | 43 | clean: 44 | rm -f *.a *.o *~ 45 | -------------------------------------------------------------------------------- /src/bpf/Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: AGPL-3.0-or-later 2 | # 3 | # Soft: The main goal of dra-guard is to provide robust and secure 4 | # extensions to DRA feature (Diameter Routing Agent). DRA are 5 | # used in mobile networks to route Diameter traffic between 6 | # mobile network equipments, like at Roaming interconnections. 7 | # DRA-Guard implements a set of features to manipulate and 8 | # analyze Diameter payloads via a Plugin framework and a 9 | # built-in Route-Optimization feature. 10 | # 11 | # Authors: Alexandre Cassen, 12 | # 13 | # This program is free software; you can redistribute it and/or 14 | # modify it under the terms of the GNU Affero General Public 15 | # License Version 3.0 as published by the Free Software Foundation; 16 | # either version 3.0 of the License, or (at your option) any later 17 | # version. 18 | # 19 | # Copyright (C) 2024 Alexandre Cassen, 20 | # 21 | 22 | # XDP program to build 23 | TARGETS := tc_sctp_nat.bpf xdp_sctp_nat.bpf 24 | BIN = ../../bin 25 | 26 | # Allows pointing LLC/CLANG to a LLVM backend with bpf support, redefine on cmdline: 27 | # make samples/bpf/ LLC=~/git/llvm/build/bin/llc CLANG=~/git/llvm/build/bin/clang 28 | LLC ?= llc 29 | CLANG ?= clang 30 | CFLAGS := -g -O2 -Wall -Werror 31 | 32 | # Include for BPF are pointing to libbpf 33 | LIBBPF = ../../libbpf 34 | LINUXINCLUDE := -I$(LIBBPF)/src 35 | 36 | all: dependencies $(TARGETS) 37 | .PHONY: dependencies clean $(CLANG) $(LLC) 38 | 39 | clean: 40 | @find . -type f \ 41 | \( -name '*~' \ 42 | -o -name '*.ll' \ 43 | -o -name '*.bc' \) \ 44 | -exec rm -vf '{}' \; 45 | @for i in $(TARGETS); do rm -vf $(BIN)/"$$i"; done 46 | 47 | dependencies: verify_cmds verify_target_bpf 48 | verify_cmds: $(CLANG) $(LLC) 49 | @for TOOL in $^ ; do \ 50 | if ! (which -- "$${TOOL}" > /dev/null 2>&1); then \ 51 | echo "*** ERROR: Cannot find LLVM tool $${TOOL}" ;\ 52 | exit 1; \ 53 | else true; fi; \ 54 | done 55 | verify_target_bpf: verify_cmds 56 | @if ! (${LLC} -march=bpf -mattr=help > /dev/null 2>&1); then \ 57 | echo "*** ERROR: LLVM (${LLC}) does not support 'bpf' target" ;\ 58 | echo " NOTICE: LLVM version >= 3.7.1 required" ;\ 59 | exit 2; \ 60 | else true; fi 61 | 62 | 63 | # asm/sysreg.h - inline assembly used by it is incompatible with llvm. 64 | # But, there is no easy way to fix it, so just exclude it since it is 65 | # useless for BPF samples. 66 | $(TARGETS): %.bpf: %.c 67 | @echo " CLANG-bpf" $@ 68 | @$(CLANG) $(CFLAGS) -S $(NOSTDINC_FLAGS) $(LINUXINCLUDE) \ 69 | -D__KERNEL__ -D__ASM_SYSREG_H \ 70 | -D__BPF_TRACING__ \ 71 | -Wall \ 72 | -Wno-unused-value -Wno-pointer-sign \ 73 | -D__TARGET_ARCH_$(ARCH) \ 74 | -Wno-compare-distinct-pointer-types \ 75 | -Wno-gnu-variable-sized-type-not-at-end \ 76 | -Wno-tautological-compare \ 77 | -Wno-unknown-warning-option \ 78 | -Wno-address-of-packed-member \ 79 | -O2 -emit-llvm -g -c $< -o ${@:.bpf=.ll} 80 | @$(LLC) -march=bpf -filetype=obj -o $(BIN)/$@ ${@:.bpf=.ll} 81 | -------------------------------------------------------------------------------- /src/dra_arp_vty.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | /* system includes */ 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | /* local includes */ 29 | #include "dra_guard.h" 30 | 31 | 32 | /* Extern data */ 33 | extern data_t *daemon_data; 34 | extern thread_master_t *master; 35 | 36 | static int arp_config_write(vty_t *vty); 37 | cmd_node_t arp_node = { 38 | .node = ARP_NODE, 39 | .parent_node = CONFIG_NODE, 40 | .prompt = "%s(arp-reply)# ", 41 | .config_write = arp_config_write, 42 | }; 43 | 44 | 45 | /* 46 | * Command 47 | */ 48 | DEFUN(arp_reply, 49 | arp_reply_cmd, 50 | "arp-reply", 51 | "Configure ARP reply\n") 52 | { 53 | vty->node = ARP_NODE; 54 | return CMD_SUCCESS; 55 | } 56 | 57 | static int 58 | arp_interface_parse(vty_t *vty, const char **argv, int *ifindex, uint32_t *ip_address) 59 | { 60 | int ret; 61 | 62 | *ifindex = if_nametoindex(argv[0]); 63 | if (!*ifindex) { 64 | vty_out(vty, "%% Error resolving interface %s (%m)%s" 65 | , argv[3] 66 | , VTY_NEWLINE); 67 | return CMD_WARNING; 68 | } 69 | 70 | ret = inet_ston(argv[1], ip_address); 71 | if (!ret) { 72 | vty_out(vty, "%% malformed IP address %s%s", argv[0], VTY_NEWLINE); 73 | return CMD_WARNING; 74 | } 75 | 76 | return 0; 77 | } 78 | 79 | DEFUN(arp_interface, 80 | arp_interface_cmd, 81 | "interface STRING ip-address A.B.C.D", 82 | "Set Global PDN nameserver\n" 83 | "IPv4 Address\n") 84 | { 85 | dra_arp_t *arp; 86 | uint32_t ip_address; 87 | int err, ifindex; 88 | 89 | if (argc < 2) { 90 | vty_out(vty, "%% missing arguments%s", VTY_NEWLINE); 91 | return CMD_WARNING; 92 | } 93 | 94 | err = arp_interface_parse(vty, argv, &ifindex, &ip_address); 95 | if (err) 96 | return CMD_WARNING; 97 | 98 | arp = dra_arp_init(ifindex, argv[0], ip_address); 99 | if (!arp) { 100 | vty_out(vty, "%% arp-reply already configured on %s for %u.%u.%u.%u%s" 101 | , argv[0], NIPQUAD(ip_address), VTY_NEWLINE); 102 | return CMD_WARNING; 103 | } 104 | 105 | dra_arp_start(arp); 106 | 107 | return CMD_SUCCESS; 108 | } 109 | 110 | DEFUN(no_arp_interface, 111 | no_arp_interface_cmd, 112 | "no interface STRING ip-address A.B.C.D", 113 | "Set Global PDN nameserver\n" 114 | "IPv4 Address\n") 115 | { 116 | uint32_t ip_address; 117 | int err, ifindex; 118 | 119 | if (argc < 2) { 120 | vty_out(vty, "%% missing arguments%s", VTY_NEWLINE); 121 | return CMD_WARNING; 122 | } 123 | 124 | err = arp_interface_parse(vty, argv, &ifindex, &ip_address); 125 | if (err) 126 | return CMD_WARNING; 127 | 128 | err = dra_arp_release(ifindex, ip_address); 129 | if (err) 130 | vty_out(vty, "%% no arp-reply configured on interface %s for %u.%u.%u.%u%s" 131 | , argv[0], NIPQUAD(ip_address), VTY_NEWLINE); 132 | return CMD_SUCCESS; 133 | } 134 | 135 | /* Configuration writer */ 136 | static int 137 | arp_config_write(vty_t *vty) 138 | { 139 | list_head_t *l = &daemon_data->arp_listeners; 140 | 141 | dra_arp_t *arp; 142 | 143 | if (list_empty(l)) 144 | return CMD_SUCCESS; 145 | 146 | vty_out(vty, "arp-reply%s", VTY_NEWLINE); 147 | list_for_each_entry(arp, l, next) { 148 | vty_out(vty, " interface %s ip-address %u.%u.%u.%u%s" 149 | , arp->ifname, NIPQUAD(arp->ip_address) 150 | , VTY_NEWLINE); 151 | } 152 | vty_out(vty, "!%s", VTY_NEWLINE); 153 | 154 | 155 | return CMD_SUCCESS; 156 | } 157 | 158 | 159 | /* 160 | * VTY init 161 | */ 162 | int 163 | dra_arp_vty_init(void) 164 | { 165 | 166 | /* Install PDN commands. */ 167 | install_node(&arp_node); 168 | install_element(CONFIG_NODE, &arp_reply_cmd); 169 | 170 | install_default(ARP_NODE); 171 | install_element(ARP_NODE, &arp_interface_cmd); 172 | install_element(ARP_NODE, &no_arp_interface_cmd); 173 | 174 | /* Install show commands */ 175 | // install_element(VIEW_NODE, &show_xdp_forwarding_cmd); 176 | 177 | 178 | return 0; 179 | } 180 | -------------------------------------------------------------------------------- /src/dra_data.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | /* system includes */ 23 | #include 24 | #include 25 | #include 26 | 27 | /* local includes */ 28 | #include "dra_guard.h" 29 | 30 | 31 | /* Extern data */ 32 | extern data_t *daemon_data; 33 | 34 | 35 | /* 36 | * Daemon Control Block helpers 37 | */ 38 | data_t * 39 | alloc_daemon_data(void) 40 | { 41 | data_t *new; 42 | 43 | PMALLOC(new); 44 | INIT_LIST_HEAD(&new->bpf_progs); 45 | INIT_LIST_HEAD(&new->arp_ip_nat_rules); 46 | INIT_LIST_HEAD(&new->ip_nat_rules); 47 | INIT_LIST_HEAD(&new->sctp_ip_nat_rules); 48 | INIT_LIST_HEAD(&new->arp_listeners); 49 | INIT_LIST_HEAD(&new->mip_hosts); 50 | INIT_LIST_HEAD(&new->sctp_proxys); 51 | INIT_LIST_HEAD(&new->plugins); 52 | dra_debug_init(&new->debug_target); 53 | 54 | return new; 55 | } 56 | 57 | void 58 | free_daemon_data(void) 59 | { 60 | dra_json_destroy(); 61 | dra_sctp_destroy(); 62 | dra_mip_destroy(); 63 | dra_arp_destroy(); 64 | dra_bpf_destroy(); 65 | dra_nat_destroy(); 66 | dra_plugin_destroy(); 67 | dra_debug_destroy(&daemon_data->debug_target); 68 | FREE(daemon_data); 69 | } 70 | 71 | -------------------------------------------------------------------------------- /src/dra_debug_vty.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | /* system includes */ 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | /* local includes */ 29 | #include "dra_guard.h" 30 | 31 | 32 | /* Extern data */ 33 | extern data_t *daemon_data; 34 | extern thread_master_t *master; 35 | 36 | static int debug_profile_config_write(vty_t *vty); 37 | cmd_node_t debug_profile_node = { 38 | .node = DEBUG_PROFILE_NODE, 39 | .parent_node = CONFIG_NODE, 40 | .prompt = "%s(debug)# ", 41 | .config_write = debug_profile_config_write, 42 | }; 43 | 44 | 45 | /* 46 | * Command 47 | */ 48 | DEFUN(debug_profile, 49 | debug_profile_cmd, 50 | "debug-profile", 51 | "Configure Debug options\n") 52 | { 53 | vty->node = DEBUG_PROFILE_NODE; 54 | return CMD_SUCCESS; 55 | } 56 | 57 | DEFUN(msisdn, 58 | msisdn_cmd, 59 | "msisdn INTEGER mip6-agent-info STRING", 60 | "MSISDN\n" 61 | "number\n" 62 | "MIP6 Agent Info to use\n" 63 | "string\n") 64 | { 65 | dra_debug_entry_t *e; 66 | dra_mip6_agent_info_t *mip; 67 | uint64_t msisdn; 68 | 69 | if (argc < 2) { 70 | vty_out(vty, "%% missing arguments%s", VTY_NEWLINE); 71 | return CMD_WARNING; 72 | } 73 | 74 | mip = dra_mip_get(argv[1]); 75 | if (!mip) { 76 | vty_out(vty, "%% unknown mip6-agent-info:'%s'%s", argv[1], VTY_NEWLINE); 77 | return CMD_WARNING; 78 | } 79 | 80 | msisdn = strtoul(argv[0], NULL, 10); 81 | 82 | e = dra_debug_entry_get(&daemon_data->debug_target, msisdn); 83 | if (!e) 84 | e = dra_debug_entry_alloc(&daemon_data->debug_target, msisdn); 85 | e->mip = mip; 86 | __set_bit(DRA_DEBUG_FL_VTY, &e->flags); 87 | dra_debug_entry_put(e); 88 | return CMD_SUCCESS; 89 | } 90 | 91 | DEFUN(no_msisdn, 92 | no_msisdn_cmd, 93 | "no msisdn INTEGER", 94 | "MSISDN\n" 95 | "number\n") 96 | { 97 | uint64_t msisdn; 98 | int err; 99 | 100 | if (argc < 1) { 101 | vty_out(vty, "%% missing arguments%s", VTY_NEWLINE); 102 | return CMD_WARNING; 103 | } 104 | 105 | msisdn = strtoul(argv[0], NULL, 10); 106 | err = dra_debug_entry_destroy(&daemon_data->debug_target, msisdn); 107 | if (err) { 108 | vty_out(vty, "%% unknown msisdn %ld%s", msisdn, VTY_NEWLINE); 109 | return CMD_WARNING; 110 | } 111 | 112 | return CMD_SUCCESS; 113 | } 114 | 115 | /* Configuration writer */ 116 | static int 117 | debug_profile_config_write(vty_t *vty) 118 | { 119 | vty_out(vty, "debug-profile%s", VTY_NEWLINE); 120 | dra_debug_vty(vty, &daemon_data->debug_target); 121 | vty_out(vty, "!%s", VTY_NEWLINE); 122 | 123 | return CMD_SUCCESS; 124 | } 125 | 126 | 127 | /* 128 | * VTY init 129 | */ 130 | int 131 | dra_debug_vty_init(void) 132 | { 133 | /* Install DEBUG commands. */ 134 | install_node(&debug_profile_node); 135 | install_element(CONFIG_NODE, &debug_profile_cmd); 136 | 137 | install_default(DEBUG_PROFILE_NODE); 138 | install_element(DEBUG_PROFILE_NODE, &msisdn_cmd); 139 | install_element(DEBUG_PROFILE_NODE, &no_msisdn_cmd); 140 | 141 | return 0; 142 | } 143 | -------------------------------------------------------------------------------- /src/dra_disk.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | /* system includes */ 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | /* local includes */ 38 | #include "dra_guard.h" 39 | 40 | 41 | /* Extern data */ 42 | extern data_t *daemon_data; 43 | 44 | 45 | /* 46 | * Disk I/O helpers 47 | */ 48 | static int 49 | dra_disk_mkpath(char *path) 50 | { 51 | struct stat sb; 52 | int last; 53 | char *p; 54 | p = path; 55 | 56 | if (p[0] == '/') ++p; 57 | for (last = 0; !last ; ++p) { 58 | if (p[0] == '\0') 59 | last = 1; 60 | else 61 | if (p[0] != '/') 62 | continue; 63 | 64 | *p = '\0'; 65 | if (!last && p[1] == '\0') 66 | last = 1; 67 | 68 | if (mkdir(path, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) < 0) { 69 | if (errno == EEXIST || errno == EISDIR) { 70 | if (stat (path, &sb) < 0) 71 | return -1; 72 | else 73 | if (!S_ISDIR(sb.st_mode)) 74 | return -1; 75 | } else 76 | return -1; 77 | } 78 | if (!last) *p = '/'; 79 | } 80 | return 0; 81 | } 82 | 83 | static int 84 | dra_disk_mkdir(char *path) 85 | { 86 | char *p; 87 | 88 | p = path + strlen(path) - 1; 89 | while (p-- != path) { 90 | if (*p == '/') 91 | break; 92 | } 93 | 94 | if (p != path) *p = '\0'; 95 | if (dra_disk_mkpath(path) < 0) { 96 | printf("%s(): Cant mkpath for file %s !!! (%m)\n" 97 | , __FUNCTION__, path); 98 | return -1; 99 | } 100 | if (p != path) *p = '/'; 101 | 102 | return 0; 103 | } 104 | 105 | 106 | /* 107 | * Write stuff 108 | */ 109 | int 110 | dra_disk_open_write(char *path) 111 | { 112 | int ret, fd = -1; 113 | 114 | fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0644); 115 | if (fd < 0) { 116 | /* Try to create path */ 117 | ret = dra_disk_mkdir(path); 118 | if (ret < 0) 119 | return -1; 120 | 121 | /* Ok target dir is created */ 122 | fd = open(path, O_CREAT | O_TRUNC | O_RDWR, 0644); 123 | if (fd < 0) 124 | return -1; 125 | } 126 | 127 | return fd; 128 | } 129 | 130 | int 131 | dra_disk_write(int fd, char *buffer, int size) 132 | { 133 | int offset = 0, ret = 0; 134 | 135 | if (!fd) 136 | return -1; 137 | 138 | retry: 139 | ret = write(fd, buffer + offset, size - offset); 140 | if (ret < 0) { 141 | printf("%s(): error writing to file (%m)", __FUNCTION__); 142 | return -1; 143 | } 144 | 145 | offset += ret; 146 | 147 | if (offset < size) 148 | goto retry; 149 | 150 | return 0; 151 | } 152 | 153 | 154 | /* 155 | * Read stuff 156 | */ 157 | int 158 | dra_disk_open_read(char *path) 159 | { 160 | int fd = -1; 161 | 162 | fd = open(path, O_RDONLY, 0644); 163 | if (fd < 0) 164 | return -1; 165 | 166 | return fd; 167 | } 168 | 169 | int 170 | dra_disk_read(int fd, char *buffer, int size) 171 | { 172 | int offset = 0, ret = 0; 173 | 174 | if (!fd) 175 | return -1; 176 | 177 | retry: 178 | ret = read(fd, buffer + offset, size - offset); 179 | if (ret < 0) 180 | return -1; 181 | 182 | if (ret == 0) 183 | return offset; 184 | 185 | offset += ret; 186 | 187 | if (offset < size) 188 | goto retry; 189 | 190 | return offset; 191 | } 192 | -------------------------------------------------------------------------------- /src/dra_htab.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | /* system includes */ 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | /* local includes */ 32 | #include "dra_guard.h" 33 | 34 | 35 | /* 36 | * Distributate lock handling 37 | */ 38 | static dlock_mutex_t * 39 | dlock_hash(dlock_mutex_t *__array, uint32_t w1, uint32_t w2) 40 | { 41 | return __array + (jhash_2words(w1, w2, 0) & DLOCK_HASHTAB_MASK); 42 | } 43 | 44 | int 45 | dlock_lock_id(dlock_mutex_t *__array, uint32_t w1, uint32_t w2) 46 | { 47 | dlock_mutex_t *m = dlock_hash(__array, w1, w2); 48 | pthread_mutex_lock(&m->mutex); 49 | __sync_add_and_fetch(&m->refcnt, 1); 50 | return 0; 51 | } 52 | 53 | int 54 | dlock_unlock_id(dlock_mutex_t *__array, uint32_t w1, uint32_t w2) 55 | { 56 | dlock_mutex_t *m = dlock_hash(__array, w1, w2); 57 | if (__sync_sub_and_fetch(&m->refcnt, 1) == 0) 58 | pthread_mutex_unlock(&m->mutex); 59 | return 0; 60 | } 61 | 62 | dlock_mutex_t * 63 | dlock_init(void) 64 | { 65 | dlock_mutex_t *new; 66 | new = (dlock_mutex_t *) MALLOC(DLOCK_HASHTAB_SIZE * sizeof(dlock_mutex_t)); 67 | return new; 68 | } 69 | 70 | int 71 | dlock_destroy(dlock_mutex_t *__array) 72 | { 73 | FREE(__array); 74 | return 0; 75 | } 76 | 77 | /* 78 | * HTAB handling 79 | */ 80 | void 81 | dra_htab_init(dra_htab_t *h, size_t size) 82 | { 83 | h->htab = (struct hlist_head *) MALLOC(sizeof(struct hlist_head) * size); 84 | h->dlock = dlock_init(); 85 | } 86 | 87 | void 88 | dra_htab_destroy(dra_htab_t *h) 89 | { 90 | FREE(h->htab); 91 | FREE(h->dlock); 92 | } 93 | -------------------------------------------------------------------------------- /src/dra_json_vty.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | /* system includes */ 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | /* local includes */ 29 | #include "dra_guard.h" 30 | 31 | 32 | /* Extern data */ 33 | extern data_t *daemon_data; 34 | extern thread_master_t *master; 35 | 36 | static int json_config_write(vty_t *vty); 37 | cmd_node_t json_node = { 38 | .node = JSON_NODE, 39 | .parent_node = CONFIG_NODE, 40 | .prompt = "%s(json)# ", 41 | .config_write = json_config_write, 42 | }; 43 | 44 | 45 | /* 46 | * Command 47 | */ 48 | DEFUN(json, 49 | json_cmd, 50 | "json", 51 | "Configure JSON channel\n") 52 | { 53 | vty->node = JSON_NODE; 54 | return CMD_SUCCESS; 55 | } 56 | 57 | DEFUN(json_listen, 58 | json_listen_cmd, 59 | // "listen (A.B.C.D|X:X:X:X) port <1024-65535>", 60 | "listen STRING port INTEGER", 61 | "DRA-Guard JSON request channel\n" 62 | "IPv4 Address\n" 63 | "IPv6 Address\n" 64 | "listening TCP Port\n" 65 | "Number\n") 66 | { 67 | dra_json_channel_t *srv = &daemon_data->json_channel; 68 | struct sockaddr_storage *addr = &srv->addr; 69 | int port = 0, err = 0; 70 | 71 | if (argc < 2) { 72 | vty_out(vty, "%% missing arguments%s", VTY_NEWLINE); 73 | return CMD_WARNING; 74 | } 75 | 76 | VTY_GET_INTEGER_RANGE("TCP Port", port, argv[1], 1024, 65535); 77 | 78 | err = inet_stosockaddr(argv[0], port, addr); 79 | if (err) { 80 | vty_out(vty, "%% malformed IP address %s%s", argv[0], VTY_NEWLINE); 81 | memset(addr, 0, sizeof(struct sockaddr_storage)); 82 | return CMD_WARNING; 83 | } 84 | 85 | srv->thread_cnt = DRA_JSON_THREAD_CNT_DEFAULT; 86 | dra_json_init(); 87 | dra_json_worker_start(); 88 | return CMD_SUCCESS; 89 | } 90 | 91 | DEFUN(json_store, 92 | json_store_cmd, 93 | "store STRING", 94 | "Save JSON entries\n" 95 | "PATH to file\n") 96 | { 97 | if (argc < 1) { 98 | vty_out(vty, "%% missing arguments%s", VTY_NEWLINE); 99 | return CMD_WARNING; 100 | } 101 | 102 | strlcpy(daemon_data->json_store, argv[0], DRA_STR_MAX_LEN); 103 | dra_debug_disk_read_entries(&daemon_data->debug_target, daemon_data->json_store); 104 | __set_bit(DRA_FL_JSON_STORE_BIT, &daemon_data->flags); 105 | return CMD_SUCCESS; 106 | } 107 | 108 | /* Configuration writer */ 109 | static int 110 | json_config_write(vty_t *vty) 111 | { 112 | dra_json_channel_t *srv = &daemon_data->json_channel; 113 | 114 | if (!__test_bit(DRA_JSON_FL_RUNNING, &srv->flags)) 115 | return CMD_SUCCESS; 116 | 117 | vty_out(vty, "json%s", VTY_NEWLINE); 118 | vty_out(vty, " listen %s port %d%s" 119 | , inet_sockaddrtos(&srv->addr) 120 | , ntohs(inet_sockaddrport(&srv->addr)) 121 | , VTY_NEWLINE); 122 | if (__test_bit(DRA_FL_JSON_STORE_BIT, &daemon_data->flags)) 123 | vty_out(vty, " store %s%s", daemon_data->json_store, VTY_NEWLINE); 124 | vty_out(vty, "!%s", VTY_NEWLINE); 125 | 126 | return CMD_SUCCESS; 127 | } 128 | 129 | 130 | /* 131 | * VTY init 132 | */ 133 | int 134 | dra_json_vty_init(void) 135 | { 136 | /* Install DEBUG commands. */ 137 | install_node(&json_node); 138 | install_element(CONFIG_NODE, &json_cmd); 139 | 140 | install_default(JSON_NODE); 141 | install_element(JSON_NODE, &json_listen_cmd); 142 | install_element(JSON_NODE, &json_store_cmd); 143 | 144 | return 0; 145 | } 146 | -------------------------------------------------------------------------------- /src/dra_layer4.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | /* system includes */ 23 | #include 24 | #include 25 | #include 26 | 27 | /* local includes */ 28 | #include "dra_guard.h" 29 | 30 | 31 | /* 32 | * Socket helpers 33 | */ 34 | enum connect_result 35 | socket_state(thread_ref_t thread, thread_func_t func) 36 | { 37 | dra_sctp_assoc_t *a = THREAD_ARG(thread); 38 | int fd = THREAD_FD(thread); 39 | int status; 40 | socklen_t addrlen; 41 | timeval_t timer_min; 42 | 43 | /* Handle connection timeout */ 44 | if (thread->type == THREAD_WRITE_TIMEOUT) 45 | return connect_timeout; 46 | 47 | /* Check file descriptor */ 48 | addrlen = sizeof(status); 49 | if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *) &status, &addrlen) < 0) 50 | return connect_error; 51 | 52 | /* If status = 0, SCTP connection to remote host is established. 53 | * Otherwise register checker thread to handle connection in progress, 54 | * and other error code until connection is established. 55 | * Recompute the write timeout (or pending connection). 56 | */ 57 | if (status == 0) 58 | return connect_success; 59 | 60 | if (status == EINPROGRESS) { 61 | timer_min = timer_sub_now(thread->sands); 62 | a->egress.w_thread = thread_add_write(thread->master, func, THREAD_ARG(thread), fd, 63 | -timer_long(timer_min), 0); 64 | return connect_in_progress; 65 | } 66 | 67 | if (status == ETIMEDOUT) 68 | return connect_timeout; 69 | 70 | /* Since the sctp_connectx() call succeeded, treat this as a 71 | * failure to establish a connection. */ 72 | return connect_fail; 73 | } 74 | 75 | bool 76 | socket_connection_state(int fd, enum connect_result status, thread_ref_t thread, 77 | thread_func_t func, unsigned long timeout) 78 | { 79 | dra_sctp_assoc_t *a = THREAD_ARG(thread); 80 | 81 | if (status == connect_success || 82 | status == connect_in_progress) { 83 | a->egress.w_thread = thread_add_write(thread->master, func, a, fd, timeout, 0); 84 | return false; 85 | } 86 | 87 | return true; 88 | } 89 | -------------------------------------------------------------------------------- /src/dra_mip.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | /* system includes */ 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | /* local includes */ 39 | #include "dra_guard.h" 40 | #include "dra_pcap.h" 41 | 42 | /* Local data */ 43 | pthread_mutex_t dra_mip_mutex = PTHREAD_MUTEX_INITIALIZER; 44 | 45 | /* Extern data */ 46 | extern data_t *daemon_data; 47 | 48 | 49 | /* 50 | * MIP Utilities 51 | */ 52 | dra_mip6_agent_info_t * 53 | dra_mip_get(const char *name) 54 | { 55 | list_head_t *l = &daemon_data->mip_hosts; 56 | dra_mip6_agent_info_t *mip; 57 | 58 | pthread_mutex_lock(&dra_mip_mutex); 59 | list_for_each_entry(mip, l, next) { 60 | if (!strncmp(name, mip->name, DRA_NAME_MAX_LEN)) { 61 | pthread_mutex_unlock(&dra_mip_mutex); 62 | return mip; 63 | } 64 | } 65 | pthread_mutex_unlock(&dra_mip_mutex); 66 | 67 | return NULL; 68 | } 69 | 70 | static int 71 | dra_mip_add(dra_mip6_agent_info_t *mip) 72 | { 73 | pthread_mutex_lock(&dra_mip_mutex); 74 | list_add_tail(&mip->next, &daemon_data->mip_hosts); 75 | pthread_mutex_unlock(&dra_mip_mutex); 76 | return 0; 77 | } 78 | 79 | static int 80 | __dra_mip_del(dra_mip6_agent_info_t *mip) 81 | { 82 | list_head_del(&mip->next); 83 | return 0; 84 | } 85 | 86 | 87 | /* 88 | * ARP Service init 89 | */ 90 | dra_mip6_agent_info_t * 91 | dra_mip_alloc(const char *name) 92 | { 93 | dra_mip6_agent_info_t *new; 94 | 95 | PMALLOC(new); 96 | INIT_LIST_HEAD(&new->next); 97 | strlcpy(new->name, name, MIP_NAME_MAX_LEN); 98 | 99 | dra_mip_add(new); 100 | return new; 101 | } 102 | 103 | static int 104 | __dra_mip_release(dra_mip6_agent_info_t *mip) 105 | { 106 | __dra_mip_del(mip); 107 | dra_pcap_destroy(mip->pcap); 108 | FREE(mip); 109 | return 0; 110 | } 111 | 112 | int 113 | dra_mip_release(const char *name) 114 | { 115 | dra_mip6_agent_info_t *mip; 116 | 117 | mip = dra_mip_get(name); 118 | if (!mip) 119 | return -1; 120 | 121 | pthread_mutex_lock(&dra_mip_mutex); 122 | __dra_mip_release(mip); 123 | pthread_mutex_unlock(&dra_mip_mutex); 124 | return 0; 125 | } 126 | 127 | int 128 | dra_mip_destroy(void) 129 | { 130 | dra_mip6_agent_info_t *mip, *_mip; 131 | 132 | pthread_mutex_lock(&dra_mip_mutex); 133 | list_for_each_entry_safe(mip, _mip, &daemon_data->mip_hosts, next) 134 | __dra_mip_release(mip); 135 | pthread_mutex_unlock(&dra_mip_mutex); 136 | 137 | return 0; 138 | } 139 | -------------------------------------------------------------------------------- /src/dra_pcap.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | /* system includes */ 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | /* local includes */ 33 | #include "dra_guard.h" 34 | #include "dra_pcap.h" 35 | 36 | 37 | /* Extern data */ 38 | extern data_t *daemon_data; 39 | 40 | 41 | static int 42 | dra_pcap_pkt_prepare(unsigned char *buffer, size_t len, int id) 43 | { 44 | uint32_t *encap_type = (uint32_t *) buffer; 45 | struct iphdr *iph = (struct iphdr *) (buffer + sizeof(uint32_t)); 46 | struct tcphdr *tcph = (struct tcphdr *) (buffer + sizeof(uint32_t) + sizeof(struct iphdr)); 47 | int offset = sizeof(uint32_t) + sizeof(struct iphdr) + sizeof(struct tcphdr); 48 | 49 | /* PCAP encap type*/ 50 | *encap_type = htonl(AF_INET); 51 | 52 | /* IP header */ 53 | iph->ihl = sizeof(struct iphdr) >> 2; 54 | iph->version = 4; 55 | iph->tos = 0; 56 | iph->tot_len = htons(len + sizeof(struct iphdr) + sizeof(struct tcphdr)); 57 | iph->id = 0; 58 | iph->frag_off = 0; 59 | iph->ttl = 255; 60 | iph->protocol = IPPROTO_TCP; 61 | iph->saddr = htonl(id); 62 | iph->daddr = htonl(id); 63 | iph->check = 0; 64 | iph->check = in_csum((uint16_t *) iph, sizeof(struct iphdr), 0); 65 | 66 | /* TCP header */ 67 | tcph->source = htons(DIAMETER_PORT); 68 | tcph->dest = htons(DIAMETER_PORT); 69 | tcph->doff = 5; 70 | tcph->window = htons(1 << 13); 71 | 72 | return offset; 73 | } 74 | 75 | void 76 | dra_pcap_pkt_write(dra_pcap_t *p, pkt_buffer_t *pkt, int id) 77 | { 78 | struct pcap_pkthdr hdr; 79 | int offset; 80 | 81 | if (!__test_bit(DRA_PCAP_FL_OPEN_BIT, &p->flags)) 82 | return; 83 | 84 | pthread_mutex_lock(&p->mutex); 85 | 86 | offset = dra_pcap_pkt_prepare(p->buffer, pkt_buffer_len(pkt), id); 87 | 88 | gettimeofday(&hdr.ts, NULL); 89 | hdr.len = hdr.caplen = pkt_buffer_len(pkt) + offset; 90 | 91 | memcpy(p->buffer + offset, pkt->head, pkt_buffer_len(pkt)); 92 | pcap_dump((u_char *)p->dumper, &hdr, p->buffer); 93 | pcap_dump_flush(p->dumper); 94 | 95 | pthread_mutex_unlock(&p->mutex); 96 | } 97 | 98 | pcap_dumper_t * 99 | dra_pcap_open(dra_pcap_t *p) 100 | { 101 | struct tm tmp; 102 | time_t now; 103 | char datetime_str[64]; 104 | 105 | now = time(NULL); 106 | memset(&tmp, 0, sizeof(struct tm)); 107 | tmp.tm_isdst = -1; 108 | localtime_r(&now, &tmp); 109 | strftime(datetime_str, 64, "%Y%m%d%H%M%S", &tmp); 110 | snprintf(p->path, DRA_PCAP_PATH, "%s-%s.pcapng", p->filename, datetime_str); 111 | 112 | p->pcap = pcap_open_dead(DLT_LOOP, 1 << 16); 113 | return pcap_dump_open(p->pcap, p->path); 114 | } 115 | 116 | dra_pcap_t * 117 | dra_pcap_alloc(const char *filename) 118 | { 119 | dra_pcap_t *p; 120 | 121 | PMALLOC(p); 122 | strlcpy(p->filename, filename, DRA_PCAP_FILESIZE); 123 | p->dumper = dra_pcap_open(p); 124 | if (!p->dumper) { 125 | log_message(LOG_INFO, "%s(): Unable to open pcap file:%s (%s)" 126 | , __FUNCTION__, filename, pcap_geterr(p->pcap)); 127 | FREE(p); 128 | return NULL; 129 | } 130 | 131 | pthread_mutex_init(&p->mutex, NULL); 132 | __set_bit(DRA_PCAP_FL_OPEN_BIT, &p->flags); 133 | return p; 134 | } 135 | 136 | void 137 | dra_pcap_destroy(dra_pcap_t *p) 138 | { 139 | if (!p) 140 | return; 141 | 142 | if (__test_bit(DRA_PCAP_FL_OPEN_BIT, &p->flags)) 143 | pcap_dump_close(p->dumper); 144 | FREE(p); 145 | } 146 | -------------------------------------------------------------------------------- /src/dra_plugin.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | /* system includes */ 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | /* local includes */ 39 | #include "dra_guard.h" 40 | 41 | /* Local data */ 42 | pthread_mutex_t dra_plugin_mutex = PTHREAD_MUTEX_INITIALIZER; 43 | 44 | /* Extern data */ 45 | extern data_t *daemon_data; 46 | 47 | 48 | /* 49 | * plugin Utilities 50 | */ 51 | dra_plugin_t * 52 | dra_plugin_get(const char *name) 53 | { 54 | list_head_t *l = &daemon_data->plugins; 55 | dra_plugin_t *plugin; 56 | 57 | pthread_mutex_lock(&dra_plugin_mutex); 58 | list_for_each_entry(plugin, l, next) { 59 | if (!strncmp(name, plugin->name, DRA_NAME_MAX_LEN)) { 60 | pthread_mutex_unlock(&dra_plugin_mutex); 61 | __sync_add_and_fetch(&plugin->refcnt, 1); 62 | return plugin; 63 | } 64 | } 65 | pthread_mutex_unlock(&dra_plugin_mutex); 66 | 67 | return NULL; 68 | } 69 | 70 | int 71 | dra_plugin_put(dra_plugin_t *plugin) 72 | { 73 | if (!plugin) 74 | return -1; 75 | 76 | __sync_sub_and_fetch(&plugin->refcnt, 1); 77 | return 0; 78 | } 79 | 80 | static int 81 | dra_plugin_add(dra_plugin_t *plugin) 82 | { 83 | pthread_mutex_lock(&dra_plugin_mutex); 84 | list_add_tail(&plugin->next, &daemon_data->plugins); 85 | pthread_mutex_unlock(&dra_plugin_mutex); 86 | return 0; 87 | } 88 | 89 | static int 90 | __dra_plugin_del(dra_plugin_t *plugin) 91 | { 92 | list_head_del(&plugin->next); 93 | return 0; 94 | } 95 | 96 | int 97 | dra_plugin_load(dra_plugin_t *plugin, const char *argv[], int argc) 98 | { 99 | plugin->hdl = dlopen(plugin->path, RTLD_LAZY); 100 | if (plugin->hdl == NULL) { 101 | log_message(LOG_INFO, "%s(): error loading '%s' (%s)" 102 | , __FUNCTION__, plugin->path, dlerror()); 103 | return -1; 104 | } 105 | 106 | plugin->init = dlsym(plugin->hdl, "init"); 107 | if (!dlerror()) { 108 | log_message(LOG_INFO, "%s(): plugin '%s' is supporting 'init()' callback" 109 | , __FUNCTION__, plugin->name); 110 | (*plugin->init) (argv, argc); 111 | } 112 | 113 | plugin->destroy = dlsym(plugin->hdl, "destroy"); 114 | if (!dlerror()) { 115 | log_message(LOG_INFO, "%s(): plugin '%s' is supporting 'destroy()' callback" 116 | , __FUNCTION__, plugin->name); 117 | } 118 | 119 | plugin->generic_pkt = dlsym(plugin->hdl, "generic_pkt"); 120 | if (!dlerror()) { 121 | log_message(LOG_INFO, "%s(): plugin '%s' is supporting 'generic_pkt()' callback" 122 | , __FUNCTION__, plugin->name); 123 | } 124 | 125 | plugin->ingress_pkt_read = dlsym(plugin->hdl, "ingress_pkt_read"); 126 | if (!dlerror()) { 127 | log_message(LOG_INFO, "%s(): plugin '%s' is supporting 'ingress_pkt_read()' callback" 128 | , __FUNCTION__, plugin->name); 129 | } 130 | 131 | plugin->egress_pkt_read = dlsym(plugin->hdl, "egress_pkt_read"); 132 | if (!dlerror()) { 133 | log_message(LOG_INFO, "%s(): plugin '%s' is supporting 'egress_pkt_read()' callback" 134 | , __FUNCTION__, plugin->name); 135 | } 136 | 137 | return 0; 138 | } 139 | 140 | static int 141 | dra_plugin_unload(dra_plugin_t *plugin) 142 | { 143 | int err; 144 | 145 | if (!plugin->hdl) 146 | return -1; 147 | 148 | if (plugin->destroy) 149 | (*plugin->destroy) (); 150 | 151 | err = dlclose(plugin->hdl); 152 | if (err) { 153 | log_message(LOG_INFO, "%s(): error unloading '%s' (%s)" 154 | , __FUNCTION__, plugin->name, dlerror()); 155 | return -1; 156 | } 157 | 158 | return 0; 159 | } 160 | 161 | 162 | /* 163 | * Plugin Service init 164 | */ 165 | int 166 | dra_plugin_argscpy(dra_plugin_t *plugin, const char *argv[], int argc) 167 | { 168 | int i; 169 | 170 | for (i = 2; i < argc; i++) { 171 | if (i > 2) 172 | strlcat(plugin->args, " ", DRA_PLUGIN_ARGS_MAX_LEN); 173 | strlcat(plugin->args, argv[i], DRA_PLUGIN_ARGS_MAX_LEN); 174 | } 175 | 176 | return 0; 177 | } 178 | 179 | dra_plugin_t * 180 | dra_plugin_alloc(const char *name) 181 | { 182 | dra_plugin_t *new; 183 | 184 | PMALLOC(new); 185 | INIT_LIST_HEAD(&new->next); 186 | strlcpy(new->name, name, DRA_NAME_MAX_LEN); 187 | 188 | dra_plugin_add(new); 189 | __sync_add_and_fetch(&new->refcnt, 1); 190 | return new; 191 | } 192 | 193 | static int 194 | __dra_plugin_release(dra_plugin_t *plugin) 195 | { 196 | __dra_plugin_del(plugin); 197 | dra_plugin_unload(plugin); 198 | FREE(plugin); 199 | return 0; 200 | } 201 | 202 | int 203 | dra_plugin_release(dra_plugin_t *plugin) 204 | { 205 | if (__sync_add_and_fetch(&plugin->refcnt, 0) != 0) 206 | return -1; 207 | 208 | pthread_mutex_lock(&dra_plugin_mutex); 209 | __dra_plugin_release(plugin); 210 | pthread_mutex_unlock(&dra_plugin_mutex); 211 | return 0; 212 | } 213 | 214 | int 215 | dra_plugin_destroy(void) 216 | { 217 | dra_plugin_t *plugin, *_plugin; 218 | 219 | pthread_mutex_lock(&dra_plugin_mutex); 220 | list_for_each_entry_safe(plugin, _plugin, &daemon_data->plugins, next) 221 | __dra_plugin_release(plugin); 222 | pthread_mutex_unlock(&dra_plugin_mutex); 223 | 224 | return 0; 225 | } 226 | -------------------------------------------------------------------------------- /src/dra_plugin_vty.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | /* system includes */ 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | /* local includes */ 29 | #include "dra_guard.h" 30 | 31 | 32 | /* Extern data */ 33 | extern data_t *daemon_data; 34 | extern thread_master_t *master; 35 | 36 | static int plugin_config_write(vty_t *vty); 37 | cmd_node_t plugin_node = { 38 | .node = PLUGIN_NODE, 39 | .parent_node = CONFIG_NODE, 40 | .prompt = "%s(plugin)# ", 41 | .config_write = plugin_config_write, 42 | }; 43 | 44 | 45 | /* 46 | * Command 47 | */ 48 | DEFUN(plugin, 49 | plugin_cmd, 50 | "plugin STRING path STRING ...", 51 | "Configure Plugin\n" 52 | "Plugin Name\n" 53 | "Path\n" 54 | "Path to plugin\n" 55 | "Arguments") 56 | { 57 | dra_plugin_t *plugin; 58 | int err; 59 | 60 | if (argc < 2) { 61 | vty_out(vty, "%% missing arguments%s", VTY_NEWLINE); 62 | return CMD_WARNING; 63 | } 64 | 65 | /* Already existing ? */ 66 | plugin = dra_plugin_get(argv[0]); 67 | if (plugin) { 68 | vty_out(vty, "%% Plugin '%s' already configured%s", argv[0], VTY_NEWLINE); 69 | dra_plugin_put(plugin); 70 | return CMD_WARNING; 71 | } 72 | plugin = dra_plugin_alloc(argv[0]); 73 | strlcpy(plugin->path, argv[1], DRA_PATH_MAX_LEN); 74 | dra_plugin_argscpy(plugin, argv, argc); 75 | 76 | err = dra_plugin_load(plugin, argv, argc); 77 | if (err) { 78 | vty_out(vty, "%% unable to load plugin '%s'%s", plugin->name, VTY_NEWLINE); 79 | dra_plugin_put(plugin); 80 | return CMD_WARNING; 81 | } 82 | 83 | vty_out(vty, "Success loading plugin '%s'%s", plugin->name, VTY_NEWLINE); 84 | dra_plugin_put(plugin); 85 | return CMD_SUCCESS; 86 | } 87 | 88 | DEFUN(no_plugin, 89 | no_plugin_cmd, 90 | "no plugin WORD", 91 | "unconfigure Plugin\n" 92 | "Plugin Name\n") 93 | { 94 | dra_plugin_t *plugin; 95 | int err; 96 | 97 | if (argc < 1) { 98 | vty_out(vty, "%% missing arguments%s", VTY_NEWLINE); 99 | return CMD_WARNING; 100 | } 101 | 102 | plugin = dra_plugin_get(argv[0]); 103 | if (!plugin) { 104 | vty_out(vty, "%% unknown plugin '%s'%s", argv[0], VTY_NEWLINE); 105 | return CMD_WARNING; 106 | } 107 | dra_plugin_put(plugin); 108 | 109 | err = dra_plugin_release(plugin); 110 | if (err) { 111 | vty_out(vty, "%% cant unload plugin '%s' (refcnt:%d)%s" 112 | , argv[0], plugin->refcnt, VTY_NEWLINE); 113 | return CMD_WARNING; 114 | } 115 | 116 | vty_out(vty, "Success unloading plugin '%s'%s", argv[0], VTY_NEWLINE); 117 | return CMD_SUCCESS; 118 | } 119 | 120 | /* Configuration writer */ 121 | static int 122 | plugin_config_write(vty_t *vty) 123 | { 124 | list_head_t *l = &daemon_data->plugins; 125 | dra_plugin_t *plugin; 126 | 127 | if (list_empty(l)) 128 | return CMD_SUCCESS; 129 | 130 | list_for_each_entry(plugin, l, next) { 131 | vty_out(vty, "plugin %s path %s %s%s" 132 | , plugin->name, plugin->path, plugin->args 133 | , VTY_NEWLINE); 134 | } 135 | vty_out(vty, "!%s", VTY_NEWLINE); 136 | 137 | return CMD_SUCCESS; 138 | } 139 | 140 | 141 | /* 142 | * VTY init 143 | */ 144 | int 145 | dra_plugin_vty_init(void) 146 | { 147 | /* Install MIP commands. */ 148 | install_node(&plugin_node); 149 | install_element(CONFIG_NODE, &plugin_cmd); 150 | install_element(CONFIG_NODE, &no_plugin_cmd); 151 | 152 | install_default(PLUGIN_NODE); 153 | 154 | return 0; 155 | } 156 | -------------------------------------------------------------------------------- /src/dra_sctp.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | /* system includes */ 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | /* local includes */ 40 | #include "dra_guard.h" 41 | 42 | /* Extern data */ 43 | extern data_t *daemon_data; 44 | 45 | /* 46 | * SCTP Proxy plugin related 47 | */ 48 | 49 | int 50 | dra_sctp_proxy_plugin_get(dra_sctp_plugin_t *p) 51 | { 52 | __sync_add_and_fetch(&p->refcnt, 1); 53 | return 0; 54 | } 55 | 56 | int 57 | dra_sctp_proxy_plugin_put(dra_sctp_plugin_t *p) 58 | { 59 | if (__sync_sub_and_fetch(&p->refcnt, 1) == 0 && 60 | __test_bit(SCTP_FL_PLUGIN_UNLOAD, &p->flags)) { 61 | dra_plugin_put(p->plugin); 62 | p->plugin = NULL; 63 | p->flags = 0; 64 | } 65 | 66 | return 0; 67 | } 68 | 69 | 70 | int 71 | dra_sctp_proxy_plugin_add(dra_sctp_proxy_t *p, dra_plugin_t *plugin) 72 | { 73 | int i; 74 | 75 | for (i = 0; i < DRA_SCTP_MAX_PLUGIN; i++) { 76 | if (p->plugin[i].plugin) 77 | continue; 78 | 79 | p->plugin[i].plugin = plugin; 80 | __sync_add_and_fetch(&p->plugin_cnt, 1); 81 | __set_bit(SCTP_FL_PLUGIN_LOADED, &p->flags); 82 | return 0; 83 | } 84 | 85 | return -1; 86 | } 87 | 88 | int 89 | dra_sctp_proxy_plugin_del(dra_sctp_proxy_t *p, const char *name) 90 | { 91 | int i; 92 | 93 | if (!__test_bit(SCTP_FL_PLUGIN_LOADED, &p->flags)) 94 | return -1; 95 | 96 | for (i = 0; i < DRA_SCTP_MAX_PLUGIN; i++) { 97 | if (!p->plugin[i].plugin) 98 | continue; 99 | 100 | if (!strncmp(p->plugin[i].plugin->name, name, DRA_NAME_MAX_LEN)) { 101 | if (__sync_sub_and_fetch(&p->plugin_cnt, 1) == 0) 102 | __clear_bit(SCTP_FL_PLUGIN_LOADED, &p->flags); 103 | 104 | __set_bit(SCTP_FL_PLUGIN_UNLOAD, &p->plugin[i].flags); 105 | if (__sync_add_and_fetch(&p->plugin[i].refcnt, 0) == 0) { 106 | dra_plugin_put(p->plugin[i].plugin); 107 | p->plugin[i].plugin = NULL; 108 | p->plugin[i].flags = 0; 109 | } 110 | return 0; 111 | } 112 | } 113 | 114 | return -1; 115 | } 116 | 117 | 118 | /* 119 | SCTP Proxy init 120 | */ 121 | static int 122 | dra_sctp_parse_addrs_list(char *addr_list, char *port, struct sockaddr **addrs) 123 | { 124 | struct addrinfo hints, *res; 125 | char *addr, *tmp; 126 | int addrs_cnt = 1; 127 | 128 | if (!addr_list || !port) 129 | return -1; 130 | 131 | for (tmp = (char *)addr_list; *tmp != '\0'; tmp++) { 132 | if (*tmp == ',') { 133 | addrs_cnt++; 134 | } 135 | } 136 | 137 | *addrs = (struct sockaddr *) MALLOC(sizeof(struct sockaddr_in) * addrs_cnt); 138 | 139 | memset(&hints, 0, sizeof(hints)); 140 | hints.ai_family = AF_INET; 141 | hints.ai_socktype = SOCK_STREAM; 142 | hints.ai_protocol = IPPROTO_SCTP; 143 | hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV; 144 | 145 | tmp = (char *)*addrs; 146 | for (addr = strtok((char *)addr_list, ","); addr != NULL; addr = strtok(NULL, ",")) { 147 | if (getaddrinfo(addr, port, &hints, &res) != 0) { 148 | FREE(*addrs); 149 | return -1; 150 | } 151 | 152 | memcpy(tmp, res->ai_addr, res->ai_addrlen); 153 | tmp += res->ai_addrlen; 154 | freeaddrinfo(res); 155 | } 156 | 157 | return addrs_cnt; 158 | } 159 | 160 | int 161 | dra_sctp_parse_addrs_list_port(char *addr_list, struct sockaddr **addrs) 162 | { 163 | char *port, *last_colon; 164 | 165 | if (!addr_list) 166 | return -1; 167 | 168 | last_colon = strrchr(addr_list, ':'); 169 | if (!last_colon) 170 | return -1; 171 | 172 | port = last_colon + 1; 173 | *last_colon = '\0'; 174 | return dra_sctp_parse_addrs_list(addr_list, port, addrs); 175 | } 176 | 177 | 178 | 179 | 180 | dra_sctp_proxy_t * 181 | dra_sctp_proxy_get(const char *name) 182 | { 183 | dra_sctp_proxy_t *p; 184 | size_t len = strlen(name); 185 | 186 | list_for_each_entry(p, &daemon_data->sctp_proxys, next) { 187 | if (!strncmp(p->name, name, len)) 188 | return p; 189 | } 190 | 191 | return NULL; 192 | } 193 | 194 | dra_sctp_proxy_t * 195 | dra_sctp_proxy_alloc(const char *name) 196 | { 197 | dra_sctp_proxy_t *new; 198 | 199 | PMALLOC(new); 200 | INIT_LIST_HEAD(&new->next); 201 | strlcpy(new->name, name, DRA_NAME_MAX_LEN); 202 | new->thread_cnt = SCTP_LISTENER_THREAD_CNT_DEFAULT; 203 | pthread_mutex_init(&new->workers_mutex, NULL); 204 | pthread_mutex_init(&new->assocs_mutex, NULL); 205 | list_add_tail(&new->next, &daemon_data->sctp_proxys); 206 | 207 | return new; 208 | } 209 | 210 | int 211 | dra_sctp_proxy_init(dra_sctp_proxy_t *l) 212 | { 213 | dra_sctp_proto_init(l); 214 | return 0; 215 | } 216 | 217 | int 218 | dra_sctp_proxy_destroy(dra_sctp_proxy_t *l) 219 | { 220 | dra_sctp_proto_destroy(l); 221 | list_head_del(&l->next); 222 | FREE(l); 223 | return 0; 224 | } 225 | 226 | static int 227 | dra_sctp_proxys_destroy(void) 228 | { 229 | dra_sctp_proxy_t *p, *_p; 230 | 231 | list_for_each_entry_safe(p, _p, &daemon_data->sctp_proxys, next) 232 | dra_sctp_proxy_destroy(p); 233 | 234 | return 0; 235 | } 236 | 237 | 238 | /* 239 | * SCTP related 240 | */ 241 | int 242 | dra_sctp_destroy(void) 243 | { 244 | dra_sctp_proxys_destroy(); 245 | return 0; 246 | } 247 | -------------------------------------------------------------------------------- /src/dra_vty.c: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | /* system includes */ 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | /* local includes */ 29 | #include "dra_guard.h" 30 | 31 | 32 | /* 33 | * VTY init 34 | */ 35 | int 36 | dra_vty_init(void) 37 | { 38 | dra_bpf_vty_init(); 39 | dra_arp_vty_init(); 40 | dra_mip_vty_init(); 41 | dra_debug_vty_init(); 42 | dra_sctp_vty_init(); 43 | dra_json_vty_init(); 44 | dra_plugin_vty_init(); 45 | 46 | return 0; 47 | } 48 | -------------------------------------------------------------------------------- /src/include/dra_arp.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _DRA_ARP_H 23 | #define _DRA_ARP_H 24 | 25 | /* defines */ 26 | #define ARP_BUFSIZE (1 << 10) 27 | 28 | /* flags */ 29 | enum arp_flags { 30 | ARP_FL_STOPPING_BIT, 31 | ARP_FL_RUNNING_BIT, 32 | 33 | }; 34 | 35 | /* ARP related */ 36 | typedef struct _arphdr_eth { 37 | __be16 ar_hrd; /* format of hardware address */ 38 | __be16 ar_pro; /* format of protocol address */ 39 | unsigned char ar_hln; /* length of hardware address */ 40 | unsigned char ar_pln; /* length of protocol address */ 41 | __be16 ar_op; /* ARP opcode (command) */ 42 | 43 | /* Ethernet specific */ 44 | unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */ 45 | uint32_t ar_sip; /* sender IP address */ 46 | unsigned char ar_tha[ETH_ALEN]; /* target hardware address */ 47 | uint32_t ar_tip; /* target IP address */ 48 | } __attribute__((packed)) arphdr_eth_t; 49 | 50 | typedef struct _dra_arp_t { 51 | char ifname[IFNAMSIZ]; 52 | int ifindex; 53 | unsigned char hwaddr[ETH_ALEN]; 54 | char buffer[ARP_BUFSIZE]; 55 | uint32_t ip_address; 56 | pthread_t task; 57 | 58 | list_head_t next; 59 | 60 | unsigned long flags; 61 | } dra_arp_t; 62 | 63 | /* Prototypes */ 64 | extern int dra_arp_start(dra_arp_t *); 65 | extern dra_arp_t *dra_arp_init(int, const char *, uint32_t); 66 | extern int dra_arp_release(int, uint32_t); 67 | extern int dra_arp_destroy(void); 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /src/include/dra_arp_vty.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _DRA_ARP_VTY_H 23 | #define _DRA_ARP_VTY_H 24 | 25 | /* Prototypes */ 26 | extern int dra_arp_vty_init(void); 27 | 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/include/dra_bpf.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _DRA_BPF_H 23 | #define _DRA_BPF_H 24 | 25 | /* defines */ 26 | #define DRA_XDP_STRERR_BUFSIZE (1 << 7) 27 | #define XDP_PATH_MAX (1 << 7) 28 | 29 | enum dra_bpf_prog_type { 30 | BPF_PROG_QDISC = 0, 31 | BPF_PROG_XDP, 32 | }; 33 | 34 | /* MAP Entries*/ 35 | enum { 36 | DRA_BPF_MAP_ARP_IP_NAT = 0, 37 | DRA_BPF_MAP_IP_NAT, 38 | DRA_BPF_MAP_SCTP_IP_NAT, 39 | DRA_BPF_MAP_CNT 40 | }; 41 | 42 | struct ip_nat_rule { 43 | __u8 type; 44 | __u32 addr; 45 | __u32 netmask; 46 | }__attribute__ ((__aligned__(8))); 47 | #define DRA_IP_NAT_SRC_DST 0 48 | #define DRA_IP_NAT_SRC 1 49 | #define DRA_IP_NAT_DST 2 50 | 51 | /* BPF related */ 52 | typedef struct _dra_bpf_maps { 53 | struct bpf_map *map; 54 | } dra_bpf_maps_t; 55 | 56 | typedef struct _dra_bpf_opts { 57 | char label[DRA_STR_MAX_LEN]; 58 | int type; 59 | char filename[DRA_STR_MAX_LEN]; 60 | char progname[DRA_STR_MAX_LEN]; 61 | int ifindex; 62 | char pin_root_path[DRA_STR_MAX_LEN]; 63 | struct bpf_object *bpf_obj; 64 | struct bpf_link *bpf_lnk; 65 | dra_bpf_maps_t *bpf_maps; 66 | vty_t *vty; 67 | 68 | void (*bpf_unload) (struct _dra_bpf_opts *); 69 | 70 | list_head_t next; 71 | } dra_bpf_opts_t; 72 | 73 | 74 | /* Prototypes */ 75 | extern int dra_bpf_map_load(dra_bpf_opts_t *); 76 | extern struct bpf_map *dra_bpf_load_map(struct bpf_object *, const char *); 77 | extern dra_bpf_opts_t *dra_bpf_opts_alloc(int, void (*bpf_unload) (dra_bpf_opts_t *)); 78 | extern int dra_bpf_opts_add(dra_bpf_opts_t *, list_head_t *); 79 | extern int dra_bpf_opts_del(dra_bpf_opts_t *); 80 | extern dra_bpf_opts_t *dra_bpf_opts_exist(list_head_t *, int, const char **); 81 | extern dra_bpf_opts_t *dra_bpf_opts_get_by_label(list_head_t *, const char *); 82 | extern void dra_bpf_opts_destroy(list_head_t *); 83 | extern int dra_bpf_opts_load(dra_bpf_opts_t *, vty_t *, int, const char **, 84 | int (*bpf_load) (dra_bpf_opts_t *)); 85 | extern int dra_xdp_load(dra_bpf_opts_t *); 86 | extern void dra_xdp_unload(dra_bpf_opts_t *); 87 | extern int dra_qdisc_clsact_load(dra_bpf_opts_t *); 88 | extern void dra_qdisc_clast_unload(dra_bpf_opts_t *); 89 | extern int dra_bpf_init(void); 90 | extern int dra_bpf_destroy(void); 91 | 92 | #endif 93 | -------------------------------------------------------------------------------- /src/include/dra_bpf_nat.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _DRA_BPF_NAT_H 23 | #define _DRA_BPF_NAT_H 24 | 25 | /* defines */ 26 | 27 | 28 | /* NAT related */ 29 | typedef struct _dra_nat_rule { 30 | uint8_t type; 31 | uint32_t key; 32 | uint32_t addr; 33 | uint32_t netmask; 34 | 35 | dra_bpf_opts_t *opts; 36 | 37 | list_head_t next; 38 | } dra_nat_rule_t; 39 | 40 | /* Prototypes */ 41 | extern int dra_bpf_arp_ip_nat_insert(vty_t *, int, const char **); 42 | extern int dra_bpf_ip_nat_insert(vty_t *, int, int, const char **); 43 | extern int dra_bpf_sctp_ip_nat_insert(vty_t *, int, const char **); 44 | extern int dra_nat_destroy(void); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /src/include/dra_bpf_vty.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _DRA_BPF_VTY_H 23 | #define _DRA_BPF_VTY_H 24 | 25 | /* Prototypes */ 26 | extern int dra_bpf_vty_init(void); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/include/dra_data.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _DRA_DATA_H 23 | #define _DRA_DATA_H 24 | 25 | /* Default values */ 26 | #define DRA_STR_MAX_LEN 128 27 | #define DRA_PATH_MAX_LEN 128 28 | #define DRA_NAME_MAX_LEN 64 29 | 30 | /* Flags */ 31 | enum daemon_flags { 32 | DRA_FL_STOP_BIT, 33 | DRA_FL_JSON_STORE_BIT, 34 | }; 35 | 36 | /* Main control block */ 37 | typedef struct _data { 38 | list_head_t bpf_progs; 39 | list_head_t arp_ip_nat_rules; 40 | list_head_t ip_nat_rules; 41 | list_head_t sctp_ip_nat_rules; 42 | list_head_t arp_listeners; 43 | list_head_t mip_hosts; 44 | list_head_t sctp_proxys; 45 | list_head_t plugins; 46 | dra_htab_t debug_target; 47 | dra_json_channel_t json_channel; 48 | char json_store[DRA_STR_MAX_LEN]; 49 | 50 | unsigned long flags; 51 | } data_t; 52 | 53 | /* Prototypes */ 54 | extern data_t *alloc_daemon_data(void); 55 | extern void free_daemon_data(void); 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /src/include/dra_debug.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _DRA_DEBUG_H 23 | #define _DRA_DEBUG_H 24 | 25 | /* Hash table */ 26 | #define DEBUG_HASHTAB_BITS 15 27 | #define DEBUG_HASHTAB_SIZE (1 << DEBUG_HASHTAB_BITS) 28 | #define DEBUG_HASHTAB_MASK (DEBUG_HASHTAB_SIZE - 1) 29 | 30 | 31 | /* Debug flags */ 32 | enum debug_flags { 33 | DRA_DEBUG_FL_MSISDN, 34 | DRA_DEBUG_FL_HASHED, 35 | DRA_DEBUG_FL_VTY, 36 | DRA_DEBUG_FL_JSON, 37 | }; 38 | 39 | typedef struct _dra_debug_entry { 40 | uint64_t msisdn; 41 | dra_mip6_agent_info_t *mip; 42 | 43 | /* hash */ 44 | struct hlist_node hlist; 45 | 46 | unsigned long flags; 47 | int refcnt; 48 | } dra_debug_entry_t; 49 | 50 | 51 | /* Prototypes */ 52 | extern dra_debug_entry_t *dra_debug_entry_get(dra_htab_t *, uint64_t); 53 | extern int dra_debug_entry_put(dra_debug_entry_t *); 54 | extern dra_debug_entry_t *dra_debug_entry_alloc(dra_htab_t *, uint64_t); 55 | extern int dra_debug_entry_destroy(dra_htab_t *, uint64_t); 56 | extern int dra_debug_vty(vty_t *, dra_htab_t *); 57 | extern int dra_debug_json(json_writer_t *, dra_htab_t *); 58 | extern int dra_debug_disk_read_entries(dra_htab_t *, char *); 59 | extern int dra_debug_disk_write_entries(dra_htab_t *, char *); 60 | extern int dra_debug_init(dra_htab_t *); 61 | extern int dra_debug_destroy(dra_htab_t *); 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /src/include/dra_debug_vty.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _DRA_DEBUG_VTY_H 23 | #define _DRA_DEBUG_VTY_H 24 | 25 | /* Prototypes */ 26 | extern int dra_debug_vty_init(void); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/include/dra_diameter.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _DRA_DIAMETER_H 23 | #define _DRA_DIAMETER_H 24 | 25 | /* Defines */ 26 | #define DIAMETER_AVP_BUFSIZE (1 << 10) 27 | 28 | /* Diameter protocol headers */ 29 | #define DIAMETER_PORT 3868 30 | #define DIAMETER_PROTO_VERSION 0x01 31 | #define DIAMETER_MAX_AVP_PARSED 64 32 | #define DIAMETER_MAX_APN_PARSED 32 33 | #define PAD4(_x) ((_x) + ( (4 - (_x)) & 3 )) 34 | #define DIAMETER_VSPEC_GET_FL(X) ((X) | 0xff000000) 35 | #define DIAMETER_GET_ULONG(X) (ntohl((X)) & 0x00ffffff) 36 | #define DIAMETER_VSPEC_FL 0xc0000000 37 | #define VENDOR_3GPP 10415UL 38 | 39 | /* Command-Code */ 40 | #define CC_3GPP_CMD_UL 316UL 41 | 42 | /* AVP Flags */ 43 | #define AVP_FL_VENDOR 0x80 44 | #define AVP_FL_MANDATORY 0x40 45 | 46 | /* AVP-Code */ 47 | #define AC_3GPP_ORIGIN_HOST 264UL 48 | #define AC_3GPP_ORIGIN_REALM 296UL 49 | #define AC_3GPP_MSISDN 701UL 50 | #define AC_3GPP_ULA_FL 1406UL 51 | #define AC_3GPP_SUBS_DATA 1400UL 52 | #define AC_3GPP_APN_CONF_PROFILE 1429UL 53 | #define AC_3GPP_APN_CONF 1430UL 54 | #define AC_3GPP_MIP6_AGENT_INFO 486UL 55 | #define AC_3GPP_MIP_HOME_AGENT_HOST 348UL 56 | #define AC_3GPP_DESTINATION_HOST 293UL 57 | #define AC_3GPP_DESTINATION_REALM 283UL 58 | #define AC_3GPP_PDN_GW_ALLOC_TYPE 1438UL 59 | #define AC_3GPP_SERVICE_SELECTION 493UL 60 | #define AC_3GPP_SPECIFIC_APN_INFO 1472UL 61 | #define AC_3GPP_CONTEXT_IDENTIFIER 1423UL 62 | 63 | typedef struct _msg_hdr { 64 | uint32_t msg_length; /* (READONLY)(3 bytes) indicates the length of the message */ 65 | uint32_t msg_code; /* (3 bytes) the command-code. */ 66 | uint32_t msg_appl; /* The application issuing this message */ 67 | uint32_t msg_hbhid; /* The Hop-by-Hop identifier of the message */ 68 | uint32_t msg_eteid; /* The End-to-End identifier of the message */ 69 | } msg_hdr_t; 70 | 71 | typedef struct _avp_hdr { 72 | uint32_t avp_code; /* the AVP Code */ 73 | uint32_t avp_len; /* (READONLY)(Only 3 bytes are used) */ 74 | } avp_hdr_t; 75 | 76 | typedef struct _avp_vendor { 77 | uint32_t avp_vendor; /* Only used if AVP_FLAG_VENDOR is present */ 78 | } avp_vendor_t; 79 | 80 | typedef struct _avp_node { 81 | avp_hdr_t *avph; 82 | uint8_t *data; /* pointer to the value of the AVP. */ 83 | } avp_node_t; 84 | 85 | typedef struct _msg_root { 86 | msg_hdr_t *msgh; 87 | avp_node_t *avp; 88 | } msg_root_t; 89 | 90 | typedef struct _avp_ctx { 91 | msg_root_t *root; 92 | avp_node_t *avp_w0; 93 | avp_node_t *avp_w1; 94 | avp_node_t *avp_w2; 95 | uint8_t avp_mai[DIAMETER_AVP_BUFSIZE]; /* MIP6-Agent-Info */ 96 | int avp_mai_len; 97 | } avp_ctx_t; 98 | 99 | 100 | /* Prototypes */ 101 | extern uint8_t *avp_get(uint32_t, uint8_t *, uint8_t *); 102 | extern avp_node_t *avp_parse(avp_node_t *, uint32_t, uint8_t *, uint8_t *); 103 | extern void avp_len_update_delta(avp_hdr_t *, int, uint8_t); 104 | extern void msg_len_update_delta(msg_hdr_t *, int, uint8_t); 105 | extern msg_root_t *msg_parse_apn_conf_profil_path(avp_ctx_t *, pkt_buffer_t *); 106 | extern int avp_mip6_agent_info_update(avp_ctx_t *, avp_node_t *, uint8_t *, int, pkt_buffer_t *); 107 | extern int avp_build_mip6_agent_info(dra_mip6_agent_info_t *); 108 | extern int avp_build_mip6_agent_info_dynamic(avp_ctx_t *, dra_mip6_agent_info_t *, pkt_buffer_t *); 109 | extern avp_ctx_t *avp_ctx_alloc(void); 110 | extern void avp_ctx_destroy(avp_ctx_t *); 111 | 112 | #endif 113 | -------------------------------------------------------------------------------- /src/include/dra_disk.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _DRA_DISK_H 23 | #define _DRA_DISK_H 24 | 25 | /* Prototypes */ 26 | extern int dra_disk_open_write(char *); 27 | extern int dra_disk_write(int, char *, int); 28 | extern int dra_disk_open_read(char *); 29 | extern int dra_disk_read(int, char *, int); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /src/include/dra_guard.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _DRA_GUARD_H 23 | #define _DRA_GUARD_H 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #include "daemon.h" 30 | #include "memory.h" 31 | #include "bitops.h" 32 | #include "utils.h" 33 | #include "pidfile.h" 34 | #include "signals.h" 35 | #include "timer.h" 36 | #include "timer_thread.h" 37 | #include "scheduler.h" 38 | #include "mpool.h" 39 | #include "vector.h" 40 | #include "command.h" 41 | #include "rbtree.h" 42 | #include "vty.h" 43 | #include "logger.h" 44 | #include "list_head.h" 45 | #include "json_reader.h" 46 | #include "json_writer.h" 47 | #include "pkt_buffer.h" 48 | #include "jhash.h" 49 | #include "dra_if.h" 50 | #include "dra_disk.h" 51 | #include "dra_layer4.h" 52 | #include "dra_htab.h" 53 | #include "dra_json.h" 54 | #include "dra_json_vty.h" 55 | #include "dra_data.h" 56 | #include "dra_vty.h" 57 | #include "dra_bpf.h" 58 | #include "dra_bpf_nat.h" 59 | #include "dra_bpf_vty.h" 60 | #include "dra_arp.h" 61 | #include "dra_arp_vty.h" 62 | #include "dra_mip.h" 63 | #include "dra_mip_vty.h" 64 | #include "dra_debug.h" 65 | #include "dra_debug_vty.h" 66 | #include "dra_diameter.h" 67 | #include "dra_route_optim.h" 68 | #include "dra_plugin.h" 69 | #include "dra_plugin_vty.h" 70 | #include "dra_sctp.h" 71 | #include "dra_sctp_proto.h" 72 | #include "dra_sctp_vty.h" 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /src/include/dra_htab.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _DRA_HTAB_H 23 | #define _DRA_HTAB_H 24 | 25 | /* Distributed lock */ 26 | #define DLOCK_HASHTAB_BITS 10 27 | #define DLOCK_HASHTAB_SIZE (1 << DLOCK_HASHTAB_BITS) 28 | #define DLOCK_HASHTAB_MASK (DLOCK_HASHTAB_SIZE - 1) 29 | 30 | typedef struct _dlock_mutex { 31 | pthread_mutex_t mutex; 32 | uint32_t refcnt; 33 | } dlock_mutex_t; 34 | 35 | /* htab */ 36 | typedef struct _dra_htab { 37 | struct hlist_head *htab; 38 | dlock_mutex_t *dlock; 39 | } dra_htab_t; 40 | 41 | /* Prototypes */ 42 | extern int dlock_lock_id(dlock_mutex_t *, uint32_t, uint32_t); 43 | extern int dlock_unlock_id(dlock_mutex_t *, uint32_t, uint32_t); 44 | extern dlock_mutex_t *dlock_init(void); 45 | extern int dlock_destroy(dlock_mutex_t *); 46 | extern void dra_htab_init(dra_htab_t *, size_t); 47 | extern void dra_htab_destroy(dra_htab_t *); 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /src/include/dra_if.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _DRA_IF_H 23 | #define _DRA_IF_H 24 | 25 | /* Defines */ 26 | #define IF_DEFAULT_CONNECTION_KEEPIDLE 20 27 | #define IF_DEFAULT_CONNECTION_KEEPCNT 2 28 | #define IF_DEFAULT_CONNECTION_KEEPINTVL 10 29 | 30 | /* Prototypes */ 31 | extern int if_setsockopt_reuseaddr(int, int); 32 | extern int if_setsockopt_nolinger(int, int); 33 | extern int if_setsockopt_tcpcork(int, int); 34 | extern int if_setsockopt_nodelay(int, int); 35 | extern int if_setsockopt_keepalive(int, int); 36 | extern int if_setsockopt_tcp_keepidle(int, int); 37 | extern int if_setsockopt_tcp_keepcnt(int, int); 38 | extern int if_setsockopt_tcp_keepintvl(int, int); 39 | extern int if_setsockopt_rcvtimeo(int, int); 40 | extern int if_setsockopt_sndtimeo(int, int); 41 | extern int if_setsockopt_reuseport(int, int); 42 | extern int if_setsockopt_hdrincl(int); 43 | extern int if_setsockopt_broadcast(int); 44 | extern int if_setsockopt_promisc(int, int, bool); 45 | extern int if_setsockopt_attach_bpf(int, int); 46 | extern int if_setsockopt_no_receive(int *); 47 | extern int if_setsockopt_rcvbuf(int *, int); 48 | extern int if_setsockopt_bindtodevice(int *, const char *); 49 | extern int if_setsockopt_priority(int *, int); 50 | extern int if_nametohwaddr(const char *, unsigned char *, size_t); 51 | extern int if_setsockopt_sctp_initmsg(int, struct sctp_initmsg *); 52 | extern int if_setsockopt_sctp_events(int, struct sctp_event_subscribe *); 53 | extern int if_setsockopt_sctp_nodelay(int, int); 54 | extern int if_getsockopt_sctp_status(int, struct sctp_status *); 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /src/include/dra_json.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _DRA_JSON_H 23 | #define _DRA_JSON_H 24 | 25 | /* Default values */ 26 | #define DRA_JSON_THREAD_CNT_DEFAULT 5 27 | #define DRA_JSON_BUFFER_SIZE 4096 28 | 29 | /* Channel definition */ 30 | #define DRA_JSON_TCP_TIMEOUT (1 * TIMER_HZ) 31 | #define DRA_JSON_TCP_LISTENER_TIMER (1 * TIMER_HZ) 32 | #define DRA_JSON_TCP_TIMER (1 * TIMER_HZ) 33 | 34 | /* Defines */ 35 | #define DRA_JSON_TIMER (3 * TIMER_HZ) 36 | 37 | /* session flags */ 38 | enum session_flags { 39 | DRA_JSON_FL_RUNNING, 40 | }; 41 | 42 | /* Resquest channel */ 43 | typedef struct _dra_json_worker { 44 | int id; 45 | pthread_t task; 46 | int fd; 47 | struct _dra_json_channel *channel; /* backpointer */ 48 | 49 | /* I/O MUX related */ 50 | thread_master_t *master; 51 | thread_ref_t r_thread; 52 | 53 | list_head_t next; 54 | 55 | unsigned long flags; 56 | } dra_json_worker_t; 57 | 58 | typedef struct _dra_json_channel { 59 | struct sockaddr_storage addr; 60 | int thread_cnt; 61 | 62 | pthread_mutex_t workers_mutex; 63 | list_head_t workers; 64 | 65 | unsigned long flags; 66 | } dra_json_channel_t; 67 | 68 | typedef struct _dra_json_session { 69 | pthread_t task; 70 | pthread_attr_t task_attr; 71 | struct sockaddr_storage addr; 72 | int fd; 73 | FILE *fp; 74 | uint32_t id; 75 | 76 | dra_json_worker_t *worker; 77 | 78 | json_writer_t *jwriter; 79 | 80 | off_t offset_read; 81 | off_t offset_sent; 82 | char buffer_in[DRA_JSON_BUFFER_SIZE]; 83 | 84 | unsigned long flags; 85 | } dra_json_session_t; 86 | 87 | 88 | /* Prototypes */ 89 | extern int dra_json_worker_start(void); 90 | extern int dra_json_init(void); 91 | extern int dra_json_destroy(void); 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /src/include/dra_json_vty.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _DRA_JSON_VTY_H 23 | #define _DRA_JSON_VTY_H 24 | 25 | /* Prototypes */ 26 | extern int dra_json_vty_init(void); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/include/dra_layer4.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _DRA_LAYER4_H 23 | #define _DRA_LAYER4_H 24 | 25 | /* Connection States */ 26 | enum connect_result { 27 | connect_error, 28 | connect_in_progress, 29 | connect_timeout, 30 | connect_fail, 31 | connect_success, 32 | connect_result_next 33 | }; 34 | 35 | /* Prototypes */ 36 | extern enum connect_result socket_state(thread_ref_t, thread_func_t); 37 | extern bool socket_connection_state(int, enum connect_result, thread_ref_t, thread_func_t, unsigned long); 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /src/include/dra_mip.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _DRA_MIP_H 23 | #define _DRA_MIP_H 24 | 25 | /* Defines */ 26 | #define MIP_DST_BUFSIZE (1 << 8) 27 | #define MIP_AVP_BUFSIZE (1 << 10) 28 | #define MIP_NAME_MAX_LEN 16 29 | 30 | /* flags */ 31 | enum mip_flags { 32 | MIP_FL_STATIC_HOST_BIT, 33 | MIP_FL_STATIC_REALM_BIT, 34 | MIP_FL_DYNAMIC_REALM_ORIGIN_BIT, 35 | MIP_FL_WILDCARD_APN_XFRM_BIT, 36 | MIP_FL_WRITE_PCAP_BIT, 37 | }; 38 | 39 | /* MIP related */ 40 | typedef struct _dra_mip6_agent_info { 41 | char name[MIP_NAME_MAX_LEN]; 42 | char destination_host[MIP_DST_BUFSIZE]; 43 | char destination_realm[MIP_DST_BUFSIZE]; 44 | uint8_t agent[MIP_AVP_BUFSIZE]; 45 | int agent_len; 46 | void *pcap; 47 | 48 | list_head_t next; 49 | 50 | unsigned long flags; 51 | } dra_mip6_agent_info_t; 52 | 53 | /* Prototypes */ 54 | extern dra_mip6_agent_info_t *dra_mip_get(const char *); 55 | extern dra_mip6_agent_info_t *dra_mip_alloc(const char *); 56 | extern int dra_mip_release(const char *); 57 | extern int dra_mip_destroy(void); 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /src/include/dra_mip_vty.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _DRA_MIP_VTY_H 23 | #define _DRA_MIP_VTY_H 24 | 25 | /* Prototypes */ 26 | extern int dra_mip_vty_init(void); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/include/dra_pcap.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _DRA_PCAP_H 23 | #define _DRA_PCAP_H 24 | 25 | /* Defines */ 26 | #define DRA_PCAP_BUFSIZE (1 << 13) 27 | #define DRA_PCAP_FILESIZE 256 28 | #define DRA_PCAP_PATH 512 29 | 30 | /* flags */ 31 | enum dra_pcap_flags { 32 | DRA_PCAP_FL_OPEN_BIT, 33 | }; 34 | 35 | /* MIP related */ 36 | typedef struct _dra_pcap { 37 | char filename[DRA_PCAP_FILESIZE]; 38 | char path[DRA_PCAP_PATH]; 39 | unsigned char buffer[DRA_PCAP_BUFSIZE]; 40 | pcap_t *pcap; 41 | pcap_dumper_t *dumper; 42 | pthread_mutex_t mutex; 43 | 44 | unsigned long flags; 45 | } dra_pcap_t; 46 | 47 | /* Prototypes */ 48 | extern void dra_pcap_pkt_write(dra_pcap_t *, pkt_buffer_t *, int); 49 | extern dra_pcap_t *dra_pcap_alloc(const char *); 50 | extern void dra_pcap_destroy(dra_pcap_t *); 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /src/include/dra_plugin.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _DRA_PLUGIN_H 23 | #define _DRA_PLUGIN_H 24 | 25 | /* Plugin Actions */ 26 | #define DRA_PLUGIN_ACT_PASS 0 27 | #define DRA_PLUGIN_ACT_DROP 1 28 | 29 | /* Plugin Hooks */ 30 | #define DRA_PLUGIN_INGRESS_READ_HOOK 0 31 | #define DRA_PLUGIN_EGRESS_READ_HOOK 1 32 | 33 | #define DRA_PLUGIN_NAME_MAX_LEN 64 34 | #define DRA_PLUGIN_PATH_MAX_LEN 128 35 | #define DRA_PLUGIN_ARGS_MAX_LEN 512 36 | 37 | /* MIP related */ 38 | typedef struct _dra_plugin { 39 | char name[DRA_PLUGIN_NAME_MAX_LEN]; 40 | char path[DRA_PLUGIN_PATH_MAX_LEN]; 41 | char args[DRA_PLUGIN_ARGS_MAX_LEN]; 42 | void *hdl; 43 | /* callback functions */ 44 | int (*generic_pkt) (pkt_buffer_t *); 45 | int (*ingress_pkt_read) (pkt_buffer_t *); 46 | int (*egress_pkt_read) (pkt_buffer_t *); 47 | int (*init) (const char **, int); 48 | int (*destroy) (void); 49 | 50 | int refcnt; 51 | list_head_t next; 52 | } dra_plugin_t; 53 | 54 | /* inline stuff */ 55 | static inline void __dra_plugin_ref(dra_plugin_t *p) 56 | { 57 | __sync_add_and_fetch(&p->refcnt, 1); 58 | } 59 | 60 | static inline void __dra_plugin_unref(dra_plugin_t *p) 61 | { 62 | __sync_sub_and_fetch(&p->refcnt, 1); 63 | } 64 | 65 | 66 | /* Prototypes */ 67 | extern dra_plugin_t *dra_plugin_get(const char *); 68 | extern int dra_plugin_put(dra_plugin_t *); 69 | extern int dra_plugin_load(dra_plugin_t *, const char **, int); 70 | extern int dra_plugin_argscpy(dra_plugin_t *plugin, const char *argv[], int argc); 71 | extern dra_plugin_t *dra_plugin_alloc(const char *); 72 | extern int dra_plugin_release(dra_plugin_t *); 73 | extern int dra_plugin_destroy(void); 74 | 75 | #endif 76 | -------------------------------------------------------------------------------- /src/include/dra_plugin_vty.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _DRA_PLUGIN_VTY_H 23 | #define _DRA_PLUGIN_VTY_H 24 | 25 | /* Prototypes */ 26 | extern int dra_plugin_vty_init(void); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/include/dra_route_optim.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _DRA_ROUTE_OPTIM_H 23 | #define _DRA_ROUTE_OPTIM_H 24 | 25 | /* Prototypes */ 26 | extern int dra_route_optimization(pkt_buffer_t *, void *, dra_mip6_agent_info_t *); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/include/dra_sctp.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _DRA_SCTP_H 23 | #define _DRA_SCTP_H 24 | 25 | /* Default values */ 26 | #define SCTP_LISTENER_THREAD_CNT_DEFAULT 5 27 | #define SCTP_PKT_BUFFER_SIZE (1 << 13) 28 | 29 | /* SCTP Channel definition */ 30 | #define DRA_SCTP_TIMEOUT (1 * TIMER_HZ) 31 | #define DRA_SCTP_LISTENER_TIMER (1 * TIMER_HZ) 32 | #define DRA_SCTP_TIMER (1 * TIMER_HZ) 33 | #define DRA_SCTP_MAX_PLUGIN 10 34 | 35 | /* SCTP session flags */ 36 | enum assoc_flags { 37 | SCTP_FL_CONNECTED = 0, 38 | SCTP_FL_INGRESS, 39 | SCTP_FL_EGRESS, 40 | SCTP_FL_STOP, 41 | SCTP_FL_RUNNING, 42 | SCTP_FL_COMPLETE, 43 | SCTP_FL_DISCARD, 44 | SCTP_FL_LOCAL_NAT, 45 | SCTP_FL_REWRITE_ULA, 46 | SCTP_FL_MATCH_TARGET_REWRITE_ULA, 47 | SCTP_FL_PLUGIN_LOADED, 48 | SCTP_FL_PLUGIN_UNLOAD, 49 | }; 50 | 51 | /* SCTP channel */ 52 | typedef struct _dra_sctp_worker { 53 | int id; 54 | pthread_t task; 55 | int fd; 56 | struct _dra_sctp_proxy *proxy; /* backpointer */ 57 | 58 | /* I/O MUX related */ 59 | thread_master_t *master; 60 | thread_ref_t r_thread; 61 | 62 | /* Diameter related */ 63 | avp_ctx_t *avp_ctx; 64 | 65 | list_head_t next; 66 | 67 | unsigned long flags; 68 | } dra_sctp_worker_t; 69 | 70 | typedef struct _dra_sctp_plugin { 71 | dra_plugin_t *plugin; 72 | int refcnt; 73 | 74 | unsigned long flags; 75 | } dra_sctp_plugin_t; 76 | 77 | typedef struct _dra_sctp_proxy { 78 | char name[DRA_NAME_MAX_LEN]; 79 | 80 | /* Server conf */ 81 | struct sockaddr *addrs; 82 | char addrs_str[DRA_STR_MAX_LEN]; 83 | int addrs_cnt; 84 | struct sctp_initmsg server_initmsg; 85 | int thread_cnt; 86 | 87 | /* Client conf */ 88 | struct sockaddr *connect_addrs; 89 | char connect_addrs_str[DRA_STR_MAX_LEN]; 90 | int connect_addrs_cnt; 91 | struct sctp_initmsg client_initmsg; 92 | uint32_t local_nat_netmask; 93 | uint32_t local_nat_ip_match; 94 | uint32_t local_nat_ip; 95 | 96 | pthread_mutex_t workers_mutex; 97 | list_head_t workers; 98 | 99 | pthread_mutex_t assocs_mutex; 100 | list_head_t assocs; 101 | 102 | dra_sctp_plugin_t plugin[DRA_SCTP_MAX_PLUGIN]; 103 | int plugin_cnt; 104 | 105 | list_head_t next; 106 | 107 | unsigned long flags; 108 | } dra_sctp_proxy_t; 109 | 110 | typedef struct _dra_sctp_peer { 111 | int fd; 112 | pkt_buffer_t *pkt; 113 | struct sctp_initmsg initmsg; 114 | struct sctp_sndrcvinfo sinfo; 115 | 116 | /* I/O MUX related */ 117 | thread_ref_t w_thread; 118 | thread_ref_t r_thread; 119 | 120 | unsigned long flags; 121 | } dra_sctp_peer_t; 122 | 123 | typedef struct _dra_sctp_assoc { 124 | struct sockaddr *addrs; 125 | char addrs_str[DRA_STR_MAX_LEN]; 126 | int addrs_cnt; 127 | dra_sctp_peer_t ingress; 128 | dra_sctp_peer_t egress; 129 | 130 | dra_sctp_worker_t *worker; /* backpointer */ 131 | 132 | list_head_t next; 133 | 134 | unsigned long flags; 135 | } dra_sctp_assoc_t; 136 | 137 | 138 | /* Prototypes */ 139 | extern int dra_sctp_proxy_plugin_get(dra_sctp_plugin_t *); 140 | extern int dra_sctp_proxy_plugin_put(dra_sctp_plugin_t *); 141 | extern int dra_sctp_proxy_plugin_add(dra_sctp_proxy_t *, dra_plugin_t *); 142 | extern int dra_sctp_proxy_plugin_del(dra_sctp_proxy_t *, const char *); 143 | extern int sctp_assoc_str(struct sockaddr *, int, char *, size_t); 144 | extern int dra_sctp_parse_addrs_list_port(char *, struct sockaddr **); 145 | extern dra_sctp_proxy_t *dra_sctp_proxy_get(const char *); 146 | extern dra_sctp_proxy_t *dra_sctp_proxy_alloc(const char *name); 147 | extern int dra_sctp_listener_destroy(dra_sctp_proxy_t *); 148 | extern int dra_sctp_destroy(void); 149 | 150 | 151 | #endif 152 | -------------------------------------------------------------------------------- /src/include/dra_sctp_proto.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _DRA_SCTP_PROTO_H 23 | #define _DRA_SCTP_PROTO_H 24 | 25 | 26 | /* Prototypes */ 27 | extern int dra_sctp_worker_start(dra_sctp_proxy_t *); 28 | extern int dra_sctp_proto_init(dra_sctp_proxy_t *); 29 | extern int dra_sctp_proto_destroy(dra_sctp_proxy_t *); 30 | 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /src/include/dra_sctp_vty.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _DRA_SCTP_VTY_H 23 | #define _DRA_SCTP_VTY_H 24 | 25 | /* Prototypes */ 26 | extern int dra_sctp_vty_init(void); 27 | 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/include/dra_vty.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _DRA_VTY_H 23 | #define _DRA_VTY_H 24 | 25 | /* STR(MACRO) stringifies MACRO */ 26 | #define _STR(x) #x 27 | #define STR(x) _STR(x) 28 | 29 | /* Prototypes */ 30 | extern int dra_vty_init(void); 31 | 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /src/include/main.h: -------------------------------------------------------------------------------- 1 | /* SPDX-License-Identifier: AGPL-3.0-or-later */ 2 | /* 3 | * Soft: The main goal of dra-guard is to provide robust and secure 4 | * extensions to DRA feature (Diameter Routing Agent). DRA are 5 | * used in mobile networks to route Diameter traffic between 6 | * mobile network equipments, like at Roaming interconnections. 7 | * DRA-Guard implements a set of features to manipulate and 8 | * analyze Diameter payloads via a Plugin framework and a 9 | * built-in Route-Optimization feature. 10 | * 11 | * Authors: Alexandre Cassen, 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU Affero General Public 15 | * License Version 3.0 as published by the Free Software Foundation; 16 | * either version 3.0 of the License, or (at your option) any later 17 | * version. 18 | * 19 | * Copyright (C) 2024 Alexandre Cassen, 20 | */ 21 | 22 | #ifndef _MAIN_H 23 | #define _MAIN_H 24 | 25 | /* global var */ 26 | thread_master_t *master = NULL; /* Scheduling master thread */ 27 | char *conf_file = NULL; /* Configuration file */ 28 | int log_facility = LOG_DAEMON; /* Optional logging facilities */ 29 | data_t *daemon_data = NULL; /* Daemon Control Block data */ 30 | char *default_conf_file = "/etc/dra-guard/dra-guard.conf"; /* Default configuration file */ 31 | 32 | #endif 33 | --------------------------------------------------------------------------------