List of commits:
Subject Hash Author Date (UTC)
SYNChronous SendMail c787c5cf5e37144221649c70af44413366f82cf8 Sylvain BERTRAND 2019-09-08 21:12:58
Commit c787c5cf5e37144221649c70af44413366f82cf8 - SYNChronous SendMail
Author: Sylvain BERTRAND
Author date (UTC): 2019-09-08 21:12
Committer name: Sylvain BERTRAND
Committer date (UTC): 2019-09-08 21:12
Parent(s):
Signer:
Signing key:
Signing status: N
Tree: 25fcd8db76a117e787ac2e05db9b194b4e5afdbe
File Lines added Lines deleted
ABBREVIATIONS 39 0
README 80 0
RULES_GLOBAL_NAMESPACE 24 0
RULES_POINTER 5 0
TODO 3 0
all.S 7 0
all.c 23 0
config.default.h 52 0
dns.h 15 0
dns/dns.txt 31 0
dns/ipv4.c 227 0
dns/ipv4.h 13 0
dns/ipv6.c 225 0
dns/ipv6.h 13 0
dns/name.c 377 0
dns/name.h 17 0
dns/namespace/ipv4.c 24 0
dns/namespace/ipv4.h 12 0
dns/namespace/ipv6.c 24 0
dns/namespace/ipv6.h 12 0
dns/namespace/name.c 15 0
dns/namespace/name.h 18 0
dns/namespace/query.h 10 0
dns/namespace/resolv_conf.c 14 0
dns/namespace/resolv_conf.h 12 0
dns/namespace/resolver.c 58 0
dns/namespace/resolver.h 20 0
dns/namespace/response.c 32 0
dns/namespace/response.h 22 0
dns/namespace/state.h 78 0
dns/query.c 83 0
dns/query.h 12 0
dns/resolv_conf.c 205 0
dns/resolv_conf.h 13 0
dns/resolver.c 547 0
dns/resolver.h 19 0
dns/response.c 576 0
dns/response.h 18 0
dns/rfc.h 81 0
dns/state.h 93 0
make_gcc_aarch64 32 0
make_gcc_x86_64 32 0
namespace/dns.h 12 0
namespace/smtp.h 12 0
namespace/syncsm.c 60 0
namespace/syncsm.h 26 0
namespace/ulinux.h 181 0
perr.h 15 0
smtp.h 15 0
smtp/namespace/smtp.c 89 0
smtp/rfc.h 22 0
smtp/smtp.c 770 0
syncsm.c 555 0
syncsm.h 78 0
ulinux.h 33 0
ulinux/README 6 0
ulinux/TODO 4 0
ulinux/archs/aarch64/epoll.h 8 0
ulinux/archs/aarch64/mmap.h 11 0
ulinux/archs/aarch64/signal/signal.h 46 0
ulinux/archs/aarch64/start.S 13 0
ulinux/archs/aarch64/stat.h 29 0
ulinux/archs/aarch64/sysc.S 3 0
ulinux/archs/aarch64/sysc.h 534 0
ulinux/archs/aarch64/types.h 8 0
ulinux/archs/aarch64/utils/endian.S 3 0
ulinux/archs/aarch64/utils/endian.h 35 0
ulinux/archs/x86_64/epoll.h 11 0
ulinux/archs/x86_64/mmap.h 10 0
ulinux/archs/x86_64/signal/handler.c 28 0
ulinux/archs/x86_64/signal/handler.h 10 0
ulinux/archs/x86_64/signal/siginfo.h 68 0
ulinux/archs/x86_64/signal/signal.h 46 0
ulinux/archs/x86_64/start.S 20 0
ulinux/archs/x86_64/stat.h 27 0
ulinux/archs/x86_64/sysc.S 3 0
ulinux/archs/x86_64/sysc.h 466 0
ulinux/archs/x86_64/types.h 8 0
ulinux/archs/x86_64/utils/endian.S 3 0
ulinux/archs/x86_64/utils/endian.h 47 0
ulinux/binfmts.h 9 0
ulinux/compiler_misc.h 26 0
ulinux/compiler_types.h 20 0
ulinux/dirent.h 14 0
ulinux/elf.h 203 0
ulinux/epoll.h 39 0
ulinux/error.h 148 0
ulinux/fcntl.h 30 0
ulinux/file.h 28 0
ulinux/fs.h 47 0
ulinux/input/evdev.h 803 0
ulinux/ioctl.h 101 0
ulinux/mmap.h 63 0
ulinux/patterns/README 1 0
ulinux/patterns/clock_nanosleep/clock_nanosleep.c 113 0
ulinux/patterns/clock_nanosleep/make 38 0
ulinux/patterns/conf_ini/conf_ini.c 363 0
ulinux/patterns/conf_ini/makefile 38 0
ulinux/patterns/conf_ini/test.conf 6 0
ulinux/patterns/dir_parse/dir_parse.c 169 0
ulinux/patterns/dir_parse/make 37 0
ulinux/patterns/epoll_signalfd/epoll_signalfd.c 150 0
ulinux/patterns/epoll_signalfd/make 37 0
ulinux/patterns/epoll_timerfd/epoll_timerfd.c 167 0
ulinux/patterns/epoll_timerfd/make 37 0
ulinux/patterns/futex/futex.c 92 0
ulinux/patterns/futex/make 38 0
ulinux/patterns/glob/glob.c 441 0
ulinux/patterns/glob/makefile 33 0
ulinux/patterns/input/evdev.c 445 0
ulinux/patterns/input/makefile 29 0
ulinux/patterns/input/ulinux_namespace.h 96 0
ulinux/patterns/insmod/insmod.c 86 0
ulinux/patterns/insmod/makefile 30 0
ulinux/patterns/network_server/pre-fork_socket_unix_tcp/makefile 53 0
ulinux/patterns/network_server/pre-fork_socket_unix_tcp/pre-fork_socket_unix_tcp.c 869 0
ulinux/patterns/network_server/pre-fork_socket_unix_tcp/ulinux_namespace.h 87 0
ulinux/patterns/network_server/pre-fork_socket_unix_tcp/x86_64_only 1 0
ulinux/patterns/so/makefile 41 0
ulinux/patterns/so/so.c 34 0
ulinux/patterns/so/so.h 11 0
ulinux/patterns/so/use_so.c 26 0
ulinux/patterns/start/make 40 0
ulinux/patterns/start/start.c 341 0
ulinux/patterns/thread/make 38 0
ulinux/patterns/thread/thread.c 92 0
ulinux/patterns/uevents_monitor/makefile 31 0
ulinux/patterns/uevents_monitor/uevents_monitor.c 205 0
ulinux/patterns/uevents_monitor/x86_64_only 1 0
ulinux/patterns/vdso/make 40 0
ulinux/patterns/vdso/vdso.c 322 0
ulinux/sched.h 58 0
ulinux/select.h 9 0
ulinux/signal/handler.h 14 0
ulinux/signal/siginfo.h 8 0
ulinux/signal/signal.h 134 0
ulinux/socket/in.h 22 0
ulinux/socket/in6.h 15 0
ulinux/socket/msg.h 115 0
ulinux/socket/netlink.h 94 0
ulinux/socket/socket.h 184 0
ulinux/socket/tcp.h 8 0
ulinux/socket/un.h 13 0
ulinux/start.S 6 0
ulinux/start.h 9 0
ulinux/stat.h 182 0
ulinux/sysc.h 8 0
ulinux/time.h 56 0
ulinux/types.h 30 0
ulinux/types_posix.h 12 0
ulinux/utils/ascii/ascii.h 142 0
ulinux/utils/ascii/block/conv/binary/binary.c 58 0
ulinux/utils/ascii/block/conv/binary/binary.h 20 0
ulinux/utils/ascii/block/conv/decimal/decimal.c 154 0
ulinux/utils/ascii/block/conv/decimal/decimal.h 26 0
ulinux/utils/ascii/block/conv/hexadecimal/hexadecimal.c 62 0
ulinux/utils/ascii/block/conv/hexadecimal/hexadecimal.h 21 0
ulinux/utils/ascii/block/conv/net/net.c 258 0
ulinux/utils/ascii/block/conv/net/net.h 22 0
ulinux/utils/ascii/match/match.c 1020 0
ulinux/utils/ascii/match/match.h 31 0
ulinux/utils/ascii/string/conv/decimal/decimal.c 173 0
ulinux/utils/ascii/string/conv/decimal/decimal.h 22 0
ulinux/utils/ascii/string/string.h 152 0
ulinux/utils/ascii/string/vsprintf.c 1388 0
ulinux/utils/ascii/string/vsprintf.h 24 0
ulinux/utils/atomic.h 22 0
ulinux/utils/div.h 14 0
ulinux/utils/endian.h 8 0
ulinux/utils/ipv6.h 40 0
ulinux/utils/maths.h 47 0
ulinux/utils/mem.c 77 0
ulinux/utils/mem.h 19 0
ulinux/utils/qsort.c 184 0
ulinux/utils/qsort.h 34 0
ulinux/utsname.h 17 0
ulinux/vim/after/syntax/c.vim 31 0
ulinux/wait.h 25 0
File ABBREVIATIONS added (mode: 100644) (index 0000000..cfee40c)
1 al : Address Literal
2 an : ANswer resource records section (dns)
3 ar : Additional Resource records section (dns)
4 arg(s) : ARGument(S)
5 buf : BUFfer
6 c : Char/Cursor
7 cmd : CoMmand
8 cmp : CoMPare
9 cpy : CoPY
10 cur : CURsor
11 desc : DESCription
12 dest : DESTination
13 dgram : DataGRAM (udp)
14 dn : Domain Name
15 dns : Domain Name System
16 e : End (usually a byte _paste_ the last byte)
17 eq : EQual
18 func(s) : FUNCtion(S)
19 idx : InDeX
20 l : Last (the last byte)
21 lvl : LeVeL (usually related to the log)
22 msg(s) : MeSage(S)
23 n : couNt
24 ns(s) : Name Server(S)
25 ptr(s) : PoinTeR(S)
26 qtion(s) : QuesTION(S)
27 rcpt(s) : ReCiPienT(S)
28 resp(s) : RESPonse(S)
29 rr(s) : Resource Record(S) (dns)
30 s : start
31 smtp : Simple Mail Transport Protocol
32 so : SOcket
33 str : string
34 sysc : SYStem Call
35 sz : SiZe
36 _t : "shared" Type suffix
37 _v : "shared" Variable suffix
38 var(s) : VARiable(S)
39 vma : Virual Address Area
File README added (mode: 100644) (index 0000000..1058e91)
1 Primary target audience:
2 - system developers
3 - advanced system administrators
4 - very advanced users
5
6 Target scale: personal program, one account.
7
8 This program is not meant to send emails to "queueing" smtp servers which
9 expect user authentication. This program does act as a "real" smtp server
10 sending emails to "real" smtp servers.
11
12 This is, yet another, _naive_ SYNChronous SendMail, for linux. Features are:
13 - No libc: direct linux "syscalls" for x86_64 and aarch64/arm64 hardware
14 architectures. ulinux, the ultra thin user level linux abstraction layer,
15 should support not too hard addition of new hardware architectures.
16 - No brain damaged build system (GNU autotools, meson, cmake, etc).
17 - Include a minimal dns resolver (expecting recursion support from the DNS
18 servers) with a resolver.conf file parser.
19 - IPv4 and IPv6 (only IPv4 was properly tested though).
20 - SMTP transparency handling (<CRLF>.<CRLF> to <CRLF>..<CRLF> without "sed").
21 If you want to handle it yourself, you can disable it in config.h.
22 - "One Compilation Unit". Actually 1 C src file and 1 assembly src file.
23
24 How to build:
25 Copy "config.default.h" wherever suits your build system/scripts and
26 rename it to "config.h". Customize it with what you must/want.
27 Use/copy&customize the make_* included scripts.
28 In theory, you could compile with:
29 "cc -I$config_h_dir -c all.c -o all_c.o"-ish
30 You could assemble with:
31 "cpp -DASSEMBLER -I$config_h_dir all.S | as -o all_S.o -"-ish
32 You could link with:
33 "ld -o syncsm all_c.o all_S.o"-ish
34
35 See the specifics for each hardware architecture in the provided make_*
36 scripts. At the time of writing, only aarch64/arm64 requires to be
37 provided the linux used hardware page size, because this value is
38 dependent on chosen options from linux compilation: we don't want to
39 dynamically discover this value using the linux auxv process vector.
40
41 It is based on a gcc/binutils toolchain, but the ground work to allow
42 adding new toolchains without insane kludge should be around (namely not
43 too hard-ish dependency on C inline assembly).
44
45 To deal with the log, egrep and "egrep -v" are your friends. The log
46 level-ish/severit-ish of a line is at its start.
47
48 'nothing/nobody is perfect'
49
50 --------------------------------------------------------------------------------
51
52 This project uses "One Compilation Unit":
53 It's possible to use the C preprocessor to perform local (part of a
54 compilation unit) namespace transformations. But those latests are
55 applied to _all_ identifiers: type names, struct member names, function
56 names, variable names, enum member names, then have limitations. The
57 main limitation is identifier collision. The idea is to work around them
58 locally (the preprocessor will warn you about collisions). Another
59 limitation is, since tranformations are using the C preprocessor,
60 special handling of macros. See GLOBAL_NAMESPACE_RULES.
61
62 This system has enough expressive power to grow projects to very large,
63 then is kind of overkill here since it's a rather poor project from a
64 namespace point of view. It is another method than the classic
65 compilation unit based partitioning of namespace.
66
67 All that to say: this code organization allows to grow "One Compilation
68 Unit" projects to very large and keep namespace in check for writting
69 code.
70
71 Resorting to "beyond sanity" complex computer languages in order to let
72 them perform global namespage management is a blunt mistake. In other
73 words, it is way more _un_reasonable than this very method.
74
75 Of course, a natural border of this model is the one between C files and
76 assembly files (and no, inline assembly is not a good answer, for many
77 reasons).
78
79 This code should support easy ipv4 support removal refurbishment and
80 simplification for a clean ipv6 only implementation.
File RULES_GLOBAL_NAMESPACE added (mode: 100644) (index 0000000..eb0eb02)
1 There are some rules to ease the management of namespaces. It's a _TRADEOFF_
2 since it's not delegated to any crazy a** computer language.
3 Comfort _always_ comes at a cost, more or less hidden.
4 Have a look at the README file.
5
6 HARD RULE: IN 1 NAMESPACE ALL IDENTIFIERS SHOULD BE UNIQUE. IDENTIFIERS ARE:
7 - TYPE NAMES
8 - VARIABLE NAMES
9 - STRUCT MEMBER NAMES
10 - FUNCTION NAMES
11 - ENUM MEMBER NAMES (AKA REAL COMPILER CONSTANTS)
12
13 Then we introduce just enough noise to help reach uniqueness with an acceptable
14 burden:
15 - _shared_ struct types with a _t suffix.
16 - _shared_ variables with a _v suffix.
17 _shared_ as non specific/private to _only one_ code section.
18
19 It helps to avoid identifier collisions while keeping struct member identifiers,
20 function names, and enum names/compiler constant names "as is".
21 In other words, we did partition the space of _shared_ identifiers names.
22
23 (all this "on top" of the base "ulinux namespace" and others which are global
24 anyway)
File RULES_POINTER added (mode: 100644) (index 0000000..47e8cbf)
1 s : "Start", usually for a pointer on the first byte
2 l : "Last", usually for a pointer on the last valid byte
3 e : "End", usually for a pointer on the byte past the last valid byte
4
5 ONLY "PRE-MEMORY ACCESS" BOUND CHECKING PLZ.
File TODO added (mode: 100644) (index 0000000..a7eef9c)
1 * test ipv6. only ipv4 IAPs were available during development, aka sh*tty IAPs,
2 and no, I did not setup an ipv6 lan.
3 * enum --> constant ?
File all.S added (mode: 100644) (index 0000000..e08b007)
1 /*
2 * this code is protected by the GNU affero GPLv3 license
3 * author:Sylvain BERTRAND
4 */
5 #include "ulinux/start.S"
6 #include "ulinux/arch/sysc.S"
7 #include "ulinux/arch/utils/endian.S"
File all.c added (mode: 100644) (index 0000000..bbf54cb)
1 /*
2 * this code is protected by the GNU affero GPLv3 license
3 * author:Sylvain BERTRAND
4 */
5 #include "config.h"
6 /*----------------------------------------------------------------------------*/
7 #include "ulinux/utils/qsort.c"
8 #include "ulinux/utils/mem.c"
9 #include "ulinux/utils/ascii/block/conv/net/net.c"
10 #include "ulinux/utils/ascii/block/conv/hexadecimal/hexadecimal.c"
11 #include "ulinux/utils/ascii/string/vsprintf.c"
12 /*----------------------------------------------------------------------------*/
13 #include "syncsm.c"
14 /*----------------------------------------------------------------------------*/
15 #include "dns/resolver.c"
16 #include "dns/ipv4.c"
17 #include "dns/ipv6.c"
18 #include "dns/query.c"
19 #include "dns/response.c"
20 #include "dns/name.c"
21 #include "dns/resolv_conf.c"
22 /*----------------------------------------------------------------------------*/
23 #include "smtp/smtp.c"
File config.default.h added (mode: 100644) (index 0000000..33c4864)
1 #ifndef CONFIG_H
2 #define CONFIG_H
3 /*
4 * this code is protected by the GNU affero GPLv3 license
5 * author:Sylvain BERTRAND
6 */
7 /*
8 * The originating email address:
9 * CONFIG_SMTP_MAIL_FROM@CONFIG_SMT_EHLO_DN_AL
10 */
11 /* #define CONFIG_SMTP_MAIL_FROM "sylvain.bertrand"
12 #define CONFIG_SMTP_EHLO_DN_AL "[x.x.x.x]"
13 #define CONFIG_SMTP_EHLO_DN_AL "[IPV6:....]" */
14 /*----------------------------------------------------------------------------*/
15 /*
16 * define the following macro if you want to handle smtp transparency
17 * manually, namely you will to escape yourself "<CRLF>.<CRLF>"
18 */
19 /* #define CONFIG_DISABLE_SMTP_TRANSPARENCY 1 */
20 /*----------------------------------------------------------------------------*/
21 /* KEEP AN EYE ON ABBREVIATIONS */
22 #define CONFIG_DNS_IPV4 1
23 #define CONFIG_SMTP_IPV4 1
24 /*----------------------------------------------------------------------------*/
25 /* the amount of address space which will be booked in our process */
26 #define CONFIG_EMAIL_ADDRESS_SPACE (100 * 1000 * 1000)
27 /*----------------------------------------------------------------------------*/
28 /*
29 * sending the same email to 32 ips/domain names is already insane for the
30 * target scale of this tool
31 */
32 #define CONFIG_DN_AL_N_MAX 32
33 /*----------------------------------------------------------------------------*/
34 #define CONFIG_DN_SMTP_IPS_N_MAX 32 /* max 32 smtp server IPs per domain name */
35 /* kind of worst case, all above ips are each from an unique mx */
36 #define CONFIG_MXS_N_MAX CONFIG_DN_SMTP_IPS_N_MAX
37 /*----------------------------------------------------------------------------*/
38 /* where is the resolv.conf file for nameservers */
39 #define CONFIG_RESOLV_CONF_PATH "/etc/resolv.conf"
40 /*----------------------------------------------------------------------------*/
41 /* a "good enough" generic buffer size (2 pages) */
42 #define CONFIG_BUFSIZ 8192
43 /*----------------------------------------------------------------------------*/
44 #define CONFIG_DNS_NSS_N_MAX 3 /* max name servers */
45 #define CONFIG_DNS_NS_RESP_WAIT_TIME_SEC 4 /* second */
46 #define CONFIG_DNS_NS_RESP_WAIT_TIME_NSEC 0 /* nanosecond */
47 /*----------------------------------------------------------------------------*/
48 #define CONFIG_DNS_LABEL_PTR_DEPTH_MAX 128
49 /*----------------------------------------------------------------------------*/
50 #define CONFIG_SMTP_REPLY_LINES_N_MAX 16
51 /*----------------------------------------------------------------------------*/
52 #endif
File dns.h added (mode: 100644) (index 0000000..b3b72c2)
1 #ifndef SYNCSM_DNS_H
2 #define SYNCSM_DNS_H
3 /*
4 * this code is protected by the GNU affero GPLv3 license
5 * author:Sylvain BERTRAND
6 */
7 #include "namespace/dns.h"
8 /*----------------------------------------------------------------------------*/
9 static void dns_init(void);
10 static void dns_resolver(void);
11 /*----------------------------------------------------------------------------*/
12 #define CLEANUP
13 #include "namespace/dns.h"
14 #undef CLEANUP
15 #endif
File dns/dns.txt added (mode: 100644) (index 0000000..8d03bf5)
1 rr(s): dns Resource Record(S)
2
3 brain soup from the following rfcs: 1034/1035(dns), 5321(smtp).
4
5 A mail domain name may be an alias of _one_ and _only_ one canonical domain
6 name. Then, keep in mind the following while reading below: for the first dns
7 query, namely asking an mx question on a mail domain name, if existing, the
8 cname rr, namely the _one_ Canonical domain NAME rr of the mail domain name
9 (which is then an alias), will be returned with 0 or more mx rrs related to
10 this very canonical domain name and _not_ related to the mail domain name
11 (which, I repeat, is then actually an alias).
12 In other words, the first thing to do is to discover the canonical domain name:
13 either provided in a cname rr, or being the targetted mail domain name itself.
14
15 mail domain name resolution: ask an mx question on the targetted mail domain
16 name. if a cname rr is present in the response then the canonical mail domain
17 name is the domain name from this very rr (and the targetted mail domain name
18 is actually an alias), or else the canonical domain name is actually the
19 targetted mail domain name. From there:
20 - if 0 mx rrs are returned for the canonical mail domain name , at least
21 1 A rr (if smtp ipv4 support is enabled) or at least 1 AAAA rr
22 (smtp ipv6 is always enabled) must be found in:
23 - either the response additional rrs section.
24 - or in the response answer sections of the A (if smtp ipv4 is
25 enabled) and AAAA questions, both on the canonical mail
26 domain name.
27 - if 1..n mx rrs are found for the canonical mail domain name, at least
28 1 mx rr exchange domain name must have 1 A or AAAA rr from:
29 - either, the response additional rrs section.
30 - or the response answer sections of A (if smtp ipv4 is enabled)
31 and AAAA questions, both on the mx rr exchange domain name.
File dns/ipv4.c added (mode: 100644) (index 0000000..1fb40e3)
1 #ifndef SYNCSM_DNS_IPV4_C
2 #define SYNCSM_DNS_IPV4_C
3 /*
4 * this code is protected by the GNU affero GPLv3 license
5 * author:Sylvain BERTRAND
6 */
7 /*----------------------------------------------------------------------------*/
8 /* compiler stuff */
9 #include <stdbool.h>
10 #include <stdarg.h>
11 /*----------------------------------------------------------------------------*/
12 #include "config.h"
13 /*----------------------------------------------------------------------------*/
14 #include "ulinux.h"
15 /*----------------------------------------------------------------------------*/
16 #include "dns/rfc.h"
17 #include "smtp/rfc.h"
18 /*----------------------------------------------------------------------------*/
19 #include "perr.h"
20 #include "syncsm.h"
21 /*----------------------------------------------------------------------------*/
22 #include "dns/state.h"
23 #include "dns/resolver.h"
24 /*============================================================================*/
25 #include "namespace/ulinux.h"
26 #include "dns/namespace/state.h"
27 #include "dns/namespace/resolver.h"
28 #include "dns/namespace/ipv4.h"
29 #include "dns/namespace/ipv4.c"
30 /*----------------------------------------------------------------------------*/
31 static si udp_so;
32 static struct sockaddr_in sa;
33 /*----------------------------------------------------------------------------*/
34 static bool qtion_send_ns(void)
35 {
36 sl r;
37 u16 sent_bytes_n;
38
39 sent_bytes_n = 0;
40 loop {
41 r = write(udp_so, query_v + sent_bytes_n,
42 query_sz_v - sent_bytes_n);
43 if (ISERR(r)) {
44 if ((r == -EAGAIN) || (r == -EINTR))
45 continue;
46 PERR("1:DNS:IPV4:WARNING:failed to send question to ipv4 name server 0x%08x for domain \"%.*s\"\n", be32_to_cpu(nss_v[ns_v].ipv4_net), dn_v->dn.l - dn_v->dn.s + 1, dn_v->dn.s);
47 return false;
48 }
49
50 sent_bytes_n += (u16)r;
51 if (sent_bytes_n == query_sz_v) {
52 PERR("i1:DNS:IPV4:sent %d bytes to ns 0x%08x\n", query_sz_v, be32_to_cpu(nss_v[ns_v].ipv4_net));
53 return true;
54 }
55 }
56 }
57
58 static void sa_init_ns(void)
59 {
60 memset(&sa, 0, sizeof(sa));
61
62 sa.family = AF_INET;
63 sa.port = cpu_to_be16(DNS_RFC_PORT);
64 memcpy(&sa.addr, &nss_v[ns_v].ipv4_net, sizeof(nss_v[ns_v].ipv4_net));
65 }
66
67 static void connect_ns(void)
68 {
69 sl r;
70
71 r = connect(udp_so, &sa, sizeof(sa));
72 if (ISERR(r)) {
73 if ((r != -EAGAIN) && (r != -EINPROGRESS) && (r != -EINTR)) {
74 PERR("0:DNS:IPV4:ERROR:%ld:unable to configure socket with the name server ipv4 address 0x%08x\n", r, be32_to_cpu(sa.addr));
75 exit(1);
76 }
77 }
78 }
79
80 static bool timer_expired(void)
81 {
82 sl r;
83 u64 expirations_n; /* the count of expirations of our timer */
84
85 expirations_n = 0;
86
87 loop {/* reads are atomic or err, aka no short reads */
88 r = read(timerfd_v, &expirations_n, sizeof(u64));
89 if (r != -EINTR);
90 break;
91 }
92
93 if (ISERR(r)) {
94 PERR("0:DNS:IPV4:ERROR:TIMER:%ld:unable reading the count of expirations\n", r);
95 exit(1);
96 }
97 PERR("1:DNS:IPV4:TIMER:count of expirations=%lu for name server 0x%08x\n", expirations_n, be32_to_cpu(nss_v[ns_v].ipv4_net));
98 if (expirations_n != 0)
99 return true;
100 return false;
101 }
102
103 static void udp_datagram_read(void)
104 {
105 sl r;
106 loop {
107 /* atomically get 1 message */
108 r = recvfrom(udp_so, resp_v, DNS_RFC_UDP_PAYLOAD_SZ_MAX, 0 ,0
109 ,0);
110 if (r == -EAGAIN || r == -EINTR)
111 continue;
112 if (!ISERR(r))
113 break;
114 PERR("0:DNS:IPV4:ERROR:%ld:error while reading the udp datagram\n", r);
115 exit(1);
116 }
117 resp_sz_v = (u16)r;
118 resp_e_v = resp_v + resp_sz_v;
119 PERR("1:DNS:RESPONSE:[0x%p-0x%p]\n", resp_v, resp_e_v - 1);
120 }
121
122 /* copy/paste/adapt from ulinux pattern epoll_timer */
123 static bool ns_resp_wait(void)
124 {
125 loop {
126 /*
127 * 2 events if the timer do happen at the same time that a udp
128 * datagram is received
129 */
130 struct epoll_event evts[2];
131 sl evt;
132 sl r;
133
134 loop {
135 memset(evts, 0, sizeof(evts));
136 r = epoll_pwait(epfd_v, evts, 2, -1, 0);
137 if (r != -EINTR)
138 break;
139 PERR("1:DNS:IPV4:WARNING:epoll_pwait was interruped by a signal, restarting\n");
140 }
141 if (ISERR(r)) {
142 PERR("0:DNS:IPV4:ERROR:%ld:epoll_wait error\n", r);
143 exit(1);
144 }
145
146 if (r == 0) /* meh... */
147 continue;
148
149 /* FIRST: probe for a udp datagram arrival event */
150 evt = 0;
151 loop {
152 if (evt == r)
153 break;
154 if (evts[evt].data.fd == udp_so) {
155 if ((evts[evt].events & EPOLLIN) != 0) {
156 udp_datagram_read();
157 return true;
158 } else {
159 PERR("0:DNS:IPV4:ERROR:got unselected event for ipv4_udp, events 0x%08x\n", evts[evt].events);
160 exit(1);
161 }
162 }
163 ++evt;
164 }
165
166 /* THEN: check the timer expiration */
167 evt = 0;
168 loop {
169 if (evt == r)
170 break;
171
172 if (evts[evt].data.fd == timerfd_v) {
173 if ((evts[evt].events & EPOLLIN) != 0) {
174 if (timer_expired())
175 return false;
176 } else {
177 PERR("0:DNS:IPv4:ERROR:got unselected event for the timer, events 0x%08x\n", evts[evt].events);
178 exit(1);
179 }
180 }
181 ++evt;
182 }
183 }
184 }
185 /******************************************************************************/
186 /* exported in ipv4.h */
187 static void ipv4_udp_so_setup(void)
188 {
189 sl r;
190 struct epoll_event evts;
191
192 /* ipv4 */
193 r = socket(AF_INET, SOCK_O_NONBLOCK | SOCK_DGRAM, 0);
194 if (ISERR(r)) {
195 PERR("0:DNS:IPV4:ERROR:%ld:unable to create ipv4 udp socket for dns\n", r);
196 exit(1);
197 }
198 udp_so = (si)r;
199
200 memset(&evts, 0, sizeof(evts));
201 evts.events = EPOLLIN;
202 evts.data.fd = udp_so;
203 r = epoll_ctl(epfd_v, EPOLL_CTL_ADD, udp_so, &evts);
204 if (ISERR(r)) {
205 PERR("0:DNS:IPV4:ERROR:%ld:unable to add the ipv4 socket file descriptor to the epoll file descriptor\n", r);
206 exit(1);
207 }
208 }
209
210 static bool ipv4_ns(void)
211 {
212 sa_init_ns();
213 connect_ns();
214
215 if (!qtion_send_ns())
216 return false;
217 return ns_resp_wait();
218 }
219 /*-----------------------------------------------------------------------------*/
220 #define CLEANUP
221 #include "namespace/ulinux.h"
222 #include "dns/namespace/state.h"
223 #include "dns/namespace/resolver.h"
224 #include "dns/namespace/ipv4.h"
225 #include "dns/namespace/ipv4.c"
226 #undef CLEANUP
227 #endif
File dns/ipv4.h added (mode: 100644) (index 0000000..d64a871)
1 #ifndef SYNCSM_DNS_IPV4_H
2 #define SYNCSM_DNS_IPV4_H
3 #include "dns/namespace/ipv4.h"
4 /*
5 * this code is protected by the GNU affero GPLv3 license
6 * author:Sylvain BERTRAND
7 */
8 static void ipv4_udp_so_setup(void);
9 static bool ipv4_ns(void);
10 #define CLEANUP
11 #include "dns/namespace/ipv4.h"
12 #undef CLEANUP
13 #endif
File dns/ipv6.c added (mode: 100644) (index 0000000..c18b68c)
1 #ifndef SYNCSM_DNS_IPV6_C
2 #define SYNCSM_DNS_IPV6_C
3 /*
4 * this code is protected by the GNU affero GPLv3 license
5 * author:Sylvain BERTRAND
6 */
7 /*----------------------------------------------------------------------------*/
8 #include <stdbool.h>
9 #include <stdarg.h>
10 /*----------------------------------------------------------------------------*/
11 #include "config.h"
12 /*----------------------------------------------------------------------------*/
13 #include "ulinux.h"
14 /*----------------------------------------------------------------------------*/
15 #include "dns/rfc.h"
16 #include "smtp/rfc.h"
17 /*----------------------------------------------------------------------------*/
18 #include "perr.h"
19 #include "syncsm.h"
20 /*----------------------------------------------------------------------------*/
21 #include "dns/state.h"
22 #include "dns/resolver.h"
23 /*============================================================================*/
24 #include "namespace/ulinux.h"
25 #include "dns/namespace/state.h"
26 #include "dns/namespace/resolver.h"
27 #include "dns/namespace/ipv6.h"
28 #include "dns/namespace/ipv6.c"
29 /*----------------------------------------------------------------------------*/
30 static si udp_so;
31 static struct sockaddr_in6 sa;
32 /*----------------------------------------------------------------------------*/
33 static bool qtion_send_ns(void)
34 {
35 sl r;
36 u16 sent_bytes_n;
37
38 sent_bytes_n = 0;
39 loop {
40 r = write(udp_so, query_v + sent_bytes_n,
41 query_sz_v - sent_bytes_n);
42 if (ISERR(r)) {
43 if ((r == -EAGAIN) || (r == -EINTR))
44 continue;
45 PERR("1:DNS:IPV6:WARNING:failed to send mx question to ipv6 name server 0x%016lx%016lx for domain \"%.*s\"\n", be64_to_cpu(nss_v[ns_v].ipv6_net_h), be64_to_cpu(nss_v[ns_v].ipv6_net_l), dn_v->dn.l - dn_v->dn.s + 1, dn_v->dn.s);
46 return false;
47 }
48
49 sent_bytes_n += (u16)r;
50 if (sent_bytes_n == query_sz_v)
51 return true;
52 }
53 }
54
55 static void sa_init_ns(void)
56 {
57 memset(&sa, 0, sizeof(sa));
58
59 sa.family = AF_INET6;
60 sa.port = cpu_to_be16(DNS_RFC_PORT);
61 memcpy(&sa.addr, &nss_v[ns_v].ipv6_net, sizeof(nss_v[ns_v].ipv6_net));
62 }
63
64 static void connect_ns(void)
65 {
66 sl r;
67
68 r = connect(udp_so, &sa, sizeof(sa));
69 if (ISERR(r)) {
70 if ((r != -EAGAIN) && (r != -EINPROGRESS) && (r != -EINTR)) {
71 PERR("0:DNS:IPV6:ERROR:%ld:unable to configure socket with the name server ipv6 address 0x%016lx%016lx\n", r, be64_to_cpu(nss_v[ns_v].ipv6_net_h), be64_to_cpu(nss_v[ns_v].ipv6_net_l));
72 exit(1);
73 }
74 }
75 }
76
77 static void udp_datagram_read(void)
78 {
79 sl r;
80 loop {
81 /* atomically get 1 message */
82 r = recvfrom(udp_so, resp_v, DNS_RFC_UDP_PAYLOAD_SZ_MAX, 0 ,0
83 ,0);
84 if (r == -EAGAIN || r == -EINTR)
85 continue;
86 if (!ISERR(r))
87 break;
88 PERR("0:DNS:IPV6:ERROR:%ld:error reading the udp datagram\n", r);
89 exit(1);
90 }
91 resp_sz_v = (u16)r;
92 resp_e_v = resp_v + resp_sz_v;
93 PERR("1:DNS:RESPONSE:[0x%p-0x%p]\n", resp_v, resp_e_v - 1);
94 }
95
96 static bool timer_expired(void)
97 {
98 sl r;
99 u64 expirations_n; /* the count of expirations of our timer */
100
101 expirations_n = 0;
102
103 loop {/* reads are atomic or err, aka no short reads */
104 r = read(timerfd_v, &expirations_n, sizeof(u64));
105 if (r != -EINTR);
106 break;
107 }
108
109 if (ISERR(r)) {
110 PERR("0:DNS:IPV6:ERROR:TIMER:%ld:unable reading the count of expirations\n", r);
111 exit(1);
112 }
113 PERR("1:DNS:IPV6:TIMER:count of expirations=%lu for name server 0x%016lx%016lx\n", expirations_n, be64_to_cpu(nss_v[ns_v].ipv6_net_h), be64_to_cpu(nss_v[ns_v].ipv6_net_l));
114 if (expirations_n != 0)
115 return true;
116 return false;
117 }
118
119 /* copy/paste/adapt from ulinux pattern epoll_timer */
120 static bool ns_resp_wait(void)
121 {
122 loop {
123 /*
124 * 2 events if the timer do happen at the same time that a udp
125 * datagram is received
126 */
127 struct epoll_event evts[2];
128 sl evt;
129 sl r;
130
131 loop {
132 memset(evts, 0, sizeof(evts));
133 r = epoll_pwait(epfd_v, evts, 2, -1, 0);
134 if (r != -EINTR)
135 break;
136 PERR("1:DNS:IPV6:WARNING:epoll_pwait was interruped by a signal, restarting\n");
137 }
138 if (ISERR(r)) {
139 PERR("0:DNS:IPV6:ERROR:%ld:epoll_wait error\n", r);
140 exit(1);
141 }
142
143 if (r == 0) /* meh... */
144 continue;
145
146 /* FIRST: probe for a udp datagram arrival event */
147 evt = 0;
148 loop {
149 if (evt == r)
150 break;
151 if (evts[evt].data.fd == udp_so) {
152 if ((evts[evt].events & EPOLLIN) != 0) {
153 udp_datagram_read();
154 return true;
155 } else {
156 PERR("0:DNS:IPV6:ERROR:got unselected event for ipv6_udp, events 0x%08x\n", evts[evt].events);
157 exit(1);
158 }
159 }
160 ++evt;
161 }
162
163 /* THEN: check the timer expiration */
164 evt = 0;
165 loop {
166 if (evt == r)
167 break;
168
169 if (evts[evt].data.fd == timerfd_v) {
170 if ((evts[evt].events & EPOLLIN) != 0) {
171 if (timer_expired())
172 return false;
173 } else {
174 PERR("0:DNS:IPV6:ERROR:got unselected event for the timer, events 0x%08x\n", evts[evt].events);
175 exit(1);
176 }
177 }
178 ++evt;
179 }
180 }
181 }
182 /******************************************************************************/
183 /* exported in ipv6.h */
184 static void ipv6_udp_so_setup(void)
185 {
186 sl r;
187 struct epoll_event evts;
188
189 /* ipv6 */
190 r = socket(AF_INET6, SOCK_O_NONBLOCK | SOCK_DGRAM, 0);
191 if (ISERR(r)) {
192 PERR("0:DNS:IPV6:ERROR:%ld:unable to create ipv6 udp socket for dns\n", r);
193 exit(1);
194 }
195 udp_so = (si)r;
196
197 memset(&evts, 0, sizeof(evts));
198 evts.events = EPOLLIN;
199 evts.data.fd = udp_so;
200 r = epoll_ctl(epfd_v, EPOLL_CTL_ADD, udp_so, &evts);
201 if (ISERR(r)) {
202 PERR("0:DNS:IPV6:ERROR:%ld:unable to add the ipv6 socket file descriptor to the epoll file descriptor\n", r);
203 exit(1);
204 }
205 }
206
207 static bool ipv6_ns(void)
208 {
209 sa_init_ns();
210 connect_ns();
211
212 if (!qtion_send_ns())
213 return false;
214 return ns_resp_wait();
215 }
216 /*-----------------------------------------------------------------------------*/
217 /* file trailer */
218 #define CLEANUP
219 #include "namespace/ulinux.h"
220 #include "dns/namespace/state.h"
221 #include "dns/namespace/resolver.h"
222 #include "dns/namespace/ipv6.h"
223 #include "dns/namespace/ipv6.c"
224 #undef CLEANUP
225 #endif
File dns/ipv6.h added (mode: 100644) (index 0000000..54a3afa)
1 #ifndef SYNCSM_DNS_IPV6_H
2 #define SYNCSM_DNS_IPV6_H
3 #include "dns/namespace/ipv6.h"
4 /*
5 * this code is protected by the GNU affero GPLv3 license
6 * author:Sylvain BERTRAND
7 */
8 static void ipv6_udp_so_setup(void);
9 static bool ipv6_ns(void);
10 #define CLEANUP
11 #include "dns/namespace/ipv6.h"
12 #undef CLEANUP
13 #endif
File dns/name.c added (mode: 100644) (index 0000000..84b5fe0)
1 #ifndef SYNCSM_DNS_NAME_C
2 #define SYNCSM_DNS_NAME_C
3 /*
4 * this code is protected by the GNU affero GPLv3 license
5 * author:Sylvain BERTRAND
6 */
7 /* compiler stuff */
8 #include <stdbool.h>
9 #include <stdarg.h>
10 /*----------------------------------------------------------------------------*/
11 #include "config.h"
12 /*----------------------------------------------------------------------------*/
13 #include "ulinux.h"
14 /*----------------------------------------------------------------------------*/
15 #include "dns/rfc.h"
16 #include "smtp/rfc.h"
17 /*----------------------------------------------------------------------------*/
18 #include "perr.h"
19 #include "syncsm.h"
20 /*============================================================================*/
21 #include "namespace/ulinux.h"
22 #include "namespace/syncsm.h"
23 #include "dns/namespace/name.h"
24 #include "dns/namespace/name.c"
25 /*----------------------------------------------------------------------------*/
26 #define IS_PTR(x) \
27 (((x) & DNS_RFC_LABEL_OFFSET_IS_PTR_MARK) == DNS_RFC_LABEL_OFFSET_IS_PTR_MARK)
28 /*----------------------------------------------------------------------------*/
29 static void label_ptr(u8 **label, u8 *msg_s, u8 *msg_e, u8 *depth)
30 {
31 if ((*label) >= msg_e) {
32 PERR("0:DNS:LABEL_PTR:ERROR:the label pointer is out of bounds\n");
33 exit(1);
34 }
35
36 if (IS_PTR((*label)[0])) {
37 u16 offset;
38
39 if (*depth == 0) {
40 PERR("0:DNS:LABEL_PTR:ERROR:max label pointer recursion reached, %u\n", CONFIG_DNS_LABEL_PTR_DEPTH_MAX);
41 exit(1);
42 }
43 (*depth)--;
44
45 if ((*label + 1) >= msg_e) {
46 PERR("0:DNS:LABEL_PTR:ERROR:the label pointer offset is itself out of bounds\n");
47 exit(1);
48 }
49
50 offset = be16_to_cpu(*(u16*)(*label));
51 offset &= DNS_RFC_LABEL_PTR_OFFSET_MASK;
52
53 PERR("1:DNS:LABEL_PTR:offset 0x%04x [0x%p-0x%p]\n", offset, msg_s, msg_e - 1);
54 *label = msg_s + offset;
55 }
56 }
57
58 /*
59 * return a pointer on the byte following the last valid byte of the destination
60 * label
61 */
62 static u8 *label_cpy(u8 *d, u8 *d_e, u8* s, u8* s_msg_e)
63 {
64 u8 sz;
65 u8 *d_l; /* last byte */
66 u8 *s_l; /* last byte */
67
68 PERR("1:DNS:LABEL_CPY:START\n");
69 if (d >= d_e) {
70 PERR("0:DNS:LABEL_CPY:ERROR:D:label is out of bounds\n");
71 exit(1);
72 }
73
74 if (s >= s_msg_e) {
75 PERR("0:DNS:LABEL_CPY:ERROR:S:label is out of bounds\n");
76 exit(1);
77 }
78
79 d[0] = s[0];
80
81 sz = s[0];
82 if (sz == 0) {
83 PERR("1:DNS:LABEL_CPY:END:EQ:zero size\n");
84 return d + 1;
85 }
86
87 d_l = d + 1 + sz - 1;
88 if (d_l >= d_e) {
89 PERR("0:DNS:LABEL_CPY:ERROR:D:label will go out of bounds\n");
90 exit(1);
91 }
92
93 s_l = s + 1 + sz -1;
94 if (s_l >= s_msg_e) {
95 PERR("0:DNS:LABEL_CPY:ERROR:S:label is going out of bounds\n");
96 exit(1);
97 }
98
99 PERR("1:DNS:LABEL_CPY:S:B:%.*s(%u)\n", sz, s + 1, sz);
100 memcpy(d + 1, s + 1, sz);
101 PERR("1:DNS:LABEL_CPY:END\n");
102 return d + 1 + sz;
103 }
104
105 static bool label_cmp(u8 *a, u8 *a_msg_e, u8* b, u8* b_msg_e)
106 {
107 u8 sz;
108 u8 *a_l;
109 u8 *b_l;
110
111 PERR("1:DNS:LABEL_CMP:START\n");
112 if (a >= a_msg_e) {
113 PERR("0:DNS:LABEL_CMP:ERROR:A:label is out of bounds\n");
114 exit(1);
115 }
116
117 if (b >= b_msg_e) {
118 PERR("0:DNS:LABEL_CMP:ERROR:B:label is out of bounds\n");
119 exit(1);
120 }
121
122 if (a[0] != b[0]) {
123 PERR("1:DNS:LABEL_CMP:END:NEQ:not the same size\n");
124 return false;
125 }
126
127 sz = a[0];
128 if (sz == 0) {
129 PERR("1:DNS:LABEL_CMP:END:EQ:zero size\n");
130 return true;
131 }
132
133 a_l = a + 1 + sz - 1;
134 if (a_l >= a_msg_e) {
135 PERR("0:DNS:LABEL_CMP:ERROR:A:label is going out of bounds\n");
136 exit(1);
137 }
138
139 b_l = b + 1 + sz -1;
140 if (b_l >= b_msg_e) {
141 PERR("0:DNS:LABEL_CMP:ERROR:B:label is going out of bounds\n");
142 exit(1);
143 }
144
145 PERR("1:DNS:LABEL_CMP:A:%.*s(%u):B:%.*s(%u)\n", a[0], a + 1, a[0], b[0], b + 1, b[0]);
146 if (!memcmp(a + 1, b + 1, sz)) {
147 PERR("1:DNS:LABEL_CMP:END:NEQ\n");
148 return false;
149 }
150 PERR("1:DNS:LABEL_CMP:END:EQ\n");
151 return true;
152 }
153 /******************************************************************************/
154 /* the following until the end of the file is exported in name.h */
155 /*
156 * build a "dns name". Good Enough.
157 * return a pointer on the byte following the name.
158 * a domain name string in smtp must not end with a dot.
159 */
160 static u8 *name_build(u8 *name, struct str_slice_t *dn)
161 {
162 u8 *label_s;
163 u8 *label_l;
164 u8 idx;
165 bool last_label;
166 u64 name_sz;
167
168 label_s = dn->s;
169 label_l = dn->s;
170 last_label = false;
171 idx = 0;
172 name_sz = 0;
173 loop {
174 if (label_l == dn->l)
175 last_label = true;
176
177 if (last_label || (label_l[1] == '.')) {
178 u64 label_sz;
179
180 label_sz = label_l - label_s + 1;
181 if (label_sz > DNS_RFC_LABEL_SZ_MAX) {
182 PERR("0:DNS:NAME_BUILDER:ERROR:dns label length greater than rfc limits, max is %u, faulty dns label is %.*s\n", DNS_RFC_LABEL_SZ_MAX, label_sz, label_s);
183 exit(1);
184 }
185 name[0] = (u8)label_sz;
186 name_sz += 1 + label_sz;
187 if (name_sz > DNS_RFC_NAME_SZ_MAX) {
188 PERR("0:DNS:ERROR:NAME_BUILDER:dns name length greater than rfc limits, max is %u, faulty dns name is %.*s\n", DNS_RFC_NAME_SZ_MAX, dn->l - dn->s + 1, dn->s);
189 exit(1);
190 }
191 memcpy(name + 1, label_s, label_sz);
192
193 PERR("1:DNS:NAME_BUILDER:LABEL:\"%.*s\"[%u]:%u:%.*s\n", dn->l - dn->s + 1, dn->s, idx, label_sz, label_sz, label_s);
194 ++idx;
195
196 if (last_label) {
197 name += 1 + label_sz;
198
199 name_sz += 1; /* the "null" root domain name, only the length octet which is 0 */
200 if (name_sz > DNS_RFC_NAME_SZ_MAX) {
201 PERR("0:DNS:ERROR:NAME_BUILDER:dns name length greater than rfc limits, cannot fit the null domain, max is %u, faulty dns name is %.*s\n", DNS_RFC_NAME_SZ_MAX, dn->l - dn->s + 1, dn->s);
202 exit(1);
203 }
204 name[0] = 0; /* the 'null'/root label */
205 return name + 1;
206 }
207
208 label_s = label_l + 2; /* skip '.' */
209 label_l = label_s;
210
211 name += 1 + label_sz;
212 } else
213 ++label_l;
214 }
215 }
216
217 /*
218 * decompress/copy a source name from a msg into a buffer.
219 * will return a pointer on the byte past the last copy byte.
220 */
221 static u8 *name_cpy(u8 *d, u8 *s, u8 *s_msg_s, u8 *s_msg_e)
222 {
223 u8 *s_label;
224 u8 s_depth;
225
226 PERR("1:DNS:NAME_CPY:START\n");
227 PERR("1:DNS:NAME_CPY:D:0x%p[DNS_RFC_NAME_SZ_MAX=0x%x]\n", d, DNS_RFC_NAME_SZ_MAX);
228 PERR("1:DNS:NAME_CPY:S:0x%p[0x%p-0x%p]\n", s, s_msg_s, s_msg_e - 1);
229
230 if (s < s_msg_s || s_msg_e <= s) {
231 PERR("0:DNS:NAME_CPY:ERROR:S:name start is out of bounds\n");
232 exit(1);
233 }
234
235 s_label = s;
236 s_depth = CONFIG_DNS_LABEL_PTR_DEPTH_MAX;;
237 loop {
238 u8 label_sz;
239
240 label_ptr(&s_label, s_msg_s, s_msg_e, &s_depth);
241
242 d = label_cpy(d, d + DNS_RFC_NAME_SZ_MAX, s_label, s_msg_e);
243
244 label_sz = s_label[0];
245
246 if (label_sz == 0) {
247 PERR("1:DNS:NAME_CPY:END\n");
248 return d;
249 }
250
251 s_label += label_sz + 1;
252 }
253 }
254
255 static bool name_cmp(u8 *a, u8 *a_msg_s, u8* a_msg_e, u8 *b, u8 *b_msg_s,
256 u8* b_msg_e)
257 {
258 u8 *a_label;
259 u8 *b_label;
260 u8 a_depth;
261 u8 b_depth;
262
263 PERR("1:DNS:NAME_CMP:START\n");
264 PERR("1:DNS:NAME_CMP:A:0x%p[0x%p-0x%p]\n", a, a_msg_s, a_msg_e - 1);
265 PERR("1:DNS:NAME_CMP:B:0x%p[0x%p-0x%p]\n", b, b_msg_s, b_msg_e - 1);
266
267 if (a < a_msg_s || a_msg_e <= a) {
268 PERR("0:DNS:NAME_CMP:ERROR:A:name start is out of bounds\n");
269 exit(1);
270 }
271 if (b < b_msg_s || b_msg_e <= b) {
272 PERR("0:DNS:NAME_CMP:ERROR:B:name start is out of bounds\n");
273 exit(1);
274 }
275
276 a_label = a;
277 b_label = b;
278 a_depth = CONFIG_DNS_LABEL_PTR_DEPTH_MAX;
279 b_depth = CONFIG_DNS_LABEL_PTR_DEPTH_MAX;;
280 loop {
281 u8 label_sz;
282
283 label_ptr(&a_label, a_msg_s, a_msg_e, &a_depth);
284 label_ptr(&b_label, b_msg_s, b_msg_e, &b_depth);
285
286 if (!label_cmp(a_label, a_msg_e, b_label, b_msg_e)) {
287 PERR("1:DNS:NAME_CMP:END:NEQ\n");
288 return false;
289 }
290
291 label_sz = a_label[0];
292
293 if (label_sz == 0) {
294 PERR("1:DNS:NAME_CMP:END:EQ\n");
295 return true;
296 }
297
298 a_label += label_sz + 1;
299 b_label += label_sz + 1;
300 }
301 }
302
303 static void name_dump(u8 *name, u8 *msg_s, u8 *msg_e)
304 {
305 u8 *label;
306 u8 name_depth;
307 u8 label_idx;
308
309 PERR("1:DNS:NAME_DUMP:START\n");
310 PERR("1:DNS:NAME_DUMP:0x%p[0x%p-0x%p]\n", name, msg_s, msg_e - 1);
311
312 label = name;
313 name_depth = CONFIG_DNS_LABEL_PTR_DEPTH_MAX;
314 label_idx = 0;
315 loop {
316 u8 *label_l;
317
318 label_ptr(&label, msg_s, msg_e, &name_depth);
319
320 if (label >= msg_e) {
321 PERR("0:DNS:NAME_DUMP:ERROR:label[%u] is out of bounds\n", label_idx);
322 exit(1);
323 }
324
325 if (label[0] == 0)
326 break;
327
328 label_l = label + 1 + label[0] - 1;
329 if (label_l >= msg_e ) {
330 PERR("0:DNS:NAME_DUMP:ERROR:label[%u] is going out of bounds\n", label_idx);
331 exit(1);
332 }
333 PERR("1:DNS:NAME_DUMP:label[%u]=%.*s(%u bytes)\n", label_idx, label[0], label + 1, label[0]);
334
335 label = label_l + 1;
336 ++label_idx;
337 }
338 PERR("1:DNS:NAME_DUMP:END\n");
339 }
340
341 static void *name_skip(u8 *name, u8 *msg_s, u8 *msg_e)
342 {
343 u8 *label;
344
345 PERR("1:DNS:NAME_SKIP:START\n");
346 PERR("1:DNS:NAME_SKIP:0x%p[0x%p-0x%p]\n", name, msg_s, msg_e - 1);
347
348 label = name;
349 loop {
350 PERR("DNS:NAME_SKIP:LABEL:0x%p\n", label);
351 if (label >= msg_e) {
352 PERR("0:DNS:NAME_SKIP:ERROR:label is out of bounds\n");
353 exit(1);
354 }
355
356 if (label[0] == 0) {
357 PERR("1:DNS:NAME_SKIP:END:ZERO\n");
358 return label + 1;
359 }
360
361 if (IS_PTR(label[0])) {
362 PERR("1:DNS:NAME_SKIP:END:POINTER\n");
363 return label + 2;
364 }
365
366 label += label[0] + 1;
367 }
368 }
369 #undef IS_PTR
370 /*----------------------------------------------------------------------------*/
371 #define CLEANUP
372 #include "namespace/ulinux.h"
373 #include "namespace/syncsm.h"
374 #include "dns/namespace/name.h"
375 #include "dns/namespace/name.c"
376 #undef CLEANUP
377 #endif
File dns/name.h added (mode: 100644) (index 0000000..2bc6162)
1 #ifndef SYNCSM_DNS_NAME_H
2 #define SYNCSM_DNS_NAME_H
3 #include "namespace/ulinux.h"
4 #include "namespace/syncsm.h"
5 #include "dns/namespace/name.h"
6 static u8 *name_build(u8 *name, struct str_slice_t *dn);
7 static bool name_cmp(u8 *a, u8 *a_msg_s, u8* a_msg_e, u8 *b, u8 *b_msg_s,
8 u8* b_msg_e);
9 static u8 *name_cpy(u8 *d, u8 *s, u8 *s_msg_s, u8 *s_msg_e);
10 static void name_dump(u8 *name, u8 *msg_s, u8 *msg_e);
11 static void *name_skip(u8 *name, u8 *msg_s, u8 *msg_e);
12 #define CLEANUP
13 #include "namespace/ulinux.h"
14 #include "namespace/syncsm.h"
15 #include "dns/namespace/name.h"
16 #undef CLEANUP
17 #endif
File dns/namespace/ipv4.c added (mode: 100644) (index 0000000..972073a)
1 /*
2 * this code is protected by the GNU affero GPLv3 license
3 * author:Sylvain BERTRAND
4 */
5 #ifndef CLEANUP
6 #define connect_ns syncsm_dns_ipv4_c_connect_ns
7 #define ns_resp_wait syncsm_dns_ipv4_c_ns_resp_wait
8 #define qtion_send_ns syncsm_dns_ipv4_c_qtion_send_ns
9 #define sa syncsm_dns_ipv4_c_sa
10 #define sa_init_ns syncsm_dns_ipv4_c_sa_init_ns
11 #define timer_expired syncsm_dns_ipv4_c_timer_expired
12 #define udp_datagram_read syncsm_dns_ipv4_c_udp_datagram_read
13 #define udp_so syncsm_dns_ipv4_c_udp_so
14 /******************************************************************************/
15 #else /* CLEANUP */
16 #undef connect_ns
17 #undef ns_resp_wait
18 #undef qtion_send_ns
19 #undef sa
20 #undef sa_init_ns
21 #undef timer_expired
22 #undef udp_datagram_read
23 #undef udp_so
24 #endif
File dns/namespace/ipv4.h added (mode: 100644) (index 0000000..d836f44)
1 /*
2 * this code is protected by the GNU affero GPLv3 license
3 * author:Sylvain BERTRAND
4 */
5 #ifndef CLEANUP
6 #define ipv4_ns syncsm_dns_ipv4_ns
7 #define ipv4_udp_so_setup syncsm_dns_ipv4_udp_so_setup
8 /******************************************************************************/
9 #else /* CLEANUP */
10 #undef ipv4_ns
11 #undef ipv4_udp_so_setup
12 #endif
File dns/namespace/ipv6.c added (mode: 100644) (index 0000000..e1aebf9)
1 /*
2 * this code is protected by the GNU affero GPLv3 license
3 * author:Sylvain BERTRAND
4 */
5 #ifndef CLEANUP
6 #define connect_ns syncsm_dns_ipv6_c_connect_ns
7 #define ns_resp_wait syncsm_dns_ipv6_c_ns_resp_wait
8 #define qtion_send_ns syncsm_dns_ipv6_c_qtion_send_ns
9 #define sa syncsm_dns_ipv6_c_sa
10 #define sa_init_ns syncsm_dns_ipv6_c_sa_init_ns
11 #define timer_expired syncsm_dns_ipv6_c_timer_expired
12 #define udp_datagram_read syncsm_dns_ipv6_c_udp_datagram_read
13 #define udp_so syncsm_dns_ipv6_c_udp_so
14 /******************************************************************************/
15 #else /* CLEANUP */
16 #undef connect_ns
17 #undef ns_resp_wait
18 #undef qtion_send_ns
19 #undef sa
20 #undef sa_init_ns
21 #undef timer_expired
22 #undef udp_datagram_read
23 #undef udp_so
24 #endif
File dns/namespace/ipv6.h added (mode: 100644) (index 0000000..786e715)
1 /*
2 * this code is protected by the GNU affero GPLv3 license
3 * author:Sylvain BERTRAND
4 */
5 #ifndef CLEANUP
6 #define ipv6_ns syncsm_dns_ipv6_ns
7 #define ipv6_udp_so_setup syncsm_dns_ipv6_udp_so_setup
8 /******************************************************************************/
9 #else /* CLEANUP */
10 #undef ipv6_ns
11 #undef ipv6_udp_so_setup
12 #endif
File dns/namespace/name.c added (mode: 100644) (index 0000000..c288b84)
1 /*
2 * this code is protected by the GNU affero GPLv3 license
3 * author:Sylvain BERTRAND
4 */
5 #ifndef CLEANUP
6 #define label_cmp syncsm_dns_name_c_label_cmp
7 #define label_cpy syncsm_dns_name_c_label_cpy
8 #define label_ptr syncsm_dns_name_c_label_ptr
9 /******************************************************************************/
10 #else /* CLEANUP */
11 #undef label_cmp
12 #undef label_cpy
13 #undef label_ptr
14 #endif
15
File dns/namespace/name.h added (mode: 100644) (index 0000000..688057c)
1 /*
2 * this code is protected by the GNU affero GPLv3 license
3 * author:Sylvain BERTRAND
4 */
5 #ifndef CLEANUP
6 #define name_build syncsm_dns_name_build
7 #define name_cmp syncsm_dns_name_cmp
8 #define name_cpy syncsm_dns_name_cpy
9 #define name_dump syncsm_dns_name_dump
10 #define name_skip syncsm_dns_name_skip
11 /******************************************************************************/
12 #else /* CLEANUP */
13 #undef name_build
14 #undef name_cmp
15 #undef name_cpy
16 #undef name_dump
17 #undef name_skip
18 #endif
File dns/namespace/query.h added (mode: 100644) (index 0000000..f2cec90)
1 /*
2 * this code is protected by the GNU affero GPLv3 license
3 * author:Sylvain BERTRAND
4 */
5 #ifndef CLEANUP
6 #define query_build syncsm_dns_query_build
7 /******************************************************************************/
8 #else /* CLEANUP */
9 #undef query_build
10 #endif
File dns/namespace/resolv_conf.c added (mode: 100644) (index 0000000..d7ed09d)
1 /*
2 * this code is protected by the GNU affero GPLv3 license
3 * author:Sylvain BERTRAND
4 */
5 #ifndef CLEANUP
6 #define parse_line syncsm_dns_resol_conf_c_parse_line
7 #define resolv_conf syncsm_dns_resol_conf_c_resolv_conf
8 #define resolv_conf_sz syncsm_dns_resol_conf_c_resolv_conf_sz
9 /******************************************************************************/
10 #else /* CLEANUP */
11 #undef parse_line
12 #undef resolv_conf
13 #undef resolv_conf_sz
14 #endif
File dns/namespace/resolv_conf.h added (mode: 100644) (index 0000000..11ad0ec)
1 /*
2 * this code is protected by the GNU affero GPLv3 license
3 * author:Sylvain BERTRAND
4 */
5 #ifndef CLEANUP
6 #define resolv_conf_parse syncsm_dns_resolv_conf_parse
7 #define resolv_conf_read syncsm_dns_resolv_conf_read
8 /******************************************************************************/
9 #else /* CLEANUP */
10 #undef resolv_conf_parse
11 #undef resolv_conf_read
12 #endif
File dns/namespace/resolver.c added (mode: 100644) (index 0000000..b08d794)
1 /*
2 * this code is protected by the GNU affero GPLv3 license
3 * author:Sylvain BERTRAND
4 */
5 #ifndef CLEANUP
6 #define canonical_dn_ips_collect syncsm_dns_resolver_c_canonical_dn_ips_collect
7 #define canonical_dn_ips_collect_from_net syncsm_dns_resolver_c_canonical_dn_ips_collect_from_net
8 #ifdef CONFIG_SMTP_IPV4
9 #define canonical_dn_ipv4_collect_from_net syncsm_dns_resolver_c_canonical_dn_ipv4_collect_from_net
10 #endif
11 #define canonical_dn_ipv6_collect_from_net syncsm_dns_resolver_c_canonical_dn_ipv6_collect_from_net
12 #define dump_dn_ips syncsm_dns_resolver_c_dump_dn_ips
13 #define dump_mxs_pref syncsm_dns_resolver_c_dump_mxs_pref
14 #define mx_cmp syncsm_dns_resolver_c_mx_cmp
15 #define mx_ips_collect_from_net syncsm_dns_resolver_c_mx_ips_collect_from_net
16 #ifdef CONFIG_SMTP_IPV4
17 #define mx_ipv4_collect_from_net syncsm_dns_resolver_c_mx_ipv4_collect_from_net
18 #endif
19 #define mx_ipv6_collect_from_net syncsm_dns_resolver_c_mx_ipv6_collect_from_net
20 #define mxs_ips_collect syncsm_dns_resolver_c_mxs_ips_collect
21 #define mxs_ips_collect_from_net syncsm_dns_resolver_c_mxs_ips_collect_from_net
22 #define mxs_ips_collect_from_resp_ar syncsm_dns_resolver_c_mxs_ips_collect_from_resp_ar
23 #define ns_ask syncsm_dns_resolver_c_ns_ask
24 #define ns_net_ask syncsm_dns_resolver_c_ns_net_ask
25 #define ns_timer_start syncsm_dns_resolver_c_ns_timer_start
26 #define nss_ask syncsm_dns_resolver_c_nss_ask
27 #define qtion_ask_ns syncsm_dns_resolver_c_qtion_ask_ns
28 #define resolver syncsm_dns_resolver_c_resolver
29 #define timer_setup syncsm_dns_resolver_c_timer_setup
30 #define udp_so_setup syncsm_dns_resolver_c_udp_so_setup
31 /******************************************************************************/
32 #else /* CLEANUP */
33 #undef canonical_dn_ips_collect
34 #undef canonical_dn_ips_collect_from_net
35 #ifdef CONFIG_SMTP_IPV4
36 #undef canonical_dn_ipv4_collect_from_net
37 #endif
38 #undef canonical_dn_ipv6_collect_from_net
39 #undef dump_dn_ips
40 #undef dump_mxs_pref
41 #undef mx_cmp
42 #undef mx_ips_collect_from_net
43 #ifdef CONFIG_SMTP_IPV4
44 #undef mx_ipv4_collect_from_net
45 #endif
46 #undef mx_ipv6_collect_from_net
47 #undef mxs_ips_collect
48 #undef mxs_ips_collect_from_net
49 #undef mxs_ips_collect_from_resp_ar
50 #undef ns_ask
51 #undef ns_net_ask
52 #undef ns_timer_start
53 #undef nss_ask
54 #undef qtion_ask_ns
55 #undef resolver
56 #undef timer_setup
57 #undef udp_so_setup
58 #endif
File dns/namespace/resolver.h added (mode: 100644) (index 0000000..62ee6d4)
1 /*
2 * this code is protected by the GNU affero GPLv3 license
3 * author:Sylvain BERTRAND
4 */
5 #ifndef CLEANUP
6 #define epfd_v syncsm_dns_resolver_epfd_v
7 #define perr_ns syncsm_dns_resolver_perr_ns
8 #define qtion_dump syncsm_dns_resolver_qtion_dump
9 #define rr_class_str syncsm_dns_resolver_rr_class_str
10 #define rr_type_str syncsm_dns_resolver_rr_type_str
11 #define timerfd_v syncsm_dns_resolver_timerfd_v
12 /******************************************************************************/
13 #else /* CLEANUP */
14 #undef epfd_v
15 #undef perr_ns
16 #undef qtion_dump
17 #undef rr_class_str
18 #undef rr_type_str
19 #undef timerfd_v
20 #endif
File dns/namespace/response.c added (mode: 100644) (index 0000000..0b401ab)
1 /*
2 * this code is protected by the GNU affero GPLv3 license
3 * author:Sylvain BERTRAND
4 */
5 #ifndef CLEANUP
6 #define addr_match_mx_exchange syncsm_dns_resp_c_addr_match_mx_exchange
7 #define addr_store_smtp_ip syncsm_dns_resp_c_addr_store_smtp_ip
8 #define additionals_parse syncsm_dns_resp_c_additionals_parse
9 #define answers_parse syncsm_dns_resp_c_answers_parse
10 #define authorities_parse syncsm_dns_resp_c_authorities_parse
11 #define basic_and_hdr_chks syncsm_dns_resp_c_basic_and_hdr_chks
12 #define hdr_info_chk syncsm_dns_resp_c_hdr_info_chk
13 #define is_addr syncsm_dns_resp_c_is_addr
14 #define mx_store syncsm_dns_resp_c_mx_store
15 #define qtion_chk syncsm_dns_resp_c_qtion_chk
16 #define qtions_parse syncsm_dns_resp_c_qtions_parse
17 #define rrs_parse syncsm_dns_resp_c_rrs_parse
18 /******************************************************************************/
19 #else /* CLEANUP */
20 #undef addr_match_mx_exchange
21 #undef addr_store_smtp_ip
22 #undef additionals_parse
23 #undef answers_parse
24 #undef authorities_parse
25 #undef basic_and_hdr_chks
26 #undef hdr_info_chk
27 #undef is_addr
28 #undef mx_store
29 #undef qtion_chk
30 #undef qtions_parse
31 #undef rrs_parse
32 #endif
File dns/namespace/response.h added (mode: 100644) (index 0000000..312f3e4)
1 /*
2 * this code is protected by the GNU affero GPLv3 license
3 * author:Sylvain BERTRAND
4 */
5 #ifndef CLEANUP
6 #define resp_an_collect_mx_ips syncsm_dns_resp_an_collect_mx_ips
7 #define resp_an_collect_canonical_dn_ips syncsm_dns_esp_an_collect_canonical_dn_ips
8 #define resp_ar_collect_mx_ips syncsm_dns_resp_ar_collect_mx_ips
9 #define resp_ar_collect_canonical_dn_ips syncsm_dns_resp_ar_collect_canonical_dn_ips
10 #define resp_basic_parse syncsm_dns_resp_basic_parse
11 #define resp_cname_rr_scan syncsm_dns_resp_cname_rr_scan
12 #define resp_mxs_scan syncsm_dns_resp_mxs_scan
13 /******************************************************************************/
14 #else /* CLEANUP */
15 #undef resp_an_collect_mx_ips
16 #undef resp_an_collect_canonical_dn_ips
17 #undef resp_ar_collect_mx_ips
18 #undef resp_ar_collect_canonical_dn_ips
19 #undef resp_basic_parse
20 #undef resp_cname_rr_scan
21 #undef resp_mxs_scan
22 #endif
File dns/namespace/state.h added (mode: 100644) (index 0000000..98e28b4)
1 /*
2 * this code is protected by the GNU affero GPLv3 license
3 * author:Sylvain BERTRAND
4 */
5 #ifndef CLEANUP
6 #define canonical_dn_v syncsm_dns_state_canonical_dn_v
7 #define canonical_dn_e_v syncsm_dns_state_canonical_dn_e_v
8 #define cname_rr_v syncsm_dns_state_cname_rr_v
9 #define dn_v syncsm_dns_state_dn_v
10 #define id_v syncsm_dns_state_id_v
11 #define mx_n syncsm_dns_state_mx_n
12 #define mxs_v syncsm_dns_state_mxs_v
13 #define mxs_n_v syncsm_dns_state_mxs_n_v
14 #define ns_v syncsm_dns_state_ns_v
15 #define nss_v syncsm_dns_state_nss_v
16 #define nss_n_v syncsm_dns_state_nss_n_v
17 #define qtion_dn_v syncsm_dns_state_qtion_dn_v
18 #define qtion_dn_e_v syncsm_dns_state_qtion_dn_e_v
19 #define qtion_type_v syncsm_dns_state_qtion_type_v
20 #define query_e_v syncsm_dns_state_query_e_v
21 #define query_qtion_e_v syncsm_dns_state_query_qtion_e_v
22 #define query_qtion_s_v syncsm_dns_state_query_qtion_s_v
23 #define query_qtion_sz_v syncsm_dns_state_query_qtion_sz_v
24 #define query_qtion_trailer_v syncsm_dns_state_query_qtion_trailer_v
25 #define query_sz_v syncsm_dns_state_query_sz_v
26 #define query_v syncsm_dns_state_query_v
27 #define resp_additionals_rrs_v syncsm_dns_state_resp_additionals_rrs_v
28 #define resp_additionals_s_v syncsm_dns_state_resp_additionals_s_v
29 #define resp_answers_rrs_v syncsm_dns_state_resp_answers_rrs_v
30 #define resp_answers_s_v syncsm_dns_state_resp_answers_s_v
31 #define resp_authorities_rrs_v syncsm_dns_state_resp_authorities_rrs_v
32 #define resp_authorities_s_v syncsm_dns_state_resp_authorities_s_v
33 #define resp_e_v syncsm_dns_state_resp_e_v
34 #define resp_qtion_t syncsm_dns_state_resp_qtion_t
35 #define resp_qtion_v syncsm_dns_state_resp_qtion_v
36 #define resp_qtions_s_v syncsm_dns_state_resp_qtions_s_v
37 #define resp_sz_v syncsm_dns_state_resp_sz_v
38 #define resp_v syncsm_dns_state_resp_v
39 #define rr_t syncsm_dns_state_rr_t
40 #define rrs_n_max syncsm_dns_state_rrs_n_max
41 /******************************************************************************/
42 #else /* CLEANUP */
43 #undef canonical_dn_v
44 #undef canonical_dn_e_v
45 #undef cname_rr_v
46 #undef dn_v
47 #undef id_v
48 #undef mx_n
49 #undef mxs_v
50 #undef mxs_n_v
51 #undef ns_v
52 #undef nss_v
53 #undef nss_n_v
54 #undef qtion_dn_v
55 #undef qtion_dn_e_v
56 #undef qtion_type_v
57 #undef query_e_v
58 #undef query_qtion_e_v
59 #undef query_qtion_s_v
60 #undef query_qtion_sz_v
61 #undef query_qtion_trailer_v
62 #undef query_sz_v
63 #undef query_v
64 #undef resp_additionals_rrs_v
65 #undef resp_additionals_s_v
66 #undef resp_answers_rrs_v
67 #undef resp_answers_s_v
68 #undef resp_authorities_rrs_v
69 #undef resp_authorities_s_v
70 #undef resp_e_v
71 #undef resp_qtion_t
72 #undef resp_qtion_v
73 #undef resp_qtions_s_v
74 #undef resp_sz_v
75 #undef resp_v
76 #undef rr_t
77 #undef rrs_n_max
78 #endif
File dns/query.c added (mode: 100644) (index 0000000..128d4b3)
1 #ifndef SYNCSM_DNS_QUERY_C
2 #define SYNCSM_DNS_QUERY_C
3 /*
4 * this code is protected by the GNU affero GPLv3 license
5 * author:Sylvain BERTRAND
6 */
7 /*----------------------------------------------------------------------------*/
8 /* compiler stuff */
9 #include <stdbool.h>
10 #include <stdarg.h>
11 /*----------------------------------------------------------------------------*/
12 #include "config.h"
13 /*----------------------------------------------------------------------------*/
14 #include "ulinux.h"
15 /*----------------------------------------------------------------------------*/
16 #include "dns/rfc.h"
17 #include "smtp/rfc.h"
18 /*----------------------------------------------------------------------------*/
19 #include "perr.h"
20 #include "syncsm.h"
21 /*----------------------------------------------------------------------------*/
22 #include "dns/state.h"
23 #include "dns/resolver.h"
24 /*============================================================================*/
25 #include "namespace/ulinux.h"
26 #include "dns/namespace/resolver.h"
27 #include "dns/namespace/state.h"
28 #include "dns/namespace/query.h"
29 /*----------------------------------------------------------------------------*/
30 /* exported in query.h */
31 static void query_build(void)
32 {
33 struct dns_rfc_hdr_t *hdr;
34 u8 *name;
35 u8 name_sz;
36 /*-------------------------------------------------------------------*/
37 hdr = (struct dns_rfc_hdr_t*)query_v;
38
39 memset(hdr, 0, sizeof(*hdr));
40 hdr->id = id_v; /* we don't care about the endian */
41 ++id_v;
42
43 /*
44 * many dns servers out there supports _only_ recursive queries,
45 * which should have been the default and only choice since the
46 * beginning for clients
47 */
48 hdr->info |= cpu_to_be16(DNS_RFC_HDR_INFO_RD_BIT);
49
50 hdr->qdcount = cpu_to_be16(1); /* one mx question */
51 /*-------------------------------------------------------------------*/
52 /* right after the header is our question */
53 query_qtion_s_v = &query_v[sizeof(*hdr)];
54 name = query_qtion_s_v;
55
56 name_sz = (u8)(qtion_dn_e_v - qtion_dn_v);
57
58 memcpy(name, qtion_dn_v, name_sz);
59 /*-------------------------------------------------------------------*/
60 query_qtion_trailer_v = (struct dns_rfc_qtion_trailer_t*)(name
61 + name_sz);
62 query_qtion_trailer_v->type = cpu_to_be16(qtion_type_v);
63 query_qtion_trailer_v->class = cpu_to_be16(DNS_RFC_RR_CLASS_IN);
64 /*-------------------------------------------------------------------*/
65 query_qtion_e_v = (u8*)query_qtion_trailer_v
66 + sizeof(*query_qtion_trailer_v);
67 query_qtion_sz_v = (u16)(query_qtion_e_v - query_qtion_s_v);
68
69 query_e_v = query_qtion_e_v; /* 1 question, then same size */
70 query_sz_v = (u16)(query_qtion_e_v - query_v);
71
72 PERR("1:DNS:built question follows:\n");
73 qtion_dump(query_qtion_s_v, query_v, query_e_v);
74 PERR("1:DNS:QUERY:[0x%p-0x%p]\n", query_v, query_e_v - 1);
75 }
76 /*----------------------------------------------------------------------------*/
77 #define CLEANUP
78 #include "namespace/ulinux.h"
79 #include "dns/namespace/resolver.h"
80 #include "dns/namespace/state.h"
81 #include "dns/namespace/query.h"
82 #undef CLEANUP
83 #endif
File dns/query.h added (mode: 100644) (index 0000000..0723493)
1 #ifndef SYNCSM_DNS_QUERY_H
2 #define SYNCSM_DNS_QUERY_H
3 #include "dns/namespace/query.h"
4 /*
5 * this code is protected by the GNU affero GPLv3 license
6 * author:Sylvain BERTRAND
7 */
8 static void query_build(void);
9 #define CLEANUP
10 #include "dns/namespace/query.h"
11 #undef CLEANUP
12 #endif
File dns/resolv_conf.c added (mode: 100644) (index 0000000..c067b7e)
1 #ifndef SYNCSM_DNS_RESOLV_CONF_C
2 #define SYNCSM_DNS_RESOLV_CONF_C
3 #include <stdbool.h>
4 #include <stdarg.h>
5 /*----------------------------------------------------------------------------*/
6 #include "config.h"
7 /*----------------------------------------------------------------------------*/
8 #include "ulinux.h"
9 /*----------------------------------------------------------------------------*/
10 #include "dns/rfc.h"
11 #include "smtp/rfc.h"
12 /*----------------------------------------------------------------------------*/
13 #include "perr.h"
14 #include "syncsm.h"
15 #include "dns/state.h"
16 #include "dns/resolver.h"
17 /*============================================================================*/
18 #include "namespace/ulinux.h"
19 #include "namespace/syncsm.h"
20 #include "dns/namespace/state.h"
21 #include "dns/namespace/resolver.h"
22 #include "dns/namespace/resolv_conf.h"
23 #include "dns/namespace/resolv_conf.c"
24 /*----------------------------------------------------------------------------*/
25 static u8 resolv_conf[CONFIG_BUFSIZ];
26 static u64 resolv_conf_sz;
27 /*----------------------------------------------------------------------------*/
28 /*
29 * on entry, e point either on the byte paste the last resolve.conf byte
30 * or the end of line mark, namely '\n'.
31 * in other words, e points past one byte the last valid line char.
32 */
33 static void parse_line(u8 line, u8 *s, u8 *e)
34 {
35 u8 *c;
36 u8 *ipvx_s; /* first ipvx char */
37 u8 *ipvx_l; /* last ipvx char */
38
39 c = s;
40 /* locate first non-space char */
41 loop {
42 if (c == e)
43 return;
44
45 if (!is_space(*c)) /* does include '\n' */
46 break;
47 ++c;
48 }
49
50 if (*c == '#' || *c == ';') /* this is a comment line */
51 return;
52
53 if ((e - c) < CSTRLEN("nameserver")) {
54 /* no room for a nameserver keyword */
55 return;
56 }
57
58 if (!memcmp(c, "nameserver", CSTRLEN("nameserver"))) {
59 /* not a nameserver keyword */
60 return;
61 }
62
63 /* we have a nameserver keyword, skip spaces */
64 c += CSTRLEN("nameserver");
65 loop {
66 if (c == e) {
67 PERR("0:DNS:RESOLV_CONF:ERROR:\"%s\":line %d:missing ip address of nameserver keyword\n", CONFIG_RESOLV_CONF_PATH, line);
68 exit(1);
69 }
70
71 if (!is_space(*c))
72 break;
73 ++c;
74 }
75
76 /* then we should have a ipvx address */
77 ipvx_s = c;
78
79 /* locate the end of the ipvx address */
80 loop {
81 if (c == e || is_space(*c))
82 break;
83 ++c;
84 }
85 ipvx_l = c - 1;
86
87 /* oops ! */
88 if (nss_n_v == CONFIG_DNS_NSS_N_MAX) {
89 PERR("0:DNS:RESOLV_CONF:ERROR:\"%s\":no more room for dns servers (max is %u)\n", CONFIG_RESOLV_CONF_PATH, CONFIG_DNS_NSS_N_MAX);
90 exit(1);
91 }
92
93 #ifdef CONFIG_DNS_IPV4
94 if (to_ipv4_blk(&nss_v[nss_n_v].ipv4_net, ipvx_s, ipvx_l)) {
95 nss_v[nss_n_v].type = ipv4;
96 ++nss_n_v;
97 return;
98 }
99 #endif
100 if (to_ipv6_blk(nss_v[nss_n_v].ipv6_net, ipvx_s, ipvx_l)) {
101 nss_v[nss_n_v].type = ipv6;
102 ++nss_n_v;
103 return;
104 }
105 #ifdef CONFIG_DNS_IPV4
106 PERR("0:DNS:RESOLV_CONF:\"%s\":line %d:ip address is not v4 or v6:\"%.*s\"\n", CONFIG_RESOLV_CONF_PATH, line, ipvx_l - ipvx_s + 1, ipvx_s);
107 #endif
108 PERR("0:DNS:RESOLV_CONF:\"%s\":line %d:ip address is not ipv6:\"%.*s\"\n", CONFIG_RESOLV_CONF_PATH, line, ipvx_l - ipvx_s + 1, ipvx_s);
109 }
110 /******************************************************************************/
111 /* exported in resolv_conf.h */
112 static void resolv_conf_parse(void)
113 {
114 u8 line;
115 u8 *line_s;
116 u8 *line_e;
117 u8 *file_e;
118 u8 i;
119
120 nss_n_v = 0;
121 if (resolv_conf_sz == 0) {
122 PERR("0:DNS:RESOLV_CONF:\"%s\" is empty, nothing to parse\n", CONFIG_RESOLV_CONF_PATH);
123 return;
124 }
125 /*--------------------------------------------------------------------*/
126 /* parse lines */
127 file_e = resolv_conf + resolv_conf_sz;
128 line_s = resolv_conf;
129 line_e = resolv_conf;
130
131 line = 1;
132 loop {
133 /* locate the end of the line */
134 loop {
135 if (line_e == file_e || *line_e == '\n')
136 break;
137 ++line_e;
138 };
139
140 parse_line(line, line_s, line_e);
141
142 if (line_e == file_e)
143 break;
144
145 line_s = line_e + 1;
146 line_e = line_s;
147 ++line;
148 }
149 /*--------------------------------------------------------------------*/
150 /* tell the user */
151 PERR("0:DNS:RESOLV_CONF:\"%s\" configured %d name server(s)\n", CONFIG_RESOLV_CONF_PATH, nss_n_v);
152 i = 0;
153 loop {
154 if (i == nss_n_v)
155 break;
156 perr_ns(0, "DNS:RESOLV_CONF", i);
157 ++i;
158 }
159 }
160
161 static void resolv_conf_read(void)
162 {
163 sl r;
164 si fd;
165 struct stat s;
166
167 r = openat(AT_CWD, CONFIG_RESOLV_CONF_PATH, O_NONBLOCK, O_RD_ONLY);
168 if (ISERR(r)) {
169 PERR("0:DNS:RESOLV_CONF:ERROR:unable to open resolv.conf file \"%s\"\n", CONFIG_RESOLV_CONF_PATH);
170 exit(1);
171 }
172
173 fd = (si)r;
174
175 r = fstat(fd, &s);
176 if (s.size > CONFIG_BUFSIZ) {
177 PERR("0:DNS:RESOLV_CONF:ERROR:resolv.conf is %ld bytes and cannot fit into the buffer of %d bytes\n", s.size, CONFIG_BUFSIZ);
178 exit(1);
179 }
180
181 resolv_conf_sz = 0;
182 loop {
183 r = read(fd, resolv_conf + resolv_conf_sz, s.size);
184 if (ISERR(r)) {
185 if (r == -EAGAIN || r == -EINTR)
186 continue;
187 PERR("0:DNS:RESOLV_CONF:ERROR:%ld:reading \"%s\"\n", r, CONFIG_RESOLV_CONF_PATH);
188 exit(1);
189 }
190 if (r == 0) /* end of file */
191 break;
192 resolv_conf_sz += (u64)r;
193 }
194 PERR("0:DNS:RESOLV_CONF:read %ld bytes from \"%s\"\n", resolv_conf_sz, CONFIG_RESOLV_CONF_PATH);
195 close(fd);
196 }
197 /*----------------------------------------------------------------------------*/
198 #define CLEANUP
199 #include "namespace/ulinux.h"
200 #include "namespace/syncsm.h"
201 #include "dns/namespace/state.h"
202 #include "dns/namespace/resolver.h"
203 #include "dns/namespace/resolv_conf.h"
204 #undef CLEANUP
205 #endif
File dns/resolv_conf.h added (mode: 100644) (index 0000000..7b024f4)
1 #ifndef SYNCSM_DNS_RESOLV_CONF_H
2 #define SYNCSM_DNS_RESOLV_CONF_H
3 #include "dns/namespace/resolv_conf.h"
4 /*
5 * this code is protected by the GNU affero GPLv3 license
6 * author:Sylvain BERTRAND
7 */
8 static void resolv_conf_parse(void);
9 static void resolv_conf_read(void);
10 #define CLEANUP
11 #include "dns/namespace/resolv_conf.h"
12 #undef CLEANUP
13 #endif
File dns/resolver.c added (mode: 100644) (index 0000000..793178a)
1 #ifndef SYNCSM_DNS_RESOLVER_C
2 #define SYNCSM_DNS_RESOLVER_C
3 /*
4 * this code is protected by the GNU affero GPLv3 license
5 * author:Sylvain BERTRAND
6 */
7 /* compiler stuff */
8 #include <stdbool.h>
9 #include <stdarg.h>
10 /*----------------------------------------------------------------------------*/
11 #include "config.h"
12 /*----------------------------------------------------------------------------*/
13 #include "ulinux.h"
14 /*----------------------------------------------------------------------------*/
15 #include "dns/rfc.h"
16 #include "smtp/rfc.h"
17 /*----------------------------------------------------------------------------*/
18 #include "perr.h"
19 #include "syncsm.h"
20 /*----------------------------------------------------------------------------*/
21 #include "dns/state.h"
22 #include "dns/resolver.h"
23 #include "dns/ipv4.h"
24 #include "dns/ipv6.h"
25 #include "dns/query.h"
26 #include "dns/response.h"
27 #include "dns/name.h"
28 #include "dns/resolv_conf.h"
29 /*============================================================================*/
30 #include "namespace/ulinux.h"
31 #include "namespace/syncsm.h"
32 #include "namespace/dns.h"
33 #include "dns/namespace/state.h"
34 #include "dns/namespace/resolver.h"
35 #include "dns/namespace/ipv4.h"
36 #include "dns/namespace/ipv6.h"
37 #include "dns/namespace/query.h"
38 #include "dns/namespace/response.h"
39 #include "dns/namespace/name.h"
40 #include "dns/namespace/resolv_conf.h"
41 #include "dns/namespace/resolver.c"
42 /*----------------------------------------------------------------------------*/
43 static void udp_so_setup(void)
44 {
45 #ifdef CONFIG_DNS_IPV4
46 ipv4_udp_so_setup();
47 #endif
48 ipv6_udp_so_setup();
49 }
50
51 static void timer_setup(void)
52 {
53 sl r;
54 struct epoll_event evts;
55
56 r = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
57 if (ISERR(r)) {
58 PERR("0:DNS:ERROR:%ld:unable to create the timer file descriptor\n", r);
59 exit(1);
60 }
61 timerfd_v = (si)r;
62
63 /* add the timerfd to the epollfd */
64 memset(&evts, 0, sizeof(evts));
65 /* could be EPOLLET since we deal only with 1 expiration */
66 evts.events = EPOLLIN;
67 evts.data.fd = timerfd_v;
68 r = epoll_ctl(epfd_v, EPOLL_CTL_ADD, timerfd_v, &evts);
69 if (ISERR(r)) {
70 PERR("0:DNS:ERROR:%ld:unable to add the timer file descriptor to the epoll file descriptor\n", r);
71 exit(1);
72 }
73 }
74
75 static void ns_timer_start(void)
76 {
77 sl r;
78 struct itimerspec itimerspec;
79
80 memset(&itimerspec, 0, sizeof(itimerspec));
81
82 /* initial expiration in the futur of current monotonic clock */
83 itimerspec.value.sec = CONFIG_DNS_NS_RESP_WAIT_TIME_SEC;
84 itimerspec.value.nsec = CONFIG_DNS_NS_RESP_WAIT_TIME_NSEC;
85
86 /* relative initial expiration */
87 r = timerfd_settime(timerfd_v, 0, &itimerspec, 0);
88 if (ISERR(r)) {
89 PERR("0:DNS:ERROR:%ld:unable to arm the name server response timer for %lu sec and %lu nanosec\n", r, CONFIG_DNS_NS_RESP_WAIT_TIME_SEC, CONFIG_DNS_NS_RESP_WAIT_TIME_NSEC);
90 exit(1);
91 }
92 }
93
94 /******************************************************************************/
95 /* exported in resolver.h */
96 static void perr_ns(u8 lvl, u8 *hdr_str, u8 i)
97 {
98 PERR("%u:%s:NAME_SERVER[%d]:", lvl, hdr_str, i);
99 #ifdef CONFIG_DNS_IPV4
100 switch (nss_v[i].type) {
101 case ipv4:
102 PERR("IPV4:0x%08x\n", be32_to_cpu(nss_v[i].ipv4_net));
103 break;
104 case ipv6:
105 #endif
106 PERR("IPV6:0x%016lx%016lx\n", be64_to_cpu(nss_v[i].ipv6_net_h), be64_to_cpu(nss_v[i].ipv6_net_l));
107 #ifdef CONFIG_DNS_IPV4
108 break;
109 }
110 #endif
111 }
112
113 static u8 *rr_type_str(u16 type)
114 {
115 switch (type) {
116 case DNS_RFC_RR_TYPE_A:
117 return "A";
118 case DNS_RFC_RR_TYPE_NS:
119 return "NS";
120 case DNS_RFC_RR_TYPE_MD:
121 return "MD";
122 case DNS_RFC_RR_TYPE_MF:
123 return "MF";
124 case DNS_RFC_RR_TYPE_CNAME:
125 return "CNAME";
126 case DNS_RFC_RR_TYPE_SOA:
127 return "SOA";
128 case DNS_RFC_RR_TYPE_MB:
129 return "MB";
130 case DNS_RFC_RR_TYPE_MG:
131 return "MG";
132 case DNS_RFC_RR_TYPE_MR:
133 return "MR";
134 case DNS_RFC_RR_TYPE_NULL:
135 return "NULL";
136 case DNS_RFC_RR_TYPE_WKS:
137 return "WKS";
138 case DNS_RFC_RR_TYPE_PTR:
139 return "PTR";
140 case DNS_RFC_RR_TYPE_HINFO:
141 return "HINFO";
142 case DNS_RFC_RR_TYPE_MINFO:
143 return "MINFO";
144 case DNS_RFC_RR_TYPE_MX:
145 return "MX";
146 case DNS_RFC_RR_TYPE_TXT:
147 return "TXT";
148 case DNS_RFC_RR_TYPE_AAAA:
149 return "AAAA";
150 default:
151 return "UNKNOWN";
152 }
153 }
154
155 static u8 *rr_class_str(u16 class)
156 {
157 switch (class) {
158 case DNS_RFC_RR_CLASS_IN:
159 return "IN";
160 case DNS_RFC_RR_CLASS_CN:
161 return "CN";
162 case DNS_RFC_RR_CLASS_CH:
163 return "CH";
164 case DNS_RFC_RR_CLASS_HS:
165 return "HS";
166 default:
167 return "UNKNOWN";
168 }
169 }
170
171 static bool qtion_dump(u8 *qtion, u8 *msg_s, u8 *msg_e)
172 {
173 struct dns_rfc_qtion_trailer_t *trailer;
174 u8* trailer_l;
175
176 PERR("1:DNS:QUESTION_DUMP:START:0x%p\n", qtion);
177
178 name_dump(qtion, msg_s, msg_e);
179
180 trailer = name_skip(qtion, msg_s, msg_e);
181
182 trailer_l = (u8*)trailer + sizeof(*trailer) - 1;
183 if (trailer_l >= msg_e) {
184 PERR("0:DNS:QUESTION_DUMP:ERROR:question trailer is going out of bounds\n");
185 return false;
186 }
187 PERR("1:DNS:QUESTION_DUMP:type=%s(0x%04x)\n", rr_type_str(be16_to_cpu(trailer->type)), be16_to_cpu(trailer->type));
188 PERR("1:DNS:QUESTION_DUMP:class=%s(0x%04x)\n", rr_class_str(be16_to_cpu(trailer->class)), be16_to_cpu(trailer->class));
189 PERR("1:DNS:QUESTION_DUMP:END\n");
190 return true;
191 }
192
193 static bool ns_net_ask(void)
194 {
195 sl r;
196
197 ns_timer_start();
198
199 #ifdef CONFIG_DNS_IPV4
200 if (nss_v[ns_v].type == ipv4)
201 return ipv4_ns();
202 #endif
203 return ipv6_ns();
204 }
205
206 static bool ns_ask(void)
207 {
208 bool r;
209
210 r = true;
211
212 PERR("1:DNS:********************************************************************************\n");
213 perr_ns(1, "DNS:RESOLVER", ns_v);
214 if (!ns_net_ask()) {
215 r = false;
216 goto exit;
217 }
218
219 if (!resp_basic_parse()) {
220 r = false;
221 goto exit;
222 }
223 exit:
224 PERR("1:DNS:********************************************************************************\n");
225 return r;
226 }
227
228 static void nss_ask(void)
229 {
230 ns_v = 0;
231 loop {
232 if (ns_v == nss_n_v) {
233 PERR("0:DNS:ERROR:\"%.*s\":no name server was able to give us a proper basic response for the current query\n", dn_v->dn.l - dn_v->dn.s + 1, dn_v->dn.s);
234 exit(1);
235 }
236
237 if (ns_ask())
238 break; /* got a basic response */
239 ++ns_v;
240 }
241 }
242
243 #ifdef CONFIG_SMTP_IPV4
244 /* XXX: only if no ips were provided in the initial response */
245 static void mx_ipv4_collect_from_net(struct mx_t *mx)
246 {
247 PERR("1:DNS:MX:A query on:\n");
248 name_dump(mx->exchange, mx->exchange, mx->exchange
249 + DNS_RFC_NAME_SZ_MAX);
250 qtion_type_v = DNS_RFC_RR_TYPE_A;
251 query_build();
252
253 nss_ask();
254
255 resp_an_collect_mx_ips(mx);
256 }
257 #endif
258
259 /* XXX: only if no ips were provided in the initial response */
260 static void mx_ipv6_collect_from_net(struct mx_t *mx)
261 {
262 PERR("1:DNS:MX:AAAA query on:\n");
263 name_dump(mx->exchange, mx->exchange, mx->exchange
264 + DNS_RFC_NAME_SZ_MAX);
265 qtion_type_v = DNS_RFC_RR_TYPE_AAAA;
266 query_build();
267
268 nss_ask();
269
270 resp_an_collect_mx_ips(mx);
271 }
272
273 /* XXX: only if no ips were provided in the initial response */
274 static void mx_ips_collect_from_net(struct mx_t *mx)
275 {
276 /* prepare the question name */
277 qtion_dn_e_v = name_cpy(qtion_dn_v, mx->exchange,
278 mx->exchange, mx->exchange + DNS_RFC_NAME_SZ_MAX);
279 #ifdef CONFIG_SMTP_IPV4
280 mx_ipv4_collect_from_net(mx);
281 #endif
282 mx_ipv6_collect_from_net(mx);
283 }
284
285 /* XXX: only if no ips were provided in the initial response */
286 static void mxs_ips_collect_from_net(void)
287 {
288 u16 i;
289 i = 0;
290 loop {
291 struct mx_t *mx;
292
293 if (i == mxs_n_v)
294 break;
295
296 mx = &mxs_v[i];
297
298 mx_ips_collect_from_net(mx);
299
300 ++i;
301 };
302 }
303
304 static void mxs_ips_collect_from_resp_ar(void)
305 {
306 u16 i;
307 i = 0;
308 loop {
309 struct mx_t *mx;
310
311 if (i == mxs_n_v)
312 break;
313
314 mx = &mxs_v[i];
315
316 resp_ar_collect_mx_ips(mx);
317
318 ++i;
319 };
320 }
321
322 static void mxs_ips_collect(void)
323 {
324 mxs_ips_collect_from_resp_ar();
325 if (dn_v->smtp_ips_n == 0)
326 mxs_ips_collect_from_net();
327 }
328
329 static s8 mx_cmp(void *a, void *b)
330 {
331 struct mx_t *a_mx;
332 struct mx_t *b_mx;
333
334 a_mx = a;
335 b_mx = b;
336 if (a_mx->preference < b_mx->preference)
337 return QSORT_CMP_LT;
338 else if (a_mx->preference == b_mx->preference)
339 return QSORT_CMP_EQ;
340 else if (a_mx->preference > b_mx->preference)
341 return QSORT_CMP_GT;
342 }
343
344 #ifdef CONFIG_SMTP_IPV4
345 static void canonical_dn_ipv4_collect_from_net(void)
346 {
347 PERR("1:DNS:CANONICAL_DOMAIN_NAME:A query on:\n");
348 qtion_type_v = DNS_RFC_RR_TYPE_A;
349 query_build();
350
351 nss_ask();
352
353 resp_an_collect_canonical_dn_ips();
354 }
355 #endif
356
357 static void canonical_dn_ipv6_collect_from_net(void)
358 {
359 PERR("1:DNS:CANONICAL_DOMAIN_NAME:AAAA query on:\n");
360 qtion_type_v = DNS_RFC_RR_TYPE_AAAA;
361 query_build();
362
363 nss_ask();
364
365 resp_an_collect_canonical_dn_ips();
366 }
367
368 static void canonical_dn_ips_collect_from_net(void)
369 {
370 /* prepare the question name */
371 qtion_dn_e_v = name_cpy(qtion_dn_v, canonical_dn_v, canonical_dn_v,
372 canonical_dn_e_v);
373 #ifdef CONFIG_SMTP_IPV4
374 canonical_dn_ipv4_collect_from_net();
375 #endif
376 canonical_dn_ipv6_collect_from_net();
377 }
378
379 static void canonical_dn_ips_collect(void)
380 {
381 resp_ar_collect_canonical_dn_ips();
382
383 if (dn_v->smtp_ips_n == 0)
384 canonical_dn_ips_collect_from_net();
385 }
386
387 static void dump_dn_ips(void)
388 {
389 u8 i;
390
391 PERR("0:DNS:****************************************************************************\n");
392 PERR("0:DNS:\"%.*s\":list of smtp ips\n", dn_v->dn.l - dn_v->dn.s + 1, dn_v->dn.s);
393
394 i = 0;
395 loop {
396 struct ip_t *ip;
397
398 if (i == dn_v->smtp_ips_n)
399 break;
400
401 PERR("DNS:----------------------------------------------------------------------------\n");
402
403 ip = &dn_v->smtp_ips[i];
404
405 #ifdef CONFIG_SMTP_IPV4
406 if (ip->type == ipv4) {
407 PERR("0:DNS:IPV4:0x%08lx\n", be32_to_cpu(ip->ipv4_net));
408 } else {
409 #endif
410 PERR("0:DNS:IPV6:0x%016lx%016lx\n", be64_to_cpu(ip->ipv6_net_h), be64_to_cpu(ip->ipv6_net_l));
411 #ifdef CONFIG_SMTP_IPV4
412 }
413 #endif
414
415 ++i;
416 }
417
418 PERR("0:DNS:****************************************************************************\n");
419 }
420
421 static void dump_mxs_pref(void)
422 {
423 u8 i;
424
425 PERR("1:DNS:****************************************************************************\n");
426 PERR("1:DNS:\"%.*s\":preference of mxs\n", dn_v->dn.l - dn_v->dn.s + 1, dn_v->dn.s);
427 loop {
428 if (i == mxs_n_v)
429 break;
430 PERR("1:DNS:\"%.*s\":mx[%u]:%u\n", dn_v->dn.l - dn_v->dn.s + 1, dn_v->dn.s, i, mxs_v[i].preference);
431 ++i;
432 }
433 PERR("1:DNS:****************************************************************************\n");
434 }
435
436
437 /* per domain name */
438 static void resolver(void)
439 {
440 u8 *cname;
441 /*
442 * high level resolver strategy.
443 * READ DNS.TXT IN THIS DIRECTORY.
444 * we diverge from dns.txt since we go query mx exchange a/aaaa only
445 * if, globally, we do not have already smtp ips.
446 */
447 PERR("DNS:\"%.*s\":MX query\n", dn_v->dn.l - dn_v->dn.s + 1, dn_v->dn.s);
448 qtion_dn_e_v = name_build(qtion_dn_v, &dn_v->dn);
449 qtion_type_v = DNS_RFC_RR_TYPE_MX;
450 query_build();
451
452 nss_ask();
453
454 /* select the proper canonical domain name */
455 if(resp_cname_rr_scan()) {
456 PERR("1:DNS:CANONICAL_NAME:mail domain name was an alias, provided canonical name follows:\n");
457 cname = cname_rr_v->part->rdata; /* alias case */
458 } else {
459 PERR("1:DNS:CANONICAL_NAME:question mail domain name is the canonical name, which is:\n");
460 cname = resp_qtion_v.name; /* direct case */
461 }
462 canonical_dn_e_v = name_cpy(canonical_dn_v, cname, resp_v,
463 resp_e_v);
464 name_dump(canonical_dn_v, canonical_dn_v, canonical_dn_v
465 + DNS_RFC_NAME_SZ_MAX);
466
467 resp_mxs_scan();
468 qsort(mxs_v, mxs_n_v, sizeof(struct mx_t), mx_cmp);
469 dump_mxs_pref();
470
471 /* time to collect some smtp ips */
472
473 dn_v->smtp_ips_n = 0;
474
475 if (mxs_n_v != 0)
476 mxs_ips_collect();
477 else {
478 canonical_dn_ips_collect();
479 if (dn_v->smtp_ips_n == 0) {
480 PERR("0:DNS:\"%.*s\":ERROR:unable to get smtp ips\n", dn_v->dn.l - dn_v->dn.s + 1, dn_v->dn.s);
481 exit(1);
482 }
483 }
484
485 dump_dn_ips();
486 }
487
488 /******************************************************************************/
489 /* exported in dns.h */
490 /* we perform all dns resolution there, all domains before sending any email */
491 static void dns_resolver(void)
492 {
493 u64 i = 0;
494 loop {
495 struct dn_al_t *d;
496
497 if (i == dn_al_n_v)
498 break;
499
500 d = (struct dn_al_t*)&dn_al_v[i];
501
502 if (d->type == domain_name) {
503 PERR("1:DNS:RESOLVER:\"%.*s\"\n", d->dn.l - d->dn.s + 1, d->dn.s);
504
505 dn_v = d; /* set the targetted domain name */
506 resolver();
507 }
508 ++i;
509 }
510 }
511
512 static void dns_init(void)
513 {
514 sl r;
515
516 resolv_conf_read();
517 resolv_conf_parse();
518
519 r = epoll_create1(0);
520 if (ISERR(r)) {
521 PERR("0:DNS:ERROR:%ld:unable to create the epoll file descriptor\n", r);
522 exit(1);
523 }
524 epfd_v = (si)r;
525
526 timer_setup();
527 udp_so_setup();
528
529 /* our id counter */
530 id_v = 0;
531 }
532 /*----------------------------------------------------------------------------*/
533 #define CLEANUP
534 #include "namespace/ulinux.h"
535 #include "namespace/syncsm.h"
536 #include "namespace/dns.h"
537 #include "dns/namespace/state.h"
538 #include "dns/namespace/resolver.h"
539 #include "dns/namespace/ipv4.h"
540 #include "dns/namespace/ipv6.h"
541 #include "dns/namespace/query.h"
542 #include "dns/namespace/response.h"
543 #include "dns/namespace/name.h"
544 #include "dns/namespace/resolv_conf.h"
545 #include "dns/namespace/resolver.c"
546 #undef CLEANUP
547 #endif
File dns/resolver.h added (mode: 100644) (index 0000000..2858f25)
1 #ifndef SYNCSM_DNS_RESOLVER_H
2 #define SYNCSM_DNS_RESOLVER_H
3 #include "namespace/ulinux.h"
4 #include "dns/namespace/resolver.h"
5 /*
6 * this code is protected by the GNU affero GPLv3 license
7 * author:Sylvain BERTRAND
8 */
9 static si epfd_v;
10 static si timerfd_v;
11 static bool qtion_dump(u8 *question, u8 *msg_s, u8 *msg_e);
12 static u8 *rr_class_str(u16 class);
13 static u8 *rr_type_str(u16 type);
14 static void perr_ns(u8 lvl, u8 *hdr_str, u8 i);
15 #define CLEANUP
16 #include "namespace/ulinux.h"
17 #include "dns/namespace/resolver.h"
18 #undef CLEANUP
19 #endif
File dns/response.c added (mode: 100644) (index 0000000..44859f3)
1 #ifndef SYNCSM_DNS_RESPONSE_C
2 #define SYNCSM_DNS_RESPONSE_C
3 /*
4 * this code is protected by the GNU affero GPLv3 license
5 * author:Sylvain BERTRAND
6 */
7 /*
8 * STRATEGY: once a severely malformed dns response is detected, the program
9 * will exit.
10 * do bound checking only right before memory access, because it is expensive.
11 */
12 /*----------------------------------------------------------------------------*/
13 /* compiler stuff */
14 #include <stdbool.h>
15 #include <stdarg.h>
16 /*----------------------------------------------------------------------------*/
17 #include "config.h"
18 /*----------------------------------------------------------------------------*/
19 #include "ulinux.h"
20 /*----------------------------------------------------------------------------*/
21 #include "dns/rfc.h"
22 #include "smtp/rfc.h"
23 /*----------------------------------------------------------------------------*/
24 #include "perr.h"
25 #include "syncsm.h"
26 /*----------------------------------------------------------------------------*/
27 #include "dns/state.h"
28 #include "dns/resolver.h"
29 #include "dns/name.h"
30 /*============================================================================*/
31 #include "namespace/ulinux.h"
32 #include "namespace/syncsm.h"
33 #include "dns/namespace/state.h"
34 #include "dns/namespace/resolver.h"
35 #include "dns/namespace/name.h"
36 #include "dns/namespace/response.h"
37 #include "dns/namespace/response.c"
38 /*----------------------------------------------------------------------------*/
39 /* will store the pointer on the byte right after the last byte */
40 static bool rrs_parse(u8 **e, struct rr_t *rrs , u8 *s, u16 n)
41 {
42 u8 *c;
43 u16 i;
44
45 c = s;
46 i = 0;
47 loop {
48 u16 cpu_rdlength;
49
50 if (i == n)
51 break;
52
53 PERR("1:DNS:RESPONSE:RR[%u]:START\n", i);
54
55 rrs->name = c;
56 name_dump(c, resp_v, resp_e_v);
57
58 rrs->part = name_skip(c, resp_v, resp_e_v);
59 PERR("1:DNS:RESPONSE:RR[%u]:FIELDS:0x%p\n", i, rrs->part);
60
61 c = (u8*)rrs->part + sizeof(*(rrs->part));
62
63 if (c >= resp_e_v) {
64 PERR("1:DNS:RESPONSE:RR[%u]:WARNING:middle fields goes out of bounds, trying next name server\n", i);
65 return false;
66 }
67 PERR("1:DNS:RESPONSE:RR[%u]:FIELDS:TYPE:%s\n", i, rr_type_str(be16_to_cpu(rrs->part->type)));
68 PERR("1:DNS:RESPONSE:RR[%u]:FIELDS:CLASS:%s\n", i, rr_class_str(be16_to_cpu(rrs->part->class)));
69 PERR("1:DNS:RESPONSE:RR[%u]:FIELDS:TTL:%d\n", i, be32_to_cpu(rrs->part->ttl));
70 cpu_rdlength = be16_to_cpu(rrs->part->rdlength);
71 PERR("1:DNS:RESPONSE:RR[%u]:FIELDS:RDLENGTH:0x%x\n", i, cpu_rdlength);
72
73 c += cpu_rdlength;
74 PERR("1:DNS:RESPONSE:RR[%u]:END\n", i);
75 ++rrs;
76 ++i;
77 }
78 *e = c;
79 return true;
80 }
81
82 static bool additionals_parse(void)
83 {
84 struct dns_rfc_hdr_t *hdr;
85 u16 cpu_arcount;
86 u8 *additionals_e;
87 bool r;
88
89 r = true;
90 hdr = (struct dns_rfc_hdr_t*)resp_v;
91 cpu_arcount = be16_to_cpu(hdr->arcount);
92
93 PERR("1:DNS:RESPONSE:ADDITIONAL_SECTION:START\n");
94
95 if (cpu_arcount > rrs_n_max) {
96 PERR("0:DNS:RESPONSE:ADDITIONAL_SECTION:ERROR:too many additional resource record(s) %u, max is %u\n", cpu_arcount, rrs_n_max);
97 exit(1);
98 }
99 PERR("1:DNS:RESPONSE:ADDITIONAL_SECTION:parsing %u resource records\n", cpu_arcount);
100
101 if (rrs_parse(&additionals_e, resp_additionals_rrs_v,
102 resp_additionals_s_v, cpu_arcount)) {
103 if (additionals_e != resp_e_v)
104 PERR("1:DNS:RESPONSE:ADDITIONAL_SECTION:WARNING:the end of section of additional resource record(s), 0x%p, is not the end of the udp datagram, 0x%p\n", additionals_e, resp_e_v);
105 } else {
106 r = false;
107 }
108 PERR("1:DNS:RESPONSE:ADDITIONAL_SECTION:END\n");
109 return r;
110 }
111
112 static bool authorities_parse(void)
113 {
114 struct dns_rfc_hdr_t *hdr;
115 u16 cpu_nscount;
116 bool r;
117
118 hdr = (struct dns_rfc_hdr_t*)resp_v;
119 cpu_nscount = be16_to_cpu(hdr->nscount);
120
121 PERR("1:DNS:RESPONSE:AUTHORITY_SECTION:START\n");
122
123 if (cpu_nscount > rrs_n_max) {
124 PERR("0:DNS:RESPONSE:AUTHORITY_SECTION:ERROR:too many authority resource record(s) %u, max is %u\n", cpu_nscount, rrs_n_max);
125 exit(1);
126 }
127 PERR("1:DNS:RESPONSE:AUTHORITY_SECTION:parsing %u resource records\n", cpu_nscount);
128
129 r = rrs_parse(&resp_additionals_s_v, resp_authorities_rrs_v,
130 resp_authorities_s_v, cpu_nscount);
131 PERR("1:DNS:RESPONSE:AUTHORITY_SECTION:END\n");
132 return r;
133 }
134
135 static bool answers_parse(void)
136 {
137 struct dns_rfc_hdr_t *hdr;
138 u16 cpu_ancount;
139 bool r;
140
141 hdr = (struct dns_rfc_hdr_t*)resp_v;
142 cpu_ancount = be16_to_cpu(hdr->ancount);
143
144 PERR("1:DNS:RESPONSE:ANSWER_SECTION:START\n");
145
146 if (cpu_ancount > rrs_n_max) {
147 PERR("0:DNS:RESPONSE:ANSWER_SECTION:ERROR:too many answer resource record(s) %u, max is %u\n", cpu_ancount, rrs_n_max);
148 exit(1);
149 }
150 PERR("1:DNS:RESPONSE:ANSWER_SECTION:parsing %u resource records\n", cpu_ancount);
151
152 r = rrs_parse(&resp_authorities_s_v, resp_answers_rrs_v,
153 resp_answers_s_v, cpu_ancount);
154 PERR("1:DNS:RESPONSE:ANSWER_SECTION:END\n");
155 return r;
156 }
157
158 /* is the response question the query question ? */
159 static bool qtions_parse(void)
160 {
161 struct dns_rfc_hdr_t *hdr;
162 struct dns_rfc_qtion_trailer_t *trailer;
163 u8 *trailer_l;
164
165 hdr = (struct dns_rfc_hdr_t*)resp_v;
166
167 PERR("1:DNS:RESPONSE:QUESTION_SECTION:START\n");
168
169 if (be16_to_cpu(hdr->qdcount) != 1) {
170 PERR("0:DNS:RESPONSE:QUESTION_SECTION:WARNING:question count is not 1 but %u, trying next name server\n", be16_to_cpu(hdr->qdcount));
171 return false;
172 }
173 PERR("1:DNS:RESPONSE:QUESTION_SECTION:parsing 1 question\n");
174 /*--------------------------------------------------------------------*/
175 resp_qtions_s_v = resp_v + sizeof(*hdr);
176
177 if (!name_cmp(resp_qtions_s_v, resp_v, resp_e_v, query_qtion_s_v,
178 query_v, query_e_v)) {
179 PERR("1:DNS:RESPONSE:QUESTION_SECTION:WARNING:name is not our name, trying next name server, wrong name follows:\n");
180 name_dump(resp_qtions_s_v, resp_v, resp_e_v);
181 return false;
182 }
183 resp_qtion_v.name = resp_qtions_s_v; /* store it for later */
184 PERR("1:DNS:RESPONSE:QUESTION_SECTION:name is ok\n");
185 /*--------------------------------------------------------------------*/
186 trailer = name_skip(resp_qtions_s_v, resp_v, resp_e_v);
187
188 trailer_l = (u8*)trailer + sizeof(*trailer) - 1;
189 if (trailer_l >= resp_e_v) {
190 PERR("1:DNS:RESPONSE:QUESTION_SECTION:WARNING:no room in the response for the question trailer, trying next name server\n");
191 return false;
192 }
193
194 if (!memcmp(trailer, query_qtion_trailer_v, sizeof(*trailer))) {
195 PERR("1:DNS:RESPONSE:QUESTION_SECTION:WARNING:trailer is not our trailer, trying next name server, wrong question follows:\n");
196 qtion_dump(resp_qtions_s_v, resp_v, resp_e_v);
197 return false;
198 }
199 resp_qtion_v.trailer = trailer; /* store it for later */
200 PERR("1:DNS:RESPONSE:QUESTION_SECTION:trailer is ok\n");
201
202 resp_answers_s_v = (u8*)trailer + sizeof(*trailer);
203
204 PERR("1:DNS:RESPONSE:QUESTION_SECTION:END\n");
205 return true; /* ok, its really our question */
206 }
207
208 static bool hdr_info_chk(void)
209 {
210 struct dns_rfc_hdr_t *hdr;
211 u16 cpu_u16;
212
213 hdr = (struct dns_rfc_hdr_t*)resp_v;
214 cpu_u16 = be16_to_cpu(hdr->info);
215 PERR("1:DNS:RESPONSE:hdr=0x%04x\n", cpu_u16);
216
217 if ((cpu_u16 & DNS_RFC_HDR_INFO_AA_BIT) != 0)
218 PERR("1:DNS:RESPONSE:name server is authoritative for our query\n");
219 else
220 PERR("1:DNS:RESPONSE:name server is not authoritative for our query\n");
221
222 if ((cpu_u16 & DNS_RFC_HDR_INFO_RD_BIT) != 0)
223 PERR("1:DNS:RESPONSE:recursion desired bit is set\n");
224 else
225 PERR("1:DNS:RESPONSE:recursion desired bit is not set\n");
226
227 if ((cpu_u16 & DNS_RFC_HDR_INFO_RA_BIT) != 0)
228 PERR("1:DNS:RESPONSE:server supports recursion\n");
229 else
230 PERR("1:DNS:RESPONSE:server does not support recursion\n");
231
232 if ((cpu_u16 & DNS_RFC_HDR_INFO_Z_MASK) != 0)
233 PERR("1:DNS:RESPONSE:WARNING:message z field is not 0, ignoring and continuing response parsing\n");
234
235 if ((cpu_u16 & DNS_RFC_HDR_INFO_QR_BIT) == 0) {
236 PERR("1:DNS:RESPONSE:WARNING:message is not a response, trying next name server\n");
237 return false;
238 }
239
240 if ((cpu_u16 & DNS_RFC_HDR_INFO_OPCODE_MASK) != 0) {
241 PERR("1:DNS:RESPONSE:WARNING:message has the wrong opcode, has 0x%x, expected 0, trying next name server\n", DNS_RFC_HDR_INFO_OPCODE(cpu_u16));
242 return false;
243 }
244
245 if ((cpu_u16 & DNS_RFC_HDR_INFO_TC_BIT) != 0) {
246 PERR("1:DNS:RESPONSE:WARNING:we do not support truncated response(yet or never), trying next name server\n");
247 return false;
248 }
249
250 if ((cpu_u16 & DNS_RFC_HDR_INFO_RCODE_MASK) != 0) {
251 PERR("1:DNS:RESPONSE:WARNING:non zero error condition 0x%x, trying next name server\n", DNS_RFC_HDR_INFO_RCODE(cpu_u16));
252 return false;
253 }
254 return true;
255 }
256
257 static bool basic_and_hdr_chks(void)
258 {
259 struct dns_rfc_hdr_t *resp_hdr;
260 struct dns_rfc_hdr_t *query_hdr;
261
262 if (resp_sz_v < sizeof(*resp_hdr)) {
263 PERR("1:DNS:RESPONSE:WARNING:udp datagram cannot fit the header, hence too small, trying next name server\n");
264 return false;
265 }
266
267 resp_hdr = (struct dns_rfc_hdr_t*)resp_v;
268 query_hdr = (struct dns_rfc_hdr_t*)query_v;
269
270 /* check the id filter */
271 if (resp_hdr->id != query_hdr->id) {
272 PERR("1:DNS:RESPONSE:WARNING:message does not have the right id, response id is 0x%x, expected id is 0x%x, trying next name server\n", resp_hdr->id, query_hdr->id);
273 return false;
274 }
275
276 if (!hdr_info_chk())
277 return false;
278 return true;
279 }
280
281 #define CANONICAL_NAME_CMP(a) name_cmp(\
282 a, resp_v, resp_e_v, \
283 canonical_dn_v, canonical_dn_v, canonical_dn_v + DNS_RFC_NAME_SZ_MAX)
284
285 #define MX_EXCHANGE_CPY(mx) name_cpy(\
286 mx.exchange, resp_mx->exchange, resp_v, resp_e_v)
287
288 #define MX_EXCHANGE_DUMP(mx) name_dump( \
289 mx.exchange, \
290 mx.exchange, \
291 mx.exchange + DNS_RFC_NAME_SZ_MAX)
292 static void mx_store(struct rr_t *mx)
293 {
294 struct dns_rfc_mx_t *resp_mx;
295
296 /*
297 * the basic scan done once receiving the dns message already did
298 * structural bound checking
299 */
300
301 /* first, is this mx targetting our canonical dn */
302 if (!CANONICAL_NAME_CMP(mx->name)) {
303 PERR("1:DNS:RESPONSE:MXS:found mx resource record _not_ targetting our canonical name, name follows and skipping:\n");
304 name_dump(mx->name, resp_v, resp_e_v);
305 return;
306 }
307
308 /* this mx rr is targetting our canonical dn */
309
310 resp_mx = (struct dns_rfc_mx_t*)mx->part->rdata;
311
312 if (mxs_n_v == CONFIG_MXS_N_MAX) {
313 PERR("1:DNS:MXS:ERROR:no room to store the found mx, max is %u\n", CONFIG_MXS_N_MAX);
314 exit(1);
315 }
316
317 PERR("1:DNS:RESPONSE:MXS:found mx resource record targetting our canonical name\n");
318
319 mxs_v[mxs_n_v].preference = be16_to_cpu(resp_mx->preference);
320 (void)MX_EXCHANGE_CPY(mxs_v[mxs_n_v]);
321
322 PERR("1:DNS:MX:%u:DUMP:START\n", mxs_n_v);
323 PERR("1:DNS:MX:%u:DUMP:PREFERENCE:%u\n", mxs_n_v, mxs_v[mxs_n_v].preference);
324 PERR("1:DNS:MX:%u:DUMP:EXCHANGE:\n", mxs_n_v);
325 MX_EXCHANGE_DUMP(mxs_v[mxs_n_v]);
326 PERR("1:DNS:MX:%u:DUMP:END\n", mxs_n_v);
327
328 ++mxs_n_v;
329 }
330 #undef CANONICAL_NAME_CMP
331 #undef MX_EXCHANGE_CPY
332 #undef MX_EXCHANGE_DUMP
333
334 static bool is_addr(struct rr_t *rr)
335 {
336 if (rr->part->class != be16_to_cpu(DNS_RFC_RR_CLASS_IN))
337 return false;
338
339 #ifdef CONFIG_SMTP_IPV4
340 if (rr->part->type == be16_to_cpu(DNS_RFC_RR_TYPE_A))
341 return true;
342 #endif
343 if (rr->part->type == be16_to_cpu(DNS_RFC_RR_TYPE_AAAA))
344 return true;
345 }
346
347 static bool addr_match_mx_exchange(struct rr_t *a, struct mx_t *mx)
348 {
349 return name_cmp(a->name, resp_v, resp_e_v, mx->exchange, mx->exchange,
350 mx->exchange + DNS_RFC_NAME_SZ_MAX);
351 }
352
353 static void addr_store_smtp_ip(struct rr_t *a)
354 {
355 struct ip_t *ip;
356
357 if (dn_v->smtp_ips_n == CONFIG_DN_SMTP_IPS_N_MAX) {
358 PERR("0:DNS:RESPONSE:%.*s:no room for new ip, max of %u ips per domain name was reached\n", dn_v->dn.l - dn_v->dn.s + 1, dn_v->dn.s, CONFIG_DN_SMTP_IPS_N_MAX);
359 exit(1);
360 }
361
362 ip = &dn_v->smtp_ips[dn_v->smtp_ips_n];
363
364 #ifdef CONFIG_SMTP_IPV4
365 if (a->part->type == be16_to_cpu(DNS_RFC_RR_TYPE_A)) {
366 ip->type = ipv4;
367 memcpy(&ip->ipv4_net, a->part->rdata, sizeof(ip->ipv4_net));
368 PERR("1:DNS:RESPONSE:\"%.*s\":storing smtp ipv4:0x%08lx\n", dn_v->dn.l - dn_v->dn.s + 1, dn_v->dn.s, be32_to_cpu(ip->ipv4_net));
369 ++(dn_v->smtp_ips_n);
370 return;
371 }
372 ip->type = ipv6;
373 #endif
374 memcpy(&ip->ipv6_net[0], a->part->rdata, sizeof(ip->ipv6_net));
375 PERR("1:DNS:RESPONSE:\"%.*s\":storing smtp ipv6:0x%016lx%016lx\n", dn_v->dn.l - dn_v->dn.s + 1, dn_v->dn.s, be64_to_cpu(ip->ipv6_net_h), be64_to_cpu(ip->ipv6_net_l));
376 ++(dn_v->smtp_ips_n);
377 return;
378 }
379 /******************************************************************************/
380 /* exported in response.h */
381 /*
382 * this data comes from "outside", do _not_ trust its content.
383 */
384 static void resp_ar_collect_mx_ips(struct mx_t *mx)
385 {
386 struct dns_rfc_hdr_t *hdr;
387 u16 cpu_arcount;
388 u16 i;
389
390 hdr = (struct dns_rfc_hdr_t*)resp_v;
391 cpu_arcount = be16_to_cpu(hdr->arcount);
392
393 i = 0;
394 loop {
395 struct rr_t *rr;
396
397 if (i == cpu_arcount)
398 break;
399
400 rr = &resp_additionals_rrs_v[i];
401
402 if (is_addr(rr) && addr_match_mx_exchange(rr, mx))
403 addr_store_smtp_ip(rr);
404 ++i;
405 }
406 }
407
408 static void resp_an_collect_mx_ips(struct mx_t *mx)
409 {
410 struct dns_rfc_hdr_t *hdr;
411 u16 cpu_ancount;
412 u16 i;
413
414 hdr = (struct dns_rfc_hdr_t*)resp_v;
415 cpu_ancount = be16_to_cpu(hdr->ancount);
416
417 i = 0;
418 loop {
419 struct rr_t *rr;
420
421 if (i == cpu_ancount)
422 break;
423
424 rr = &resp_answers_rrs_v[i];
425
426 if (is_addr(rr) && addr_match_mx_exchange(rr, mx))
427 addr_store_smtp_ip(rr);
428 ++i;
429 }
430 }
431
432 static void resp_an_collect_canonical_dn_ips(void)
433 {
434 struct dns_rfc_hdr_t *hdr;
435 u16 cpu_ancount;
436 u16 i;
437
438 hdr = (struct dns_rfc_hdr_t*)resp_v;
439 cpu_ancount = be16_to_cpu(hdr->ancount);
440
441 i = 0;
442 loop {
443 struct rr_t *rr;
444
445 if (i == cpu_ancount)
446 break;
447
448 rr = &resp_answers_rrs_v[i];
449
450 if (is_addr(rr) && name_cmp(rr->name, resp_v, resp_e_v,
451 canonical_dn_v, canonical_dn_v,
452 canonical_dn_e_v))
453 addr_store_smtp_ip(rr);
454 ++i;
455 }
456 }
457
458 static void resp_ar_collect_canonical_dn_ips(void)
459 {
460 struct dns_rfc_hdr_t *hdr;
461 u16 cpu_arcount;
462 u16 i;
463
464 hdr = (struct dns_rfc_hdr_t*)resp_v;
465 cpu_arcount = be16_to_cpu(hdr->arcount);
466
467 i = 0;
468 loop {
469 struct rr_t *rr;
470
471 if (i == cpu_arcount)
472 break;
473
474 rr = &resp_additionals_rrs_v[i];
475
476 if (is_addr(rr) && name_cmp(rr->name, resp_v, resp_e_v,
477 canonical_dn_v, canonical_dn_v,
478 canonical_dn_e_v))
479 addr_store_smtp_ip(rr);
480 ++i;
481 }
482 }
483
484 static bool resp_basic_parse(void)
485 {
486 PERR("1:DNS:RESPONSE:received udp datagram of %lu bytes\n", resp_sz_v);
487
488 if (!basic_and_hdr_chks())
489 return false;
490 if (!qtions_parse())
491 return false;
492 if (!answers_parse())
493 return false;
494 if (!authorities_parse())
495 return false;
496 if (!additionals_parse())
497 return false;
498 return true;
499 }
500
501 /*
502 * scan the answer section for a cname rr which defines the canonical domain
503 * name for our question domain name
504 */
505 static bool resp_cname_rr_scan(void)
506 {
507 struct dns_rfc_hdr_t *hdr;
508 u16 ancount;
509 u16 i;
510
511 hdr = (struct dns_rfc_hdr_t*)resp_v;
512 ancount = be16_to_cpu(hdr->ancount);
513
514 i = 0;
515 loop {
516 struct rr_t *rr;
517
518 if (i == ancount)
519 break;
520
521 rr = &resp_answers_rrs_v[i];
522
523 if ( rr->part->class == cpu_to_be16(DNS_RFC_RR_CLASS_IN)
524 && rr->part->type == cpu_to_be16(DNS_RFC_RR_TYPE_CNAME)
525 && rr->part->ttl != 0
526 && rr->part->rdlength != 0
527 && name_cmp(rr->name, resp_v, resp_e_v,
528 resp_qtion_v.name, resp_v, resp_e_v)) {
529 cname_rr_v = rr;
530 return true;
531 }
532 ++i;
533 }
534 return false;
535 }
536
537 static void resp_mxs_scan(void)
538 {
539 struct dns_rfc_hdr_t *hdr;
540 u16 ancount;
541 u16 i;
542
543 hdr = (struct dns_rfc_hdr_t*)resp_v;
544 ancount = be16_to_cpu(hdr->ancount);
545
546 mxs_n_v = 0;
547 i = 0;
548 PERR("1:DNS:********************************************************************************\n");
549 PERR("1:DNS:RESPONSE:MXS:SCANNING:START\n");
550 loop {
551 struct rr_t *rr;
552
553 if (i == ancount)
554 break;
555
556 rr = &resp_answers_rrs_v[i];
557 if (rr->part->class = cpu_to_be16(DNS_RFC_RR_CLASS_IN)
558 && rr->part->type == cpu_to_be16(DNS_RFC_RR_TYPE_MX)) {
559 mx_store(rr);
560 }
561 ++i;
562 }
563 PERR("1:DNS:RESPONSE:MXS:SCANNING:END\n");
564 PERR("1:DNS:********************************************************************************\n");
565 }
566 /*----------------------------------------------------------------------------*/
567 #define CLEANUP
568 #include "namespace/ulinux.h"
569 #include "namespace/syncsm.h"
570 #include "dns/namespace/state.h"
571 #include "dns/namespace/resolver.h"
572 #include "dns/namespace/name.h"
573 #include "dns/namespace/response.h"
574 #include "dns/namespace/response.c"
575 #undef CLEANUP
576 #endif
File dns/response.h added (mode: 100644) (index 0000000..d9c5961)
1 #ifndef SYNCSM_DNS_RESPONSE_H
2 #define SYNCSM_DNS_RESPONSE_H
3 #include "dns/namespace/response.h"
4 /*
5 * this code is protected by the GNU affero GPLv3 license
6 * author:Sylvain BERTRAND
7 */
8 static void resp_an_collect_canonical_dn_ips(void);
9 static void resp_an_collect_mx_ips(struct mx_t *mx);
10 static void resp_ar_collect_canonical_dn_ips(void);
11 static void resp_ar_collect_mx_ips(struct mx_t *mx);
12 static bool resp_basic_parse(void);
13 static bool resp_cname_rr_scan(void);
14 static void resp_mxs_scan(void);
15 #define CLEANUP
16 #include "dns/namespace/response.h"
17 #undef CLEANUP
18 #endif
File dns/rfc.h added (mode: 100644) (index 0000000..2473ba0)
1 #ifndef DNS_RFC_H
2 #define DNS_RFC_H
3 /*
4 * this code is protected by the GNU affero GPLv3 license
5 * author:Sylvain BERTRAND
6 */
7 #include "namespace/ulinux.h"
8 /*----------------------------------------------------------------------------*/
9 /* universe global, short enough, no namespace */
10 #define DNS_RFC_UDP_PAYLOAD_SZ_MAX 512
11 #define DNS_RFC_PORT 53 /* could be tcp */
12 #define DNS_RFC_NAME_SZ_MAX 255
13 #define DNS_RFC_LABEL_SZ_MAX 63
14
15 #define DNS_RFC_RR_TYPE_A 1
16 #define DNS_RFC_RR_TYPE_NS 2
17 #define DNS_RFC_RR_TYPE_MD 3
18 #define DNS_RFC_RR_TYPE_MF 4
19 #define DNS_RFC_RR_TYPE_CNAME 5
20 #define DNS_RFC_RR_TYPE_SOA 6
21 #define DNS_RFC_RR_TYPE_MB 7
22 #define DNS_RFC_RR_TYPE_MG 8
23 #define DNS_RFC_RR_TYPE_MR 9
24 #define DNS_RFC_RR_TYPE_NULL 10
25 #define DNS_RFC_RR_TYPE_WKS 11
26 #define DNS_RFC_RR_TYPE_PTR 12
27 #define DNS_RFC_RR_TYPE_HINFO 13
28 #define DNS_RFC_RR_TYPE_MINFO 14
29 #define DNS_RFC_RR_TYPE_MX 15
30 #define DNS_RFC_RR_TYPE_TXT 16
31 #define DNS_RFC_RR_TYPE_AAAA 28
32
33 #define DNS_RFC_RR_CLASS_IN 1
34 #define DNS_RFC_RR_CLASS_CN 2
35 #define DNS_RFC_RR_CLASS_CH 3
36 #define DNS_RFC_RR_CLASS_HS 4
37
38 #define DNS_RFC_LABEL_OFFSET_IS_PTR_MARK 0xc0
39 #define DNS_RFC_LABEL_PTR_OFFSET_MASK 0x3fff
40
41 #define DNS_RFC_HDR_INFO_QR_BIT (1 << 15)
42 #define DNS_RFC_HDR_INFO_OPCODE_MASK 0x7800
43 #define DNS_RFC_HDR_INFO_OPCODE(x) (((x) & DNS_RFC_HDR_INFO_OPCODE_MASK) >> 11)
44 #define DNS_RFC_HDR_INFO_AA_BIT (1 << 10)
45 #define DNS_RFC_HDR_INFO_TC_BIT (1 << 9)
46 #define DNS_RFC_HDR_INFO_RD_BIT (1 << 8)
47 #define DNS_RFC_HDR_INFO_RA_BIT (1 << 7)
48 #define DNS_RFC_HDR_INFO_Z_MASK 0x0070
49 #define DNS_RFC_HDR_INFO_RCODE_MASK 0x000f
50 #define DNS_RFC_HDR_INFO_RCODE(x) ((x) & DNS_RFC_HDR_INFO_RCODE_MASK)
51 struct dns_rfc_hdr_t {
52 u16 id;
53 u16 info;
54 u16 qdcount;
55 u16 ancount;
56 u16 nscount;
57 u16 arcount;
58 } PACKED;
59 /*----------------------------------------------------------------------------*/
60 struct dns_rfc_qtion_trailer_t {
61 u16 type;
62 u16 class;
63 } PACKED;
64 /*----------------------------------------------------------------------------*/
65 struct dns_rfc_rr_part_t {
66 u16 type;
67 u16 class;
68 s32 ttl;
69 u16 rdlength;
70 u8 rdata[];
71 } PACKED;
72 /*----------------------------------------------------------------------------*/
73 struct dns_rfc_mx_t {
74 u16 preference;
75 u8 exchange[];
76 } PACKED;
77 /*----------------------------------------------------------------------------*/
78 #define CLEANUP
79 #include "namespace/ulinux.h"
80 #undef CLEANUP
81 #endif
File dns/state.h added (mode: 100644) (index 0000000..dfc44b0)
1 #ifndef SYNCSM_DNS_STATE_H
2 #define SYNCSM_DNS_STATE_H
3 /*
4 * this code is protected by the GNU affero GPLv3 license
5 * author:Sylvain BERTRAND
6 */
7 #include "namespace/ulinux.h"
8 #include "namespace/syncsm.h"
9 #include "dns/namespace/state.h"
10 /*----------------------------------------------------------------------------*/
11 static struct dn_al_t *dn_v; /* current targetted dn */
12
13 /* the canonical domain name which since the targetted dn could be an alias */
14 static u8 canonical_dn_v[DNS_RFC_NAME_SZ_MAX];
15 static u8 *canonical_dn_e_v;
16
17 /*
18 * if mxs are provided, store them in order to get their A (if smtp ipv4 is
19 * enabled) and AAAA
20 */
21 struct mx_t {
22 u16 preference;
23 u8 exchange[DNS_RFC_NAME_SZ_MAX];
24 };
25 static struct mx_t mxs_v[CONFIG_MXS_N_MAX];
26 static u16 mxs_n_v;
27 /*----------------------------------------------------------------------------*/
28 /*
29 * Some dns servers do support _only_ recursive query mode (for instance
30 * cisco wifi routers used in many starbucks). They do not support the default
31 * mandatory iterative query mode.
32 * Whatever, from a client point of view, it should be simple to query
33 * the dns, hence the recursive mode should have been the default and only mode
34 * since the beginning, from a client point of view. The iterative mode should
35 * actually be used only by the network of dns servers.
36 */
37 static struct ip_t nss_v[CONFIG_DNS_NSS_N_MAX];
38 static u8 nss_n_v;
39 static u8 ns_v; /* current targetted ns */
40 /*----------------------------------------------------------------------------*/
41 /******************************************************************************/
42 /******************************************************************************/
43 static u16 id_v;
44 /*============================================================================*/
45 /* query/question */
46 static u8 qtion_dn_v[DNS_RFC_NAME_SZ_MAX];
47 static u8 *qtion_dn_e_v;
48 static u16 qtion_type_v; /* mx? a? aaaa? */
49
50 static u8 query_v[DNS_RFC_UDP_PAYLOAD_SZ_MAX];
51 static u8 *query_qtion_s_v;
52 static struct dns_rfc_qtion_trailer_t *query_qtion_trailer_v;
53 static u16 query_qtion_sz_v;
54 static u8 *query_qtion_e_v; /* comfort variable */
55 static u16 query_sz_v;
56 static u8 *query_e_v; /* comfort variable */
57 /*============================================================================*/
58 /* response */
59 static u8 resp_v[DNS_RFC_UDP_PAYLOAD_SZ_MAX];
60 static u16 resp_sz_v;
61 static u8 *resp_e_v; /* comfort variable */
62 /*----------------------------------------------------------------------------*/
63 struct resp_qtion_t {
64 u8 *name;
65 struct dns_rfc_qtion_trailer_t *trailer;
66 };
67 static u8 *resp_qtions_s_v;
68 static struct resp_qtion_t resp_qtion_v; /* we are only 1 question */
69 /*----------------------------------------------------------------------------*/
70 enum { rrs_n_max = 100 };
71 struct rr_t {
72 u8 *name;
73 struct dns_rfc_rr_part_t *part;
74 };
75 /*----------------------------------------------------------------------------*/
76 static u8 *resp_answers_s_v;
77 static struct rr_t resp_answers_rrs_v[rrs_n_max];
78
79 static struct rr_t *cname_rr_v; /* the first cname in this section */
80 /*----------------------------------------------------------------------------*/
81 static u8 *resp_authorities_s_v;
82 static struct rr_t resp_authorities_rrs_v[rrs_n_max];
83 /*----------------------------------------------------------------------------*/
84 static u8 *resp_additionals_s_v;
85 static struct rr_t resp_additionals_rrs_v[rrs_n_max];
86 /******************************************************************************/
87 /******************************************************************************/
88 #define CLEANUP
89 #include "namespace/ulinux.h"
90 #include "namespace/syncsm.h"
91 #include "dns/namespace/state.h"
92 #undef CLEANUP
93 #endif
File make_gcc_aarch64 added (mode: 100755) (index 0000000..6ebc404)
1 #!/bin/sh
2 LC_ALL=C
3 export LC_ALL
4 set -e
5 #-------------------------------------------------------------------------------
6 # build dir and src dir
7 build_dir=$(readlink -e .)
8 echo build_dir=$build_dir
9
10 src_dir=$(readlink -e $(dirname $0))
11 echo src_dir=$src_dir
12
13 config_h_dir=$build_dir
14 #-------------------------------------------------------------------------------
15 arch=aarch64
16 #-------------------------------------------------------------------------------
17 # configure our ultra-thin linux "uapi" (User API) abstraction layer
18 rm -f $build_dir/ulinux/arch
19 mkdir -p $build_dir/ulinux
20 ln -f -s $src_dir/ulinux/archs/$arch $build_dir/ulinux/arch
21 #-------------------------------------------------------------------------------
22 echo ASM all.S;
23 $arch-linux-gnu-gcc -pipe -c -fvisibility=hidden -o $build_dir/all_S.o -I$config_h_dir -I$build_dir $src_dir/all.S
24
25 echo CC all.c
26 $arch-linux-gnu-gcc -pipe -fPIC -O2 -c -static-libgcc -fvisibility=hidden -o $build_dir/all_c.o -I$config_h_dir -I$build_dir -I$src_dir $src_dir/all.c
27
28 echo LD syncsm
29 $arch-linux-gnu-ld -Bstatic -nostdlib $($arch-linux-gnu-gcc -print-libgcc-file-name) -o $build_dir/syncsm $build_dir/all_S.o $build_dir/all_c.o
30
31 echo STRIP syncsm
32 $arch-linux-gnu-strip -s $build_dir/syncsm
File make_gcc_x86_64 added (mode: 100755) (index 0000000..303ed53)
1 #!/bin/sh
2 LC_ALL=C
3 export LC_ALL
4 set -e
5 #-------------------------------------------------------------------------------
6 # build dir and src dir
7 build_dir=$(readlink -e .)
8 echo build_dir=$build_dir
9
10 src_dir=$(readlink -e $(dirname $0))
11 echo src_dir=$src_dir
12
13 config_h_dir=$build_dir
14 #-------------------------------------------------------------------------------
15 arch=x86_64
16 #-------------------------------------------------------------------------------
17 # configure our ultra-thin linux "uapi" (User API) abstraction layer
18 rm -f $build_dir/ulinux/arch
19 mkdir -p $build_dir/ulinux
20 ln -f -s $src_dir/ulinux/archs/$arch $build_dir/ulinux/arch
21 #-------------------------------------------------------------------------------
22 echo ASM all.S;
23 $arch-linux-gnu-gcc -pipe -c -fvisibility=hidden -o $build_dir/all_S.o -I$config_h_dir -I$build_dir $src_dir/all.S
24
25 echo CC all.c
26 $arch-linux-gnu-gcc -pipe -fPIC -O2 -c -static-libgcc -fvisibility=hidden -o $build_dir/all_c.o -I$config_h_dir -I$build_dir -I$src_dir $src_dir/all.c
27
28 echo LD syncsm
29 $arch-linux-gnu-ld -Bstatic -nostdlib $($arch-linux-gnu-gcc -print-libgcc-file-name) -o $build_dir/syncsm $build_dir/all_S.o $build_dir/all_c.o
30
31 echo STRIP syncsm
32 $arch-linux-gnu-strip -s $build_dir/syncsm
File namespace/dns.h added (mode: 100644) (index 0000000..bb99ef9)
1 /*
2 * this code is protected by the GNU affero GPLv3 license
3 * author:Sylvain BERTRAND
4 */
5 #ifndef CLEANUP
6 #define dns_init syncsm_dns_init
7 #define dns_resolver syncsm_dns_resolver
8 /******************************************************************************/
9 #else /* CLEANUP */
10 #undef dns_init
11 #undef dns_resolver
12 #endif
File namespace/smtp.h added (mode: 100644) (index 0000000..a718d8f)
1 /*
2 * this code is protected by the GNU affero GPLv3 license
3 * author:Sylvain BERTRAND
4 */
5 #ifndef CLEANUP
6 #define smtp_init syncsm_smtp_init
7 #define smtp_send syncsm_smtp_send
8 /******************************************************************************/
9 #else /* CLEANUP */
10 #undef smtp_init
11 #undef smtp_send
12 #endif
File namespace/syncsm.c added (mode: 100644) (index 0000000..206654b)
1 /*
2 * this code is protected by the GNU affero GPLv3 license
3 * author:Sylvain BERTRAND
4 */
5 #ifndef CLEANUP
6 #define dn_al_eq syncsm_c_dn_al_eq
7 #define dn_al_insert syncsm_c_dn_al_insert
8 #define dn_al_locate syncsm_c_dn_al_locate
9 #ifdef CONFIG_DISABLE_SMTP_TRANSPARENCY
10 #define email_read_from_stdin syncsm_c_email_read_from_stdin
11 #else
12 #define stdin_read syncsm_c_stdin_read
13 #define email_write_byte syncsm_c_email_write_byte
14 #define email_write_bytes syncsm_c_email_write_bytes
15 #define match syncsm_c_match
16 #define normal syncsm_c_normal
17 #define flush_partial_terminator syncsm_c_flush_partial_terminator
18 #define matching_terminator syncsm_c_matching_terminator
19 #define email_read_and_escape_from_stdin syncsm_c_email_read_and_escape_from_stdin
20 #endif
21 #define globals_init syncsm_c_globals_init
22 #define ip_eq syncsm_c_ip_eq
23 #define rcpt_dn_al_process syncsm_c_rcpt_dn_al_process
24 #define rcpt_prepare syncsm_c_rcpt_prepare
25 #define rcpt_slices syncsm_c_rcpt_slices
26 #define rcpts syncsm_c_rcpts
27 #define rcpts_locate_from syncsm_c_rcpts_locate_from
28 #define rcpts_prepare syncsm_c_rcpts_prepare
29 #define slice_eq syncsm_c_slice_eq
30 #define stdin_nonblock_status syncsm_c_stdin_nonblock_status
31 #define to_ipv6 syncsm_c_to_ipv6
32 /******************************************************************************/
33 #else /* CLEANUP */
34 #undef dn_al_desc
35 #undef dn_al_insert
36 #undef dn_al_locate
37 #ifdef CONFIG_DISABLE_SMTP_TRANSPARENCY
38 #undef email_read_from_stdin
39 #else
40 #undef stdin_read
41 #undef email_write_byte
42 #undef email_write_bytes
43 #undef match
44 #undef normal
45 #undef flush_partial_terminator
46 #undef matching_terminator
47 #undef email_read_and_escape_from_stdin
48 #endif
49 #undef globals_init
50 #undef ip_eq
51 #undef rcpt_dn_al_process
52 #undef rcpt_prepare
53 #undef rcpt_slices
54 #undef rcpts
55 #undef rcpts_locate_from
56 #undef rcpts_prepare
57 #undef slice_eq
58 #undef stdin_nonblock_status
59 #undef to_ipv6
60 #endif
File namespace/syncsm.h added (mode: 100644) (index 0000000..76b7759)
1 /*
2 * this code is protected by the GNU affero GPLv3 license
3 * author:Sylvain BERTRAND
4 */
5 #ifndef CLEANUP
6 #define dn_al_t syncsm_dn_al_t
7 #define dn_al_v syncsm_dn_al_v
8 #define dn_al_n_v syncsm_dn_al_n_v
9 #define email_v syncsm_email_v
10 #define email_sz_v syncsm_email_sz_v
11 #define ip_t syncsm_ip_t
12 #define ipv4 syncsm_ipv4
13 #define ipv6 syncsm_ipv6
14 #define str_slice_t syncsm_str_slice_t
15 /******************************************************************************/
16 #else /* CLEANUP */
17 #undef dn_al_t
18 #undef dn_al_v
19 #undef dn_al_n_v
20 #undef email_v
21 #undef email_sz_v
22 #undef ip_t
23 #undef ipv4
24 #undef ipv6
25 #undef str_slice_t
26 #endif
File namespace/ulinux.h added (mode: 100644) (index 0000000..d659ba3)
1 /*
2 * this code is protected by the GNU affero GPLv3
3 * author:Sylvain BERTRAND
4 */
5 #ifndef CLEANUP
6 #define loop for(;;)
7 #define sl ulinux_sl
8 #define si ulinux_si
9 #define ul ulinux_ul
10 #define u8 ulinux_u8
11 #define s8 ulinux_s8
12 #define u16 ulinux_u16
13 #define s16 ulinux_s16
14 #define s32 ulinux_s32
15 #define u32 ulinux_u32
16 #define s64 ulinux_s64
17 #define u64 ulinux_u64
18 /*----------------------------------------------------------------------------*/
19 #define dprintf ulinux_dprintf
20 #define snprintf ulinux_snprintf
21 /*----------------------------------------------------------------------------*/
22 #define EAGAIN ULINUX_EAGAIN
23 #define EINTR ULINUX_EINTR
24 #define ISERR ULINUX_ISERR
25 /*----------------------------------------------------------------------------*/
26 #define exit(a) ulinux_sysc(exit_group,1,a)
27 /*----------------------------------------------------------------------------*/
28 #define read(a,b,c) ulinux_sysc(read,3,a,b,c)
29 #define write(a,b,c) ulinux_sysc(write,3,a,b,c)
30 /*----------------------------------------------------------------------------*/
31 #define PROT_READ ULINUX_PROT_READ
32 #define PROT_WRITE ULINUX_PROT_WRITE
33 #define MAP_ANONYMOUS ULINUX_MAP_ANONYMOUS
34 #define MAP_UNINITIALIZED ULINUX_MAP_UNINITIALIZED
35 #define MAP_PRIVATE ULINUX_MAP_PRIVATE
36 #define mmap(addr,sz,attr,flgs,fd,off) ulinux_sysc(mmap,6,addr,sz,attr,flgs,fd,off)
37 /*----------------------------------------------------------------------------*/
38 #define AT_CWD ULINUX_AT_CWD
39 #define O_RD_ONLY ULINUX_O_RDONLY
40 #define O_NONBLOCK ULINUX_O_NONBLOCK
41 #define openat(a,b,c,d) ulinux_sysc(openat,4,a,b,c,d)
42 /*----------------------------------------------------------------------------*/
43 #define stat ulinux_stat
44 #define fstat(a,b) ulinux_sysc(fstat,2,a,b)
45 /*----------------------------------------------------------------------------*/
46 #define close(a) ulinux_sysc(close,1,a)
47 /*----------------------------------------------------------------------------*/
48 #define F_SETFL ULINUX_F_SETFL
49 #define F_GETFL ULINUX_F_GETFL
50 #define fcntl(a,b,c) ulinux_sysc(fcntl,3,a,b,c)
51 /*----------------------------------------------------------------------------*/
52 #define memset ulinux_memset
53 #define memcmp ulinux_memcmp
54 #define memcpy ulinux_memcpy
55 /*----------------------------------------------------------------------------*/
56 #define is_digit ulinux_is_digit
57 #define is_space ulinux_is_space
58 #define is_print ulinux_is_print
59 #define to_ipv4_blk ulinux_to_ipv4_blk
60 #define to_ipv6_blk ulinux_to_ipv6_blk
61 #define cpu_to_be16 ulinux_cpu_to_be16
62 #define be16_to_cpu ulinux_be16_to_cpu
63 #define be32_to_cpu ulinux_be32_to_cpu
64 #define be64_to_cpu ulinux_be64_to_cpu
65 /*----------------------------------------------------------------------------*/
66 #if defined CONFIG_DNS_IPV4 || defined CONFIG_SMTP_IPV4
67 #define AF_INET ULINUX_AF_INET
68 #define sockaddr_in ulinux_sockaddr_in
69 #endif
70 #define AF_INET6 ULINUX_AF_INET6
71 #define IPPROTO_TCP ULINUX_IPPROTO_TCP
72 #define TCP_USER_TIMEOUT ULINUX_TCP_USER_TIMEOUT
73 #define setsockopt(a,b,c,d,e) ulinux_sysc(setsockopt,5,a,b,c,d,e)
74 #define getsockopt(a,b,c,d,e) ulinux_sysc(getsockopt,5,a,b,c,d,e)
75 #define sockaddr_in6 ulinux_sockaddr_in6
76 #define SOCK_DGRAM ULINUX_SOCK_DGRAM
77 #define SOCK_STREAM ULINUX_SOCK_STREAM
78 #define SOCK_O_NONBLOCK ULINUX_O_NONBLOCK
79 #define socket(a,b,c) ulinux_sysc(socket,3,a,b,c)
80 #define EINPROGRESS ULINUX_EINPROGRESS
81 #define connect(a,b,c) ulinux_sysc(connect,3,a,b,c)
82 #define recvfrom(a,b,c,d,e,f) ulinux_sysc(recvfrom,6,a,b,c,d,e,f)
83 /*----------------------------------------------------------------------------*/
84 #define CLOCK_MONOTONIC ULINUX_CLOCK_MONOTONIC
85 #define TFD_NONBLOCK ULINUX_TFD_NONBLOCK
86 #define itimerspec ulinux_itimerspec
87 #define timerfd_create(a,b) ulinux_sysc(timerfd_create,2,a,b)
88 #define timerfd_settime(a,b,c,d) ulinux_sysc(timerfd_settime,4,a,b,c,d)
89 #define epoll_create1(a) ulinux_sysc(epoll_create1,1,a)
90 #define epoll_event ulinux_epoll_event
91 #define EPOLLIN ULINUX_EPOLLIN
92 #define epoll_ctl(a,b,c,d) ulinux_sysc(epoll_ctl,4,a,b,c,d)
93 #define EPOLL_CTL_ADD ULINUX_EPOLL_CTL_ADD
94 #define EPOLL_CTL_DEL ULINUX_EPOLL_CTL_DEL
95 #define epoll_pwait(a,b,c,d,e) ulinux_sysc(epoll_pwait,5,a,b,c,d,e)
96 /*----------------------------------------------------------------------------*/
97 #define QSORT_CMP_LT ULINUX_QSORT_CMP_LT
98 #define QSORT_CMP_EQ ULINUX_QSORT_CMP_EQ
99 #define QSORT_CMP_GT ULINUX_QSORT_CMP_GT
100 #define qsort ulinux_qsort
101 /******************************************************************************/
102 #else /* CLEANUP */
103 #undef loop
104 #undef sl
105 #undef si
106 #undef ul
107 #undef u8
108 #undef s8
109 #undef u16
110 #undef s16
111 #undef s32
112 #undef u32
113 #undef s64
114 #undef u64
115 #undef dprintf
116 #undef EAGAIN
117 #undef EINTR
118 #undef ISERR
119 #undef exit
120 #undef read
121 #undef write
122 #undef PROT_READ
123 #undef PROT_WRITE
124 #undef MAP_ANONYMOUS
125 #undef MAP_UNINITIALIZED
126 #undef MAP_PRIVATE
127 #undef mmap
128 #undef AT_CWD
129 #undef O_RD_ONLY
130 #undef O_NONBLOCK
131 #undef openat
132 #undef stat
133 #undef fstat
134 #undef close
135 #undef F_SETFL
136 #undef F_GETFL
137 #undef fcntl
138 #undef memset
139 #undef memcmp
140 #undef memcpy
141 #undef is_digit
142 #undef is_space
143 #undef is_print
144 #undef to_ipv4_blk
145 #undef to_ipv6_blk
146 #undef cpu_to_be16
147 #undef be16_to_cpu
148 #undef be32_to_cpu
149 #undef be64_to_cpu
150 #if defined CONFIG_DNS_IPV4 || defined CONFIG_SMTP_IPV4
151 #undef AF_INET
152 #undef sockaddr_in
153 #endif
154 #undef AF_INET6
155 #undef IPPROTO_TCP
156 #undef TCP_USER_TIMEOUT
157 #undef setsockopt
158 #undef getsockopt
159 #undef sockaddr_in6
160 #undef SOCK_DGRAM
161 #undef SOCK_O_NONBLOCK
162 #undef socket
163 #undef EINPROGRESS
164 #undef connect
165 #undef recvfrom
166 #undef CLOCK_MONOTONIC
167 #undef TFD_NONBLOCK
168 #undef itimerspec
169 #undef timerfd_create
170 #undef timerfd_settime
171 #undef epoll_create1
172 #undef epoll_event
173 #undef EPOLLIN
174 #undef epoll_ctl
175 #undef EPOLL_CTL_ADD
176 #undef epoll_pwait
177 #undef QSORT_CMP_LT
178 #undef QSORT_CMP_EQ
179 #undef QSORT_CMP_GT
180 #undef qsort
181 #endif
File perr.h added (mode: 100644) (index 0000000..6b73d3e)
1 #ifndef PERR_H
2 #define PERR_H
3 /*
4 * this code is protected by the GNU affero GPLv3 license
5 * author:Sylvain BERTRAND
6 */
7 #include "namespace/ulinux.h"
8 /* secure a 0 terminating byte */
9 #define PERR(fmt,...) dprintf(2, &syncsm_dprint_buf[0], CONFIG_BUFSIZ - 1, fmt, ##__VA_ARGS__)
10 #define CSTRLEN(cstr) (sizeof(cstr) - 1)
11 static u8 syncsm_dprint_buf[CONFIG_BUFSIZ];
12 #define CLEANUP
13 #include "namespace/ulinux.h"
14 #undef CLEANUP
15 #endif
File smtp.h added (mode: 100644) (index 0000000..88813b8)
1 #ifndef SYNCSM_SMTP_H
2 #define SYNCSM_SMTP_H
3 /*
4 * this code is protected by the GNU affero GPLv3 license
5 * author:Sylvain BERTRAND
6 */
7 #include "namespace/smtp.h"
8 /*----------------------------------------------------------------------------*/
9 static void smtp_init(void);
10 static void smtp_send(void);
11 /*----------------------------------------------------------------------------*/
12 #define CLEANUP
13 #include "namespace/smtp.h"
14 #undef CLEANUP
15 #endif
File smtp/namespace/smtp.c added (mode: 100644) (index 0000000..a55261d)
1 /*
2 * this code is protected by the GNU affero GPLv3 license
3 * author:Sylvain BERTRAND
4 */
5 #ifndef CLEANUP
6 #define cmd syncsm_smtp_smtp_c_cmd
7 #define cmd_data syncsm_smtp_smtp_c_cmd_data
8 #define cmd_e syncsm_smtp_smtp_c_cmd_e
9 #define cmd_ehlo syncsm_smtp_smtp_c_cmd_ehlo
10 #define cmd_mail_from syncsm_smtp_smtp_c_cmd_mail_from
11 #define cmd_quit syncsm_smtp_smtp_c_cmd_quit
12 #define cmd_rcpt syncsm_smtp_smtp_c_cmd_rcpt
13 #define dn_al syncsm_smtp_smtp_c_dn_al
14 #define epfd syncsm_smtp_smtp_c_epfd
15 #define ip syncsm_smtp_smtp_c_ip
16 #define mail_send syncsm_smtp_smtp_c_mail_send
17 #define perr_cmd syncsm_smtp_smtp_c_perr_cmd
18 #define perr_ipvx syncsm_smtp_smtp_c_perr_ipvx
19 #define perr_reply_line syncsm_smtp_smtp_c_perr_reply_line
20 #define reply_data syncsm_smtp_smtp_c_reply_data
21 #define reply_data_e syncsm_smtp_smtp_c_reply_data_e
22 #define reply_data_p syncsm_smtp_smtp_c_reply_data_p
23 #define reply_data_recv syncsm_smtp_smtp_c_reply_data_recv
24 #define reply_line syncsm_smtp_smtp_c_reply_line
25 #define reply_line_e syncsm_smtp_smtp_c_reply_line_e
26 #define reply_line_next syncsm_smtp_smtp_c_reply_line_next
27 #define reply_xxx syncsm_smtp_smtp_c_reply_xxx
28 #define sa syncsm_smtp_smtp_c_sa
29 #define sa_init syncsm_smtp_smtp_c_sa_init
30 #define send_cmd syncsm_smtp_smtp_c_send_cmd
31 #define server_send syncsm_smtp_smtp_c_server_send
32 #define servers_send syncsm_smtp_smtp_c_servers_send
33 #define so syncsm_smtp_smtp_c_so
34 #define so_create syncsm_smtp_smtp_c_so_create
35 #define so_recv syncsm_smtp_smtp_c_so_recv
36 #define so_send syncsm_smtp_smtp_c_so_send
37 #define so_shutdown syncsm_smtp_smtp_c_so_shutdown
38 #define so_user_timeout syncsm_smtp_smtp_c_so_user_timeout
39 #define tcp_connect syncsm_smtp_smtp_c_tcp_connect
40 #define tcp_send_timeout_restore syncsm_smtp_smtp_c_tcp_send_timeout_restore
41 #define tcp_send_timeout_set syncsm_smtp_smtp_c_tcp_send_timeout_set
42 #define timer_expired syncsm_smtp_smtp_c_timer_expired
43 #define timer_setup syncsm_smtp_smtp_c_timer_setup
44 #define timer_start syncsm_smtp_smtp_c_timer_start
45 #define timerfd syncsm_smtp_smtp_c_timerfd
46 #define user_timeout_once syncsm_smtp_smtp_c_user_timeout_once
47 /******************************************************************************/
48 #else /* CLEANUP */
49 #undef cmd
50 #undef cmd_data
51 #undef cmd_e
52 #undef cmd_ehlo
53 #undef cmd_mail_from
54 #undef cmd_quit
55 #undef cmd_rcpt
56 #undef dn_al
57 #undef epfd
58 #undef ip
59 #undef mail_send
60 #undef perr_cmd
61 #undef perr_ipvx
62 #undef perr_reply_line
63 #undef reply_data
64 #undef reply_data_e
65 #undef reply_data_p
66 #undef reply_data_recv
67 #undef reply_line
68 #undef reply_line_e
69 #undef reply_line_next
70 #undef reply_xxx
71 #undef sa
72 #undef sa_init
73 #undef send_cmd
74 #undef servers_send
75 #undef so
76 #undef so_create
77 #undef so_recv
78 #undef so_send
79 #undef so_shutdown
80 #undef so_user_timeout
81 #undef tcp_connect
82 #undef tcp_send_timeout_restore
83 #undef tcp_send_timeout_set
84 #undef timer_expired
85 #undef timer_setup
86 #undef timer_start
87 #undef timerfd
88 #undef user_timeout_once
89 #endif
File smtp/rfc.h added (mode: 100644) (index 0000000..5369c4e)
1 #ifndef SMTP_RFC_H
2 #define SMTP_RFC_H
3 /*
4 * this code is protected by the GNU affero GPLv3 license
5 * author:Sylvain BERTRAND
6 */
7 /* minimum of 100 recipients per mail */
8 #define SMTP_RFC_RCPTS_N_MAX 100
9 #define SMTP_RFC_PORT 25
10 #define SMTP_RFC_REPLY_LINE_N_MAX 512
11 #define SMTP_RFC_COMMAND_LINE_N_MAX 512
12 #define SMTP_RFC_INITIAL_REPLY_TIMEOUT_SEC (5 * 60)
13 #define SMTP_RFC_COMMAND_MAIL_FROM_REPLY_TIMEOUT_SEC (5 * 60)
14 #define SMTP_RFC_COMMAND_RCPT_TO_REPLY_TIMEOUT_SEC (5 * 60)
15 #define SMTP_RFC_COMMAND_DATA_REPLY_TIMEOUT_SEC (2 * 60)
16 #define SMTP_RFC_DATA_TERMINATION_REPLY_TIMEOUT_SEC (10 * 60)
17 #define SMTP_RFC_DATA_BLOCK_TIMEOUT_MSEC (3 * 60 * 1000)
18
19 #define SMTP_RFC_TERMINATOR "\r\n.\r\n"
20 #define SMTP_RFC_TERMINATOR_ESCAPE "\r\n..\r\n"
21 #endif
22
File smtp/smtp.c added (mode: 100644) (index 0000000..d077c39)
1 #ifndef SYNCSM_SMTP_SMTP_C
2 #define SYNCSM_SMTP_SMTP_C
3 #include <stdbool.h>
4 #include <stdarg.h>
5 /*----------------------------------------------------------------------------*/
6 #include "config.h"
7 /*----------------------------------------------------------------------------*/
8 #include "ulinux.h"
9 /*----------------------------------------------------------------------------*/
10 #include "dns/rfc.h"
11 #include "smtp/rfc.h"
12 /*----------------------------------------------------------------------------*/
13 #include "perr.h"
14 #include "syncsm.h"
15 /*============================================================================*/
16 #include "namespace/ulinux.h"
17 #include "namespace/syncsm.h"
18 #include "namespace/smtp.h"
19 #include "smtp/namespace/smtp.c"
20 /*----------------------------------------------------------------------------*/
21 static struct dn_al_t *dn_al;
22 static struct ip_t *ip;
23 static si epfd;
24 static si timerfd;
25 static si so;
26 static si so_user_timeout; /* backup of the current system value */
27 static bool user_timeout_once; /* info about the timeout only 1 time */
28 /* we share this struct with the _smaller_ ipv4 version */
29 static struct sockaddr_in6 sa;
30
31 static u8 reply_line[SMTP_RFC_REPLY_LINE_N_MAX];
32 static u8 *reply_line_e;
33
34 static u8 reply_data[SMTP_RFC_REPLY_LINE_N_MAX];
35 static u8 *reply_data_p; /* reply data processing tracker */
36 static u8 *reply_data_e;
37
38 static u8 cmd[SMTP_RFC_COMMAND_LINE_N_MAX];
39 static u8 *cmd_e;
40 /*----------------------------------------------------------------------------*/
41 static void sa_init(void)
42 {
43 #ifdef CONFIG_SMTP_IPV4
44 if (ip->type == ipv4) {
45 struct sockaddr_in *sa_ipv4;
46
47 sa_ipv4 = (struct sockaddr_in*)&sa;
48
49 memset(sa_ipv4, 0, sizeof(*sa_ipv4));
50
51 sa_ipv4->family = AF_INET;
52 sa_ipv4->port = cpu_to_be16(SMTP_RFC_PORT);
53 memcpy(&sa_ipv4->addr, &ip->ipv4_net, sizeof(ip->ipv4_net));
54 } else if (ip->type == ipv6) {
55 #endif
56 memset(&sa, 0, sizeof(sa));
57
58 sa.family = AF_INET6;
59 sa.port = cpu_to_be16(SMTP_RFC_PORT);
60 memcpy(&sa.addr, &ip->ipv6_net, sizeof(ip->ipv6_net));
61 #ifdef CONFIG_SMTP_IPV4
62 }
63 #endif
64 }
65
66 static void perr_ipvx(void)
67 {
68 #ifdef CONFIG_SMTP_IPV4
69 if (ip->type == ipv4) {
70 PERR("ipv4(0x%08lx)", be32_to_cpu(ip->ipv4_net));
71 } else if (ip->type == ipv6) {
72 #endif
73 PERR("ipv6(0x%016lx%016lx)", be64_to_cpu(ip->ipv6_net_h), be64_to_cpu(ip->ipv6_net_l));
74 #ifdef CONFIG_SMTP_IPV4
75 }
76 #endif
77 }
78
79 static bool so_create(void)
80 {
81 sl r;
82 sl af_inet;
83
84 struct epoll_event evts;
85
86 #ifdef CONFIG_SMTP_IPV4
87 if (ip->type == ipv4) {
88 af_inet = AF_INET;
89 } else if (ip->type == ipv6) {
90 #endif
91 af_inet = AF_INET6;
92 #ifdef CONFIG_SMTP_IPV4
93 }
94 #endif
95
96 r = socket(af_inet, SOCK_O_NONBLOCK | SOCK_STREAM, 0);
97 if (ISERR(r)) {
98 PERR("1:SMTP:");perr_ipvx();PERR(":WARNING:%ld:unable to create tcp socket, trying next server\n", r);
99 goto err;
100 }
101
102 so = (si)r;
103
104 memset(&evts, 0, sizeof(evts));
105 evts.events = EPOLLIN;
106 evts.data.fd = so;
107 r = epoll_ctl(epfd, EPOLL_CTL_ADD, so, &evts);
108 if (ISERR(r)) {
109 PERR("1:SMTP:");perr_ipvx();PERR(":WARNING:%ld:unable to add the tcp socket file descriptor to the epoll file descriptor, trying next server\n", r);
110 goto err_close_socket;
111 }
112 return true;
113
114 err_close_socket:
115 r = close(so);
116 if (ISERR(r))
117 {PERR("1:SMTP:");perr_ipvx();PERR(":WARNING:%ld:unable to close the tcp socket file descriptor\n", r);}
118 err:
119 return false;
120 }
121
122 static void so_shutdown(void)
123 {
124 sl r;
125
126 r = epoll_ctl(epfd, EPOLL_CTL_DEL, so, 0);
127 if (ISERR(r))
128 {PERR("1:SMTP:");perr_ipvx();PERR(":WARNING:%ld:unable to remove the server socket from the epoll file descriptor\n", r);}
129
130 r = close(so);
131 if (ISERR(r))
132 {PERR("1:SMTP:");perr_ipvx();PERR(":WARNING:%ld:unable to close the server socket\n", r);}
133 }
134
135 static bool tcp_connect(void)
136 {
137 sl r;
138
139 sa_init();
140 if (!so_create())
141 return false;
142
143 r = connect(so, &sa, sizeof(sa));
144 if (ISERR(r)) {
145 if ((r != -EAGAIN) && (r != -EINPROGRESS) && (r != -EINTR)) {
146 PERR("1:SMTP:");perr_ipvx();PERR(":WARNING:%ld:unable to configure the tcp socket for this server, trying next one\n", r);
147 so_shutdown();
148 return false;
149 }
150 }
151 PERR("1:SMTP:");perr_ipvx();PERR(":tcp socket is connected\n");
152 return true;
153 }
154
155 static void timer_start(u64 s, u64 ns)
156 {
157 sl r;
158 struct itimerspec itimerspec;
159
160 memset(&itimerspec, 0, sizeof(itimerspec));
161
162 /* initial expiration in the futur of current monotonic clock */
163 itimerspec.value.sec = s;
164 itimerspec.value.nsec = ns;
165
166 /* relative initial expiration */
167 r = timerfd_settime(timerfd, 0, &itimerspec, 0);
168 if (ISERR(r)) {
169 PERR("0:SMTP:");perr_ipvx();PERR(":ERROR:%ld:unable to reset and arm our timer for %lu sec and %lu nanosec\n", r, s, ns);
170 exit(1);
171 }
172 }
173
174 static bool timer_expired(void)
175 {
176 sl r;
177 u64 expirations_n; /* the count of expirations of our timer */
178
179 expirations_n = 0;
180
181 loop {/* reads are atomic or err, aka no short reads */
182 r = read(timerfd, &expirations_n, sizeof(u64));
183 if (r != -EINTR);
184 break;
185 }
186
187 if (ISERR(r)) {
188 PERR("0:SMTP:");perr_ipvx();PERR(":ERROR:TIMER:%ld:unable reading the count of expirations\n", r);
189 exit(1);
190 }
191 PERR("1:SMTP:");perr_ipvx();PERR(":TIMER:count of expirations=%lu, trying next server\n", expirations_n);
192
193 if (expirations_n != 0)
194 return true;
195 return false;
196 }
197
198 static bool so_recv(void)
199 {
200 sl r;
201
202 reply_data_e = reply_data;
203 reply_data_p = reply_data; /* reply data processing tracker */
204 loop {
205 r = recvfrom(so, reply_data, SMTP_RFC_REPLY_LINE_N_MAX, 0 ,0
206 ,0);
207 /*
208 * the epoll event told us we have data, do insist till we get
209 * this data
210 */
211 if (r == -EAGAIN || r == -EINTR)
212 continue;
213 if (!ISERR(r))
214 break;
215 PERR("1:SMTP:");perr_ipvx();PERR(":ERROR:%ld:error while reading from the tcp socket, trying next server\n", r);
216 return false;
217 }
218
219 if (r == 0) {
220 PERR("1:SMTP:");perr_ipvx();PERR(":WARNING:the tcp connection was shut down, trying next server\n");
221 return false;
222 }
223
224 reply_data_e += r; /* r is min 1 */
225 return true;
226 }
227
228 static bool reply_data_recv(void)
229 {
230 /*
231 * 2 events if the timer do happen at the same time that some
232 * gram is received
233 */
234 struct epoll_event evts[2];
235 sl evt;
236 sl r;
237
238 loop {
239 memset(evts, 0, sizeof(evts));
240 r = epoll_pwait(epfd, evts, 2, -1, 0);
241 if (r != -EINTR && r != 0)
242 break;
243 PERR("1:SMTP:");perr_ipvx();PERR(":WARNING:epoll_pwait was interruped by a signal or exited with 0 event, restarting\n");
244 }
245 if (ISERR(r)) {
246 PERR("0:SMTP:");perr_ipvx();PERR(":ERROR:%ld:epoll_wait error\n", r);
247 exit(1);
248 }
249
250 /* first: get some tcp data */
251 evt = 0;
252 loop {
253 if (evt == r)
254 break;
255 if (evts[evt].data.fd == so) {
256 if ((evts[evt].events & EPOLLIN) != 0) {
257 if (!so_recv())
258 return false;
259 return true; /* have reply data to process */
260 } else {
261 PERR("0:SMTP:");perr_ipvx();PERR(":ERROR:got unselected event for the tcp socket, events 0x%08x\n", evts[evt].events);
262 exit(1);
263 }
264 break;
265 }
266 ++evt;
267 }
268
269 /* first: check the timer expiration if no reply data arrived */
270 evt = 0;
271 loop {
272 if (evt == r)
273 break;
274
275 if (evts[evt].data.fd == timerfd) {
276 if ((evts[evt].events & EPOLLIN) != 0) {
277 if (timer_expired())
278 return false;
279 } else {
280 PERR("0:SMTP:");perr_ipvx();PERR(":ERROR:got unselected event for the timer, events 0x%08x\n", evts[evt].events);
281 exit(1);
282 }
283 break;
284 }
285 ++evt;
286 }
287 PERR("0:SMTP:");perr_ipvx();PERR(":ERROR:unknown event\n");
288 exit(1);
289 }
290
291 static void perr_reply_line(void)
292 {
293 u8 *c;
294
295 c = reply_line;
296 PERR("1:SMTP:");perr_ipvx();PERR(":REPLY LINE:");
297 loop {
298 if (c == reply_line_e)
299 break;
300 if (is_print(*c))
301 PERR("%c", *c);
302 ++c;
303 }
304 PERR("\n");
305 }
306
307 static void perr_cmd(void)
308 {
309 u8 *c;
310
311 c = cmd;
312 PERR("1:SMTP:");perr_ipvx();PERR(":CMD:");
313 loop {
314 if (c == cmd_e)
315 break;
316 if (is_print(*c))
317 PERR("%c", *c);
318 ++c;
319 }
320 PERR("\n");
321 }
322
323 #define HAVE_REPLY_LINE 0x01
324 #define NEED_MORE_DATA 0x02
325 #define NEXT_SERVER 0x03
326 static u8 reply_line_next(void)
327 {
328 loop {
329 if ((reply_line_e - reply_line) == SMTP_RFC_REPLY_LINE_N_MAX) {
330 PERR("1:SMTP:");perr_ipvx();PERR(":WARNING:reply line too long, trying next server\n");
331 return NEXT_SERVER;
332 }
333
334 if (reply_data_p == reply_data_e)
335 return NEED_MORE_DATA;
336
337 *reply_line_e = *reply_data_p;
338 ++reply_line_e;
339 ++reply_data_p;
340
341 /* checking for the end of line */
342 if (reply_line_e[-1] == '\n'
343 && &reply_line_e[-2] >= reply_line
344 && reply_line_e[-2] == '\r')
345 return HAVE_REPLY_LINE;
346 }
347 }
348
349 static bool reply_xxx(u8 *code, u64 timeout)
350 {
351 u8 line;
352
353 /* a full multiline reply must be received within this time */
354 timer_start(timeout, 0);
355
356 line = 0;
357 reply_line_e = reply_line;
358 loop {
359
360 if (!reply_data_recv())
361 return false;
362
363 loop {
364 u8 r;
365 u16 reply_line_sz;
366
367 if (line == CONFIG_SMTP_REPLY_LINES_N_MAX) {
368 PERR("1:SMTP:");perr_ipvx();PERR(":WARNING:maximum number, %u, of reply lines in a multine reply reached, trying next server\n", CONFIG_SMTP_REPLY_LINES_N_MAX);
369 return false;
370 }
371
372 r = reply_line_next();
373 if (r == NEXT_SERVER)
374 return false;
375 else if (r == NEED_MORE_DATA)
376 break;
377
378 /* r == HAVE_REPLY_LINE */
379
380 perr_reply_line();
381
382 reply_line_sz = reply_line_e - reply_line;
383
384 /*
385 * for a multiline reply we do check the code only
386 * on the last line.
387 * the major state is the line size.
388 */
389 if (reply_line_sz < 3) {
390 PERR("1:SMTP:");perr_ipvx();PERR(":WARNING:reply line too short to contain a code, trying next server\n");
391 return false;
392 }
393
394 if (reply_line_sz == 3) {
395 if (memcmp(reply_line, code, 3)) {
396 return true;
397 } else {
398 PERR("1:SMTP:");perr_ipvx();PERR(":WARNING:wrong reply code from the server, expecting %s, trying next server\n", code);
399 return false;
400 }
401 }
402
403 /*
404 * reply_line_sz > 3
405 *
406 * "1 liner with text" reply or last line of multine
407 * reply
408 */
409 if (reply_line[3] != '-') {
410 if (memcmp(reply_line, code, 3)) {
411 return true;
412 } else {
413 PERR("1:SMTP:");perr_ipvx();PERR(":WARNING:wrong reply code from the server, expecting %s, trying next server\n", code);
414 return false;
415 }
416 }
417
418 /* multiline reply */
419
420 ++line;
421 reply_line_e = reply_line;
422 }
423 }
424 }
425 #undef HAVE_REPLY_LINE
426 #undef NEED_MORE_DATA
427 #undef NEXT_SERVER
428
429 static void tcp_send_timeout_set(void)
430 {
431 si timeout;
432 si timeout_sz;
433 sl r;
434
435 /* backup the current value */
436 timeout_sz = sizeof(so_user_timeout);
437 r = getsockopt(so, IPPROTO_TCP, TCP_USER_TIMEOUT, &so_user_timeout,
438 &timeout_sz);
439 if (ISERR(r))
440 {PERR("1:SMTP:");perr_ipvx();PERR(":WARNING:%ld:failed to get the tcp user timeout(size=%d), continuing anyway\n", r, timeout_sz);}
441
442 if (user_timeout_once) {
443 PERR("1:SMTP:");perr_ipvx();PERR(":current tcp user timeout is %d ms (size is %d bytes)\n", so_user_timeout, timeout_sz);
444 user_timeout_once = false;
445 }
446
447 timeout = SMTP_RFC_DATA_BLOCK_TIMEOUT_MSEC;
448 r = setsockopt(so, IPPROTO_TCP, TCP_USER_TIMEOUT, &timeout,
449 sizeof(timeout));
450 if (ISERR(r))
451 {PERR("1:SMTP:");perr_ipvx();PERR(":WARNING:%ld:failed to set the tcp user timeout to %d ms, continuing anyway\n", r, timeout);}
452
453 }
454
455 static void tcp_send_timeout_restore(void)
456 {
457 sl r;
458
459 r = setsockopt(so, IPPROTO_TCP, TCP_USER_TIMEOUT, &so_user_timeout,
460 sizeof(so_user_timeout));
461 if (ISERR(r))
462 {PERR("1:SMTP:");perr_ipvx();PERR(":WARNING:%ld:failed to restore the tcp user timeout to %d ms, continuing anyway\n", r, so_user_timeout);}
463 }
464
465 static sl so_send(u8 *buf, u64 sz)
466 {
467 sl r;
468 u64 sent_bytes_n;
469
470 tcp_send_timeout_set();
471
472 sent_bytes_n = 0;
473 loop {
474 r = write(so, buf + sent_bytes_n, sz - sent_bytes_n);
475 if (ISERR(r)) {
476 /*
477 * we were told by epoll we can write to the socket,
478 * do insist
479 */
480 if ((r == -EAGAIN) || (r == -EINTR))
481 continue;
482 break;
483 }
484
485 /* we force if r == 0 */
486
487 sent_bytes_n += (u16)r;
488 if (sent_bytes_n == sz)
489 break;
490 }
491
492 tcp_send_timeout_restore();
493 return r;
494 }
495
496 static bool send_cmd(void)
497 {
498 sl r;
499 u64 cmd_sz;
500
501 cmd_sz = cmd_e - cmd;
502
503 r = so_send(cmd, cmd_sz);
504 if (ISERR(r)) {
505 PERR("1:SMTP:");perr_ipvx();PERR(":WARNING:%ld:failed to send the command, trying next server\n", r);
506 return false;
507 }
508 PERR("1:SMTP:");perr_ipvx();PERR(":cmd sent, %u bytes\n", cmd_sz);
509 return true;
510 }
511
512 static bool mail_send(void)
513 {
514 sl r;
515
516 r = so_send(email_v, email_sz_v);
517 if (ISERR(r)) {
518 PERR("1:SMTP:");perr_ipvx();PERR(":WARNING:%ld:failed to send the mail, trying next server\n", r);
519 return false;
520 }
521 PERR("1:SMTP:");perr_ipvx();PERR(":mail sent, %u bytes\n", email_sz_v);
522
523 r = so_send(SMTP_RFC_TERMINATOR, CSTRLEN(SMTP_RFC_TERMINATOR));
524 if (ISERR(r)) {
525 PERR("1:SMTP:");perr_ipvx();PERR(":WARNING:%ld:failed to send the terminator sequence <CRLF>.<CRLF>, trying next server\n", r);
526 return false;
527 }
528 PERR("1:SMTP:");perr_ipvx();PERR(":mail terminator sent, %u bytes\n", CSTRLEN(SMTP_RFC_TERMINATOR));
529 return true;
530 }
531
532 static bool cmd_ehlo(void)
533 {
534 #define CMD "EHLO " CONFIG_SMTP_EHLO_DN_AL "\r\n"
535 memcpy(cmd, CMD, CSTRLEN(CMD));
536 cmd_e = cmd + CSTRLEN(CMD);
537 #undef CMD
538 perr_cmd();
539 return send_cmd();
540 }
541
542 static bool cmd_mail_from(void)
543 {
544 #define CMD "MAIL FROM:<" CONFIG_SMTP_MAIL_FROM "@" \
545 CONFIG_SMTP_EHLO_DN_AL ">\r\n"
546 memcpy(cmd, CMD, CSTRLEN(CMD));
547 cmd_e = cmd + CSTRLEN(CMD);
548 #undef CMD
549 perr_cmd();
550 return send_cmd();
551 }
552
553 static bool cmd_rcpt(struct str_slice_t *rcpt)
554 {
555 u64 len; /* trailing 0 is not accounted */
556 /*
557 * XXX: our slice in actually pointing in the program arguments, which
558 * is a zero terminated string
559 */
560 #define CMD "RCPT TO:<%s>\r\n"
561 len = snprintf(cmd, SMTP_RFC_COMMAND_LINE_N_MAX, CMD, rcpt->s);
562 #undef CMD
563 cmd_e = cmd + len;
564 perr_cmd();
565 return send_cmd();
566 }
567
568 static bool cmd_data(void)
569 {
570 #define CMD "DATA\r\n"
571 memcpy(cmd, CMD, CSTRLEN(CMD));
572 cmd_e = cmd + CSTRLEN(CMD);
573 #undef CMD
574 perr_cmd();
575 return send_cmd();
576 }
577
578 static bool cmd_quit(void)
579 {
580 #define CMD "QUIT\r\n"
581 memcpy(cmd, CMD, CSTRLEN(CMD));
582 cmd_e = cmd + CSTRLEN(CMD);
583 #undef CMD
584 perr_cmd();
585 return send_cmd();
586 }
587
588 /* this is our mail transaction with a specific server */
589 static bool server_send(void)
590 {
591 bool r;
592 u8 rcpt;
593
594 r = true;
595
596 if (!tcp_connect()) {
597 r = false;
598 goto exit;
599 }
600
601 /* from here, we have a connected tcp socket to the server */
602
603 if (!reply_xxx("220", SMTP_RFC_INITIAL_REPLY_TIMEOUT_SEC)) {
604 r = false;
605 goto shutdown_so;
606 }
607
608 if (!cmd_ehlo()) {
609 r = false;
610 goto shutdown_so;
611 }
612
613 if (!reply_xxx("250", SMTP_RFC_INITIAL_REPLY_TIMEOUT_SEC)) {
614 r = false;
615 goto shutdown_so;
616 }
617
618 if (!cmd_mail_from()) {
619 r = false;
620 goto shutdown_so;
621 }
622
623 if (!reply_xxx("250", SMTP_RFC_COMMAND_MAIL_FROM_REPLY_TIMEOUT_SEC)) {
624 r = false;
625 goto shutdown_so;
626 }
627
628 rcpt = 0;
629 loop {
630 if (rcpt == dn_al->local_parts_n)
631 break;
632 if (!cmd_rcpt(&dn_al->local_parts[rcpt])) {
633 r = false;
634 goto shutdown_so;
635 }
636
637 if (!reply_xxx("250",
638 SMTP_RFC_COMMAND_RCPT_TO_REPLY_TIMEOUT_SEC)) {
639 r = false;
640 goto shutdown_so;
641 }
642
643 ++rcpt;
644 }
645
646 if (!cmd_data()) {
647 r = false;
648 goto shutdown_so;
649 }
650
651 if (!reply_xxx("354", SMTP_RFC_COMMAND_DATA_REPLY_TIMEOUT_SEC)) {
652 r = false;
653 goto shutdown_so;
654 }
655
656 if (!mail_send()) {
657 r = false;
658 goto shutdown_so;
659 }
660
661 if (!reply_xxx("250", SMTP_RFC_DATA_TERMINATION_REPLY_TIMEOUT_SEC)) {
662 r = false;
663 goto shutdown_so;
664 }
665
666 /*
667 * XXX: just in case some nasty smtp servers would cancel our email
668 * transaction without a proper quit/221 sequence, but since smtp is
669 * based upon an underlying connected protocol, the tcp termination
670 * should be enough. the smtp protocol rfc should have used
671 * basic "underlying connected protocol operations/events" like
672 * timeout/disconnect.
673 */
674
675 if (!cmd_quit()) {
676 r = false;
677 goto shutdown_so;
678 }
679
680 if (!reply_xxx("221", SMTP_RFC_COMMAND_DATA_REPLY_TIMEOUT_SEC))
681 r = false;
682
683 PERR("0:SMTP:");perr_ipvx();PERR(":mail sent\n");
684
685 shutdown_so:
686 so_shutdown();
687 exit:
688 return r;
689 }
690
691 static void servers_send(void)
692 {
693 u8 i;
694
695 i = 0;
696 loop {
697 if (i == dn_al->smtp_ips_n)
698 return;
699
700 ip = &dn_al->smtp_ips[i];
701 if (server_send())
702 break;
703 ++i;
704 }
705 }
706
707 static void timer_setup(void)
708 {
709 sl r;
710 struct epoll_event evts;
711
712 r = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
713 if (ISERR(r)) {
714 PERR("0:SMTP:ERROR:%ld:unable to create the timer file descriptor\n", r);
715 exit(1);
716 }
717 timerfd = (si)r;
718
719 /* add the timerfd to the epollfd */
720 memset(&evts, 0, sizeof(evts));
721 /* could be EPOLLET since we deal only with 1 expiration */
722 evts.events = EPOLLIN;
723 evts.data.fd = timerfd;
724 r = epoll_ctl(epfd, EPOLL_CTL_ADD, timerfd, &evts);
725 if (ISERR(r)) {
726 PERR("0:SMTP:ERROR:%ld:unable to add the timer file descriptor to the epoll file descriptor\n", r);
727 exit(1);
728 }
729 }
730 /******************************************************************************/
731 /* exported in smtp.h */
732 static void smtp_send(void)
733 {
734 u64 d;
735
736 d = 0;
737 loop {
738 if (d == dn_al_n_v)
739 break;
740
741 dn_al = &dn_al_v[d];
742
743 servers_send();
744 ++d;
745 }
746 }
747
748 static void smtp_init(void)
749 {
750 sl r;
751
752 cmd_e = cmd;
753 user_timeout_once = true;
754
755 r = epoll_create1(0);
756 if (ISERR(r)) {
757 PERR("0:SMTP:ERROR:%ld:unable to create the epoll file descriptor\n", r);
758 exit(1);
759 }
760 epfd = (si)r;
761 timer_setup();
762 }
763 /*----------------------------------------------------------------------------*/
764 #define CLEANUP
765 #include "namespace/ulinux.h"
766 #include "namespace/syncsm.h"
767 #include "namespace/smtp.h"
768 #include "smtp/namespace/smtp.c"
769 #undef CLEANUP
770 #endif
File syncsm.c added (mode: 100644) (index 0000000..1169541)
1 #ifndef SYNCSM_C
2 #define SYNCSM_C
3 /*
4 * this code is protected by the GNU affero GPLv3 license
5 * author:Sylvain BERTRAND
6 */
7 /* compiler stuff */
8 #include <stdbool.h>
9 #include <stdarg.h>
10 /*----------------------------------------------------------------------------*/
11 #include "config.h"
12 /*----------------------------------------------------------------------------*/
13 #include "ulinux.h"
14 /*----------------------------------------------------------------------------*/
15 #include "smtp/rfc.h"
16 /*----------------------------------------------------------------------------*/
17 #include "perr.h"
18 #include "syncsm.h"
19 #include "dns.h"
20 #include "smtp.h"
21 /*============================================================================*/
22 #include "namespace/ulinux.h"
23 #include "namespace/syncsm.h"
24 #include "namespace/dns.h"
25 #include "namespace/smtp.h"
26 #include "namespace/syncsm.c"
27 /*----------------------------------------------------------------------------*/
28 /* array of pointers, on 0 terminated recipient string */
29 static u8 **rcpts;
30 /*----------------------------------------------------------------------------*/
31 /* XXX: quoted-string is not supported */
32 static void rcpt_slices(u8 *rcpt, struct str_slice_t *local_part,
33 struct str_slice_t *dn_al_slice)
34 {
35 u8 *c;
36
37 memset(local_part, 0, sizeof(*local_part));
38 memset(dn_al_slice, 0, sizeof(*dn_al_slice));
39
40 c = rcpt;
41 local_part->s = c;
42
43 loop {
44 if (*c == 0) {
45 dn_al_slice->l = c - 1;
46 break;
47 }
48
49 if (*c == '@') {
50 local_part->l = c - 1;
51 dn_al_slice->s = c + 1;
52 }
53
54 ++c;
55 }
56
57 if (((local_part->l - local_part->s) < 0)
58 || ((dn_al_slice->l - dn_al_slice->s) < 0)) {
59 PERR("SYNCSM:RECIPIENT:ERROR:wrong local/(domain name | address literal) parts for \"%s\"\n", rcpt);
60 exit(1);
61 }
62
63 PERR("SYNCSM:RECIPIENT:local part is \"%.*s\"", local_part->l - local_part->s + 1, local_part->s);
64 PERR(", (domain name | address literal) is \"%.*s\"\n", dn_al_slice->l - dn_al_slice->s + 1, dn_al_slice->s);
65 }
66
67 /* domain part in an smtp mailbox does not have a terminating '.' */
68 static bool slice_eq(struct str_slice_t *a, struct str_slice_t *b)
69 {
70 u64 a_len;
71 u64 b_len;
72
73 a_len = a->l - a->s + 1;
74 b_len = b->l - b->s + 1;
75
76 if (a_len != b_len)
77 return false;
78 if (!memcmp(a->s, b->s, a_len))
79 return false;
80 return true;
81 }
82
83 static bool ip_eq(struct ip_t *a, struct ip_t *b)
84 {
85 #if defined CONFIG_SMTP_IPV4 || defined CONFIG_DNS_IPV4
86 if (a->type != b->type)
87 return false;
88
89 switch (a->type) {
90 case ipv4:
91 if (a->ipv4_net == b->ipv4_net)
92 return true;
93 break;
94 case ipv6:
95 #endif
96 if (memcmp(a->ipv6_net, b->ipv6_net, 16))
97 return true;
98 #if defined CONFIG_SMTP_IPV4 || defined CONFIG_DNS_IPV4
99 break;
100 }
101 #endif
102 return false;
103 }
104
105 static bool dn_al_eq(struct dn_al_t *a, struct dn_al_t *b)
106 {
107 if (a->type != b->type)
108 return false;
109
110 switch (a->type) {
111 case literal_ip:
112 if (ip_eq(&a->smtp_ips[0], &b->smtp_ips[0]))
113 return true;
114 break;
115 case domain_name:
116 if (slice_eq(&a->dn, &b->dn))
117 return true;
118 break;
119 }
120 return false;
121 }
122
123 static struct dn_al_t *dn_al_locate(struct dn_al_t *dn_al)
124 {
125 u64 i;
126
127 i = 0;
128 loop {
129 struct dn_al_t *cur;
130
131 if (i == dn_al_n_v)
132 return 0;
133
134 cur = &dn_al_v[i];
135 if (dn_al_eq(cur, dn_al))
136 return cur;
137 ++i;
138 }
139 }
140
141 static struct dn_al_t *dn_al_insert(struct dn_al_t *dn_al,
142 struct str_slice_t *local_part)
143 {
144 struct dn_al_t *dest;
145
146 dest = dn_al_locate(dn_al);
147
148 if (dest == 0) { /* not found */
149 /* partial "copy constructor" for the oo retards */
150 dest = &dn_al_v[dn_al_n_v];
151
152 dest->type = dn_al->type;
153 dest->local_parts_n = 0;
154
155 if (dn_al->type == domain_name) {
156 memcpy(&dest->dn, &dn_al->dn, sizeof(dest->dn));
157 dest->smtp_ips_n = 0;
158 } else if (dn_al->type == literal_ip) {
159 memcpy(&dest->smtp_ips[0], &dn_al->smtp_ips[0],
160 sizeof(dest->smtp_ips[0]));
161 dest->smtp_ips_n = 1;
162 }
163 ++dn_al_n_v;
164 }
165
166 if (dest->local_parts_n == SMTP_RFC_RCPTS_N_MAX) {
167 PERR("0:SYNCSM:DOMAIN_NAME/ADDRESS_LITERAL:ERROR:too many recipients for \"%s\"\n", local_part->s);
168 exit(1);
169 }
170
171 memcpy(&dest->local_parts[dest->local_parts_n], local_part, sizeof(*local_part));
172 ++(dest->local_parts_n);
173 return dest;
174 }
175
176 static bool to_ipv6(u8 *ipv6, u8 *s, u8 *l)
177 {
178 /* we must check for the tag */
179 if ((l - s + 1) < CSTRLEN("IPv6:"))
180 return false;
181 if (memcmp(s,"IPv6:", CSTRLEN("IPv6:")))
182 return false;
183 if (!to_ipv6_blk(ipv6, s + CSTRLEN("IPv6:"), l))
184 return false;
185 return true;
186 }
187
188 static void rcpt_dn_al_process(struct str_slice_t *local_part,
189 struct str_slice_t *dn_al_slice)
190 {
191 struct dn_al_t rcpt_dn_al;
192 struct dn_al_t *dn_al;
193
194 if (*dn_al_slice->s == '[') { /* it's an address literal */
195 if (*dn_al_slice->l != ']') {
196 PERR("0:SYNCSM:RECIPIENT:ERROR:\"%s\" is missing the closing ']' of its address literal\n", local_part->s);
197 exit(1);
198 }
199
200 if ((dn_al_slice->s + 1) == dn_al_slice->l) {
201 PERR("0:SYNCSM:RECIPIENT:ERROR:\"%s\" has an empty ss literal\n", local_part->s);
202 exit(1);
203 }
204
205 #ifdef CONFIG_SMTP_IPV4
206 if (to_ipv4_blk(&rcpt_dn_al.smtp_ips[0].ipv4_net,
207 dn_al_slice->s + 1, dn_al_slice->l - 1)) {
208 PERR("0:SYNCSM:RECIPIENT:\"%s\" has an IPv4 address literal '0x%08x'\n", local_part->s, be32_to_cpu(rcpt_dn_al.smtp_ips[0].ipv4_net));
209 rcpt_dn_al.smtp_ips[0].type = ipv4;
210 rcpt_dn_al.smtp_ips_n = 1;
211 rcpt_dn_al.type = literal_ip;
212 }
213 else
214 #endif
215 if (to_ipv6(rcpt_dn_al.smtp_ips[0].ipv6_net, dn_al_slice->s + 1,
216 dn_al_slice->l - 1)) {
217 PERR("0:SYNCSM:RECIPIENT:\"%s\" has an IPv6 address literal '0x%016lx%016lx'\n", local_part->s, be64_to_cpu(rcpt_dn_al.smtp_ips[0].ipv6_net_h), be64_to_cpu(rcpt_dn_al.smtp_ips[0].ipv6_net_l));
218 #ifdef CONFIG_SMTP_IPV4
219 rcpt_dn_al.smtp_ips[0].type = ipv6;
220 rcpt_dn_al.smtp_ips_n = 1;
221 rcpt_dn_al.type = literal_ip;
222 #endif
223 } else {
224 #ifdef CONFIG_SMTP_IPV4
225 PERR("0:SYNCSM:RECIPIENT:\"%s\" has neither an IPv4 nor an IPv6 address literal\n", local_part->s);
226 #else
227 PERR("0:SYNCSM:RECIPIENT:\"%s\" has not an IPv6 address literal\n", local_part->s);
228 #endif
229 PERR("0:SYNCSM:RECIPIENT:ERROR:\"%s\", unable to interpret its address literal\n", local_part->s);
230 exit(1);
231 }
232 } else { /* it should be a domain name */
233 rcpt_dn_al.type = domain_name;
234 memcpy(&rcpt_dn_al.dn, dn_al_slice, sizeof(*dn_al_slice));
235 rcpt_dn_al.smtp_ips_n = 0;
236 }
237
238 dn_al = dn_al_insert(&rcpt_dn_al, local_part);
239 PERR("0:SYNCSM:DOMAIN_NAME/ADDRESS_LITERAL:\"%.*s\" has now %d local parts\n", dn_al_slice->l - dn_al_slice->s + 1, dn_al_slice->s, dn_al->local_parts_n);
240 }
241
242 static void rcpt_prepare(u8 *rcpt)
243 {
244 struct str_slice_t local_part;
245 struct str_slice_t dn_al_slice;
246
247 PERR("0:SYNCSM:RECIPIENT:preparing sending email to \"%s\"\n", rcpt);
248
249 rcpt_slices(rcpt, &local_part, &dn_al_slice);
250 rcpt_dn_al_process(&local_part, &dn_al_slice);
251 }
252
253 static void rcpts_prepare(void)
254 {
255 u8 **rcpt;
256
257 rcpt = rcpts;
258 loop {
259 if (*rcpt == 0)
260 break;
261
262 rcpt_prepare(*rcpt);
263
264 ++rcpt;
265 }
266 }
267 #ifdef CONFIG_DISABLE_SMTP_TRANSPARENCY
268 static void email_read_from_stdin(void)
269 {
270 email_sz_v = 0;
271 loop {
272 sl r;
273
274 r = read(0, email_v + email_sz_v, CONFIG_EMAIL_ADDRESS_SPACE
275 - email_sz_v);
276 if (ISERR(r)) {
277 if ((r == -EAGAIN) || (r == -EINTR))
278 continue;
279 PERR("0:SYNCSM:EMAIL:ERROR:%ld:error while reading the email from stdin\n", r);
280 exit(1);
281 }
282
283 if (r == 0) /* end of input */
284 break;
285
286 email_sz_v += (u64)r;
287 }
288
289 PERR("0:SYNCSM:EMAIL:%lu bytes read from stdin\n", email_sz_v);
290 if (email_sz_v == 0) {
291 PERR("0:SYNCSM:EMAIL:no email to send, exiting\n");
292 exit(0);
293 }
294 }
295 #else /* CONFIG_DISABLE_SMTP_TRANSPARENCY */
296 /* will return the count of read bytes. 0 means the end of file */
297 static u64 stdin_read(u8 *buf, u64 at_most_sz)
298 {
299 loop {
300 sl r;
301
302 r = read(0, buf, at_most_sz);
303
304 if (!ISERR(r) && (r >= 0))
305 return (u64)r;
306
307 if ((r != -EAGAIN) && (r != -EINTR)) {
308 PERR("0:SYNCSM:EMAIL:ERROR:%ld:error while reading the email from stdin\n", r);
309 exit(1);
310 }
311 /*
312 * insist on EAGAIN and EINTR, namely untill we get the
313 * end of file or a real error
314 */
315 }
316 }
317
318 static inline void email_write_byte(u8 c)
319 {
320 if (email_sz_v == CONFIG_EMAIL_ADDRESS_SPACE) {
321 PERR("0:SYNCSM:EMAIL:ERROR:email buffer is full (%lu bytes)\n", CONFIG_EMAIL_ADDRESS_SPACE);
322 exit(1);
323 }
324 email_v[email_sz_v] = c;
325 ++email_sz_v;
326 }
327
328 static inline void email_write_bytes(u8 *s, u64 sz)
329 {
330 if ((email_sz_v + sz) > CONFIG_EMAIL_ADDRESS_SPACE) {
331 PERR("0:SYNCSM:EMAIL:ERROR:email buffer too small (max %lu bytes)\n", CONFIG_EMAIL_ADDRESS_SPACE);
332 exit(1);
333 }
334 memcpy(email_v + email_sz_v, s, sz);
335 email_sz_v += sz;
336 }
337 #define NORMAL 0x01
338 #define MATCHING_TERMINATOR 0x02
339 struct match {
340 u8 *terminator_s;
341 u8 *terminator_l;
342 u8 *terminator_expected;
343
344 u64 escapes_n;
345 };
346
347 static u8 normal(struct match *match, u8 c)
348 {
349 if (c == *(match->terminator_s)) {
350 match->terminator_expected = match->terminator_s + 1;
351 return MATCHING_TERMINATOR;
352 }
353 email_write_byte(c);
354 return NORMAL;
355 }
356
357 static void flush_partial_terminator(struct match *match)
358 {
359 u8 *partial_match_l;
360
361 partial_match_l = match->terminator_expected - 1;
362
363 /* write the partially matched sequence */
364 email_write_bytes(match->terminator_s,
365 partial_match_l - match->terminator_s + 1);
366 }
367
368 static u8 matching_terminator(struct match *match, u8 c)
369 {
370 /* not a terminator sequence of chars */
371 if (c != *(match->terminator_expected)) {
372 flush_partial_terminator(match);
373
374 /* then rescan in normal state the "faulty" char */
375 return normal(match, c);
376 }
377
378 /* expected terminator char */
379
380 /* last expected terminator char, escaping! */
381 if (match->terminator_expected == match->terminator_l) {
382 /* write the escape sequence */
383 email_write_bytes(SMTP_RFC_TERMINATOR_ESCAPE,
384 CSTRLEN(SMTP_RFC_TERMINATOR_ESCAPE));
385 ++(match->escapes_n);
386 return NORMAL;
387 }
388
389 /* not the last expected terminator char, next */
390 ++(match->terminator_expected);
391 return MATCHING_TERMINATOR;
392 }
393 /*
394 * XXX: read the WHOLE email and escape the smtp terminator sequence
395 * '<crlf>.<crlf>' to '<crlf>..<crlf>': this is called 'smtp transparency'.
396 * this is a mini regex automaton.
397 */
398 static void email_read_and_escape_from_stdin(void)
399 {
400 static u8 read_buf[CONFIG_BUFSIZ];
401 u8 *c;
402 u8 state;
403 struct match match;
404
405 /* init the escaped email buffer */
406 email_sz_v = 0;
407
408 /* terminator matching */
409 match.terminator_s = SMTP_RFC_TERMINATOR;
410 match.terminator_l = match.terminator_s + CSTRLEN(SMTP_RFC_TERMINATOR) - 1;
411 match.escapes_n = 0;
412
413 /* we start in NORMAL state */
414 state = NORMAL;
415 loop {
416 u64 read_bytes_n;
417 u8 *read_bytes_e;
418
419 read_bytes_n = stdin_read(read_buf, sizeof(read_buf));
420
421 if (read_bytes_n == 0) { /* end of file */
422 if (state == MATCHING_TERMINATOR)
423 flush_partial_terminator(&match);
424 break;
425 }
426
427 read_bytes_e = read_buf + read_bytes_n;
428 c = read_buf;
429
430 loop {
431 if (c == read_bytes_e)
432 break;
433
434 switch (state) {
435 case NORMAL:
436 state = normal(&match, *c);
437 break;
438 case MATCHING_TERMINATOR:
439 state = matching_terminator(&match, *c);
440 break;
441 }
442 ++c;
443 }
444 }
445
446 PERR("0:SYNCSM:EMAIL:%lu bytes from stdin and %u smtp transparency escapes (<CRLF>.<CRLF> to <CRLF>..<CRLF>)\n", email_sz_v, match.escapes_n);
447 if (email_sz_v == 0) {
448 PERR("0:SYNCSM:EMAIL:no email to send, exiting\n");
449 exit(0);
450 }
451 }
452 #undef NORMAL
453 #undef MATCHING_TERMINATOR
454 #endif /* CONFIG_DISABLE_SMTP_TRANSPARENCY */
455 static void stdin_nonblock_status(void)
456 {
457 sl r;
458 ul status_flags;
459
460 r = fcntl(0, F_GETFL, 0);
461 if (ISERR(r)) {
462 PERR("0:SYNCSM:STDIN:ERROR:%ld:unable to get file descriptor status flags\n", r);
463 exit(1);
464 }
465
466 status_flags = (ul)r;
467 status_flags |= O_NONBLOCK;
468
469 r = fcntl(0, F_SETFL, status_flags);
470 if (ISERR(r)) {
471 PERR("0:SYNCSM:STDIN:ERROR:%ld:unable to set file descriptor status flags\n", r);
472 exit(1);
473 }
474 PERR("1:SYNCSM:STDIN:switched to nonblock-ing operations (status flags are 0x%lx/0%lo)\n", status_flags, status_flags);
475 }
476
477 /* we expect the list of rcpts after '--' */
478 static void rcpts_locate_from(u8 *abi_stack)
479 {
480 u8 **args = (u8**)(abi_stack + sizeof(ul)); /* skip argc */
481 u8 arg_idx = 1; /* skip program path */
482
483 loop {
484 u8 *arg = args[arg_idx];
485
486 if (arg == 0)
487 break;
488
489 /* lookup for the '--' separator */
490 if (arg[0] == '-' && arg[1] == '-' && arg[2] == 0) {
491 rcpts = args + arg_idx + 1;
492 break;
493 }
494
495 ++arg_idx;
496 }
497
498 if (rcpts == 0 || rcpts[0] == 0) {
499 PERR("0:SYNCSM:no recipient, exiting\n");
500 exit(0);
501 }
502 }
503
504 static void globals_init(void)
505 {
506 sl r;
507
508 /* initialize a 0 terminating byte */
509 syncsm_dprint_buf[CONFIG_BUFSIZ - 1] = 0;
510
511 rcpts = 0; /* no recipient */
512
513 r = mmap(0, CONFIG_EMAIL_ADDRESS_SPACE, PROT_READ | PROT_WRITE,
514 MAP_PRIVATE | MAP_ANONYMOUS | MAP_UNINITIALIZED, -1, 0);
515 if (ISERR(r)) {
516 PERR("0:SYNCSM:ERROR:%ld:unable to allocate email address space\n", r);
517 exit(1);
518 }
519 email_v = (u8*)r;
520 }
521
522 /* this symbol is outside this compilation unit */
523 void ulinux_start(u8 *abi_stack)
524 {
525 globals_init();
526
527 rcpts_locate_from(abi_stack);
528
529 if (rcpts == 0)
530 exit(0);
531
532 stdin_nonblock_status();
533 #ifndef CONFIG_DISABLE_SMTP_TRANSPARENCY
534 email_read_and_escape_from_stdin();
535 #else
536 email_read_from_stdin();
537 #endif
538 rcpts_prepare();
539
540 dns_init();
541 dns_resolver();
542
543 smtp_init();
544 smtp_send();
545 exit(0);
546 }
547 /*----------------------------------------------------------------------------*/
548 #define CLEANUP
549 #include "namespace/ulinux.h"
550 #include "namespace/syncsm.h"
551 #include "namespace/dns.h"
552 #include "namespace/smtp.h"
553 #include "namespace/syncsm.c"
554 #undef CLEANUP
555 #endif
File syncsm.h added (mode: 100644) (index 0000000..678eed4)
1 #ifndef SYNCSM_H
2 #define SYNCSM_H
3 /*
4 * this code is protected by the GNU affero GPLv3 license
5 * author:Sylvain BERTRAND
6 */
7 #include "namespace/ulinux.h"
8 #include "namespace/syncsm.h"
9 /*----------------------------------------------------------------------------*/
10 struct str_slice_t {
11 u8 *s; /* first valid char */
12 u8 *l; /* last valid char */
13 };
14
15 #if defined CONFIG_SMTP_IPV4 || defined CONFIG_DNS_IPV4
16 enum {/* maybe too generic for ip type constants */
17 ipv6 = 0x01,
18 ipv4 = 0x02
19 };
20 #endif
21 struct ip_t {
22 #if defined CONFIG_SMTP_IPV4 || defined CONFIG_DNS_IPV4
23 u8 type;
24 #endif
25 union {
26 /* net endian, aka big endian */
27 #if defined CONFIG_SMTP_IPV4 || defined CONFIG_DNS_IPV4
28 u32 ipv4_net;
29 #endif
30 union { /* different ways to get into an ipv6 addr*/
31 u8 ipv6_net[16];
32 struct {
33 u64 ipv6_net_h;
34 u64 ipv6_net_l;
35 } PACKED;
36
37 };
38 };
39 };
40 /*----------------------------------------------------------------------------*/
41 /*
42 * (domain name | address literal) index:
43 * for each (domain name | address literal), we'll have the list of recipients
44 */
45 enum {
46 literal_ip = 0x01,
47 domain_name = 0x02
48 };
49 struct dn_al_t {
50 u8 type;
51 struct str_slice_t dn;
52
53 struct str_slice_t local_parts[SMTP_RFC_RCPTS_N_MAX];
54 u8 local_parts_n;
55
56 /*
57 * literal ip: smtp_ips[0] is the ip.
58 * domain name: ordered (based on mx preference if existing) smtp
59 * ips
60 */
61 struct ip_t smtp_ips[CONFIG_DN_SMTP_IPS_N_MAX];
62 u8 smtp_ips_n;
63 };
64 static struct dn_al_t dn_al_v[CONFIG_DN_AL_N_MAX];
65 static u64 dn_al_n_v;
66 /*----------------------------------------------------------------------------*/
67 /*
68 * aarch64 gcc/binutils(6.3.0/2.28) is unable to deal with very large
69 * bss sections. we have to mmap manually.
70 */
71 static u8 *email_v;
72 static u64 email_sz_v;
73 /*----------------------------------------------------------------------------*/
74 #define CLEANUP
75 #include "namespace/ulinux.h"
76 #include "namespace/syncsm.h"
77 #undef CLEANUP
78 #endif
File ulinux.h added (mode: 100644) (index 0000000..82aad12)
1 #ifndef ULINUX_H
2 #define ULINUX_H
3 /*
4 * this code is protected by the GNU affero GPLv3 license
5 * author:Sylvain BERTRAND
6 */
7 #include <ulinux/compiler_types.h>
8 #include <ulinux/compiler_misc.h>
9 #include <ulinux/types.h>
10 #include <ulinux/sysc.h>
11
12 #include <ulinux/error.h>
13 #include <ulinux/start.h>
14 #include <ulinux/mmap.h>
15 #include <ulinux/file.h>
16 #include <ulinux/fcntl.h>
17 #include <ulinux/stat.h>
18 #include <ulinux/socket/socket.h>
19 #if defined CONFIG_DNS_IPV4 || defined CONFIG_SMTP_IPV4
20 #include <ulinux/socket/in.h>
21 #endif
22 #include <ulinux/socket/in6.h>
23 #include <ulinux/socket/tcp.h>
24 #include <ulinux/time.h>
25 #include <ulinux/epoll.h>
26
27 #include <ulinux/utils/qsort.h>
28 #include <ulinux/utils/endian.h>
29 #include <ulinux/utils/mem.h>
30 #include <ulinux/utils/ascii/ascii.h>
31 #include <ulinux/utils/ascii/string/vsprintf.h>
32 #include <ulinux/utils/ascii/block/conv/net/net.h>
33 #endif
File ulinux/README added (mode: 100644) (index 0000000..54970c3)
1 *DO* really check the pattern dir. Those are supposed to be building blocks for
2 your applications.
3
4 Utils source files support the "One Compilation Model" by default, hence, love
5 must be given to namespaces. If you want to contain ulinux utils code into
6 their own compilation units, globally define ULINUX_UTILS_EXTERNAL
File ulinux/TODO added (mode: 100644) (index 0000000..8753c55)
1 Cleanup the patterns, most are broken:
2 - makefile to sh scripts
3 - ISO C90-ish: Move the code to ISO C90 declaration (beginning of a block), etc
4 - etc
File ulinux/archs/aarch64/epoll.h added (mode: 100644) (index 0000000..b23da09)
1 #ifndef ULINUX_ARCH_EPOLL_H
2 #define ULINUX_ARCH_EPOLL_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 #define EPOLL_PACKED
8 #endif
File ulinux/archs/aarch64/mmap.h added (mode: 100644) (index 0000000..fa5054a)
1 #ifndef ULINUX_ARCH_MMAP_H
2 #define ULINUX_ARCH_MMAP_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 #ifndef ULINUX_PAGE_SHIFT
8 #error "ulinux:you must define ULINUX_PAGE_SHIFT macro to 12(page size=4KiB, the most common) or 14(page size=16KiB) or 16(page size=64KiB) because it depends on your linux build configuration"
9 #endif
10 #define ULINUX_PAGE_SZ (1 << ULINUX_PAGE_SHIFT)
11 #endif
File ulinux/archs/aarch64/signal/signal.h added (mode: 100644) (index 0000000..cf1d895)
1 #ifndef ULINUX_ARCH_SIGNAL_SIGNAL_H
2 #define ULINUX_ARCH_SIGNAL_SIGNAL_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7
8 /* keep it arch specific till official merged in kernel */
9 #define ULINUX_SIGHUP 1
10 #define ULINUX_SIGINT 2
11 #define ULINUX_SIGQUIT 3
12 #define ULINUX_SIGILL 4
13 #define ULINUX_SIGTRAP 5
14 #define ULINUX_SIGABRT 6
15 #define ULINUX_SIGIOT 6
16 #define ULINUX_SIGBUS 7
17 #define ULINUX_SIGFPE 8
18 #define ULINUX_SIGKILL 9
19 #define ULINUX_SIGUSR1 10
20 #define ULINUX_SIGSEGV 11
21 #define ULINUX_SIGUSR2 12
22 #define ULINUX_SIGPIPE 13
23 #define ULINUX_SIGALRM 14
24 #define ULINUX_SIGTERM 15
25 #define ULINUX_SIGSTKFLT 16
26 #define ULINUX_SIGCHLD 17
27 #define ULINUX_SIGCONT 18
28 #define ULINUX_SIGSTOP 19
29 #define ULINUX_SIGTSTP 20
30 #define ULINUX_SIGTTIN 21
31 #define ULINUX_SIGTTOU 22
32 #define ULINUX_SIGURG 23
33 #define ULINUX_SIGXCPU 24
34 #define ULINUX_SIGXFSZ 25
35 #define ULINUX_SIGVTALRM 26
36 #define ULINUX_SIGPROF 27
37 #define ULINUX_SIGWINCH 28
38 #define ULINUX_SIGIO 29
39 #define ULINUX_SIGPOLL ULINUX_SIGIO
40 #define ULINUX_SIGPWR 30
41 #define ULINUX_SIGSYS 31
42 #define ULINUX_SIGUNUSED 31
43 /* These should not be considered constants from userland. */
44 #define ULINUX_SIGRTMIN 32
45 #define ULINUX_SIGRTMAX 64
46 #endif
File ulinux/archs/aarch64/start.S added (mode: 100644) (index 0000000..4571872)
1 #ifndef ULINUX_ARCHS_AARCH64_START_S
2 #define ULINUX_ARCHS_AARCH64_START_S
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 .text
8 .globl _start
9 .type _start,@function
10 _start:
11 mov x0, sp
12 b ulinux_start
13 #endif
File ulinux/archs/aarch64/stat.h added (mode: 100644) (index 0000000..28ca12a)
1 #ifndef ULINUX_ARCH_STAT_H
2 #define ULINUX_ARCH_STAT_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 struct ulinux_stat {
8 ulinux_ul dev; /* Device. */
9 ulinux_ul ino; /* File serial number. */
10 ulinux_ui mode; /* File mode. */
11 ulinux_ui nlink; /* Link count. */
12 ulinux_ui uid; /* User ID of the file's owner. */
13 ulinux_ui gid; /* Group ID of the file's group. */
14 ulinux_ul rdev; /* Device number, if device. */
15 ulinux_ul __pad1;
16 ulinux_sl size; /* Size of file, in bytes. */
17 ulinux_si blksize; /* Optimal block size for I/O. */
18 ulinux_si __pad2;
19 ulinux_sl blocks; /* Number 512-byte blocks allocated. */
20 ulinux_sl atime; /* Time of last access. */
21 ulinux_ul atime_nsec;
22 ulinux_sl mtime; /* Time of last modification. */
23 ulinux_ul mtime_nsec;
24 ulinux_sl ctime; /* Time of last status change. */
25 ulinux_ul ctime_nsec;
26 ulinux_ui __unused4;
27 ulinux_ui __unused5;
28 };
29 #endif
File ulinux/archs/aarch64/sysc.S added (mode: 100644) (index 0000000..ef24635)
1 #ifndef ULINUX_ARCHS_AARCH64_SYSC_S
2 #define ULINUX_ARCHS_AARCH64_SYSC_S
3 #endif
File ulinux/archs/aarch64/sysc.h added (mode: 100644) (index 0000000..27164e1)
1 #ifndef ULINUX_ARCH_SYSC_H
2 #define ULINUX_ARCH_SYSC_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7
8 /*
9 * linux takes system call args in registers:
10 * syscall number x8
11 * arg 1 x0
12 * arg 2 x1
13 * arg 3 x2
14 * arg 4 x3
15 * arg 5 x4
16 * arg 6 x5
17 * arg 7 x6
18 *
19 * The compiler is going to form a call by coming here, through PSEUDO, with
20 * arguments
21 * syscall number in the DO_CALL macro
22 * arg 1 x0
23 * arg 2 x1
24 * arg 3 x2
25 * arg 4 x3
26 * arg 5 x4
27 * arg 6 x5
28 * arg 7 x6
29 *
30 */
31
32 /*
33 * List of system calls which are supported as vsyscalls:
34 * CLOCK_GETRES
35 * CLOCK_GETTIME
36 * GETTIMEOFDAY
37 */
38
39 /*============================================================================*/
40 #ifdef __GNUC__
41
42 /* gnu libc derived */
43
44 #define ulinux_sysc(name, nr, args...) \
45 ({ \
46 LOAD_ARGS_##nr(args) \
47 register unsigned long _x8 asm ("x8") = (__ULINUX_NR_##name); \
48 asm volatile ( \
49 "svc 0" \
50 :"=r"(_x0) \
51 :"r"(_x8) ASM_ARGS_##nr \
52 : "memory"); \
53 (long)_x0;})
54
55
56 /*----------------------------------------------------------------------------*/
57 /* x0 is input/output: arg0 as input, sysc return value as output */
58 #define LOAD_ARGS_0() \
59 register long _x0 asm ("x0");
60
61 #define LOAD_ARGS_1(x0) \
62 long _x0tmp = (long)(x0); \
63 LOAD_ARGS_0() \
64 _x0 = _x0tmp;
65
66 #define LOAD_ARGS_2(x0, x1) \
67 long _x1tmp = (long)(x1); \
68 LOAD_ARGS_1(x0) \
69 register long _x1 asm ("x1") = _x1tmp;
70
71 #define LOAD_ARGS_3(x0, x1, x2) \
72 long _x2tmp = (long) (x2); \
73 LOAD_ARGS_2(x0, x1) \
74 register long _x2 asm ("x2") = _x2tmp;
75
76 #define LOAD_ARGS_4(x0, x1, x2, x3) \
77 long _x3tmp = (long)(x3); \
78 LOAD_ARGS_3(x0, x1, x2) \
79 register long _x3 asm ("x3") = _x3tmp;
80
81 #define LOAD_ARGS_5(x0, x1, x2, x3, x4) \
82 long _x4tmp = (long)(x4); \
83 LOAD_ARGS_4(x0, x1, x2, x3) \
84 register long _x4 asm ("x4") = _x4tmp;
85
86 #define LOAD_ARGS_6(x0, x1, x2, x3, x4, x5) \
87 long _x5tmp = (long)(x5); \
88 LOAD_ARGS_5 (x0, x1, x2, x3, x4) \
89 register long _x5 asm ("x5") = _x5tmp;
90
91 #define LOAD_ARGS_7(x0, x1, x2, x3, x4, x5, x6) \
92 long _x6tmp = (long)(x6); \
93 LOAD_ARGS_6 (x0, x1, x2, x3, x4, x5) \
94 register long _x6 asm ("x6") = _x6tmp;
95 /*----------------------------------------------------------------------------*/
96
97
98 /*----------------------------------------------------------------------------*/
99 #define ASM_ARGS_0
100 #define ASM_ARGS_1 , "r"(_x0)
101 #define ASM_ARGS_2 ASM_ARGS_1, "r"(_x1)
102 #define ASM_ARGS_3 ASM_ARGS_2, "r"(_x2)
103 #define ASM_ARGS_4 ASM_ARGS_3, "r"(_x3)
104 #define ASM_ARGS_5 ASM_ARGS_4, "r"(_x4)
105 #define ASM_ARGS_6 ASM_ARGS_5, "r"(_x5)
106 #define ASM_ARGS_7 ASM_ARGS_6, "r"(_x6)
107 /*----------------------------------------------------------------------------*/
108 #else
109 #error "no aarch64 syscall code is defined for your toolchain"
110 #endif /* __GNUC__ */
111
112 /*============================================================================*/
113 /*
114 * this list is probably not up to date, see:
115 * - do generate the linux headers for arm64 arch, and follow linux/unistd.h
116 */
117 #define __ULINUX_NR_io_setup 0
118 #define __ULINUX_NR_io_destroy 1
119 #define __ULINUX_NR_io_submit 2
120 #define __ULINUX_NR_io_cancel 3
121 #define __ULINUX_NR_io_getevents 4
122
123 /* fs/xattr.c */
124 #define __ULINUX_NR_setxattr 5
125 #define __ULINUX_NR_lsetxattr 6
126 #define __ULINUX_NR_fsetxattr 7
127 #define __ULINUX_NR_getxattr 8
128 #define __ULINUX_NR_lgetxattr 9
129 #define __ULINUX_NR_fgetxattr 10
130 #define __ULINUX_NR_listxattr 11
131 #define __ULINUX_NR_llistxattr 12
132 #define __ULINUX_NR_flistxattr 13
133 #define __ULINUX_NR_removexattr 14
134 #define __ULINUX_NR_lremovexattr 15
135 #define __ULINUX_NR_fremovexattr 16
136
137 /* fs/dcache.c */
138 #define __ULINUX_NR_getcwd 17
139
140 /* fs/cookies.c */
141 #define __ULINUX_NR_lookup_dcookie 18
142
143 /* fs/eventfd.c */
144 #define __ULINUX_NR_eventfd2 19
145
146 /* fs/eventpoll.c */
147 #define __ULINUX_NR_epoll_create1 20
148 #define __ULINUX_NR_epoll_ctl 21
149 #define __ULINUX_NR_epoll_pwait 22
150
151 /* fs/fcntl.c */
152 #define __ULINUX_NR_dup 23
153 #define __ULINUX_NR_dup3 24
154 #define __ULINUX_NR_fcntl 25
155
156 /* fs/inotify_user.c */
157 #define __ULINUX_NR_inotify_init1 26
158 #define __ULINUX_NR_inotify_add_watch 27
159 #define __ULINUX_NR_inotify_rm_watch 28
160
161 /* fs/ioctl.c */
162 #define __ULINUX_NR_ioctl 29
163
164 /* fs/ioprio.c */
165 #define __ULINUX_NR_ioprio_set 30
166 #define __ULINUX_NR_ioprio_get 31
167
168 /* fs/locks.c */
169 #define __ULINUX_NR_flock 32
170
171 /* fs/namei.c */
172 #define __ULINUX_NR_mknodat 33
173 #define __ULINUX_NR_mkdirat 34
174 #define __ULINUX_NR_unlinkat 35
175 #define __ULINUX_NR_symlinkat 36
176 #define __ULINUX_NR_linkat 37
177 /* renameat is superseded with flags by renameat2 */
178 #define __ULINUX_NR_renameat 38
179
180 /* fs/namespace.c */
181 #define __ULINUX_NR_umount2 39
182 #define __ULINUX_NR_mount 40
183 #define __ULINUX_NR_pivot_root 41
184
185 /* fs/nfsctl.c */
186 #define __ULINUX_NR_nfsservctl 42
187
188 /* fs/open.c */
189 #define __ULINUX_NR_statfs 43
190 #define __ULINUX_NR_fstatfs 44
191 #define __ULINUX_NR_truncate 45
192 #define __ULINUX_NR_ftruncate 46
193
194 #define __ULINUX_NR_fallocate 47
195 #define __ULINUX_NR_faccessat 48
196 #define __ULINUX_NR_chdir 49
197 #define __ULINUX_NR_fchdir 50
198 #define __ULINUX_NR_chroot 51
199 #define __ULINUX_NR_fchmod 52
200 #define __ULINUX_NR_fchmodat 53
201 #define __ULINUX_NR_fchownat 54
202 #define __ULINUX_NR_fchown 55
203 #define __ULINUX_NR_openat 56
204 #define __ULINUX_NR_close 57
205 #define __ULINUX_NR_vhangup 58
206
207 /* fs/pipe.c */
208 #define __ULINUX_NR_pipe2 59
209
210 /* fs/quota.c */
211 #define __ULINUX_NR_quotactl 60
212
213 /* fs/readdir.c */
214 #define __ULINUX_NR_getdents64 61
215
216 /* fs/read_write.c */
217 #define __ULINUX_NR_lseek 62
218 #define __ULINUX_NR_read 63
219 #define __ULINUX_NR_write 64
220 #define __ULINUX_NR_readv 65
221 #define __ULINUX_NR_writev 66
222 #define __ULINUX_NR_pread64 67
223 #define __ULINUX_NR_pwrite64 68
224 #define __ULINUX_NR_preadv 69
225 #define __ULINUX_NR_pwritev 70
226
227 /* fs/sendfile.c */
228 #define __ULINUX_NR_sendfile 71
229
230 /* fs/select.c */
231 #define __ULINUX_NR_pselect6 72
232 #define __ULINUX_NR_ppoll 73
233
234 /* fs/signalfd.c */
235 #define __ULINUX_NR_signalfd4 74
236
237 /* fs/splice.c */
238 #define __ULINUX_NR_vmsplice 75
239 #define __ULINUX_NR_splice 76
240 #define __ULINUX_NR_tee 77
241
242 /* fs/stat.c */
243 #define __ULINUX_NR_readlinkat 78
244 #define __ULINUX_NR_fstatat 79
245 #define __ULINUX_NR_fstat 80
246
247 /* fs/sync.c */
248 #define __ULINUX_NR_sync 81
249 #define __ULINUX_NR_fsync 82
250 #define __ULINUX_NR_fdatasync 83
251 #define __ULINUX_NR_sync_file_range 84
252
253 /* fs/timerfd.c */
254 #define __ULINUX_NR_timerfd_create 85
255 #define __ULINUX_NR_timerfd_settime 86
256 #define __ULINUX_NR_timerfd_gettime 87
257
258 /* fs/utimes.c */
259 #define __ULINUX_NR_utimensat 88
260
261 /* kernel/acct.c */
262 #define __ULINUX_NR_acct 89
263
264 /* kernel/capability.c */
265 #define __ULINUX_NR_capget 90
266 #define __ULINUX_NR_capset 91
267
268 /* kernel/exec_domain.c */
269 #define __ULINUX_NR_personality 92
270
271 /* kernel/exit.c */
272 #define __ULINUX_NR_exit 93
273 #define __ULINUX_NR_exit_group 94
274 #define __ULINUX_NR_waitid 95
275
276 /* kernel/fork.c */
277 #define __ULINUX_NR_set_tid_address 96
278 #define __ULINUX_NR_unshare 97
279
280 /* kernel/futex.c */
281 #define __ULINUX_NR_futex 98
282 #define __ULINUX_NR_set_robust_list 99
283 #define __ULINUX_NR_get_robust_list 100
284
285 /* kernel/hrtimer.c */
286 #define __ULINUX_NR_nanosleep 101
287
288 /* kernel/itimer.c */
289 #define __ULINUX_NR_getitimer 102
290 #define __ULINUX_NR_setitimer 103
291
292 /* kernel/kexec.c */
293 #define __ULINUX_NR_kexec_load 104
294
295 /* kernel/module.c */
296 #define __ULINUX_NR_init_module 105
297 #define __ULINUX_NR_delete_module 106
298
299 /* kernel/posix-timers.c */
300 #define __ULINUX_NR_timer_create 107
301 #define __ULINUX_NR_timer_gettime 108
302 #define __ULINUX_NR_timer_getoverrun 109
303 #define __ULINUX_NR_timer_settime 110
304 #define __ULINUX_NR_timer_delete 111
305 #define __ULINUX_NR_clock_settime 112
306 #define __ULINUX_NR_clock_gettime 113
307 #define __ULINUX_NR_clock_getres 114
308 #define __ULINUX_NR_clock_nanosleep 115
309
310 /* kernel/printk.c */
311 #define __ULINUX_NR_syslog 116
312
313 /* kernel/ptrace.c */
314 #define __ULINUX_NR_ptrace 117
315
316 /* kernel/sched/core.c */
317 #define __ULINUX_NR_sched_setparam 118
318 #define __ULINUX_NR_sched_setscheduler 119
319 #define __ULINUX_NR_sched_getscheduler 120
320 #define __ULINUX_NR_sched_getparam 121
321 #define __ULINUX_NR_sched_setaffinity 122
322 #define __ULINUX_NR_sched_getaffinity 123
323 #define __ULINUX_NR_sched_yield 124
324 #define __ULINUX_NR_sched_get_priority_max 125
325 #define __ULINUX_NR_sched_get_priority_min 126
326 #define __ULINUX_NR_sched_rr_get_interval 127
327
328 /* kernel/signal.c */
329 #define __ULINUX_NR_restart_syscall 128
330 #define __ULINUX_NR_kill 129
331 #define __ULINUX_NR_tkill 130
332 #define __ULINUX_NR_tgkill 131
333 #define __ULINUX_NR_sigaltstack 132
334 #define __ULINUX_NR_rt_sigsuspend 133
335 #define __ULINUX_NR_rt_sigaction 134
336 #define __ULINUX_NR_rt_sigprocmask 135
337 #define __ULINUX_NR_rt_sigpending 136
338 #define __ULINUX_NR_rt_sigtimedwait 137
339 #define __ULINUX_NR_rt_sigqueueinfo 138
340 #define __ULINUX_NR_rt_sigreturn 139
341
342 /* kernel/sys.c */
343 #define __ULINUX_NR_setpriority 140
344 #define __ULINUX_NR_getpriority 141
345 #define __ULINUX_NR_reboot 142
346 #define __ULINUX_NR_setregid 143
347 #define __ULINUX_NR_setgid 144
348 #define __ULINUX_NR_setreuid 145
349 #define __ULINUX_NR_setuid 146
350 #define __ULINUX_NR_setresuid 147
351 #define __ULINUX_NR_getresuid 148
352 #define __ULINUX_NR_setresgid 149
353 #define __ULINUX_NR_getresgid 150
354 #define __ULINUX_NR_setfsuid 151
355 #define __ULINUX_NR_setfsgid 152
356 #define __ULINUX_NR_times 153
357 #define __ULINUX_NR_setpgid 154
358 #define __ULINUX_NR_getpgid 155
359 #define __ULINUX_NR_getsid 156
360 #define __ULINUX_NR_setsid 157
361 #define __ULINUX_NR_getgroups 158
362 #define __ULINUX_NR_setgroups 159
363 #define __ULINUX_NR_uname 160
364 #define __ULINUX_NR_sethostname 161
365 #define __ULINUX_NR_setdomainname 162
366
367 /* getrlimit and setrlimit are superseded with prlimit64 */
368 #define __ULINUX_NR_getrlimit 163
369 #define __ULINUX_NR_setrlimit 164
370
371 #define __ULINUX_NR_getrusage 165
372 #define __ULINUX_NR_umask 166
373 #define __ULINUX_NR_prctl 167
374 #define __ULINUX_NR_getcpu 168
375
376 /* kernel/time.c */
377 #define __ULINUX_NR_gettimeofday 169
378 #define __ULINUX_NR_settimeofday 170
379 #define __ULINUX_NR_adjtimex 171
380
381 /* kernel/timer.c */
382 #define __ULINUX_NR_getpid 172
383 #define __ULINUX_NR_getppid 173
384 #define __ULINUX_NR_getuid 174
385 #define __ULINUX_NR_geteuid 175
386 #define __ULINUX_NR_getgid 176
387 #define __ULINUX_NR_getegid 177
388 #define __ULINUX_NR_gettid 178
389 #define __ULINUX_NR_sysinfo 179
390
391 /* ipc/mqueue.c */
392 #define __ULINUX_NR_mq_open 180
393 #define __ULINUX_NR_mq_unlink 181
394 #define __ULINUX_NR_mq_timedsend 182
395 #define __ULINUX_NR_mq_timedreceive 183
396 #define __ULINUX_NR_mq_notify 184
397 #define __ULINUX_NR_mq_getsetattr 185
398
399 /* ipc/msg.c */
400 #define __ULINUX_NR_msgget 186
401 #define __ULINUX_NR_msgctl 187
402 #define __ULINUX_NR_msgrcv 188
403 #define __ULINUX_NR_msgsnd 189
404
405 /* ipc/sem.c */
406 #define __ULINUX_NR_semget 190
407 #define __ULINUX_NR_semctl 191
408 #define __ULINUX_NR_semtimedop 192
409 #define __ULINUX_NR_semop 193
410
411 /* ipc/shm.c */
412 #define __ULINUX_NR_shmget 194
413 #define __ULINUX_NR_shmctl 195
414 #define __ULINUX_NR_shmat 196
415 #define __ULINUX_NR_shmdt 197
416
417 /* net/socket.c */
418 #define __ULINUX_NR_socket 198
419 #define __ULINUX_NR_socketpair 199
420 #define __ULINUX_NR_bind 200
421 #define __ULINUX_NR_listen 201
422 #define __ULINUX_NR_accept 202
423 #define __ULINUX_NR_connect 203
424 #define __ULINUX_NR_getsockname 204
425 #define __ULINUX_NR_getpeername 205
426 #define __ULINUX_NR_sendto 206
427 #define __ULINUX_NR_recvfrom 207
428 #define __ULINUX_NR_setsockopt 208
429 #define __ULINUX_NR_getsockopt 209
430 #define __ULINUX_NR_shutdown 210
431 #define __ULINUX_NR_sendmsg 211
432 #define __ULINUX_NR_recvmsg 212
433
434 /* mm/filemap.c */
435 #define __ULINUX_NR_readahead 213
436
437 /* mm/nommu.c, also with MMU */
438 #define __ULINUX_NR_brk 214
439 #define __ULINUX_NR_munmap 215
440 #define __ULINUX_NR_mremap 216
441
442 /* security/keys/keyctl.c */
443 #define __ULINUX_NR_add_key 217
444 #define __ULINUX_NR_request_key 218
445 #define __ULINUX_NR_keyctl 219
446
447 /* arch/example/kernel/sys_example.c */
448 #define __ULINUX_NR_clone 220
449 #define __ULINUX_NR_execve 221
450
451 #define __ULINUX_NR_mmap 222
452 /* mm/fadvise.c */
453 #define __ULINUX_NR_fadvise64 223
454
455 /* mm/, CONFIG_MMU only */
456 #define __ULINUX_NR_swapon 224
457 #define __ULINUX_NR_swapoff 225
458 #define __ULINUX_NR_mprotect 226
459 #define __ULINUX_NR_msync 227
460 #define __ULINUX_NR_mlock 228
461 #define __ULINUX_NR_munlock 229
462 #define __ULINUX_NR_mlockall 230
463 #define __ULINUX_NR_munlockall 231
464 #define __ULINUX_NR_mincore 232
465 #define __ULINUX_NR_madvise 233
466 #define __ULINUX_NR_remap_file_pages 234
467 #define __ULINUX_NR_mbind 235
468 #define __ULINUX_NR_get_mempolicy 236
469 #define __ULINUX_NR_set_mempolicy 237
470 #define __ULINUX_NR_migrate_pages 238
471 #define __ULINUX_NR_move_pages 239
472
473 #define __ULINUX_NR_rt_tgsigqueueinfo 240
474 #define __ULINUX_NR_perf_event_open 241
475 #define __ULINUX_NR_accept4 242
476 #define __ULINUX_NR_recvmmsg 243
477
478 /*
479 * Architectures may provide up to 16 syscalls of their own
480 * starting with this value.
481 */
482 #define __ULINUX_NR_arch_specific_syscall 244
483
484 #define __ULINUX_NR_wait4 260
485 #define __ULINUX_NR_prlimit64 261
486 #define __ULINUX_NR_fanotify_init 262
487 #define __ULINUX_NR_fanotify_mark 263
488 #define __ULINUX_NR_name_to_handle_at 264
489 #define __ULINUX_NR_open_by_handle_at 265
490 #define __ULINUX_NR_clock_adjtime 266
491 #define __ULINUX_NR_syncfs 267
492 #define __ULINUX_NR_setns 268
493 #define __ULINUX_NR_sendmmsg 269
494 #define __ULINUX_NR_process_vm_readv 270
495 #define __ULINUX_NR_process_vm_writev 271
496 #define __ULINUX_NR_kcmp 272
497 #define __ULINUX_NR_finit_module 273
498 #define __ULINUX_NR_sched_setattr 274
499 #define __ULINUX_NR_sched_getattr 275
500 #define __ULINUX_NR_renameat2 276
501 #define __ULINUX_NR_seccomp 277
502 #define __ULINUX_NR_getrandom 278
503 #define __ULINUX_NR_memfd_create 279
504 #define __ULINUX_NR_bpf 280
505 #define __ULINUX_NR_execveat 281
506 #define __ULINUX_NR_userfaultfd 282
507 #define __ULINUX_NR_membarrier 283
508 #define __ULINUX_NR_mlock2 284
509 #define __ULINUX_NR_copy_file_range 285
510 #define __ULINUX_NR_preadv2 286
511 #define __ULINUX_NR_pwritev2 287
512 #define __ULINUX_NR_pkey_mprotect 288
513 #define __ULINUX_NR_pkey_alloc 289
514 #define __ULINUX_NR_pkey_free 290
515 #define __ULINUX_NR_statx 291
516 #define __ULINUX_NR_io_pgetevents 292
517 #define __ULINUX_NR_rseq 293
518 #define __ULINUX_NR_kexec_file_load 294
519 /* 295 through 402 are unassigned to sync up with generic numbers, don't use */
520
521 #define __ULINUX_NR_pidfd_send_signal 424
522 #define __ULINUX_NR_io_uring_setup 425
523 #define __ULINUX_NR_io_uring_enter 426
524 #define __ULINUX_NR_io_uring_register 427
525 #define __ULINUX_NR_open_tree 428
526 #define __ULINUX_NR_move_mount 429
527 #define __ULINUX_NR_fsopen 430
528 #define __ULINUX_NR_fsconfig 431
529 #define __ULINUX_NR_fsmount 432
530 #define __ULINUX_NR_fspick 433
531 /*---------------------------------------------------------------------------*/
532 /* the following is a mapping to get the same on x86_64 and aarch64 */
533 #define __ULINUX_NR_newfstatat __ULINUX_NR_fstatat
534 #endif /* ULINUX_ARCH_SYSC_H */
File ulinux/archs/aarch64/types.h added (mode: 100644) (index 0000000..8d77ba9)
1 #ifndef ULINUX_ARCH_TYPES_H
2 #define ULINUX_ARCH_TYPES_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 #define BITS_PER_LONG 64
8 #endif
File ulinux/archs/aarch64/utils/endian.S added (mode: 100644) (index 0000000..079d98d)
1 #ifndef ULINUX_ARCHS_AARCH64_UTILS_ENDIAN_S
2 #define ULINUX_ARCHS_AARCH64_UTILS_ENDIAN_S
3 #endif
File ulinux/archs/aarch64/utils/endian.h added (mode: 100644) (index 0000000..71c6f0c)
1 #ifndef ULINUX_ARCH_UTILS_ENDIAN_H
2 #define ULINUX_ARCH_UTILS_ENDIAN_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7
8 #ifdef __GNUC__
9 static inline ulinux_u16 ulinux_cpu_to_be16(ulinux_u16 v)
10 {
11 return __builtin_bswap16(v);
12 }
13 #define ulinux_be16_to_cpu(v) ulinux_cpu_to_be16(v)
14
15 static inline ulinux_u32 ulinux_cpu_to_be32(ulinux_u32 v)
16 {
17 return __builtin_bswap32(v);
18 }
19 #define ulinux_be32_to_cpu(v) ulinux_cpu_to_be32(v)
20
21 static inline ulinux_u64 ulinux_cpu_to_be64(ulinux_u64 v)
22 {
23 return __builtin_bswap64(v);
24 }
25 #define ulinux_be64_to_cpu(v) ulinux_cpu_to_be64(v)
26 #else
27 #error "missing endian conversions for your toolchain"
28 #endif
29
30 /* little endian */
31 #define ulinux_cpu_to_le32(v) (v)
32 #define ulinux_cpu_to_le64(v) (v)
33 #define ulinux_le32_to_cpu(v) (v)
34 #define ulinux_le64_to_cpu(v) (v)
35 #endif
File ulinux/archs/x86_64/epoll.h added (mode: 100644) (index 0000000..0bfa437)
1 #ifndef ULINUX_ARCH_EPOLL_H
2 #define ULINUX_ARCH_EPOLL_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 #ifndef PACKED
8 #error "missing x86_64 PACKED macro"
9 #endif
10 #define EPOLL_PACKED PACKED
11 #endif
File ulinux/archs/x86_64/mmap.h added (mode: 100644) (index 0000000..3a0a039)
1 #ifndef ULINUX_ARCH_MMAP_H
2 #define ULINUX_ARCH_MMAP_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 /* only 4KiB base page size */
8 #define ULINUX_PAGE_SHIFT 12
9 #define ULINUX_PAGE_SZ (1 << ULINUX_PAGE_SHIFT)
10 #endif
File ulinux/archs/x86_64/signal/handler.c added (mode: 100644) (index 0000000..723d15e)
1 /*
2 * this code is protected by the GNU affero GPLv3
3 * author:Sylvain BERTRAND
4 */
5
6 /* XXX: PROBABLY DEAD AND OBSOLETE CODE */
7
8 #define ULINUX_ARCH_C
9 /*
10 * signal handler setup is arch depend
11 * on x86_84, a syscall restorer must be called and that must be rt_sigreturn
12 * in order to get a usable stack-->naked syscall 15, namely rt_sigreturn
13 * gdb won't be able to deal with the signal handler
14 */
15 extern void restore_rt(void) asm ("__restore_rt");
16 asm(
17 ".text\n"
18 "__restore_rt:\n"
19 " movq $15,%rax\n"
20 " syscall\n");
21
22 ulinux_sl arch_sigaction(ulinux_sl num,struct ulinux_sigaction *kact,
23 struct ulinux_sigaction *okact)
24 {
25 kact->sa_flags|=SA_RESTORER;/* *MUST* have a restorer on x86_64, see above */
26 kact->sa_restorer=restore_rt;/* bear rt_sigreturn syscall */
27 return sysc(rt_sigaction,4,num,kact,okact,sizeof(ulinux_ul));
28 }
File ulinux/archs/x86_64/signal/handler.h added (mode: 100644) (index 0000000..d48b787)
1 /*******************************************************************************
2 this code is protected by the GNU affero GPLv3
3 author:Sylvain BERTRAND (sylvain.bertrand AT gmail dot com)
4 *******************************************************************************/
5 #ifndef ULINUX_ARCH_SIGNAL_HANDLER_H
6 #define ULINUX_ARCH_SIGNAL_HANDLER_H
7 #define ULINUX_SA_RESTORER 0x04000000
8 extern ulinux_sl arch_sigaction(ulinux_sl num,struct ulinux_sigaction *kact,
9 struct ulinux_sigaction *okact);
10 #endif
File ulinux/archs/x86_64/signal/siginfo.h added (mode: 100644) (index 0000000..c82b293)
1 #ifndef ULINUX_ARCH_SIGNAL_SIGINFO_H
2 #define ULINUX_ARCH_SIGNAL_SIGINFO_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 union ulinux_sigval {
8 ulinux_si i;
9 void* ptr;
10 };
11
12 #define ULINUX_SI_PREAMBLE_SIZE (4*sizeof(ulinux_si))
13 #define ULINUX_SI_MAX_SIZE 128
14 #define ULINUX_SI_PAD_SIZE ((ULINUX_SI_MAX_SIZE-ULINUX_SI_PREAMBLE_SIZE)\
15 /sizeof(ulinux_si))
16
17 struct ulinux_siginfo{
18 ulinux_si si_signo;
19 ulinux_si si_errno;
20 ulinux_si si_code;
21
22 union {
23 ulinux_si pad[ULINUX_SI_PAD_SIZE];
24
25 /* kill() */
26 struct{
27 ulinux_si pid; /* sender's pid */
28 ulinux_ui uid; /* sender's uid */
29 } kill;
30
31 /* posix.1b timers */
32 struct {
33 ulinux_si tid; /* timer id */
34 ulinux_si overrun; /* overrun count */
35 union ulinux_sigval sigval; /* same as below */
36 ulinux_si sys_private; /* not to be passed to user */
37 } timer;
38
39 /* posix.1b signals */
40 struct {
41 ulinux_si pid; /* sender's pid */
42 ulinux_ui uid; /* sender's uid */
43 union ulinux_sigval sigval;
44 } rt;
45
46 /* SIGCHLD */
47 struct {
48 ulinux_si pid; /* which child */
49 ulinux_us uid; /* sender's uid */
50 ulinux_si status; /* exit code */
51 ulinux_sl utime;
52 ulinux_sl stime;
53 } sigchld;
54
55 /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
56 struct {
57 void* addr; /* faulting insn/memory ref. */
58 ulinux_ss addr_lsb; /* lsb of the reported address */
59 } sigfault;
60
61 /* SIGPOLL */
62 struct {
63 ulinux_sl band; /* POLL_IN, POLL_OUT, POLL_MSG */
64 ulinux_si fd;
65 } sigpoll;
66 } fields;
67 };
68 #endif
File ulinux/archs/x86_64/signal/signal.h added (mode: 100644) (index 0000000..0987d63)
1 #ifndef ULINUX_ARCH_SIGNAL_SIGNAL_H
2 #define ULINUX_ARCH_SIGNAL_SIGNAL_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7
8 /* keep it arch specific till official merged in kernel */
9 #define ULINUX_SIGHUP 1
10 #define ULINUX_SIGINT 2
11 #define ULINUX_SIGQUIT 3
12 #define ULINUX_SIGILL 4
13 #define ULINUX_SIGTRAP 5
14 #define ULINUX_SIGABRT 6
15 #define ULINUX_SIGIOT 6
16 #define ULINUX_SIGBUS 7
17 #define ULINUX_SIGFPE 8
18 #define ULINUX_SIGKILL 9
19 #define ULINUX_SIGUSR1 10
20 #define ULINUX_SIGSEGV 11
21 #define ULINUX_SIGUSR2 12
22 #define ULINUX_SIGPIPE 13
23 #define ULINUX_SIGALRM 14
24 #define ULINUX_SIGTERM 15
25 #define ULINUX_SIGSTKFLT 16
26 #define ULINUX_SIGCHLD 17
27 #define ULINUX_SIGCONT 18
28 #define ULINUX_SIGSTOP 19
29 #define ULINUX_SIGTSTP 20
30 #define ULINUX_SIGTTIN 21
31 #define ULINUX_SIGTTOU 22
32 #define ULINUX_SIGURG 23
33 #define ULINUX_SIGXCPU 24
34 #define ULINUX_SIGXFSZ 25
35 #define ULINUX_SIGVTALRM 26
36 #define ULINUX_SIGPROF 27
37 #define ULINUX_SIGWINCH 28
38 #define ULINUX_SIGIO 29
39 #define ULINUX_SIGPOLL ULINUX_SIGIO
40 #define ULINUX_SIGPWR 30
41 #define ULINUX_SIGSYS 31
42 #define ULINUX_SIGUNUSED 31
43 /* These should not be considered constants from userland. */
44 #define ULINUX_SIGRTMIN 32
45 #define ULINUX_SIGRTMAX 64
46 #endif
File ulinux/archs/x86_64/start.S added (mode: 100644) (index 0000000..9de67b9)
1 #ifndef ULINUX_ARCHS_X86_64_START_S
2 #define ULINUX_ARCHS_X86_64_START_S
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 .text
8 .globl _start
9 .type _start,@function
10 _start:
11 xorl %ebp, %ebp /* suggested by abi */
12 movq %rsp, %rdi /* stack pointer:argc, argv, envp, auxv */
13 /*
14 * 32 bytes DOWN aligned stack: if already aligned, it is fine since
15 * the stack pointer is decremented before pushing/storing a value on
16 * this stack, aka we don't lose argc
17 */
18 andq $~31, %rsp
19 jmp ulinux_start
20 #endif
File ulinux/archs/x86_64/stat.h added (mode: 100644) (index 0000000..c16e455)
1 #ifndef ULINUX_ARCH_STAT_H
2 #define ULINUX_ARCH_STAT_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 struct ulinux_stat {
8 ulinux_ul dev;
9 ulinux_ul ino;
10 ulinux_ul nlink;
11 ulinux_ui mode;
12 ulinux_ui uid;
13 ulinux_ui gid;
14 ulinux_ui __pad0;
15 ulinux_ul rdev;
16 ulinux_sl size;
17 ulinux_sl blksize;
18 ulinux_sl blocks; /* Number 512-byte blocks allocated. */
19 ulinux_ul atime;
20 ulinux_ul atime_nsec;
21 ulinux_ul mtime;
22 ulinux_ul mtime_nsec;
23 ulinux_ul ctime;
24 ulinux_ul ctime_nsec;
25 ulinux_sl __unused[3];
26 };
27 #endif
File ulinux/archs/x86_64/sysc.S added (mode: 100644) (index 0000000..de587fb)
1 #ifndef ULINUX_ARCHS_X86_64_SYSC_S
2 #define ULINUX_ARCHS_X86_64_SYSC_S
3 #endif
File ulinux/archs/x86_64/sysc.h added (mode: 100644) (index 0000000..7aba487)
1 #ifndef ULINUX_ARCH_SYSC_H
2 #define ULINUX_ARCH_SYSC_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7
8 /*============================================================================*/
9 #ifdef __GNUC__
10
11 /* gnu libc derived */
12
13 #define ulinux_sysc(name, nr, args...) \
14 ({ \
15 unsigned long resultvar; \
16 SYSC_LOAD_ARGS_##nr(args) \
17 SYSC_LOAD_REGS_##nr \
18 asm volatile ( \
19 "syscall\n\t" \
20 :"=a"(resultvar) \
21 :"0"(__ULINUX_NR_##name)SYSC_ASM_ARGS_##nr \
22 :"memory","cc","r11","cx"); \
23 (long)resultvar;})
24
25 /*----------------------------------------------------------------------------*/
26 #define SYSC_LOAD_ARGS_0()
27 #define SYSC_LOAD_REGS_0
28 #define SYSC_ASM_ARGS_0
29 /*----------------------------------------------------------------------------*/
30
31
32 /*----------------------------------------------------------------------------*/
33 #define SYSC_LOAD_ARGS_1(a1) \
34 long __arg1 = (long)(a1); \
35 SYSC_LOAD_ARGS_0()
36
37 #define SYSC_LOAD_REGS_1 \
38 register long _a1 asm ("rdi") = __arg1; \
39 SYSC_LOAD_REGS_0
40
41 #define SYSC_ASM_ARGS_1 SYSC_ASM_ARGS_0, "r"(_a1)
42 /*----------------------------------------------------------------------------*/
43
44
45 /*----------------------------------------------------------------------------*/
46 #define SYSC_LOAD_ARGS_2(a1, a2) \
47 long __arg2 = (long)(a2); \
48 SYSC_LOAD_ARGS_1(a1)
49
50 #define SYSC_LOAD_REGS_2 \
51 register long _a2 asm ("rsi") = __arg2; \
52 SYSC_LOAD_REGS_1
53
54 #define SYSC_ASM_ARGS_2 SYSC_ASM_ARGS_1, "r"(_a2)
55 /*----------------------------------------------------------------------------*/
56
57
58 /*----------------------------------------------------------------------------*/
59 #define SYSC_LOAD_ARGS_3(a1, a2, a3) \
60 long __arg3 = (long)(a3); \
61 SYSC_LOAD_ARGS_2(a1, a2)
62
63 #define SYSC_LOAD_REGS_3 \
64 register long _a3 asm ("rdx") = __arg3; \
65 SYSC_LOAD_REGS_2
66
67 #define SYSC_ASM_ARGS_3 SYSC_ASM_ARGS_2, "r"(_a3)
68 /*----------------------------------------------------------------------------*/
69
70
71 /*----------------------------------------------------------------------------*/
72 #define SYSC_LOAD_ARGS_4(a1, a2, a3, a4) \
73 long __arg4 = (long)(a4); \
74 SYSC_LOAD_ARGS_3(a1, a2, a3)
75
76 #define SYSC_LOAD_REGS_4 \
77 register long _a4 asm ("r10") = __arg4; \
78 SYSC_LOAD_REGS_3
79
80 #define SYSC_ASM_ARGS_4 SYSC_ASM_ARGS_3, "r"(_a4)
81 /*----------------------------------------------------------------------------*/
82
83
84 /*----------------------------------------------------------------------------*/
85 #define SYSC_LOAD_ARGS_5(a1, a2, a3, a4, a5) \
86 long __arg5 = (long)(a5); \
87 SYSC_LOAD_ARGS_4(a1, a2, a3, a4)
88
89 #define SYSC_LOAD_REGS_5 \
90 register long _a5 asm ("r8") = __arg5; \
91 SYSC_LOAD_REGS_4
92
93 #define SYSC_ASM_ARGS_5 SYSC_ASM_ARGS_4, "r"(_a5)
94 /*----------------------------------------------------------------------------*/
95
96
97 /*----------------------------------------------------------------------------*/
98 #define SYSC_LOAD_ARGS_6(a1, a2, a3, a4, a5, a6) \
99 long __arg6 = (long)(a6); \
100 SYSC_LOAD_ARGS_5(a1, a2, a3, a4, a5)
101
102 #define SYSC_LOAD_REGS_6 \
103 register long _a6 asm ("r9") = __arg6; \
104 SYSC_LOAD_REGS_5
105
106 #define SYSC_ASM_ARGS_6 SYSC_ASM_ARGS_5, "r"(_a6)
107 /*----------------------------------------------------------------------------*/
108 #else
109 #error "no x86_64 syscall code is defined for your toolchain"
110 #endif /* __GNUC__ */
111 /*============================================================================*/
112
113
114 /*============================================================================*/
115 /*
116 * Note: holes are not allowed.
117 * this list is probably not up to date, see:
118 * - linux_src/arch/x86/entry/syscalls/syscall_64.tbl
119 * - do generate the linux headers for x86 arch, and follow linux/unistd.h
120 */
121 #define __ULINUX_NR_read 0
122 #define __ULINUX_NR_write 1
123 #define __ULINUX_NR_open 2
124 #define __ULINUX_NR_close 3
125 #define __ULINUX_NR_stat 4
126 #define __ULINUX_NR_fstat 5
127 #define __ULINUX_NR_lstat 6
128 #define __ULINUX_NR_poll 7
129 #define __ULINUX_NR_lseek 8
130 #define __ULINUX_NR_mmap 9
131 #define __ULINUX_NR_mprotect 10
132 #define __ULINUX_NR_munmap 11
133 #define __ULINUX_NR_brk 12
134 #define __ULINUX_NR_rt_sigaction 13
135 #define __ULINUX_NR_rt_sigprocmask 14
136 #define __ULINUX_NR_rt_sigreturn 15
137 #define __ULINUX_NR_ioctl 16
138 #define __ULINUX_NR_pread64 17
139 #define __ULINUX_NR_pwrite64 18
140 #define __ULINUX_NR_readv 19
141 #define __ULINUX_NR_writev 20
142 #define __ULINUX_NR_access 21
143 #define __ULINUX_NR_pipe 22
144 #define __ULINUX_NR_select 23
145 #define __ULINUX_NR_sched_yield 24
146 #define __ULINUX_NR_mremap 25
147 #define __ULINUX_NR_msync 26
148 #define __ULINUX_NR_mincore 27
149 #define __ULINUX_NR_madvise 28
150 #define __ULINUX_NR_shmget 29
151 #define __ULINUX_NR_shmat 30
152 #define __ULINUX_NR_shmctl 31
153 #define __ULINUX_NR_dup 32
154 #define __ULINUX_NR_dup2 33
155 #define __ULINUX_NR_pause 34
156 #define __ULINUX_NR_nanosleep 35
157 #define __ULINUX_NR_getitimer 36
158 #define __ULINUX_NR_alarm 37
159 #define __ULINUX_NR_setitimer 38
160 #define __ULINUX_NR_getpid 39
161 #define __ULINUX_NR_sendfile 40
162 #define __ULINUX_NR_socket 41
163 #define __ULINUX_NR_connect 42
164 #define __ULINUX_NR_accept 43
165 #define __ULINUX_NR_sendto 44
166 #define __ULINUX_NR_recvfrom 45
167 #define __ULINUX_NR_sendmsg 46
168 #define __ULINUX_NR_recvmsg 47
169 #define __ULINUX_NR_shutdown 48
170 #define __ULINUX_NR_bind 49
171 #define __ULINUX_NR_listen 50
172 #define __ULINUX_NR_getsockname 51
173 #define __ULINUX_NR_getpeername 52
174 #define __ULINUX_NR_socketpair 53
175 #define __ULINUX_NR_setsockopt 54
176 #define __ULINUX_NR_getsockopt 55
177 #define __ULINUX_NR_clone 56
178 #define __ULINUX_NR_fork 57
179 #define __ULINUX_NR_vfork 58
180 #define __ULINUX_NR_execve 59
181 #define __ULINUX_NR_exit 60
182 #define __ULINUX_NR_wait4 61
183 #define __ULINUX_NR_kill 62
184 #define __ULINUX_NR_uname 63
185 #define __ULINUX_NR_semget 64
186 #define __ULINUX_NR_semop 65
187 #define __ULINUX_NR_semctl 66
188 #define __ULINUX_NR_shmdt 67
189 #define __ULINUX_NR_msgget 68
190 #define __ULINUX_NR_msgsnd 69
191 #define __ULINUX_NR_msgrcv 70
192 #define __ULINUX_NR_msgctl 71
193 #define __ULINUX_NR_fcntl 72
194 #define __ULINUX_NR_flock 73
195 #define __ULINUX_NR_fsync 74
196 #define __ULINUX_NR_fdatasync 75
197 #define __ULINUX_NR_truncate 76
198 #define __ULINUX_NR_ftruncate 77
199 #define __ULINUX_NR_getdents 78
200 #define __ULINUX_NR_getcwd 79
201 #define __ULINUX_NR_chdir 80
202 #define __ULINUX_NR_fchdir 81
203 #define __ULINUX_NR_rename 82
204 #define __ULINUX_NR_mkdir 83
205 #define __ULINUX_NR_rmdir 84
206 #define __ULINUX_NR_creat 85
207 #define __ULINUX_NR_link 86
208 #define __ULINUX_NR_unlink 87
209 #define __ULINUX_NR_symlink 88
210 #define __ULINUX_NR_readlink 89
211 #define __ULINUX_NR_chmod 90
212 #define __ULINUX_NR_fchmod 91
213 #define __ULINUX_NR_chown 92
214 #define __ULINUX_NR_fchown 93
215 #define __ULINUX_NR_lchown 94
216 #define __ULINUX_NR_umask 95
217 #define __ULINUX_NR_gettimeofday 96
218 #define __ULINUX_NR_getrlimit 97
219 #define __ULINUX_NR_getrusage 98
220 #define __ULINUX_NR_sysinfo 99
221 #define __ULINUX_NR_times 100
222 #define __ULINUX_NR_ptrace 101
223 #define __ULINUX_NR_getuid 102
224 #define __ULINUX_NR_syslog 103
225 #define __ULINUX_NR_getgid 104
226 #define __ULINUX_NR_setuid 105
227 #define __ULINUX_NR_setgid 106
228 #define __ULINUX_NR_geteuid 107
229 #define __ULINUX_NR_getegid 108
230 #define __ULINUX_NR_setpgid 109
231 #define __ULINUX_NR_getppid 110
232 #define __ULINUX_NR_getpgrp 111
233 #define __ULINUX_NR_setsid 112
234 #define __ULINUX_NR_setreuid 113
235 #define __ULINUX_NR_setregid 114
236 #define __ULINUX_NR_getgroups 115
237 #define __ULINUX_NR_setgroups 116
238 #define __ULINUX_NR_setresuid 117
239 #define __ULINUX_NR_getresuid 118
240 #define __ULINUX_NR_setresgid 119
241 #define __ULINUX_NR_getresgid 120
242 #define __ULINUX_NR_getpgid 121
243 #define __ULINUX_NR_setfsuid 122
244 #define __ULINUX_NR_setfsgid 123
245 #define __ULINUX_NR_getsid 124
246 #define __ULINUX_NR_capget 125
247 #define __ULINUX_NR_capset 126
248 #define __ULINUX_NR_rt_sigpending 127
249 #define __ULINUX_NR_rt_sigtimedwait 128
250 #define __ULINUX_NR_rt_sigqueueinfo 129
251 #define __ULINUX_NR_rt_sigsuspend 130
252 #define __ULINUX_NR_sigaltstack 131
253 #define __ULINUX_NR_utime 132
254 #define __ULINUX_NR_mknod 133
255 #define __ULINUX_NR_uselib 134
256 #define __ULINUX_NR_personality 135
257 #define __ULINUX_NR_ustat 136
258 #define __ULINUX_NR_statfs 137
259 #define __ULINUX_NR_fstatfs 138
260 #define __ULINUX_NR_sysfs 139
261 #define __ULINUX_NR_getpriority 140
262 #define __ULINUX_NR_setpriority 141
263 #define __ULINUX_NR_sched_setparam 142
264 #define __ULINUX_NR_sched_getparam 143
265 #define __ULINUX_NR_sched_setscheduler 144
266 #define __ULINUX_NR_sched_getscheduler 145
267 #define __ULINUX_NR_sched_get_priority_max 146
268 #define __ULINUX_NR_sched_get_priority_min 147
269 #define __ULINUX_NR_sched_rr_get_interval 148
270 #define __ULINUX_NR_mlock 149
271 #define __ULINUX_NR_munlock 150
272 #define __ULINUX_NR_mlockall 151
273 #define __ULINUX_NR_munlockall 152
274 #define __ULINUX_NR_vhangup 153
275 #define __ULINUX_NR_modify_ldt 154
276 #define __ULINUX_NR_pivot_root 155
277 #define __ULINUX_NR__sysctl 156
278 #define __ULINUX_NR_prctl 157
279 #define __ULINUX_NR_arch_prctl 158
280 #define __ULINUX_NR_adjtimex 159
281 #define __ULINUX_NR_setrlimit 160
282 #define __ULINUX_NR_chroot 161
283 #define __ULINUX_NR_sync 162
284 #define __ULINUX_NR_acct 163
285 #define __ULINUX_NR_settimeofday 164
286 #define __ULINUX_NR_mount 165
287 #define __ULINUX_NR_umount2 166
288 #define __ULINUX_NR_swapon 167
289 #define __ULINUX_NR_swapoff 168
290 #define __ULINUX_NR_reboot 169
291 #define __ULINUX_NR_sethostname 170
292 #define __ULINUX_NR_setdomainname 171
293 #define __ULINUX_NR_iopl 172
294 #define __ULINUX_NR_ioperm 173
295 #define __ULINUX_NR_create_module 174
296 #define __ULINUX_NR_init_module 175
297 #define __ULINUX_NR_delete_module 176
298 #define __ULINUX_NR_get_kernel_syms 177
299 #define __ULINUX_NR_query_module 178
300 #define __ULINUX_NR_quotactl 179
301 #define __ULINUX_NR_nfsservctl 180
302 #define __ULINUX_NR_getpmsg 181
303 #define __ULINUX_NR_putpmsg 182
304 #define __ULINUX_NR_afs_syscall 183
305 #define __ULINUX_NR_tuxcall 184
306 #define __ULINUX_NR_security 185
307 #define __ULINUX_NR_gettid 186
308 #define __ULINUX_NR_readahead 187
309 #define __ULINUX_NR_setxattr 188
310 #define __ULINUX_NR_lsetxattr 189
311 #define __ULINUX_NR_fsetxattr 190
312 #define __ULINUX_NR_getxattr 191
313 #define __ULINUX_NR_lgetxattr 192
314 #define __ULINUX_NR_fgetxattr 193
315 #define __ULINUX_NR_listxattr 194
316 #define __ULINUX_NR_llistxattr 195
317 #define __ULINUX_NR_flistxattr 196
318 #define __ULINUX_NR_removexattr 197
319 #define __ULINUX_NR_lremovexattr 198
320 #define __ULINUX_NR_fremovexattr 199
321 #define __ULINUX_NR_tkill 200
322 #define __ULINUX_NR_time 201
323 #define __ULINUX_NR_futex 202
324 #define __ULINUX_NR_sched_setaffinity 203
325 #define __ULINUX_NR_sched_getaffinity 204
326 #define __ULINUX_NR_set_thread_area 205
327 #define __ULINUX_NR_io_setup 206
328 #define __ULINUX_NR_io_destroy 207
329 #define __ULINUX_NR_io_getevents 208
330 #define __ULINUX_NR_io_submit 209
331 #define __ULINUX_NR_io_cancel 210
332 #define __ULINUX_NR_get_thread_area 211
333 #define __ULINUX_NR_lookup_dcookie 212
334 #define __ULINUX_NR_epoll_create 213
335 #define __ULINUX_NR_epoll_ctl_old 214
336 #define __ULINUX_NR_epoll_wait_old 215
337 #define __ULINUX_NR_remap_file_pages 216
338 #define __ULINUX_NR_getdents64 217
339 #define __ULINUX_NR_set_tid_address 218
340 #define __ULINUX_NR_restart_syscall 219
341 #define __ULINUX_NR_semtimedop 220
342 #define __ULINUX_NR_fadvise64 221
343 #define __ULINUX_NR_timer_create 222
344 #define __ULINUX_NR_timer_settime 223
345 #define __ULINUX_NR_timer_gettime 224
346 #define __ULINUX_NR_timer_getoverrun 225
347 #define __ULINUX_NR_timer_delete 226
348 #define __ULINUX_NR_clock_settime 227
349 #define __ULINUX_NR_clock_gettime 228
350 #define __ULINUX_NR_clock_getres 229
351 #define __ULINUX_NR_clock_nanosleep 230
352 #define __ULINUX_NR_exit_group 231
353 #define __ULINUX_NR_epoll_wait 232
354 #define __ULINUX_NR_epoll_ctl 233
355 #define __ULINUX_NR_tgkill 234
356 #define __ULINUX_NR_utimes 235
357 #define __ULINUX_NR_vserver 236
358 #define __ULINUX_NR_mbind 237
359 #define __ULINUX_NR_set_mempolicy 238
360 #define __ULINUX_NR_get_mempolicy 239
361 #define __ULINUX_NR_mq_open 240
362 #define __ULINUX_NR_mq_unlink 241
363 #define __ULINUX_NR_mq_timedsend 242
364 #define __ULINUX_NR_mq_timedreceive 243
365 #define __ULINUX_NR_mq_notify 244
366 #define __ULINUX_NR_mq_getsetattr 245
367 #define __ULINUX_NR_kexec_load 246
368 #define __ULINUX_NR_waitid 247
369 #define __ULINUX_NR_add_key 248
370 #define __ULINUX_NR_request_key 249
371 #define __ULINUX_NR_keyctl 250
372 #define __ULINUX_NR_ioprio_set 251
373 #define __ULINUX_NR_ioprio_get 252
374 #define __ULINUX_NR_inotify_init 253
375 #define __ULINUX_NR_inotify_add_watch 254
376 #define __ULINUX_NR_inotify_rm_watch 255
377 #define __ULINUX_NR_migrate_pages 256
378 #define __ULINUX_NR_openat 257
379 #define __ULINUX_NR_mkdirat 258
380 #define __ULINUX_NR_mknodat 259
381 #define __ULINUX_NR_fchownat 260
382 #define __ULINUX_NR_futimesat 261
383 #define __ULINUX_NR_newfstatat 262
384 #define __ULINUX_NR_unlinkat 263
385 #define __ULINUX_NR_renameat 264
386 #define __ULINUX_NR_linkat 265
387 #define __ULINUX_NR_symlinkat 266
388 #define __ULINUX_NR_readlinkat 267
389 #define __ULINUX_NR_fchmodat 268
390 #define __ULINUX_NR_faccessat 269
391 #define __ULINUX_NR_pselect6 270
392 #define __ULINUX_NR_ppoll 271
393 #define __ULINUX_NR_unshare 272
394 #define __ULINUX_NR_set_robust_list 273
395 #define __ULINUX_NR_get_robust_list 274
396 #define __ULINUX_NR_splice 275
397 #define __ULINUX_NR_tee 276
398 #define __ULINUX_NR_sync_file_range 277
399 #define __ULINUX_NR_vmsplice 278
400 #define __ULINUX_NR_move_pages 279
401 #define __ULINUX_NR_utimensat 280
402 #define __ULINUX_NR_epoll_pwait 281
403 #define __ULINUX_NR_signalfd 282
404 #define __ULINUX_NR_timerfd_create 283
405 #define __ULINUX_NR_eventfd 284
406 #define __ULINUX_NR_fallocate 285
407 #define __ULINUX_NR_timerfd_settime 286
408 #define __ULINUX_NR_timerfd_gettime 287
409 #define __ULINUX_NR_accept4 288
410 #define __ULINUX_NR_signalfd4 289
411 #define __ULINUX_NR_eventfd2 290
412 #define __ULINUX_NR_epoll_create1 291
413 #define __ULINUX_NR_dup3 292
414 #define __ULINUX_NR_pipe2 293
415 #define __ULINUX_NR_inotify_init1 294
416 #define __ULINUX_NR_preadv 295
417 #define __ULINUX_NR_pwritev 296
418 #define __ULINUX_NR_rt_tgsigqueueinfo 297
419 #define __ULINUX_NR_perf_event_open 298
420 #define __ULINUX_NR_recvmmsg 299
421 #define __ULINUX_NR_fanotify_init 300
422 #define __ULINUX_NR_fanotify_mark 301
423 #define __ULINUX_NR_prlimit64 302
424 #define __ULINUX_NR_name_to_handle_at 303
425 #define __ULINUX_NR_open_by_handle_at 304
426 #define __ULINUX_NR_clock_adjtime 305
427 #define __ULINUX_NR_syncfs 306
428 #define __ULINUX_NR_sendmmsg 307
429 #define __ULINUX_NR_setns 308
430 #define __ULINUX_NR_getcpu 309
431 #define __ULINUX_NR_process_vm_readv 310
432 #define __ULINUX_NR_process_vm_writev 311
433 #define __ULINUX_NR_kcmp 312
434 #define __ULINUX_NR_finit_module 313
435 #define __ULINUX_NR_sched_setattr 314
436 #define __ULINUX_NR_sched_getattr 315
437 #define __ULINUX_NR_renameat2 316
438 #define __ULINUX_NR_seccomp 317
439 #define __ULINUX_NR_getrandom 318
440 #define __ULINUX_NR_memfd_create 319
441 #define __ULINUX_NR_kexec_file_load 320
442 #define __ULINUX_NR_bpf 321
443 #define __ULINUX_NR_execveat 322
444 #define __ULINUX_NR_userfaultfd 323
445 #define __ULINUX_NR_membarrier 324
446 #define __ULINUX_NR_mlock2 325
447 #define __ULINUX_NR_copy_file_range 326
448 #define __ULINUX_NR_preadv2 327
449 #define __ULINUX_NR_pwritev2 328
450 #define __ULINUX_NR_pkey_mprotect 329
451 #define __ULINUX_NR_pkey_alloc 330
452 #define __ULINUX_NR_pkey_free 331
453 #define __ULINUX_NR_statx 332
454 #define __ULINUX_NR_io_pgetevents 333
455 #define __ULINUX_NR_rseq 334
456 #define __ULINUX_NR_pidfd_send_signal 424
457 #define __ULINUX_NR_io_uring_setup 425
458 #define __ULINUX_NR_io_uring_enter 426
459 #define __ULINUX_NR_io_uring_register 427
460 #define __ULINUX_NR_open_tree 428
461 #define __ULINUX_NR_move_mount 429
462 #define __ULINUX_NR_fsopen 430
463 #define __ULINUX_NR_fsconfig 431
464 #define __ULINUX_NR_fsmount 432
465 #define __ULINUX_NR_fspick 433
466 #endif /* ULINUX_ARCH_SYSC_H */
File ulinux/archs/x86_64/types.h added (mode: 100644) (index 0000000..8d77ba9)
1 #ifndef ULINUX_ARCH_TYPES_H
2 #define ULINUX_ARCH_TYPES_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 #define BITS_PER_LONG 64
8 #endif
File ulinux/archs/x86_64/utils/endian.S added (mode: 100644) (index 0000000..c25ac87)
1 #ifndef ULINUX_ARCHS_X86_64_UTILS_ENDIAN_S
2 #define ULINUX_ARCHS_X86_64_UTILS_ENDIAN_S
3 #endif
File ulinux/archs/x86_64/utils/endian.h added (mode: 100644) (index 0000000..a424b65)
1 #ifndef ULINUX_ARCH_UTILS_ENDIAN_H
2 #define ULINUX_ARCH_UTILS_ENDIAN_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 static inline ulinux_u16 ulinux_cpu_to_be16(ulinux_u16 v)
8 {
9 return (ulinux_u16)((((ulinux_u16)(v)&(ulinux_u16)0x00ffU)<<8)
10 |(((ulinux_u16)(v)&(ulinux_u16)0xff00U)>>8));
11 }
12 #define ulinux_be16_to_cpu(v) ulinux_cpu_to_be16(v)
13
14 #ifdef __GNUC__
15 static inline ulinux_u32 ulinux_cpu_to_be32(ulinux_u32 v)
16 {
17 asm ("bswapl %0":"=r" (v):"0" (v));
18 return v;
19 }
20 #define ulinux_be32_to_cpu(v) ulinux_cpu_to_be32(v)
21
22 static inline ulinux_u64 ulinux_cpu_to_be64(ulinux_u64 val)
23 {
24 union {
25 struct {
26 ulinux_u32 a;
27 ulinux_u32 b;
28 } s;
29 ulinux_u64 u;
30 } v;
31 v.u = val;
32 asm ("bswapl %0 ; bswapl %1 ; xchgl %0,%1"
33 : "=r" (v.s.a), "=r" (v.s.b)
34 : "0" (v.s.a), "1" (v.s.b));
35 return v.u;
36 }
37 #define ulinux_be64_to_cpu(v) ulinux_cpu_to_be64(v)
38 #else
39 #error "missing endian conversions for your toolchain"
40 #endif
41
42 /* little endian */
43 #define ulinux_cpu_to_le32(v) (v)
44 #define ulinux_cpu_to_le64(v) (v)
45 #define ulinux_le32_to_cpu(v) (v)
46 #define ulinux_le64_to_cpu(v) (v)
47 #endif
File ulinux/binfmts.h added (mode: 100644) (index 0000000..3302385)
1 #ifndef ULINUX_BINFMTS_H
2 #define ULINUX_BINFMTS_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 /* this is a random value decided for linux exec syscalls */
8 #define ULINUX_MAX_ARG_STRLEN (ULINUX_PAGE_SZ * 32)
9 #endif
File ulinux/compiler_misc.h added (mode: 100644) (index 0000000..780bab5)
1 #ifndef ULINUX_COMPILER_MISC_H
2 #define ULINUX_COMPILER_MISC_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 /*----------------------------------------------------------------------------*/
8 #if __GNUC__
9 #define unreachable __builtin_unreachable
10 #define GCC_NOCLONE __attribute__((noclone))
11 #define GCC_NOINLINE __attribute__((noinline))
12 #else
13 #define unreachable()
14 #endif
15 /*----------------------------------------------------------------------------*/
16
17 /*----------------------------------------------------------------------------*/
18 #if __GNUC__
19 #define PACKED __attribute__((packed))
20 #endif
21
22 #ifndef PACKED
23 #error "the compiler must support packed structure in some way"
24 #endif
25 /*----------------------------------------------------------------------------*/
26 #endif
File ulinux/compiler_types.h added (mode: 100644) (index 0000000..2974cc7)
1 #ifndef ULINUX_COMPILER_TYPES_H
2 #define ULINUX_COMPILER_TYPES_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 #define ulinux_sc signed char
8 #define ulinux_ss signed short
9 #define ulinux_si signed int
10 #define ulinux_sl signed long
11 #define ulinux_sll signed long long
12
13 #define ulinux_uc unsigned char
14 #define ulinux_us unsigned short
15 #define ulinux_ui unsigned int
16 #define ulinux_ul unsigned long
17 #define ulinux_ull unsigned long long
18
19 #define ulinux_f float
20 #endif
File ulinux/dirent.h added (mode: 100644) (index 0000000..3db47f9)
1 #ifndef ULINUX_DIRENT_H
2 #define ULINUX_DIRENT_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 struct ulinux_dirent64{
8 ulinux_u64 ino;
9 ulinux_s64 off;
10 ulinux_us rec_len;
11 ulinux_u8 type;
12 ulinux_u8 name[0];
13 };
14 #endif
File ulinux/elf.h added (mode: 100644) (index 0000000..0d7f973)
1 #ifndef ULINUX_ELF_H
2 #define ULINUX_ELF_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7
8 /* reduced version */
9
10 /* entry types */
11 #define ULINUX_AT_NULL 0 /* end of vector */
12 #define ULINUX_AT_SYSINFO_EHDR 33 /* vdso related */
13
14 struct ulinux_elf64_auxv
15 {
16 ulinux_u64 type; /* entry type */
17 ulinux_u64 val; /* integer value */
18 };
19
20 /******************************************************************************/
21 #define ULINUX_EI_NIDENT 16
22
23 struct ulinux_elf64_ehdr {
24 ulinux_u8 ident[ULINUX_EI_NIDENT];/* Magic number and other info */
25 ulinux_u16 type; /* Object file type */
26 ulinux_u16 machine; /* Architecture */
27 ulinux_u32 version; /* Object file version */
28 ulinux_u64 entry; /* Entry point virtual address */
29 ulinux_u64 phoff; /* Program segment header table file offset */
30 ulinux_u64 shoff; /* Section header table file offset */
31 ulinux_u32 flags; /* Processor-specific flags */
32 ulinux_u16 ehsize; /* ELF header size in bytes */
33 ulinux_u16 phentsize; /* Program segment header table entry size */
34 ulinux_u16 phnum; /* Program segment header table entry count */
35 ulinux_u16 shentsize; /* Section header table entry size */
36 ulinux_u16 shnum; /* Section header table entry count */
37 ulinux_u16 shstrndx; /* Section header string table index */
38 };
39 /******************************************************************************/
40
41
42 /******************************************************************************/
43 struct ulinux_elf64_phdr {
44 ulinux_u32 type; /* program segment type */
45 ulinux_u32 flags; /* program segment flags */
46 ulinux_u64 offset; /* program segment file offset */
47 ulinux_u64 vaddr; /* program segment virtual address */
48 ulinux_u64 paddr; /* program segment physical address */
49 ulinux_u64 filesz; /* program segment size in file */
50 ulinux_u64 memsz; /* program segment size in memory */
51 ulinux_u64 align; /* program segment alignment */
52 };
53 /*----------------------------------------------------------------------------*/
54 /* program segment types */
55 #define ULINUX_PT_NULL 0 /* Program header table entry unused */
56 #define ULINUX_PT_LOAD 1 /* Loadable program segment */
57 #define ULINUX_PT_DYNAMIC 2 /* Dynamic linking information */
58 #define ULINUX_PT_INTERP 3 /* Program interpreter */
59 #define ULINUX_PT_NOTE 4 /* Auxiliary information */
60 #define ULINUX_PT_SHLIB 5 /* Reserved */
61 #define ULINUX_PT_PHDR 6 /* Entry for header table itself */
62 #define ULINUX_PT_TLS 7 /* Thread-local storage segment */
63 #define ULINUX_PT_NUM 8 /* Number of defined types */
64 #define ULINUX_PT_LOOS 0x60000000 /* Start of OS-specific */
65 #define ULINUX_PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */
66 #define ULINUX_PT_GNU_STACK 0x6474e551 /* Indicates stack executability */
67 #define ULINUX_PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */
68 #define ULINUX_PT_LOSUNW 0x6ffffffa
69 #define ULINUX_PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */
70 #define ULINUX_PT_SUNWSTACK 0x6ffffffb /* Stack segment */
71 #define ULINUX_PT_HISUNW 0x6fffffff
72 #define ULINUX_PT_HIOS 0x6fffffff /* End of OS-specific */
73 #define ULINUX_PT_LOPROC 0x70000000 /* Start of processor-specific */
74 #define ULINUX_PT_HIPROC 0x7fffffff /* End of processor-specific */
75 /******************************************************************************/
76
77
78
79 /******************************************************************************/
80 struct ulinux_elf64_dyn {
81 ulinux_s64 tag; /* Dynamic entry type */
82 union {
83 ulinux_u64 val; /* Integer value */
84 ulinux_u64 ptr; /* Address value */
85 };
86 };
87 /*============================================================================*/
88 /* values for tag */
89 /*----------------------------------------------------------------------------*/
90 /* major values for tag */
91 #define ULINUX_DT_NULL 0 /* Marks end of dynamic section */
92 #define ULINUX_DT_NEEDED 1 /* Name of needed library */
93 #define ULINUX_DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */
94 #define ULINUX_DT_PLTGOT 3 /* Processor defined value */
95 #define ULINUX_DT_HASH 4 /* Address of symbol hash table */
96 #define ULINUX_DT_STRTAB 5 /* Address of string table */
97 #define ULINUX_DT_SYMTAB 6 /* Address of symbol table */
98 #define ULINUX_DT_RELA 7 /* Address of Rela relocs */
99 #define ULINUX_DT_RELASZ 8 /* Total size of Rela relocs */
100 #define ULINUX_DT_RELAENT 9 /* Size of one Rela reloc */
101 #define ULINUX_DT_STRSZ 10 /* Size of string table */
102 #define ULINUX_DT_SYMENT 11 /* Size of one symbol table entry */
103 #define ULINUX_DT_INIT 12 /* Address of init function */
104 #define ULINUX_DT_FINI 13 /* Address of termination function */
105 #define ULINUX_DT_SONAME 14 /* Name of shared object */
106 #define ULINUX_DT_RPATH 15 /* Library search path (deprecated) */
107 #define ULINUX_DT_SYMBOLIC 16 /* Start symbol search here */
108 #define ULINUX_DT_REL 17 /* Address of Rel relocs */
109 #define ULINUX_DT_RELSZ 18 /* Total size of Rel relocs */
110 #define ULINUX_DT_RELENT 19 /* Size of one Rel reloc */
111 #define ULINUX_DT_PLTREL 20 /* Type of reloc in PLT */
112 #define ULINUX_DT_DEBUG 21 /* For debugging; unspecified */
113 #define ULINUX_DT_TEXTREL 22 /* Reloc might modify .text */
114 #define ULINUX_DT_JMPREL 23 /* Address of PLT relocs */
115 #define ULINUX_DT_BIND_NOW 24 /* Process relocations of object */
116 #define ULINUX_DT_INIT_ARRAY 25 /* Array with addresses of init fct */
117 #define ULINUX_DT_FINI_ARRAY 26 /* Array with addresses of fini fct */
118 #define ULINUX_DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */
119 #define ULINUX_DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */
120 #define ULINUX_DT_RUNPATH 29 /* Library search path */
121 #define ULINUX_DT_FLAGS 30 /* Flags for the object being loaded */
122 #define ULINUX_DT_ENCODING 32 /* Start of encoded range */
123 #define ULINUX_DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/
124 #define ULINUX_DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */
125 #define ULINUX_DT_NUM 34 /* Number used */
126 #define ULINUX_DT_LOOS 0x6000000d /* Start of OS-specific */
127 #define ULINUX_DT_HIOS 0x6ffff000 /* End of OS-specific */
128 /* here, there are many more tags, see below */
129 #define ULINUX_DT_LOPROC 0x70000000 /* Start of processor-specific */
130 #define ULINUX_DT_HIPROC 0x7fffffff /* End of processor-specific */
131 #define ULINUX_DT_PROCNUM ULINUX_DT_MIPS_NUM /* Most used by any processor */
132 /*----------------------------------------------------------------------------*/
133 /* the versioning entry types: both extensions may be used at the same time */
134 /* GNU extension */
135 #define ULINUX_DT_VERSYM 0x6ffffff0
136
137 #define ULINUX_DT_RELACOUNT 0x6ffffff9
138 #define ULINUX_DT_RELCOUNT 0x6ffffffa
139
140 /* Sun(now oracle) extension */
141 #define ULINUX_DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */
142 #define ULINUX_DT_VERDEF 0x6ffffffc /* Address of version definition table */
143 #define ULINUX_DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */
144 #define ULINUX_DT_VERNEED 0x6ffffffe /* Address of table with needed versions */
145 #define ULINUX_DT_VERNEEDNUM 0x6fffffff /* Number of needed versions */
146 #define ULINUX_DT_VERSIONTAGIDX(tag) (ULINUX_DT_VERNEEDNUM - (tag)) /* Reverse order! */
147 #define ULINUX_DT_VERSIONTAGNUM 16
148 /*----------------------------------------------------------------------------*/
149 /* values for tag */
150 /*============================================================================*/
151 /******************************************************************************/
152
153
154 /******************************************************************************/
155 /*
156 * here, only dynamic symbols, we are not a compiler linker, we are
157 * in the dynamic use case
158 */
159 struct ulinux_elf64_sym {
160 ulinux_u32 name; /* Symbol name (string tbl index) */
161 /* Symbol type and binding: 0xf0 is bind, 0x0f is type */
162 ulinux_u8 info;
163 ulinux_u8 other; /* Symbol visibility */
164 ulinux_u16 shndx; /* Section index */
165 ulinux_u64 value; /* Symbol value */
166 ulinux_u64 size; /* Symbol size */
167 };
168 /*----------------------------------------------------------------------------*/
169 /* Legal values for ST_BIND subfield of st_info (symbol binding). */
170 #define ULINUX_STB_LOCAL 0 /* Local symbol */
171 #define ULINUX_STB_GLOBAL 1 /* Global symbol */
172 #define ULINUX_STB_WEAK 2 /* Weak symbol */
173 #define ULINUX_STB_NUM 3 /* Number of defined types. */
174 #define ULINUX_STB_LOOS 10 /* Start of OS-specific */
175 #define ULINUX_STB_GNU_UNIQUE 10 /* Unique symbol. */
176 #define ULINUX_STB_HIOS 12 /* End of OS-specific */
177 #define ULINUX_STB_LOPROC 13 /* Start of processor-specific */
178 #define ULINUX_STB_HIPROC 15 /* End of processor-specific */
179 /*----------------------------------------------------------------------------*/
180 /* Legal values for ST_TYPE subfield of st_info (symbol type). */
181 #define ULINUX_STT_NOTYPE 0 /* Symbol type is unspecified */
182 #define ULINUX_STT_OBJECT 1 /* Symbol is a data object */
183 #define ULINUX_STT_FUNC 2 /* Symbol is a code object */
184 #define ULINUX_STT_SECTION 3 /* Symbol associated with a section */
185 #define ULINUX_STT_FILE 4 /* Symbol's name is file name */
186 #define ULINUX_STT_COMMON 5 /* Symbol is a common data object */
187 #define ULINUX_STT_TLS 6 /* Symbol is thread-local data object*/
188 #define ULINUX_STT_NUM 7 /* Number of defined types. */
189 #define ULINUX_STT_LOOS 10 /* Start of OS-specific */
190 #define ULINUX_STT_GNU_IFUNC 10 /* Symbol is indirect code object */
191 #define ULINUX_STT_HIOS 12 /* End of OS-specific */
192 #define ULINUX_STT_LOPROC 13 /* Start of processor-specific */
193 #define ULINUX_STT_HIPROC 15 /* End of processor-specific */
194 /*----------------------------------------------------------------------------*/
195 /*
196 * Symbol table indices are found in the hash buckets and chain table
197 * of a symbol hash table section. This special index value indicates
198 * the end of a chain, meaning no further symbols are found in that bucket.
199 */
200 #define ULINUX_STN_UNDEF 0 /* End of a chain. */
201 /*----------------------------------------------------------------------------*/
202 /******************************************************************************/
203 #endif
File ulinux/epoll.h added (mode: 100644) (index 0000000..edacba1)
1 #ifndef ULINUX_EPOLL_H
2 #define ULINUX_EPOLL_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 #ifndef ULINUX_O_CLOEXEC
8 #error "missing definition of ULINUX_O_CLOEXEC"
9 #endif
10 #define ULINUX_EPOLL_CLOEXEC ULINUX_O_CLOEXEC
11
12 #define ULINUX_EPOLL_CTL_ADD 1
13 #define ULINUX_EPOLL_CTL_DEL 2
14 #define ULINUX_EPOLL_CTL_MOD 3
15
16 #define ULINUX_EPOLLIN 0x0001
17 #define ULINUX_EPOLLPRI 0x0002
18 #define ULINUX_EPOLLOUT 0x0004
19 #define ULINUX_EPOLLERR 0x0008
20 #define ULINUX_EPOLLHUP 0x0010
21 #define ULINUX_EPOLLNVAL 0x0020
22 #define ULINUX_EPOLLRDHUP 0x2000
23 #define ULINUX_EPOLLONESHOT (1<<30)
24 #define ULINUX_EPOLLET (1<<31)
25
26 union ulinux_epoll_data{
27 void *ptr;
28 ulinux_si fd;
29 ulinux_u32 _32;
30 ulinux_u64 _64;
31 };
32
33 #include <ulinux/arch/epoll.h>
34
35 struct ulinux_epoll_event{
36 ulinux_u32 events;
37 union ulinux_epoll_data data;
38 } EPOLL_PACKED; /* Only x86_64 */
39 #endif
File ulinux/error.h added (mode: 100644) (index 0000000..5a125da)
1 #ifndef ULINUX_ERROR_H
2 #define ULINUX_ERROR_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7
8 #define ULINUX_ISERR(x) (-4095<=(x)&&(x)<=-1)
9 #define ULINUX_EPERM 1/*Operation not permitted*/
10 #define ULINUX_ENOENT 2/*No such file or directory*/
11 #define ULINUX_ESRCH 3/*No such process*/
12 #define ULINUX_EINTR 4/*Interrupted system call*/
13 #define ULINUX_EIO 5/*I/O error*/
14 #define ULINUX_ENXIO 6/*No such device or address*/
15 #define ULINUX_E2BIG 7/*Argument list too long*/
16 #define ULINUX_ENOEXEC 8/*Exec format error*/
17 #define ULINUX_EBADF 9/*Bad file number*/
18 #define ULINUX_ECHILD 10/*No child processes*/
19 #define ULINUX_EAGAIN 11/*Try again*/
20 #define ULINUX_ENOMEM 12/*Out of memory*/
21 #define ULINUX_EACCES 13/*Permission denied*/
22 #define ULINUX_EFAULT 14/*Bad address*/
23 #define ULINUX_ENOTBLK 15/*Block device required*/
24 #define ULINUX_EBUSY 16/*Device or resource busy*/
25 #define ULINUX_EEXIST 17/*File exists*/
26 #define ULINUX_EXDEV 18/*Cross-device link*/
27 #define ULINUX_ENODEV 19/*No such device*/
28 #define ULINUX_ENOTDIR 20/*Not a directory*/
29 #define ULINUX_EISDIR 21/*Is a directory*/
30 #define ULINUX_EINVAL 22/*Invalid argument*/
31 #define ULINUX_ENFILE 23/*File table overflow*/
32 #define ULINUX_EMFILE 24/*Too many open files*/
33 #define ULINUX_ENOTTY 25/*Not a typewriter*/
34 #define ULINUX_ETXTBSY 26/*Text file busy*/
35 #define ULINUX_EFBIG 27/*File too large*/
36 #define ULINUX_ENOSPC 28/*No space left on device*/
37 #define ULINUX_ESPIPE 29/*Illegal seek*/
38 #define ULINUX_EROFS 30/*Read-only file system*/
39 #define ULINUX_EMLINK 31/*Too many links*/
40 #define ULINUX_EPIPE 32/*Broken pipe*/
41 #define ULINUX_EDOM 33/*Math argument out of domain of func*/
42 #define ULINUX_ERANGE 34/*Math result not representable*/
43 #define ULINUX_EDEADLK 35/*Resource deadlock would occur*/
44 #define ULINUX_ENAMETOOLONG 36/*File name too long*/
45 #define ULINUX_ENOLCK 37/*No record locks available*/
46 #define ULINUX_ENOSYS 38/*Function not implemented*/
47 #define ULINUX_ENOTEMPTY 39/*Directory not empty*/
48 #define ULINUX_ELOOP 40/*Too many symbolic links encountered*/
49 #define ULINUX_EWOULDBLOCK ULINUX_EAGAIN/*Operation would block*/
50 #define ULINUX_ENOMSG 42/*No message of desired type*/
51 #define ULINUX_EIDRM 43/*Identifier removed*/
52 #define ULINUX_ECHRNG 44/*Channel number out of range*/
53 #define ULINUX_EL2NSYNC 45/*Level 2 not synchronized*/
54 #define ULINUX_EL3HLT 46/*Level 3 halted*/
55 #define ULINUX_EL3RST 47/*Level 3 reset*/
56 #define ULINUX_ELNRNG 48/*Link number out of range*/
57 #define ULINUX_EUNATCH 49/*Protocol driver not attached*/
58 #define ULINUX_ENOCSI 50/*No CSI structure available*/
59 #define ULINUX_EL2HLT 51/*Level 2 halted*/
60 #define ULINUX_EBADE 52/*Invalid exchange*/
61 #define ULINUX_EBADR 53/*Invalid request descriptor*/
62 #define ULINUX_EXFULL 54/*Exchange full*/
63 #define ULINUX_ENOANO 55/*No anode*/
64 #define ULINUX_EBADRQC 56/*Invalid request code*/
65 #define ULINUX_EBADSLT 57/*Invalid slot*/
66
67 #define ULINUX_EDEADLOCK ULINUX_EDEADLK
68
69 #define ULINUX_EBFONT 59/*Bad font file format*/
70 #define ULINUX_ENOSTR 60/*Device not a stream*/
71 #define ULINUX_ENODATA 61/*No data available*/
72 #define ULINUX_ETIME 62/*Timer expired*/
73 #define ULINUX_ENOSR 63/*Out of streams resources*/
74 #define ULINUX_ENONET 64/*Machine is not on the network*/
75 #define ULINUX_ENOPKG 65/*Package not installed*/
76 #define ULINUX_EREMOTE 66/*Object is remote*/
77 #define ULINUX_ENOLINK 67/*Link has been severed*/
78 #define ULINUX_EADV 68/*Advertise error*/
79 #define ULINUX_ESRMNT 69/*Srmount error*/
80 #define ULINUX_ECOMM 70/*Communication error on send*/
81 #define ULINUX_EPROTO 71/*Protocol error*/
82 #define ULINUX_EMULTIHOP 72/*Multihop attempted*/
83 #define ULINUX_EDOTDOT 73/*RFS specific error*/
84 #define ULINUX_EBADMSG 74/*Not a data message*/
85 #define ULINUX_EOVERFLOW 75/*Value too large for defined data type*/
86 #define ULINUX_ENOTUNIQ 76/*Name not unique on network*/
87 #define ULINUX_EBADFD 77/*File descriptor in bad state*/
88 #define ULINUX_EREMCHG 78/*Remote address changed*/
89 #define ULINUX_ELIBACC 79/*Can not access a needed shared library*/
90 #define ULINUX_ELIBBAD 80/*Accessing a corrupted shared library*/
91 #define ULINUX_ELIBSCN 81/*.lib section in a.out corrupted*/
92 #define ULINUX_ELIBMAX 82/*Attempting to link in too many shared libraries*/
93 #define ULINUX_ELIBEXEC 83/*Cannot exec a shared library directly*/
94 #define ULINUX_EILSEQ 84/*Illegal byte sequence*/
95 #define ULINUX_ERESTART 85/*Interrupted system call should be restarted*/
96 #define ULINUX_ESTRPIPE 86/*Streams pipe error*/
97 #define ULINUX_EUSERS 87/*Too many users*/
98 #define ULINUX_ENOTSOCK 88/*Socket operation on non-socket*/
99 #define ULINUX_EDESTADDRREQ 89/*Destination address required*/
100 #define ULINUX_EMSGSIZE 90/*Message too long*/
101 #define ULINUX_EPROTOTYPE 91/*Protocol wrong type for socket*/
102 #define ULINUX_ENOPROTOOPT 92/*Protocol not available*/
103 #define ULINUX_EPROTONOSUPPORT 93/*Protocol not supported*/
104 #define ULINUX_ESOCKTNOSUPPORT 94/*Socket type not supported*/
105 #define ULINUX_EOPNOTSUPP 95/*Operation not supported on transport endpoint*/
106 #define ULINUX_EPFNOSUPPORT 96/*Protocol family not supported*/
107 #define ULINUX_EAFNOSUPPORT 97/*Address family not supported by protocol*/
108 #define ULINUX_EADDRINUSE 98/*Address already in use*/
109 #define ULINUX_EADDRNOTAVAIL 99/*Cannot assign requested address*/
110 #define ULINUX_ENETDOWN 100/*Network is down*/
111 #define ULINUX_ENETUNREACH 101/*Network is unreachable*/
112 #define ULINUX_ENETRESET i 102/*Network dropped connection because of reset*/
113 #define ULINUX_ECONNABORTED 103/*Software caused connection abort*/
114 #define ULINUX_ECONNRESET 104/*Connection reset by peer*/
115 #define ULINUX_ENOBUFS 105/*No buffer space available*/
116 #define ULINUX_EISCONN 106/*Transport endpoint is already connected*/
117 #define ULINUX_ENOTCONN 107/*Transport endpoint is not connected*/
118 #define ULINUX_ESHUTDOWN 108/*Cannot send after transport endpoint shutdown*/
119 #define ULINUX_ETOOMANYREFS 109/*Too many references: cannot splice*/
120 #define ULINUX_ETIMEDOUT 110/*Connection timed out*/
121 #define ULINUX_ECONNREFUSED 111/*Connection refused*/
122 #define ULINUX_EHOSTDOWN 112/*Host is down*/
123 #define ULINUX_EHOSTUNREACH 113/*No route to host*/
124 #define ULINUX_EALREADY 114/*Operation already in progress*/
125 #define ULINUX_EINPROGRESS 115/*Operation now in progress*/
126 #define ULINUX_ESTALE 116/*Stale NFS file handle*/
127 #define ULINUX_EUCLEAN 117/*Structure needs cleaning*/
128 #define ULINUX_ENOTNAM 118/*Not a XENIX named type file*/
129 #define ULINUX_ENAVAIL 119/*No XENIX semaphores available*/
130 #define ULINUX_EISNAM 120/*Is a named type file*/
131 #define ULINUX_EREMOTEIO 121/*Remote I/O error*/
132 #define ULINUX_EDQUOT 122/*Quota exceeded*/
133
134 #define ULINUX_ENOMEDIUM 123/*No medium found*/
135 #define ULINUX_EMEDIUMTYPE 124/*Wrong medium type*/
136 #define ULINUX_ECANCELED 125/*Operation Canceled*/
137 #define ULINUX_ENOKEY 126/*Required key not available*/
138 #define ULINUX_EKEYEXPIRED 127/*Key has expired*/
139 #define ULINUX_EKEYREVOKED 128/*Key has been revoked*/
140 #define ULINUX_EKEYREJECTED 129/*Key was rejected by service*/
141
142 /*for robust mutexes*/
143 #define ULINUX_EOWNERDEAD 130/*Owner died*/
144 #define ULINUX_ENOTRECOVERABLE 131/*State not recoverable*/
145
146 #define ULINUX_ERFKILL 132/*Operation not possible due to RF-kill*/
147
148 #endif
File ulinux/fcntl.h added (mode: 100644) (index 0000000..e72caaa)
1 #ifndef ULINUX_FCNTL_H
2 #define ULINUX_FCNTL_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 /* some commands may be already defined for some archs */
8 #define ULINUX_F_DUPFD 0 /* dup */
9 #define ULINUX_F_GETFD 1 /* get close_on_exec */
10 #define ULINUX_F_SETFD 2 /* set/clear close_on_exec */
11 #define ULINUX_F_GETFL 3 /* get file->f_flags */
12 #define ULINUX_F_SETFL 4 /* set file->f_flags */
13 #ifndef ULINUX_F_GETLK
14 #define ULINUX_F_GETLK 5
15 #define ULINUX_F_SETLK 6
16 #define ULINUX_F_SETLKW 7
17 #endif
18 #ifndef ULINUX_F_SETOWN
19 #define ULINUX_F_SETOWN 8 /* for sockets */
20 #define ULINUX_F_GETOWN 9 /* for sockets */
21 #endif
22 #ifndef ULINUX_F_SETSIG
23 #define ULINUX_F_SETSIG 10 /* for sockets */
24 #define ULINUX_F_GETSIG 11 /* for sockets */
25 #endif
26 #ifndef ULINUX_F_SETOWN_EX
27 #define ULINUX_F_SETOWN_EX 15
28 #define ULINUX_F_GETOWN_EX 16
29 #endif
30 #endif
File ulinux/file.h added (mode: 100644) (index 0000000..4e85086)
1 #ifndef ULINUX_FILE_H
2 #define ULINUX_FILE_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 #define ULINUX_O_ACCMODE 00000003
8 #define ULINUX_O_RDONLY 00000000
9 #define ULINUX_O_WRONLY 00000001
10 #define ULINUX_O_RDWR 00000002
11 #define ULINUX_O_CREAT 00000100 /* not fcntl */
12 #define ULINUX_O_EXCL 00000200 /* not fcntl */
13 #define ULINUX_O_NOCTTY 00000400 /* not fcntl */
14 #define ULINUX_O_TRUNC 00001000 /* not fcntl */
15 #define ULINUX_O_APPEND 00002000
16 #define ULINUX_O_NONBLOCK 00004000
17 #define ULINUX_O_DSYNC 00010000 /* used to be O_SYNC, see below */
18 #define ULINUX_FASYNC 00020000 /* fcntl, for BSD compatibility */
19 #define ULINUX_O_DIRECT 00040000 /* direct disk access hint */
20 #define ULINUX_O_LARGEFILE 00100000
21 #define ULINUX_O_DIRECTORY 00200000 /* must be a directory */
22 #define ULINUX_O_NOFOLLOW 00400000 /* don't follow links */
23 #define ULINUX_O_NOATIME 01000000
24 #define ULINUX_O_CLOEXEC 02000000 /* set close_on_exec */
25
26 #define __ULINUX_O_SYNC 04000000
27 #define ULINUX_O_SYNC (__ULINUX_O_SYNC|ULINUX_O_DSYNC)
28 #endif
File ulinux/fs.h added (mode: 100644) (index 0000000..46b2230)
1 #ifndef ULINUX_FS_H
2 #define ULINUX_FS_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 #define ULINUX_MS_RDONLY 1/* mount read-only */
8 #define ULINUX_MS_NOSUID 2/* ignore suid and sgid bits */
9 #define ULINUX_MS_NODEV 4/* disallow access to device special files */
10 #define ULINUX_MS_NOEXEC 8/* disallow program execution */
11 #define ULINUX_MS_SYNCHRONOUS 16/* writes are synced at once */
12 #define ULINUX_MS_REMOUNT 32/* alter flags of a mounted fs */
13 #define ULINUX_MS_MANDLOCK 64/* allow mandatory locks on an fs */
14 #define ULINUX_MS_DIRSYNC 128/* directory modifications are synchronous */
15 #define ULINUX_MS_NOATIME 1024/* do not update access times */
16 #define ULINUX_MS_NODIRATIME 2048/* do not update directory access times */
17 #define ULINUX_MS_BIND 4096
18 #define ULINUX_MS_MOVE 8192
19 #define ULINUX_MS_REC 16384
20 #define ULINUX_MS_VERBOSE 32768/* MS_VERBOSE is deprecated */
21 #define ULINUX_MS_SILENT 32768
22 #define ULINUX_MS_POSIXACL (1<<16)/* vfs does not apply the umask */
23 #define ULINUX_MS_UNBINDABLE (1<<17)/* change to unbindable */
24 #define ULINUX_MS_PRIVATE (1<<18)/* change to private */
25 #define ULINUX_MS_SLAVE (1<<19)/* change to slave */
26 #define ULINUX_MS_SHARED (1<<20)/* change to shared */
27 #define ULINUX_MS_RELATIME (1<<21)/* update atime relative to mtime/ctime */
28 #define ULINUX_MS_KERNMOUNT (1<<22)/* this is a kern_mount call */
29 #define ULINUX_MS_I_VERSION (1<<23)/* update inode i_version field */
30 #define ULINUX_MS_STRICTATIME (1<<24)/* always perform atime updates */
31 #define ULINUX_MS_NOSEC (1<<28)
32 #define ULINUX_MS_BORN (1<<29)
33 #define ULINUX_MS_ACTIVE (1<<30)
34 #define ULINUX_MS_NOUSER (1<<31)
35
36 #define ULINUX_DT_UNKNOWN 0
37 #define ULINUX_DT_FIFO 1
38 #define ULINUX_DT_CHR 2
39 #define ULINUX_DT_DIR 4
40 #define ULINUX_DT_BLK 6
41 #define ULINUX_DT_REG 8
42 #define ULINUX_DT_LNK 10
43 #define ULINUX_DT_SOCK 12
44 #define ULINUX_DT_WHT 14
45
46 #define ULINUX_AT_REMOVEDIR 0x200
47 #endif
File ulinux/input/evdev.h added (mode: 100644) (index 0000000..20bc4ca)
1 #ifndef ULINUX_INPUT_EVDEV_H
2 #define ULINUX_INPUT_EVDEV_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7
8 struct ulinux_input_event {
9 struct ulinux_timeval time;
10 ulinux_u16 type;
11 ulinux_u16 code;
12 ulinux_s32 value;
13 };
14
15 struct unlinux_input_id {
16 ulinux_u16 bustype;
17 ulinux_u16 vendor;
18 ulinux_u16 product;
19 ulinux_u16 version;
20 };
21
22 /*
23 * struct input_keymap_entry - used by EVIOCGKEYCODE/EVIOCSKEYCODE ioctls
24 * @scancode: scancode represented in machine-endian form.
25 * @len: length of the scancode that resides in @scancode buffer.
26 * @index: index in the keymap, may be used instead of scancode
27 * @flags: allows to specify how kernel should handle the request. For
28 * example, setting INPUT_KEYMAP_BY_INDEX flag indicates that kernel
29 * should perform lookup in keymap by @index instead of @scancode
30 * @keycode: key code assigned to this scancode
31 *
32 * The structure is used to retrieve and modify keymap data. Users have
33 * option of performing lookup either by @scancode itself or by @index
34 * in keymap entry. EVIOCGKEYCODE will also return scancode or index
35 * (depending on which element was used to perform lookup).
36 */
37
38 struct ulinux_input_keymap_entry {
39 #define INPUT_KEYMAP_BY_INDEX (1<<0)
40 ulinux_u8 flags;
41 ulinux_u8 len;
42 ulinux_u16 index;
43 ulinux_u32 keycode;
44 ulinux_u8 scancode[32];
45 };
46
47 /* get driver version */
48 #define ULINUX_EVIOCGVERSION ULINUX_IOR('E',0x01,ulinux_si)
49 /* get device ID */
50 #define ULINUX_EVIOCGID ULINUX_IOR('E',0x02,struct ulinux_input_id)
51 /* get repeat settings */
52 #define ULINUX_EVIOCGREP ULINUX_IOR('E',0x03,ulinux_ui[2])
53 /* set repeat settings */
54 #define ULINUX_EVIOCSREP ULINUX_IOW('E',0x03,ulinux_ui[2])
55
56 /* get keycode */
57 #define ULINUX_EVIOCGKEYCODE ULINUX_IOR('E',0x04,ulinux_ui[2])
58 #define ULINUX_EVIOCGKEYCODE_V2 ULINUX_IOR('E',0x04,\
59 struct ulinux_input_keymap_entry)
60 /* set keycode */
61 #define ULINUX_EVIOCSKEYCODE ULINUX_IOW('E',0x04,unlinux_i[2])
62 #define ULINUX_EVIOCSKEYCODE_V2 ULINUX_IOW('E',0x04,\
63 struct ulinux_input_keymap_entry)
64
65 /* get device name */
66 #define ULINUX_EVIOCGNAME(len) ULINUX_IOC(ULINUX_IOC_READ,'E',0x06,len)
67 /* get physical location */
68 #define ULINUX_EVIOCGPHYS(len) ULINUX_IOC(ULINUX_IOC_READ,'E',0x07,len)
69 /* get unique identifier */
70 #define ULINUX_EVIOCGUNIQ(len) ULINUX_IOC(ULINUX_IOC_READ,'E',0x08,len)
71 /* get device properties */
72 #define ULINUX_EVIOCGPROP(len) ULINUX_IOC(ULINUX_IOC_READ,'E',0x09,len)
73 /* get event bits */
74 #define ULINUX_EVIOCGBIT(ev,len) ULINUX_IOC(ULINUX_IOC_READ,'E',0x20+(ev),len)
75
76 /* event types bit offsets */
77 #define ULINUX_EV_SYN 0x00
78 #define ULINUX_EV_KEY 0x01
79 #define ULINUX_EV_REL 0x02
80 #define ULINUX_EV_ABS 0x03
81 #define ULINUX_EV_MSC 0x04
82 #define ULINUX_EV_SW 0x05
83 #define ULINUX_EV_LED 0x11
84 #define ULINUX_EV_SND 0x12
85 #define ULINUX_EV_REP 0x14
86 #define ULINUX_EV_FF 0x15
87 #define ULINUX_EV_PWR 0x16
88 #define ULINUX_EV_FF_STATUS 0x17
89 #define ULINUX_EV_MAX 0x1f
90 #define ULINUX_EV_CNT (ULINUX_EV_MAX+1)
91
92 /* synchronization events */
93 #define ULINUX_SYN_REPORT 0
94 #define ULINUX_SYN_CONFIG 1
95 #define ULINUX_SYN_MT_REPORT 2
96 #define ULINUX_SYN_DROPPED 3
97
98 /*
99 * Keys and buttons
100 *
101 * Most of the keys/buttons are modeled after USB HUT 1.12
102 * (see http://www.usb.org/developers/hidpage).
103 * Abbreviations in the comments:
104 * AC - Application Control
105 * AL - Application Launch Button
106 * SC - System Control
107 */
108 #define ULINUX_KEY_RESERVED 0
109 #define ULINUX_KEY_ESC 1
110 #define ULINUX_KEY_1 2
111 #define ULINUX_KEY_2 3
112 #define ULINUX_KEY_3 4
113 #define ULINUX_KEY_4 5
114 #define ULINUX_KEY_5 6
115 #define ULINUX_KEY_6 7
116 #define ULINUX_KEY_7 8
117 #define ULINUX_KEY_8 9
118 #define ULINUX_KEY_9 10
119 #define ULINUX_KEY_0 11
120 #define ULINUX_KEY_MINUS 12
121 #define ULINUX_KEY_EQUAL 13
122 #define ULINUX_KEY_BACKSPACE 14
123 #define ULINUX_KEY_TAB 15
124 #define ULINUX_KEY_Q 16
125 #define ULINUX_KEY_W 17
126 #define ULINUX_KEY_E 18
127 #define ULINUX_KEY_R 19
128 #define ULINUX_KEY_T 20
129 #define ULINUX_KEY_Y 21
130 #define ULINUX_KEY_U 22
131 #define ULINUX_KEY_I 23
132 #define ULINUX_KEY_O 24
133 #define ULINUX_KEY_P 25
134 #define ULINUX_KEY_LEFTBRACE 26
135 #define ULINUX_KEY_RIGHTBRACE 27
136 #define ULINUX_KEY_ENTER 28
137 #define ULINUX_KEY_LEFTCTRL 29
138 #define ULINUX_KEY_A 30
139 #define ULINUX_KEY_S 31
140 #define ULINUX_KEY_D 32
141 #define ULINUX_KEY_F 33
142 #define ULINUX_KEY_G 34
143 #define ULINUX_KEY_H 35
144 #define ULINUX_KEY_J 36
145 #define ULINUX_KEY_K 37
146 #define ULINUX_KEY_L 38
147 #define ULINUX_KEY_SEMICOLON 39
148 #define ULINUX_KEY_APOSTROPHE 40
149 #define ULINUX_KEY_GRAVE 41
150 #define ULINUX_KEY_LEFTSHIFT 42
151 #define ULINUX_KEY_BACKSLASH 43
152 #define ULINUX_KEY_Z 44
153 #define ULINUX_KEY_X 45
154 #define ULINUX_KEY_C 46
155 #define ULINUX_KEY_V 47
156 #define ULINUX_KEY_B 48
157 #define ULINUX_KEY_N 49
158 #define ULINUX_KEY_M 50
159 #define ULINUX_KEY_COMMA 51
160 #define ULINUX_KEY_DOT 52
161 #define ULINUX_KEY_SLASH 53
162 #define ULINUX_KEY_RIGHTSHIFT 54
163 #define ULINUX_KEY_KPASTERISK 55
164 #define ULINUX_KEY_LEFTALT 56
165 #define ULINUX_KEY_SPACE 57
166 #define ULINUX_KEY_CAPSLOCK 58
167 #define ULINUX_KEY_F1 59
168 #define ULINUX_KEY_F2 60
169 #define ULINUX_KEY_F3 61
170 #define ULINUX_KEY_F4 62
171 #define ULINUX_KEY_F5 63
172 #define ULINUX_KEY_F6 64
173 #define ULINUX_KEY_F7 65
174 #define ULINUX_KEY_F8 66
175 #define ULINUX_KEY_F9 67
176 #define ULINUX_KEY_F10 68
177 #define ULINUX_KEY_NUMLOCK 69
178 #define ULINUX_KEY_SCROLLLOCK 70
179 #define ULINUX_KEY_KP7 71
180 #define ULINUX_KEY_KP8 72
181 #define ULINUX_KEY_KP9 73
182 #define ULINUX_KEY_KPMINUS 74
183 #define ULINUX_KEY_KP4 75
184 #define ULINUX_KEY_KP5 76
185 #define ULINUX_KEY_KP6 77
186 #define ULINUX_KEY_KPPLUS 78
187 #define ULINUX_KEY_KP1 79
188 #define ULINUX_KEY_KP2 80
189 #define ULINUX_KEY_KP3 81
190 #define ULINUX_KEY_KP0 82
191 #define ULINUX_KEY_KPDOT 83
192
193 #define ULINUX_KEY_ZENKAKUHANKAKU 85
194 #define ULINUX_KEY_102ND 86
195 #define ULINUX_KEY_F11 87
196 #define ULINUX_KEY_F12 88
197 #define ULINUX_KEY_RO 89
198 #define ULINUX_KEY_KATAKANA 90
199 #define ULINUX_KEY_HIRAGANA 91
200 #define ULINUX_KEY_HENKAN 92
201 #define ULINUX_KEY_KATAKANAHIRAGANA 93
202 #define ULINUX_KEY_MUHENKAN 94
203 #define ULINUX_KEY_KPJPCOMMA 95
204 #define ULINUX_KEY_KPENTER 96
205 #define ULINUX_KEY_RIGHTCTRL 97
206 #define ULINUX_KEY_KPSLASH 98
207 #define ULINUX_KEY_SYSRQ 99
208 #define ULINUX_KEY_RIGHTALT 100
209 #define ULINUX_KEY_LINEFEED 101
210 #define ULINUX_KEY_HOME 102
211 #define ULINUX_KEY_UP 103
212 #define ULINUX_KEY_PAGEUP 104
213 #define ULINUX_KEY_LEFT 105
214 #define ULINUX_KEY_RIGHT 106
215 #define ULINUX_KEY_END 107
216 #define ULINUX_KEY_DOWN 108
217 #define ULINUX_KEY_PAGEDOWN 109
218 #define ULINUX_KEY_INSERT 110
219 #define ULINUX_KEY_DELETE 111
220 #define ULINUX_KEY_MACRO 112
221 #define ULINUX_KEY_MUTE 113
222 #define ULINUX_KEY_VOLUMEDOWN 114
223 #define ULINUX_KEY_VOLUMEUP 115
224 #define ULINUX_KEY_POWER 116/*SC System Power Down*/
225 #define ULINUX_KEY_KPEQUAL 117
226 #define ULINUX_KEY_KPPLUSMINUS 118
227 #define ULINUX_KEY_PAUSE 119
228 #define ULINUX_KEY_SCALE 120/*AL Compiz Scale (Expose)*/
229
230 #define ULINUX_KEY_KPCOMMA 121
231 #define ULINUX_KEY_HANGEUL 122
232 #define ULINUX_KEY_HANGUEL ULINUX_KEY_HANGEUL
233 #define ULINUX_KEY_HANJA 123
234 #define ULINUX_KEY_YEN 124
235 #define ULINUX_KEY_LEFTMETA 125
236 #define ULINUX_KEY_RIGHTMETA 126
237 #define ULINUX_KEY_COMPOSE 127
238
239 #define ULINUX_KEY_STOP 128/*AC Stop*/
240 #define ULINUX_KEY_AGAIN 129
241 #define ULINUX_KEY_PROPS 130/*AC Properties*/
242 #define ULINUX_KEY_UNDO 131/*AC Undo*/
243 #define ULINUX_KEY_FRONT 132
244 #define ULINUX_KEY_COPY 133/*AC Copy */
245 #define ULINUX_KEY_OPEN 134/*AC Open*/
246 #define ULINUX_KEY_PASTE 135/*AC Paste*/
247 #define ULINUX_KEY_FIND 136/*AC Search*/
248 #define ULINUX_KEY_CUT 137/*AC Cut*/
249 #define ULINUX_KEY_HELP 138/*AL Integrated Help Center*/
250 #define ULINUX_KEY_MENU 139/*Menu (show menu)*/
251 #define ULINUX_KEY_CALC 140/*AL Calculator*/
252 #define ULINUX_KEY_SETUP 141
253 #define ULINUX_KEY_SLEEP 142/*SC System Sleep*/
254 #define ULINUX_KEY_WAKEUP 143/*System Wake Up*/
255 #define ULINUX_KEY_FILE 144/*AL Local Machine Browser*/
256 #define ULINUX_KEY_SENDFILE 145
257 #define ULINUX_KEY_DELETEFILE 146
258 #define ULINUX_KEY_XFER 147
259 #define ULINUX_KEY_PROG1 148
260 #define ULINUX_KEY_PROG2 149
261 #define ULINUX_KEY_WWW 150/*AL Internet Browser*/
262 #define ULINUX_KEY_MSDOS 151
263 #define ULINUX_KEY_COFFEE 152/*AL Terminal Lock/Screensaver*/
264 #define ULINUX_KEY_SCREENLOCK ULINUX_KEY_COFFEE
265 #define ULINUX_KEY_DIRECTION 153
266 #define ULINUX_KEY_CYCLEWINDOWS 154
267 #define ULINUX_KEY_MAIL 155
268 #define ULINUX_KEY_BOOKMARKS 156/*AC Bookmarks*/
269 #define ULINUX_KEY_COMPUTER 157
270 #define ULINUX_KEY_BACK 158/*AC Back*/
271 #define ULINUX_KEY_FORWARD 159/*AC Forward*/
272 #define ULINUX_KEY_CLOSECD 160
273 #define ULINUX_KEY_EJECTCD 161
274 #define ULINUX_KEY_EJECTCLOSECD 162
275 #define ULINUX_KEY_NEXTSONG 163
276 #define ULINUX_KEY_PLAYPAUSE 164
277 #define ULINUX_KEY_PREVIOUSSONG 165
278 #define ULINUX_KEY_STOPCD 166
279 #define ULINUX_KEY_RECORD 167
280 #define ULINUX_KEY_REWIND 168
281 #define ULINUX_KEY_PHONE 169/*Media Select Telephone*/
282 #define ULINUX_KEY_ISO 170
283 #define ULINUX_KEY_CONFIG 171/*AL Consumer Control Configuration*/
284 #define ULINUX_KEY_HOMEPAGE 172/*AC Home*/
285 #define ULINUX_KEY_REFRESH 173/*AC Refresh*/
286 #define ULINUX_KEY_EXIT 174/*AC Exit*/
287 #define ULINUX_KEY_MOVE 175
288 #define ULINUX_KEY_EDIT 176
289 #define ULINUX_KEY_SCROLLUP 177
290 #define ULINUX_KEY_SCROLLDOWN 178
291 #define ULINUX_KEY_KPLEFTPAREN 179
292 #define ULINUX_KEY_KPRIGHTPAREN 180
293 #define ULINUX_KEY_NEW 181/*AC New*/
294 #define ULINUX_KEY_REDO 182/*AC Redo/Repeat*/
295
296 #define ULINUX_KEY_F13 183
297 #define ULINUX_KEY_F14 184
298 #define ULINUX_KEY_F15 185
299 #define ULINUX_KEY_F16 186
300 #define ULINUX_KEY_F17 187
301 #define ULINUX_KEY_F18 188
302 #define ULINUX_KEY_F19 189
303 #define ULINUX_KEY_F20 190
304 #define ULINUX_KEY_F21 191
305 #define ULINUX_KEY_F22 192
306 #define ULINUX_KEY_F23 193
307 #define ULINUX_KEY_F24 194
308
309 #define ULINUX_KEY_PLAYCD 200
310 #define ULINUX_KEY_PAUSECD 201
311 #define ULINUX_KEY_PROG3 202
312 #define ULINUX_KEY_PROG4 203
313 #define ULINUX_KEY_DASHBOARD 204/*AL Dashboard*/
314 #define ULINUX_KEY_SUSPEND 205
315 #define ULINUX_KEY_CLOSE 206/*AC Close*/
316 #define ULINUX_KEY_PLAY 207
317 #define ULINUX_KEY_FASTFORWARD 208
318 #define ULINUX_KEY_BASSBOOST 209
319 #define ULINUX_KEY_PRINT 210/*AC Print*/
320 #define ULINUX_KEY_HP 211
321 #define ULINUX_KEY_CAMERA 212
322 #define ULINUX_KEY_SOUND 213
323 #define ULINUX_KEY_QUESTION 214
324 #define ULINUX_KEY_EMAIL 215
325 #define ULINUX_KEY_CHAT 216
326 #define ULINUX_KEY_SEARCH 217
327 #define ULINUX_KEY_CONNECT 218
328 #define ULINUX_KEY_FINANCE 219/*AL Checkbook/Finance*/
329 #define ULINUX_KEY_SPORT 220
330 #define ULINUX_KEY_SHOP 221
331 #define ULINUX_KEY_ALTERASE 222
332 #define ULINUX_KEY_CANCEL 223/*AC Cancel*/
333 #define ULINUX_KEY_BRIGHTNESSDOWN 224
334 #define ULINUX_KEY_BRIGHTNESSUP 225
335 #define ULINUX_KEY_MEDIA 226
336
337 #define ULINUX_KEY_SWITCHVIDEOMODE 227/*
338 * Cycle between available video outputs
339 * (Monitor/LCD/TV-out/etc)
340 */
341 #define ULINUX_KEY_KBDILLUMTOGGLE 228
342 #define ULINUX_KEY_KBDILLUMDOWN 229
343 #define ULINUX_KEY_KBDILLUMUP 230
344
345 #define ULINUX_KEY_SEND 231/*AC Send*/
346 #define ULINUX_KEY_REPLY 232/*AC Reply*/
347 #define ULINUX_KEY_FORWARDMAIL 233/*AC Forward Msg*/
348 #define ULINUX_KEY_SAVE 234/*AC Save*/
349 #define ULINUX_KEY_DOCUMENTS 235
350
351 #define ULINUX_KEY_BATTERY 236
352
353 #define ULINUX_KEY_BLUETOOTH 237
354 #define ULINUX_KEY_WLAN 238
355 #define ULINUX_KEY_UWB 239
356
357 #define ULINUX_KEY_UNKNOWN 240
358
359 #define ULINUX_KEY_VIDEO_NEXT 241/*drive next video source*/
360 #define ULINUX_KEY_VIDEO_PREV 242/*drive previous video source*/
361 #define ULINUX_KEY_BRIGHTNESS_CYCLE 243/*brightness up, after max is min*/
362 #define ULINUX_KEY_BRIGHTNESS_ZERO 244/*brightness off, use ambient*/
363 #define ULINUX_KEY_DISPLAY_OFF 245/*display device to off state*/
364
365 #define ULINUX_KEY_WIMAX 246
366 #define ULINUX_KEY_RFKILL 247/*Key that controls all radios*/
367
368 #define ULINUX_KEY_MICMUTE 248/*Mute / unmute the microphone*/
369
370 /*Code 255 is reserved for special needs of AT keyboard driver*/
371
372 #define ULINUX_BTN_MISC 0x100
373 #define ULINUX_BTN_0 0x100
374 #define ULINUX_BTN_1 0x101
375 #define ULINUX_BTN_2 0x102
376 #define ULINUX_BTN_3 0x103
377 #define ULINUX_BTN_4 0x104
378 #define ULINUX_BTN_5 0x105
379 #define ULINUX_BTN_6 0x106
380 #define ULINUX_BTN_7 0x107
381 #define ULINUX_BTN_8 0x108
382 #define ULINUX_BTN_9 0x109
383
384 #define ULINUX_BTN_MOUSE 0x110
385 #define ULINUX_BTN_LEFT 0x110
386 #define ULINUX_BTN_RIGHT 0x111
387 #define ULINUX_BTN_MIDDLE 0x112
388 #define ULINUX_BTN_SIDE 0x113
389 #define ULINUX_BTN_EXTRA 0x114
390 #define ULINUX_BTN_FORWARD 0x115
391 #define ULINUX_BTN_BACK 0x116
392 #define ULINUX_BTN_TASK 0x117
393
394 #define ULINUX_BTN_JOYSTICK 0x120
395 #define ULINUX_BTN_TRIGGER 0x120
396 #define ULINUX_BTN_THUMB 0x121
397 #define ULINUX_BTN_THUMB2 0x122
398 #define ULINUX_BTN_TOP 0x123
399 #define ULINUX_BTN_TOP2 0x124
400 #define ULINUX_BTN_PINKIE 0x125
401 #define ULINUX_BTN_BASE 0x126
402 #define ULINUX_BTN_BASE2 0x127
403 #define ULINUX_BTN_BASE3 0x128
404 #define ULINUX_BTN_BASE4 0x129
405 #define ULINUX_BTN_BASE5 0x12a
406 #define ULINUX_BTN_BASE6 0x12b
407 #define ULINUX_BTN_DEAD 0x12f
408
409 #define ULINUX_BTN_GAMEPAD 0x130
410 #define ULINUX_BTN_A 0x130
411 #define ULINUX_BTN_B 0x131
412 #define ULINUX_BTN_C 0x132
413 #define ULINUX_BTN_X 0x133
414 #define ULINUX_BTN_Y 0x134
415 #define ULINUX_BTN_Z 0x135
416 #define ULINUX_BTN_TL 0x136
417 #define ULINUX_BTN_TR 0x137
418 #define ULINUX_BTN_TL2 0x138
419 #define ULINUX_BTN_TR2 0x139
420 #define ULINUX_BTN_SELECT 0x13a
421 #define ULINUX_BTN_START 0x13b
422 #define ULINUX_BTN_MODE 0x13c
423 #define ULINUX_BTN_THUMBL 0x13d
424 #define ULINUX_BTN_THUMBR 0x13e
425
426 #define ULINUX_BTN_DIGI 0x140
427 #define ULINUX_BTN_TOOL_PEN 0x140
428 #define ULINUX_BTN_TOOL_RUBBER 0x141
429 #define ULINUX_BTN_TOOL_BRUSH 0x142
430 #define ULINUX_BTN_TOOL_PENCIL 0x143
431 #define ULINUX_BTN_TOOL_AIRBRUSH 0x144
432 #define ULINUX_BTN_TOOL_FINGER 0x145
433 #define ULINUX_BTN_TOOL_MOUSE 0x146
434 #define ULINUX_BTN_TOOL_LENS 0x147
435 #define ULINUX_BTN_TOOL_QUINTTAP 0x148/*Five fingers on trackpad*/
436 #define ULINUX_BTN_TOUCH 0x14a
437 #define ULINUX_BTN_STYLUS 0x14b
438 #define ULINUX_BTN_STYLUS2 0x14c
439 #define ULINUX_BTN_TOOL_DOUBLETAP 0x14d
440 #define ULINUX_BTN_TOOL_TRIPLETAP 0x14e
441 #define ULINUX_BTN_TOOL_QUADTAP 0x14f/*Four fingers on trackpad*/
442
443 #define ULINUX_BTN_WHEEL 0x150
444 #define ULINUX_BTN_GEAR_DOWN 0x150
445 #define ULINUX_BTN_GEAR_UP 0x151
446
447 #define ULINUX_KEY_OK 0x160
448 #define ULINUX_KEY_SELECT 0x161
449 #define ULINUX_KEY_GOTO 0x162
450 #define ULINUX_KEY_CLEAR 0x163
451 #define ULINUX_KEY_POWER2 0x164
452 #define ULINUX_KEY_OPTION 0x165
453 #define ULINUX_KEY_INFO 0x166/*AL OEM Features/Tips/Tutorial*/
454 #define ULINUX_KEY_TIME 0x167
455 #define ULINUX_KEY_VENDOR 0x168
456 #define ULINUX_KEY_ARCHIVE 0x169
457 #define ULINUX_KEY_PROGRAM 0x16a/*Media Select Program Guide*/
458 #define ULINUX_KEY_CHANNEL 0x16b
459 #define ULINUX_KEY_FAVORITES 0x16c
460 #define ULINUX_KEY_EPG 0x16d
461 #define ULINUX_KEY_PVR 0x16e/*Media Select Home*/
462 #define ULINUX_KEY_MHP 0x16f
463 #define ULINUX_KEY_LANGUAGE 0x170
464 #define ULINUX_KEY_TITLE 0x171
465 #define ULINUX_KEY_SUBTITLE 0x172
466 #define ULINUX_KEY_ANGLE 0x173
467 #define ULINUX_KEY_ZOOM 0x174
468 #define ULINUX_KEY_MODE 0x175
469 #define ULINUX_KEY_KEYBOARD 0x176
470 #define ULINUX_KEY_SCREEN 0x177
471 #define ULINUX_KEY_PC 0x178/*Media Select Computer*/
472 #define ULINUX_KEY_TV 0x179/*Media Select TV*/
473 #define ULINUX_KEY_TV2 0x17a/*Media Select Cable*/
474 #define ULINUX_KEY_VCR 0x17b/*Media Select VCR*/
475 #define ULINUX_KEY_VCR2 0x17c/*VCR Plus*/
476 #define ULINUX_KEY_SAT 0x17d/*Media Select Satellite*/
477 #define ULINUX_KEY_SAT2 0x17e
478 #define ULINUX_KEY_CD 0x17f/*Media Select CD*/
479 #define ULINUX_KEY_TAPE 0x180/*Media Select Tape*/
480 #define ULINUX_KEY_RADIO 0x181
481 #define ULINUX_KEY_TUNER 0x182/*Media Select Tuner*/
482 #define ULINUX_KEY_PLAYER 0x183
483 #define ULINUX_KEY_TEXT 0x184
484 #define ULINUX_KEY_DVD 0x185/*Media Select DVD*/
485 #define ULINUX_KEY_AUX 0x186
486 #define ULINUX_KEY_MP3 0x187
487 #define ULINUX_KEY_AUDIO 0x188/*AL Audio Browser*/
488 #define ULINUX_KEY_VIDEO 0x189/*AL Movie Browser*/
489 #define ULINUX_KEY_DIRECTORY 0x18a
490 #define ULINUX_KEY_LIST 0x18b
491 #define ULINUX_KEY_MEMO 0x18c/*Media Select Messages*/
492 #define ULINUX_KEY_CALENDAR 0x18d
493 #define ULINUX_KEY_RED 0x18e
494 #define ULINUX_KEY_GREEN 0x18f
495 #define ULINUX_KEY_YELLOW 0x190
496 #define ULINUX_KEY_BLUE 0x191
497 #define ULINUX_KEY_CHANNELUP 0x192/*Channel Increment*/
498 #define ULINUX_KEY_CHANNELDOWN 0x193/*Channel Decrement*/
499 #define ULINUX_KEY_FIRST 0x194
500 #define ULINUX_KEY_LAST 0x195/*Recall Last*/
501 #define ULINUX_KEY_AB 0x196
502 #define ULINUX_KEY_NEXT 0x197
503 #define ULINUX_KEY_RESTART 0x198
504 #define ULINUX_KEY_SLOW 0x199
505 #define ULINUX_KEY_SHUFFLE 0x19a
506 #define ULINUX_KEY_BREAK 0x19b
507 #define ULINUX_KEY_PREVIOUS 0x19c
508 #define ULINUX_KEY_DIGITS 0x19d
509 #define ULINUX_KEY_TEEN 0x19e
510 #define ULINUX_KEY_TWEN 0x19f
511 #define ULINUX_KEY_VIDEOPHONE 0x1a0/*Media Select Video Phone*/
512 #define ULINUX_KEY_GAMES 0x1a1/*Media Select Games*/
513 #define ULINUX_KEY_ZOOMIN 0x1a2/*AC Zoom In*/
514 #define ULINUX_KEY_ZOOMOUT 0x1a3/*AC Zoom Out*/
515 #define ULINUX_KEY_ZOOMRESET 0x1a4/*AC Zoom*/
516 #define ULINUX_KEY_WORDPROCESSOR 0x1a5/*AL Word Processor*/
517 #define ULINUX_KEY_EDITOR 0x1a6/*AL Text Editor*/
518 #define ULINUX_KEY_SPREADSHEET 0x1a7/*AL Spreadsheet*/
519 #define ULINUX_KEY_GRAPHICSEDITOR 0x1a8/*AL Graphics Editor*/
520 #define ULINUX_KEY_PRESENTATION 0x1a9/*AL Presentation App*/
521 #define ULINUX_KEY_DATABASE 0x1aa/*AL Database App*/
522 #define ULINUX_KEY_NEWS 0x1ab/*AL Newsreader*/
523 #define ULINUX_KEY_VOICEMAIL 0x1ac/*AL Voicemail*/
524 #define ULINUX_KEY_ADDRESSBOOK 0x1ad/*AL Contacts/Address Book*/
525 #define ULINUX_KEY_MESSENGER 0x1ae/*AL Instant Messaging*/
526 #define ULINUX_KEY_DISPLAYTOGGLE 0x1af/*Turn display (LCD) on and off*/
527 #define ULINUX_KEY_SPELLCHECK 0x1b0/*AL Spell Check*/
528 #define ULINUX_KEY_LOGOFF 0x1b1/*AL Logoff*/
529
530 #define ULINUX_KEY_DOLLAR 0x1b2
531 #define ULINUX_KEY_EURO 0x1b3
532
533 #define ULINUX_KEY_FRAMEBACK 0x1b4/*Consumer - transport controls*/
534 #define ULINUX_KEY_FRAMEFORWARD 0x1b5
535 #define ULINUX_KEY_CONTEXT_MENU 0x1b6/*GenDesc - system context menu*/
536 #define ULINUX_KEY_MEDIA_REPEAT 0x1b7/*Consumer - transport control*/
537 #define ULINUX_KEY_10CHANNELSUP 0x1b8/*10 channels up (10+)*/
538 #define ULINUX_KEY_10CHANNELSDOWN 0x1b9/*10 channels down (10-)*/
539 #define ULINUX_KEY_IMAGES 0x1ba/*AL Image Browser*/
540
541 #define ULINUX_KEY_DEL_EOL 0x1c0
542 #define ULINUX_KEY_DEL_EOS 0x1c1
543 #define ULINUX_KEY_INS_LINE 0x1c2
544 #define ULINUX_KEY_DEL_LINE 0x1c3
545
546 #define ULINUX_KEY_FN 0x1d0
547 #define ULINUX_KEY_FN_ESC 0x1d1
548 #define ULINUX_KEY_FN_F1 0x1d2
549 #define ULINUX_KEY_FN_F2 0x1d3
550 #define ULINUX_KEY_FN_F3 0x1d4
551 #define ULINUX_KEY_FN_F4 0x1d5
552 #define ULINUX_KEY_FN_F5 0x1d6
553 #define ULINUX_KEY_FN_F6 0x1d7
554 #define ULINUX_KEY_FN_F7 0x1d8
555 #define ULINUX_KEY_FN_F8 0x1d9
556 #define ULINUX_KEY_FN_F9 0x1da
557 #define ULINUX_KEY_FN_F10 0x1db
558 #define ULINUX_KEY_FN_F11 0x1dc
559 #define ULINUX_KEY_FN_F12 0x1dd
560 #define ULINUX_KEY_FN_1 0x1de
561 #define ULINUX_KEY_FN_2 0x1df
562 #define ULINUX_KEY_FN_D 0x1e0
563 #define ULINUX_KEY_FN_E 0x1e1
564 #define ULINUX_KEY_FN_F 0x1e2
565 #define ULINUX_KEY_FN_S 0x1e3
566 #define ULINUX_KEY_FN_B 0x1e4
567
568 #define ULINUX_KEY_BRL_DOT1 0x1f1
569 #define ULINUX_KEY_BRL_DOT2 0x1f2
570 #define ULINUX_KEY_BRL_DOT3 0x1f3
571 #define ULINUX_KEY_BRL_DOT4 0x1f4
572 #define ULINUX_KEY_BRL_DOT5 0x1f5
573 #define ULINUX_KEY_BRL_DOT6 0x1f6
574 #define ULINUX_KEY_BRL_DOT7 0x1f7
575 #define ULINUX_KEY_BRL_DOT8 0x1f8
576 #define ULINUX_KEY_BRL_DOT9 0x1f9
577 #define ULINUX_KEY_BRL_DOT10 0x1fa
578
579 #define ULINUX_KEY_NUMERIC_0 0x200/*used by phones, remote controls,*/
580 #define ULINUX_KEY_NUMERIC_1 0x201/*and other keypads*/
581 #define ULINUX_KEY_NUMERIC_2 0x202
582 #define ULINUX_KEY_NUMERIC_3 0x203
583 #define ULINUX_KEY_NUMERIC_4 0x204
584 #define ULINUX_KEY_NUMERIC_5 0x205
585 #define ULINUX_KEY_NUMERIC_6 0x206
586 #define ULINUX_KEY_NUMERIC_7 0x207
587 #define ULINUX_KEY_NUMERIC_8 0x208
588 #define ULINUX_KEY_NUMERIC_9 0x209
589 #define ULINUX_KEY_NUMERIC_STAR 0x20a
590 #define ULINUX_KEY_NUMERIC_POUND 0x20b
591
592 #define ULINUX_KEY_CAMERA_FOCUS 0x210
593 #define ULINUX_KEY_WPS_BUTTON 0x211/*WiFi Protected Setup key*/
594
595 #define ULINUX_KEY_TOUCHPAD_TOGGLE 0x212/*Request switch touchpad on or off*/
596 #define ULINUX_KEY_TOUCHPAD_ON 0x213
597 #define ULINUX_KEY_TOUCHPAD_OFF 0x214
598
599 #define ULINUX_KEY_CAMERA_ZOOMIN 0x215
600 #define ULINUX_KEY_CAMERA_ZOOMOUT 0x216
601 #define ULINUX_KEY_CAMERA_UP 0x217
602 #define ULINUX_KEY_CAMERA_DOWN 0x218
603 #define ULINUX_KEY_CAMERA_LEFT 0x219
604 #define ULINUX_KEY_CAMERA_RIGHT 0x21a
605
606 #define ULINUX_BTN_TRIGGER_HAPPY 0x2c0
607 #define ULINUX_BTN_TRIGGER_HAPPY1 0x2c0
608 #define ULINUX_BTN_TRIGGER_HAPPY2 0x2c1
609 #define ULINUX_BTN_TRIGGER_HAPPY3 0x2c2
610 #define ULINUX_BTN_TRIGGER_HAPPY4 0x2c3
611 #define ULINUX_BTN_TRIGGER_HAPPY5 0x2c4
612 #define ULINUX_BTN_TRIGGER_HAPPY6 0x2c5
613 #define ULINUX_BTN_TRIGGER_HAPPY7 0x2c6
614 #define ULINUX_BTN_TRIGGER_HAPPY8 0x2c7
615 #define ULINUX_BTN_TRIGGER_HAPPY9 0x2c8
616 #define ULINUX_BTN_TRIGGER_HAPPY10 0x2c9
617 #define ULINUX_BTN_TRIGGER_HAPPY11 0x2ca
618 #define ULINUX_BTN_TRIGGER_HAPPY12 0x2cb
619 #define ULINUX_BTN_TRIGGER_HAPPY13 0x2cc
620 #define ULINUX_BTN_TRIGGER_HAPPY14 0x2cd
621 #define ULINUX_BTN_TRIGGER_HAPPY15 0x2ce
622 #define ULINUX_BTN_TRIGGER_HAPPY16 0x2cf
623 #define ULINUX_BTN_TRIGGER_HAPPY17 0x2d0
624 #define ULINUX_BTN_TRIGGER_HAPPY18 0x2d1
625 #define ULINUX_BTN_TRIGGER_HAPPY19 0x2d2
626 #define ULINUX_BTN_TRIGGER_HAPPY20 0x2d3
627 #define ULINUX_BTN_TRIGGER_HAPPY21 0x2d4
628 #define ULINUX_BTN_TRIGGER_HAPPY22 0x2d5
629 #define ULINUX_BTN_TRIGGER_HAPPY23 0x2d6
630 #define ULINUX_BTN_TRIGGER_HAPPY24 0x2d7
631 #define ULINUX_BTN_TRIGGER_HAPPY25 0x2d8
632 #define ULINUX_BTN_TRIGGER_HAPPY26 0x2d9
633 #define ULINUX_BTN_TRIGGER_HAPPY27 0x2da
634 #define ULINUX_BTN_TRIGGER_HAPPY28 0x2db
635 #define ULINUX_BTN_TRIGGER_HAPPY29 0x2dc
636 #define ULINUX_BTN_TRIGGER_HAPPY30 0x2dd
637 #define ULINUX_BTN_TRIGGER_HAPPY31 0x2de
638 #define ULINUX_BTN_TRIGGER_HAPPY32 0x2df
639 #define ULINUX_BTN_TRIGGER_HAPPY33 0x2e0
640 #define ULINUX_BTN_TRIGGER_HAPPY34 0x2e1
641 #define ULINUX_BTN_TRIGGER_HAPPY35 0x2e2
642 #define ULINUX_BTN_TRIGGER_HAPPY36 0x2e3
643 #define ULINUX_BTN_TRIGGER_HAPPY37 0x2e4
644 #define ULINUX_BTN_TRIGGER_HAPPY38 0x2e5
645 #define ULINUX_BTN_TRIGGER_HAPPY39 0x2e6
646 #define ULINUX_BTN_TRIGGER_HAPPY40 0x2e7
647
648 /*We avoid low common keys in module aliases so they don't get huge.*/
649 #define ULINUX_KEY_MIN_INTERESTING ULINUX_KEY_MUTE
650 #define ULINUX_KEY_MAX 0x2ff
651 #define ULINUX_KEY_CNT (ULINUX_KEY_MAX+1)
652
653 /*relative axes bit offsets*/
654 #define ULINUX_REL_X 0x00
655 #define ULINUX_REL_Y 0x01
656 #define ULINUX_REL_Z 0x02
657 #define ULINUX_REL_RX 0x03
658 #define ULINUX_REL_RY 0x04
659 #define ULINUX_REL_RZ 0x05
660 #define ULINUX_REL_HWHEEL 0x06
661 #define ULINUX_REL_DIAL 0x07
662 #define ULINUX_REL_WHEEL 0x08
663 #define ULINUX_REL_MISC 0x09
664 #define ULINUX_REL_MAX 0x0f
665 #define ULINUX_REL_CNT (ULINUX_REL_MAX+1)
666
667 /*Absolute axes bit offsets*/
668 #define ULINUX_ABS_X 0x00
669 #define ULINUX_ABS_Y 0x01
670 #define ULINUX_ABS_Z 0x02
671 #define ULINUX_ABS_RX 0x03
672 #define ULINUX_ABS_RY 0x04
673 #define ULINUX_ABS_RZ 0x05
674 #define ULINUX_ABS_THROTTLE 0x06
675 #define ULINUX_ABS_RUDDER 0x07
676 #define ULINUX_ABS_WHEEL 0x08
677 #define ULINUX_ABS_GAS 0x09
678 #define ULINUX_ABS_BRAKE 0x0a
679 #define ULINUX_ABS_HAT0X 0x10
680 #define ULINUX_ABS_HAT0Y 0x11
681 #define ULINUX_ABS_HAT1X 0x12
682 #define ULINUX_ABS_HAT1Y 0x13
683 #define ULINUX_ABS_HAT2X 0x14
684 #define ULINUX_ABS_HAT2Y 0x15
685 #define ULINUX_ABS_HAT3X 0x16
686 #define ULINUX_ABS_HAT3Y 0x17
687 #define ULINUX_ABS_PRESSURE 0x18
688 #define ULINUX_ABS_DISTANCE 0x19
689 #define ULINUX_ABS_TILT_X 0x1a
690 #define ULINUX_ABS_TILT_Y 0x1b
691 #define ULINUX_ABS_TOOL_WIDTH 0x1c
692
693 #define ULINUX_ABS_VOLUME 0x20
694
695 #define ULINUX_ABS_MISC 0x28
696
697 #define ULINUX_ABS_MT_SLOT 0x2f/*MT slot being modified*/
698 #define ULINUX_ABS_MT_TOUCH_MAJOR 0x30/*Major axis of touching ellipse*/
699 #define ULINUX_ABS_MT_TOUCH_MINOR 0x31/*Minor axis (omit if circular)*/
700 #define ULINUX_ABS_MT_WIDTH_MAJOR 0x32/*Major axis of approaching ellipse*/
701 #define ULINUX_ABS_MT_WIDTH_MINOR 0x33/*Minor axis (omit if circular)*/
702 #define ULINUX_ABS_MT_ORIENTATION 0x34/*Ellipse orientation*/
703 #define ULINUX_ABS_MT_POSITION_X 0x35/*Center X touch position*/
704 #define ULINUX_ABS_MT_POSITION_Y 0x36/*Center Y touch position*/
705 #define ULINUX_ABS_MT_TOOL_TYPE 0x37/*Type of touching device*/
706 #define ULINUX_ABS_MT_BLOB_ID 0x38/*Group a set of packets as a blob*/
707 #define ULINUX_ABS_MT_TRACKING_ID 0x39/*Unique ID of initiated contact*/
708 #define ULINUX_ABS_MT_PRESSURE 0x3a/*Pressure on contact area*/
709 #define ULINUX_ABS_MT_DISTANCE 0x3b/*Contact hover distance*/
710 #define ULINUX_ABS_MT_TOOL_X 0x3c/*Center X tool position*/
711 #define ULINUX_ABS_MT_TOOL_Y 0x3d/*Center Y tool position*/
712
713 #define ULINUX_ABS_MAX 0x3f
714 #define ULINUX_ABS_CNT (ULINUX_ABS_MAX+1)
715
716 /*Misc events bit offsets*/
717 #define ULINUX_MSC_SERIAL 0x00
718 #define ULINUX_MSC_PULSELED 0x01
719 #define ULINUX_MSC_GESTURE 0x02
720 #define ULINUX_MSC_RAW 0x03
721 #define ULINUX_MSC_SCAN 0x04
722 #define ULINUX_MSC_MAX 0x07
723 #define ULINUX_MSC_CNT (ULINUX_MSC_MAX+1)
724
725 /*Switch events bit offsets*/
726 #define ULINUX_SW_LID 0x00/*set = lid shut*/
727 #define ULINUX_SW_TABLET_MODE 0x01/*set = tablet mode*/
728 #define ULINUX_SW_HEADPHONE_INSERT 0x02/*set = inserted*/
729 #define ULINUX_SW_RFKILL_ALL 0x03/*rfkill master switch, type "any"*/
730 /*set = radio enabled*/
731 #define ULINUX_SW_RADIO ULINUX_SW_RFKILL_ALL/*deprecated*/
732 #define ULINUX_SW_MICROPHONE_INSERT 0x04/*set = inserted*/
733 #define ULINUX_SW_DOCK 0x05/*set = plugged into dock*/
734 #define ULINUX_SW_LINEOUT_INSERT 0x06/*set = inserted*/
735 #define ULINUX_SW_JACK_PHYSICAL_INSERT 0x07/*set = mechanical switch set*/
736 #define ULINUX_SW_VIDEOOUT_INSERT 0x08/*set = inserted*/
737 #define ULINUX_SW_CAMERA_LENS_COVER 0x09/*set = lens covered*/
738 #define ULINUX_SW_KEYPAD_SLIDE 0x0a/*set = keypad slide out*/
739 #define ULINUX_SW_FRONT_PROXIMITY 0x0b/*set = front proximity sensor
740 active*/
741 #define ULINUX_SW_ROTATE_LOCK 0x0c/*set = rotate locked/disabled*/
742 #define ULINUX_SW_LINEIN_INSERT 0x0d/*set = inserted*/
743 #define ULINUX_SW_MAX 0x0f
744 #define ULINUX_SW_CNT (ULINUX_SW_MAX+1)
745
746 /*LEDs bit offsets*/
747 #define ULINUX_LED_NUML 0x00
748 #define ULINUX_LED_CAPSL 0x01
749 #define ULINUX_LED_SCROLLL 0x02
750 #define ULINUX_LED_COMPOSE 0x03
751 #define ULINUX_LED_KANA 0x04
752 #define ULINUX_LED_SLEEP 0x05
753 #define ULINUX_LED_SUSPEND 0x06
754 #define ULINUX_LED_MUTE 0x07
755 #define ULINUX_LED_MISC 0x08
756 #define ULINUX_LED_MAIL 0x09
757 #define ULINUX_LED_CHARGING 0x0a
758 #define ULINUX_LED_MAX 0x0f
759 #define ULINUX_LED_CNT (ULINUX_LED_MAX+1)
760
761 /*Sounds bit offsets*/
762 #define ULINUX_SND_CLICK 0x00
763 #define ULINUX_SND_BELL 0x01
764 #define ULINUX_SND_TONE 0x02
765 #define ULINUX_SND_MAX 0x07
766 #define ULINUX_SND_CNT (ULINUX_SND_MAX+1)
767
768 /*ff status of a force-feedback effect offset bits*/
769 #define ULINUX_FF_STATUS_STOPPED 0x00
770 #define ULINUX_FF_STATUS_PLAYING 0x01
771 #define ULINUX_FF_STATUS_MAX 0x01
772
773 /*Force feedback effect types*/
774 #define ULINUX_FF_RUMBLE 0x50
775 #define ULINUX_FF_PERIODIC 0x51
776 #define ULINUX_FF_CONSTANT 0x52
777 #define ULINUX_FF_SPRING 0x53
778 #define ULINUX_FF_FRICTION 0x54
779 #define ULINUX_FF_DAMPER 0x55
780 #define ULINUX_FF_INERTIA 0x56
781 #define ULINUX_FF_RAMP 0x57
782
783 #define ULINUX_FF_EFFECT_MIN FF_RUMBLE
784 #define ULINUX_FF_EFFECT_MAX FF_RAMP
785
786 /*Force feedback periodic effect types*/
787 #define ULINUX_FF_SQUARE 0x58
788 #define ULINUX_FF_TRIANGLE 0x59
789 #define ULINUX_FF_SINE 0x5a
790 #define ULINUX_FF_SAW_UP 0x5b
791 #define ULINUX_FF_SAW_DOWN 0x5c
792 #define ULINUX_FF_CUSTOM 0x5d
793
794 #define ULINUX_FF_WAVEFORM_MIN FF_SQUARE
795 #define ULINUX_FF_WAVEFORM_MAX FF_CUSTOM
796
797 /*Set ff device properties*/
798 #define ULINUX_FF_GAIN 0x60
799 #define ULINUX_FF_AUTOCENTER 0x61
800
801 #define ULINUX_FF_MAX 0x7f
802 #define ULINUX_FF_CNT (ULINUX_FF_MAX+1)
803 #endif
File ulinux/ioctl.h added (mode: 100644) (index 0000000..161f068)
1 #ifndef ULINUX_IOCTL_H
2 #define ULINUX_IOCTL_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7
8 /*
9 * ioctl command encoding: 32 bits total, command in lower 16 bits,
10 * size of the parameter structure in the lower 14 bits of the
11 * upper 16 bits.
12 * Encoding the size of the parameter structure in the ioctl request
13 * is useful for catching programs compiled with old versions
14 * and to avoid overwriting user space outside the user buffer area.
15 * The highest 2 bits are reserved for indicating the ``access mode''.
16 * NOTE: This limits the max parameter size to 16kB -1 !
17 *
18 * The following is for compatibility across the various Linux
19 * platforms. The generic ioctl numbering scheme doesn't really enforce
20 * a type field. De facto, however, the top 8 bits of the lower 16
21 * bits are indeed used as a type field, so we might just as well make
22 * this explicit here. Please be sure to use the decoding macros
23 * below from now on.
24 */
25
26 #define ULINUX_IOC_NRBITS 8
27 #define ULINUX_IOC_TYPEBITS 8
28
29 /*
30 * Let any architecture override either of the following before
31 * including this file.
32 */
33
34 /*XXX:can be arch dependent*/
35 #define ULINUX_IOC_SIZEBITS 14
36
37 /*XXX:can be arch dependent*/
38 #define ULINUX_IOC_DIRBITS 2
39
40 #define ULINUX_IOC_NRMASK ((1<<ULINUX_IOC_NRBITS)-1)
41 #define ULINUX_IOC_TYPEMASK ((1<<ULINUX_IOC_TYPEBITS)-1)
42 #define ULINUX_IOC_SIZEMASK ((1<<ULINUX_IOC_SIZEBITS)-1)
43 #define ULINUX_IOC_DIRMASK ((1<<ULINUX_IOC_DIRBITS)-1)
44
45 #define ULINUX_IOC_NRSHIFT 0
46 #define ULINUX_IOC_TYPESHIFT (ULINUX_IOC_NRSHIFT+ULINUX_IOC_NRBITS)
47 #define ULINUX_IOC_SIZESHIFT (ULINUX_IOC_TYPESHIFT+ULINUX_IOC_TYPEBITS)
48 #define ULINUX_IOC_DIRSHIFT (ULINUX_IOC_SIZESHIFT+ULINUX_IOC_SIZEBITS)
49
50 /*
51 * Direction bits, which any architecture can choose to override
52 * before including this file.
53 */
54
55 /*XXX:can be arch dependent*/
56 #define ULINUX_IOC_NONE 0U
57
58 /*XXX:can be arch dependent*/
59 #define ULINUX_IOC_WRITE 1U
60
61 /*XXX:can be arch dependent*/
62 #define ULINUX_IOC_READ 2U
63
64 #define ULINUX_IOC(dir,type,nr,size) \
65 (((dir)<<ULINUX_IOC_DIRSHIFT) | \
66 ((type)<<ULINUX_IOC_TYPESHIFT) | \
67 ((nr)<<ULINUX_IOC_NRSHIFT) | \
68 ((size)<<ULINUX_IOC_SIZESHIFT))
69
70 #define ULINUX_IOC_TYPECHECK(t) (sizeof(t))
71
72 /*used to create numbers*/
73 #define ULINUX_IO(type,nr) ULINUX_IOC(ULINUX_IOC_NONE,(type),(nr),0)
74 #define ULINUX_IOR(type,nr,size)\
75 ULINUX_IOC(ULINUX_IOC_READ,(type),(nr),(ULINUX_IOC_TYPECHECK(size)))
76 #define ULINUX_IOW(type,nr,size)\
77 ULINUX_IOC(ULINUX_IOC_WRITE,(type),(nr),(ULINUX_IOC_TYPECHECK(size)))
78 #define ULINUX_IOWR(type,nr,size)\
79 ULINUX_IOC(ULINUX_IOC_READ|ULINUX_IOC_WRITE,(type),(nr),\
80 (ULINUX_IOC_TYPECHECK(size)))
81 #define ULINUX_IOR_BAD(type,nr,size) ULINUX_IOC(ULINUX_IOC_READ,(type),(nr),\
82 sizeof(size))
83 #define ULINUX_IOW_BAD(type,nr,size) ULINUX_IOC(ULINUX_IOC_WRITE,(type),(nr),\
84 sizeof(size))
85 #define ULINUX_IOWR_BAD(type,nr,size)\
86 ULINUX_IOC(ULINUX_IOC_READ|ULINUX_IOC_WRITE,(type),(nr),sizeof(size))
87
88 /*used to decode ioctl numbers*/
89 #define ULINUX_IOC_DIR(nr) (((nr)>>ULINUX_IOC_DIRSHIFT)&ULINUX_IOC_DIRMASK)
90 #define ULINUX_IOC_TYPE(nr) (((nr)>>ULINUX_IOC_TYPESHIFT)&ULINUX_IOC_TYPEMASK)
91 #define ULINUX_IOC_NR(nr) (((nr)>>ULINUX_IOC_NRSHIFT)&ULINUX_IOC_NRMASK)
92 #define ULINUX_IOC_SIZE(nr) (((nr)>>ULINUX_IOC_SIZESHIFT)&ULINUX_IOC_SIZEMASK)
93
94 /*...and for the drivers/sound files...*/
95 #define ULINUX_IOC_IN (ULINUX_IOC_WRITE<<ULINUX_IOC_DIRSHIFT)
96 #define ULINUX_IOC_OUT (ULINUX_IOC_READ<<ULINUX_IOC_DIRSHIFT)
97 #define ULINUX_IOC_INOUT ((ULINUX_IOC_WRITE|ULINUX_IOC_READ)<<\
98 ULINUX_IOC_DIRSHIFT)
99 #define ULINUX_IOCSIZE_MASK (ULINUX_IOC_SIZEMASK<<ULINUX_IOC_SIZESHIFT)
100 #define ULINUX_IOCSIZE_SHIFT (ULINUX_IOC_SIZESHIFT)
101 #endif
File ulinux/mmap.h added (mode: 100644) (index 0000000..d5c2450)
1 #ifndef ULINUX_MMAP_H
2 #define ULINUX_MMAP_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 #include <ulinux/arch/mmap.h>
8
9 #define ULINUX_MAP_GROWSDOWN 0x0100 /* stack-like segment */
10 #define ULINUX_MAP_DENYWRITE 0x0800 /* ETXTBSY */
11 #define ULINUX_MAP_EXECUTABLE 0x1000 /* mark it as an executable */
12 #define ULINUX_MAP_LOCKED 0x2000 /* pages are locked */
13 #define ULINUX_MAP_NORESERVE 0x4000 /* don't check for reservations */
14 #define ULINUX_MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
15 #define ULINUX_MAP_NONBLOCK 0x10000 /* do not block on IO */
16 #define ULINUX_MAP_STACK 0x20000 /*
17 * give out an address that is best
18 * suited for process/thread stacks
19 * XXX:it's a NOOP, linux does not use
20 * it
21 */
22 #define ULINUX_MAP_HUGETLB 0x40000 /* create a huge page mapping */
23 #define ULINUX_MAP_SYNC 0x80000 /*
24 * perform synchronous page faults for
25 * the mapping
26 */
27
28 #define ULINUX_MCL_CURRENT 1 /* lock all current mappings */
29 #define ULINUX_MCL_FUTURE 2 /* lock all future mappings */
30 #define ULINUX_MCL_ONFAULT 4 /* lock all pages that are faulted in */
31
32 /*---------------------------------------------------------------------------*/
33
34 #define ULINUX_PROT_READ 0x1 /* page can be read */
35 #define ULINUX_PROT_WRITE 0x2 /* page can be written */
36 #define ULINUX_PROT_EXEC 0x4 /* page can be executed */
37 #define ULINUX_PROT_SEM 0x8 /*
38 * page may be used for atomic
39 * ops
40 */
41 #define ULINUX_PROT_NONE 0x0 /* page can not be accessed */
42 #define ULINUX_PROT_GROWSDOWN 0x01000000 /*
43 * mprotect flag: extend change
44 * to start of growsdown vma
45 */
46 #define ULINUX_PROT_GROWSUP 0x02000000 /*
47 * mprotect flag: extend change
48 * to end of growsup vma
49 */
50
51 #define ULINUX_MAP_TYPE 0x0f /* Mask for type of mapping */
52 #define ULINUX_MAP_FIXED 0x10 /* Interpret addr exactly */
53 #define ULINUX_MAP_ANONYMOUS 0x20 /* don't use a file */
54 #define ULINUX_MAP_UNINITIALIZED 0x4000000
55
56 /*---------------------------------------------------------------------------*/
57
58 #define ULINUX_MAP_SHARED 0x01 /* Share changes */
59 #define ULINUX_MAP_PRIVATE 0x02 /* Changes are private */
60
61 #define ULINUX_MREMAP_MAYMOVE 0x1
62 #define ULINUX_MREMAP_FIXED 0x2
63 #endif
File ulinux/patterns/README added (mode: 100644) (index 0000000..76c95db)
1 Most, but not all, are broken. It's meant to show the way.
File ulinux/patterns/clock_nanosleep/clock_nanosleep.c added (mode: 100644) (index 0000000..9eed910)
1 /*
2 * XXX: if you are a heavy user of of time related calls, vdso calls
3 * are prefered to syscalls. That depends on the arch.
4 */
5 #include <stdarg.h>
6
7 #include <ulinux/compiler_types.h>
8 #include <ulinux/sysc.h>
9
10 #include <ulinux/error.h>
11 #include <ulinux/types.h>
12
13 #include <ulinux/time.h>
14
15 #include <ulinux/utils/mem.h>
16 #include <ulinux/utils/ascii/string/vsprintf.h>
17
18 /* ulinux namespace */
19 #define EINTR ULINUX_EINTR
20 #define EAGAIN ULINUX_EAGAIN
21 #define si ulinux_si
22 #define sl ulinux_sl
23 #define u8 ulinux_u8
24 #define exit(a) ulinux_sysc(exit,1,a)
25 #define ISERR(x) ULINUX_ISERR(x)
26 #define CLOCK_MONOTONIC ULINUX_CLOCK_MONOTONIC
27 #define TIMER_ABSTIME ULINUX_TIMER_ABSTIME
28 #define clock_getres(a,b) ulinux_sysc(clock_getres,2,a,b)
29 #define clock_gettime(a,b) ulinux_sysc(clock_gettime,2,a,b)
30 #define clock_nanosleep(a,b,c,d) ulinux_sysc(clock_nanosleep,4,a,b,c,d)
31 #define memset(a,b,c) ulinux_memset((u8*)a,b,c)
32 #define timespec ulinux_timespec
33
34 #define loop for(;;)
35
36 #define BUFSIZ 8192
37 static u8 dprint_buf[BUFSIZ];
38 #define POUT(fmt,...) ulinux_dprintf(1, &dprint_buf[0], BUFSIZ - 1, fmt, ##__VA_ARGS__)
39
40 #define SLEEP_TIME_SEC 8
41
42 static void get_monotonic_clock(struct timespec *request)
43 {
44 sl r;
45
46 memset(request, 0, sizeof(*request));
47
48 r = clock_gettime(CLOCK_MONOTONIC, request);
49 if (ISERR(r)) {
50 POUT("error while getting the current monotonic clock time (%ld)\n", r);
51 exit(2);
52 }
53 POUT("current monotonic clock is %ld secs and %ld nsecs\n", request->sec, request->nsec);
54 }
55
56 void _start(void)
57 {
58 sl r;
59 struct timespec resolution;
60 struct timespec target;
61 struct timespec current_time;
62
63 dprint_buf[BUFSIZ - 1] = 0; /* secure a 0 terminating char */
64
65 memset(&resolution, 0, sizeof(resolution));
66
67 r = clock_getres(CLOCK_MONOTONIC, &resolution);
68
69 if (ISERR(r)) {
70 POUT("error while getting the resolution of the monotonic clock (%ld)\n", r);
71 exit(1);
72 }
73
74 POUT("monotonic clock resolution is %lu|%lu sec|nsec\n", resolution.sec, resolution.nsec);
75
76 /*-------------------------------------------------------------------*/
77
78 get_monotonic_clock(&target);
79
80 /*-------------------------------------------------------------------*/
81
82 /* project ourself of a few secs in the future of this absolute clock */
83 target.sec += SLEEP_TIME_SEC;
84 target.nsec = 0;
85 POUT("targeting monotonic clock at %ld secs and %ld nsecs\n", target.sec, target.nsec);
86
87 /*
88 * we put the call in a loop because it should be restarted if the call
89 * was interrupted my a interrupt
90 */
91 loop {
92 /* ABSolute timer */
93 r = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &target, 0);
94 if (r == 0)
95 break;
96
97 if (r == -EINTR) {
98 POUT("interrupted by a runned signal handler at: ");
99 get_monotonic_clock(&current_time);
100 POUT("restarting, targeting the same absolute clock time\n");
101 continue;
102 }
103
104 if (ISERR(r)) {
105 POUT("error while nanosleeping (%ld) at:\n", r);
106 get_monotonic_clock(&current_time);
107 exit(4);
108 }
109 }
110 POUT("successfully waited and we are at: ");
111 get_monotonic_clock(&current_time);
112 exit(0);
113 }
File ulinux/patterns/clock_nanosleep/make added (mode: 100755) (index 0000000..e414a63)
1 #!/bin/sh
2
3 set -e
4
5 ulinux_location=$(readlink -e ../../..)
6 build_dir=$(readlink -e .)
7 echo "ulinux_location=$ulinux_location"
8 echo "build_dir=$build_dir"
9
10 if test "$1" = "clean"; then
11 echo cleaning build products... in $build_dir
12
13 rm -f $build_dir/ulinux/arch
14 rmdir $build_dir/ulinux || true
15
16 rm -f $build_dir/mem.o
17 rm -f $build_dir/vsprintf.o
18 rm -f $build_dir/clock_nanosleep.o
19 rm -f $build_dir/clock_nanosleep
20 exit 0;
21 fi
22
23 leaner_gcc_opts='-fno-stack-protector -fno-asynchronous-unwind-tables -fno-dwarf2-cfi-asm'
24 cc="gcc -pipe -O2 -I. -I$ulinux_location -static-libgcc $leaner_gcc_opts"
25 ld="ld -O -nostdlib -Bstatic --strip-all $(gcc -print-libgcc-file-name)"
26 echo "cc=$cc"
27 echo "ld=$ld"
28
29 mkdir -p $build_dir/ulinux
30 # arch is hardcoded
31 ln -sTf $ulinux_location/ulinux/archs/x86_64 $build_dir/ulinux/arch
32
33 $cc -c $ulinux_location/ulinux/utils/mem.c -o $build_dir/mem.o
34 $cc -c $ulinux_location/ulinux/utils/ascii/string/vsprintf.c \
35 -o $build_dir/vsprintf.o
36 $cc -c $build_dir/clock_nanosleep.c -o $build_dir/clock_nanosleep.o
37 $ld $build_dir/mem.o $build_dir/vsprintf.o $build_dir/clock_nanosleep.o \
38 -o $build_dir/clock_nanosleep
File ulinux/patterns/conf_ini/conf_ini.c added (mode: 100644) (index 0000000..41aaf96)
1 #include <stdarg.h>
2 #include <ulinux/compiler_types.h>
3 #include <ulinux/sysc.h>
4 #include <ulinux/types.h>
5 #include <ulinux/error.h>
6 #include <ulinux/args_env.h>
7 #include <ulinux/file.h>
8 #include <ulinux/stat.h>
9 #include <ulinux/mmap.h>
10
11 #include <ulinux/utils/mem.h>
12 #include <ulinux/utils/ascii/string/string.h>
13 #include <ulinux/utils/ascii/string/vsprintf.h>
14 #include <ulinux/utils/ascii/block/conv/decimal/decimal.h>
15
16 //------------------------------------------------------------------------------
17 //ulinux namespace
18 #define EINTR ULINUX_EINTR
19 #define EAGAIN ULINUX_EAGAIN
20 #define si ulinux_si
21 #define sl ulinux_sl
22 #define u8 ulinux_u8
23 #define s8 ulinux_s8
24 #define u32 ulinux_u32
25 #define s32 ulinux_s32
26 #define u64 ulinux_u64
27 #define s64 ulinux_s64
28 #define ISERR ULINUX_ISERR
29 #define stat ulinux_stat
30 #define PROT_READ ULINUX_PROT_READ
31 #define MAP_PRIVATE ULINUX_MAP_PRIVATE
32 #define MAP_POPULATE ULINUX_MAP_POPULATE
33 #define strncmp ulinux_strncmp
34 #define dec2u32_blk ulinux_dec2u32_blk
35 #define O_RDONLY ULINUX_O_RDONLY
36 #define open(path,flgs,more) ulinux_sysc(open,3,path,flgs,more)
37 #define fstat(fd,stat) ulinux_sysc(fstat,2,fd,stat)
38 #define mmap(addr,sz,attr,flgs,fd,off) ulinux_sysc(mmap,6,addr,sz,attr,flgs,fd,\
39 off)
40 #define close(fd) ulinux_sysc(close,1,fd)
41 #define munmap(addr,sz) ulinux_sysc(munmap,2,addr,sz)
42 #define exit(code) ulinux_sysc(exit_group,1,code)
43 //------------------------------------------------------------------------------
44
45 #define CONF_INI_ERR -1
46 #define CONF_INI_OK 0
47
48 #define DPRINTF_BUF_SZ 512
49
50 #define cs_n(x) (sizeof(x)-1)
51
52 #define PERRC(str) {l rl;do{rl=ulinux_sysc(write,3,2,str,cs_n(str));}\
53 while(rl==-EINTR||rl==-EAGAIN);}
54 #define PERR(fmt,...) ulinux_dprintf(2,dprintf_buf,DPRINTF_BUF_SZ,fmt,\
55 ##__VA_ARGS__)
56 #define POUT(fmt,...) ulinux_dprintf(1,dprintf_buf,DPRINTF_BUF_SZ,fmt,\
57 ##__VA_ARGS__)
58 #define POUTC(str) {l rl;do{rl=ulinux_sysc(write,3,1,str,cs_n(str));}\
59 while(rl==-EINTR||rl==-EAGAIN);}
60
61 static u8 *dprintf_buf;
62
63 //******************************************************************************
64 //data structs
65 struct ctx{
66 i fd;
67 void *m;
68 u64 sz;
69 };
70
71 struct ctx_mysection{
72 //here should go some variable to match properly a mysection
73 struct ctx c;
74 };
75 //******************************************************************************
76
77 //******************************************************************************
78 //generic parse functions
79 static s64 blanks_skip(struct ctx *c,s64 start,s64 line_end)
80 {
81 while(1){
82 if(start==line_end) break;
83 u8 start_char=*(u8*)(c->m+start);
84 if(start_char!=' '&&start_char!='\t') break;
85 ++start;
86 }
87 return start;
88 }
89
90 static s64 non_blanks_skip(struct ctx *c,s64 start,s64 line_end)
91 {
92 while(1){
93 if(start==line_end) break;
94 u8 start_char=*(u8*)(c->m+start);
95 if(start_char==' '||start_char=='\t') break;
96 ++start;
97 }
98 return start;
99 }
100
101 #define KEY_SKIP_TO_VAL_NO_VAL -1
102 static s64 key_skip_to_val(struct ctx *c,s64 start, s64 line_end)
103 {
104 while(1){
105 if(start==line_end) break;
106 if(*(u8*)(c->m+start)=='=') break;
107 ++start;
108 }
109 if(start==line_end) return KEY_SKIP_TO_VAL_NO_VAL;
110 s64 val_start=start+1;
111 if(val_start==line_end) return KEY_SKIP_TO_VAL_NO_VAL;
112 return val_start;
113 }
114
115 //line_end is the offset of the terminating '/n' or of the byte right after
116 //the last file byte
117 static s64 line_end_reach(struct ctx *c,s64 line_start)
118 {
119 s64 line_end=line_start;
120 while(1){
121 if((u64)line_end==c->sz||*(u8*)(c->m+line_end)=='\n') return line_end;
122 ++line_end;
123 }
124 }
125 //end generic parse functions
126 //******************************************************************************
127
128 //******************************************************************************
129 //file management related functions
130 static s8 file_open_ro(struct ctx *c,void *path)
131 {
132 i fd;
133 do fd=open(path,O_RDONLY,0); while(fd==-EINTR);
134 if(ISERR(fd)){
135 PERR("file:error(%d):unable to open conf file %s\n",fd,path);
136 goto err;
137 }
138
139 struct stat cfg_stat;
140 l r=fstat(fd,&cfg_stat);
141 if(ISERR(r)){
142 PERR("file:error(%ld):unable to stat conf file %s\n",r,path);
143 goto err_close_fd;
144 }
145
146 l addr=mmap(0,cfg_stat.sz,PROT_READ,MAP_PRIVATE|MAP_POPULATE,fd,0);
147 if(!addr||ISERR(addr)){
148 PERR("file:error(%ld):unable to mmap conf file %s\n",addr,path);
149 goto err_close_fd;
150 }
151
152 c->fd=fd;
153 c->m=(void*)addr;
154 c->sz=(u64)cfg_stat.sz;
155
156 POUT("file:conf file %s opened and mmaped\n",path);
157 return CONF_INI_OK;
158
159 err_close_fd:
160 do r=close(fd); while(r==-EINTR);
161 if(ISERR(r))
162 PERR("file:error(%ld):unable to close conf file\n",r,path);
163 err:
164 return CONF_INI_ERR;
165 }
166
167 static s8 file_close(struct ctx *c)
168 {
169 s8 r0=CONF_INI_OK;
170
171 l r=munmap(c->m,c->sz);
172 if(ISERR(r)){
173 PERR("file:error(%ld):unable to munmap conf file\n",r);
174 r0=CONF_INI_ERR;goto exit;
175 }
176
177 do r=close(c->fd); while(r==-EINTR);
178 if(ISERR(r)){
179 PERR("file:error(%ld):closing conf file gone wrong\n",r);
180 r0=CONF_INI_ERR;goto exit;
181 }
182
183 POUTC("file:conf file unmapped and closed\n");
184 exit:
185 return r0;
186 }
187 //end file management related functions
188 //******************************************************************************
189
190 //******************************************************************************
191 //parse section properties
192 static void *string_property_get(struct ctx_mysection *cm,s64 val_start,
193 s64 line_end)
194 {
195 POUTC("string property found\n");
196 void *r="not valid value";
197
198 s64 val_end=non_blanks_skip(&cm->c,val_start,line_end);
199
200 if((val_end-val_start)==cs_n("value0")&&!strncmp(cm->c.m+val_start,"value0",
201 val_end-val_start))
202 r="value0";
203 else if((val_end-val_start)==cs_n("value1")&&!strncmp(cm->c.m+val_start,
204 "value1",val_end-val_start))
205 r="value1";
206 return r;
207 }
208
209 static s32 integer_property_get(struct ctx_mysection *cm,s64 val_start,
210 s64 line_end)
211 {
212 POUTC("integer property found\n");
213 s32 r0=0;
214
215 s64 val_end=non_blanks_skip(&cm->c,val_start,line_end);
216
217 u32 integer;
218 u8 r1=dec2u32_blk(&integer,cm->c.m+val_start,cm->c.m+val_end-1);
219 if(!r1){
220 PERRC("integer not a valid number\n");
221 goto exit;
222 }
223 if(integer>0x7fffffff){
224 PERR("integer(%u) above max(%u)\n",integer,0x7fffffff);
225 goto exit;
226 }
227 r0=(s32)integer;
228 exit:
229 return r0;
230 }
231
232 #define STRING_PROPERTY_KEY_STR "string"
233 #define INTEGER_PROPERTY_KEY_STR "integer"
234
235 #define IS_KEY(x) (val_start-1-key_start)==cs_n(x ## _KEY_STR)\
236 &&!strncmp(cm->c.m+key_start,x ## _KEY_STR,val_start-1-key_start)
237 static void mysection_mycategory_properties_get(struct ctx_mysection *cm,
238 s64 mysection_start)
239 {
240 void *string_property="not found";
241 u32 integer_property=0;
242
243 s64 line_start=mysection_start;
244 while(1){
245 if((u64)line_start>=cm->c.sz){
246 POUTC("no more mycategory properties:line start not in file\n");
247 break;
248 }
249
250 s64 line_end=line_end_reach(&cm->c,line_start);
251 s64 key_start=blanks_skip(&cm->c,line_start,line_end);
252
253 //finished:beginning of next section reached ("[key]")
254 if(*(u8*)(cm->c.m+key_start)=='[') break;
255
256 s64 val_start=key_skip_to_val(&cm->c,key_start,line_end);
257 if(val_start==KEY_SKIP_TO_VAL_NO_VAL){
258 POUTC("no value\n");
259 }else{
260 if(IS_KEY(STRING_PROPERTY))
261 string_property=string_property_get(cm,val_start,line_end);
262 else if(IS_KEY(INTEGER_PROPERTY))
263 integer_property=integer_property_get(cm,val_start,line_end);
264 //add more properties in mycategory here
265 }
266
267 line_start=line_end+1;
268 }
269 POUT("CONF:string_property=%s integer_property=%d\n",string_property,
270 integer_property);
271 }
272 //end parse section properties
273 //******************************************************************************
274
275 //******************************************************************************
276 //parse conf file sections
277 #define MYSECTION_STR "[mysection]"
278 #define NO_MORE_MYSECTIONS -1
279 static s64 next(struct ctx_mysection *cm,s64 line_start)
280 {
281 while(1){
282 if((u64)line_start>=cm->c.sz){
283 PERRC("no more output section:line start not in file\n");
284 return NO_MORE_MYSECTIONS;
285 }
286
287 s64 line_end=line_end_reach(&cm->c,line_start);
288 s64 key_start=blanks_skip(&cm->c,line_start,line_end);
289 s64 key_end=non_blanks_skip(&cm->c,key_start,line_end);
290
291 if(key_end-key_start==cs_n(MYSECTION_STR)&&!strncmp(cm->c.m+key_start,
292 MYSECTION_STR,key_end-key_start)){
293 PERR("mysection found at %ld\n",key_start);
294 return line_end+1;
295 }
296
297 line_start=line_end+1;
298 }
299 }
300
301 #define MATCH_ERR -1
302 #define NO_MATCH 0
303 #define MATCH 1
304 static s8 match(struct ctx_mysection *cm,s64 mysection_start)
305 {
306 //XXX:in the meantime we match all the time
307 (void)cm;(void)mysection_start;
308 POUTC("unimplemented->we always match the first mysection\n");
309 return MATCH;
310 }
311
312 #define LOOKUP_ERR -2
313 #define LOOKUP_NOT_FOUND -1
314 static s64 mysection_lookup(struct ctx_mysection *cm)
315 {
316 s64 mysection_start=0;
317 while(1){
318 mysection_start=next(cm,mysection_start);
319 if(mysection_start==NO_MORE_MYSECTIONS){
320 POUTC("no matching mysection was found\n");
321 return LOOKUP_NOT_FOUND;
322 }
323
324 s8 r=match(cm,mysection_start);
325 if(r==MATCH){
326 POUTC("a matching mysection was found\n");
327 return mysection_start;
328 }
329 if(r==MATCH_ERR){
330 return LOOKUP_ERR;
331 }
332 }
333 }
334 //parse conf file sections
335 //******************************************************************************
336
337 void ulinux_start(l argc,void **argv)
338 {
339 u8 _dprintf_buf[DPRINTF_BUF_SZ];
340 dprintf_buf=&_dprintf_buf[0];
341
342 if(argc!=2){
343 PERR("args:error:missing path name argument for conf file(argc=%d)\n",argc);
344 exit(-1);
345 }
346
347 struct ctx_mysection cm;
348 cm.c.fd=-1;
349 cm.c.m=0;
350 cm.c.sz=0;
351
352 s8 r=file_open_ro(&cm.c,argv[1]);
353 if(r==CONF_INI_ERR) exit(-1);
354
355 s64 mysection_start=mysection_lookup(&cm);
356 if(mysection_start>=0){
357 mysection_mycategory_properties_get(&cm,mysection_start);
358 //here you can add other property categories
359 }
360
361 file_close(&cm.c);//ignore errors
362 exit(0);
363 }
File ulinux/patterns/conf_ini/makefile added (mode: 100644) (index 0000000..e4ed7db)
1 .PHONY:clean
2
3 #does remove some useless ELF sections
4 OPTIM=-fno-stack-protector -fno-asynchronous-unwind-tables -fno-dwarf2-cfi-asm \
5 -Ofast -march=native
6
7 ARCH?=$(shell uname -m | sed -e s/i.86/x86/ -e s/parisc64/parisc/ \
8 -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/ -e s/sh.*/sh/)
9
10 conf_ini:conf_ini.c ../../../ulinux/arch
11 cpp -Wall -Wextra -I../../.. ../../utils/mem.c -o cpp_mem.c
12 gcc -Wall -Wextra -std=gnu99 $(OPTIM) -c cpp_mem.c -o mem.o
13 cpp -Wall -Wextra -I../../.. ../../utils/ascii/string/vsprintf.c \
14 -o cpp_vsprintf.c
15 gcc -Wall -Wextra -std=gnu99 $(OPTIM) -c cpp_vsprintf.c -o vsprintf.o
16 as ../../arch/args_env.s -o args_env.o
17 cpp -Wall -Wextra -I../../.. \
18 ../../utils/ascii/block/conv/decimal/decimal.c \
19 -o cpp_decimal.c
20 gcc -Wall -Wextra -std=gnu99 $(OPTIM) -c cpp_decimal.c -o decimal.o
21 as ../../arch/args_env.s -o args_env.o
22 cpp -Wall -Wextra -I../../.. conf_ini.c -o cpp_conf_ini.c
23 gcc -Wall -Wextra -std=gnu99 $(OPTIM) -c cpp_conf_ini.c -o conf_ini.o
24 ld -O -nostdlib -Bstatic --strip-all conf_ini.o args_env.o string.o \
25 mem.o vsprintf.o decimal.o $$(gcc -print-libgcc-file-name) \
26 --output conf_ini
27
28 ../../../ulinux/arch:
29 ln -s archs/$(ARCH) ../../../ulinux/arch
30
31 clean:
32 -rm -f ../../../ulinux/arch
33 -rm -f cpp_conf_ini.c conf_ini.o conf_ini \
34 cpp_mem.c mem.o \
35 cpp_decimal.c decimal.o \
36 cpp_vsprintf.c vsprintf.o \
37 args_env.o
38
File ulinux/patterns/conf_ini/test.conf added (mode: 100644) (index 0000000..67f99e0)
1
2
3
4 [mysection]
5 integer=1024
6 string=value1
File ulinux/patterns/dir_parse/dir_parse.c added (mode: 100644) (index 0000000..c98e3be)
1 #include <stdarg.h>
2 #include <ulinux/compiler_types.h>
3 #include <ulinux/sysc.h>
4 #include <ulinux/types.h>
5 #include <ulinux/error.h>
6 #include <ulinux/args_env.h>
7 #include <ulinux/file.h>
8 #include <ulinux/fs.h>
9 #include <ulinux/dirent.h>
10
11 #include <ulinux/utils/ascii/string/vsprintf.h>
12
13 /*----------------------------------------------------------------------------*/
14 /*ulinux namespace*/
15 #define EINTR ULINUX_EINTR
16 #define EAGAIN ULINUX_EAGAIN
17 #define si ulinux_si
18 #define sl ulinux_sl
19 #define u8 ulinux_u8
20 #define s64 ulinux_s64
21 #define dirent64 ulinux_dirent64
22 #define getdents64(fd,dirents,sz) ulinux_sysc(getdents64,3,fd,dirents,sz)
23 #define ISERR ULINUX_ISERR
24 #define exit(code) ulinux_sysc(exit_group,1,code)
25 #define DT_DIR ULINUX_DT_DIR
26 #define openat(fd,name,flgs) ulinux_sysc(openat,4,fd,name,flgs,0)
27 #define open(path,flgs) ulinux_sysc(open,3,path,flgs,0)
28 #define RDONLY ULINUX_O_RDONLY
29 #define NONBLOCK ULINUX_O_NONBLOCK
30 #define close(fd) ulinux_sysc(close,1,fd)
31 #define loop while(1)
32 /*----------------------------------------------------------------------------*/
33
34 #define DPRINTF_BUF_SZ 1024
35 static u8 *dprintf_buf;
36
37 #define cs_n(x) (sizeof(x)-1)
38
39 #define PERRC(str) \
40 { \
41 l rl; \
42 loop{ \
43 rl=ulinux_sysc(write,3,2,str,cs_n(str)); \
44 if(rl!=-EINTR&&rl!=-EAGAIN) break; \
45 } \
46 }
47
48 #define PERR(fmt,...) ulinux_dprintf(2,dprintf_buf,DPRINTF_BUF_SZ,\
49 (ulinux_u8*)fmt, ##__VA_ARGS__)
50
51 #define POUT(fmt,...) ulinux_dprintf(1,dprintf_buf,DPRINTF_BUF_SZ,\
52 (ulinux_u8*)fmt,##__VA_ARGS__)
53
54 #define POUTC(str) \
55 { \
56 l rl; \
57 loop{ \
58 rl=ulinux_sysc(write,3,1,str,cs_n(str)); \
59 if(rl!=-EINTR&&rl!=-EAGAIN) break; \
60 } \
61 }
62
63 static u8 is_current(u8 *n)
64 {
65 if(n[0]=='.'&&n[1]==0) return 1;
66 return 0;
67 }
68
69 static u8 is_parent(u8 *n)
70 {
71 if(n[0]=='.'&&n[1]=='.'&&n[2]==0) return 1;
72 return 0;
73 }
74
75 static s64 depth=-1;
76
77 static void dout(struct dirent64 *d)
78 {
79 s64 j;
80
81 POUT("%20lu %20ld %2u ",d->ino,d->off,d->type);
82 j=depth;
83 loop{
84 if(j==0) break;
85 j--;
86 POUTC(" ");
87 }
88 POUT("%s\n",d->name);
89 }
90
91 #define DIRENTS_BUF_SZ 8192
92 /*XXX:carefull, the dentry type is not supported by all fs*/
93 static void dir_parse(i parent_fd)
94 {
95 u8 dirents[DIRENTS_BUF_SZ];
96
97 ++depth;
98 loop{
99 l r;
100 l j;
101
102 r=getdents64(parent_fd,dirents,DIRENTS_BUF_SZ);
103 if(ISERR(r)){
104 PERR("ERROR(%ld):getdents error\n",r);
105 exit(-1);
106 }
107
108 if(!r) break;
109
110 j=0;
111 loop{
112 struct dirent64 *d;
113
114 if(j>=r) break;
115
116 d=(struct dirent64*)(dirents+j);
117
118 dout(d);
119
120 if(d->type==DT_DIR&&!is_current(d->name)&&!is_parent(d->name)){
121 i dir_fd;
122
123 loop{
124 dir_fd=(i)openat(parent_fd,d->name,RDONLY|NONBLOCK);
125 if(dir_fd!=-EINTR) break;
126 }
127 if(ISERR(dir_fd))
128 PERR("ERROR(%d):unable to open subdir:%s\n",dir_fd,d->name);
129 else{
130 dir_parse(dir_fd);
131 loop{
132 l r1;
133
134 r1=close(dir_fd);
135 if(r1!=-EINTR) break;
136 }
137 }
138 }
139 j+=d->rec_len;
140 }
141 }
142 depth--;
143 }
144
145 void ulinux_start(l argc,ulinux_u8 **argv)
146 {
147 u8 _dprintf_buf[DPRINTF_BUF_SZ];
148 i root_fd;
149
150 dprintf_buf=&_dprintf_buf[0];
151
152 if(argc!=2){
153 PERR("ERROR:wrong number of command arguments(%d)\n",argc);
154 exit(-1);
155 }
156
157 /*root fd*/
158 loop{
159 root_fd=(i)open(argv[1],RDONLY|NONBLOCK);
160 if(root_fd!=-EINTR) break;
161 }
162 if(ISERR(root_fd)){
163 PERR("ERROR(%d):unable to open root dir:%s\n",root_fd,argv[1]);
164 exit(-1);
165 }
166
167 dir_parse(root_fd);
168 exit(0);
169 }
File ulinux/patterns/dir_parse/make added (mode: 100755) (index 0000000..cbe30be)
1 #!/bin/sh
2
3 clean_do(){
4 rm -f ../../../ulinux/arch
5 rm -f cpp_dir_parse.c dir_parse.o dir_parse \
6 cpp_mem.c mem.o \
7 cpp_vsprintf.c vsprintf.o \
8 args_env.o
9 exit 0
10 }
11
12 for opt do
13 case "$opt" in
14 clean) clean_do
15 ;;
16 *) echo "unknown option"; exit 1
17 ;;
18 esac
19 done
20
21 arch=$(uname -m | sed -e s/i.86/x86/ -e s/parisc64/parisc/ \
22 -e s/sun4u/sparc64/ -e s/arm.*/arm/ \
23 -e s/sa110/arm/ -e s/sh.*/sh/)
24
25 ln -fs archs/$arch ../../../ulinux/arch
26
27
28 cpp -Wall -Wextra -I../../.. ../../utils/mem.c -o cpp_mem.c
29 gcc -Wall -Wextra -std=gnu99 -O0 -c cpp_mem.c -o mem.o
30 cpp -Wall -Wextra -I../../.. ../../utils/ascii/string/vsprintf.c \
31 -o cpp_vsprintf.c
32 gcc -Wall -Wextra -std=gnu99 -O0 -c cpp_vsprintf.c -o vsprintf.o
33 as -I../../.. ../../args_env.s -o args_env.o
34 cpp -Wall -Wextra -I../../.. dir_parse.c -o cpp_dir_parse.c
35 gcc -Wall -Wextra -O0 -c cpp_dir_parse.c -o dir_parse.o
36 ld -O -nostdlib -Bstatic --strip-all dir_parse.o args_env.o mem.o vsprintf.o \
37 $(gcc -print-libgcc-file-name) --output dir_parse
File ulinux/patterns/epoll_signalfd/epoll_signalfd.c added (mode: 100644) (index 0000000..8e66845)
1 #include <stdarg.h>
2
3 #include <ulinux/compiler_types.h>
4 #include <ulinux/compiler_misc.h>
5 #include <ulinux/sysc.h>
6 #include <ulinux/types.h>
7 #include <ulinux/epoll.h>
8 #include <ulinux/file.h>
9 #include <ulinux/error.h>
10 #include <ulinux/signal/signal.h>
11
12 #include <ulinux/utils/mem.h>
13 #include <ulinux/utils/ascii/string/string.h>
14 #include <ulinux/utils/ascii/string/vsprintf.h>
15
16 /* ulinux namespace */
17 #define EINTR ULINUX_EINTR
18 #define EAGAIN ULINUX_EAGAIN
19 #define si ulinux_si
20 #define sl ulinux_sl
21 #define u8 ulinux_u8
22 #define u64 ulinux_u64
23 #define exit(code) ulinux_sysc(exit_group,1,code)
24 #define rt_sigprocmask(a,b,c,d) ulinux_sysc(rt_sigprocmask,4,a,b,c,d)
25 #define SIG_BLOCK ULINUX_SIG_BLOCK
26 #define SIGUSR1 ULINUX_SIGUSR1
27 #define SIGUSR2 ULINUX_SIGUSR2
28 #define ISERR ULINUX_ISERR
29 #define signalfd4(a,b,c,d) ulinux_sysc(signalfd4,4,a,b,c,d)
30 #define SFD_NONBLOCK ULINUX_SFD_NONBLOCK
31 #define epoll_create1(a) ulinux_sysc(epoll_create1,1,a)
32 #define epoll_event ulinux_epoll_event
33 #define memset(a,b,c) ulinux_memset((ulinux_u8*)a,b,c)
34 #define EPOLLET ULINUX_EPOLLET
35 #define EPOLLIN ULINUX_EPOLLIN
36 #define epoll_ctl(a,b,c,d) ulinux_sysc(epoll_ctl,4,a,b,c,d)
37 #define EPOLL_CTL_ADD ULINUX_EPOLL_CTL_ADD
38 #define epoll_wait(a,b,c,d) ulinux_sysc(epoll_wait,4,a,b,c,d)
39 #define signalfd_siginfo ulinux_signalfd_siginfo
40 #define read(a,b,c) ulinux_sysc(read,3,a,b,c)
41 #define getpid() ulinux_sysc(getpid,0)
42
43 /* convenience macros */
44 #define BUFSIZ 8192
45 static u8 dprint_buf[BUFSIZ];
46 #define POUT(fmt,...) ulinux_dprintf(1, &dprint_buf[0], BUFSIZ - 1, fmt, ##__VA_ARGS__)
47 #define SIGBIT(sig) (1 << (sig - 1))
48 #define EPOLL_EVENTS_N 10
49 #define loop for(;;)
50
51 void _start(void)
52 {
53 sl pid;
54 u64 mask;
55 sl r;
56 si sigs_fd;
57 si epfd;
58 struct epoll_event evts[EPOLL_EVENTS_N];
59 u8 *illegal;
60
61 dprint_buf[BUFSIZ - 1] = 0; /* secure a 0 terminating char */
62 illegal = 0;
63
64 pid = getpid();
65 POUT("PID=%ld\n", pid);
66
67 mask = ~0;
68 r = rt_sigprocmask(SIG_BLOCK, &mask, 0, sizeof(mask));
69 if (ISERR(r)) {
70 POUT("\nunable to block 'all' signals for synchronous delivery\n");
71 exit(-1);
72 }
73
74 mask = SIGBIT(SIGUSR1) | SIGBIT(SIGUSR2);
75 sigs_fd = (si)signalfd4(-1, &mask, sizeof(mask), SFD_NONBLOCK);
76 if (ISERR(sigs_fd)) {
77 POUT("\nunable to create the signalfd\n");
78 exit(-2);
79 }
80
81 epfd = (si)epoll_create1(0);
82 if (ISERR(epfd)) {
83 POUT("\nunable to create the epoll fd\n");
84 exit(-3);
85 }
86
87 memset(evts, 0, sizeof(evts));
88 evts[0].events = EPOLLET | EPOLLIN;
89 evts[0].data.fd = sigs_fd;
90 r = epoll_ctl(epfd, EPOLL_CTL_ADD, sigs_fd, &evts[0]);
91 if (ISERR(r)) {
92 POUT("\nunable to add the signalfd to the epoll fd\n");
93 exit(-4);
94 }
95
96 loop {
97 sl j;
98
99 loop {
100 memset(evts, 0, sizeof(evts));
101 r = epoll_wait(epfd, evts, EPOLL_EVENTS_N, -1);
102 if (r != -EINTR)
103 break;
104
105 POUT("\nepoll_wait was interruped by a signal, but got nothing in the signalfd: MUST BE SIGSTOP/SIGCONT\n");
106 }
107 if (ISERR(r)) {
108 POUT("epoll_wait error\n");
109 exit(-6);
110 }
111
112 j = 0;
113 loop {
114 if (j == r)
115 break;
116 if (evts[j].data.fd == sigs_fd) {
117 if ((evts[j].events & EPOLLIN) != 0) {
118 struct signalfd_siginfo info;
119
120 loop {
121 memset(&info, 0, sizeof(info));
122 loop {/* reads are atomic or err, aka no short reads */
123 r = read(sigs_fd, &info, sizeof(info));
124 if (r != -EINTR);
125 break;
126 }
127 if ((r != -EAGAIN) && (ISERR(r))) {
128 POUT("\nsomething went wront while getting signal information\n");
129 exit(-7);
130 }
131
132 switch (info.ssi_signo) {
133 case SIGUSR1:
134 POUT("\nSIGUSR1:generating illegal access\n");
135 *illegal = 0;
136 break;
137 case SIGUSR2:
138 POUT("\nSIGUSR2\n");
139 break;
140 }
141 }
142 } else {
143 POUT("\ngot an unwanted event\n");
144 exit(-8);
145 }
146 }
147 ++j;
148 }
149 }
150 }
File ulinux/patterns/epoll_signalfd/make added (mode: 100755) (index 0000000..d4f9083)
1 #!/bin/sh
2
3 set -e
4
5 ulinux_location=$(readlink -e ../../..)
6 build_dir=$(readlink -e .)
7 echo "ulinux_location=$ulinux_location"
8 echo "build_dir=$build_dir"
9
10 if test "$1" = "clean"; then
11 echo cleaning build products... in $build_dir
12
13 rm -f $build_dir/ulinux/arch
14 rmdir $build_dir/ulinux || true
15
16 rm -f $build_dir/mem.o
17 rm -f $build_dir/vsprintf.o
18 rm -f $build_dir/epoll_signalfd.o
19 rm -f $build_dir/epoll_signalfd
20 exit 0;
21 fi
22
23 leaner_gcc_opts='-fno-stack-protector -fno-asynchronous-unwind-tables -fno-dwarf2-cfi-asm'
24 cc="gcc -pipe -O0 -I. -I$ulinux_location -static-libgcc $leaner_gcc_opts"
25 ld="ld -O -nostdlib -Bstatic --strip-all $(gcc -print-libgcc-file-name)"
26 echo "cc=$cc"
27 echo "ld=$ld"
28
29 mkdir -p $build_dir/ulinux
30 ln -sTf $ulinux_location/ulinux/archs/x86_64 $build_dir/ulinux/arch
31
32 $cc -c $ulinux_location/ulinux/utils/mem.c -o $build_dir/mem.o
33 $cc -c $ulinux_location/ulinux/utils/ascii/string/vsprintf.c \
34 -o $build_dir/vsprintf.o
35 $cc -c $build_dir/epoll_signalfd.c -o $build_dir/epoll_signalfd.o
36 $ld $build_dir/mem.o $build_dir/vsprintf.o $build_dir/epoll_signalfd.o \
37 -o $build_dir/epoll_signalfd
File ulinux/patterns/epoll_timerfd/epoll_timerfd.c added (mode: 100644) (index 0000000..a99ebcb)
1 /*
2 * XXX: if you are a heavy user of time related calls, you should use vdso
3 * calls instead of syscalls. That depends on the arch.
4 */
5 #include <stdarg.h>
6
7 #include <ulinux/compiler_types.h>
8 #include <ulinux/compiler_misc.h>
9 #include <ulinux/sysc.h>
10 #include <ulinux/types.h>
11 #include <ulinux/epoll.h>
12 #include <ulinux/file.h>
13 #include <ulinux/error.h>
14 #include <ulinux/time.h>
15
16 #include <ulinux/utils/mem.h>
17 #include <ulinux/utils/ascii/string/string.h>
18 #include <ulinux/utils/ascii/string/vsprintf.h>
19
20 /* ulinux namespace */
21 #define EINTR ULINUX_EINTR
22 #define EAGAIN ULINUX_EAGAIN
23 #define si ulinux_si
24 #define sl ulinux_sl
25 #define u8 ulinux_u8
26 #define u64 ulinux_u64
27 /* kill process, aka thread group */
28 #define exit(code) ulinux_sysc(exit_group,1,code)
29 #define ISERR ULINUX_ISERR
30 #define CLOCK_MONOTONIC ULINUX_CLOCK_MONOTONIC
31 #define clock_gettime(a,b) ulinux_sysc(clock_gettime,2,a,b)
32 #define TFD_NONBLOCK ULINUX_TFD_NONBLOCK
33 #define TFD_TIMER_ABSTIME ULINUX_TFD_TIMER_ABSTIME
34 #define itimerspec ulinux_itimerspec
35 #define timerfd_create(a,b) ulinux_sysc(timerfd_create,2,a,b)
36 #define timerfd_settime(a,b,c,d) ulinux_sysc(timerfd_settime,4,a,b,c,d)
37 #define epoll_create1(a) ulinux_sysc(epoll_create1,1,a)
38 #define epoll_event ulinux_epoll_event
39 #define memset(a,b,c) ulinux_memset((ulinux_u8*)a,b,c)
40 #define EPOLLIN ULINUX_EPOLLIN
41 #define epoll_ctl(a,b,c,d) ulinux_sysc(epoll_ctl,4,a,b,c,d)
42 #define EPOLL_CTL_ADD ULINUX_EPOLL_CTL_ADD
43 /* common to x86_64 and aarch64 */
44 #define epoll_pwait(a,b,c,d,e) ulinux_sysc(epoll_pwait,5,a,b,c,d,e)
45 #define read(a,b,c) ulinux_sysc(read,3,a,b,c)
46
47 /* convenience macros */
48 #define BUFSIZ 8192
49 static u8 dprint_buf[BUFSIZ];
50 #define POUT(fmt,...) ulinux_dprintf(1,&dprint_buf[0],BUFSIZ-1,fmt,##__VA_ARGS__)
51 #define EPOLL_EVENTS_N 10
52 #define loop for(;;)
53
54 #define INITIAL_EXPIRATION_SECS 8
55
56 void _start(void)
57 {
58 sl r;
59 si timerfd;
60 struct itimerspec itimerspec;
61 si epfd;
62 struct epoll_event evts[EPOLL_EVENTS_N];
63 sl evt;
64
65 dprint_buf[BUFSIZ - 1] = 0; /* secure a 0 terminating char */
66
67 timerfd = (si)timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);
68 if (ISERR(timerfd)) {
69 POUT("unable to create the timer fd (%d)\n", timerfd);
70 exit(1);
71 }
72
73 memset(&itimerspec, 0, sizeof(itimerspec));
74
75 /*--------------------------------------------------------------------*/
76
77 r = clock_gettime(CLOCK_MONOTONIC, &itimerspec.value);
78 if (ISERR(r)) {
79 POUT("error while getting the current monotonic clock time (%ld)\n", r);
80 exit(2);
81 }
82 POUT("current monotonic clock is %ld secs and %ld nsecs\n", itimerspec.value.sec, itimerspec.value.nsec);
83
84 /*--------------------------------------------------------------------*/
85
86 /* initial expiration in the futur of current monotonic clock */
87 itimerspec.value.sec += INITIAL_EXPIRATION_SECS;
88 itimerspec.value.nsec = 0;
89
90 /* we are looking for an absolute initial expiration */
91 r = timerfd_settime(timerfd, TFD_TIMER_ABSTIME, &itimerspec, 0);
92 if (ISERR(r)) {
93 POUT("unable to arm the timer\n");
94 exit(3);
95 }
96
97 epfd = (si)epoll_create1(0);
98 if (ISERR(epfd)) {
99 POUT("unable to create the epoll fd\n");
100 exit(4);
101 }
102
103 memset(evts, 0, sizeof(evts));
104 evts[0].events = EPOLLIN; /* could be EPOLLET too */
105 evts[0].data.fd = timerfd;
106 r = epoll_ctl(epfd, EPOLL_CTL_ADD, timerfd, &evts[0]);
107 if (ISERR(r)) {
108 POUT("unable to add the timer fd to the epoll fd (%ld)\n", r);
109 exit(5);
110 }
111
112 loop {
113 memset(evts, 0, sizeof(evts));
114 r = epoll_pwait(epfd, evts, EPOLL_EVENTS_N, -1, 0);
115 if (r != -EINTR)
116 break;
117
118 POUT("epoll_pwait was interruped by a signal (we did not set any timeout), restarting\n");
119 }
120 if (ISERR(r)) {
121 POUT("epoll_wait error (%ld)\n", r);
122 exit(6);
123 }
124
125 evt = 0;
126 loop {
127 if (evt == r)
128 break;
129
130 if (evts[evt].data.fd == timerfd) {
131 if ((evts[evt].events & EPOLLIN) != 0) {
132 u64 expirations_n = 0; /* the count of expirations of our timer */
133
134 loop {/* reads are atomic or err, aka no short reads */
135 r = read(timerfd, &expirations_n, sizeof(u64));
136 if (r != -EINTR);
137 break;
138 }
139
140 if (r == -EAGAIN) { /* for a non blocking fd, means we read it */
141 POUT("something is wrong: we got notified of some timer expirations, but there is no count of expirations!\n");
142 exit(7);
143 }
144 if (ISERR(r)) {
145 POUT("something went wrong while reading the count of expirations (%ld)\n", r);
146 exit(8);
147 }
148 POUT("count of expirations=%lu\n", expirations_n);
149 } else {
150 POUT("got an unwanted event on the timer fd\n");
151 exit(9);
152 }
153 }
154 ++evt; /* next epoll event */
155 }
156
157 /*--------------------------------------------------------------------*/
158
159 memset(&itimerspec, 0, sizeof(itimerspec));
160 r = clock_gettime(CLOCK_MONOTONIC, &itimerspec.value);
161 if (ISERR(r)) {
162 POUT("error while getting the current monotonic clock time at exit time(%ld)\n", r);
163 exit(10);
164 }
165 POUT("monotonic clock at exit is %ld secs and %ld nsecs\n", itimerspec.value.sec, itimerspec.value.nsec);
166 exit(0);
167 }
File ulinux/patterns/epoll_timerfd/make added (mode: 100755) (index 0000000..24d26a3)
1 #!/bin/sh
2
3 set -e
4
5 ulinux_location=$(readlink -e ../../..)
6 build_dir=$(readlink -e .)
7 echo "ulinux_location=$ulinux_location"
8 echo "build_dir=$build_dir"
9
10 if test "$1" = "clean"; then
11 echo cleaning build products... in $build_dir
12
13 rm -f $build_dir/ulinux/arch
14 rmdir $build_dir/ulinux || true
15
16 rm -f $build_dir/mem.o
17 rm -f $build_dir/vsprintf.o
18 rm -f $build_dir/epoll_timerfd.o
19 rm -f $build_dir/epoll_timerfd
20 exit 0;
21 fi
22
23 leaner_gcc_opts='-fno-stack-protector -fno-asynchronous-unwind-tables -fno-dwarf2-cfi-asm'
24 cc="gcc -pipe -O0 -I. -I$ulinux_location -static-libgcc $leaner_gcc_opts"
25 ld="ld -O -nostdlib -Bstatic --strip-all $(gcc -print-libgcc-file-name)"
26 echo "cc=$cc"
27 echo "ld=$ld"
28
29 mkdir -p $build_dir/ulinux
30 ln -sTf $ulinux_location/ulinux/archs/x86_64 $build_dir/ulinux/arch
31
32 $cc -c $ulinux_location/ulinux/utils/mem.c -o $build_dir/mem.o
33 $cc -c $ulinux_location/ulinux/utils/ascii/string/vsprintf.c \
34 -o $build_dir/vsprintf.o
35 $cc -c $build_dir/epoll_timerfd.c -o $build_dir/epoll_timerfd.o
36 $ld $build_dir/mem.o $build_dir/vsprintf.o $build_dir/epoll_timerfd.o \
37 -o $build_dir/epoll_timerfd
File ulinux/patterns/futex/futex.c added (mode: 100644) (index 0000000..de974d0)
1 #include <stdarg.h>
2
3 #include <ulinux/compiler_types.h>
4 #include <ulinux/sysc.h>
5
6 #include <ulinux/types.h>
7 #include <ulinux/sched.h>
8 #include <ulinux/mmap.h>
9
10 #include <ulinux/utils/ascii/string/vsprintf.h>
11
12 /* ulinux namespace */
13 #define EINTR ULINUX_EINTR
14 #define EAGAIN ULINUX_EAGAIN
15 #define si ulinux_si
16 #define sl ulinux_sl
17 #define u8 ulinux_u8
18 #define exit(a) ulinux_sysc(exit,1,a)
19 #define mmap(a,b,c,d,e,f) ulinux_sysc(mmap,6,a,b,c,d,e,f)
20 #define RD ULINUX_PROT_READ
21 #define WR ULINUX_PROT_WRITE
22 #define PRIVATE ULINUX_MAP_PRIVATE
23 #define ANONYMOUS ULINUX_MAP_ANONYMOUS
24 #define GROWSDOWN ULINUX_MAP_GROWSDOWN
25 #define clone(a,b,c,d,e) ulinux_sysc(clone,5,a,b,c,d,e)
26 #define THREAD ULINUX_CLONE_THREAD
27 #define SIGHAND ULINUX_CLONE_SIGHAND
28 #define VM ULINUX_CLONE_VM
29 #define FILES ULINUX_CLONE_FILES
30 #define FS ULINUX_CLONE_FS
31 #define IO ULINUX_CLONE_IO
32 #define SYSVSEM ULINUX_CLONE_SYSVSEM
33 #define PAGE_SZ ULINUX_PAGE_SZ
34
35 #define loop for(;;)
36 #define STACK_SZ 512 * PAGE_SZ
37
38 #define BUFSIZ 8192
39 static u8 dprint_buf[BUFSIZ];
40 #define POUT(fmt,...) ulinux_dprintf(1, &dprint_buf[0], BUFSIZ - 1, fmt, ##__VA_ARGS__)
41
42 /*
43 * XXX: be carefull that this c++ cr*p which is now gcc don't optimize
44 * out/weirdly the thread entry function
45 */
46 static void thread_entry(void)
47 {
48 POUT("CHILD\n");
49 loop;
50 exit(0);
51 }
52
53 void _start(void)
54 {
55 sl r;
56 sl stack_map_bottom;
57 sl stack_map_top; /* 1 byte out of map */
58 sl stack_map_top_down_aligned;
59
60 dprint_buf[BUFSIZ - 1] = 0; /* secure a 0 terminating char */
61
62 stack_map_bottom = mmap(0, STACK_SZ, RD | WR, PRIVATE | ANONYMOUS
63 | GROWSDOWN, -1, 0);
64 stack_map_top = stack_map_bottom + STACK_SZ;
65
66 POUT("THREAD STACK MAP:0x%p-0x%p STACK_MAP_SZ=0x%x PAGE_SZ=0x%x\n",
67 stack_map_bottom, stack_map_top, STACK_SZ, PAGE_SZ);
68
69 /*
70 * we align DOWN on a 16 bytes boundary. Fits aarch64 and x86_64
71 * ("function stack frames" should be too)
72 */
73 if ((stack_map_top & 0xf) != 0)
74 stack_map_top_down_aligned = stack_map_top & (~0xf);
75 else
76 stack_map_top_down_aligned = (stack_map_top - 1) & (~0xf);
77 POUT("16 bytes aligned thread stack at 0x%p\n",
78 stack_map_top_down_aligned);
79
80 /*
81 * XXX: carefull, the order of the syscall args varies from arch to
82 * arch. If you create a process (namely without the VM flag), you
83 * don't need to provide a stack, just put 0 (copy-on-write)
84 */
85 r = clone(THREAD | SIGHAND | VM | FILES | FS | IO | SYSVSEM,
86 stack_map_top_down_aligned, 0, 0, 0);
87 if (r == 0)
88 thread_entry();
89 POUT("PARENT\n");
90 loop;
91 exit(0);
92 }
File ulinux/patterns/futex/make added (mode: 100755) (index 0000000..7afc143)
1 #!/bin/sh
2
3 set -e
4
5 ulinux_location=$(readlink -e ../../..)
6 build_dir=$(readlink -e .)
7 echo "ulinux_location=$ulinux_location"
8 echo "build_dir=$build_dir"
9
10 if test "$1" = "clean"; then
11 echo cleaning build products... in $build_dir
12
13 rm -f $build_dir/ulinux/arch
14 rmdir $build_dir/ulinux || true
15
16 rm -f $build_dir/mem.o
17 rm -f $build_dir/vsprintf.o
18 rm -f $build_dir/futex.o
19 rm -f $build_dir/futex
20 exit 0;
21 fi
22
23 leaner_gcc_opts='-fno-stack-protector -fno-asynchronous-unwind-tables -fno-dwarf2-cfi-asm'
24 cc="gcc -pipe -O2 -I. -I$ulinux_location -static-libgcc $leaner_gcc_opts"
25 ld="ld -O -nostdlib -Bstatic --strip-all $(gcc -print-libgcc-file-name)"
26 echo "cc=$cc"
27 echo "ld=$ld"
28
29 mkdir -p $build_dir/ulinux
30 # arch is hardcoded
31 ln -sTf $ulinux_location/ulinux/archs/x86_64 $build_dir/ulinux/arch
32
33 $cc -c $ulinux_location/ulinux/utils/mem.c -o $build_dir/mem.o
34 $cc -c $ulinux_location/ulinux/utils/ascii/string/vsprintf.c \
35 -o $build_dir/vsprintf.o
36 $cc -c $build_dir/futex.c -o $build_dir/futex.o
37 $ld $build_dir/mem.o $build_dir/vsprintf.o $build_dir/futex.o \
38 -o $build_dir/futex
File ulinux/patterns/glob/glob.c added (mode: 100644) (index 0000000..1af3acd)
1 #include <stdarg.h>
2 #include <ulinux/compiler_types.h>
3 #include <ulinux/types.h>
4 #include <ulinux/sysc.h>
5 #include <ulinux/args_env.h>
6
7 #include <ulinux/utils/ascii/string/vsprintf.h>
8 #include <ulinux/utils/ascii/match/match.h>
9
10 struct test{
11 void *string;
12 void *pattern;
13 ulinux_u8 flags;
14 };
15
16 //******************************************************************************
17 //Stolen glibc tests for the posix locale (ascii).
18 //Upgrade to a GNU Lesser GPLv3 protection.
19 //Copyrights, Sylvain BERTRAND (sylvain.bertrand@gmail.com).
20 //******************************************************************************
21 #define NOMATCH 0x01
22 #define EXTMATCH 0x02
23 struct test tests[]={
24 {"!#%+,-./01234567889","!#%+,-./01234567889",0},
25 {":;=@ABCDEFGHIJKLMNO",":;=@ABCDEFGHIJKLMNO",0},
26 {"PQRSTUVWXYZ]abcdefg","PQRSTUVWXYZ]abcdefg",0},
27 {"hijklmnopqrstuvwxyz","hijklmnopqrstuvwxyz",0},
28 {"^_{}~","^_{}~",0},
29 {"\"$&'()","\\\"\\$\\&\\'\\(\\)",0},
30 {"*?[\\`|","\\*\\?\\[\\\\\\`\\|",0},
31 {"<>","\\<\\>",0},
32 {"?*[","[?*[][?*[][?*[]",0},
33 {"a/b","?/b",0},
34 {"a/b","a?b",0},
35 {"a/b","a/?",0},
36 {"aa/b","?/b",NOMATCH},
37 {"aa/b","a?b",NOMATCH},
38 {"a/bb","a/?",NOMATCH},
39 {"abc","[abc]",NOMATCH},
40 {"x","[abc]",NOMATCH},
41 {"a","[abc]",0},
42 {"[","[[abc]",0},
43 {"a","[][abc]",0},
44 {"a]","[]a]]",0},
45 {"xyz","[!abc]",NOMATCH},
46 {"x","[!abc]",0},
47 {"a","[!abc]",NOMATCH},
48 {"]","[][abc]",0},
49 {"abc]","[][abc]",NOMATCH},
50 {"[]abc","[][]abc",NOMATCH},
51 {"]","[!]]",NOMATCH},
52 {"aa]","[!]a]",NOMATCH},
53 {"]","[!a]",0},
54 {"]]","[!a]]",0},
55 {"a","[[:alnum:]]",0},
56 {"a","[![:alnum:]]",NOMATCH},
57 {"-","[[:alnum:]]",NOMATCH},
58 {"a]a","[[:alnum:]]a",NOMATCH},
59 {"-","[[:alnum:]-]",0},
60 {"aa","[[:alnum:]]a",0},
61 {"-","[![:alnum:]]",0},
62 {"]","[!][:alnum:]]",NOMATCH},
63 {"[","[![:alnum:][]",NOMATCH},
64 {"a","[[:alnum:]]",0},
65 {"b","[[:alnum:]]",0},
66 {"c","[[:alnum:]]",0},
67 {"d","[[:alnum:]]",0},
68 {"e","[[:alnum:]]",0},
69 {"f","[[:alnum:]]",0},
70 {"g","[[:alnum:]]",0},
71 {"h","[[:alnum:]]",0},
72 {"i","[[:alnum:]]",0},
73 {"j","[[:alnum:]]",0},
74 {"k","[[:alnum:]]",0},
75 {"l","[[:alnum:]]",0},
76 {"m","[[:alnum:]]",0},
77 {"n","[[:alnum:]]",0},
78 {"o","[[:alnum:]]",0},
79 {"p","[[:alnum:]]",0},
80 {"q","[[:alnum:]]",0},
81 {"r","[[:alnum:]]",0},
82 {"s","[[:alnum:]]",0},
83 {"t","[[:alnum:]]",0},
84 {"u","[[:alnum:]]",0},
85 {"v","[[:alnum:]]",0},
86 {"w","[[:alnum:]]",0},
87 {"x","[[:alnum:]]",0},
88 {"y","[[:alnum:]]",0},
89 {"z","[[:alnum:]]",0},
90 {"A","[[:alnum:]]",0},
91 {"B","[[:alnum:]]",0},
92 {"C","[[:alnum:]]",0},
93 {"D","[[:alnum:]]",0},
94 {"E","[[:alnum:]]",0},
95 {"F","[[:alnum:]]",0},
96 {"G","[[:alnum:]]",0},
97 {"H","[[:alnum:]]",0},
98 {"I","[[:alnum:]]",0},
99 {"J","[[:alnum:]]",0},
100 {"K","[[:alnum:]]",0},
101 {"L","[[:alnum:]]",0},
102 {"M","[[:alnum:]]",0},
103 {"N","[[:alnum:]]",0},
104 {"O","[[:alnum:]]",0},
105 {"P","[[:alnum:]]",0},
106 {"Q","[[:alnum:]]",0},
107 {"R","[[:alnum:]]",0},
108 {"S","[[:alnum:]]",0},
109 {"T","[[:alnum:]]",0},
110 {"U","[[:alnum:]]",0},
111 {"V","[[:alnum:]]",0},
112 {"W","[[:alnum:]]",0},
113 {"X","[[:alnum:]]",0},
114 {"Y","[[:alnum:]]",0},
115 {"Z","[[:alnum:]]",0},
116 {"0","[[:alnum:]]",0},
117 {"1","[[:alnum:]]",0},
118 {"2","[[:alnum:]]",0},
119 {"3","[[:alnum:]]",0},
120 {"4","[[:alnum:]]",0},
121 {"5","[[:alnum:]]",0},
122 {"6","[[:alnum:]]",0},
123 {"7","[[:alnum:]]",0},
124 {"8","[[:alnum:]]",0},
125 {"9","[[:alnum:]]",0},
126 {"!","[[:alnum:]]",NOMATCH},
127 {"#","[[:alnum:]]",NOMATCH},
128 {"%","[[:alnum:]]",NOMATCH},
129 {"+","[[:alnum:]]",NOMATCH},
130 {",","[[:alnum:]]",NOMATCH},
131 {"-","[[:alnum:]]",NOMATCH},
132 {".","[[:alnum:]]",NOMATCH},
133 {"/","[[:alnum:]]",NOMATCH},
134 {":","[[:alnum:]]",NOMATCH},
135 {";","[[:alnum:]]",NOMATCH},
136 {"=","[[:alnum:]]",NOMATCH},
137 {"@","[[:alnum:]]",NOMATCH},
138 {"[","[[:alnum:]]",NOMATCH},
139 {"\\","[[:alnum:]]",NOMATCH},
140 {"]","[[:alnum:]]",NOMATCH},
141 {"^","[[:alnum:]]",NOMATCH},
142 {"_","[[:alnum:]]",NOMATCH},
143 {"{","[[:alnum:]]",NOMATCH},
144 {"}","[[:alnum:]]",NOMATCH},
145 {"~","[[:alnum:]]",NOMATCH},
146 {"\"","[[:alnum:]]",NOMATCH},
147 {"$","[[:alnum:]]",NOMATCH},
148 {"&","[[:alnum:]]",NOMATCH},
149 {"'","[[:alnum:]]",NOMATCH},
150 {"(","[[:alnum:]]",NOMATCH},
151 {")","[[:alnum:]]",NOMATCH},
152 {"*","[[:alnum:]]",NOMATCH},
153 {"?","[[:alnum:]]",NOMATCH},
154 {"`","[[:alnum:]]",NOMATCH},
155 {"|","[[:alnum:]]",NOMATCH},
156 {"<","[[:alnum:]]",NOMATCH},
157 {">","[[:alnum:]]",NOMATCH},
158 {"\t","[[:cntrl:]]",0},
159 {"t","[[:cntrl:]]",NOMATCH},
160 {"t","[[:lower:]]",0},
161 {"\t","[[:lower:]]",NOMATCH},
162 {"T","[[:lower:]]",NOMATCH},
163 {"\t","[[:space:]]",0},
164 {"t","[[:space:]]",NOMATCH},
165 {"t","[[:alpha:]]",0},
166 {"\t","[[:alpha:]]",NOMATCH},
167 {"0","[[:digit:]]",0},
168 {"\t","[[:digit:]]",NOMATCH},
169 {"t","[[:digit:]]",NOMATCH},
170 {"\t","[[:print:]]",NOMATCH},
171 {"t","[[:print:]]",0},
172 {"T","[[:upper:]]",0},
173 {"\t","[[:upper:]]",NOMATCH},
174 {"t","[[:upper:]]",NOMATCH},
175 {"\t","[[:blank:]]",0},
176 {"t","[[:blank:]]",NOMATCH},
177 {"\t","[[:graph:]]",NOMATCH},
178 {"t","[[:graph:]]",0},
179 {".","[[:punct:]]",0},
180 {"t","[[:punct:]]",NOMATCH},
181 {"\t","[[:punct:]]",NOMATCH},
182 {"0","[[:xdigit:]]",0},
183 {"\t","[[:xdigit:]]",NOMATCH},
184 {"a","[[:xdigit:]]",0},
185 {"A","[[:xdigit:]]",0},
186 {"t","[[:xdigit:]]",NOMATCH},
187 {"a","[[alpha]]",NOMATCH},
188 {"a","[[alpha:]]",NOMATCH},
189 {"a]","[[alpha]]",0},
190 {"a]","[[alpha:]]",0},
191 {"a","[[:alpha:][:digit:]]",0},
192 {"a","[[:digit:][:alpha:]]",0},
193 {"a","[a-c]",0},
194 {"a","[b-c]",NOMATCH},
195 {"d","[b-c]",NOMATCH},
196 {"B","[a-c]",NOMATCH},
197 {"b","[A-C]",NOMATCH},
198 {"","[a-c]",NOMATCH},
199 {"as","[a-ca-z]",NOMATCH},
200 {"a","[a-c0-9]",0},
201 {"d","[a-c0-9]",NOMATCH},
202 {"B","[a-c0-9]",NOMATCH},
203 {"-","[-a]",0},
204 {"a","[-b]",NOMATCH},
205 {"-","[!-a]",NOMATCH},
206 {"a","[!-b]",0},
207 {"-","[a-c-0-9]",0},
208 {"b","[a-c-0-9]",0},
209 {"a:","a[0-9-a]",NOMATCH},
210 {"a:","a[09-a]",0},
211 {"","*",0},
212 {"asd/sdf","*",0},
213 {"as","[a-c][a-z]",0},
214 {"as","??",0},
215 {"asd/sdf","as*df",0},
216 {"asd/sdf","as*",0},
217 {"asd/sdf","*df",0},
218 {"asd/sdf","as*dg",NOMATCH},
219 {"asdf","as*df",0},
220 {"asdf","as*df?",NOMATCH},
221 {"asdf","as*??",0},
222 {"asdf","a*???",0},
223 {"asdf","*????",0},
224 {"asdf","????*",0},
225 {"asdf","??*?",0},
226 {"/","/", 0},
227 {"/","/*",0},
228 {"/","*/",0},
229 {"/","/?",NOMATCH},
230 {"/","?/",NOMATCH},
231 {"/","?",0},
232 {".","?",0},
233 {"/.","??",0},
234 {"/","[!a-c]",0},
235 {".","[!a-c]",0},
236 {"/$","\\/\\$",0},
237 {"/[","\\/\\[",0},
238 {"/[","\\/[",0},
239 {"/[]","\\/\\[]",0},
240 {"foobar","foo*[abc]z",NOMATCH},
241 {"foobaz","foo*[abc][xyz]",0},
242 {"foobaz","foo?*[abc][xyz]",0},
243 {"foobaz","foo?*[abc][x/yz]",0},
244 {"az","[a-]z",0},
245 {"bz","[ab-]z",0},
246 {"cz","[ab-]z",NOMATCH},
247 {"-z","[ab-]z",0},
248 {"az","[-a]z",0},
249 {"bz","[-ab]z",0},
250 {"cz","[-ab]z",NOMATCH},
251 {"-z","[-ab]z",0},
252 {"\\","[\\\\-a]",0},
253 {"_","[\\\\-a]",0},
254 {"a","[\\\\-a]",0},
255 {"-","[\\\\-a]",NOMATCH},
256 {"\\","[\\]-a]",NOMATCH},
257 {"_","[\\]-a]",0},
258 {"a","[\\]-a]",0},
259 {"]","[\\]-a]",0},
260 {"-","[\\]-a]",NOMATCH},
261 {"\\","[!\\\\-a]",NOMATCH},
262 {"_","[!\\\\-a]",NOMATCH},
263 {"a","[!\\\\-a]",NOMATCH},
264 {"-","[!\\\\-a]",0},
265 {"!","[\\!-]",0},
266 {"-","[\\!-]",0},
267 {"\\","[\\!-]",NOMATCH},
268 {"Z","[Z-\\\\]",0},
269 {"[","[Z-\\\\]",0},
270 {"\\","[Z-\\\\]",0},
271 {"-","[Z-\\\\]",NOMATCH},
272 {"Z","[Z-\\]]",0},
273 {"[","[Z-\\]]",0},
274 {"\\","[Z-\\]]",0},
275 {"]","[Z-\\]]",0},
276 {"-","[Z-\\]]",NOMATCH},
277 {"abcd","?@(a|b)*@(c)d",EXTMATCH},
278 {"12","[1-9]*([0-9])",EXTMATCH},
279 {"12abc","[1-9]*([0-9])",NOMATCH|EXTMATCH},
280 {"1","[1-9]*([0-9])",EXTMATCH},
281 {"07","+([0-7])",EXTMATCH},
282 {"0377","+([0-7])",EXTMATCH},
283 {"09","+([0-7])",NOMATCH|EXTMATCH},
284 {"paragraph","para@(chute|graph)",EXTMATCH},
285 {"paramour","para@(chute|graph)",NOMATCH|EXTMATCH},
286 {"para991","para?([345]|99)1",EXTMATCH},
287 {"para381","para?([345]|99)1",NOMATCH|EXTMATCH},
288 {"paragraph","para*([0-9])",NOMATCH|EXTMATCH},
289 {"para","para*([0-9])",EXTMATCH},
290 {"para13829383746592","para*([0-9])",EXTMATCH},
291 {"paragraph","para+([0-9])",NOMATCH|EXTMATCH},
292 {"para","para+([0-9])",NOMATCH|EXTMATCH},
293 {"para987346523","para+([0-9])",EXTMATCH},
294 {"paragraph","para!(*.[0-9])",EXTMATCH},
295 {"para.38","para!(*.[0-9])",EXTMATCH},
296 {"para.graph","para!(*.[0-9])",EXTMATCH},
297 {"para39","para!(*.[0-9])",EXTMATCH},
298 {"","*(0|1|3|5|7|9)",EXTMATCH},
299 {"137577991","*(0|1|3|5|7|9)",EXTMATCH},
300 {"2468","*(0|1|3|5|7|9)",NOMATCH|EXTMATCH},
301 {"1358","*(0|1|3|5|7|9)",NOMATCH|EXTMATCH},
302 {"file.c","*.c?(c)",EXTMATCH},
303 {"file.C","*.c?(c)",NOMATCH|EXTMATCH},
304 {"file.cc","*.c?(c)",EXTMATCH},
305 {"file.ccc","*.c?(c)",NOMATCH|EXTMATCH},
306 {"parse.y","!(*.c|*.h|Makefile.in|config*|README)",EXTMATCH},
307 {"shell.c","!(*.c|*.h|Makefile.in|config*|README)",NOMATCH|EXTMATCH},
308 {"Makefile","!(*.c|*.h|Makefile.in|config*|README)",EXTMATCH},
309 {"abcfefg","ab**(e|f)",EXTMATCH},
310 {"abcfefg","ab**(e|f)g",EXTMATCH},
311 {"ab","ab*+(e|f)",NOMATCH|EXTMATCH},
312 {"abef","ab***ef",EXTMATCH},
313 {"abef","ab**",EXTMATCH},
314 {"fofo","*(f*(o))",EXTMATCH},
315 {"ffo","*(f*(o))",EXTMATCH},
316 {"foooofo","*(f*(o))",EXTMATCH},
317 {"foooofof","*(f*(o))",EXTMATCH},
318 {"fooofoofofooo","*(f*(o))",EXTMATCH},
319 {"foooofof","*(f+(o))",NOMATCH|EXTMATCH},
320 {"xfoooofof","*(f*(o))",NOMATCH|EXTMATCH},
321 {"foooofofx","*(f*(o))",NOMATCH|EXTMATCH},
322 {"ofxoofxo","*(*(of*(o)x)o)",EXTMATCH},
323 {"ofooofoofofooo","*(f*(o))",NOMATCH|EXTMATCH},
324 {"foooxfooxfoxfooox","*(f*(o)x)",EXTMATCH},
325 {"foooxfooxofoxfooox","*(f*(o)x)",NOMATCH|EXTMATCH},
326 {"foooxfooxfxfooox","*(f*(o)x)",EXTMATCH},
327 {"ofxoofxo","*(*(of*(o)x)o)",EXTMATCH},
328 {"ofoooxoofxo","*(*(of*(o)x)o)",EXTMATCH},
329 {"ofoooxoofxoofoooxoofxo","*(*(of*(o)x)o)",EXTMATCH},
330 {"ofoooxoofxoofoooxoofxoo","*(*(of*(o)x)o)",EXTMATCH},
331 {"ofoooxoofxoofoooxoofxofo","*(*(of*(o)x)o)",NOMATCH|EXTMATCH},
332 {"ofoooxoofxoofoooxoofxooofxofxo","*(*(of*(o)x)o)",EXTMATCH},
333 {"aac","*(@(a))a@(c)",EXTMATCH},
334 {"ac","*(@(a))a@(c)",EXTMATCH},
335 {"c","*(@(a))a@(c)",NOMATCH|EXTMATCH},
336 {"aaac","*(@(a))a@(c)",EXTMATCH},
337 {"baaac","*(@(a))a@(c)",NOMATCH|EXTMATCH},
338 {"abcd","?@(a|b)*@(c)d",EXTMATCH},
339 {"abcd","@(ab|a*@(b))*(c)d",EXTMATCH},
340 {"acd","@(ab|a*(b))*(c)d",EXTMATCH},
341 {"abbcd","@(ab|a*(b))*(c)d",EXTMATCH},
342 {"effgz","@(b+(c)d|e*(f)g?|?(h)i@(j|k))",EXTMATCH},
343 {"efgz","@(b+(c)d|e*(f)g?|?(h)i@(j|k))",EXTMATCH},
344 {"egz","@(b+(c)d|e*(f)g?|?(h)i@(j|k))",EXTMATCH},
345 {"egzefffgzbcdij","*(b+(c)d|e*(f)g?|?(h)i@(j|k))",EXTMATCH},
346 {"egz","@(b+(c)d|e+(f)g?|?(h)i@(j|k))",NOMATCH|EXTMATCH},
347 {"ofoofo","*(of+(o))",EXTMATCH},
348 {"oxfoxoxfox","*(oxf+(ox))",EXTMATCH},
349 {"oxfoxfox","*(oxf+(ox))",NOMATCH|EXTMATCH},
350 {"ofoofo","*(of+(o)|f)",EXTMATCH},
351 {"foofoofo","@(foo|f|fo)*(f|of+(o))",EXTMATCH},
352 {"oofooofo","*(of|oof+(o))",EXTMATCH},
353 {"fffooofoooooffoofffooofff","*(*(f)*(o))",EXTMATCH},
354 {"fofoofoofofoo","*(fo|foo)",EXTMATCH},
355 {"foo","!(x)",EXTMATCH},
356 {"foo","!(x)*",EXTMATCH},
357 {"foo","!(foo)",NOMATCH|EXTMATCH},
358 {"foo","!(foo)*",EXTMATCH},
359 {"foobar","!(foo)",EXTMATCH},
360 {"foobar","!(foo)*",EXTMATCH},
361 {"moo.cow","!(*.*).!(*.*)",EXTMATCH},
362 {"mad.moo.cow","!(*.*).!(*.*)",NOMATCH|EXTMATCH},
363 {"mucca.pazza","mu!(*(c))?.pa!(*(z))?",NOMATCH|EXTMATCH},
364 {"fff","!(f)",EXTMATCH},
365 {"fff","*(!(f))",EXTMATCH},
366 {"fff","+(!(f))",EXTMATCH},
367 {"ooo","!(f)",EXTMATCH},
368 {"ooo","*(!(f))",EXTMATCH},
369 {"ooo","+(!(f))",EXTMATCH},
370 {"foo","!(f)",EXTMATCH},
371 {"foo","*(!(f))",EXTMATCH},
372 {"foo","+(!(f))",EXTMATCH},
373 {"f","!(f)",NOMATCH|EXTMATCH},
374 {"f","*(!(f))",NOMATCH|EXTMATCH},
375 {"f","+(!(f))",NOMATCH|EXTMATCH},
376 {"foot","@(!(z*)|*x)",EXTMATCH},
377 {"zoot","@(!(z*)|*x)",NOMATCH|EXTMATCH},
378 {"foox","@(!(z*)|*x)",EXTMATCH},
379 {"zoox","@(!(z*)|*x)",EXTMATCH},
380 {"foo" ,"*(!(foo))",EXTMATCH},
381 {"foob","!(foo)b*",NOMATCH|EXTMATCH},
382 {"foobb","!(foo)b*",EXTMATCH},
383 {"[","*([a[])",EXTMATCH},
384 {"]","*([]a[])",EXTMATCH},
385 {"a","*([]a[])",EXTMATCH},
386 {"b","*([!]a[])",EXTMATCH},
387 {"[","*([!]a[]|[[])",EXTMATCH},
388 {"]","*([!]a[]|[]])",EXTMATCH},
389 {"[","!([!]a[])",EXTMATCH},
390 {"]","!([!]a[])",EXTMATCH},
391 {")","*([)])",EXTMATCH},
392 {"*","*([*(])",EXTMATCH},
393 {"abcd","*!(|a)cd",EXTMATCH},
394 {"","",0},
395 {"","",EXTMATCH},
396 {"","*([abc])",EXTMATCH},
397 {"","?([abc])",EXTMATCH},
398 {0,0,0}
399 };
400
401
402 #define BUF_SZ 2048
403 void _start(void)
404 {
405 ulinux_u8 buf[BUF_SZ];
406 struct test *test=&tests[0];
407 ulinux_u16 n=0;
408 while(1){
409 if(test->pattern==0) break;
410
411 ulinux_u8 flgs=0;
412 if(test->flags&EXTMATCH) flgs|=ULINUX_MATCH_EXTMATCH;
413
414 ulinux_s8 expected=ULINUX_MATCH_MATCH;
415 void *expected_str="match";
416 if(test->flags&NOMATCH){
417 expected=ULINUX_MATCH_NOMATCH;
418 expected_str="nomatch";
419 }
420
421 ulinux_dprintf(1,buf,BUF_SZ,"%u:%s %s 0x%02x ",n,test->string,test->pattern,
422 flgs);
423 ulinux_s8 r=ulinux_match(test->pattern,test->string,flgs);
424
425 if(r==expected){
426 ulinux_dprintf(1,buf,BUF_SZ,"OK(%s)\n",expected_str);
427 }else {
428 void *str;
429 if(expected==ULINUX_MATCH_MATCH){
430 str="nomatch";
431 if(r!=ULINUX_MATCH_NOMATCH) str="error code";
432 }else{
433 str="match";
434 if(r!=ULINUX_MATCH_MATCH) str="error code";
435 }
436 ulinux_dprintf(1,buf,BUF_SZ,"ERROR(expected:%s but got %s(%d))\n",expected_str,str,r);
437 }
438 ++test;++n;
439 }
440 ulinux_sysc(exit_group,1,0);
441 }
File ulinux/patterns/glob/makefile added (mode: 100644) (index 0000000..f4b205f)
1 .PHONY:clean
2
3 #does remove some useless ELF sections
4 OPTIM=-fno-stack-protector -fno-asynchronous-unwind-tables -fno-dwarf2-cfi-asm \
5 -Ofast -march=native
6
7 ARCH?=$(shell uname -m | sed -e s/i.86/x86/ -e s/parisc64/parisc/ \
8 -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/ -e s/sh.*/sh/)
9
10 glob:glob.c ../../../ulinux/arch
11 cpp -Wall -Wextra -I../../.. ../../utils/ascii/match/match.c \
12 -o cpp_match.c
13 gcc -Wall -Wextra -std=gnu99 $(OPTIM) -c cpp_match.c -o match.o
14 cpp -Wall -Wextra -I../../.. ../../utils/mem.c -o cpp_mem.c
15 gcc -Wall -Wextra -std=gnu99 $(OPTIM) -c cpp_mem.c -o mem.o
16 cpp -Wall -Wextra -I../../.. ../../utils/ascii/string/vsprintf.c \
17 -o cpp_vsprintf.c
18 gcc -Wall -Wextra -std=gnu99 $(OPTIM) -c cpp_vsprintf.c -o vsprintf.o
19 cpp -Wall -Wextra -I../../.. glob.c -o cpp_glob.c
20 gcc -Wall -Wextra -std=gnu99 $(OPTIM) -c cpp_glob.c -o glob.o
21 ld -O -nostdlib -Bstatic --strip-all glob.o mem.o \
22 vsprintf.o match.o \
23 $$(gcc -print-libgcc-file-name) --output glob
24
25 ../../../ulinux/arch:
26 ln -s archs/$(ARCH) ../../../ulinux/arch
27
28 clean:
29 -rm -f ../../../ulinux/arch
30 -rm -f cpp_glob.c glob.o glob \
31 cpp_match.c match.o \
32 cpp_mem.c mem.o \
33 cpp_vsprintf.c vsprintf.o
File ulinux/patterns/input/evdev.c added (mode: 100644) (index 0000000..82aa957)
1 #include <stdarg.h>
2 #include <ulinux/compiler_types.h>
3 #include <ulinux/sysc.h>
4 #include <ulinux/types.h>
5 #include <ulinux/error.h>
6 #include <ulinux/file.h>
7 #include <ulinux/fs.h>
8 #include <ulinux/dirent.h>
9 #include <ulinux/ioctl.h>
10 #include <ulinux/time.h>
11 #include <ulinux/input/evdev.h>
12 #include <ulinux/epoll.h>
13
14 #include <ulinux/utils/ascii/string/string.h>
15 #include <ulinux/utils/ascii/string/vsprintf.h>
16 #include <ulinux/utils/mem.h>
17
18 #include "ulinux_namespace.h"
19
20 #define DPRINTF_BUF_SZ 1024
21 static u8 *dprintf_buf;
22
23 #define PERRC(str) {l rl;do{rl=ulinux_sysc(write,3,2,str,sizeof(str));}\
24 while(rl==-EINTR||rl==-EAGAIN);}
25
26 #define PERR(fmt,...) ulinux_dprintf(2,dprintf_buf,DPRINTF_BUF_SZ,fmt,\
27 ##__VA_ARGS__)
28
29 #define EVDEVS_MAX 32//see linux/Documentation/input/input.txt:#3.2.4
30 //bits field sizes are long size modulos
31 #define LONG_BITS (sizeof(l)<<3)
32
33 struct evdev{
34 i fd;
35 struct input_event ev;
36 u8 ev_read_bytes;
37 l ev_bits[((EV_MAX/LONG_BITS)+1)];
38 l key_bits[((KEY_MAX/LONG_BITS)+1)];
39 l rel_bits[((REL_MAX/LONG_BITS)+1)];
40 l abs_bits[((ABS_MAX/LONG_BITS)+1)];
41 l msc_bits[((MSC_MAX/LONG_BITS)+1)];
42 l sw_bits[((SW_MAX/LONG_BITS)+1)];
43 l led_bits[((LED_MAX/LONG_BITS)+1)];
44 l snd_bits[((SND_MAX/LONG_BITS)+1)];
45 l ff_bits[((FF_MAX/LONG_BITS)+1)];
46 };
47 static u32 evdevs_n=0;
48 static struct evdev evdevs[EVDEVS_MAX];
49
50 static void bits_dump(void *hdr,l *p,u8 bytes)
51 {
52 PERR("%s=0x",hdr);
53 u8 *a=(u8*)p;
54 for(u8 j=0;j<bytes;++j) PERR("%1x%1x",a[j]&0x0f,a[j]>>4);
55 PERRC("\n");
56 }
57
58 static u8 test_bit(l *p,u16 bit_off)
59 {
60 u16 byte_off=bit_off>>3;
61 u8 byte_bit_off=bit_off%8;
62 u8 *a=(u8*)p;
63 return (a[byte_off]>>byte_bit_off)&1;
64 }
65
66 static s8 ev_bits(void)
67 {
68 l r=ioctl(evdevs[evdevs_n].fd,EVIOCGBIT(0,sizeof(evdevs[evdevs_n].ev_bits)),
69 (l)&evdevs[evdevs_n].ev_bits[0]);
70 if(ISERR(r)){
71 PERR("error(%ld):unable to get the evdev ev bits\n",r);
72 return -1;
73 }
74 bits_dump("ev_bits",&evdevs[evdevs_n].ev_bits[0],
75 sizeof(evdevs[evdevs_n].ev_bits));
76 return 0;
77 }
78
79 static s8 xxx_bits(u16 type,l *xxx_bits_array,l xxx_bits_array_sz,void *desc)
80 {
81 if(test_bit(evdevs[evdevs_n].ev_bits,type)){
82 l r=ioctl(evdevs[evdevs_n].fd,EVIOCGBIT(type,xxx_bits_array_sz),
83 xxx_bits_array);
84 if(ISERR(r)){
85 PERR("error(%ld):unable to get the evdev %s bits\n",r,desc);
86 return -1;
87 }
88 bits_dump(desc,xxx_bits_array,xxx_bits_array_sz);
89 }else PERR("no %s bits\n",desc);
90 return 0;
91 }
92
93 static void dentry_process(i dev_input_fd,struct dirent64 *d)
94 {
95 if(evdevs_n==EVDEVS_MAX||strncmp(d->name,"event",5)) goto exit;
96
97 PERR("\nstart processing %u:/dev/input/%s...\n",evdevs_n,d->name);
98
99 l r;
100 do r=openat(dev_input_fd,d->name,RDWR|NONBLOCK,0); while(r==-EINTR);
101 if(ISERR(r)){
102 PERR("error(%ld):unable to open the evdev node\n",r);
103 goto exit;
104 }
105
106 evdevs[evdevs_n].fd=(i)r;
107
108 i driver_version;
109 r=ioctl(evdevs[evdevs_n].fd,EVIOCGVERSION,(l)&driver_version);
110 if(ISERR(r)){
111 PERR("error(%ld):unable to get the driver version\n",r);
112 goto close_evdev_fd;
113 }
114 PERR("driver version=0x%08x\n",driver_version);
115
116 static u8 buf[256];
117 r=ioctl(evdevs[evdevs_n].fd,EVIOCGNAME(sizeof(buf)),(l)&buf[0]);
118 if(ISERR(r)){
119 PERR("error(%ld):unable to get the evdev name\n",r);
120 goto close_evdev_fd;
121 }
122 PERR("evdev name=%s\n",buf);
123
124 r=ioctl(evdevs[evdevs_n].fd,EVIOCGPHYS(sizeof(buf)),(l)&buf[0]);
125 if(ISERR(r)){
126 PERR("error(%ld):unable to get the evdev physical location\n",r);
127 goto close_evdev_fd;
128 }
129 PERR("evdev physical location=%s\n",buf);
130
131 if(ev_bits()!=0) goto close_evdev_fd;
132 if(xxx_bits(EV_KEY,&evdevs[evdevs_n].key_bits[0],
133 sizeof(evdevs[evdevs_n].key_bits),"key")!=0)
134 goto close_evdev_fd;
135 if(xxx_bits(EV_REL,&evdevs[evdevs_n].rel_bits[0],
136 sizeof(evdevs[evdevs_n].rel_bits),"rel")!=0)
137 goto close_evdev_fd;
138 if(xxx_bits(EV_ABS,&evdevs[evdevs_n].abs_bits[0],
139 sizeof(evdevs[evdevs_n].abs_bits),"abs")!=0)
140 goto close_evdev_fd;
141 if(xxx_bits(EV_MSC,&evdevs[evdevs_n].msc_bits[0],
142 sizeof(evdevs[evdevs_n].msc_bits),"msc")!=0)
143 goto close_evdev_fd;
144 if(xxx_bits(EV_SW,&evdevs[evdevs_n].sw_bits[0],
145 sizeof(evdevs[evdevs_n].sw_bits),"sw")!=0)
146 goto close_evdev_fd;
147 if(xxx_bits(EV_LED,&evdevs[evdevs_n].led_bits[0],
148 sizeof(evdevs[evdevs_n].led_bits),"led")!=0)
149 goto close_evdev_fd;
150 if(xxx_bits(EV_SND,&evdevs[evdevs_n].snd_bits[0],
151 sizeof(evdevs[evdevs_n].snd_bits),"snd")!=0)
152 goto close_evdev_fd;
153 if(xxx_bits(EV_FF,&evdevs[evdevs_n].ff_bits[0],
154 sizeof(evdevs[evdevs_n].ff_bits),"ff")!=0)
155 goto close_evdev_fd;
156 ++evdevs_n;
157 goto exit;
158
159 close_evdev_fd:
160 do r=close(evdevs[evdevs_n].fd); while(r==-EINTR);
161
162 exit:
163 return;
164 }
165
166 #define DIRENTS_BUF_SZ 8192
167 static void dev_input_parse(i dev_input_fd)
168 {
169 u8 dirents[DIRENTS_BUF_SZ];
170 while(1){
171 l r=getdents64(dev_input_fd,dirents,DIRENTS_BUF_SZ);
172 if(ISERR(r)){
173 PERR("ERROR(%ld):getdents error\n",r);
174 exit(-1);
175 }
176 if(!r) break;
177 l j=0;
178 while(j<r){
179 struct dirent64 *d=(struct dirent64*)(dirents+j);
180
181 dentry_process(dev_input_fd,d);
182 j+=d->rec_len;
183 }
184 }
185 }
186
187 static void *syn_code_str(u16 code)
188 {
189 switch(code){
190 case SYN_REPORT:
191 return "report";
192 case SYN_CONFIG:
193 return "config";
194 case SYN_MT_REPORT:
195 return "mt_report";
196 case SYN_DROPPED:
197 return "dropped";
198 default:
199 return "unknown syn code";
200 }
201 }
202
203 static void *rel_code_str(u16 code)
204 {
205 switch(code){
206 case REL_X:
207 return "x";
208 case REL_Y:
209 return "y";
210 case REL_Z:
211 return "z";
212 case REL_RX:
213 return "rx";
214 case REL_RY:
215 return "ry";
216 case REL_HWHEEL:
217 return "hwheel";
218 case REL_DIAL:
219 return "dial";
220 case REL_WHEEL:
221 return "wheel";
222 case REL_MISC:
223 return "misc";
224 default:
225 return "unknown rel code";
226 }
227 }
228
229 static void *msc_code_str(u16 code)
230 {
231 switch(code){
232 case MSC_SERIAL:
233 return "serial";
234 case MSC_PULSELED:
235 return "pulseled";
236 case MSC_GESTURE:
237 return "gesture";
238 case MSC_RAW:
239 return "raw";
240 case MSC_SCAN:
241 return "scan";
242 default:
243 return "unknown msc code";
244 }
245 }
246
247 static void *sw_code_str(u16 code)
248 {
249 switch(code){
250 case SW_LID:
251 return "lid";
252 case SW_TABLET_MODE:
253 return "tablet mode";
254 case SW_HEADPHONE_INSERT:
255 return "headphone insert";
256 case SW_RFKILL_ALL:
257 return "rf kill all";
258 case SW_MICROPHONE_INSERT:
259 return "microphone insert";
260 case SW_DOCK:
261 return "dock";
262 case SW_LINEOUT_INSERT:
263 return "line out insert";
264 case SW_JACK_PHYSICAL_INSERT:
265 return "jack physical insert";
266 case SW_VIDEOOUT_INSERT:
267 return "video out insert";
268 case SW_CAMERA_LENS_COVER:
269 return "camera lens cover";
270 case SW_KEYPAD_SLIDE:
271 return "keypad slide";
272 case SW_FRONT_PROXIMITY:
273 return "front proximity";
274 case SW_ROTATE_LOCK:
275 return "rotate lock";
276 case SW_LINEIN_INSERT:
277 return "line in insert";
278 default:
279 return "unknown sw code";
280 }
281 }
282
283 static void *snd_code_str(u16 code)
284 {
285 switch(code){
286 case SND_CLICK:
287 return "click";
288 case SND_BELL:
289 return "bell";
290 case SND_TONE:
291 return "tone";
292 default:
293 return "unknown snd code";
294 }
295 }
296
297 static void device_event_process(u8 j)
298 {
299 struct input_event *ev=&evdevs[j].ev;
300 void *type_str;
301 void *code_str;
302 switch(ev->type){
303 case EV_SYN:
304 type_str="syn";
305 code_str=syn_code_str(ev->code);
306 break;
307 case EV_KEY:
308 type_str="key";
309 code_str="see key table in ulinux/input/evdev.h";
310 break;
311 case EV_REL:
312 type_str="rel";
313 code_str=rel_code_str(ev->code);
314 break;
315 case EV_ABS:
316 type_str="abs";
317 code_str="see abs table in ulinux/input/evdev.h";
318 break;
319 case EV_MSC:
320 type_str="msc";
321 code_str=msc_code_str(ev->code);
322 break;
323 case EV_SW:
324 type_str="sw";
325 code_str=sw_code_str(ev->code);
326 break;
327 case EV_LED:
328 type_str="led";
329 code_str="LED IN ONLY OUPUT, NOT INPUT!!!";
330 break;
331 case EV_SND:
332 type_str="snd";
333 code_str=snd_code_str(ev->code);
334 break;
335 case EV_REP:
336 type_str="rep";
337 code_str="support is not implemented!";
338 break;
339 case EV_FF:
340 type_str="ff";
341 code_str="see ff table in ulinux/input/evdev.h";
342 break;
343 case EV_PWR:
344 type_str="pwr";
345 code_str="support is not implemented!";
346 break;
347 case EV_FF_STATUS:
348 type_str="ff_status";
349 code_str="see ff status table in ulinux_input/evdev.h";
350 break;
351 default:
352 type_str="unknown";
353 code_str="unknown type";
354 }
355
356 PERR("\ngot event from device %u:\n"
357 " time=%ld.%ld\n"
358 " type=0x%04x(%s)\n"
359 " code=0x%04x(%s)\n"
360 " value=0x%08x\n",
361 j,ev->time.sec,ev->time.usec,ev->type,type_str,ev->code,code_str,
362 ev->value);
363 }
364
365 static void monitor(void)
366 {
367 l r0=epoll_create1(0);
368 if(ISERR(r0)){
369 PERR("error(%ld) create epoll fd\n",r0);
370 exit(-1);
371 }
372 i epfd=(i)r0;
373
374 struct epoll_event evts[EVDEVS_MAX];
375 memset(evts,0,sizeof(struct epoll_event)*evdevs_n);
376
377 for(u8 j=0;j<evdevs_n;++j){
378 evts[j].events=EPOLLET|EPOLLIN;
379 evts[j].data._32=j;
380 r0=epoll_ctl(epfd,EPOLL_CTL_ADD,evdevs[j].fd,&evts[j]);
381 if(ISERR(r0)){
382 PERR("error(%ld) adding fd from ev device %u\n",r0,j);
383 exit(-1);
384 }
385 }
386
387 //main loop
388 while(1){
389 do{
390 memset(evts,0,sizeof(evts));
391 r0=epoll_wait(epfd,evts,evdevs_n,-1);
392 }while(r0==-EINTR);
393 if(ISERR(r0)){
394 PERR("error(%ld) while waiting epoll event\n",r0);
395 exit(-1);
396 }
397
398 //parse events
399 for(u8 j=0;j<(u8)r0;++j)
400 if(evts[j].events&EPOLLIN){//only read events
401 while(1){
402 struct evdev *d=&evdevs[evts[j].data._32];
403 //reset event content if it was read and dealed with
404 if(d->ev_read_bytes==sizeof(d->ev)){
405 memset(&d->ev,0,sizeof(d->ev));
406 d->ev_read_bytes=0;
407 }
408
409 //XXX:buffer should be bigger, since one "input event" generates many
410 //*evdev* (input) events. Reads get a whole number of events.
411 l r1;
412 do
413 r1=read(d->fd,(void*)(&d->ev)+d->ev_read_bytes,sizeof(d->ev)
414 -d->ev_read_bytes);
415 while(r1==-EINTR);
416 if(r1==-EAGAIN) break;//read all we can, then go to next event
417 if(ISERR(r1)){
418 PERR("error(%ld) read from ev device %u\n",r1,evts[j].data._32);
419 exit(-1);
420 }
421
422 d->ev_read_bytes+=(u8)r1;
423 if(d->ev_read_bytes==sizeof(d->ev))
424 device_event_process(evts[j].data._32);
425 }
426 }//not handled (hot unplugging will be ignored with consequences)
427 }
428 }
429
430 void _start(void)
431 {
432 u8 _dprintf_buf[DPRINTF_BUF_SZ];
433 dprintf_buf=&_dprintf_buf[0];
434
435 l r;
436 do r=open("/dev/input",RDONLY|NONBLOCK,0);while(r==-EINTR);
437 if(ISERR(r)){
438 PERR("ERROR(%ld):unable to open /dev/input\n",r);
439 exit(-1);
440 }
441
442 dev_input_parse((i)r);
443 monitor();
444 exit(0);
445 }
File ulinux/patterns/input/makefile added (mode: 100644) (index 0000000..e1a2afd)
1 .PHONY:clean
2
3 #does remove some useless ELF sections
4 OPTIM=-fno-stack-protector -fno-asynchronous-unwind-tables -fno-dwarf2-cfi-asm \
5 -Ofast -march=native
6
7 ARCH?=$(shell uname -m | sed -e s/i.86/x86/ -e s/parisc64/parisc/ \
8 -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/ -e s/sh.*/sh/)
9
10 evdev:evdev.c ../../../ulinux/arch
11 cpp -Wall -Wextra -I../../.. ../../utils/mem.c -o cpp_mem.c
12 gcc -Wall -Wextra -std=gnu99 $(OPTIM) -c cpp_mem.c -o mem.o
13 cpp -Wall -Wextra -I../../.. ../../utils/ascii/string/vsprintf.c \
14 -o cpp_vsprintf.c
15 gcc -Wall -Wextra -std=gnu99 $(OPTIM) -c cpp_vsprintf.c -o vsprintf.o
16 cpp -Wall -Wextra -I../../.. evdev.c -o cpp_evdev.c
17 gcc -Wall -Wextra -std=gnu99 $(OPTIM) -c cpp_evdev.c -o evdev.o
18 ld -O -nostdlib -Bstatic --strip-all evdev.o string.o \
19 mem.o vsprintf.o $$(gcc -print-libgcc-file-name) \
20 --output evdev
21
22 ../../../ulinux/arch:
23 ln -s archs/$(ARCH) ../../../ulinux/arch
24
25 clean:
26 -rm -f ../../../ulinux/arch
27 -rm -f cpp_evdev.c evdev.o evdev \
28 cpp_mem.c mem.o \
29 cpp_vsprintf.c vsprintf.o
File ulinux/patterns/input/ulinux_namespace.h added (mode: 100644) (index 0000000..61d409a)
1 #ifndef ULINUX_NAMESPACE_H
2 #define ULINUX_NAMESPACE_H
3 #define EINTR ULINUX_EINTR
4 #define EAGAIN ULINUX_EAGAIN
5 #define si ulinux_si
6 #define sl ulinux_sl
7 #define u8 ulinux_u8
8 #define s8 ulinux_s8
9 #define u16 ulinux_u16
10 #define u32 ulinux_u32
11 #define s32 ulinux_s32
12 #define u64 ulinux_u64
13 #define s64 ulinux_s64
14 #define input_event ulinux_input_event
15 #define EV_SYN ULINUX_EV_SYN
16 #define EV_MAX ULINUX_EV_MAX
17 #define EV_KEY ULINUX_EV_KEY
18 #define KEY_MAX ULINUX_KEY_MAX
19 #define EV_REL ULINUX_EV_REL
20 #define REL_MAX ULINUX_REL_MAX
21 #define EV_ABS ULINUX_EV_ABS
22 #define ABS_MAX ULINUX_ABS_MAX
23 #define EV_MSC ULINUX_EV_MSC
24 #define MSC_MAX ULINUX_MSC_MAX
25 #define EV_SW ULINUX_EV_SW
26 #define SW_MAX ULINUX_SW_MAX
27 #define EV_LED ULINUX_EV_LED
28 #define LED_MAX ULINUX_LED_MAX
29 #define EV_REP ULINUX_EV_REP
30 #define EV_SND ULINUX_EV_SND
31 #define SND_MAX ULINUX_SND_MAX
32 #define EV_FF ULINUX_EV_FF
33 #define FF_MAX ULINUX_FF_MAX
34 #define EV_PWR ULINUX_EV_PWR
35 #define EV_FF_STATUS ULINUX_EV_FF_STATUS
36 #define ioctl(a,b,c) ulinux_sysc(ioctl,3,a,b,c)
37 #define EVIOCGBIT ULINUX_EVIOCGBIT
38 #define ISERR ULINUX_ISERR
39 #define dirent64 ulinux_dirent64
40 #define strncmp ulinux_strncmp
41 #define openat(a,b,c,d) ulinux_sysc(openat,4,a,b,c,d)
42 #define RDWR ULINUX_O_RDWR
43 #define RDONLY ULINUX_O_RDONLY
44 #define NONBLOCK ULINUX_O_NONBLOCK
45 #define EVIOCGVERSION ULINUX_EVIOCGVERSION
46 #define EVIOCGNAME ULINUX_EVIOCGNAME
47 #define EVIOCGPHYS ULINUX_EVIOCGPHYS
48 #define close(a) ulinux_sysc(close,1,a)
49 #define getdents64(a,b,c) ulinux_sysc(getdents64,3,a,b,c)
50 #define exit(a) ulinux_sysc(exit_group,1,a)
51 #define SYN_REPORT ULINUX_SYN_REPORT
52 #define SYN_CONFIG ULINUX_SYN_CONFIG
53 #define SYN_MT_REPORT ULINUX_SYN_MT_REPORT
54 #define SYN_DROPPED ULINUX_SYN_DROPPED
55 #define REL_X ULINUX_REL_X
56 #define REL_Y ULINUX_REL_Y
57 #define REL_Z ULINUX_REL_Z
58 #define REL_RX ULINUX_REL_RX
59 #define REL_RY ULINUX_REL_RY
60 #define REL_HWHEEL ULINUX_REL_HWHEEL
61 #define REL_DIAL ULINUX_REL_DIAL
62 #define REL_WHEEL ULINUX_REL_WHEEL
63 #define REL_MISC ULINUX_REL_MISC
64 #define MSC_SERIAL ULINUX_MSC_SERIAL
65 #define MSC_PULSELED ULINUX_MSC_PULSELED
66 #define MSC_GESTURE ULINUX_MSC_GESTURE
67 #define MSC_RAW ULINUX_MSC_RAW
68 #define MSC_SCAN ULINUX_MSC_SCAN
69 #define SW_LID ULINUX_SW_LID
70 #define SW_TABLET_MODE ULINUX_SW_TABLET_MODE
71 #define SW_HEADPHONE_INSERT ULINUX_SW_HEADPHONE_INSERT
72 #define SW_RFKILL_ALL ULINUX_SW_RFKILL_ALL
73 #define SW_MICROPHONE_INSERT ULINUX_SW_MICROPHONE_INSERT
74 #define SW_DOCK ULINUX_SW_DOCK
75 #define SW_LINEOUT_INSERT ULINUX_SW_LINEOUT_INSERT
76 #define SW_JACK_PHYSICAL_INSERT ULINUX_SW_JACK_PHYSICAL_INSERT
77 #define SW_VIDEOOUT_INSERT ULINUX_SW_VIDEOOUT_INSERT
78 #define SW_CAMERA_LENS_COVER ULINUX_SW_CAMERA_LENS_COVER
79 #define SW_KEYPAD_SLIDE ULINUX_SW_KEYPAD_SLIDE
80 #define SW_FRONT_PROXIMITY ULINUX_SW_FRONT_PROXIMITY
81 #define SW_ROTATE_LOCK ULINUX_SW_ROTATE_LOCK
82 #define SW_LINEIN_INSERT ULINUX_SW_LINEIN_INSERT
83 #define SND_CLICK ULINUX_SND_CLICK
84 #define SND_BELL ULINUX_SND_BELL
85 #define SND_TONE ULINUX_SND_TONE
86 #define epoll_create1(a) ulinux_sysc(epoll_create1,1,a)
87 #define epoll_event ulinux_epoll_event
88 #define memset ulinux_memset
89 #define EPOLLET ULINUX_EPOLLET
90 #define EPOLLIN ULINUX_EPOLLIN
91 #define EPOLL_CTL_ADD ULINUX_EPOLL_CTL_ADD
92 #define epoll_ctl(a,b,c,d) ulinux_sysc(epoll_ctl,4,a,b,c,d)
93 #define epoll_wait(a,b,c,d) ulinux_sysc(epoll_wait,4,a,b,c,d)
94 #define read(a,b,c) ulinux_sysc(read,3,a,b,c)
95 #define open(a,b,c) ulinux_sysc(open,3,a,b,c)
96 #endif
File ulinux/patterns/insmod/insmod.c added (mode: 100644) (index 0000000..b8fcedc)
1 #include <stdarg.h>
2 #include <ulinux/compiler_types.h>
3 #include <ulinux/sysc.h>
4 #include <ulinux/types.h>
5 #include <ulinux/error.h>
6 #include <ulinux/args_env.h>
7 #include <ulinux/file.h>
8 #include <ulinux/stat.h>
9 #include <ulinux/mmap.h>
10
11 #include <ulinux/utils/mem.h>
12 #include <ulinux/utils/ascii/string/vsprintf.h>
13
14 //------------------------------------------------------------------------------
15 //ulinux namespace
16 #define EINTR ULINUX_EINTR
17 #define EAGAIN ULINUX_EAGAIN
18 #define si ulinux_si
19 #define sl ulinux_sl
20 #define u8 ulinux_u8
21 #define exit(a) ulinux_sysc(exit_group,1,a)
22 #define open(a,b,c) ulinux_sysc(open,3,a,b,c)
23 #define RDONLY ULINUX_O_RDONLY
24 #define ISERR ULINUX_ISERR
25 #define stat ulinux_stat
26 #define fstat(a,b) ulinux_sysc(fstat,2,a,b)
27 #define mmap(a,b,c,d,e,f) ulinux_sysc(mmap,6,a,b,c,d,e,f)
28 #define PROT_READ ULINUX_PROT_READ
29 #define MAP_PRIVATE ULINUX_MAP_PRIVATE
30 #define MAP_POPULATE ULINUX_MAP_POPULATE
31 #define init_module(a,b,c) ulinux_sysc(init_module,3,a,b,c)
32 //------------------------------------------------------------------------------
33
34 #define DPRINTF_BUF_SZ 1024
35 static u8 *dprintf_buf;
36
37 #define PERRC(str) {l rl;do{rl=ulinux_sysc(write,3,2,str,sizeof(str));}\
38 while(rl==-EINTR||rl==-EAGAIN);}
39
40 #define PERR(fmt,...) ulinux_dprintf(2,dprintf_buf,DPRINTF_BUF_SZ,fmt,\
41 ##__VA_ARGS__)
42
43 #define POUT(fmt,...) ulinux_dprintf(1,dprintf_buf,DPRINTF_BUF_SZ,fmt,\
44 ##__VA_ARGS__)
45
46 #define POUTC(str) {l rl;do{rl=ulinux_sysc(write,3,1,str,sizeof(str));}\
47 while(rl==-EINTR||rl==-EAGAIN);}
48
49 void ulinux_start(l argc,void **argv)
50 {
51 u8 _dprintf_buf[DPRINTF_BUF_SZ];
52 dprintf_buf=&_dprintf_buf[0];
53
54 if(argc!=2){
55 PERR("ERROR:wrong number of command arguments(%d)\n",argc);
56 exit(-1);
57 }
58
59 i fd;
60 do fd=(i)open(argv[1],RDONLY,0); while(fd==-EINTR);
61 if(ISERR(fd)){
62 PERR("ERROR(%ld):unable to open module %s\n",fd,argv[1]);
63 exit(-1);
64 }
65
66 struct stat m_stat;
67 l r=fstat(fd,&m_stat);
68 if(ISERR(r)){
69 PERR("ERROR(%ld):unable to stat module\n",r);
70 exit(-1);
71 }
72 POUT("size=%lu\n",m_stat.sz);
73
74 l addr=mmap(0,m_stat.sz,PROT_READ,MAP_PRIVATE|MAP_POPULATE,fd,0);
75 if(!addr||ISERR(addr)){
76 PERR("ERROR(%ld):unable to mmap module file\n",addr);
77 exit(-1);
78 }
79
80 r=init_module(addr,m_stat.sz,"");
81 if(ISERR(r)){
82 PERR("ERROR(%ld):unable init module\n",r);
83 exit(-1);
84 }
85 exit(0);
86 }
File ulinux/patterns/insmod/makefile added (mode: 100644) (index 0000000..f7d295b)
1 .PHONY:clean
2
3 #does remove some useless ELF sections
4 OPTIM=-fno-stack-protector -fno-asynchronous-unwind-tables -fno-dwarf2-cfi-asm \
5 -Ofast -march=native
6
7 ARCH?=$(shell uname -m | sed -e s/i.86/x86/ -e s/parisc64/parisc/ \
8 -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/ -e s/sh.*/sh/)
9
10 insmod:insmod.c ../../../ulinux/arch
11 cpp -Wall -Wextra -I../../.. ../../utils/mem.c -o cpp_mem.c
12 gcc -Wall -Wextra -std=gnu99 $(OPTIM) -c cpp_mem.c -o mem.o
13 cpp -Wall -Wextra -I../../.. ../../utils/ascii/string/vsprintf.c \
14 -o cpp_vsprintf.c
15 gcc -Wall -Wextra -std=gnu99 $(OPTIM) -c cpp_vsprintf.c -o vsprintf.o
16 as ../../arch/args_env.s -o args_env.o
17 cpp -Wall -Wextra -I../../.. insmod.c -o cpp_insmod.c
18 gcc -Wall -Wextra -std=gnu99 $(OPTIM) -c cpp_insmod.c -o insmod.o
19 ld -O -nostdlib -Bstatic --strip-all insmod.o args_env.o string.o mem.o \
20 vsprintf.o $$(gcc -print-libgcc-file-name) --output insmod
21
22 ../../../ulinux/arch:
23 ln -s archs/$(ARCH) ../../../ulinux/arch
24
25 clean:
26 -rm -f ../../../ulinux/arch
27 -rm -f cpp_insmod.c insmod.o insmod \
28 cpp_mem.c mem.o \
29 cpp_vsprintf.c vsprintf.o \
30 args_env.o
File ulinux/patterns/network_server/pre-fork_socket_unix_tcp/makefile added (mode: 100644) (index 0000000..e80c3b8)
1 .PHONY:clean
2
3 #does remove some useless ELF sections
4 OPTIM=-fno-stack-protector -fno-asynchronous-unwind-tables -fno-dwarf2-cfi-asm \
5 -Ofast -march=native
6
7 ARCH?=$(shell uname -m | sed -e s/i.86/x86/ -e s/parisc64/parisc/ \
8 -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/ -e s/sh.*/sh/)
9
10 pre-fork_socket_unix_tcp:pre-fork_socket_unix_tcp.c ../../../../ulinux/arch
11 cpp -Wall -Wextra -I../../../.. ../../../utils/mem.c -o cpp_mem.c
12 gcc -Wall -Wextra -std=gnu99 $(OPTIM) -c cpp_mem.c -o mem.o
13 cpp -Wall -Wextra -I../../../.. ../../../utils/ascii/string/vsprintf.c \
14 -o cpp_vsprintf.c
15 gcc -Wall -Wextra -std=gnu99 $(OPTIM) -c cpp_vsprintf.c -o vsprintf.o
16 as ../../../arch/args_env.s -o args_env.o
17 cpp -Wall -Wextra -I../../../.. ../../../utils/ascii/block/conv/net/net.c \
18 -o cpp_net.c
19 gcc -Wall -Wextra -std=gnu99 $(OPTIM) -c cpp_net.c -o net.o
20 cpp -Wall -Wextra -I../../../.. \
21 ../../../utils/ascii/string/conv/decimal/decimal.c \
22 -o cpp_string_decimal.c
23 gcc -Wall -Wextra -std=gnu99 $(OPTIM) -c cpp_string_decimal.c \
24 -o string_decimal.o
25 cpp -Wall -Wextra -I../../../.. \
26 ../../../utils/ascii/block/conv/decimal/decimal.c \
27 -o cpp_block_decimal.c
28 gcc -Wall -Wextra -std=gnu99 $(OPTIM) -c cpp_block_decimal.c \
29 -o block_decimal.o
30 cpp -Wall -Wextra -I../../../.. pre-fork_socket_unix_tcp.c \
31 -o cpp_pre-fork_socket_unix_tcp.c
32 gcc -Wall -Wextra -std=gnu99 $(OPTIM) -c \
33 cpp_pre-fork_socket_unix_tcp.c -o pre-fork_socket_unix_tcp.o
34 ld -O -nostdlib -Bstatic --strip-all block_decimal.o string_decimal.o \
35 net.o args_env.o string.o mem.o vsprintf.o \
36 pre-fork_socket_unix_tcp.o \
37 $$(gcc -print-libgcc-file-name) \
38 --output pre-fork_socket_unix_tcp
39
40 ../../../../ulinux/arch:
41 ln -s archs/$(ARCH) ../../../../ulinux/arch
42
43 clean:
44 -rm -f ../../../../ulinux/arch
45 -rm -f cpp_pre-fork_socket_unix_tcp.c \
46 pre-fork_socket_unix_tcp.o \
47 pre-fork_socket_unix_tcp \
48 cpp_mem.c mem.o \
49 cpp_vsprintf.c vsprintf.o \
50 args_env.o \
51 cpp_net.c net.o \
52 cpp_string_decimal.c string_decimal.o \
53 cpp_block_decimal.c block_decimal.o
File ulinux/patterns/network_server/pre-fork_socket_unix_tcp/pre-fork_socket_unix_tcp.c added (mode: 100644) (index 0000000..3e7f6dd)
1 //******************************************************************************
2 //*this code is protected by the GNU affero GPLv3
3 //*author:Sylvain BERTRAND <sylvain.bertrand AT gmail dot com>
4 //* <digital.ragnarok AT gmail dot com>
5 //******************************************************************************
6 //------------------------------------------------------------------------------
7 //|compiler stuff
8 //------------------------------------------------------------------------------
9 #include <stdarg.h>
10 //------------------------------------------------------------------------------
11
12 //------------------------------------------------------------------------------
13 //|ulinux stuff
14 //------------------------------------------------------------------------------
15 #include <ulinux/compiler_types.h>
16 #include <ulinux/types.h>
17 #include <ulinux/sysc.h>
18
19 #include <ulinux/args_env.h>
20 #include <ulinux/file.h>
21 #include <ulinux/socket/socket.h>
22 #include <ulinux/socket/in.h>
23 #include <ulinux/socket/msg.h>
24 #include <ulinux/signal/signal.h>
25 #include <ulinux/error.h>
26 #include <ulinux/epoll.h>
27 #include <ulinux/mmap.h>
28 #include <ulinux/wait.h>
29
30 #include <ulinux/utils/atomic.h>
31 #include <ulinux/utils/ascii/ascii.h>
32 #include <ulinux/utils/ascii/string/string.h>
33 #include <ulinux/utils/ascii/string/vsprintf.h>
34 #include <ulinux/utils/ascii/string/conv/decimal/decimal.h>
35 #include <ulinux/utils/endian.h>
36 #include <ulinux/utils/ascii/block/conv/net/net.h>
37 #include <ulinux/utils/mem.h>
38
39 #include "ulinux_namespace.h"
40 //------------------------------------------------------------------------------
41
42
43 //------------------------------------------------------------------------------
44 //|sockets stuff
45 //------------------------------------------------------------------------------
46 static struct sockaddr_in srv_addr={
47 .sin_family=AF_INET,
48 .sin_port=0,
49 .sin_addr={INADDR_ANY}};
50 static i srv_sock=-1;//the main listening socket
51 static i cnx_sock=-1;
52 //------------------------------------------------------------------------------
53
54
55 //------------------------------------------------------------------------------
56 //|non preclones stuff
57 //------------------------------------------------------------------------------
58 static u16 ps_max=0;//max of non preclone processes
59 static u16 ps_n=0;//current number of non preclone processes
60 //------------------------------------------------------------------------------
61
62
63 //------------------------------------------------------------------------------
64 //|precloneS stuff
65 //------------------------------------------------------------------------------
66 struct preclone{
67 i sock;//unix socket to pass TCP sockets
68 i pid;
69 };
70 static struct preclone *preclones=0;//preclones management
71 static s16 preclones_n=0;//can be 0
72
73 #define PRECLONE_AVAILABLE 0
74 #define PRECLONE_BUSY 1
75 static atomic_u8_t *preclones_states=0;//shared array of atomic states
76
77 static struct msg_hdr msg;//msg to pass the connexion socket
78 //the control message buffer: control hdr long padded block, plus data long
79 //padded block
80 static u8 cmsg_buf[CMSG_SPACE(sizeof(cnx_sock))];
81 //------------------------------------------------------------------------------
82
83
84 //------------------------------------------------------------------------------
85 //|preclone stuff
86 //------------------------------------------------------------------------------
87 static u16 preclone_runs=0;//number of runs a preclone does before dying
88 static s16 preclone_slot=-1;
89 static i preclone_parent_sock=-1;//where to receive the fd of the connexion socket
90 //------------------------------------------------------------------------------
91
92
93 //------------------------------------------------------------------------------
94 //|fd facilities
95 //------------------------------------------------------------------------------
96 static i sigs_fd=-1;//fd for signals
97 static i epfd=-1;//epoll fd
98 //------------------------------------------------------------------------------
99
100
101 //------------------------------------------------------------------------------
102 //|misc
103 //------------------------------------------------------------------------------
104 static u32* allows;
105 static u32 allow_n=0;//ipv4 address to allow traffic from
106 #define DPRINTF_BUF_SZ 1024
107 static u8 *dprintf_buf;
108 #define POUTC(str) {l rl;do{rl=ulinux_sysc(write,3,0,str,sizeof(str));}\
109 while(rl==-EINTR||rl==-EAGAIN);}
110
111 #define PERRC(str) {l rl;do{rl=ulinux_sysc(write,3,2,str,sizeof(str));}\
112 while(rl==-EINTR||rl==-EAGAIN);}
113
114 #define PERR(fmt,...) ulinux_dprintf(2,dprintf_buf,DPRINTF_BUF_SZ,fmt,\
115 ##__VA_ARGS__)
116 #define SIGBIT(sig) (1<<(sig-1))
117 //------------------------------------------------------------------------------
118
119 //******************************************************************************
120 //******************************************************************************
121 //******************************************************************************
122
123 static void usage(void)
124 {
125 POUTC("-inet <x.x.x.x IPv4 address to listen to>\n"
126 "-port <TCP port to listen to>\n"
127 "-psmax <max number of non precloned processes\n"
128 " default in 0, max is 65536>\n"
129 "-preclones <number of precloned processes\n"
130 " default is 0, max is 65535>\n"
131 " -runs <number of runs a preclones does before dying\n"
132 " default is infinite,max is 65535>\n"
133 "-allows <coma separated list of IPv4 adresses, x0.x0.x0.x0,x1.x1.x1.x1...\n"
134 " default is all ipv4 addresses accepted>\n"
135 "-help display this text\n");
136 }
137
138 //******************************************************************************
139
140 static void cnx_sendrecv_setup(void)
141 {
142 memset(&msg,0,sizeof(msg));
143 memset(cmsg_buf,0,sizeof(cmsg_buf));
144
145 msg.ctl=cmsg_buf;
146 msg.ctl_len=sizeof(cmsg_buf);//long padded size for hdr
147 //plus long padded size for data
148 struct cmsg_hdr *cmsg=CMSG_FIRSTHDR(&msg);
149 cmsg->lvl=SOL_SOCKET;
150 cmsg->type=SCM_RIGHTS;
151 cmsg->len=CMSG_LEN(sizeof(cnx_sock));//long padded size for hdr plus
152 //*not* long padded size for data
153 //XXX:was wrong but had worked
154 //msg.ctl_len=cmsg->len;//long padded for hdr plus
155 //*not* long padded size for data
156 //that means to ignore the padding bytes at the end
157 //of the data block
158 }
159
160 //******************************************************************************
161 //*clone stuff
162 //******************************************************************************
163 static void clone_sigs_setup(void)
164 {
165 //cannot change SIGKILL, neither SIGSTOP
166 u64 mask=(~0);
167 l r=rt_sigprocmask(SIG_BLOCK,&mask,0,sizeof(mask));
168 if(ISERR(r)){
169 PERR("FATAL:child:clone:error blocking mostly all signals (%ld)\n",r);
170 exit(-1);
171 }
172 }
173
174 static void clone_cnx_do(void)
175 {
176 POUTC("CLONE:DOING SOME WORK!\n");
177 l r;
178 do r=close(cnx_sock); while(r==-EINTR);
179 }
180
181 static void clone_setup(void)
182 {
183 clone_sigs_setup();
184
185 l r=dup2(cnx_sock,0);
186 if(ISERR(r)){
187 PERR("FATAL:child:clone:unable to make stdin the connexion socket (%ld)\n",
188 r);
189 exit(-1);
190 }
191
192 r=dup2(cnx_sock,1);
193 if(ISERR(r)){
194 PERR("FATAL:child:clone:unable to make stdout the connexion socket (%ld)\n",
195 r);
196 exit(-1);
197 }
198 }
199
200 static void clone_entry(void)
201 {
202 clone_setup();
203 clone_cnx_do();
204 exit(0);
205 }
206 //******************************************************************************
207
208
209 //******************************************************************************
210 //*preclone stuff (if too much, will go away in another source file)
211 //*fds mapping:
212 //* - 0 connexion socket
213 //* - 1 connexion socket
214 //* - 2 parent stderr
215 //* - 3 epoll
216 //* - 4 signalfd fd
217 //* - 5 parent unix socket for receiving connexion socket
218 //******************************************************************************
219 static void preclone_sigs_setup(void)
220 {
221 //cannot change SIGKILL, neither SIGSTOP
222 ul mask=(~0);
223 l r=rt_sigprocmask(SIG_BLOCK,&mask,0,sizeof(mask));
224 if(ISERR(r)){
225 PERR("FATAL:child:preclone:%d:error blocking mostly all signals (%ld)\n",
226 preclone_slot,r);
227 exit(-1);
228 }
229
230 mask=SIGBIT(SIGTERM);
231 i sigs_fd=(i)signalfd4(-1,&mask,sizeof(mask),SFD_NONBLOCK);
232 if(ISERR(r)){
233 PERR("FATAL:child:preclone:%d:error setting up fd for signals (%d)\n",
234 preclone_slot,sigs_fd);
235 exit(-1);
236 }
237
238 if(sigs_fd!=4){//moving signalfd fd to 4, if required
239 r=dup2(sigs_fd,4);
240 if(ISERR(r)){
241 PERR("FATAL:child:preclone:%d:unable to move signalfd fd (%ld)\n",
242 preclone_slot,r);
243 exit(-1);
244 }
245 do r=close(sigs_fd); while(r==-EINTR);
246 }
247 }
248
249 static void preclone_epoll_setup(void)
250 {
251 i epfd=(i)epoll_create1(0);
252 if(ISERR(epfd)){
253 PERR("FATAL:child:preclone:%d:unable to create epoll fd (%d)\n",
254 preclone_slot,epfd);
255 exit(-1);
256 }
257
258 if(epfd!=3){//moving epoll fd to 3, if required
259 l r=dup2(epfd,3);
260 if(ISERR(r)){
261 PERR("FATAL:child:preclone:%d:unable to move epoll fd (%ld)\n",
262 preclone_slot,r);
263 exit(-1);
264 }
265 do r=close(epfd); while(r==-EINTR);
266 }
267
268 struct epoll_event ep_evt;
269 memset(&ep_evt,0,sizeof(ep_evt));
270 ep_evt.events=EPOLLET|EPOLLIN;
271
272 ep_evt.data.fd=4;
273 l r=epoll_ctl(3,EPOLL_CTL_ADD,4,&ep_evt);
274 if(ISERR(r)){
275 PERR("FATAL:child:preclone:%d:unable to register signal fd to epoll (%ld)\n",
276 preclone_slot,r);
277 exit(-1);
278 }
279
280 ep_evt.data.fd=5;
281 ep_evt.events=EPOLLIN|EPOLLPRI;
282 r=epoll_ctl(3,EPOLL_CTL_ADD,5,&ep_evt);
283 if(ISERR(r)){
284 PERR("FATAL:child:preclone:%d:unable to register parent socket to epoll"
285 " (%ld)\n",preclone_slot,r);
286 exit(-1);
287 }
288 }
289
290 static void preclone_cnx_get(void)
291 {
292 cnx_sendrecv_setup();
293
294 l r;
295 do r=recvmsg(5,&msg,0); while(r==-EINTR);
296 if(ISERR(r)){
297 PERR("FATAL:child:preclone:%d:unable to get the connexion from parent (%ld)"
298 "\n",preclone_slot,r);
299 exit(-1);
300 }
301 if(msg.flgs&MSG_CTRUNC){
302 PERR("FATAL:child:preclone:%d:buffer error getting the connexion from"
303 " parent (0x%x)\n",preclone_slot,msg.flgs);
304 exit(-1);
305 }
306
307 i cnx_sock=*((i*)(CMSG_DATA(CMSG_FIRSTHDR(&msg))));
308
309 if(cnx_sock!=0){//moving connexion socket fd to 0 if required
310 r=dup2(cnx_sock,0);
311 if(ISERR(r)){
312 PERR("FATAL:child:preclone:%d:unable to move socket connexion fd (%ld)\n",
313 preclone_slot,r);
314 exit(-1);
315 }
316 do r=close(cnx_sock); while(r==-EINTR);
317 }
318
319 r=dup2(0,1);//stdout is connexion socket, 1 was already closed
320 if(ISERR(r)){
321 PERR("FATAL:child:preclone:%d:unable to duplicate connexion socket on"
322 " stdout (%ld)\n",preclone_slot,r);
323 exit(-1);
324 }
325 }
326
327 static void preclone_cnx_do(void)
328 {
329 preclone_cnx_get();
330 POUTC("PRE-CLONE:DOING SOME WORK!\n");
331 l r;
332 do r=close(0); while(r==-EINTR);
333 do r=close(1); while(r==-EINTR);
334 if(preclone_runs) if(!--preclone_runs) exit(0);//time to die
335 atomic_u8_set(preclones_states+preclone_slot,PRECLONE_AVAILABLE);
336 }
337
338 static void preclone_sigs_consume(void)
339 {
340 static struct signalfd_siginfo info;
341
342 while(1){
343 l r;
344 do r=read(4,&info,sizeof(info)); while(r==-EINTR);
345 if(r!=-EAGAIN&&(ISERR(r)||(r>0&&r!=sizeof(info)))){
346 PERR("FATAL:child:preclone:%d:error consuming signals (%ld)\n",
347 preclone_slot,r);
348 exit(-1);
349 }
350 if(r==0||r==-EAGAIN) break;
351
352 switch(info.ssi_signo){
353 case SIGTERM:
354 exit(0);
355 }
356 }
357 }
358
359 static void preclone_loop(void)
360 {
361 while(1){
362 static struct epoll_event evts[3];
363 l r;
364 do{
365 memset(evts,0,sizeof(evts));
366 r=epoll_wait(3,evts,3,-1);
367 }while(r==-EINTR);
368 if(ISERR(r)){
369 PERR("FATAL:child:preclone:%d:error epolling fds (%ld)\n",preclone_slot,
370 r);
371 exit(-1);
372 }
373 for(l j=0;j<r;++j)
374 if(evts[j].data.fd==4){
375 if(evts[j].events&EPOLLIN) preclone_sigs_consume();
376 else{
377 PERR("FATAL:child:preclone:%d:unknown epolling event on signal fd"
378 " n=%ld events=%u\n",preclone_slot,j,evts[j].events);
379 exit(-1);
380 }
381 }else if(evts[j].data.fd==5){
382 if(evts[j].events&(EPOLLERR|EPOLLHUP|EPOLLPRI)){
383 PERR("FATAL:child:preclone:%d:something wrong with parent socket"
384 " epolling n=%ld events=%u\n",preclone_slot,j,evts[j].events);
385 exit(-1);
386 }else if(evts[j].events&EPOLLIN){
387 preclone_cnx_do();
388 }else{
389 PERR("FATAL:child:preclone:%d:unknown epolling event on parent socket"
390 " n=%ld events=%u\n",preclone_slot,j,evts[j].events);
391 exit(-1);
392 }
393 }
394 }
395 }
396
397 static void preclone_setup(void)
398 {
399 if(preclone_parent_sock!=5){//moving parent socket fd to 5, if requiered
400 l r=dup2(preclone_parent_sock,5);
401 if(ISERR(r)){
402 PERR("FATAL:child:preclone:%d:unable to move parent socket fd (%ld)\n",
403 preclone_slot,r);
404 exit(-1);
405 }
406 do r=close(preclone_parent_sock); while(r==-EINTR);
407 }
408
409 preclone_sigs_setup();
410 preclone_epoll_setup();
411 memset(&msg,0,sizeof(msg));
412 }
413
414 static void preclone_entry(void)
415 {
416 preclone_setup();
417 atomic_u8_set(preclones_states+preclone_slot,PRECLONE_AVAILABLE);
418 preclone_loop();
419 }
420 //******************************************************************************
421
422 static void clone_spawn(void)
423 {
424 l r;
425 if(ps_n<ps_max){
426 r=clone(SIGCHLD,0,0,0,0);
427 if(ISERR(r)){
428 PERR("FATAL:error cloning %ld\n",r);
429 kill(0,SIGTERM);
430 exit(-1);
431 }
432 if(r==0) goto clone_entry_setup;
433
434 ++ps_n;
435 }
436 return;
437
438 clone_entry_setup:
439 do r=close(0); while(r==-EINTR);//for the connexion socket
440 do r=close(1); while(r==-EINTR);//for the connexion socket
441 //keep stderr
442
443 do r=close(sigs_fd); while(r==-EINTR);//don't care of parent signal
444 do r=close(epfd); while(r==-EINTR);//don't use parent epoll
445
446 clone_entry();
447 return;
448 }
449
450 static void preclone_ctl_socket(i sockets[2])
451 {
452 l r=socketpair(AF_UNIX,SOCK_DGRAM,0,sockets);
453 if(ISERR(r)){
454 PERR("FATAL:error creating preclone socket pair (%ld)\n",r);
455 kill(0,SIGTERM);
456 exit(-1);
457 }
458 }
459
460 static i preclone_spawn(s16 slot)
461 {
462 atomic_u8_set(preclones_states+slot,PRECLONE_BUSY);
463
464 i sockets[2];
465 preclone_ctl_socket(sockets);
466
467 l r=clone(SIGCHLD,0,0,0,0);
468 if(ISERR(r)){
469 PERR("FATAL:error precloning process slot %d with error %ld\n",slot,r);
470 return -1;
471 }
472 if(r==0) goto preclone_entry_setup;
473
474 preclones[slot].sock=sockets[1];
475 do r=close(sockets[0]); while(r==-EINTR);
476 preclones[slot].pid=(i)r;
477 return 0;
478
479 preclone_entry_setup:
480 preclone_slot=slot;
481 do r=close(sockets[1]); while(r==-EINTR);//close parent unix socket
482 preclone_parent_sock=sockets[0];
483
484 do r=close(0); while(r==-EINTR);//for the connexion socket
485 do r=close(1); while(r==-EINTR);//for the connexion socket
486 //keep stderr
487
488 do r=close(sigs_fd); while(r==-EINTR);//don't care of parent signal
489 do r=close(epfd); while(r==-EINTR);//don't use parent epoll
490
491 preclone_entry();
492 return -1;
493 }
494
495 static void sigs_setup(void)
496 {//synchronous treatement of signals with signalfd
497 //cannot change SIGKILL, neither SIGSTOP
498 ul mask=(~0);
499 l r=rt_sigprocmask(SIG_BLOCK,&mask,0,sizeof(mask));
500 if(ISERR(r)){
501 PERR("FATAL:error blocking mostly all signals (%ld)\n",r);
502 exit(-1);
503 }
504
505 mask=SIGBIT(SIGTERM)|SIGBIT(SIGCHLD);
506 sigs_fd=(i)signalfd4(-1,&mask,sizeof(mask),SFD_NONBLOCK);
507 if(ISERR(sigs_fd)){
508 PERR("FATAL:error setting up fd for signals (%d)\n",sigs_fd);
509 exit(-1);
510 }
511 }
512
513 static void mem_allocate(void)
514 {
515 if(!preclones_n) return;//nothing to allocate
516
517 l r=mmap(0,(preclones_n)*sizeof(&preclones),PROT_READ|PROT_WRITE,
518 MAP_PRIVATE|MAP_ANONYMOUS|MAP_POPULATE,0,0);
519 if(!r||ISERR(r)){
520 PERR("FATAL:unable to allocate children infos memory:%ld\n",r);
521 exit(-1);
522 }
523 preclones=(struct preclone *)r;
524
525 r=mmap(0,(preclones_n)*sizeof(&preclones_states),PROT_READ|PROT_WRITE,
526 MAP_SHARED|MAP_ANONYMOUS|MAP_POPULATE,0,0);
527 if(!r||ISERR(r)){
528 PERR("FATAL:unable to allocate children shared memory:%ld\n",r);
529 exit(-1);
530 }
531 preclones_states=(atomic_u8_t *)r;
532 for(s16 slot=0;slot<preclones_n;++slot)
533 atomic_u8_set(preclones_states+slot,PRECLONE_AVAILABLE);
534 }
535
536 static void srv_sock_create(void)
537 {
538 //TCP on IPv4... erk!
539 srv_sock=(i)socket(PF_INET,SOCK_STREAM|SOCK_NONBLOCK,0);
540 if(ISERR(srv_sock)){
541 PERR("FATAL:unable to create the server listening socket:%d\n",srv_sock);
542 kill(0,SIGTERM);
543 exit(-1);
544 }
545
546 l bool_true=1;
547 l r=setsockopt(srv_sock,SOL_SOCKET,SO_REUSEADDR,&bool_true,sizeof(bool_true));
548 if(ISERR(r)){
549 PERR("FATAL:unable to turn on socket rebinding option:%ld\n",r);
550 kill(0,SIGTERM);
551 exit(-1);
552 }
553
554 r=bind(srv_sock,&srv_addr,sizeof(srv_addr));
555 if(ISERR(r)){
556 PERR("FATAL:unable to bind address/port on server listening socket:%ld\n",r);
557 kill(0,SIGTERM);
558 exit(-1);
559 }
560
561 r=listen(srv_sock,0);
562 if(ISERR(r)){
563 PERR("FATAL:unable to flag server listening socket:%ld\n",r);
564 kill(0,SIGTERM);
565 exit(-1);
566 }
567 }
568
569 static void epoll_sigs_setup(void)
570 {
571 epfd=(i)epoll_create1(0);
572 if(ISERR(epfd)){
573 PERR("FATAL:unable to create epoll fd (%d)\n",epfd);
574 exit(-1);
575 }
576 struct epoll_event ep_evt;
577 memset(&ep_evt,0,sizeof(ep_evt));
578 ep_evt.events=EPOLLET|EPOLLIN;
579 ep_evt.data.fd=sigs_fd;
580 l r=epoll_ctl(epfd,EPOLL_CTL_ADD,sigs_fd,&ep_evt);
581 if(ISERR(r)){
582 PERR("FATAL:unable to register signal fd to epoll (%ld)\n",r);
583 exit(-1);
584 }
585 }
586
587 static void epoll_srv_sock_setup(void)
588 {
589 struct epoll_event ep_evt;
590 memset(&ep_evt,0,sizeof(ep_evt));
591 ep_evt.events=EPOLLIN|EPOLLPRI;
592 ep_evt.data.fd=srv_sock;
593 l r=epoll_ctl(epfd,EPOLL_CTL_ADD,srv_sock,&ep_evt);
594 if(ISERR(r)){
595 PERR("FATAL:unable to register server socket to epoll (%ld)\n",r);
596 kill(0,SIGTERM);
597 exit(-1);
598 }
599 }
600
601 static void preclones_spawn(void)
602 {
603 for(s16 slot=0;slot<preclones_n;++slot)
604 if(preclone_spawn(slot)<0){
605 kill(0,SIGTERM);
606 exit(-1);
607 }
608 }
609
610 static void setup(void)
611 {
612 mem_allocate();
613 sigs_setup();
614 epoll_sigs_setup();
615 preclones_spawn();
616 //from there, do not forget to kill the children (configured as no zombie)
617 srv_sock_create();
618 epoll_srv_sock_setup();
619 }
620
621 static void cmdline_options_allow_parse(void *list)
622 {
623 u8 *start=(u8*)list;
624 while(*start){
625 u8 *end=start;
626 while(*end&&*end!=',') ++end;
627 if(!str_2ipv4_blk((u32*)list+allow_n,start,end-1)){
628 PERR("FATAL:unable to convert IPv4 address from ascii to kernel format"
629 " (address n:%d)\n",allow_n+1);
630 exit(-1);
631 }
632 ++allow_n;
633 if(!*end) break;
634 start=end+1;
635 }
636 }
637
638 static void cmdline_options(l argc,void *argv[])
639 {
640 #define OPTION(string) strncmp(string,argv[j],sizeof(string)-1)==0
641 #define CHECK_ARG if(argc<=j+1){usage();exit(0);}
642
643 for(i j=1;j<argc;j+=2){
644 if(OPTION("-inet")){
645 CHECK_ARG
646
647 u64 len=0;
648 if(!strnlen(&len,argv[j+1],sizeof("xxx.xxx.xxx.xxx")-1)){
649 PERR("FATAL:invalid listening IPv4 address(size):%s\n",argv[j+1]);
650 exit(-1);
651 }
652 if(!str_2ipv4_blk((u32*)&srv_addr.sin_addr,argv[j+1],argv[j+1]+len-1)){
653 PERR("FATAL:invalid listening IPv4 address(format):%s\n",argv[j+1]);
654 exit(-1);
655 }
656 }else if(OPTION("-port")){
657 CHECK_ARG
658
659 if(!dec2u16(&srv_addr.sin_port,argv[j+1])){
660 PERR("FATAL:failed network port conversion:%s\n",argv[j+1]);
661 exit(-1);
662 }
663 srv_addr.sin_port=cpu2be16(srv_addr.sin_port);
664 }else if(OPTION("-psmax")){
665 CHECK_ARG
666
667 if(!dec2u16(&ps_max,argv[j+1])){
668 PERR("FATAL:failed maximum number of non precloned processes"
669 " conversion:%s\n",argv[j+1]);
670 exit(-1);
671 }
672 }else if(OPTION("-preclones")){
673 CHECK_ARG
674
675 u16 arg;
676 if(!dec2u16(&arg,argv[j+1])){
677 PERR("FATAL:failed number of precloned processes conversion:%s\n",
678 argv[j+1]);
679 exit(-1);
680 }
681 preclones_n=(s16)arg;
682 }else if(OPTION("-allows")){
683 CHECK_ARG
684
685 cmdline_options_allow_parse(argv[j+1]);
686 allows=(u32*)argv[j+1];
687 }else if(OPTION("-runs")){
688 CHECK_ARG
689
690 if(!dec2u16(&preclone_runs,argv[j+1])){
691 PERR("FATAL:failed number of runs conversion:%s\n",argv[j+1]);
692 exit(-1);
693 }
694 }else{//"-help"
695 usage();
696 exit(0);
697 }
698 }
699 }
700
701 static void sigchld(void)
702 {
703 while(1){
704 l r;
705 do r=wait4(-1,0,WNOHANG|WALL,0); while(r==-EINTR);
706 //ECHILD seems to means not even 1 child to wait for
707 if(r!=-ECHILD&&ISERR(r)){
708 PERR("FATAL:error waiting on dead children (%ld)\n",r);
709 kill(0,SIGTERM);
710 exit(-1);
711 }
712 if(r==0||r==-ECHILD) break;
713
714 s16 slot;
715 for(slot=0;slot<preclones_n;++slot) if(preclones[slot].pid==(i)r) break;
716
717 if(slot<preclones_n){
718 do r=close(preclones[slot].sock); while(r==-EINTR);
719 if(preclone_spawn(slot)<0){
720 kill(0,SIGTERM);
721 exit(-1);
722 }
723 }else ps_n--;//a not precloned process died
724 }
725 }
726
727 static void sigs_consume(void)
728 {
729 static struct signalfd_siginfo info;
730
731 while(1){
732 l r;
733 do{
734 memset(&info,0,sizeof(info));
735 r=read(sigs_fd,&info,sizeof(info));
736 }while(r==-EINTR);
737 if(r!=-EAGAIN&&((ISERR(r)||(r>0&&r!=sizeof(info))))){
738 PERR("FATAL:error consuming signals (%ld)\n",r);
739 kill(0,SIGTERM);
740 exit(-1);
741 }
742 if(r==0||r==-EAGAIN) break;
743
744 switch(info.ssi_signo){
745 case SIGCHLD:
746 sigchld();
747 break;
748 case SIGTERM:
749 kill(0,SIGTERM);
750 exit(0);
751 }
752 }
753 }
754
755 static void cnx_send(s16 slot)
756 {
757 cnx_sendrecv_setup();
758 *((i*)(CMSG_DATA(CMSG_FIRSTHDR(&msg))))=cnx_sock;
759
760 l r=sendmsg(preclones[slot].sock,&msg,0);
761 if(ISERR(r)){
762 PERR("FATAL:error sending connexion socket to preclone %d (%ld)\n",slot,r);
763 kill(0,SIGTERM);
764 exit(0);
765 }
766 }
767
768 static void cnx_dispatch(void)
769 {
770 s16 slot;
771 for(slot=0;slot<preclones_n;++slot)
772 if(atomic_u8_read(preclones_states+slot)==PRECLONE_AVAILABLE) break;
773
774 if(slot<preclones_n){
775 atomic_u8_set(preclones_states+slot,PRECLONE_BUSY);
776 cnx_send(slot);
777 }else clone_spawn();
778 l r;
779 do r=close(cnx_sock); while(r==-EINTR);
780 }
781
782 static u8 peer_is_allowed(u32 ipv4)
783 {
784 for(u32 j=0;j<allow_n;++j) if(allows[j]==ipv4) return 1;
785 return 0;
786 }
787
788 static void cnxs_consume(void)
789 {
790 while(1){
791 l r;
792 struct sockaddr_in peer;
793 l peer_len=sizeof(peer);
794 do r=accept(srv_sock,&peer,&peer_len); while(r==-EINTR||r==-ECONNABORTED);
795
796 if(r!=-EAGAIN&&ISERR(r)){//error
797 PERR("FATAL:error accepting connexion:%ld\n",r);
798 kill(0,SIGTERM);
799 exit(-1);
800 }
801 if(peer_len!=sizeof(peer)){
802 PERR("FATAL:error accepting connexion(socket address size):%ld\n",r);
803 kill(0,SIGTERM);
804 exit(-1);
805 }
806
807 if(r==-EAGAIN) break;//no more connexion pending
808
809 cnx_sock=(i)r;
810 if(allow_n){//allow filter is unabled if at least one address was provided
811 if(peer_is_allowed(peer.sin_addr.s_addr)) cnx_dispatch();
812 else do r=close(cnx_sock); while(r==-EINTR);
813 }else cnx_dispatch();
814 }
815 }
816
817 static void loop(void)
818 {
819 while(1){
820 static struct epoll_event evts[2];//sigs_fd and srv_sock
821 l r;
822 do{
823 memset(evts,0,sizeof(evts));
824 r=epoll_wait(epfd,evts,2,-1);
825 }while(r==-EINTR);
826 if(ISERR(r)){
827 PERR("FATAL:error epolling fds (%ld)\n",r);
828 kill(0,SIGTERM);
829 exit(-1);
830 }
831 for(l j=0;j<r;++j)
832 if(evts[j].data.fd==sigs_fd){
833 if(evts[j].events&EPOLLIN) sigs_consume();
834 else{
835 PERR("FATAL:something wrong with signal fd epolling n=%ld"
836 " events=%u\n",j,evts[j].events);
837 kill(0,SIGTERM);
838 exit(-1);
839 }
840 }else if(evts[j].data.fd==srv_sock){
841 if(evts[j].events&(EPOLLERR|EPOLLHUP|EPOLLPRI)){
842 PERR("FATAL:something wrong with server socket epolling n=%ld"
843 " events=%u\n",j,evts[j].events);
844 kill(0,SIGTERM);
845 exit(-1);
846 }else if(evts[j].events&EPOLLIN){
847 cnxs_consume();
848 }else{
849 PERR("FATAL:unknown epolling event on server socket n=%ld"
850 " events=%u\n",j,evts[j].events);
851 kill(0,SIGTERM);
852 exit(-1);
853 }
854 }
855 }
856 }
857
858 //*****************************************************************************
859 //XXX:may do the daemonic stuff if really we need it:logger instead of tty,
860 // own session...
861 void ulinux_start(l argc,void **argv)
862 {
863 u8 buf[DPRINTF_BUF_SZ];
864 dprintf_buf=&buf[0];
865
866 cmdline_options(argc,argv);
867 setup();
868 loop();
869 }
File ulinux/patterns/network_server/pre-fork_socket_unix_tcp/ulinux_namespace.h added (mode: 100644) (index 0000000..574be4a)
1 #ifndef ULINUX_NAMESPACE_H
2 #define ULINUX_NAMESPACE_H
3 #define sl ulinux_sl
4 #define si ulinux_si
5 #define ul ulinux_ul
6 #define u8 ulinux_u8
7 #define u16 ulinux_u16
8 #define s16 ulinux_s16
9 #define u32 ulinux_u32
10 #define u64 ulinux_u64
11 #define sockaddr_in ulinux_sockaddr_in
12 #define AF_INET ULINUX_AF_INET
13 #define INADDR_ANY ULINUX_INADDR_ANY
14 #define atomic_u8_t ulinux_atomic_u8_t
15 #define msg_hdr ulinux_msg_hdr
16 #define CMSG_SPACE ULINUX_CMSG_SPACE
17 #define EINTR ULINUX_EINTR
18 #define EAGAIN ULINUX_EAGAIN
19 #define memset ulinux_memset
20 #define SOL_SOCKET ULINUX_SOL_SOCKET
21 #define SCM_RIGHTS ULINUX_SCM_RIGHTS
22 #define CMSG_LEN ULINUX_CMSG_LEN
23 #define exit(a) ulinux_sysc(exit_group,1,a)
24 #define rt_sigprocmask(a,b,c,d) ulinux_sysc(rt_sigprocmask,4,a,b,c,d)
25 #define SIG_BLOCK ULINUX_SIG_BLOCK
26 #define ISERR ULINUX_ISERR
27 #define close(a) ulinux_sysc(close,1,a)
28 #define dup2(a,b) ulinux_sysc(dup2,2,a,b)
29 #define SIGTERM ULINUX_SIGTERM
30 #define signalfd4(a,b,c,d) ulinux_sysc(signalfd4,4,a,b,c,d)
31 #define SFD_NONBLOCK ULINUX_SFD_NONBLOCK
32 #define epoll_create1(a) ulinux_sysc(epoll_create1,1,a)
33 #define epoll_event ulinux_epoll_event
34 #define memset ulinux_memset
35 #define EPOLLET ULINUX_EPOLLET
36 #define EPOLLIN ULINUX_EPOLLIN
37 #define EPOLL_CTL_ADD ULINUX_EPOLL_CTL_ADD
38 #define EPOLLPRI ULINUX_EPOLLPRI
39 #define EPOLLERR ULINUX_EPOLLERR
40 #define EPOLLHUP ULINUX_EPOLLHUP
41 #define epoll_ctl(a,b,c,d) ulinux_sysc(epoll_ctl,4,a,b,c,d)
42 #define recvmsg(a,b,c) ulinux_sysc(recvmsg,3,a,b,c)
43 #define MSG_CTRUNC ULINUX_MSG_CTRUNC
44 #define CMSG_DATA ULINUX_CMSG_DATA
45 #define CMSG_FIRSTHDR ULINUX_CMSG_FIRSTHDR
46 #define atomic_u8_set ulinux_atomic_u8_set
47 #define signalfd_siginfo ulinux_signalfd_siginfo
48 #define read(a,b,c) ulinux_sysc(read,3,a,b,c)
49 #define epoll_event ulinux_epoll_event
50 #define epoll_wait(a,b,c,d) ulinux_sysc(epoll_wait,4,a,b,c,d)
51 #define clone(a,b,c,d,e) ulinux_sysc(clone,5,a,b,c,d,e)
52 #define SIGCHLD ULINUX_SIGCHLD
53 #define kill(a,b) ulinux_sysc(kill,2,a,b)
54 #define socketpair(a,b,c,d) ulinux_sysc(socketpair,4,a,b,c,d)
55 #define AF_UNIX ULINUX_AF_UNIX
56 #define SOCK_DGRAM ULINUX_SOCK_DGRAM
57 #define mmap(a,b,c,d,e,f) ulinux_sysc(mmap,6,a,b,c,d,e,f)
58 #define PROT_READ ULINUX_PROT_READ
59 #define PROT_WRITE ULINUX_PROT_WRITE
60 #define MAP_PRIVATE ULINUX_MAP_PRIVATE
61 #define MAP_ANONYMOUS ULINUX_MAP_ANONYMOUS
62 #define MAP_POPULATE ULINUX_MAP_POPULATE
63 #define MAP_SHARED ULINUX_MAP_SHARED
64 #define socket(a,b,c) ulinux_sysc(socket,3,a,b,c)
65 #define PF_INET ULINUX_PF_INET
66 #define setsockopt(a,b,c,d,e) ulinux_sysc(setsockopt,5,a,b,c,d,e)
67 #define SOL_SOCKET ULINUX_SOL_SOCKET
68 #define SO_REUSEADDR ULINUX_SO_REUSEADDR
69 #define bind(a,b,c) ulinux_sysc(bind,3,a,b,c)
70 #define listen(a,b) ulinux_sysc(listen,2,a,b)
71 #define str_2ipv4_blk ulinux_2ipv4_blk
72 #define strncmp ulinux_strncmp
73 #define strnlen ulinux_strnlen
74 #define dec2u16 ulinux_dec2u16
75 #define cpu2be16 ulinux_cpu2be16
76 #define wait4(a,b,c,d) ulinux_sysc(wait4,4,a,b,c,d)
77 #define WNOHANG ULINUX_WNOHANG
78 #define WALL ULINUX_WALL
79 #define ECHILD ULINUX_ECHILD
80 #define sendmsg(a,b,c) ulinux_sysc(sendmsg,3,a,b,c)
81 #define accept(a,b,c) ulinux_sysc(accept,3,a,b,c)
82 #define ECONNABORTED ULINUX_ECONNABORTED
83 #define SOCK_STREAM ULINUX_SOCK_STREAM
84 #define SOCK_NONBLOCK ULINUX_SOCK_NONBLOCK
85 #define atomic_u8_read ulinux_atomic_u8_read
86 #define cmsg_hdr ulinux_cmsg_hdr
87 #endif
File ulinux/patterns/network_server/pre-fork_socket_unix_tcp/x86_64_only added (mode: 100644) (index 0000000..6957433)
1 for x86 you must use the socketcall system call multiplexer
File ulinux/patterns/so/makefile added (mode: 100644) (index 0000000..140292c)
1 .PHONY:clean all help
2
3 #does remove some useless ELF sections
4 OPTIM=-fno-stack-protector -fno-asynchronous-unwind-tables -fno-dwarf2-cfi-asm \
5 -Ofast -march=native -fPIC
6
7 ARCH?=$(shell uname -m | sed -e s/i.86/x86/ -e s/parisc64/parisc/ \
8 -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/ -e s/sh.*/sh/)
9
10 help:
11 @echo "to test use command line:LD_LIBRARY_PATH=./ (you linux loader path)\
12 use_os"
13
14 all:so.so use_so
15
16 so.so:so.c ../../../ulinux/arch
17 cpp -Wall -Wextra -I../../.. ../../utils/mem.c -o cpp_mem.c
18 gcc -Wall -Wextra -std=gnu99 $(OPTIM) -c cpp_mem.c -o mem.o
19 cpp -Wall -Wextra -I../../.. ../../utils/ascii/string/vsprintf.c \
20 -o cpp_vsprintf.c
21 gcc -Wall -Wextra -std=gnu99 $(OPTIM) -c cpp_vsprintf.c -o vsprintf.o
22 cpp -Wall -Wextra -I../../.. so.c -o cpp_so.c
23 gcc -Wall -Wextra -std=gnu99 $(OPTIM) -c cpp_so.c -o so.o
24 ld -O -nostdlib -shared so.o string.o mem.o \
25 vsprintf.o $$(gcc -print-libgcc-file-name) --output so.so
26
27 use_so:use_so.c ../../../ulinux/arch
28 cpp -Wall -Wextra -I../../.. use_so.c -o cpp_use_so.c
29 gcc -Wall -Wextra -std=gnu99 $(OPTIM) -c cpp_use_so.c -o use_so.o
30 ld -O -nostdlib use_so.o so.so \
31 $$(gcc -print-libgcc-file-name) --output use_so
32
33 ../../../ulinux/arch:
34 ln -s archs/$(ARCH) ../../../ulinux/arch
35
36 clean:
37 -rm -f ../../../ulinux/arch
38 -rm -f cpp_so.c so.o so.so \
39 cpp_use_so.c use_so.o use_so \
40 cpp_mem.c mem.o \
41 cpp_vsprintf.c vsprintf.o
File ulinux/patterns/so/so.c added (mode: 100644) (index 0000000..6254539)
1 #define SO_C
2 #include <stdarg.h>
3 #include <ulinux/compiler_types.h>
4 #include <ulinux/sysc.h>
5 #include <ulinux/types.h>
6 #include <ulinux/utils/ascii/string/vsprintf.h>
7
8 //------------------------------------------------------------------------------
9 //ulinux namespace
10 #define EINTR ULINUX_EINTR
11 #define EAGAIN ULINUX_EAGAIN
12 #define si ulinux_si
13 #define u8 ulinux_u8
14 //------------------------------------------------------------------------------
15
16 #include "so.h"
17
18 #define POUT(fmt,...) ulinux_dprintf(1,dprintf_buf,DPRINTF_BUF_SZ,fmt,\
19 ##__VA_ARGS__)
20
21 #define POUTC(str) {l rl;do{rl=ulinux_sysc(write,3,1,str,sizeof(str));}\
22 while(rl==-EINTR||rl==-EAGAIN);}
23
24 i function_1(i a,i b)
25 {
26 POUT("function_1:%d,%d\n",a,b);
27 return 0;
28 }
29
30 i function_2(i a,i b)
31 {
32 POUT("function_2:%d,%d,%d\n",a,b,a+b);
33 return a-b;
34 }
File ulinux/patterns/so/so.h added (mode: 100644) (index 0000000..5c6a0ab)
1 #ifndef SO_H
2 #define SO_H
3 #define DPRINTF_BUF_SZ 1024
4 #ifdef SO_C
5 u8 *dprintf_buf;
6 #else
7 extern u8 *dprintf_buf;
8 #endif
9 extern i function_1(i a,i b);
10 extern i function_2(i a,i b);
11 #endif
File ulinux/patterns/so/use_so.c added (mode: 100644) (index 0000000..1c4cb2e)
1 #include <stdarg.h>
2 #include <ulinux/compiler_types.h>
3 #include <ulinux/sysc.h>
4 #include <ulinux/types.h>
5
6 //------------------------------------------------------------------------------
7 //ulinux namespace
8 #define EINTR ULINUX_EINTR
9 #define EAGAIN ULINUX_EAGAIN
10 #define si ulinux_si
11 #define u8 ulinux_u8
12 #define exit(a) ulinux_sysc(exit,1,a)
13 //------------------------------------------------------------------------------
14
15
16 #include "so.h"
17
18 void _start(void)
19 {
20 u8 buf[DPRINTF_BUF_SZ];
21 dprintf_buf=&buf[0];
22
23 function_1(1,2);
24 function_2(3,4);
25 exit(0);
26 }
File ulinux/patterns/start/make added (mode: 100755) (index 0000000..513d68c)
1 #!/bin/sh
2
3 set -e
4
5 ulinux_location=$(readlink -e ../../..)
6 build_dir=$(readlink -e .)
7 echo "ulinux_location=$ulinux_location"
8 echo "build_dir=$build_dir"
9
10 if test "$1" = "clean"; then
11 echo cleaning build products... in $build_dir
12
13 rm -f $build_dir/ulinux/arch
14 rmdir $build_dir/ulinux || true
15
16 rm -f $build_dir/mem.o
17 rm -f $build_dir/vsprintf.o
18 rm -f $build_dir/ulinux_start.o
19 rm -f $build_dir/start.o
20 rm -f $build_dir/start
21 exit 0;
22 fi
23
24 leaner_gcc_opts='-fno-stack-protector -fno-asynchronous-unwind-tables -fno-dwarf2-cfi-asm'
25 as="gcc -pipe -c"
26 cc="gcc -pipe -O0 -I. -I$ulinux_location -static-libgcc $leaner_gcc_opts"
27 ld="ld -O -nostdlib -Bstatic --strip-all $(gcc -print-libgcc-file-name)"
28 echo "cc=$cc"
29 echo "ld=$ld"
30
31 mkdir -p $build_dir/ulinux
32 ln -sTf $ulinux_location/ulinux/archs/x86_64 $build_dir/ulinux/arch
33
34 $as $ulinux_location/ulinux/start.S -o $build_dir/ulinux_start.o
35 $cc -c $ulinux_location/ulinux/utils/mem.c -o $build_dir/mem.o
36 $cc -c $ulinux_location/ulinux/utils/ascii/string/vsprintf.c \
37 -o $build_dir/vsprintf.o
38 $cc -c $build_dir/start.c -o $build_dir/start.o
39 $ld $build_dir/mem.o $build_dir/vsprintf.o $build_dir/ulinux_start.o \
40 $build_dir/start.o -o $build_dir/start
File ulinux/patterns/start/start.c added (mode: 100644) (index 0000000..d283be9)
1 /*
2 * COMMON ABBREVIATIONS:
3 * dyn : dynamic
4 * ehdr : Extended HeaDeR
5 * hdr : HeaDeR
6 * idx(s) : InDeX(S)
7 * phdr(s) : Program segment HeaDeR(S)
8 * ptr(s) : PoinTeR(S)
9 * seg(s): program SEGment(S)
10 * spec(s) : specification(s)
11 * tab(s) : TABLe(S)
12 * val(s) : VALue(S)
13 * rvaddr : Real Virual ADDRess
14 */
15 #include <stdarg.h>
16 #include <stdbool.h>
17
18 #include <ulinux/compiler_types.h>
19 #include <ulinux/types.h>
20 #include <ulinux/sysc.h>
21
22 #include <ulinux/compiler_misc.h>
23
24 #include <ulinux/start.h>
25 #include <ulinux/elf.h>
26
27 #include <ulinux/utils/ascii/string/vsprintf.h>
28
29 #define ul ulinux_ul
30 #define u8 ulinux_u8
31 #define u16 ulinux_u16
32 #define u32 ulinux_u32
33 #define u64 ulinux_u64
34 /* kill process, aka thread group */
35 #define exit(code) ulinux_sysc(exit_group,1,code)
36 #define elf64_auxv ulinux_elf64_auxv
37 #define AT_NULL ULINUX_AT_NULL
38 #define AT_SYSINFO_EHDR ULINUX_AT_SYSINFO_EHDR
39 /* elf tabs */
40 #define PT_LOAD ULINUX_PT_LOAD
41 #define PT_DYNAMIC ULINUX_PT_DYNAMIC
42 #define elf64_ehdr ulinux_elf64_ehdr
43 #define elf64_phdr ulinux_elf64_phdr
44 #define DT_NULL ULINUX_DT_NULL
45 #define DT_HASH ULINUX_DT_HASH
46 #define DT_STRTAB ULINUX_DT_STRTAB
47 #define DT_SYMTAB ULINUX_DT_SYMTAB
48 #define DT_VERSYM ULINUX_DT_VERSYM
49 #define DT_VERDEF ULINUX_DT_VERDEF
50 #define elf64_dyn ulinux_elf64_dyn
51 #define STN_UNDEF ULINUX_STN_UNDEF
52 #define elf64_sym ulinux_elf64_sym
53
54 /* convenience macros */
55 #define BUFSIZ 8192
56 static u8 dprint_buf[BUFSIZ];
57 #define POUT(fmt,...) ulinux_dprintf(1,&dprint_buf[0],BUFSIZ-1,fmt,##__VA_ARGS__)
58
59 #define loop for(;;)
60
61 #if BITS_PER_LONG != 64
62 #error "sorry, only elf64 code"
63 #endif
64
65 /*============================================================================*/
66 /* see linux_src/tools/testing/selftests/vDSO for reference parsing */
67
68 static u8 *vdso;
69 static u64 vdso_load_offset;
70 /*----------------------------------------------------------------------------*/
71 /* the following are the "dynamic" version elf sections */
72 static u32 *vdso_hash; /* hash hdr is 2 32 bits words */
73 static u32 *vdso_hash_buckets; /* 32 bits words, each one is a chain idx */
74 static u32 vdso_hash_buckets_n; /* first 32 bits word of the hdr */
75 static u32 *vdso_hash_chains; /* 32 bit words, each one is a symtab idxs */
76 static u32 vdso_hash_chains_n; /* second 32 bits word of the hdr */
77 /*----------------------------------------------------------------------------*/
78 /* the following are the "dynamic" version elf sections */
79 static u8 *vdso_strtab;
80 static struct elf64_sym *vdso_symtab;
81 static u8 *vdso_versym;
82 static u8 *vdso_verdef;
83
84 static void vdso_sym_dump(u32 idx)
85 {
86 POUT("dynamic symbol entry idx 0x%lx at 0x%p\n", idx, &vdso_symtab[idx]);
87 POUT("\tname=%s\n\n", vdso_strtab + vdso_symtab[idx].name);
88 }
89
90 static void vdso_hash_scan(void)
91 {
92 u32 bucket;
93 u32 chain;
94
95 POUT("----------------\n");
96 POUT("scanning hash table at 0x%p for dynamic symbols in dynamic section at 0x%p\n", vdso_hash, vdso_symtab);
97
98 bucket = 0;
99 chain = STN_UNDEF;
100 loop {
101 u32 chain;
102
103 if (bucket == vdso_hash_buckets_n)
104 break;
105 POUT("----\n");
106 POUT("bucket %lu:\n\n", bucket);
107
108 chain = vdso_hash_buckets[bucket];
109 loop {
110 if (chain == STN_UNDEF)
111 break;
112 /*
113 * the chain value is an index in the dynamic symbol
114 * table _AND_ the chain table as well
115 */
116 vdso_sym_dump(chain);
117
118 /* next in chain */
119 chain = vdso_hash_chains[chain];
120 }
121
122 ++bucket;
123 }
124 }
125
126 static void vdso_dyns(struct elf64_dyn *dyn)
127 {
128 POUT("----------------\n");
129 POUT("parsing dynamic elf section, or elf dynamic entries starting at 0x%p\n", dyn);
130
131 loop {
132 if (dyn->tag == DT_NULL) {
133 break;
134 } else if (dyn->tag == DT_STRTAB) {
135 POUT("found string table dynamic entry at vaddr 0x%lx\n", dyn->ptr);
136
137 vdso_strtab = (u8*)(dyn->ptr + vdso_load_offset);
138 } else if (dyn->tag == DT_SYMTAB) {
139 POUT("found symbol table dynamic entry at vaddr 0x%lx\n", dyn->ptr);
140
141 vdso_symtab = (struct elf64_sym*)(dyn->ptr
142 + vdso_load_offset);
143 } else if (dyn->tag == DT_VERSYM) {
144 POUT("found version symbol table dynamic entry at vaddr 0x%lx\n", dyn->ptr);
145 } else if (dyn->tag == DT_VERDEF) {
146 POUT("found version definition table dynamic entry at vaddr 0x%lx\n", dyn->ptr);
147 } else if (dyn->tag == DT_HASH) {
148
149 vdso_hash = (u32*)(dyn->ptr + vdso_load_offset);
150 vdso_hash_buckets_n = vdso_hash[0];
151 vdso_hash_chains_n = vdso_hash[1];
152 vdso_hash_buckets = &vdso_hash[2];
153 vdso_hash_chains =
154 &vdso_hash_buckets[vdso_hash_buckets_n];
155 POUT("found dynamic symbol hash at vaddr 0x%lx, %u buckets %u chains\n", dyn->ptr, vdso_hash_buckets_n, vdso_hash_chains_n);
156 } else {
157 POUT("found dynamic entry type 0x%x\n", dyn->tag);
158 }
159 ++dyn;
160 }
161
162 vdso_hash_scan();
163 }
164
165 /*
166 * the vdso is in a bastard ("PRE-LINKED") state. there is no rigorous
167 * definition. You have to follow what you get from the gnu linker script and
168 * how it is mapped in linux arch specific code. In glibc (2.29), you can find
169 * the castrated, but kind of generic, loading procedure in
170 * glibc_src/elf/setup-vdso.c
171 */
172 static void vdso_auxv(void)
173 {
174 struct elf64_ehdr *ehdr;
175 struct elf64_phdr *phdrs;
176 u16 i;
177 bool load_seg_found;
178 bool dyn_seg_found;
179 u64 dyns; /* will be the rvaddr of the "dynamic" elf section */
180
181 /* XXX: the vdso pointer is actually where the sole "load" elf program
182 * segment is mapped ("pre-linked"). from the gnu linker script
183 * we know we have the elf64 hdrs at the start of this memory map
184 * (should we have a "PHDRS" elf program segment? the gnu linker
185 * script does not do that at the time of writting for x86_64)
186 */
187 ehdr = (struct elf64_ehdr*)vdso;
188 POUT("parsing the vdso elf extended header at memory 0x%p for high performance system calls...\n", ehdr);
189 phdrs = (struct elf64_phdr*)(vdso + ehdr->phoff);
190
191 load_seg_found = false;
192 dyn_seg_found = false;
193 i = 0;
194 loop {
195 if (i == ehdr->phnum)
196 break;
197
198 /*
199 * XXX: only "load" elf program segments are actually mapped
200 * into memory. the elf program segments of other types are
201 * loaded into "load" elf program segments: they overlap.
202 * The "load" elf program segments are mapped in memory in
203 * ascending order (specs). the real vaddr of the first
204 * "load" elf program segment does matter.
205 */
206 if ((phdrs[i].type == PT_LOAD) && !load_seg_found) {
207 POUT("found first \"load\" program segment[%u]:\n", i);
208 POUT("\tfile offset=0x%lx\n", phdrs[i].offset);
209 POUT("\tfile size=0x%lx\n", phdrs[i].filesz);
210 POUT("\tvaddr=0x%lx\n", phdrs[i].vaddr);
211 POUT("\tmemory size=0x%lx\n", phdrs[i].memsz);
212 POUT("\tflags=0x%lx\n", phdrs[i].flags);
213 POUT("\talign=0x%lx\n", phdrs[i].align);
214
215 load_seg_found = true;
216
217 /*
218 * XXX: from the table vaddr to real vaddr:
219 * rvaddr = vaddr + offset
220 * then offset = rvaddr - vaddr
221 * the first "load" elf program segment was loaded at vdso.
222 * cheeky unsigned arithmetic (warp around)
223 */
224 vdso_load_offset = (u64)vdso - phdrs[i].vaddr;
225
226 } else if (phdrs[i].type == PT_DYNAMIC) {
227 /*
228 * XXX: the "dynamic" program segment, is already mapped
229 * into the sole and first "load" program segment. it
230 * contains the "dynamic" elf section, by ABI
231 * definition.
232 */
233 POUT("found \"dynamic\" program segment[%u]:\n", i);
234 POUT("\tfile offset=0x%lx\n", phdrs[i].offset);
235 POUT("\tfile size=0x%lx\n", phdrs[i].filesz);
236 POUT("\tvaddr=0x%lx\n", phdrs[i].vaddr);
237 POUT("\tmemory size=0x%lx\n", phdrs[i].memsz);
238 POUT("\tflags=0x%lx\n", phdrs[i].flags);
239 POUT("\talign=0x%lx\n", phdrs[i].align);
240
241 dyn_seg_found = true;
242
243 dyns = phdrs[i].vaddr;
244 } else {
245 POUT("found program segment[%u] type 0x%x\n", i, phdrs[i].type);
246 POUT("\tfile offset=0x%lx\n", phdrs[i].offset);
247 POUT("\tfile size=0x%lx\n", phdrs[i].filesz);
248 POUT("\tvaddr=0x%lx\n", phdrs[i].vaddr);
249 POUT("\tmemory size=0x%lx\n", phdrs[i].memsz);
250 POUT("\tflags=0x%lx\n", phdrs[i].flags);
251 POUT("\talign=0x%lx\n", phdrs[i].align);
252 }
253 ++i;
254 }
255
256 if (!load_seg_found) {
257 POUT("not load elf program segment found\n");
258 return;
259 }
260
261 if (!dyn_seg_found) {
262 POUT("not dynamic elf program segment, hence dynamic elf section, found\n");
263 return;
264 }
265
266 /* XXX: compute the rvaddr with the offset we now have */
267 dyns += vdso_load_offset;
268 vdso_dyns((struct elf64_dyn*)dyns);
269 }
270 /* vdso */
271 /*============================================================================*/
272
273 /* shows what arch ABIs, linux ABI, put on the initial stack */
274 void ulinux_start(u8 *stack)
275 {
276 ul *argc;
277 u8 **argv;
278 u8 **envp;
279 struct elf64_auxv *auxv;
280 ul arg_idx;
281
282 dprint_buf[BUFSIZ - 1] = 0; /* secure a 0 terminating char */
283
284 /* argc */
285 POUT("----------------\n");
286 argc = (ul*)stack;
287 POUT("argc=%lu\n", *argc);
288
289 /* skip argc */
290 stack += sizeof(*argc);
291
292 /* argv */
293 POUT("----------------\n");
294 argv = (u8**)stack;
295 arg_idx = 0;
296 loop {
297 if (*argv == 0)
298 break;
299 POUT("arg[%lu]=%s\n", arg_idx, *argv);
300 ++argv;
301 ++arg_idx;
302 }
303
304 /* skip ending 0 pointer */
305 ++argv;
306 stack = (u8*)argv;
307
308 /* envp */
309 POUT("----------------\n");
310 envp = (u8**)stack;
311 loop {
312 if (*envp == 0)
313 break;
314 POUT("envp:%s\n", *envp);
315 ++envp;
316 }
317
318 /* skip ending 0 pointer */
319 ++envp;
320 stack = (u8*)envp;
321
322 /* auxv */
323 POUT("----------------\n");
324 auxv = (struct elf64_auxv*)stack;
325 loop {
326 if (auxv->type == AT_NULL)
327 break;
328 POUT("auxv:0x%p:type=%lu:val=0x%lx", auxv, auxv->type, auxv->val);
329 if (auxv->type == AT_SYSINFO_EHDR) {
330 POUT(":VDSO\n");
331 vdso = (u8*)auxv->val;
332 } else
333 POUT("\n");
334 ++auxv;
335 }
336
337 /* vdso auxv, linux ABI specific */
338 POUT("----------------\n");
339 vdso_auxv();
340 exit(0);
341 }
File ulinux/patterns/thread/make added (mode: 100755) (index 0000000..2369565)
1 #!/bin/sh
2
3 set -e
4
5 ulinux_location=$(readlink -e ../../..)
6 build_dir=$(readlink -e .)
7 echo "ulinux_location=$ulinux_location"
8 echo "build_dir=$build_dir"
9
10 if test "$1" = "clean"; then
11 echo cleaning build products... in $build_dir
12
13 rm -f $build_dir/ulinux/arch
14 rmdir $build_dir/ulinux || true
15
16 rm -f $build_dir/mem.o
17 rm -f $build_dir/vsprintf.o
18 rm -f $build_dir/thread.o
19 rm -f $build_dir/thread
20 exit 0;
21 fi
22
23 leaner_gcc_opts='-fno-stack-protector -fno-asynchronous-unwind-tables -fno-dwarf2-cfi-asm'
24 cc="gcc -pipe -O2 -I. -I$ulinux_location -static-libgcc $leaner_gcc_opts"
25 ld="ld -O -nostdlib -Bstatic --strip-all $(gcc -print-libgcc-file-name)"
26 echo "cc=$cc"
27 echo "ld=$ld"
28
29 mkdir -p $build_dir/ulinux
30 # arch is hardcoded
31 ln -sTf $ulinux_location/ulinux/archs/x86_64 $build_dir/ulinux/arch
32
33 $cc -c $ulinux_location/ulinux/utils/mem.c -o $build_dir/mem.o
34 $cc -c $ulinux_location/ulinux/utils/ascii/string/vsprintf.c \
35 -o $build_dir/vsprintf.o
36 $cc -c $build_dir/thread.c -o $build_dir/thread.o
37 $ld $build_dir/mem.o $build_dir/vsprintf.o $build_dir/thread.o \
38 -o $build_dir/thread
File ulinux/patterns/thread/thread.c added (mode: 100644) (index 0000000..de974d0)
1 #include <stdarg.h>
2
3 #include <ulinux/compiler_types.h>
4 #include <ulinux/sysc.h>
5
6 #include <ulinux/types.h>
7 #include <ulinux/sched.h>
8 #include <ulinux/mmap.h>
9
10 #include <ulinux/utils/ascii/string/vsprintf.h>
11
12 /* ulinux namespace */
13 #define EINTR ULINUX_EINTR
14 #define EAGAIN ULINUX_EAGAIN
15 #define si ulinux_si
16 #define sl ulinux_sl
17 #define u8 ulinux_u8
18 #define exit(a) ulinux_sysc(exit,1,a)
19 #define mmap(a,b,c,d,e,f) ulinux_sysc(mmap,6,a,b,c,d,e,f)
20 #define RD ULINUX_PROT_READ
21 #define WR ULINUX_PROT_WRITE
22 #define PRIVATE ULINUX_MAP_PRIVATE
23 #define ANONYMOUS ULINUX_MAP_ANONYMOUS
24 #define GROWSDOWN ULINUX_MAP_GROWSDOWN
25 #define clone(a,b,c,d,e) ulinux_sysc(clone,5,a,b,c,d,e)
26 #define THREAD ULINUX_CLONE_THREAD
27 #define SIGHAND ULINUX_CLONE_SIGHAND
28 #define VM ULINUX_CLONE_VM
29 #define FILES ULINUX_CLONE_FILES
30 #define FS ULINUX_CLONE_FS
31 #define IO ULINUX_CLONE_IO
32 #define SYSVSEM ULINUX_CLONE_SYSVSEM
33 #define PAGE_SZ ULINUX_PAGE_SZ
34
35 #define loop for(;;)
36 #define STACK_SZ 512 * PAGE_SZ
37
38 #define BUFSIZ 8192
39 static u8 dprint_buf[BUFSIZ];
40 #define POUT(fmt,...) ulinux_dprintf(1, &dprint_buf[0], BUFSIZ - 1, fmt, ##__VA_ARGS__)
41
42 /*
43 * XXX: be carefull that this c++ cr*p which is now gcc don't optimize
44 * out/weirdly the thread entry function
45 */
46 static void thread_entry(void)
47 {
48 POUT("CHILD\n");
49 loop;
50 exit(0);
51 }
52
53 void _start(void)
54 {
55 sl r;
56 sl stack_map_bottom;
57 sl stack_map_top; /* 1 byte out of map */
58 sl stack_map_top_down_aligned;
59
60 dprint_buf[BUFSIZ - 1] = 0; /* secure a 0 terminating char */
61
62 stack_map_bottom = mmap(0, STACK_SZ, RD | WR, PRIVATE | ANONYMOUS
63 | GROWSDOWN, -1, 0);
64 stack_map_top = stack_map_bottom + STACK_SZ;
65
66 POUT("THREAD STACK MAP:0x%p-0x%p STACK_MAP_SZ=0x%x PAGE_SZ=0x%x\n",
67 stack_map_bottom, stack_map_top, STACK_SZ, PAGE_SZ);
68
69 /*
70 * we align DOWN on a 16 bytes boundary. Fits aarch64 and x86_64
71 * ("function stack frames" should be too)
72 */
73 if ((stack_map_top & 0xf) != 0)
74 stack_map_top_down_aligned = stack_map_top & (~0xf);
75 else
76 stack_map_top_down_aligned = (stack_map_top - 1) & (~0xf);
77 POUT("16 bytes aligned thread stack at 0x%p\n",
78 stack_map_top_down_aligned);
79
80 /*
81 * XXX: carefull, the order of the syscall args varies from arch to
82 * arch. If you create a process (namely without the VM flag), you
83 * don't need to provide a stack, just put 0 (copy-on-write)
84 */
85 r = clone(THREAD | SIGHAND | VM | FILES | FS | IO | SYSVSEM,
86 stack_map_top_down_aligned, 0, 0, 0);
87 if (r == 0)
88 thread_entry();
89 POUT("PARENT\n");
90 loop;
91 exit(0);
92 }
File ulinux/patterns/uevents_monitor/makefile added (mode: 100644) (index 0000000..6a3e2f2)
1 .PHONY:clean
2
3 #does remove some useless ELF sections
4 OPTIM=-fno-stack-protector -fno-asynchronous-unwind-tables -fno-dwarf2-cfi-asm \
5 -Ofast -march=native
6
7 ARCH?=$(shell uname -m | sed -e s/i.86/x86/ -e s/parisc64/parisc/ \
8 -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/ -e s/sh.*/sh/)
9
10 uevents_monitor:uevents_monitor.c ../../../ulinux/arch
11 cpp -Wall -Wextra -I../../.. ../../utils/mem.c -o cpp_mem.c
12 gcc -Wall -Wextra -std=gnu99 $(OPTIM) -c cpp_mem.c -o mem.o
13 cpp -Wall -Wextra -I../../.. ../../utils/ascii/string/vsprintf.c \
14 -o cpp_vsprintf.c
15 gcc -Wall -Wextra -std=gnu99 $(OPTIM) -c cpp_vsprintf.c -o vsprintf.o
16 cpp -Wall -Wextra -I../../.. uevents_monitor.c -o cpp_uevents_monitor.c
17 gcc -Wall -Wextra -std=gnu99 $(OPTIM) -c cpp_uevents_monitor.c \
18 -o uevents_monitor.o
19 ld -O -nostdlib -Bstatic --strip-all uevents_monitor.o string.o mem.o \
20 vsprintf.o $$(gcc -print-libgcc-file-name) \
21 --output uevents_monitor
22
23 ../../../ulinux/arch:
24 ln -s archs/$(ARCH) ../../../ulinux/arch
25
26 clean:
27 -rm -f ../../../ulinux/arch
28 -rm -f \
29 cpp_uevents_monitor.c uevents_monitor.o uevents_monitor \
30 cpp_mem.c mem.o \
31 cpp_vsprintf.c vsprintf.o
File ulinux/patterns/uevents_monitor/uevents_monitor.c added (mode: 100644) (index 0000000..855438d)
1 //******************************************************************************
2 //*this code is protected by the GNU affero GPLv3
3 //*author:Sylvain BERTRAND <sylvain.bertrand AT gmail dot com>
4 //* <digital.ragnarok AT gmail dot com>
5 //******************************************************************************
6 #include <stdarg.h>
7 #include <ulinux/compiler_types.h>
8 #include <ulinux/sysc.h>
9 #include <ulinux/types.h>
10 #include <ulinux/error.h>
11 #include <ulinux/file.h>
12 #include <ulinux/stat.h>
13 #include <ulinux/mmap.h>
14 #include <ulinux/time.h>
15 #include <ulinux/signal/signal.h>
16 #include <ulinux/socket/socket.h>
17 #include <ulinux/socket/msg.h>
18 #include <ulinux/socket/netlink.h>
19 #include <ulinux/epoll.h>
20 #include <ulinux/utils/ascii/string/vsprintf.h>
21 #include <ulinux/utils/mem.h>
22
23 //------------------------------------------------------------------------------
24 //ulinux namespace
25 #define EINTR ULINUX_EINTR
26 #define EAGAIN ULINUX_EAGAIN
27 #define si ulinux_si
28 #define sl ulinux_sl
29 #define u8 ulinux_u8
30 #define memset ulinux_memset
31 #define io_vec ulinux_io_vec
32 #define msg_hdr ulinux_msg_hdr
33 #define recvmsg(a,b,c) ulinux_sysc(recvmsg,3,a,b,c)
34 #define ISERR ULINUX_ISERR
35 #define MSG_TRUNC ULINUX_MSG_TRUNC
36 #define exit(code) ulinux_sysc(exit_group,1,code)
37 #define epoll_create1(a) ulinux_sysc(epoll_create1,1,a)
38 #define socket(a,b,c) ulinux_sysc(socket,3,a,b,c)
39 #define NETLINK ULINUX_PF_NETLINK
40 #define RAW ULINUX_SOCK_RAW
41 #define NONBLOCK ULINUX_SOCK_NONBLOCK
42 #define NETLINK_KOBJECT_UEVENT ULINUX_NETLINK_KOBJECT_UEVENT
43 #define setsockopt(a,b,c,d,e) ulinux_sysc(setsockopt,5,a,b,c,d,e)
44 #define SOL_SOCKET ULINUX_SOL_SOCKET
45 #define SO_RCVBUFFORCE ULINUX_SO_RCVBUFFORCE
46 #define sockaddr_nl ulinux_sockaddr_nl
47 #define AF_NETLINK ULINUX_AF_NETLINK
48 #define bind(a,b,c) ulinux_sysc(bind,3,a,b,c)
49 #define nanosleep(a,b) ulinux_sysc(nanosleep,2,a,b)
50 #define epoll_event ulinux_epoll_event
51 #define epoll_ctl(a,b,c,d) ulinux_sysc(epoll_ctl,4,a,b,c,d)
52 #define ADD ULINUX_EPOLL_CTL_ADD
53 #define epoll_wait(a,b,c,d) ulinux_sysc(epoll_wait,4,a,b,c,d)
54 #define IN ULINUX_EPOLLIN
55 #define timespec ulinux_timespec
56 //------------------------------------------------------------------------------
57
58 //XXX:what udev does in extra
59 // - it checks on socket credential
60 // - it checks the netlink sender is 0 (kernel)
61 // - it uses the socket filter
62
63 #define DPRINTF_BUF_SZ 1024
64 static u8 *g_dprintf_buf;
65 #define ERR(fmt,...) ulinux_dprintf(2,g_dprintf_buf,DPRINTF_BUF_SZ,\
66 fmt,##__VA_ARGS__)
67
68 #define ERRC(str) {l rl;do rl=ulinux_sysc(write,3,2,str,sizeof(str));\
69 while(rl==-EINTR||rl==-EAGAIN);}
70
71 static void uevent_rcv(i sock)
72 {
73 u8 buf[8192];
74 memset(buf,0,sizeof(buf));
75
76 struct io_vec io_vec;
77 io_vec.base=buf;
78 io_vec.len=sizeof(buf);
79
80 struct msg_hdr msg;
81 memset(&msg,0,sizeof(msg));
82 msg.iov=&io_vec;
83 msg.iov_len=1;
84
85 l r;
86 do r=recvmsg(sock,&msg,0); while(r==-EINTR);
87 if(ISERR(r)){
88 ERR("ERROR:unable to receive the uevent(%ld)\n",r);
89 exit(-1);
90 }
91 if(msg.flgs&MSG_TRUNC){
92 ERR("ERROR:the uevent was truncated(flags=0x%x)\n",msg.flgs);
93 exit(-1);
94 }
95 ERRC("uevent received:\n");
96 i len=r;
97 u8 *p=&buf[0];
98 while(len){
99 if(*p){ERR("%c",*p);}else{ERRC("\n")};
100 ++p;
101 len--;
102 }
103 ERRC("\n");
104 }
105
106 void _start(void)
107 {
108 static u8 dprintf_buf[DPRINTF_BUF_SZ];
109 g_dprintf_buf=&dprintf_buf[0];
110
111 //----------------------------------------------------------------------------
112
113 i ep_fd=(i)epoll_create1(0);
114 if(ISERR(ep_fd)){
115 ERR("ERROR:unable to create epoll fd (%d)\n",ep_fd);
116 exit(-1);
117 }
118
119 //----------------------------------------------------------------------------
120
121 i so=(i)socket(NETLINK,RAW|NONBLOCK,NETLINK_KOBJECT_UEVENT);
122 if(ISERR(so)){
123 ERR("ERROR:unable to uevent netlink socket:%d\n",so);
124 exit(-1);
125 }
126
127 //----------------------------------------------------------------------------
128
129 //why that big (stolen from udev)?
130 //moreover it can be skipped most of the time
131 //must be priviledged
132 i recv_buf_sz=128*1024*1024;
133 l r=setsockopt(so,SOL_SOCKET,SO_RCVBUFFORCE,&recv_buf_sz,sizeof(recv_buf_sz));
134 if(ISERR(r)){
135 ERR("ERROR:unable to force the size of the socket buffer (%ld)\n",r);
136 exit(-1);
137 }
138
139 //----------------------------------------------------------------------------
140
141 //uevent groups? only one: 1
142 struct sockaddr_nl addr={AF_NETLINK,0,0,1};
143 r=bind(so,&addr,sizeof(addr));
144 if(ISERR(r)){
145 ERR("ERROR:unable to bind address to uevent netlink socket:%ld\n",r);
146 exit(-1);
147 }
148
149 //----------------------------------------------------------------------------
150
151 struct timespec wanted={20,0};
152 struct timespec rem={0,0};
153 ERRC("sleeping 20 sec (buffering)...\n");
154 r=nanosleep(&wanted,&rem);
155 if(r==-EINTR){
156 ERR("WARNING:sleep was interruped. Remainder %ld sec/%ld nsec\n",rem.sec,
157 rem.nsec);
158 }else if(ISERR(r)){
159 ERR("ERROR:sleeping:%ld\n",r);
160 exit(-1);
161 }
162 ERRC("done\n");
163
164 //----------------------------------------------------------------------------
165
166 struct epoll_event ep_evt;
167 memset(&ep_evt,0,sizeof(ep_evt));
168 ep_evt.events=IN;
169 ep_evt.data.fd=so;
170 r=epoll_ctl(ep_fd,ADD,so,&ep_evt);
171 if(ISERR(r)){
172 ERR("ERROR:unable to register uevent netlink socket to epoll (%ld)\n",r);
173 exit(-1);
174 }
175
176 //----------------------------------------------------------------------------
177
178 while(1){
179 static struct epoll_event evts[1];//uevent netlink event
180 do{
181 memset(evts,0,sizeof(evts));
182 r=epoll_wait(ep_fd,evts,1,-1);
183 }while(r==-EINTR);
184 if(ISERR(r)){
185 ERR("ERROR:error epolling fds (%ld)\n",r);
186 exit(-1);
187 }
188
189 l j=0;
190 while(1){
191 if(j>=r) break;
192 if(evts[j].data.fd==so){
193 if(evts[j].events&IN){
194 uevent_rcv(so);
195 }else{
196 ERR("ERROR:unmanaged epolling event on uevent netlink socket"
197 " n=%ld events=%u\n",j,evts[j].events);
198 exit(-1);
199 }
200 }
201 ++j;
202 }
203 }
204 exit(0);
205 }
File ulinux/patterns/uevents_monitor/x86_64_only added (mode: 100644) (index 0000000..dc2abc7)
1 on x86 you must use the socketcall system call multiplexer
File ulinux/patterns/vdso/make added (mode: 100755) (index 0000000..cb2504b)
1 #!/bin/sh
2
3 set -e
4
5 ulinux_location=$(readlink -e ../../..)
6 build_dir=$(readlink -e .)
7 echo "ulinux_location=$ulinux_location"
8 echo "build_dir=$build_dir"
9
10 if test "$1" = "clean"; then
11 echo cleaning build products... in $build_dir
12
13 rm -f $build_dir/ulinux/arch
14 rmdir $build_dir/ulinux || true
15
16 rm -f $build_dir/mem.o
17 rm -f $build_dir/vsprintf.o
18 rm -f $build_dir/ulinux_start.o
19 rm -f $build_dir/vdso.o
20 rm -f $build_dir/vdso
21 exit 0;
22 fi
23
24 leaner_gcc_opts='-fno-stack-protector -fno-asynchronous-unwind-tables -fno-dwarf2-cfi-asm'
25 as="gcc -pipe -c"
26 cc="gcc -pipe -O0 -I. -I$ulinux_location -static-libgcc $leaner_gcc_opts"
27 ld="ld -O -nostdlib -Bstatic --strip-all $(gcc -print-libgcc-file-name)"
28 echo "cc=$cc"
29 echo "ld=$ld"
30
31 mkdir -p $build_dir/ulinux
32 ln -sTf $ulinux_location/ulinux/archs/x86_64 $build_dir/ulinux/arch
33
34 $as $ulinux_location/ulinux/start.S -o $build_dir/ulinux_start.o
35 $cc -c $ulinux_location/ulinux/utils/mem.c -o $build_dir/mem.o
36 $cc -c $ulinux_location/ulinux/utils/ascii/string/vsprintf.c \
37 -o $build_dir/vsprintf.o
38 $cc -c $build_dir/vdso.c -o $build_dir/vdso.o
39 $ld $build_dir/mem.o $build_dir/vsprintf.o $build_dir/ulinux_start.o \
40 $build_dir/vdso.o -o $build_dir/vdso
File ulinux/patterns/vdso/vdso.c added (mode: 100644) (index 0000000..13a3eb8)
1 /* see the start pattern */
2 /*
3 * COMMON ABBREVIATIONS:
4 * dyn : dynamic
5 * ehdr : Extended HeaDeR
6 * hdr : HeaDeR
7 * idx(s) : InDeX(S)
8 * phdr(s) : Program segment HeaDeR(S)
9 * ptr(s) : PoinTeR(S)
10 * seg(s): program SEGment(S)
11 * spec(s) : specification(s)
12 * tab(s) : TABLe(S)
13 * val(s) : VALue(S)
14 * rvaddr : Real Virual ADDRess
15 */
16 #include <stdarg.h>
17 #include <stdbool.h>
18
19 #include <ulinux/compiler_types.h>
20 #include <ulinux/types.h>
21 #include <ulinux/sysc.h>
22
23 #include <ulinux/compiler_misc.h>
24
25 #include <ulinux/error.h>
26
27 #include <ulinux/start.h>
28 #include <ulinux/elf.h>
29
30 #include <ulinux/utils/mem.h>
31 #include <ulinux/utils/ascii/string/string.h>
32 #include <ulinux/utils/ascii/string/vsprintf.h>
33
34 #include <ulinux/file.h>
35 #include <ulinux/time.h>
36
37 #define ui ulinux_ui
38 #define si ulinux_si
39 #define ul ulinux_ul
40 #define sl ulinux_sl
41 #define u8 ulinux_u8
42 #define u16 ulinux_u16
43 #define u32 ulinux_u32
44 #define u64 ulinux_u64
45 /* kill process, aka thread group */
46 #define exit(code) ulinux_sysc(exit_group,1,code)
47 #define elf64_auxv ulinux_elf64_auxv
48 #define AT_NULL ULINUX_AT_NULL
49 #define AT_SYSINFO_EHDR ULINUX_AT_SYSINFO_EHDR
50 #define strcmp(a,b) ulinux_strcmp((u8*)a,(u8*)b)
51 #define ISERR ULINUX_ISERR
52 #define CLOCK_MONOTONIC_RAW ULINUX_CLOCK_MONOTONIC_RAW
53 #define timespec ulinux_timespec
54 /* elf tabs */
55 #define PT_LOAD ULINUX_PT_LOAD
56 #define PT_DYNAMIC ULINUX_PT_DYNAMIC
57 #define elf64_ehdr ulinux_elf64_ehdr
58 #define elf64_phdr ulinux_elf64_phdr
59 #define DT_NULL ULINUX_DT_NULL
60 #define DT_HASH ULINUX_DT_HASH
61 #define DT_STRTAB ULINUX_DT_STRTAB
62 #define DT_SYMTAB ULINUX_DT_SYMTAB
63 #define DT_VERSYM ULINUX_DT_VERSYM
64 #define DT_VERDEF ULINUX_DT_VERDEF
65 #define elf64_dyn ulinux_elf64_dyn
66 #define STN_UNDEF ULINUX_STN_UNDEF
67 #define elf64_sym ulinux_elf64_sym
68
69 /* convenience macros */
70 #define BUFSIZ 8192
71 static u8 dprint_buf[BUFSIZ];
72 #define POUT(fmt,...) ulinux_dprintf(1,&dprint_buf[0],BUFSIZ-1,fmt,##__VA_ARGS__)
73
74 #define loop for(;;)
75
76 #if BITS_PER_LONG != 64
77 #error "sorry, only elf64 code"
78 #endif
79
80 /*----------------------------------------------------------------------------*/
81 /* vdso getcpu */
82 struct getcpu_cache {/* dummy */};
83 static sl (*getcpu)(ui *cpu, ui *node, struct getcpu_cache *tcache);
84 #define VDSO_GETCPU_CAST(x) (sl(*)(ui *cpu, ui *node, struct getcpu_cache *tcache))(x)
85 #define VDSO_GETCPU_SYM "__vdso_getcpu"
86 /*----------------------------------------------------------------------------*/
87
88
89 /*----------------------------------------------------------------------------*/
90 /* vdso clock_gettime */
91 static sl (*clock_gettime)(si clock_id, struct timespec *timespec);
92 #define VDSO_CLOCK_GETTIME_CAST(x) (sl (*)(si clock_id, struct timespec *timespec))(x)
93 #define VDSO_CLOCK_GETTIME_SYM "__vdso_clock_gettime"
94 /*----------------------------------------------------------------------------*/
95
96
97 /*============================================================================*/
98 static u8 *vdso;
99 static u64 vdso_load_offset;
100 /*----------------------------------------------------------------------------*/
101 /* the following are the "dynamic" version elf sections */
102 static u32 *vdso_hash; /* hash hdr is 2 32 bits words */
103 static u32 *vdso_hash_buckets; /* 32 bits words, each one is a chain idx */
104 static u32 vdso_hash_buckets_n; /* first 32 bits word of the hdr */
105 static u32 *vdso_hash_chains; /* 32 bit words, each one is a symtab idxs */
106 static u32 vdso_hash_chains_n; /* second 32 bits word of the hdr */
107 /*----------------------------------------------------------------------------*/
108 /* the following are the "dynamic" version elf sections */
109 static u8 *vdso_strtab;
110 static struct elf64_sym *vdso_symtab;
111 static u8 *vdso_versym;
112 static u8 *vdso_verdef;
113 /*----------------------------------------------------------------------------*/
114
115 static void vdso_sym_select(u32 idx)
116 {
117 if (strcmp(vdso_strtab + vdso_symtab[idx].name, VDSO_GETCPU_SYM) == 0) {
118 getcpu = VDSO_GETCPU_CAST(vdso_symtab[idx].value
119 + vdso_load_offset);
120 POUT("getcpu found at 0x%p\n", getcpu);
121 return;
122 }
123
124 if (strcmp(vdso_strtab + vdso_symtab[idx].name, VDSO_CLOCK_GETTIME_SYM)
125 == 0) {
126 clock_gettime = VDSO_CLOCK_GETTIME_CAST(vdso_symtab[idx].value
127 + vdso_load_offset);
128 POUT("clock_gettime found at 0x%p\n", clock_gettime);
129 return;
130 }
131 }
132
133 static void vdso_hash_scan(void)
134 {
135 u32 bucket;
136 u32 chain;
137
138 bucket = 0;
139 chain = STN_UNDEF;
140 loop {
141 u32 chain;
142
143 if (bucket == vdso_hash_buckets_n)
144 break;
145
146 chain = vdso_hash_buckets[bucket];
147 loop {
148 if (chain == STN_UNDEF)
149 break;
150 vdso_sym_select(chain);
151
152 /* next in chain */
153 chain = vdso_hash_chains[chain];
154 }
155
156 ++bucket;
157 }
158 }
159
160 static void vdso_dyns(struct elf64_dyn *dyn)
161 {
162 loop {
163 if (dyn->tag == DT_NULL) {
164 break;
165 } else if (dyn->tag == DT_STRTAB) {
166 vdso_strtab = (u8*)(dyn->ptr + vdso_load_offset);
167 } else if (dyn->tag == DT_SYMTAB) {
168 vdso_symtab = (struct elf64_sym*)(dyn->ptr
169 + vdso_load_offset);
170 } else if (dyn->tag == DT_HASH) {
171 vdso_hash = (u32*)(dyn->ptr + vdso_load_offset);
172 vdso_hash_buckets_n = vdso_hash[0];
173 vdso_hash_chains_n = vdso_hash[1];
174 vdso_hash_buckets = &vdso_hash[2];
175 vdso_hash_chains =
176 &vdso_hash_buckets[vdso_hash_buckets_n];
177 }
178 ++dyn;
179 }
180 vdso_hash_scan();
181 }
182
183 static void vdso_auxv(void)
184 {
185 struct elf64_ehdr *ehdr;
186 struct elf64_phdr *phdrs;
187 u16 i;
188 bool load_seg_found;
189 bool dyn_seg_found;
190 u64 dyns;
191
192 ehdr = (struct elf64_ehdr*)vdso;
193 phdrs = (struct elf64_phdr*)(vdso + ehdr->phoff);
194
195 load_seg_found = false;
196 dyn_seg_found = false;
197 i = 0;
198 loop {
199 if (i == ehdr->phnum)
200 break;
201
202 if ((phdrs[i].type == PT_LOAD) && !load_seg_found) {
203 load_seg_found = true;
204 vdso_load_offset = (u64)vdso - phdrs[i].vaddr;
205
206 } else if (phdrs[i].type == PT_DYNAMIC) {
207 dyn_seg_found = true;
208
209 dyns = phdrs[i].vaddr;
210 }
211 ++i;
212 }
213
214 if (!load_seg_found) {
215 POUT("not load elf program segment found\n");
216 return;
217 }
218
219 if (!dyn_seg_found) {
220 POUT("not dynamic elf program segment, hence dynamic elf section, found\n");
221 return;
222 }
223
224 /* XXX: compute the rvaddr with the offset we now have */
225 dyns += vdso_load_offset;
226 vdso_dyns((struct elf64_dyn*)dyns);
227 }
228 /* vdso */
229 /*============================================================================*/
230
231 /* shows what arch ABIs, linux ABI, put on the initial stack */
232 void ulinux_start(u8 *stack)
233 {
234 ul *argc;
235 u8 **argv;
236 u8 **envp;
237 struct elf64_auxv *auxv;
238 ul arg_idx;
239
240 dprint_buf[BUFSIZ - 1] = 0; /* secure a 0 terminating char */
241 getcpu = 0;
242
243 /*--------------------------------------------------------------------*/
244
245 /* skip argc */
246 argc = (ul*)stack;
247 stack += sizeof(*argc);
248
249 /*--------------------------------------------------------------------*/
250
251 /* skik argv, the slow way */
252 argv = (u8**)stack;
253 arg_idx = 0;
254 loop {
255 if (*argv == 0)
256 break;
257 ++argv;
258 ++arg_idx;
259 }
260
261 /* skip ending 0 pointer */
262 ++argv;
263 stack = (u8*)argv;
264
265 /*--------------------------------------------------------------------*/
266
267 /* skip envp */
268 envp = (u8**)stack;
269 loop {
270 if (*envp == 0)
271 break;
272 ++envp;
273 }
274
275 /* skip ending 0 pointer */
276 ++envp;
277 stack = (u8*)envp;
278
279 /*--------------------------------------------------------------------*/
280
281 /* parse auxv */
282 auxv = (struct elf64_auxv*)stack;
283 loop {
284 if (auxv->type == AT_NULL)
285 break;
286 if (auxv->type == AT_SYSINFO_EHDR) {
287 vdso = (u8*)auxv->val;
288 }
289 ++auxv;
290 }
291
292 /* vdso auxv, linux ABI specific */
293 vdso_auxv();
294
295 /*====================================================================*/
296
297 /* high performance vdso calls */
298
299 if (getcpu != 0) {
300 sl r;
301 ui cpu;
302 ui node;
303
304 r = getcpu(&cpu, &node, 0);
305 if (ISERR(r))
306 POUT("error while calling vdso getcpu\n");
307 else
308 POUT("getcpu:cpu=%u;node=%u\n", cpu, node);
309 }
310
311 if (clock_gettime != 0) {
312 sl r;
313 struct timespec timespec;
314
315 r = clock_gettime(CLOCK_MONOTONIC_RAW, &timespec);
316 if (ISERR(r))
317 POUT("error while calling vdso clock_gettime\n");
318 else
319 POUT("clock_gettime:sec=%lu:nsec=%lu\n", timespec.sec, timespec.nsec);
320 }
321 exit(0);
322 }
File ulinux/sched.h added (mode: 100644) (index 0000000..e05c08c)
1 #ifndef ULINUX_SCHED_H
2 #define ULINUX_SCHED_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7
8 /* signal mask to be sent at exit */
9 #define ULINUX_CSIGNAL 0x000000ff
10 /* set if vm shared between processes */
11 #define ULINUX_CLONE_VM 0x00000100
12 /* set if fs info shared between processes */
13 #define ULINUX_CLONE_FS 0x00000200
14 /* set if open files shared between processes */
15 #define ULINUX_CLONE_FILES 0x00000400
16 /* set if signal handlers and blocked signals shared */
17 #define ULINUX_CLONE_SIGHAND 0x00000800
18 /* set if we want to let tracing continue on the child too */
19 #define ULINUX_CLONE_PTRACE 0x00002000
20 /* set if the parent wants the child to wake it up on mm_release */
21 #define ULINUX_CLONE_VFORK 0x00004000
22 /* set if we want to have the same parent as the cloner */
23 #define ULINUX_CLONE_PARENT 0x00008000
24 /* same thread group? */
25 #define ULINUX_CLONE_THREAD 0x00010000
26 /* new namespace group? */
27 #define ULINUX_CLONE_NEWNS 0x00020000
28 /* share system v sem_undo semantics */
29 #define ULINUX_CLONE_SYSVSEM 0x00040000
30 /* create a new tls for the child */
31 #define ULINUX_CLONE_SETTLS 0x00080000
32 /* set the tid in the parent */
33 #define ULINUX_CLONE_PARENT_SETTID 0x00100000
34 /* clear the tid in the child */
35 #define ULINUX_CLONE_CHILD_CLEARTID 0x00200000
36 /* unused, ignored */
37 #define ULINUX_CLONE_DETACHED 0x00400000
38 /* set if the tracing process can't force clone_ptrace on this clone */
39 #define ULINUX_CLONE_UNTRACED 0x00800000
40 /* set the tid in the child */
41 #define ULINUX_CLONE_CHILD_SETTID 0x01000000
42 /*
43 * 0x0200000 was previously the unused clone_stopped (start in stopped state)
44 * and isnow available for re-use.
45 */
46 /* new utsname group? */
47 #define ULINUX_CLONE_NEWUTS 0x04000000
48 /* new ipcs */
49 #define ULINUX_CLONE_NEWIPC 0x08000000
50 /* new user namespace */
51 #define ULINUX_CLONE_NEWUSER 0x10000000
52 /* new pid namespace */
53 #define ULINUX_CLONE_NEWPID 0x20000000
54 /* new network namespace */
55 #define ULINUX_CLONE_NEWNET 0x40000000
56 /* clone io context */
57 #define ULINUX_CLONE_IO 0x80000000
58 #endif
File ulinux/select.h added (mode: 100644) (index 0000000..9d0993c)
1 #ifndef ULINUX_SELECT_H
2 #define ULINUX_SELECT_H
3 /*******************************************************************************
4 this code is protected by the GNU affero GPLv3
5 author:Sylvain BERTRAND (sylvain.bertrand AT gmail dot com)
6 *******************************************************************************/
7 /* array of 1024 bits split in uls */
8 #define ULINUX_FD_SET_ULS_N (1024 / (8 * sizeof(ulinux_ul)))
9 #endif
File ulinux/signal/handler.h added (mode: 100644) (index 0000000..06ec83a)
1 /*
2 * this code is protected by the GNU affero GPLv3
3 * author:Sylvain BERTRAND
4 */
5 #ifndef ULINUX_SIGNAL_HANDLER_H
6 #define ULINUX_SIGNAL_HANDLER_H
7 struct ulinux_sigaction {
8 void *ulinux_sa_handler;
9 ulinux_ul sa_flags;
10 void (*sa_restorer)(void);
11 ulinux_ul sa_mask;
12 };
13 #include <ulinux/arch/signal/handler.h>
14 #endif
File ulinux/signal/siginfo.h added (mode: 100644) (index 0000000..552440c)
1 #ifndef ULINUX_SIGNAL_SIGINFO
2 #define ULINUX_SIGNAL_SIGINFO
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 #include <ulinux/arch/signal/siginfo.h>
8 #endif
File ulinux/signal/signal.h added (mode: 100644) (index 0000000..8e42aad)
1 #ifndef ULINUX_SIGNAL_SIGNAL_H
2 #define ULINUX_SIGNAL_SIGNAL_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 #include <ulinux/arch/signal/signal.h>
8 /*
9 * In POSIX a signal is sent either to a specific thread (Linux task)
10 * or to the process as a whole (Linux thread group). How the signal
11 * is sent determines whether it's to one thread or the whole group,
12 * which determines which signal mask(s) are involved in blocking it
13 * from being delivered until later. When the signal is delivered,
14 * either it's caught or ignored by a user handler or it has a default
15 * effect that applies to the whole thread group (POSIX process).
16 *
17 * The possible effects an unblocked signal set to SIG_DFL can have are:
18 * ignore - Nothing Happens
19 * terminate - kill the process, i.e. all threads in the group,
20 * similar to exit_group. The group leader (only) reports
21 * WIFSIGNALED status to its parent.
22 * coredump - write a core dump file describing all threads using
23 * the same mm and then kill all those threads
24 * stop - stop all the threads in the group, i.e. TASK_STOPPED state
25 *
26 * SIGKILL and SIGSTOP cannot be caught, blocked, or ignored.
27 * Other signals when not blocked and set to SIG_DFL behaves as follows.
28 * The job control signals also have other special effects.
29 *
30 * +--------------------+------------------+
31 * | POSIX signal | default action |
32 * +--------------------+------------------+
33 * | SIGHUP | terminate |
34 * | SIGINT | terminate |
35 * | SIGQUIT | coredump |
36 * | SIGILL | coredump |
37 * | SIGTRAP | coredump |
38 * | SIGABRT/SIGIOT | coredump |
39 * | SIGBUS | coredump |
40 * | SIGFPE | coredump |
41 * | SIGKILL | terminate(+) |
42 * | SIGUSR1 | terminate |
43 * | SIGSEGV | coredump |
44 * | SIGUSR2 | terminate |
45 * | SIGPIPE | terminate |
46 * | SIGALRM | terminate |
47 * | SIGTERM | terminate |
48 * | SIGCHLD | ignore |
49 * | SIGCONT | ignore(*) |
50 * | SIGSTOP | stop(*)(+) |
51 * | SIGTSTP | stop(*) |
52 * | SIGTTIN | stop(*) |
53 * | SIGTTOU | stop(*) |
54 * | SIGURG | ignore |
55 * | SIGXCPU | coredump |
56 * | SIGXFSZ | coredump |
57 * | SIGVTALRM | terminate |
58 * | SIGPROF | terminate |
59 * | SIGPOLL/SIGIO | terminate |
60 * | SIGSYS/SIGUNUSED | coredump |
61 * | SIGSTKFLT | terminate |
62 * | SIGWINCH | ignore |
63 * | SIGPWR | terminate |
64 * | SIGRTMIN-SIGRTMAX | terminate |
65 * +--------------------+------------------+
66 * | non-POSIX signal | default action |
67 * +--------------------+------------------+
68 * | SIGEMT | coredump |
69 * +--------------------+------------------+
70 *
71 * (+) For SIGKILL and SIGSTOP the action is "always", not just "default".
72 * (*) Special job control effects:
73 * When SIGCONT is sent, it resumes the process (all threads in the group)
74 * from TASK_STOPPED state and also clears any pending/queued stop signals
75 * (any of those marked with "stop(*)"). This happens regardless of blocking,
76 * catching, or ignoring SIGCONT. When any stop signal is sent, it clears
77 * any pending/queued SIGCONT signals; this happens regardless of blocking,
78 * catching, or ignored the stop signal, though (except for SIGSTOP) the
79 * default action of stopping the process may happen later or never.
80 */
81
82 #define ULINUX_SIG_BLOCK 0 /* for blocking signals */
83 #define ULINUX_SIG_UNBLOCK 1 /* for unblocking signals */
84 #define ULINUX_SIG_SETMASK 2 /* for setting the signal mask */
85
86
87 /*----------------------------------------------------------------------------*/
88 /* signalfd */
89 #ifndef ULINUX_O_NONBLOCK
90 #error "missing definition of ULINUX_O_NONBLOCK"
91 #endif
92 #define ULINUX_SFD_NONBLOCK ULINUX_O_NONBLOCK
93 #ifndef ULINUX_O_CLOEXEC
94 #error "missing definition of ULINUX_O_CLOEXEC"
95 #endif
96 #define ULINUX_SFD_CLOEXEC ULINUX_O_CLOEXEC
97
98 /* user siginfo stuff */
99 struct ulinux_signalfd_siginfo {
100 ulinux_u32 ssi_signo;
101 ulinux_s32 ssi_errno;
102 ulinux_s32 ssi_code;
103 ulinux_u32 ssi_pid;
104 ulinux_u32 ssi_uid;
105 ulinux_s32 ssi_fd;
106 ulinux_u32 ssi_tid;
107 ulinux_u32 ssi_band;
108 ulinux_u32 ssi_overrun;
109 ulinux_u32 ssi_trapno;
110 ulinux_s32 ssi_status;
111 ulinux_s32 ssi_int;
112 ulinux_u64 ssi_ptr;
113 ulinux_u64 ssi_utime;
114 ulinux_u64 ssi_stime;
115 ulinux_u64 ssi_addr;
116 ulinux_u16 ssi_addr_lsb;
117 ulinux_u16 __pad2;
118 ulinux_s32 ssi_syscall;
119 ulinux_u64 ssi_call_addr;
120 ulinux_u32 ssi_arch;
121
122 /*
123 * Pad strcture to 128 bytes. Remember to update the
124 * pad size when you add new members. We use a fixed
125 * size structure to avoid compatibility problems with
126 * future versions, and we leave extra space for additional
127 * members. We use fixed size members because this strcture
128 * comes out of a read(2) and we really don't want to have
129 * a compat on read(2).
130 */
131 ulinux_u8 __pad[28];
132 };
133 /*----------------------------------------------------------------------------*/
134 #endif
File ulinux/socket/in.h added (mode: 100644) (index 0000000..6ca8677)
1 #ifndef ULINUX_SOCKET_IN_H
2 #define ULINUX_SOCKET_IN_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 /*
8 * ipv4 sockaddr must have this size, kind of minimum size for any type of
9 * socketaddr
10 */
11 #define ULINUX_SOCKADDR_IN_SZ 16
12 struct ulinux_sockaddr_in {
13 ulinux_u16 family; /* AF_INET */
14 ulinux_u16 port;
15 ulinux_u32 addr; /* ipv4 */
16
17 /*pad to size of `struct sockaddr'*/
18 ulinux_u8 __pad[ULINUX_SOCKADDR_IN_SZ - sizeof(ulinux_u16)
19 - sizeof(ulinux_u16) - sizeof(ulinux_u32)];
20 };
21 #define ULINUX_INADDR_ANY ((ulinux_ul)0x00000000)
22 #endif
File ulinux/socket/in6.h added (mode: 100644) (index 0000000..2738f55)
1 #ifndef ULINUX_SOCKET_IN6_H
2 #define ULINUX_SOCKET_IN6_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 struct ulinux_sockaddr_in6 {
8 ulinux_u16 family; /* AF_INET6 */
9 ulinux_u16 port;
10 ulinux_u32 flowinfo;
11 ulinux_u8 addr[16]; /* ipv6 address */
12 /* scope id (new in RFC2553), endian not defined */
13 ulinux_u32 scope_id;
14 };
15 #endif
File ulinux/socket/msg.h added (mode: 100644) (index 0000000..a986f3b)
1 #ifndef ULINUX_SOCKET_MSG_H
2 #define ULINUX_SOCKET_MSG_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 #define ULINUX_SOL_SOCKET 1
8
9 struct ulinux_io_vec { /*will probably go somewhere else*/
10 void *base; /*BSD uses caddr_t (1003.1g requires void *)*/
11 ulinux_sz len; /*Must be size_t (1003.1g)*/
12 };
13
14 struct ulinux_msg_hdr {
15 void *name; /*socket name*/
16 ulinux_si name_len; /*length of name*/
17 struct ulinux_io_vec *iov; /*data blocks*/
18 ulinux_sz iov_len; /*number of blocks*/
19 /*per protocol magic (eg BSD file descriptor passing)*/
20 void *ctl;
21 ulinux_sz ctl_len; /*length of cmsg list*/
22 ulinux_ui flgs;
23 };
24
25 /*the c prefix stands for access *c*ontrol message (other name ancillary data)*/
26 struct ulinux_cmsg_hdr {
27 ulinux_sz len; /*data byte count, including hdr*/
28 ulinux_si lvl; /*originating protocol*/
29 ulinux_si type; /*protocol-specific type*/
30 };
31
32 #define __ULINUX_CMSG_NXTHDR(ctl,len,cmsg) \
33 __ulinux_cmsg_nxthdr((ctl),(len),(cmsg))
34 #define ULINUX_CMSG_NXTHDR(mhdr,cmsg) ulinux_cmsg_nxthdr((mhdr),(cmsg))
35
36 #define ULINUX_CMSG_ALIGN(len) (((len)+sizeof(ulinux_sl)-1)\
37 &~(sizeof(ulinux_sl)-1))
38
39 #define ULINUX_CMSG_DATA(cmsg) ((void*)((ulinux_u8*)(cmsg)\
40 +ULINUX_CMSG_ALIGN(sizeof(struct ulinux_cmsg_hdr))))
41 #define ULINUX_CMSG_SPACE(len) \
42 (ULINUX_CMSG_ALIGN(sizeof(struct ulinux_cmsg_hdr))+ULINUX_CMSG_ALIGN(len))
43 #define ULINUX_CMSG_LEN(len) \
44 (ULINUX_CMSG_ALIGN(sizeof(struct ulinux_cmsg_hdr))+(len))
45
46 #define __ULINUX_CMSG_FIRSTHDR(ctl,len) ((len)>=sizeof(struct ulinux_cmsg_hdr)\
47 ? (struct ulinux_cmsg_hdr *)(ctl) : (struct ulinux_cmsg_hdr *)0)
48 #define ULINUX_CMSG_FIRSTHDR(msg) __ULINUX_CMSG_FIRSTHDR((msg)->ctl,\
49 (msg)->ctl_len)
50 #define ULINUX_CMSG_OK(mhdr, cmsg) \
51 ((cmsg)->cmsg_len>=sizeof(struct ulinux_cmsg_hdr)&&\
52 (cmsg)->cmsg_len<=(ulinux_ul)\
53 ((mhdr)->ctl_len-\
54 ((ulinux_u8*)(cmsg)-(ulinux_u8*)(mhdr)->ctl)))
55
56 static inline struct ulinux_cmsg_hdr * __ulinux_cmsg_nxthdr(void *ctl,
57 ulinux_sz size,struct ulinux_cmsg_hdr *cmsg)
58 {
59 struct ulinux_cmsg_hdr *ptr;
60
61 ptr=(struct ulinux_cmsg_hdr*)(((ulinux_u8*)cmsg)
62 + ULINUX_CMSG_ALIGN(cmsg->len));
63 if((ulinux_ul)((ulinux_u8*)(ptr + 1) - (ulinux_u8*)ctl) > size)
64 return (struct ulinux_cmsg_hdr*)0;
65 return ptr;
66 }
67
68 static inline struct ulinux_cmsg_hdr *ulinux_cmsg_nxthdr(
69 struct ulinux_msg_hdr *msg, struct ulinux_cmsg_hdr *cmsg)
70 {
71 return __ulinux_cmsg_nxthdr(msg->ctl, msg->ctl_len,cmsg);
72 }
73
74 #define ULINUX_MSG_OOB 1
75 #define ULINUX_MSG_PEEK 2
76 #define ULINUX_MSG_DONTROUTE 4
77 /* synonym for msg_dontroute for decnet */
78 #define ULINUX_MSG_TRYHARD 4
79 #define ULINUX_MSG_CTRUNC 8
80 /* do not send. only probe path f.e. for mtu */
81 #define ULINUX_MSG_PROBE 0x10
82 #define ULINUX_MSG_TRUNC 0x20
83 /* nonblocking io */
84 #define ULINUX_MSG_DONTWAIT 0x40
85 /* end of record */
86 #define ULINUX_MSG_EOR 0x80
87 /* wait for a full request */
88 #define ULINUX_MSG_WAITALL 0x100
89 #define ULINUX_MSG_FIN 0x200
90 #define ULINUX_MSG_SYN 0x400
91 /* confirm path validity */
92 #define ULINUX_MSG_CONFIRM 0x800
93 #define ULINUX_MSG_RST 0x1000
94 /* fetch message from error queue */
95 #define ULINUX_MSG_ERRQUEUE 0x2000
96 /* do not generate sigpipe */
97 #define ULINUX_MSG_NOSIGNAL 0x4000
98 /* sender will send more */
99 #define ULINUX_MSG_MORE 0x8000
100 /* recvmmsg(): block until 1+ packets avail */
101 #define ULINUX_MSG_WAITFORONE 0x10000
102 #define ULINUX_MSG_EOF ULINUX_MSG_FIN
103 /* set close_on_exit for file descriptor received through scm_rights */
104 #define ULINUX_MSG_CMSG_CLOEXEC 0x40000000
105
106 /* "socket"-level control message types: */
107 #define ULINUX_SCM_RIGHTS 0x01 /* rw: access rights (array of int) */
108 #define ULINUX_SCM_CREDENTIALS 0x02 /* rw: struct ucred */
109 #define ULINUX_SCM_SECURITY 0x03 /* rw: security label */
110 struct ulinux_ucred{
111 ulinux_u32 pid;
112 ulinux_u32 uid;
113 ulinux_u32 gid;
114 };
115 #endif
File ulinux/socket/netlink.h added (mode: 100644) (index 0000000..0ce858c)
1 #ifndef ULINUX_SOCKET_NETLINK_H
2 #define ULINUX_SOCKET_NETLINK_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 #define ULINUX_NETLINK_ROUTE 0/*routing/device hook*/
8 #define ULINUX_NETLINK_UNUSED 1/*unused number*/
9 #define ULINUX_NETLINK_USERSOCK 2/*reserved for user mode socket protos*/
10 #define ULINUX_NETLINK_FIREWALL 3/*firewalling hook*/
11 #define ULINUX_NETLINK_INET_DIAG 4/*inet socket monitoring*/
12 #define ULINUX_NETLINK_NFLOG 5/*netfilter/iptables ulog*/
13 #define ULINUX_NETLINK_XFRM 6/*ipsec*/
14 #define ULINUX_NETLINK_SELINUX 7/*selinux event notifications*/
15 #define ULINUX_NETLINK_ISCSI 8/*open-iscsi*/
16 #define ULINUX_NETLINK_AUDIT 9/*auditing */
17 #define ULINUX_NETLINK_FIB_LOOKUP 10
18 #define ULINUX_NETLINK_CONNECTOR 11
19 #define ULINUX_NETLINK_NETFILTER 12/*netfilter subsystem*/
20 #define ULINUX_NETLINK_IP6_FW 13
21 #define ULINUX_NETLINK_DNRTMSG 14/*decnet routing messages*/
22 #define ULINUX_NETLINK_KOBJECT_UEVENT 15/*kernel messages to userspace*/
23 #define ULINUX_NETLINK_GENERIC 16
24 /*leave room for netlink_dm (dm events)*/
25 #define ULINUX_NETLINK_SCSITRANSPORT 18/*scsi transports*/
26 #define ULINUX_NETLINK_ECRYPTFS 19
27 #define ULINUX_NETLINK_RDMA 20
28 #define ULINUX_MAX_LINKS 32
29
30 struct ulinux_sockaddr_nl {
31 ulinux_us nl_family; /*AF_NETLINK*/
32 ulinux_us nl_pad; /*zero*/
33 ulinux_u32 nl_pid; /**port* id*/
34 ulinux_u32 nl_groups; /*multicast groups mask*/
35 /*padding on ULINUX_SOCK_ADDR_SZ in 0*/
36 };
37
38 struct ulinux_nl_msg_hdr{
39 ulinux_u32 len; /*length of message including header*/
40 ulinux_u16 type;/*message content*/
41 ulinux_u16 flgs;/*additional flags*/
42 ulinux_u32 seq; /*sequence number*/
43 ulinux_u32 pid; /*sending process port id*/
44 };
45
46 /*flags values*/
47 #define ULINUX_NLM_F_REQUEST 1/*it is request message*/
48 #define ULINUX_NLM_F_MULTI 2/*multipart message, terminated by nlmsg_done*/
49 #define ULINUX_NLM_F_ACK 4/*reply with ack, with zero or error code*/
50 #define ULINUX_NLM_F_ECHO 8/*echo this request*/
51 #define ULINUX_NLM_F_DUMP_INTR 16/*dump was inconsistent due to sequence
52 change*/
53
54 /*modifiers to get request*/
55 #define ULINUX_NLM_F_ROOT 0x100/*specify tree root*/
56 #define ULINUX_NLM_F_MATCH 0x200/*return all matching*/
57 #define ULINUX_NLM_F_ATOMIC 0x400/*atomic get*/
58 #define ULINUX_NLM_F_DUMP (ULINUX_NLM_F_ROOT|ULINUXNLM_F_MATCH)
59
60 /*modifiers to new request*/
61 #define ULINUX_NLM_F_REPLACE 0x100/*override existing*/
62 #define ULINUX_NLM_F_EXCL 0x200/*do not touch, if it exists*/
63 #define ULINUX_NLM_F_CREATE 0x400/*create, if it does not exist*/
64 #define ULINUX_NLM_F_APPEND 0x800/*add to end of list*/
65
66 #define ULINUX_NLMSG_ALIGNTO 4U
67 #define ULINUX_NLMSG_ALIGN(len) (((len)+ULINUX_NLMSG_ALIGNTO-1)\
68 &~(ULINUX_NLMSG_ALIGNTO-1))
69 #define ULINUX_NLMSG_HDRLEN ((ulinux_si)ULINUX_NLMSG_ALIGN(\
70 sizeof(struct ulinux_nl_msg_hdr)))
71 #define ULINUX_NLMSG_LENGTH(len) ((len)+ULINUX_NLMSG_ALIGN(ULINUX_NLMSG_HDRLEN))
72 #define ULINUX_NLMSG_SPACE(len) ULINUX_NLMSG_ALIGN(ULINUX_NLMSG_LENGTH(len))
73 #define ULINUX_NLMSG_DATA(nlh) ((void*)(((ulinux_uc*)nlh)\
74 +ULINUX_NLMSG_LENGTH(0)))
75 #define ULINUX_NLMSG_NEXT(nlh,len) ((len)-=ULINUX_NLMSG_ALIGN((nlh)->len),\
76 (struct ulinux_nl_msg_hdr*)(((ulinux_uc*)(nlh))\
77 +ULINUX_NLMSG_ALIGN((nlh)->len)))
78 #define ULINUX_NLMSG_OK(nlh,len) \
79 ((len)>=(ulinux_si)sizeof(struct ulinux_nl_msg_hdr)\
80 &&(nlh)->len>=sizeof(struct ulinux_nl_msg_hdr)\
81 &&(nlh)->len<=(len))
82 #define ULINUX_NLMSG_PAYLOAD(nlh,len) ((nlh)->len-ULINUX_NLMSG_SPACE((len)))
83
84 #define ULINUX_NLMSG_NOOP 0x1/*nothing*/
85 #define ULINUX_NLMSG_ERROR 0x2/*error*/
86 #define ULINUX_NLMSG_DONE 0x3/*end of a dump*/
87 #define ULINUX_NLMSG_OVERRUN 0x4/*data lost*/
88 #define ULINUX_NLMSG_MIN_TYPE 0x10/*<0x10:reserved control messages*/
89
90 struct ulinux_nl_msg_err {
91 ulinux_si error;
92 struct ulinux_nl_msg_hdr msg;
93 };
94 #endif
File ulinux/socket/socket.h added (mode: 100644) (index 0000000..671ce26)
1 #ifndef ULINUX_SOCKET_SOCKET_H
2 #define ULINUX_SOCKET_SOCKET_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 #define ULINUX_AF_UNSPEC 0
8 #define ULINUX_AF_UNIX 1/*Unix domain sockets*/
9 #define ULINUX_AF_LOCAL 1/*POSIX name for AF_UNIX*/
10 #define ULINUX_AF_INET 2/*Internet IP Protocol*/
11 #define ULINUX_AF_AX25 3/*Amateur Radio AX.25*/
12 #define ULINUX_AF_IPX 4/*Novell IPX*/
13 #define ULINUX_AF_APPLETALK 5/*AppleTalk DDP*/
14 #define ULINUX_AF_NETROM 6/*Amateur Radio NET/ROM*/
15 #define ULINUX_AF_BRIDGE 7/*Multiprotocol bridge*/
16 #define ULINUX_AF_ATMPVC 8/*ATM PVCs*/
17 #define ULINUX_AF_X25 9/*Reserved for X.25 project*/
18 #define ULINUX_AF_INET6 10/*IP version 6*/
19 #define ULINUX_AF_ROSE 11/*Amateur Radio X.25 PLP*/
20 #define ULINUX_AF_DECnet 12/*Reserved for DECnet project*/
21 #define ULINUX_AF_NETBEUI 13/*Reserved for 802.2LLC project*/
22 #define ULINUX_AF_SECURITY 14/*Security callback pseudo AF*/
23 #define ULINUX_AF_KEY 15/*PF_KEY key management API*/
24 #define ULINUX_AF_NETLINK 16
25 #define ULINUX_AF_ROUTE ULINUX_AF_NETLINK/*Alias to emulate 4.4BSD*/
26 #define ULINUX_AF_PACKET 17/*Packet family*/
27 #define ULINUX_AF_ASH 18/*Ash*/
28 #define ULINUX_AF_ECONET 19/*Acorn Econet*/
29 #define ULINUX_AF_ATMSVC 20/*ATM SVCs*/
30 #define ULINUX_AF_RDS 21/*RDS sockets*/
31 #define ULINUX_AF_SNA 22/*Linux SNA Project (nutters!)*/
32 #define ULINUX_AF_IRDA 23/*IRDA sockets*/
33 #define ULINUX_AF_PPPOX 24/*PPPoX sockets*/
34 #define ULINUX_AF_WANPIPE 25/*Wanpipe API Sockets*/
35 #define ULINUX_AF_LLC 26/*Linux LLC*/
36 #define ULINUX_AF_CAN 29/*Controller Area Network*/
37 #define ULINUX_AF_TIPC 30/*TIPC sockets*/
38 #define ULINUX_AF_BLUETOOTH 31/*Bluetooth sockets*/
39 #define ULINUX_AF_IUCV 32/*IUCV sockets*/
40 #define ULINUX_AF_RXRPC 33/*RxRPC sockets*/
41 #define ULINUX_AF_ISDN 34/*mISDN sockets*/
42 #define ULINUX_AF_PHONET 35/*Phonet sockets*/
43 #define ULINUX_AF_IEEE802154 36/*IEEE802154 sockets*/
44 #define ULINUX_AF_CAIF 37/*CAIF sockets*/
45 #define ULINUX_AF_MAX 38/*For now..*/
46
47 /*protocol families, same as address families*/
48 #define ULINUX_PF_UNSPEC ULINUX_AF_UNSPEC
49 #define ULINUX_PF_UNIX ULINUX_AF_UNIX
50 #define ULINUX_PF_LOCAL ULINUX_AF_LOCAL
51 #define ULINUX_PF_INET ULINUX_AF_INET
52 #define ULINUX_PF_AX25 ULINUX_AF_AX25
53 #define ULINUX_PF_IPX ULINUX_AF_IPX
54 #define ULINUX_PF_APPLETALK ULINUX_AF_APPLETALK
55 #define ULINUX_PF_NETROM ULINUX_AF_NETROM
56 #define ULINUX_PF_BRIDGE ULINUX_AF_BRIDGE
57 #define ULINUX_PF_ATMPVC ULINUX_AF_ATMPVC
58 #define ULINUX_PF_X25 ULINUX_AF_X25
59 #define ULINUX_PF_INET6 ULINUX_AF_INET6
60 #define ULINUX_PF_ROSE ULINUX_AF_ROSE
61 #define ULINUX_PF_DECnet ULINUX_AF_DECnet
62 #define ULINUX_PF_NETBEUI ULINUX_AF_NETBEUI
63 #define ULINUX_PF_SECURITY ULINUX_AF_SECURITY
64 #define ULINUX_PF_KEY ULINUX_AF_KEY
65 #define ULINUX_PF_NETLINK ULINUX_AF_NETLINK
66 #define ULINUX_PF_ROUTE ULINUX_AF_ROUTE
67 #define ULINUX_PF_PACKET ULINUX_AF_PACKET
68 #define ULINUX_PF_ASH ULINUX_AF_ASH
69 #define ULINUX_PF_ECONET ULINUX_AF_ECONET
70 #define ULINUX_PF_ATMSVC ULINUX_AF_ATMSVC
71 #define ULINUX_PF_RDS ULINUX_AF_RDS
72 #define ULINUX_PF_SNA ULINUX_AF_SNA
73 #define ULINUX_PF_IRDA ULINUX_AF_IRDA
74 #define ULINUX_PF_PPPOX ULINUX_AF_PPPOX
75 #define ULINUX_PF_WANPIPE ULINUX_AF_WANPIPE
76 #define ULINUX_PF_LLC ULINUX_AF_LLC
77 #define ULINUX_PF_CAN ULINUX_AF_CAN
78 #define ULINUX_PF_TIPC ULINUX_AF_TIPC
79 #define ULINUX_PF_BLUETOOTH ULINUX_AF_BLUETOOTH
80 #define ULINUX_PF_IUCV ULINUX_AF_IUCV
81 #define ULINUX_PF_RXRPC ULINUX_AF_RXRPC
82 #define ULINUX_PF_ISDN ULINUX_AF_ISDN
83 #define ULINUX_PF_PHONET ULINUX_AF_PHONET
84 #define ULINUX_PF_IEEE802154 ULINUX_AF_IEEE802154
85 #define ULINUX_PF_CAIF ULINUX_AF_CAIF
86 #define ULINUX_PF_MAX ULINUX_AF_MAX
87
88 #define ULINUX_SOCK_STREAM 1
89 #define ULINUX_SOCK_DGRAM 2
90 #define ULINUX_SOCK_RAW 3
91 #define ULINUX_SOCK_RDM 4
92 #define ULINUX_SOCK_SEQPACKET 5
93 #define ULINUX_SOCK_DCCP 6
94 #define ULINUX_SOCK_PACKET 10
95
96 #ifndef ULINUX_O_NONBLOCK
97 #error "missing definition of ULINUX_O_NONBLOCK"
98 #endif
99 #define ULINUX_SOCK_NONBLOCK ULINUX_O_NONBLOCK
100
101 /*----------------------------------------------------------------------------*/
102 /*options*/
103 #define ULINUX_SOL_SOCKET 1/*sol is *so*cket *l*evel for setsockopt(2)*/
104
105 #define ULINUX_SO_DEBUG 1
106 #define ULINUX_SO_REUSEADDR 2
107 #define ULINUX_SO_TYPE 3
108 #define ULINUX_SO_ERROR 4
109 #define ULINUX_SO_DONTROUTE 5
110 #define ULINUX_SO_BROADCAST 6
111 #define ULINUX_SO_SNDBUF 7
112 #define ULINUX_SO_RCVBUF 8
113 #define ULINUX_SO_SNDBUFFORCE 32
114 #define ULINUX_SO_RCVBUFFORCE 33
115 #define ULINUX_SO_KEEPALIVE 9
116 #define ULINUX_SO_OOBINLINE 10
117 #define ULINUX_SO_NO_CHECK 11
118 #define ULINUX_SO_PRIORITY 12
119 #define ULINUX_SO_LINGER 13
120 #define ULINUX_SO_BSDCOMPAT 14
121 /*to add :#define SO_REUSEPORT 15*/
122 #define ULINUX_SO_PASSCRED 16
123 #define ULINUX_SO_PEERCRED 17
124 #define ULINUX_SO_RCVLOWAT 18
125 #define ULINUX_SO_SNDLOWAT 19
126 #define ULINUX_SO_RCVTIMEO 20
127 #define ULINUX_SO_SNDTIMEO 21
128
129 /*security levels - as per NRL IPv6 - don't actually do anything*/
130 #define ULINUX_SO_SECURITY_AUTHENTICATION 22
131 #define ULINUX_SO_SECURITY_ENCRYPTION_TRANSPORT 23
132 #define ULINUX_SO_SECURITY_ENCRYPTION_NETWORK 24
133
134 #define ULINUX_SO_BINDTODEVICE 25
135
136 /*socket filtering*/
137 #define ULINUX_SO_ATTACH_FILTER 26
138 #define ULINUX_SO_DETACH_FILTER 27
139
140 #define ULINUX_SO_PEERNAME 28
141 #define ULINUX_SO_TIMESTAMP 29
142 #define ULINUX_SCM_TIMESTAMP ULINUX_SO_TIMESTAMP
143
144 #define ULINUX_SO_ACCEPTCONN 30
145
146 #define ULINUX_SO_PEERSEC 31
147 #define ULINUX_SO_PASSSEC 34
148 #define ULINUX_SO_TIMESTAMPNS 35
149 #define ULINUX_SCM_TIMESTAMPNS ULINUX_SO_TIMESTAMPNS
150
151 #define ULINUX_SO_MARK 36
152
153 #define ULINUX_SO_TIMESTAMPING 37
154 #define ULINUX_SCM_TIMESTAMPING ULINUX_SO_TIMESTAMPING
155
156 #define ULINUX_SO_PROTOCOL 38
157 #define ULINUX_SO_DOMAIN 39
158
159 #define ULINUX_SO_RXQ_OVFL 40
160 /*----------------------------------------------------------------------------*/
161
162 /*----------------------------------------------------------------------------*/
163 /*socketcall multiplexer*/
164 #define ULINUX_SYS_SOCKET 1
165 #define ULINUX_SYS_BIND 2
166 #define ULINUX_SYS_CONNECT 3
167 #define ULINUX_SYS_LISTEN 4
168 #define ULINUX_SYS_ACCEPT 5
169 #define ULINUX_SYS_GETSOCKNAME 6
170 #define ULINUX_SYS_GETPEERNAME 7
171 #define ULINUX_SYS_SOCKETPAIR 8
172 #define ULINUX_SYS_SEND 9
173 #define ULINUX_SYS_RECV 10
174 #define ULINUX_SYS_SENDTO 11
175 #define ULINUX_SYS_RECVFROM 12
176 #define ULINUX_SYS_SHUTDOWN 13
177 #define ULINUX_SYS_SETSOCKOPT 14
178 #define ULINUX_SYS_GETSOCKOPT 15
179 #define ULINUX_SYS_SENDMSG 16
180 #define ULINUX_SYS_RECVMSG 17
181 #define ULINUX_SYS_ACCEPT4 18
182 #define ULINUX_SYS_RECVMMSG 19
183 #define ULINUX_SYS_SENDMMSG 20
184 #endif
File ulinux/socket/tcp.h added (mode: 100644) (index 0000000..6fdf6ae)
1 #ifndef ULINUX_SOCKET_TCP_H
2 #define ULINUX_SOCKET_TCP_H
3 /* the socket option level */
4 #define ULINUX_IPPROTO_TCP 6
5
6 /* the socket options */
7 #define ULINUX_TCP_USER_TIMEOUT 18 /* How long for loss retry before timeout */
8 #endif
File ulinux/socket/un.h added (mode: 100644) (index 0000000..ca2d0ce)
1 #ifndef ULINUX_SOCKET_UN_H
2 #define ULINUX_SOCKET_UN_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 #define ULINUX_UNIX_PATH_MAX 108
8
9 struct ulinux_sockaddr_un {
10 ulinux_us sun_family;
11 ulinux_u8 sun_path[ULINUX_UNIX_PATH_MAX];
12 };
13 #endif
File ulinux/start.S added (mode: 100644) (index 0000000..aada05a)
1 #include "ulinux/arch/start.S"
2 /*
3 * To avoid an exe stack by default, must add that line.
4 * ELF GNU_STACK segment should go away soon for non executable stack.
5 */
6 .section .note.GNU-stack,"",@progbits
File ulinux/start.h added (mode: 100644) (index 0000000..64882e9)
1 #ifndef ULINUX_START_H
2 #define ULINUX_START_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 /* on the stack, argc, argv, envp, auxv */
8 void ulinux_start(ulinux_u8 *abi_stack) GCC_NOCLONE GCC_NOINLINE;
9 #endif
File ulinux/stat.h added (mode: 100644) (index 0000000..fed3f73)
1 #ifndef ULINUX_STAT_H
2 #define ULINUX_STAT_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7
8 /*
9 * for the "old" stat syscall which could be arch specific, should use the
10 * "new" statx which is "arch independant"
11 */
12 #include <ulinux/arch/stat.h>
13
14 #define ULINUX_AT_CWD -100
15
16 /*----------------------------------------------------------------------------*/
17 #define ULINUX_S_IFMT 00170000
18 #define ULINUX_S_IFSOCK 0140000
19 #define ULINUX_S_IFLNK 0120000
20 #define ULINUX_S_IFREG 0100000
21 #define ULINUX_S_IFBLK 0060000
22 #define ULINUX_S_IFDIR 0040000
23 #define ULINUX_S_IFCHR 0020000
24 #define ULINUX_S_IFIFO 0010000
25
26 #define ULINUX_S_ISUID 0004000
27 #define ULINUX_S_ISGID 0002000
28 #define ULINUX_S_ISVTX 0001000
29
30 #define ULINUX_S_IRWXU 00700
31 #define ULINUX_S_IRUSR 00400
32 #define ULINUX_S_IWUSR 00200
33 #define ULINUX_S_IXUSR 00100
34
35 #define ULINUX_S_IRWXG 00070
36 #define ULINUX_S_IRGRP 00040
37 #define ULINUX_S_IWGRP 00020
38 #define ULINUX_S_IXGRP 00010
39
40 #define ULINUX_S_IRWXO 00007
41 #define ULINUX_S_IROTH 00004
42 #define ULINUX_S_IWOTH 00002
43 #define ULINUX_S_IXOTH 00001
44 /*----------------------------------------------------------------------------*/
45
46 #define ULINUX_S_IRWXUGO (ULINUX_S_IRWXU|ULINUX_S_IRWXG|ULINUX_S_IRWXO)
47 #define ULINUX_S_IALLUGO (ULINUX_S_ISUID|ULINUX_S_ISGID|ULINUX_S_ISVTX\
48 \ |ULINUX_S_IRWXUGO)
49 #define ULINUX_S_IRUGO (ULINUX_S_IRUSR|ULINUX_S_IRGRP|ULINUX_S_IROTH)
50 #define ULINUX_S_IWUGO (ULINUX_S_IWUSR|ULINUX_S_IWGRP|ULINUX_S_IWOTH)
51 #define ULINUX_S_IXUGO (ULINUX_S_IXUSR|ULINUX_S_IXGRP|ULINUX_S_IXOTH)
52
53 /*============================================================================*/
54 /* statx syscall to prefer than stat syscall on not too old kernels */
55
56 /*
57 * Timestamp structure for the timestamps in struct statx.
58 *
59 * tv_sec holds the number of seconds before (negative) or after (positive)
60 * 00:00:00 1st January 1970 UTC.
61 *
62 * tv_nsec holds a number of nanoseconds (0..999,999,999) after the tv_sec time.
63 *
64 * __reserved is held in case we need a yet finer resolution.
65 */
66 struct ulinux_statx_timestamp {
67 ulinux_s64 tv_sec;
68 ulinux_u32 tv_nsec;
69 ulinux_s32 __reserved;
70 };
71
72 /*
73 * Structures for the extended file attribute retrieval system call
74 * (statx()).
75 *
76 * The caller passes a mask of what they're specifically interested in as a
77 * parameter to statx(). What statx() actually got will be indicated in
78 * st_mask upon return.
79 *
80 * For each bit in the mask argument:
81 *
82 * - if the datum is not supported:
83 *
84 * - the bit will be cleared, and
85 *
86 * - the datum will be set to an appropriate fabricated value if one is
87 * available (eg. CIFS can take a default uid and gid), otherwise
88 *
89 * - the field will be cleared;
90 *
91 * - otherwise, if explicitly requested:
92 *
93 * - the datum will be synchronised to the server if AT_STATX_FORCE_SYNC is
94 * set or if the datum is considered out of date, and
95 *
96 * - the field will be filled in and the bit will be set;
97 *
98 * - otherwise, if not requested, but available in approximate form without any
99 * effort, it will be filled in anyway, and the bit will be set upon return
100 * (it might not be up to date, however, and no attempt will be made to
101 * synchronise the internal state first);
102 *
103 * - otherwise the field and the bit will be cleared before returning.
104 *
105 * Items in STATX_BASIC_STATS may be marked unavailable on return, but they
106 * will have values installed for compatibility purposes so that stat() and
107 * co. can be emulated in userspace.
108 */
109 struct ulinux_statx {
110 /* 0x00 */
111 ulinux_u32 mask; /* What results were written [uncond] */
112 ulinux_u32 blksize; /* Preferred general I/O size [uncond] */
113 ulinux_u64 attributes; /* Flags conveying information about the file [uncond] */
114 /* 0x10 */
115 ulinux_u32 nlink; /* Number of hard links */
116 ulinux_u32 uid; /* User ID of owner */
117 ulinux_u32 gid; /* Group ID of owner */
118 ulinux_u16 mode; /* File mode */
119 ulinux_u16 __spare0[1];
120 /* 0x20 */
121 ulinux_u64 ino; /* Inode number */
122 ulinux_u64 size; /* File size */
123 ulinux_u64 blocks; /* Number of 512-byte blocks allocated */
124 ulinux_u64 attributes_mask; /* Mask to show what's supported in stx_attributes */
125 /* 0x40 */
126 struct ulinux_statx_timestamp atime; /* Last access time */
127 struct ulinux_statx_timestamp btime; /* File creation time */
128 struct ulinux_statx_timestamp ctime; /* Last attribute change time */
129 struct ulinux_statx_timestamp mtime; /* Last data modification time */
130 /* 0x80 */
131 ulinux_u32 rdev_major; /* Device ID of special file [if bdev/cdev] */
132 ulinux_u32 rdev_minor;
133 ulinux_u32 dev_major; /* ID of device containing file [uncond] */
134 ulinux_u32 dev_minor;
135 /* 0x90 */
136 ulinux_u64 __spare2[14]; /* Spare space for future expansion */
137 /* 0x100 */
138 };
139
140 /*
141 * Flags to be stx_mask
142 *
143 * Query request/result mask for statx() and struct statx::stx_mask.
144 *
145 * These bits should be set in the mask argument of statx() to request
146 * particular items when calling statx().
147 */
148 #define ULINUX_STATX_TYPE 0x00000001U /* Want/got stx_mode & S_IFMT */
149 #define ULINUX_STATX_MODE 0x00000002U /* Want/got stx_mode & ~S_IFMT */
150 #define ULINUX_STATX_NLINK 0x00000004U /* Want/got stx_nlink */
151 #define ULINUX_STATX_UID 0x00000008U /* Want/got stx_uid */
152 #define ULINUX_STATX_GID 0x00000010U /* Want/got stx_gid */
153 #define ULINUX_STATX_ATIME 0x00000020U /* Want/got stx_atime */
154 #define ULINUX_STATX_MTIME 0x00000040U /* Want/got stx_mtime */
155 #define ULINUX_STATX_CTIME 0x00000080U /* Want/got stx_ctime */
156 #define ULINUX_STATX_INO 0x00000100U /* Want/got stx_ino */
157 #define ULINUX_STATX_SIZE 0x00000200U /* Want/got stx_size */
158 #define ULINUX_STATX_BLOCKS 0x00000400U /* Want/got stx_blocks */
159 #define ULINUX_STATX_BASIC_STATS 0x000007ffU /* The stuff in the normal stat struct */
160 #define ULINUX_STATX_BTIME 0x00000800U /* Want/got stx_btime */
161 #define ULINUX_STATX_ALL 0x00000fffU /* All currently supported flags */
162 #define ULINUX_STATX__RESERVED 0x80000000U /* Reserved for future struct statx expansion */
163
164 /*
165 * Attributes to be found in stx_attributes and masked in stx_attributes_mask.
166 *
167 * These give information about the features or the state of a file that might
168 * be of use to ordinary userspace programs such as GUIs or ls rather than
169 * specialised tools.
170 *
171 * Note that the flags marked [I] correspond to generic FS_IOC_FLAGS
172 * semantically. Where possible, the numerical value is picked to correspond
173 * also.
174 */
175 #define ULINUX_STATX_ATTR_COMPRESSED 0x00000004 /* [I] File is compressed by the fs */
176 #define ULINUX_STATX_ATTR_IMMUTABLE 0x00000010 /* [I] File is marked immutable */
177 #define ULINUX_STATX_ATTR_APPEND 0x00000020 /* [I] File is append-only */
178 #define ULINUX_STATX_ATTR_NODUMP 0x00000040 /* [I] File is not to be dumped */
179 #define ULINUX_STATX_ATTR_ENCRYPTED 0x00000800 /* [I] File requires key to decrypt in fs */
180
181 #define ULINUX_STATX_ATTR_AUTOMOUNT 0x00001000 /* Dir: Automount trigger */
182 #endif
File ulinux/sysc.h added (mode: 100644) (index 0000000..fc47f3e)
1 #ifndef ULINUX_SYSC_H
2 #define ULINUX_SYSC_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 #include <ulinux/arch/sysc.h>
8 #endif
File ulinux/time.h added (mode: 100644) (index 0000000..fe7b0ab)
1 #ifndef ULINUX_TIME_H
2 #define ULINUX_TIME_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 struct ulinux_timespec {
8 ulinux_sl sec; /*seconds*/
9 ulinux_sl nsec; /*nanoseconds*/
10 };
11
12 struct ulinux_timeval {
13 ulinux_sl sec; /*seconds*/
14 ulinux_sl usec; /*micro seconds, type can be arch dependent (i.e. an int)*/
15 };
16
17 struct ulinux_itimerspec {
18 struct ulinux_timespec interval;/* timer period */
19 struct ulinux_timespec value; /* timer expiration */
20 };
21
22 #define ULINUX_CLOCK_REALTIME 0
23 #define ULINUX_CLOCK_MONOTONIC 1
24 #define ULINUX_CLOCK_PROCESS_CPUTIME_ID 2
25 #define ULINUX_CLOCK_THREAD_CPUTIME_ID 3
26 #define ULINUX_CLOCK_MONOTONIC_RAW 4
27 #define ULINUX_CLOCK_REALTIME_COARSE 5
28 #define ULINUX_CLOCK_MONOTONIC_COARSE 6
29 #define ULINUX_CLOCK_BOOTTIME 7
30 #define ULINUX_CLOCK_REALTIME_ALARM 8
31 #define ULINUX_CLOCK_BOOTTIME_ALARM 9
32 /* hole */
33 #define ULINUX_MAX_CLOCKS 16
34
35 #define ULINUX_CLOCKS_MASK (ULINUX_CLOCK_REALTIME | ULINUX_CLOCK_MONOTONIC)
36 #define ULINUX_CLOCKS_MONO ULINUX_CLOCK_MONOTONIC
37
38 #define ULINUX_TIMER_ABSTIME 0x01
39
40 /*
41 * XXX: monitor closely those flags because they may collide with others and be
42 * updated
43 */
44 #define ULINUX_TFD_TIMER_ABSTIME (1 << 0)
45 #define ULINUX_TFD_TIMER_CANCEL_ON_SET (1 << 1)
46
47 #ifndef ULINUX_O_CLOEXEC
48 #error "missing definition of ULINUX_O_CLOEXEC"
49 #endif
50 #define ULINUX_TFD_CLOEXEC ULINUX_O_CLOEXEC
51
52 #ifndef ULINUX_O_NONBLOCK
53 #error "missing definition of ULINUX_O_NONBLOCK"
54 #endif
55 #define ULINUX_TFD_NONBLOCK ULINUX_O_NONBLOCK
56 #endif
File ulinux/types.h added (mode: 100644) (index 0000000..8cb701f)
1 #ifndef ULINUX_TYPES_H
2 #define ULINUX_TYPES_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 #include <ulinux/arch/types.h>
8
9 #define ulinux_s8 ulinux_sc
10 #define ulinux_u8 ulinux_uc
11
12 #define ulinux_s16 ulinux_ss
13 #define ulinux_u16 ulinux_us
14
15 #define ulinux_s32 ulinux_si
16 #define ulinux_u32 ulinux_ui
17 #define ulinux_f32 ulinux_f
18
19 #define ulinux_s64 ulinux_sll
20 #define ulinux_u64 ulinux_ull
21
22 /* fix C */
23 #if BITS_PER_LONG == 64
24 #define ulinux_sz ulinux_ul
25 #define ulinux_ptrdiff ulinux_sl
26 #else
27 #define ulinux_sz ulinux_ui
28 #define ulinux_ptrdiff ulinux_si
29 #endif
30 #endif
File ulinux/types_posix.h added (mode: 100644) (index 0000000..215bdd3)
1 #ifndef ULINUX_TYPES_POSIX_H
2 #define ULINUX_TYPES_POSIX_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7
8 #define uint8_t ulinux_u8
9 #define uint16_t ulinux_u16
10 #define uint32_t ulinux_u32
11 #define uint64_t ulinux_u64
12 #endif
File ulinux/utils/ascii/ascii.h added (mode: 100644) (index 0000000..31970b0)
1 #ifndef ULINUX_UTILS_ASCII_ASCII_H
2 #define ULINUX_UTILS_ASCII_ASCII_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 #define ulinux_dec2ut_blk ulinux_dec2u8
8 #define ulinux_dec2us_blk ulinux_dec2u16_blk
9 #define ulinux_dec2us ulinux_dec2u16
10 #if BITS_PER_LONG==64
11 #define ulinux_dec2ul_blk ulinux_dec2u64_blk
12 #define ulinux_dec2ul ulinux_dec2u64
13 #else
14 #define ulinux_dec2ul_blk ulinux_dec2u32_blk
15 #define ulinux_dec2ul ulinux_dec2u32
16 #endif
17 #define ulinux_dec2ull_blk ulinux_dec2u64_blk
18 #define ulinux_dec2ull ulinux_dec2u64
19
20 /* XXX:may use linux ctype ascii table */
21 static inline bool ulinux_is_digit(ulinux_u8 c)
22 {
23 if ('0' <= c && c<= '9')
24 return true;
25 return false;
26 }
27
28 static inline bool ulinux_is_alnum(ulinux_u8 c)
29 {
30 if ('0' <= c && c <= '9')
31 return true;
32 if ('A' <= c && c <= 'Z')
33 return true;
34 if ('a' <= c && c <= 'z')
35 return true;
36 return false;
37 }
38
39 static inline bool ulinux_is_lower(ulinux_u8 c)
40 {
41 if ('a' <= c && c <= 'z')
42 return true;
43 return false;
44 }
45
46 static inline bool ulinux_is_upper(ulinux_u8 c)
47 {
48 if ('A' <= c && c <= 'Z')
49 return true;
50 return false;
51 }
52
53 static inline bool ulinux_is_alpha(ulinux_u8 c)
54 {
55 if ('A' <= c && c <= 'Z')
56 return true;
57 if ('a' <= c && c<= 'z')
58 return true;
59 return false;
60 }
61
62 static inline bool ulinux_is_blank(ulinux_u8 c)
63 {
64 if (c == ' ' || c == '\t')
65 return true;
66 return false;
67 }
68
69 static inline bool ulinux_is_space(ulinux_u8 c)
70 {
71 /* see ascii table */
72 if ( ('\t' <= c && c <= '\r') || (c == ' '))
73 return true;
74 return false;
75 }
76
77 static inline bool ulinux_is_xdigit(ulinux_u8 c)
78 {
79 if ('0' <= c && c <= '9')
80 return true;
81 if ('A' <= c && c <= 'F')
82 return true;
83 if ('a' <= c && c <= 'f')
84 return true;
85 return false;
86 }
87
88 static inline bool ulinux_is_cntrl(ulinux_u8 c)
89 {
90 if (c <= 0x1f || c == 0x7f)
91 return true;
92 return false;
93 }
94
95 static inline bool ulinux_is_punct(ulinux_u8 c)
96 {
97 if (('!' <= c && c <= '/') || (':' <= c && c <= '@')
98 || ('[' <= c && c <= '`') || ('{' <= c && c <= '~'))
99 return true;
100 return false;
101 }
102
103 /* XXX: send back the base ascii char and not a boolean ! */
104 static inline ulinux_u8 ulinux_is_hex(ulinux_u8 c)
105 {
106 if ('0' <= c && c <= '9')
107 return '0';
108 if ('A' <= c && c <= 'F')
109 return 'A';
110 if ('a' <= c && c <= 'z')
111 return 'a';
112 return 0;
113 }
114
115 static inline bool ulinux_is_print(ulinux_u8 c)
116 {
117 if (' ' <= c && c <= '~')
118 return true;
119 return false;
120 }
121
122 static inline bool ulinux_is_graph(ulinux_u8 c)
123 {
124 if ('!' <= c && c <= '~')
125 return true;
126 return false;
127 }
128
129 static inline ulinux_u8 ulinux_2upper(ulinux_u8 c)
130 {
131 if (ulinux_is_lower(c))
132 c &= ~0x20;
133 return c;
134 }
135
136 static inline ulinux_u8 ulinux_2lower(ulinux_u8 c)
137 {
138 if (ulinux_is_upper(c))
139 c |= 0x20;
140 return c;
141 }
142 #endif
File ulinux/utils/ascii/block/conv/binary/binary.c added (mode: 100644) (index 0000000..67bf0ab)
1 #ifndef ULINUX_UTILS_ASCII_BLOCK_CONV_BINARY_BINARY_C
2 #define ULINUX_UTILS_ASCII_BLOCK_CONV_BINARY_BINARY_C
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 #include <stdbool.h>
8
9 #include <ulinux/compiler_types.h>
10 #include <ulinux/types.h>
11
12 /*----------------------------------------------------------------------------*/
13 /* "One Compilation Unit" support */
14 #ifdef ULINUX_UTILS_EXTERNAL
15 #define ULINUX_EXPORT
16 #else
17 #define ULINUX_EXPORT static
18 #endif
19 /*----------------------------------------------------------------------------*/
20
21 /*----------------------------------------------------------------------------*/
22 /* local */
23 #define loop for(;;)
24 #define CSTRLEN(cstr) (sizeof(cstr) - 1)
25 /*----------------------------------------------------------------------------*/
26
27 /*
28 * strict unsigned binary ascii block to u16
29 * caller must provide a valid memory block
30 * inplace conversion: ok
31 */
32 ULINUX_EXPORT bool ulinux_bin2u16_blk(ulinux_u16 *dest, ulinux_u8 *start,
33 ulinux_u8 *last)
34 {/* do *not* trust content */
35 if ((ulinux_u64)(last - start) >= CSTRLEN("1111111111111111"))
36 return false;
37
38 *dest = 0;
39 loop {
40 if (start > last)
41 break;
42
43 if (*last != '0' && *last != '1')
44 return false;
45 *dest = (*dest << 1) | (*start - '0');
46 ++start;
47 }
48 /*no overflow*/
49 return true;
50 }
51
52 /*----------------------------------------------------------------------------*/
53 /* local cleanup*/
54 #undef loop
55 #undef CSTRLEN
56 /*----------------------------------------------------------------------------*/
57 #undef ULINUX_EXPORT
58 #endif
File ulinux/utils/ascii/block/conv/binary/binary.h added (mode: 100644) (index 0000000..05da9a1)
1 #ifndef ULINUX_UTILS_ASCII_BLOCK_CONV_BINARY_BINARY_H
2 #define ULINUX_UTILS_ASCII_BLOCK_CONV_BINARY_BINARY_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7
8 /*----------------------------------------------------------------------------*/
9 /* "One Compilation Unit" support */
10 #ifdef ULINUX_UTILS_EXTERNAL
11 #define ULINUX_EXPORT extern
12 #else
13 #define ULINUX_EXPORT static
14 #endif
15 /*----------------------------------------------------------------------------*/
16
17 ULINUX_EXPORT bool ulinux_bin_to_u16_blk(ulinux_u16 *dest, ulinux_u8 *start,
18 ulinux_u8 *last);
19 #undef ULINUX_EXPORT
20 #endif
File ulinux/utils/ascii/block/conv/decimal/decimal.c added (mode: 100644) (index 0000000..2f65559)
1 #ifndef ULINUX_UTILS_ASCII_BLOCK_CONV_DECIMAL_DECIMAL_C
2 #define ULINUX_UTILS_ASCII_BLOCK_CONV_DECIMAL_DECIMAL_C
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 #include <stdbool.h>
8
9 #include <ulinux/compiler_types.h>
10 #include <ulinux/types.h>
11
12 #include <ulinux/utils/ascii/ascii.h>
13
14 /*----------------------------------------------------------------------------*/
15 /* "One Compilation Unit" support */
16 #ifdef ULINUX_UTILS_EXTERNAL
17 #define ULINUX_EXPORT
18 #else
19 #define ULINUX_EXPORT static
20 #endif
21 /*----------------------------------------------------------------------------*/
22
23 /*----------------------------------------------------------------------------*/
24 /* local */
25 #define loop for(;;)
26 #define CSTRLEN(cstr) (sizeof(cstr) - 1)
27 /*----------------------------------------------------------------------------*/
28
29 /*
30 * strict unsigned decimal ascii block to byte
31 * caller must provide a valid memory block
32 * inplace conversion: ok
33 */
34 ULINUX_EXPORT bool ulinux_dec2u8_blk(ulinux_u8 *dest, ulinux_u8 *start,
35 ulinux_u8 *last)
36 {/* do *not* trust content */
37 ulinux_u16 buf;
38
39 if ((ulinux_u64)(last - start) >= CSTRLEN("255"))
40 return false;
41 buf = 0;
42 loop {
43 if (start > last)
44 break;
45
46 if (!ulinux_is_digit(*start))
47 return false;
48 buf = buf * 10 + (*start - '0');
49 ++start;
50 }
51 /* overflow, max is 999 way below what can do a u16 */
52 if (buf & 0xff00)
53 return false;
54 *dest = (ulinux_u8)buf;
55 return true;
56 }
57
58 /*
59 * strict unsigned decimal ascii block to u16
60 * caller must provide a valid memory block
61 * inplace conversion: ok
62 */
63 ULINUX_EXPORT bool ulinux_dec2u16_blk(ulinux_u16 *dest, ulinux_u8 *start,
64 ulinux_u8 *last)
65 {/* do *not* trust content */
66 ulinux_u32 buf;
67
68 if ((ulinux_u64)(last - start) >= CSTRLEN("65535"))
69 return false;
70 buf = 0;
71 loop {
72 if (start > last)
73 break;
74
75 if (!ulinux_is_digit(*start))
76 return 0;
77 buf = buf * 10 + (*start - '0');
78 ++start;
79 }
80 /* overflow, max is 99999 way below what can do a u32 */
81 if (buf & 0xffff0000)
82 return false;
83 *dest = (ulinux_u16)buf;
84 return true;
85 }
86
87 /*
88 * strict unsigned decimal ascii block to u32
89 * caller must provide a valid memory block
90 * inplace conversion: ok
91 */
92 ULINUX_EXPORT bool ulinux_dec2u32_blk(ulinux_u32 *dest, ulinux_u8 *start,
93 ulinux_u8 *last)
94 {/* do *not* trust content */
95 ulinux_u64 buf;
96
97 if ((ulinux_u64)(last - start) >= CSTRLEN("4294967295"))
98 return false;
99 buf = 0;
100 loop {
101 if (start > last)
102 break;
103
104 if (!ulinux_is_digit(*start))
105 return false;
106 buf = buf * 10 + (*start - '0');
107 ++start;
108 }
109 /* overflow, max is 9999999999 way below what can do a u64 */
110 if (buf & 0xffffffff00000000)
111 return false;
112 *dest = (ulinux_u32)buf;
113 return true;
114 }
115
116 /*
117 * strict unisgned decimal ascii block to u64
118 * caller must provide a valid memory block
119 * inplace conversion: ok
120 */
121 ULINUX_EXPORT bool ulinux_dec2u64_blk(ulinux_u64 *dest, ulinux_u8 *start,
122 ulinux_u8 *last)
123 {/* do *not* trust */
124 ulinux_u64 buf;
125
126 if ((ulinux_u64)(last - start) >= CSTRLEN("18446744073709551615"))
127 return false;
128 buf = 0;
129 loop {
130 ulinux_u64 old_buf;
131
132 if(start > last)
133 break;
134
135 if(!ulinux_is_digit(*start))
136 return false;
137
138 old_buf = buf;
139 buf = buf * 10 + (*start - '0');
140 if (buf < old_buf) /* overflow check */
141 return false;
142 ++start;
143 }
144 *dest = buf;
145 return true;
146 }
147
148 /*----------------------------------------------------------------------------*/
149 /* local cleanup*/
150 #undef loop
151 #undef CSTRLEN
152 /*----------------------------------------------------------------------------*/
153 #undef ULINUX_EXPORT
154 #endif
File ulinux/utils/ascii/block/conv/decimal/decimal.h added (mode: 100644) (index 0000000..518136a)
1 #ifndef ULINUX_UTILS_ASCII_BLOCK_CONV_DECIMAL_DECIMAL_H
2 #define ULINUX_UTILS_ASCII_BLOCK_CONV_DECIMAL_DECIMAL_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7
8 /*----------------------------------------------------------------------------*/
9 /* "One Compilation Unit" support */
10 #ifdef ULINUX_UTILS_EXTERNAL
11 #define ULINUX_EXPORT extern
12 #else
13 #define ULINUX_EXPORT static
14 #endif
15 /*----------------------------------------------------------------------------*/
16
17 ULINUX_EXPORT bool ulinux_dec2u8_blk(ulinux_u8 *dest, ulinux_u8 *start,
18 ulinux_u8 *last);
19 ULINUX_EXPORT bool ulinux_dec2u16_blk(ulinux_u16 *dest, ulinux_u8 *start,
20 ulinux_u8 *last);
21 ULINUX_EXPORT bool ulinux_dec2u32_blk(ulinux_u32 *dest, ulinux_u8 *start,
22 ulinux_u8 *last);
23 ULINUX_EXPORT bool ulinux_dec2u64_blk(ulinux_u64 *dest, ulinux_u8 *start,
24 ulinux_u8 *last);
25 #undef ULINUX_EXPORT
26 #endif
File ulinux/utils/ascii/block/conv/hexadecimal/hexadecimal.c added (mode: 100644) (index 0000000..e4afe6f)
1 #ifndef ULINUX_UTILS_ASCII_BLOCK_CONV_HEXADECIMAL_HEXADECIMAL_C
2 #define ULINUX_UTILS_ASCII_BLOCK_CONV_HEXADECIMAL_HEXADECIMAL_C
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 #include <stdbool.h>
8
9 #include <ulinux/compiler_types.h>
10 #include <ulinux/types.h>
11
12 #include <ulinux/utils/ascii/ascii.h>
13
14 /*----------------------------------------------------------------------------*/
15 /* "One Compilation Unit" support */
16 #ifdef ULINUX_UTILS_EXTERNAL
17 #define ULINUX_EXPORT
18 #else
19 #define ULINUX_EXPORT static
20 #endif
21 /*----------------------------------------------------------------------------*/
22
23 /*----------------------------------------------------------------------------*/
24 /* local */
25 #define loop for(;;)
26 #define CSTRLEN(cstr) (sizeof("ffff") - 1)
27 /*----------------------------------------------------------------------------*/
28
29 /* caller must provide a valid memory block */
30 ULINUX_EXPORT bool ulinux_hex_to_u16_blk(ulinux_u16 *dest, ulinux_u8 *start,
31 ulinux_u8 *last)
32 {/* do *not* trust content */
33 if ((ulinux_u64)(last - start + 1) > CSTRLEN("ffff"))
34 return false;
35
36 *dest = 0;
37 loop {
38 ulinux_u8 base;
39
40 if (start > last)
41 break;
42
43 base = ulinux_is_hex(*start);
44 if (base == 0)
45 return false;
46
47 *dest = (*dest << 4) + (*start - base);
48 if ((base & 0x40) != 0) /* 'A' or 'a' are 0x41 and '0x61' */
49 *dest += 0x0a;
50 ++start;
51 }
52 /* no overflow */
53 return true;
54 }
55
56 /*----------------------------------------------------------------------------*/
57 /* local cleanup */
58 #undef loop
59 #undef CSTRLEN
60 /*----------------------------------------------------------------------------*/
61 #undef ULINUX_EXPORT
62 #endif
File ulinux/utils/ascii/block/conv/hexadecimal/hexadecimal.h added (mode: 100644) (index 0000000..7f67182)
1 #ifndef ULINUX_UTILS_ASCII_BLOCK_CONV_HEXADECIMAL_HEXADECIMAL_H
2 #define ULINUX_UTILS_ASCII_BLOCK_CONV_HEXADECIMAL_HEXADECIMAL_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7
8 /*----------------------------------------------------------------------------*/
9 /* "One Compilation Unit" support */
10 #ifdef ULINUX_UTILS_EXTERNAL
11 #define ULINUX_EXPORT extern
12 #else
13 #define ULINUX_EXPORT static
14 #endif
15 /*----------------------------------------------------------------------------*/
16
17 ULINUX_EXPORT bool ulinux_hex_to_u16_blk(ulinux_u16 *dest, ulinux_u8 *start,
18 ulinux_u8 *last);
19 #undef ULINUX_EXPORT
20 #endif
21
File ulinux/utils/ascii/block/conv/net/net.c added (mode: 100644) (index 0000000..3d0cc72)
1 #ifndef ULINUX_UTILS_ASCII_BLOCK_CONV_NET_NET_C
2 #define ULINUX_UTILS_ASCII_BLOCK_CONV_NET_NET_C
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 /*----------------------------------------------------------------------------*/
8 #include <stdbool.h>
9 /*----------------------------------------------------------------------------*/
10 #include <ulinux/compiler_types.h>
11 #include <ulinux/types.h>
12 /*----------------------------------------------------------------------------*/
13 #include <ulinux/utils/mem.h>
14 #include <ulinux/utils/ascii/block/conv/decimal/decimal.h>
15 #include <ulinux/utils/ascii/block/conv/hexadecimal/hexadecimal.h>
16 #include <ulinux/utils/endian.h>
17 /*----------------------------------------------------------------------------*/
18 #include <ulinux/utils/ascii/block/conv/decimal/decimal.c>
19 #include <ulinux/utils/ascii/block/conv/hexadecimal/hexadecimal.c>
20
21 /*----------------------------------------------------------------------------*/
22 /* "One Compilation Unit" support */
23 #ifdef ULINUX_UTILS_EXTERNAL
24 #define ULINUX_EXPORT
25 #else
26 #define ULINUX_EXPORT static
27 #endif
28 /*----------------------------------------------------------------------------*/
29
30 /******************************************************************************/
31 /* some basic debug/trace stuff */
32 #if 0
33 #include <stdarg.h>
34 #include <ulinux/sysc.h>
35 #include <ulinux/utils/ascii/string/vsprintf.h>
36 #define BUFSIZ 8192
37 static ulinux_u8 dprintf_buf[BUFSIZ];
38 #define PERR(fmt,...) ulinux_dprintf(2,dprintf_buf,BUFSIZ,fmt,__VA_ARGS__)
39 #endif
40 /******************************************************************************/
41 /* local */
42 #define loop for(;;)
43 /*----------------------------------------------------------------------------*/
44 /*
45 * strict ipv4 (xxx.xxx.xxx.xxx) decimal ascii block to 32 bits big endian
46 * (network endian) ipv4
47 * caller must provide a valid memory block (start <= last)
48 * inplace conversion: ok because minimal address is 7 bytes to 4 bytes
49 */
50 ULINUX_EXPORT bool ulinux_to_ipv4_blk(ulinux_u32 *dest, ulinux_u8 *start,
51 ulinux_u8 *last)
52 {/* do *not* trust content */
53 ulinux_u32 ipv4;
54 ulinux_u8 *n_start;
55 ulinux_u8 *n_end;
56 ulinux_u8 u;
57 ulinux_u8 i;
58
59 ipv4 = 0;
60 n_start = start;
61 n_end = start;
62 i = 0;
63 loop {
64 if (i > 2)
65 break;
66
67 if (*n_end == '.')
68 return false;
69
70 loop {
71 if ((n_end > last) || ((n_end - n_start) > 3)
72 || (*n_end == '.'))
73 break;
74 ++n_end;
75 }
76
77 if ((n_end == last) || (*n_end != '.'))
78 return false;
79
80 u = 0;
81 if (!ulinux_dec2u8_blk(&u, n_start, n_end - 1))
82 return false;
83 ipv4 |= u << (24 - (i * 8));
84
85 n_start = n_end + 1;
86 n_end = n_start;
87
88 ++i;
89 }
90
91 u = 0;
92 if (!ulinux_dec2u8_blk(&u, n_start, last))
93 return false;
94 ipv4 |= u;
95 *dest = ulinux_cpu_to_be32(ipv4);
96 return true;
97 }
98
99 /*
100 * "good enough" conversion
101 * expect a valid memory block ( start <= last )
102 * there is probably a way to use malformed address for attacks
103 */
104 #define CSTRLEN(cstr) (sizeof(cstr) - 1)
105 #define GROUP_IDX_MAX 7
106 #define u8 ulinux_u8
107 #define u16 ulinux_u16
108 #define hex_to_u16 ulinux_hex_to_u16_blk
109 #define cpu_to_be16 ulinux_cpu_to_be16
110 #define memset ulinux_memset
111 ULINUX_EXPORT bool ulinux_to_ipv6_blk(u8 *dest, u8 *start, u8 *last)
112 {/* do *not* trust content */
113 u8 *c; /* Colmun/Cursor */
114 u8 *group_start;
115 u8 *group_last;
116 u8 group_next_idx;
117 u16 *groups;
118 u8 *compression_mark;
119 u8 backward_group_idx_min;
120
121 #define COMPRESSION_MARK "::"
122 if ((last - start + 1) < CSTRLEN(COMPRESSION_MARK))
123 return false;
124 if (CSTRLEN("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx")
125 < (last - start + 1))
126 return false;
127
128 memset(dest, 0, 16);
129 groups = (u16*)dest;
130
131 /*--------------------------------------------------------------------*/
132 /*
133 * forward loop, we bump on:
134 * - last char.
135 * - the compression mark.
136 */
137 c = start;
138 group_start = start;
139 group_last = 0;
140 group_next_idx = 0;
141 compression_mark = 0;
142 loop {
143 if (c == last) {
144 group_last = last;
145 } else if (c[0] == ':') {
146 /* we are not the last char, we can peek */
147 if (c[1] == ':') {
148 compression_mark = c;
149 /* compression mark at the start */
150 if (c == start)
151 break; /* go to backward loop */
152 }
153
154 if (c == start) /* garbage ':' */
155 return false;
156 group_last = c - 1;
157 }
158
159 if (group_last != 0) {
160 u16 cpu_u16; /* cpu endian u16 or group */
161
162 if (!hex_to_u16(&cpu_u16, group_start, group_last))
163 return false;
164
165 #define group_idx group_next_idx
166 groups[group_idx] = cpu_to_be16(cpu_u16);
167
168 if (group_last == last || group_idx == GROUP_IDX_MAX)
169 if (group_last == last
170 && group_idx == GROUP_IDX_MAX)
171 return true;
172 else
173 return false;
174 #undef group_idx
175 ++group_next_idx;
176
177 if (compression_mark != 0)
178 break; /* go to backward loop */
179
180 group_start = group_last + 2; /* skip the ':' */
181 group_last = 0;
182 c = group_start;
183 } else
184 ++c;
185 }
186
187 ++compression_mark; /* point on the second ':' */
188 if (compression_mark == last) /* compression mark an the end */
189 return true;
190
191 /* account at least 1 zero group for the compression mark */
192 backward_group_idx_min = group_next_idx + 1;
193
194 /*--------------------------------------------------------------------*/
195 /*
196 * backward loop, we bump on:
197 * - the not-at-the-end compression mark (actually its second ':').
198 * - the minimum group idx allowed based on the compression mark
199 * location found in the forward loop.
200 */
201 c = last;
202 group_start = 0;
203 group_last = last;
204 group_next_idx = 7;
205 loop {
206 if (c[0] == ':') {
207 if (c == group_last) /* garbage ':' */
208 return false;
209 group_start = c + 1;
210 }
211
212 if (group_start != 0) {
213 ulinux_u16 cpu_u16; /* cpu endian u16 or group */
214
215 if (!hex_to_u16(&cpu_u16, group_start, group_last))
216 return false;
217
218 #define group_idx group_next_idx
219 groups[group_idx] = cpu_to_be16(cpu_u16);
220
221 if ((group_start - 1) == compression_mark)
222 break;
223
224 if (group_idx == backward_group_idx_min) {
225 /*
226 * maximum count of groups converted, then we
227 * must have reached the compression mark
228 */
229 if ((group_start - 1) != compression_mark)
230 return false;
231 break;
232 }
233 #undef group_idx
234 group_next_idx--;
235
236 group_last = group_start - 2; /* skip the ':' */
237 group_start = 0;
238 c = group_last;
239 } else
240 c--;
241 }
242 return true;
243 }
244 #undef COMPRESSION_MARK
245 #undef CSTRLEN
246 #undef GROUP_IDX_MAX
247 #undef u8
248 #undef u16
249 #undef hex_to_u16
250 #undef cpu_to_be16
251 #undef memset
252
253 /*----------------------------------------------------------------------------*/
254 /* local cleanup */
255 #undef loop
256 /*----------------------------------------------------------------------------*/
257 #undef ULINUX_EXPORT
258 #endif
File ulinux/utils/ascii/block/conv/net/net.h added (mode: 100644) (index 0000000..ea7f03f)
1 #ifndef ULINUX_UTILS_ASCII_BLOCK_CONV_NET_NET_H
2 #define ULINUX_UTILS_ASCII_BLOCK_CONV_NET_NET_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7
8 /*----------------------------------------------------------------------------*/
9 /* "One Compilation Unit" support */
10 #ifdef ULINUX_UTILS_EXTERNAL
11 #define ULINUX_EXPORT extern
12 #else
13 #define ULINUX_EXPORT static
14 #endif
15 /*----------------------------------------------------------------------------*/
16
17 ULINUX_EXPORT bool ulinux_to_ipv4_blk(ulinux_u32 *dest, ulinux_u8 *start,
18 ulinux_u8 *last);
19 ULINUX_EXPORT bool ulinux_to_ipv6_blk(ulinux_u8 *dest, ulinux_u8 *start,
20 ulinux_u8 *last);
21 #undef ULINUX_EXPORT
22 #endif
File ulinux/utils/ascii/match/match.c added (mode: 100644) (index 0000000..a62515c)
1 #ifndef ULINUX_UTILS_ASCII_MATCH_MATCH_C
2 #define ULINUX_UTILS_ASCII_MATCH_MATCH_C
3 /*
4 * This is a derived work based on GNU glibc implementation on 20130409.
5 * Switch to GNU Lesser GPLv3 protection.
6 * author:Sylvain BERTRAND
7 */
8 /******************************************************************************/
9 /*
10 * NOTE:do *NOT* even try to read that code without ksh extended glob
11 * specifications, and keeping an eye on the abbreviations below
12 *
13 * upstream code is hard to grasp
14 */
15 /******************************************************************************/
16 #include <stdbool.h>
17 #include <ulinux/compiler_types.h>
18 #include <ulinux/types.h>
19 #include <ulinux/sysc.h>
20 #include <ulinux/error.h>
21
22 #include <ulinux/utils/mem.h>
23 #include <ulinux/utils/ascii/ascii.h>
24 #include <ulinux/utils/ascii/string/string.h>
25 #include <ulinux/utils/ascii/match/match.h>
26 #include <ulinux/mmap.h>
27
28 /*----------------------------------------------------------------------------*/
29 /* "One Compilation Unit" support */
30 #ifdef ULINUX_UTILS_EXTERNAL
31 #define ULINUX_EXPORT
32 #else
33 #define ULINUX_EXPORT static
34 #endif
35 /*----------------------------------------------------------------------------*/
36
37 /*----------------------------------------------------------------------------*/
38 /* ulinux namespace */
39 #define loop for(;;)
40 #define ANONYMOUS ULINUX_MAP_ANONYMOUS
41 #define CASEFOLD ULINUX_MATCH_CASEFOLD
42 #define ERR ULINUX_MATCH_ERR
43 #define ERR_NOMEM ULINUX_MATCH_ERR_NOMEM
44 #define EXTMATCH ULINUX_MATCH_EXTMATCH
45 #define is_alnum ulinux_is_alnum
46 #define is_alpha ulinux_is_alpha
47 #define is_blank ulinux_is_blank
48 #define is_cntrl ulinux_is_cntrl
49 #define is_digit ulinux_is_digit
50 #define is_graph ulinux_is_graph
51 #define is_lower ulinux_is_lower
52 #define is_print ulinux_is_print
53 #define is_punct ulinux_is_punct
54 #define is_space ulinux_is_space
55 #define is_upper ulinux_is_upper
56 #define is_xdigit ulinux_is_xdigit
57 #define ISERR ULINUX_ISERR
58 #define sl ulinux_sl
59 #define MATCH ULINUX_MATCH_MATCH
60 #define memchr ulinux_memchr
61 #define memcpy ulinux_memcpy
62 #define mmap(a,b,c) ulinux_sysc(mmap,6,0,a,b,c,-1,0)
63 #define mremap(a,b,c) ulinux_sysc(mremap,4,a,b,c,0)
64 #define munmap(a,b) ulinux_sysc(munmap,2,a,b)
65 #define NOMATCH ULINUX_MATCH_NOMATCH
66 #define PRIVATE ULINUX_MAP_PRIVATE
67 #define RD ULINUX_PROT_READ
68 #define s64 ulinux_s64
69 #define s8 ulinux_s8
70 #define u16 ulinux_u16
71 #define u64 ulinux_u64
72 #define u8 ulinux_u8
73 #define strcat ulinux_strcat
74 #define strcmp ulinux_strcmp
75 #define strlen ulinux_strlen
76 #define WR ULINUX_PROT_WRITE
77 /*----------------------------------------------------------------------------*/
78 /* local symbols and types */
79 #define match_params ulinux_utils_ascii_match_match_params
80 #define fold ulinux_utils_ascii_match_fold
81 #define endp ulinux_utils_ascii_match_endp
82 #define star_handler ulinux_utils_ascii_match_star_handler
83 #define bracket_skip ulinux_utils_ascii_match_bracket_skip
84 #define bracket_matched ulinux_utils_ascii_match_bracket_matched
85 #define bracket_normal ulinux_utils_ascii_match_bracket_normal
86 #define bracket_char_class_get ulinux_utils_ascii_match_bracket_char_class_get
87 #define bracket_escape ulinux_utils_ascii_match_bracket_escape
88 #define bracket_class ulinux_utils_ascii_match_bracket_class
89 #define bracket_handler ulinux_utils_ascii_match_bracket_handler
90 #define question_mark_handler ulinux_utils_ascii_match_question_mark_handler
91 #define misc_handler ulinux_utils_ascii_match_misc_handler
92 #define escape_handler ulinux_utils_ascii_match_escape_handler
93 #define special_char ulinux_utils_ascii_match_special_char
94 #define match ulinux_utils_ascii_match_match
95 #define p ulinux_utils_ascii_match_p
96 #define ep ulinux_utils_ascii_match_ep
97 #define ep_p_new ulinux_utils_ascii_match_ep_p_new
98 #define ep_p_get ulinux_utils_ascii_match_ep_p_get
99 #define ep_p_next ulinux_utils_ascii_match_ep_p_next
100 #define ep_split ulinux_utils_ascii_match_ep_split
101 #define match_at_least_once ulinux_utils_ascii_match_match_at_least_once
102 #define match_only_once ulinux_utils_ascii_match_match_only_once
103 #define match_none ulinux_utils_ascii_match_match_none
104 #define extended_match_try ulinux_utils_ascii_match_extended_match_try
105 /*----------------------------------------------------------------------------*/
106 /*
107 * ABBREVIATIONS
108 * addr address
109 * c character
110 * char(s) character(s)
111 * cur current
112 * ep(s) extended pattern(s)
113 * err error
114 * nomem no memory
115 * of offset
116 * p(s) pattern(s)
117 * params parameters
118 * pc pattern char
119 * r return value
120 * rd read
121 * rem remainder
122 * sc string char
123 * str string
124 * sz size
125 * wr write
126 */
127 /*----------------------------------------------------------------------------*/
128 #define CHAR_CLASS_MAX (sizeof("xdigit") - 1)
129 #define STREQ(s1,s2) (strcmp(s1, s2) == 0)
130 /*----------------------------------------------------------------------------*/
131 /* return values */
132 /*#define ULINUX_MATCH_ERR_NOMEM -3*/
133 /*#define ULINUX_MATCH_ERR -2*/
134 #define NO_VALID_P -1
135 /*#define ULINUX_MATCH_MATCH 0*/
136 #define OK 0
137 /*#define ULINUX_MATCH_NOMATCH 1*/
138 /*----------------------------------------------------------------------------*/
139 /*
140 * In the context a match call, it's used to store the location of the
141 * "ending" * following, at the same depth, a "starting" *.
142 * The matcher is locked in the star_handler between 2 stars at the
143 * same depth.
144 */
145 struct match_params {
146 void *p;
147 void *str;
148 };
149
150 static u8 fold(u8 c, u8 flgs)
151 {
152 if(!(flgs & CASEFOLD))
153 return c;
154 return ulinux_2lower(c);
155 }
156
157 /*
158 * Recursively skip a p. Return a pointer right after it, or a pointer on the
159 *start of the p to skip if the 0 terminating char is encountered before the
160 * end of the p.
161 */
162 static u8 *end_p(u8 *p)
163 {
164 u8 *pc = p;
165 loop {
166 if (*++pc == '\0')
167 return p; /* this is an invalid p */
168 else if (*pc == '[') {/* handle brackets special */
169 /*
170 * Skip the not sign. We have to recognize it because of
171 * a possibly following ']'.
172 */
173 if ((*++pc == '!') || (*pc == '^'))
174 ++pc;
175 if(*pc == ']')
176 ++pc; /* a leading ']' is recognized as such */
177 /* skip over all chars of the list */
178 loop {
179 if (*pc == ']')
180 break;
181 if(*pc++ == '\0')
182 return p; /* this is no valid p */
183 }
184 } else if (((*pc == '?') || (*pc == '*') || (*pc == '+')
185 || (*pc == '@') || (*pc == '!')) && (pc[1] == '(')) {
186 pc = end_p(pc + 1);
187 } else if (*pc == ')') {
188 break;
189 }
190 }
191 return pc + 1;
192 }
193
194 static s8 extended_match_try(u8 type, u8 *p, u8 *str, u8 *str_end, u8 flgs);
195 static s8 match(u8 *p, u8 *str, u8 *str_end, u8 flgs,
196 struct match_params *end_star);
197
198 /*----------------------------------------------------------------------------*/
199 /* return value for the following handlers */
200 #define BIT(x) (1 << x)
201 #define R_GET(r) ((s8)(r & 0xff))
202 #define R_SET(r) ((u16)(r & 0xff))
203 #define RETURN_R BIT(9)
204 #define MATCH_NORMAL BIT(10)
205 #define NEXT_STR_CHAR BIT(11)
206 #define NEXT_P_CHAR BIT(12)
207 #define TEST_STR_END_REACHED BIT(13)
208 /*----------------------------------------------------------------------------*/
209
210 static u16 star_handler(u8 *c, u8 **pc, u8 **sc, u8 *str_end, u8 flgs,
211 struct match_params *end_star)
212 {
213 struct match_params local_end_star;
214
215 if ((flgs & EXTMATCH) && (**pc == '(')) {
216 s8 r = extended_match_try(*c, *pc, *sc, str_end, flgs);
217 if (r != NO_VALID_P)
218 return RETURN_R | R_SET(r);
219 } else if (end_star) {
220 /* this star will exit the current star context matching */
221 end_star->p = *pc - 1;
222 end_star->str = *sc;
223 return RETURN_R | R_SET(MATCH);
224 }
225
226 loop {
227 *c = *(*pc)++;
228
229 /*
230 * do "absorb" in the current * the following sequence of
231 * ?,*,?() and *()
232 */
233 if ((*c != '?') && (*c != '*'))
234 break;
235
236 /*
237 * ?() and *() are "zero or one|more" occurences of matched
238 * patterns, then absorbed them in the *
239 */
240 if ((**pc == '(') && (flgs & EXTMATCH)) {
241 u8 *endp = end_p(*pc);
242 if (endp != *pc) { /* This is a p. Skip over it */
243 *pc = endp;
244 continue;
245 }
246 }
247
248 if (*c == '?') { /* match one any char from the string */
249 /* a ? needs to match one char */
250 if (*sc == str_end) {
251 /* there isn't another char; no match */
252 return RETURN_R | R_SET(NOMATCH);
253 } else {
254 /*
255 * one char of the str is consumed in matching
256 * this ? wildcard, so *??? won't match if there
257 * are less than three chars
258 */
259 ++(*sc);
260 }
261 }
262 }
263
264 /* the wildcard(s) is/are the last element of the p flag is set */
265 if (*c == '\0')
266 return RETURN_R | R_SET(MATCH);
267
268 local_end_star.p = 0;
269
270 if ((*c == '[') || ((flgs & EXTMATCH) && ((*c == '@') || (*c == '+')
271 || (*c=='!')) && (**pc == '('))) {
272 /* the * is followed by a bracket or an "not absorbed" ep */
273 (*pc)--;
274 /*
275 * See explanation of star context matching right below. Instead
276 * of a char like below, it's an ep.
277 */
278 loop {
279 s8 r;
280 if (*sc == str_end)
281 break;
282 r = match(*pc, *sc, str_end, flgs, &local_end_star);
283 if (r == MATCH) {
284 if (local_end_star.p == 0)
285 return RETURN_R | R_SET(MATCH);
286 break;
287 }
288 ++(*sc);
289 }
290 } else { /* the * is followed by a "normal" char */
291 if (*c == '\\')
292 *c=**pc;
293 *c = fold(*c, flgs);
294 (*pc)--;
295 /*
296 * scan the str till we find a char which is the same than the
297 * first p char right after the *, then start to match in star
298 * context, namely till we reach the end, or we find another
299 * will will end the matching in that context
300 */
301 loop {
302 if (*sc == str_end)
303 break;
304 if(fold(**sc, flgs) == *c) {
305 s8 r = match(*pc, *sc, str_end, flgs,
306 &local_end_star);
307 if (r == MATCH) {
308 if (local_end_star.p == 0)
309 return RETURN_R | R_SET(MATCH);
310 break;
311 }
312 }
313 ++(*sc);
314 }
315 if (local_end_star.p != 0) {
316 /* we are finish to match the str in star context */
317 *pc = local_end_star.p;
318 *sc = local_end_star.str;
319 return NEXT_P_CHAR;
320 }
321 }
322 /* if we come here no match is possible with the wildcard */
323 return RETURN_R | R_SET(NOMATCH);
324 }
325
326 static u16 bracket_skip(u8 *c, u8 **pc)
327 {
328 loop {
329 ignore_next:
330 *c = *(*pc)++;
331
332 if (*c == '\0') {
333 /* [... (unterminated) loses */
334 return RETURN_R | R_SET(NOMATCH);
335 }
336
337 if (*c == '\\') {
338 if (**pc == '\0')
339 return RETURN_R | R_SET(NOMATCH);
340 /* XXX 1003.2d11 is unclear if this is right */
341 ++(*pc);
342 } else if ((*c == '[') && (**pc == ':')) {
343 u8 char_class_n = 0;
344 u8 *char_class_start_pc = *pc;
345
346 loop {
347 *c = *++(*pc);
348 if (++char_class_n == (CHAR_CLASS_MAX + 1))
349 return RETURN_R | R_SET(NOMATCH);
350
351 if ((**pc == ':') && ((*pc)[1] == ']'))
352 break;
353
354 if ((*c < 'a') || (*c >= 'z')) {
355 /* is_lower(c) && is_weaker_alpha(c) */
356 *pc = char_class_start_pc;
357 goto ignore_next; /* XXX: goto here */
358 }
359 }
360 (*pc) += 2;
361 *c = *(*pc)++;
362 }
363 if (*c == ']')
364 break;
365 }
366 return OK;
367 }
368
369 static u16 bracket_matched(u8 *c, u8 **pc, u8 not)
370 {
371 u16 r = bracket_skip(c, pc);
372 if (r != OK)
373 return r;
374
375 if (not)
376 return RETURN_R | R_SET(NOMATCH);
377 return NEXT_STR_CHAR;
378 }
379
380 /* input:*c may not be folded */
381 static u16 bracket_normal(u8 *c, u8 **pc, u8 not, u8 sc_folded)
382 {
383 u8 c_old;
384 u8 is_range = ((**pc=='-') && ((*pc)[1] != '\0') && ((*pc)[1] != ']'));
385
386 if (!is_range && (*c == sc_folded))
387 return bracket_matched(c, pc, not);
388
389 c_old = *c;
390 *c = *(*pc)++;
391
392 if ((*c == '-') && (**pc != ']')) {
393 u8 c_end = *(*pc)++;
394
395 if (c_end == '\\')
396 c_end = *(*pc)++;
397 if (c_end == '\0')
398 return RETURN_R | R_SET(NOMATCH);
399
400 /* it is a range, ascii collation */
401 if ((c_old <= sc_folded) && (sc_folded <= c_end))
402 return bracket_matched(c, pc, not);
403 *c = *(*pc)++;
404 }
405 return OK;
406 }
407
408 static u16 bracket_char_class_get(u8 *c, u8 **pc, u8 not, u8 sc_folded,
409 u8 *char_class)
410 {
411 u8 char_class_n = 0;
412 u8 *char_class_start_pc = *pc;
413
414 loop {
415 if (char_class_n == (CHAR_CLASS_MAX + 1))
416 return RETURN_R | R_SET(NOMATCH);
417
418 *c = *++(*pc);
419 if ((*c == ':') && ((*pc)[1] == ']')) {
420 (*pc)+=2;
421 break;
422 }
423
424 if ((*c < 'a') || (*c >= 'z')) {
425 /* is_lower(c) && is_weaker_alpha(c) */
426 u16 r;
427 /*
428 * This cannot possibly be a char class name. Rewind and
429 * try to match it as a normal range.
430 */
431 *pc = char_class_start_pc;
432 *c = '[';
433 r = bracket_normal(c, pc, not, sc_folded);
434 if (r != OK)
435 return r;
436 }
437 char_class[char_class_n++] = *c;
438 }
439 char_class[char_class_n] = '\0';
440 return OK;
441 }
442
443 static u16 bracket_escape(u8 *c, u8 **pc, u8 flgs, u8 not, u8 sc_folded)
444 {
445 u16 r;
446
447 if (**pc == '\0')
448 return RETURN_R | R_SET(NOMATCH);
449 *c = fold(**pc, flgs);
450 ++(*pc);
451 r = bracket_normal(c, pc, not, sc_folded);
452 if (r != OK)
453 return r;
454 return OK;
455 }
456
457 /* input: *c=='[' **pc==':' */
458 static u16 bracket_class(u8 *c, u8 **pc, u8 **sc, u8 not, u8 sc_folded)
459 {
460 /*don't forget the 0 terminating char*/
461 u8 char_class[CHAR_CLASS_MAX + 1];
462 u16 r = bracket_char_class_get(c, pc, not, sc_folded, &char_class[0]);
463 if (r != OK)
464 return r;
465
466 if ( (STREQ(char_class,"alnum") && is_alnum(**sc))
467 || (STREQ(char_class,"alpha") && is_alpha(**sc))
468 || (STREQ(char_class,"blank") && is_blank(**sc))
469 || (STREQ(char_class,"cntrl") && is_cntrl(**sc))
470 || (STREQ(char_class,"digit") && is_digit(**sc))
471 || (STREQ(char_class,"graph") && is_graph(**sc))
472 || (STREQ(char_class,"lower") && is_lower(**sc))
473 || (STREQ(char_class,"print") && is_print(**sc))
474 || (STREQ(char_class,"punct") && is_punct(**sc))
475 || (STREQ(char_class,"space") && is_space(**sc))
476 || (STREQ(char_class,"upper") && is_upper(**sc))
477 || (STREQ(char_class,"xdigit") && is_xdigit(**sc)))
478 return bracket_matched(c, pc, not);
479 *c = *(*pc)++;
480 return OK;
481 }
482
483 static u16 bracket_handler(u8 *c, u8 **pc, u8 **sc, void *str_end, u8 flgs)
484 {
485 u8 not;
486 u8 sc_folded;
487
488 u8 *pc_init = *pc;
489 if (*sc == str_end)
490 return RETURN_R | R_SET(NOMATCH);
491
492 not =((**pc == '!') || (**pc == '^'));
493 if (not)
494 ++(*pc);
495
496 sc_folded = fold(**sc, flgs);
497
498 *c = *(*pc)++;
499 loop {
500 if (*c == '\\') {
501 u16 r = bracket_escape(c, pc, flgs, not, sc_folded);
502 if (r != OK)
503 return r;
504 } else if ((*c == '[') && (**pc == ':')) {
505 u16 r = bracket_class(c, pc, sc, not, sc_folded);
506 if (r != OK)
507 return r;
508 } else if (c == '\0') {
509 /*
510 * [ unterminated, rewind and tell above to match normal
511 */
512 *pc = pc_init;
513 *c = '[';
514 return MATCH_NORMAL;
515 } else {
516 u16 r;
517 *c = fold(*c, flgs);
518 r = bracket_normal(c, pc, not, sc_folded);
519 if (r != 0)
520 return r;
521 }
522 if (*c == ']')
523 break;
524 }
525 if (!not)
526 return RETURN_R | R_SET(NOMATCH);
527 return NEXT_STR_CHAR;
528 }
529
530 static u16 question_mark_handler(u8 c, u8 *pc, u8 *sc, void *str_end, u8 flgs)
531 {
532 if ((flgs & EXTMATCH) && (*pc=='(')) {
533 s8 r = extended_match_try(c, pc, sc, str_end, flgs);
534 if (r != NO_VALID_P)
535 return RETURN_R | R_SET(r);
536 }
537 return TEST_STR_END_REACHED;
538 }
539
540 static u16 misc_handler(u8 c, u8 *pc, u8 *sc, void *str_end, u8 flgs)
541 {
542 if ((flgs & EXTMATCH) && (*pc=='(')) {
543 s8 r = extended_match_try(c, pc, sc, str_end, flgs);
544 if (r != NO_VALID_P)
545 return RETURN_R | R_SET(r);
546 }
547 return MATCH_NORMAL;
548 }
549
550 static u16 escape_handler(u8 *c, u8 **pc, u8 flgs)
551 {
552 u16 r = MATCH_NORMAL;
553 *c = *(*pc)++;
554 if (c=='\0')
555 return r | RETURN_R | R_SET(NOMATCH); /*railing \ loses*/
556 *c = fold(*c, flgs);
557 return r;
558 }
559
560 static u16 special_char(u8 *c, u8 **pc, u8 **sc, void *str_end, u8 flgs,
561 struct match_params *end_star)
562 {
563 u16 r = RETURN_R | R_SET(ERR);
564 switch (*c) {
565 case '[':
566 r = bracket_handler(c, pc, sc, str_end, flgs);
567 break;
568 case '*':
569 r = star_handler(c, pc, sc, str_end, flgs, end_star);
570 break;
571 case '?':
572 r = question_mark_handler(*c, *pc, *sc, str_end, flgs);
573 break;
574 case '+':
575 case '@':
576 case '!':
577 r = misc_handler(*c, *pc, *sc, str_end, flgs);
578 break;
579 case '\\':
580 r = escape_handler(c, pc, flgs);
581 break;
582 }
583 return r;
584 }
585
586 /* str_end points right after the last char of str, the '\0' char */
587 static s8 match(u8 *p, u8 *str, u8 *str_end, u8 flgs,
588 struct match_params *end_star)
589 {
590 u8 c;
591
592 u8 *pc = p;
593 u8 *sc = str;
594
595 loop {
596 u16 r;
597
598 c = *pc++;
599 if (c=='\0')
600 break;
601
602 c = fold(c, flgs);
603
604 switch (c) {
605 case '[':
606 case '*':
607 case '?':
608 case '+':
609 case '@':
610 case '!':
611 case '\\':
612 r = special_char(&c, &pc, &sc, str_end, flgs, end_star);
613 break;
614 default:
615 r = MATCH_NORMAL;
616 }
617
618 if (!(r & NEXT_STR_CHAR)) {
619 if (r & RETURN_R)
620 return R_GET(r);
621 if (r & NEXT_P_CHAR)
622 continue;
623 if ((r & MATCH_NORMAL) || (r & TEST_STR_END_REACHED))
624 if (sc == str_end)
625 return NOMATCH;
626 if(r & MATCH_NORMAL)
627 if (c != fold(*sc, flgs))
628 return NOMATCH;
629 }
630 ++sc;
631 }
632
633 if (sc == str_end)
634 return MATCH;
635 return NOMATCH;
636 }
637
638 /*============================================================================*/
639 /* ep */
640 struct p {
641 u64 sz; /* not accounting the 0 terminating char */
642 u8 str[];
643 };
644
645 struct ep {
646 u64 full_p_sz; /* the p sz from which the ep belongs to */
647 struct p *ps;
648 s64 last; /* offset */
649 u64 sz;
650 u8 *p_rem; /* remainder of the p (right and side of the ep) */
651 u8 type;
652 };
653
654 /*
655 * based on the ep type, we may need to book enough room to put a worst case
656 * scenario of a concatenated sub-p with the ep p rem
657 */
658 static s8 ep_p_new(struct ep *ep,u8 *p_str,u64 p_sz)
659 {
660 /*
661 * We will do some p concatenation for the following p types. Then book
662 * room for the worst case scenario.
663 */
664 u64 map_sz;
665 sl addr;
666 struct p *p;
667
668 u64 str_sz = (ep->type == '?') || (ep->type == '@') ? ep->full_p_sz
669 : p_sz;
670
671 if (!ep->ps) {/* first allocation */
672 /* count the 0 terminating char */
673 map_sz = sizeof(*ep->ps) + str_sz + 1;
674 addr = mmap(map_sz, RD | WR,PRIVATE | ANONYMOUS);
675 if (!addr || ISERR(addr))
676 return ERR_NOMEM;
677
678 ep->last=0;
679 } else {
680 struct p *p_last;
681 /* count the 0 terminating char */
682 u64 new_p_sz = sizeof(*ep->ps) + str_sz + 1;
683 map_sz = ep->sz + new_p_sz;
684 addr = mremap(ep->ps, ep->sz, map_sz);
685 if (!addr || ISERR(addr))
686 return ERR_NOMEM; /* ep is unmapped elsewhere */
687
688 p_last=(struct p*)((u8*)(ep->ps) + ep->last);
689 /* count the 0 terminating char */
690 ep->last += sizeof(*p_last) + p_last->sz + 1;
691 }
692 ep->ps = (struct p*)addr;
693 ep->sz = map_sz;
694 p = (struct p*)((u8*)(ep->ps) + ep->last);
695 p->sz = str_sz;
696 memcpy(&p->str[0], p_str, p_sz); /* copy only p_sz chars */
697 p->str[p_sz] = 0; /* set the 0 terminating char */
698 return OK;
699 }
700
701 static struct p *ep_p_get(struct ep *ep, s64 of)
702 {
703 return (struct p*)((u8*)(ep->ps) + of);
704 }
705
706 #define NO_MORE_P -1
707 static s64 ep_p_next(struct ep *ep, s64 p_of)
708 {
709 struct p *p = (struct p*)((u8*)(ep->ps) + p_of);
710 if (ep->sz == p_of + sizeof(*p) + p->sz + 1)
711 return NO_MORE_P;
712 return p_of + sizeof(*p) + p->sz + 1;
713 }
714 /*ep end*/
715 /*============================================================================*/
716
717 /*
718 * This function splits the ep in sub-ps which use '|' char as a separator. Deal
719 * with nested eps. Sub-ps are stored (copied) in a list (the ep struct)
720 * input parameters:
721 * - p to point on the opening ( of the ep
722 * - ep is where the sub-patterns will be stored (copied)
723 * output parameters:
724 * - p will point right after the closing ) fo the ep
725 * - ep will contain copies of all sub-ps of the ep
726 * if successful ep will contain at least one p
727 */
728 static s8 ep_split(u8 *p, struct ep *ep)
729 {
730 void *sub_p_start;
731 s64 depth; /* depth, if we have nested eps */
732
733 s8 r = OK;
734 u8 *pc = p;
735
736 ++pc; /* skip the opening ( */
737 sub_p_start=pc;
738 depth = 0;
739
740 loop {
741 if (depth < 0)
742 break;
743
744 if (*pc == '\0') {
745 r = NO_VALID_P;
746 goto out;
747 }else if (*pc == '[') { /* handle brackets special */
748 /*
749 * Skip the not sign. We have to recognize it because of
750 * a possibly following ']'.
751 */
752 ++pc;
753 if ((*pc == '!') || (*pc == '^'))
754 ++pc;
755
756 if (*pc == ']')
757 ++pc; /* a leading ']' is recognized as such */
758
759 loop { /* skip over all chars of the list */
760 if (*pc == ']')
761 break;
762 if (*pc == '\0') {
763 r = NO_VALID_P;
764 goto out;
765 }
766 ++pc;
767 }
768 } else if (((*pc == '?') || (*pc == '*') || (*pc == '+')
769 || (*pc == '@') || (*pc == '!')) && (pc[1] == '(')) {
770 ++depth; /* remember the nesting depth of nested eps */
771 } else if (*pc==')') {
772 /* this means we found the end of the ep */
773 if (depth ==0 ) {
774 r = ep_p_new(ep, sub_p_start,
775 pc - (u8*)sub_p_start);
776 if (r != OK)
777 goto out;
778 }
779 depth--;
780 } else if(*pc == '|') {
781 if (depth == 0) {
782 r = ep_p_new(ep, sub_p_start,
783 pc - (u8*)sub_p_start);
784 if (r != OK)
785 goto out;
786 sub_p_start =pc + 1;
787 }
788 }
789 ++pc;
790 }
791 /* store a pointer on the rem of the p, right after the closing ) */
792 ep->p_rem = pc;
793 out:
794 return r;
795 }
796
797 static s8 match_at_least_once(struct ep *ep, u8 *p, u8 *str, u8 *str_end,
798 u8 flgs)
799 {
800 s64 cur_p_of = 0;
801 loop {
802 struct p *cur_p = ep_p_get(ep, cur_p_of);
803 u8 *sc = str;
804
805 loop {
806 s8 r;
807
808 if (sc > (u8*)str_end)
809 break;
810
811 /* first match the prefix with the cur p */
812 r = match(cur_p->str, str, sc, flgs, 0);
813 if (r == MATCH) {
814 /*
815 * This was successful. Now match the str rem
816 * with the p rem.
817 */
818 r = match(ep->p_rem, sc, str_end, flgs, 0);
819 if (r == NOMATCH) {
820 /*
821 * Unable to match the p rem with the
822 * str rem, then try to match again the
823 * ep by rewinding the p from the start.
824 * We can because we are to match the ep
825 * more than once
826 */
827 if (sc != str) {
828 r = match((u8*)p - 1, sc,
829 str_end, flgs, 0);
830 if (r == MATCH)
831 return MATCH;
832 }
833 } else if (r == MATCH) {
834 return MATCH;
835 } else
836 return r; /* oops! */
837 }
838 ++sc;
839 }
840 cur_p_of = ep_p_next(ep, cur_p_of);
841 if (cur_p_of == NO_MORE_P)
842 break;
843 }
844 return NOMATCH; /* none of the ps lead to a match */
845 }
846
847 static s8 match_only_once(struct ep *ep, u8 *str, u8 *str_end, u8 flgs)
848 {
849 s64 cur_p_of = 0; /* offset */
850 loop {
851 struct p *cur_p = ep_p_get(ep, cur_p_of);
852 /*
853 * I cannot believe it but `strcat' is actually acceptable here.
854 * Match the entire str with the prefix from the ep and the
855 * rem of the p following the ep. We made room in the p str
856 * buffer in order to store the concatened p.
857 */
858 s8 r = match(strcat(cur_p->str, ep->p_rem), str, str_end, flgs,
859 0);
860 if (r == MATCH)
861 return MATCH;
862
863 cur_p_of = ep_p_next(ep, cur_p_of);
864 if (cur_p_of == NO_MORE_P)
865 break;
866 }
867 return NOMATCH; /* none of the ps lead to a match */
868 }
869
870 static s8 match_none(struct ep *ep, u8 *str, u8 *str_end, u8 flgs)
871 {
872 u8 *sc = str;
873 loop {
874 s64 cur_p_of;
875
876 if (sc > (u8*)str_end)
877 break;
878
879 cur_p_of = 0;
880 loop {
881 s8 r;
882
883 struct p *cur_p = ep_p_get(ep, cur_p_of);
884
885 r = match(cur_p->str, str, sc, flgs, 0);
886 if (r == MATCH)
887 break;
888
889 cur_p_of = ep_p_next(ep, cur_p_of);
890 if (cur_p_of == NO_MORE_P)
891 break;
892 }
893
894 /*
895 * if none of the ps matched see whether the p rem match the str
896 * rem
897 */
898 if (cur_p_of == NO_MORE_P) {
899 s8 r = match(ep->p_rem, sc, str_end, flgs, 0);
900 if (r == MATCH)
901 return MATCH;
902 }
903 ++sc;
904 }
905 /* none of the ps together with the rem of the p lead to a match */
906 return NOMATCH;
907 }
908
909 /* will return WATCH/NOMATCH/NO_VALID_P *and* misc errors */
910 static s8 extended_match_try(u8 type, u8 *p, u8 *str, u8 *str_end, u8 flgs)
911 {
912 struct ep ep;
913 s8 r;
914
915 ep.type = type;
916 /* count the ep type char right befor the opening ( */
917 ep.full_p_sz = strlen(p) + 1;
918 ep.ps = 0;
919 ep.last = 0;
920 ep.sz = 0;
921 ep.p_rem = 0;
922
923 r = ep_split(p, &ep);
924 if (r != OK)
925 goto out;
926
927 /* from here, p_rem points right after the closing ) of the ep */
928
929 r = MATCH;
930 switch (type) {
931 case '*':
932 if (match(ep.p_rem, str, str_end, flgs, 0) == MATCH)
933 break;
934 /* FALLTHROUGH to at least once sub-p matched */
935 case '+':
936 r = match_at_least_once(&ep, p, str, str_end, flgs);
937 break;
938 case '?':
939 if (match(ep.p_rem, str, str_end, flgs, 0) == MATCH)
940 break;
941 /* FALLTHROUGH to only once sub-p matched */
942 case '@':
943 r = match_only_once(&ep, str, str_end, flgs);
944 break;
945 case '!':
946 r = match_none(&ep, str, str_end, flgs);
947 break;
948 default:
949 r = NO_VALID_P;
950 }
951 out:
952 if (ep.ps)
953 munmap(ep.ps, ep.sz);
954 return r;
955 }
956
957 ULINUX_EXPORT s8 ulinux_match(u8 *pattern, u8 *str, u8 flgs)
958 {
959 return match(pattern, str,(u8*)str + strlen(str), flgs, 0);
960 }
961
962 /*----------------------------------------------------------------------------*/
963 /* local cleanup */
964 #undef loop
965 #undef ANONYMOUS
966 #undef CASEFOLD
967 #undef ERR
968 #undef ERR_NOMEM
969 #undef EXTMATCH
970 #undef is_alnum
971 #undef is_alpha
972 #undef is_blank
973 #undef is_cntrl
974 #undef is_digit
975 #undef is_graph
976 #undef is_lower
977 #undef is_print
978 #undef is_punct
979 #undef is_space
980 #undef is_upper
981 #undef is_xdigit
982 #undef ISERR
983 #undef sl
984 #undef MATCH
985 #undef memchr
986 #undef memcpy
987 #undef mmap
988 #undef mremap
989 #undef munmap
990 #undef NOMATCH
991 #undef PRIVATE
992 #undef RD
993 #undef s64
994 #undef s8
995 #undef u16
996 #undef u64
997 #undef u8
998 #undef strcat
999 #undef strcmp
1000 #undef strlen
1001 #undef WR
1002 /*----------------------------------------------------------------------------*/
1003 #undef CHAR_CLASS_MAX
1004 #undef STREQ
1005 #undef NO_VALID_P
1006 #undef OK
1007 /*----------------------------------------------------------------------------*/
1008 #undef BIT
1009 #undef R_GET
1010 #undef R_SET
1011 #undef RETURN_R
1012 #undef MATCH_NORMAL
1013 #undef NEXT_STR_CHAR
1014 #undef NEXT_P_CHAR
1015 #undef TEST_STR_END_REACHED
1016 /*----------------------------------------------------------------------------*/
1017 #undef NO_MORE_P
1018 /*----------------------------------------------------------------------------*/
1019 #undef ULINUX_EXPORT
1020 #endif
File ulinux/utils/ascii/match/match.h added (mode: 100644) (index 0000000..4d80e1d)
1 #ifndef ULINUX_UTILS_ASCII_MATCH_H
2 #define ULINUX_UTILS_ASCII_MATCH_H
3 /*
4 * This is a derived work based on GNU glibc implementation on 20130409.
5 * Switch to GNU Lesser GPLv3 protection
6 * author:Sylvain BERTRAND
7 */
8
9 /*----------------------------------------------------------------------------*/
10 /* "One Compilation Unit" support */
11 #ifdef ULINUX_UTILS_EXTERNAL
12 #define ULINUX_EXPORT extern
13 #else
14 #define ULINUX_EXPORT static
15 #endif
16 /*----------------------------------------------------------------------------*/
17
18 /* flags */
19 #define ULINUX_MATCH_CASEFOLD (1 << 0) /* compare without regard to case */
20 #define ULINUX_MATCH_EXTMATCH (1 << 1) /* use ksh-like extended matching */
21
22 /* return values */
23 #define ULINUX_MATCH_ERR_NOMEM -3
24 #define ULINUX_MATCH_ERR -2
25 #define ULINUX_MATCH_MATCH 0
26 #define ULINUX_MATCH_NOMATCH 1
27
28 ULINUX_EXPORT ulinux_s8 ulinux_match(ulinux_u8 *p, ulinux_u8 *str,
29 ulinux_u8 flgs);
30 #undef ULINUX_EXPORT
31 #endif
File ulinux/utils/ascii/string/conv/decimal/decimal.c added (mode: 100644) (index 0000000..921abfe)
1 #ifndef ULINUX_UTILS_ASCII_STRING_CONV_DECIMAL_DECIMAL_C
2 #define ULINUX_UTILS_ASCII_STRING_CONV_DECIMAL_DECIMAL_C
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 #include <stdbool.h>
8 /*----------------------------------------------------------------------------*/
9 #include <ulinux/compiler_types.h>
10 #include <ulinux/types.h>
11 #include <ulinux/utils/mem.h>
12 #include <ulinux/utils/ascii/ascii.h>
13 #include <ulinux/utils/ascii/string/string.h>
14 /*----------------------------------------------------------------------------*/
15 /* "One Compilation Unit" support */
16 #ifdef ULINUX_UTILS_EXTERNAL
17 #define ULINUX_EXPORT
18 #else
19 #define ULINUX_EXPORT static
20 #endif
21 /*----------------------------------------------------------------------------*/
22 /* local */
23 #define loop for(;;)
24 /*----------------------------------------------------------------------------*/
25 /*
26 * strict unsigned decimal ascii str to u8
27 * C version
28 * caller must provide a valid pointer with readable data
29 * inplace conversion: ok
30 * return compiler boolean:success or failed
31 */
32 ULINUX_EXPORT ulinux_u8 ulinux_dec2u8(ulinux_u8 *dest, ulinux_u8 *start)
33 { /* do *not* trust */
34 ulinux_u64 len;
35 ulinux_u16 buf;
36 ulinux_u8 *end;
37
38 if (!ulinux_strnlen(&len, start, sizeof("255") - 1))
39 return 0;
40 if (!len)
41 return 0;
42
43 buf = 0;
44 end = start + len - 1;
45 loop {
46 if (start > end)
47 break;
48
49 if (!ulinux_is_digit(*start))
50 return 0;
51 buf = buf * 10 + (*start - '0');
52 ++start;
53 }
54 /* overflow, max is "999" way below what can do a u16 */
55 if (buf & 0xff00)
56 return 0;
57 *dest = (ulinux_u8)buf;
58 return 1;
59 }
60
61 /*
62 * strict unsigned decimal ascii str to u16
63 * C version
64 * caller must provide a valid pointer with readable data
65 * inplace conversion: ok
66 * return compiler boolean:success or failed
67 */
68 ULINUX_EXPORT ulinux_u8 ulinux_dec2u16(ulinux_u16 *dest, ulinux_u8 *start)
69 {/* do *not* trust */
70 ulinux_u64 len;
71 ulinux_u32 buf;
72 ulinux_u8 *end;
73
74 if (!ulinux_strnlen(&len, start, sizeof("65535") - 1))
75 return 0;
76 if (!len)
77 return 0;
78
79 buf = 0;
80 end = start + len - 1;
81 loop {
82 if (start > end)
83 break;
84
85 if (!ulinux_is_digit(*start))
86 return 0;
87 buf = buf * 10 + (*start - '0');
88 ++start;
89 }
90 /* overflow, max is "99999" way below what can do a u32 */
91 if (buf & 0xffff0000)
92 return 0;
93 *dest = (ulinux_u16)buf;
94 return 1;
95 }
96
97 /*
98 * strict unsigned decimal ascii str to u32
99 * C version
100 * caller must provide a valid pointer with readable data
101 * inplace conversion: ok
102 * return compiler boolean:success or failed
103 */
104 ULINUX_EXPORT ulinux_u8 ulinux_dec2u32(ulinux_u32 *dest, ulinux_u8 *start)
105 {/* do *not* trust */
106 ulinux_u64 len;
107 ulinux_u64 buf;
108 ulinux_u8 *end;
109
110 if (!ulinux_strnlen(&len, start, sizeof("4294967295") - 1))
111 return 0;
112 if (!len)
113 return 0;
114
115 buf = 0;
116 end = start + len - 1;
117 loop {
118 if (start > end)
119 break;
120 if (!ulinux_is_digit(*start))
121 return 0;
122 buf = buf * 10 + (*start - '0');
123 ++start;
124 }
125 /* overflow, max is "9999999999" way below what can do a u32 */
126 if (buf & 0xffffffff00000000)
127 return 0;
128 *dest = (ulinux_u32)buf;
129 return 1;
130 }
131
132 /*
133 * strict unsigned decimal ascii str to u64
134 * C version
135 * caller must provide a valid pointer with readable data
136 * inplace conversion: ok
137 * return compiler boolean:success or failed
138 */
139 ULINUX_EXPORT ulinux_u8 ulinux_dec2u64(ulinux_u64 *dest, ulinux_u8 *start)
140 { /* do *not* trust content */
141 ulinux_u64 len;
142 ulinux_u64 buf;
143 ulinux_u8 *end;
144
145 if(!ulinux_strnlen(&len,start,sizeof("18446744073709551615")-1)) return 0;
146 if(!len) return 0;
147
148 buf = 0;
149 end = start + len - 1;
150 loop {
151 ulinux_u64 old_buf;
152
153 if (start > end)
154 break;
155
156 if (!ulinux_is_digit(*start))
157 return 0;
158 old_buf = buf;
159 buf = buf * 10 + (*start - '0');
160 if (buf < old_buf)
161 return 0; /* overflow check */
162 ++start;
163 }
164 *dest = buf;
165 return 1;
166 }
167
168 /*----------------------------------------------------------------------------*/
169 /* local cleanup */
170 #undef loop
171 /*----------------------------------------------------------------------------*/
172 #undef ULINUX_EXPORT
173 #endif
File ulinux/utils/ascii/string/conv/decimal/decimal.h added (mode: 100644) (index 0000000..9da5402)
1 #ifndef ULINUX_UTILS_ASCII_STRING_CONV_DECIMAL_DECIMAL_H
2 #define ULINUX_UTILS_ASCII_STRING_CONV_DECIMAL_DECIMAL_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7
8 /*----------------------------------------------------------------------------*/
9 /* "One Compilation Unit" support */
10 #ifdef ULINUX_UTILS_EXTERNAL
11 #define ULINUX_EXPORT extern
12 #else
13 #define ULINUX_EXPORT static
14 #endif
15 /*----------------------------------------------------------------------------*/
16
17 ULINUX_EXPORT ulinux_u8 ulinux_dec2u8(ulinux_u8 *dest, ulinux_u8 *start);
18 ULINUX_EXPORT ulinux_u8 ulinux_dec2u16(ulinux_u16 *dest, ulinux_u8 *start);
19 ULINUX_EXPORT ulinux_u8 ulinux_dec2u32(ulinux_u32 *dest, ulinux_u8 *start);
20 ULINUX_EXPORT ulinux_u8 ulinux_dec2u64(ulinux_u64 *dest, ulinux_u8 *start);
21 #undef ULINUX_EXPORT
22 #endif
File ulinux/utils/ascii/string/string.h added (mode: 100644) (index 0000000..b4b0577)
1 #ifndef ULINUX_UTILS_ASCII_STRING_STRING_H
2 #define ULINUX_UTILS_ASCII_STRING_STRING_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7
8 #define ulinux_loop for(;;)
9
10 static inline ulinux_s8 ulinux_strncmp(ulinux_u8 *cs, ulinux_u8 *ct,
11 ulinux_u64 n)
12 {
13 ulinux_u8 c1;
14 ulinux_u8 c2;
15
16 ulinux_loop {
17 if (n == 0)
18 break;
19
20 c1 = *cs++;
21 c2 = *ct++;
22 if (c1 != c2)
23 return c1 < c2 ? -1 : 1;
24 if (!c1)
25 break;
26 n--;
27 }
28 return 0;
29 }
30
31 /* use carefully */
32 static inline ulinux_s8 ulinux_strcmp(ulinux_u8 *cs, ulinux_u8 *ct)
33 {
34 ulinux_u8 c1;
35 ulinux_u8 c2;
36
37 ulinux_loop {
38 c1 = *cs++;
39 c2 = *ct++;
40 if (c1 != c2)
41 return c1 < c2 ? -1 : 1;
42 if (!c1)
43 break;
44 }
45 return 0;
46 }
47
48 /* use carefully */
49 static inline void ulinux_strcpy(ulinux_u8 *dest, ulinux_u8 *src)
50 {
51 ulinux_loop {
52 *dest++ = *src;
53 if (*src++ == 0)
54 break;
55 }
56 }
57
58 static inline void ulinux_strncpy(ulinux_u8 *d, ulinux_u8 *src, ulinux_u64 n)
59 {
60 ulinux_loop {
61 if ((n == 0) || (*src == 0))
62 break;
63
64 *d++ = *src++;
65 n--;
66 }
67 ulinux_loop {
68 if (n == 0)
69 break;
70
71 *d++ = 0;
72 n--;
73 }
74 }
75
76 static inline ulinux_u8 ulinux_strnlen(ulinux_u64 *sz, ulinux_u8 *start,
77 ulinux_u64 max)
78 {
79 ulinux_u8 *end;
80
81 end = start;
82 ulinux_loop {
83 if ((max-- == 0) || (*end == 0))
84 break;
85 ++end;
86 }
87 if (*end == 0) {
88 *sz = end - start;
89 return 1;
90 }
91 return 0;
92 }
93
94 /* use carefully */
95 static inline ulinux_u64 ulinux_strlen(ulinux_u8 *start)
96 {
97 ulinux_u8 *end;
98
99 end = start;
100 ulinux_loop {
101 if (*end == 0)
102 break;
103 ++end;
104 }
105 return end - start;
106 }
107
108 /* use carefully */
109 static inline ulinux_u8 *ulinux_strcat(ulinux_u8 *dest,ulinux_u8 *src)
110 {
111 ulinux_u8 *tmp = dest;
112
113 ulinux_loop {
114 if (*dest == 0)
115 break;
116 ++dest;
117 }
118 ulinux_loop {
119 if ((*dest++ = *src++) == 0)
120 break;
121 }
122 return tmp;
123 }
124
125 /* use carefully */
126 static inline ulinux_u8 *ulinux_strstr(ulinux_u8 *haystack, ulinux_u8 *needle)
127 {
128 ulinux_u64 haystack_rem_len;
129 ulinux_u64 needle_len;
130
131 needle_len = ulinux_strlen(needle);
132
133 if (!needle_len)
134 return haystack;
135
136 haystack_rem_len = ulinux_strlen(haystack);
137
138 ulinux_loop {
139 if (haystack_rem_len < needle_len)
140 break;
141
142 haystack_rem_len--;
143
144 if (ulinux_memcmp(haystack, needle, needle_len))
145 return haystack;
146
147 ++haystack;
148 }
149 return 0;
150 }
151 #undef ulinux_loop
152 #endif
File ulinux/utils/ascii/string/vsprintf.c added (mode: 100644) (index 0000000..ef278dc)
1 #ifndef ULINUX_UTILS_ASCII_STRING_VSPRINTF_C
2 #define ULINUX_UTILS_ASCII_STRING_VSPRINTF_C
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * ripper:Sylvain BERTRAND
6 * ripped, buggyfied and sort of ported (heavily derived) to user space from
7 * Linux kernel (then the linux GPLv2 does not apply).
8 * XXX: ipv[46] is severely broken, remove or fix... one day
9 * XXX: many of the code paths here are not tested (aka overkill)
10 */
11 /*---------------------------------------------------------------------------*/
12 /*
13 * linux/lib/vsprintf.c
14 *
15 * Copyright (C) 1991, 1992 Linus Torvalds
16 *
17 *
18 * vsprintf.c -- Lars Wirzenius & Linus Torvalds.
19 *
20 * Wirzenius wrote this portably, Torvalds fucked it up :-)
21 *
22 *
23 * Fri Jul 13 2001 Crutcher Dunnavant <crutcher+kernel@datastacks.com>
24 * - changed to provide snprintf and vsnprintf functions
25 * So Feb 1 16:51:32 CET 2004 Juergen Quade <quade@hsnr.de>
26 * - scnprintf and vscnprintf
27 */
28 /*---------------------------------------------------------------------------*/
29 #include <stdbool.h>
30 #include <stdarg.h>
31 /*---------------------------------------------------------------------------*/
32 #include <ulinux/compiler_types.h>
33 #include <ulinux/types.h>
34 #include <ulinux/mmap.h>
35 #include <ulinux/utils/div.h>
36 #include <ulinux/utils/endian.h>
37 #include <ulinux/socket/in6.h>
38 #include <ulinux/utils/ipv6.h>
39 #include <ulinux/utils/mem.h>
40 #include <ulinux/utils/ascii/ascii.h>
41 #include <ulinux/utils/ascii/string/string.h>
42 #include <ulinux/sysc.h>
43 #include <ulinux/error.h>
44 /*----------------------------------------------------------------------------*/
45 /* "One Compilation Unit" support */
46 #ifdef ULINUX_UTILS_EXTERNAL
47 #define ULINUX_EXPORT
48 #else
49 #define ULINUX_EXPORT static
50 #endif
51 /*----------------------------------------------------------------------------*/
52 /******************************************************************************/
53 /* some basic debug/trace stuff */
54 #if 0
55 #define WERR(str) ulinux_sysc(write, 3, 2, str, ulinux_strlen(str))
56 #define WERRBUF(buf,sz) ulinux_sysc(write, 3, 2, buf, sz)
57 #endif
58 /******************************************************************************/
59 /* local */
60 #define loop for(;;)
61 /* symbols and types */
62 #define printf_spec ulinux_utils_ascii_string_vsprintf_printf_spec
63 #define put_dec_full ulinux_utils_ascii_string_vsprintf_put_dec_full
64 #define put_dec_trunc ulinux_utils_ascii_string_vsprintf_put_dec_trunc
65 #define put_dec ulinux_utils_ascii_string_vsprintf_put_dec
66 #define number ulinux_utils_ascii_string_vsprintf_number
67 #define string ulinux_utils_ascii_string_vsprintf_string
68 #define pack_hex_byte ulinux_utils_ascii_string_vsprintf_pack_hex_byte
69 #define mac_address_string ulinux_utils_ascii_string_vsprintf_mac_address_string
70 #define ip4_string ulinux_utils_ascii_string_vsprintf_ip4_string
71 #define ip6_compressed_string ulinux_utils_ascii_string_vsprintf_ip6_compressed_string
72 #define ip6_string ulinux_utils_ascii_string_vsprintf_ip6_string
73 #define ip6_addr_string ulinux_utils_ascii_string_vsprintf_ip6_addr_string
74 #define ip4_addr_string ulinux_utils_ascii_string_vsprintf_ip4_addr_string
75 #define uuid_tbls_init ulinux_utils_ascii_string_vsprintf_uuid_tbls_init
76 #define uuid_string ulinux_utils_ascii_string_vsprintf_uuid_string
77 #define pointer ulinux_utils_ascii_string_vsprintf_pointer
78 #define a2u16 ulinux_utils_ascii_string_vsprintf_a2u16
79 #define format_decode ulinux_utils_ascii_string_vsprintf_format_decode
80 /*---------------------------------------------------------------------------*/
81 /* works only for digits and letters, but small and fast */
82 #define TOLOWER(x) ((x)|0x20)
83
84 #define ZEROPAD 1 /* pad with zero */
85 #define SIGN 2 /* unsigned/signed long */
86 #define PLUS 4 /* show plus */
87 #define SPACE 8 /* space if plus */
88 #define LEFT 16 /* left justified */
89 #define SMALL 32 /* use lowercase in hex (must be 32 == 0x20) */
90 #define SPECIAL 64 /* prefix hex with "0x", octal with "0" */
91
92 /* just a string part */
93 #define FMT_TYPE_NONE 0
94 #define FMT_TYPE_WIDTH 1
95 #define FMT_TYPE_PRECISION 2
96 #define FMT_TYPE_CHAR 3
97 #define FMT_TYPE_STR 4
98 #define FMT_TYPE_PTR 5
99 #define FMT_TYPE_PERCENT_CHAR 6
100 #define FMT_TYPE_INVALID 7
101 #define FMT_TYPE_LONG_LONG 8
102 #define FMT_TYPE_ULONG 9
103 #define FMT_TYPE_LONG 10
104 #define FMT_TYPE_UBYTE 11
105 #define FMT_TYPE_BYTE 12
106 #define FMT_TYPE_USHORT 13
107 #define FMT_TYPE_SHORT 14
108 #define FMT_TYPE_UINT 15
109 #define FMT_TYPE_INT 16
110 #define FMT_TYPE_NRCHARS 17
111 #define FMT_TYPE_SIZE_T 18
112 #define FMT_TYPE_PTRDIFF 19
113
114 struct printf_spec {
115 ulinux_u8 type; /* format_type enum */
116 ulinux_u8 flags; /* flags to number() */
117 ulinux_u8 base; /* number base, 8, 10 or 16 only */
118 ulinux_u8 qualifier; /* number qualifier, one of 'hHlLtzZ' */
119 /*
120 * width of output field, -1 means not presentor ignored for some
121 * reason
122 */
123 ulinux_s16 field_width;
124 /* # of digits/chars, -1 means not present or ignored for some reason */
125 ulinux_s16 precision;
126 };
127
128 /* Same with if's removed. Always emits five digits. */
129 static ulinux_u8 *put_dec_full(ulinux_u8 *buf, ulinux_u64 q)
130 {
131 /*
132 * BTW, if q is in [0,9999], 8-bit ints will be enough,
133 * but anyway, gcc produces better code with full-sized ints
134 */
135 ulinux_u64 d3, d2, d1, d0;
136 d1 = (q >> 4) & 0xf;
137 d2 = (q >> 8) & 0xf;
138 d3 = (q >> 12);
139
140 /*
141 * Possible ways to approx. divide by 10
142 * gcc -O2 replaces multiply with shifts and adds
143 * (x * 0xcd) >> 11: 11001101 - shorter code than * 0x67 (on i386)
144 * (x * 0x67) >> 10: 1100111
145 * (x * 0x34) >> 9: 110100 - same
146 * (x * 0x1a) >> 8: 11010 - same
147 * (x * 0x0d) >> 7: 1101 - same, shortest code (on i386)
148 */
149 d0 = 6 * (d3 + d2 + d1) + (q & 0xf);
150 q = (d0 * 0xcd) >> 11;
151 d0 = d0 - 10 * q;
152 *buf++ = d0 + '0';
153 d1 = q + 9 * d3 + 5 * d2+ d1;
154 q = (d1 * 0xcd) >> 11;
155 d1 = d1 - 10 * q;
156 *buf++ = d1 + '0';
157
158 d2 = q + 2 * d2;
159 q = (d2 * 0xd) >> 7;
160 d2 = d2 - 10 * q;
161 *buf++ = d2 + '0';
162
163 d3 = q + 4 * d3;
164 q = (d3 * 0xcd) >> 11; /* - shorter code */
165 /* q = (d3 * 0x67) >> 10; - would also work */
166 d3 = d3 -10 * q;
167 *buf++ = d3 + '0';
168 *buf++ = q + '0';
169 return buf;
170 }
171
172 /*
173 * Decimal conversion is by far the most typical, and is used
174 * for /proc and /sys data. This directly impacts e.g. top performance
175 * with many processes running. We optimize it for speed
176 * using code from
177 * http://www.cs.uiowa.edu/~jones/bcd/decimal.html
178 * (with permission from the author, Douglas W. Jones).
179 *
180 * Formats correctly any integer in [0,99999].
181 * Outputs from one to five digits depending on input.
182 * On i386 gcc 4.1.2 -O2: ~250 bytes of code.
183 */
184 static ulinux_u8 *put_dec_trunc(ulinux_u8 *buf, ulinux_u64 q)
185 {
186 ulinux_u64 d3, d2, d1, d0;
187 d1 = (q >> 4) & 0xf;
188 d2 = (q >> 8) & 0xf;
189 d3 = (q >> 12);
190
191 d0 = 6 * (d3 + d2 + d1) + (q & 0xf);
192 q = (d0 * 0xcd) >> 11;
193 d0 = d0 - 10 * q;
194 *buf++ = d0 + '0'; /* least significant digit */
195 d1 = q + 9 * d3 + 5 * d2 +d1;
196 if (d1 !=0 ) {
197 q = (d1 * 0xcd) >> 11;
198 d1 = d1 - 10 * q;
199 *buf++ = d1 + '0'; /* next digit */
200
201 d2 = q + 2 * d2;
202 if ((d2 != 0) || (d3 != 0)) {
203 q = (d2 * 0xd) >> 7;
204 d2 = d2 - 10 * q;
205 *buf++ = d2 + '0'; /* next digit */
206
207 d3 = q + 4 * d3;
208 if (d3 !=0 ) {
209 q = (d3 * 0xcd) >> 11;
210 d3 = d3 - 10 * q;
211 *buf++ = d3 + '0'; /* next digit */
212 if (q != 0)
213 *buf++ = q + '0'; /* most sign. digit */
214 }
215 }
216 }
217 return buf;
218 }
219
220 /* no inlining helps gcc to use registers better */
221 static ulinux_u8 *put_dec(ulinux_u8 *buf, ulinux_u64 num)
222 {
223 loop {
224 ulinux_u64 rem;
225
226 if (num < 100000)
227 return put_dec_trunc(buf,num);
228 rem = ulinux_do_div(num, 100000);
229 buf = put_dec_full(buf, rem);
230 }
231 }
232
233 static ulinux_u8 *number(ulinux_u8 *buf,ulinux_u8 *end, ulinux_u64 num,
234 struct printf_spec spec)
235 {
236 ulinux_u8 locase;
237 ulinux_u8 sign;
238 ulinux_u8 need_pfx;
239 ulinux_u8 *digits;
240 /* octal max digit number for unsigned 64 bits plus sign */
241 ulinux_u8 tmp[66];
242 ulinux_s64 i;
243
244 /*
245 * we are called with base 8, 10 or 16, only, thus don't need "G..."
246 * locase = 0 or 0x20. ORing digits or letters with 'locase'
247 * produces same digits or (maybe lowercased) letters
248 */
249 locase = spec.flags & SMALL;
250 if (spec.flags & LEFT)
251 spec.flags &= ~ZEROPAD;
252
253 sign = 0;
254 if (spec.flags & SIGN) {
255 if ((ulinux_s64)num < 0) {
256 sign = '-';
257 num =- (ulinux_s64)num;
258 spec.field_width--;
259 }else if (spec.flags&PLUS) {
260 sign = '+';
261 spec.field_width--;
262 }else if (spec.flags & SPACE) {
263 sign = ' ';
264 spec.field_width--;
265 }
266 }
267
268 need_pfx = ((spec.flags & SPECIAL) && (spec.base != 10));
269 if (need_pfx) {
270 spec.field_width--;
271 if (spec.base == 16)
272 spec.field_width--;
273 }
274
275 /* generate full string in tmp[], in reverse order */
276 digits = (ulinux_u8*)"0123456789ABCDEF"; /* "GHIJKLMNOPQRSTUVWXYZ"; */
277 i = 0;
278 if (num == 0) {
279 tmp[i++] = '0';
280 /*
281 * Generic code, for any base:
282 * else do {
283 * tmp[i++] = (digits[do_div(num,base)] | locase);
284 * } while (num != 0);
285 */
286 } else if (spec.base != 10) { /*8 or 16*/
287 ulinux_u8 mask;
288 ulinux_u8 shift;
289
290 mask = spec.base - 1;
291 shift = 3;
292
293 if (spec.base == 16)
294 shift = 4;
295
296 loop {
297 tmp[i++] = (digits[((ulinux_u8)num) & mask] | locase);
298 num >>= shift;
299
300 if (num == 0)
301 break;
302 }
303 } else {
304 i = put_dec(tmp, num) - tmp; /* base 10 */
305 }
306
307 /* printing 100 using %2d gives "100", not "00" */
308 if (i > spec.precision)
309 spec.precision = i;
310
311 /* leading space padding */
312 spec.field_width -= spec.precision;
313 if (!(spec.flags & (ZEROPAD + LEFT)))
314 loop {
315 if (--spec.field_width < 0)
316 break;
317 if (buf < end)
318 *buf = ' ';
319 ++buf;
320 }
321
322 /* sign */
323 if (sign) {
324 if (buf < end)
325 *buf = sign;
326 ++buf;
327 }
328
329 /* "0x" / "0" prefix */
330 if (need_pfx) {
331 if (buf < end)
332 *buf = '0';
333 ++buf;
334 if (spec.base == 16) {
335 if (buf < end)
336 *buf = ('X' | locase);
337 ++buf;
338 }
339 }
340
341 /* zero or space padding */
342 if (!(spec.flags & LEFT)) {
343 ulinux_u8 c;
344
345 c = (spec.flags & ZEROPAD) ? '0' : ' ';
346
347 loop {
348 if (--spec.field_width < 0)
349 break;
350 if (buf < end)
351 *buf = c;
352 ++buf;
353 }
354 }
355
356 /* hmm even more zero padding? */
357 loop {
358 if (i > --spec.precision)
359 break;
360 if (buf < end)
361 *buf = '0';
362 ++buf;
363 }
364
365 /* actual digits of result */
366 loop {
367 if (--i < 0)
368 break;
369 if (buf < end)
370 *buf = tmp[i];
371 ++buf;
372 }
373
374 /* trailing space padding */
375 loop {
376 if (--spec.field_width < 0)
377 break;
378 if (buf < end)
379 *buf = ' ';
380 ++buf;
381 }
382 return buf;
383 }
384
385 static ulinux_u8 *string(ulinux_u8 *buf, ulinux_u8 *end, ulinux_u8 *s,
386 struct printf_spec spec)
387 {
388 ulinux_u64 i;
389 ulinux_u64 len;
390 #ifdef __GNUC__
391 /*
392 * pointer to integer cast is always whining if different size
393 * ABI:long is pointer size
394 */
395 ulinux_ul s_ul;
396 ulinux_u64 s_u64;
397
398 s_ul = (ulinux_ul)s;
399 s_u64 = (ulinux_u64)s_ul;
400 if (s_u64 < ULINUX_PAGE_SZ)
401 s = (ulinux_u8*)"(null)";
402 #else
403 /* any pointer in the first memory page is invalid */
404 if ((ulinux_u64)s < ULINUX_PAGE_SZ)
405 s = (ulinux_u8*)"(null)";
406 #endif
407
408 if (!ulinux_strnlen(&len, s, spec.precision))
409 len = spec.precision;
410
411 if (!(spec.flags & LEFT)) /* it's RIGHT */
412 loop {
413 if ((ulinux_s16)len >= spec.field_width--)
414 break;
415 if (buf < end)
416 *buf = ' ';
417 ++buf;
418 }
419
420 i = 0;
421 loop {
422 if (i++ >= len)
423 break;
424 if (buf < end)
425 *buf = *s;
426 ++buf;
427 ++s;
428 }
429
430 loop {
431 if ((ulinux_s16)len >= spec.field_width--)
432 break;
433 if (buf < end)
434 *buf = ' ';
435 ++buf;
436 }
437 return buf;
438 }
439
440 #define hex_asc_lo(x) hex_asc[((x) & 0x0f)]
441 #define hex_asc_hi(x) hex_asc[((x) & 0xf0) >> 4]
442
443 static ulinux_u8 *pack_hex_byte(ulinux_u8 *buf, ulinux_u8 byte)
444 {
445 ulinux_u8 *hex_asc;
446
447 hex_asc = (ulinux_u8*)"0123456789abcdef";
448 *buf++ = hex_asc_hi(byte);
449 *buf++ = hex_asc_lo(byte);
450 return buf;
451 }
452
453 static ulinux_u8 *mac_address_string(ulinux_u8 *buf, ulinux_u8 *end,
454 ulinux_u8 *addr, struct printf_spec spec, ulinux_u8 *fmt)
455 {
456 ulinux_u8 mac_addr[sizeof("xx:xx:xx:xx:xx:xx")];
457 ulinux_u8 *p;
458 ulinux_u8 separator;
459 ulinux_u8 i;
460
461 p = &mac_addr[0];
462
463 if (fmt[1] == 'F')
464 separator = '-'; /* FDDI canonical format */
465 else
466 separator = ':';
467
468 i = 0;
469 loop {
470 if (i >= 6)
471 break;
472
473 p = pack_hex_byte(p, addr[i]);
474 if ((fmt[0] == 'M') && (i != 5))
475 *p++ = separator;
476 ++i;
477 }
478 *p = 0;
479 return string(buf, end, mac_addr, spec);
480 }
481
482 static ulinux_u8 *ip4_string(ulinux_u8 *p, ulinux_u8 *addr, ulinux_u8 *fmt)
483 {
484 ulinux_s8 index,step;
485 ulinux_u8 i;
486 ulinux_u8 leading_zeros;
487
488 switch (fmt[2]) {
489 case 'h':
490 # ifdef __BIG_ENDIAN
491 index = 0;
492 step = 1;
493 # else
494 index = 3;
495 step = -1;
496 # endif
497 break;
498 case 'l':
499 index = 3;
500 step = -1;
501 break;
502 case 'n':
503 case 'b':
504 default:
505 index = 0;
506 step = 1;
507 break;
508 }
509
510 leading_zeros = (fmt[0] == 'i');
511 i = 0;
512 loop {
513 ulinux_u8 temp[3]; /* hold each IP quad in reverse order */
514 ulinux_u8 digits;
515
516 if (i >= 4)
517 break;
518
519 digits = put_dec_trunc(temp, addr[index]) - temp;
520 if (leading_zeros) {
521 if (digits < 3)
522 *p++ = '0';
523 if (digits < 2)
524 *p++ = '0';
525 }
526 /* reverse the digits in the quad */
527 loop {
528 if (digits-- == 0)
529 break;
530 *p++ = temp[digits];
531 }
532 if (i < 3)
533 *p++ = '.';
534 index += step;
535 ++i;
536 }
537 *p = 0;
538 return p;
539 }
540
541 static ulinux_u8 *ip6_compressed_string(ulinux_u8 *p, ulinux_u8 *addr)
542 {
543 ulinux_u8 needcolon;
544 struct ulinux_in6_addr in6;
545 ulinux_u8 i;
546 ulinux_u8 useIPv4;
547 ulinux_u8 zerolength[8];
548 ulinux_u8 range;
549 ulinux_u8 longest;
550 ulinux_u8 colonpos;
551
552 needcolon = 0;
553 ulinux_memcpy((ulinux_u8*)&in6, addr, sizeof(in6));
554
555 useIPv4 = ulinux_ipv6_addr_v4mapped(&in6)
556 || ulinux_ipv6_addr_is_isatap(&in6);
557
558 ulinux_memset(zerolength, 0, sizeof(zerolength));
559
560 if (useIPv4)
561 range = 6;
562 else
563 range = 8;
564
565 /* find position of longest 0 run */
566 i = 0;
567 loop {
568 ulinux_u8 j;
569 if (i >= range)
570 break;
571
572 j = i;
573 loop {
574 if (j >= range)
575 break;
576
577 if (in6.s6_addr16[j] != 0)
578 break;
579 zerolength[i]++;
580 ++j;
581 }
582 ++i;
583 }
584
585 longest = 1;
586 colonpos = -1;
587 i = 0;
588 loop {
589 if (i >= range)
590 break;
591
592 if (zerolength[i] > longest) {
593 longest = zerolength[i];
594 colonpos = i;
595 }
596 ++i;
597 }
598
599 /* emit address */
600 i = 0;
601 loop {
602 ulinux_u16 word;
603 ulinux_u8 hi;
604 ulinux_u8 lo;
605 ulinux_u8 *hex_asc;
606
607 hex_asc = (ulinux_u8*)"0123456789abcdef";
608
609 if (i >= range)
610 break;
611
612 if (i == colonpos) {
613 if (needcolon || (i == 0))
614 *p++ = ':';
615 *p++ = ':';
616 needcolon = 0;
617 i += longest - 1;
618 continue;
619 }
620 if (needcolon) {
621 *p++ = ':';
622 needcolon = 0;
623 }
624 /* hex u16 without leading 0s */
625 word = ulinux_be16_to_cpu(in6.s6_addr16[i]);
626 hi = word >> 8;
627 lo = word & 0xff;
628 if (hi) {
629 if (hi > 0x0f)
630 p = pack_hex_byte(p, hi);
631 else
632 *p++ = hex_asc_lo(hi);
633
634 p = pack_hex_byte(p, lo);
635 } else if(lo > 0x0f) {
636 p = pack_hex_byte(p, lo);
637 } else
638 *p++ = hex_asc_lo(lo);
639 needcolon = 1;
640 ++i;
641 }
642
643 if (useIPv4) {
644 if (needcolon)
645 *p++ = ':';
646 p = ip4_string(p, &in6.s6_addr[12], (ulinux_u8*)"I4");
647 }
648 *p = 0;
649 return p;
650 }
651
652 static ulinux_u8 *ip6_string(ulinux_u8 *p, ulinux_u8 *addr, ulinux_u8 *fmt)
653 {
654 ulinux_u8 i;
655 i = 0;
656 loop {
657 if (i >= 8)
658 break;
659
660 p = pack_hex_byte(p, *addr++);
661 p = pack_hex_byte(p, *addr++);
662 if ((fmt[0] == 'I') && (i != 7))
663 *p++ = ':';
664 ++i;
665 }
666 *p = 0;
667 return p;
668 }
669
670 static ulinux_u8 *ip6_addr_string(ulinux_u8 *buf,ulinux_u8 *end,
671 ulinux_u8 *addr, struct printf_spec spec, ulinux_u8 *fmt)
672 {
673 ulinux_u8 ip6_addr[
674 sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255")];
675
676 if ((fmt[0] == 'I') && (fmt[2] == 'c'))
677 ip6_compressed_string(ip6_addr, addr);
678 else
679 ip6_string(ip6_addr, addr, fmt);
680 return string(buf, end, ip6_addr, spec);
681 }
682
683 static ulinux_u8 *ip4_addr_string(ulinux_u8 *buf,ulinux_u8 *end,
684 ulinux_u8 *addr, struct printf_spec spec, ulinux_u8 *fmt)
685 {
686 ulinux_u8 ip4_addr[sizeof("255.255.255.255")];
687
688 ip4_string(ip4_addr, addr, fmt);
689 return string(buf, end, ip4_addr, spec);
690 }
691
692 static void uuid_tbls_init(ulinux_u8 *be, ulinux_u8 *le)
693 {
694 ulinux_u8 i;
695 i = 0;
696 loop {
697 be[i] = i;
698 ++i;
699 if (i == 16)
700 break;
701 }
702
703 le[0] = 3;
704 le[1] = 2;
705 le[2] = 1;
706 le[3] = 0;
707 le[4] = 5;
708 le[5] = 4;
709 le[6] = 7;
710 le[7] = 6;
711 i = 8;
712 loop {
713 le[i] = i;
714 ++i;
715 if (i == 16)
716 break;
717 }
718 }
719
720 static ulinux_u8 *uuid_string(ulinux_u8 *buf,ulinux_u8 *end,
721 ulinux_u8 *addr, struct printf_spec spec, ulinux_u8 *fmt)
722 {
723 ulinux_u8 be[16];
724 ulinux_u8 le[16];
725 ulinux_u8 *index;
726 ulinux_u8 uc;
727 ulinux_u8 i;
728 ulinux_u8 uuid[sizeof("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")];
729 ulinux_u8 *p;
730
731 uuid_tbls_init(&be[0], &le[0]);
732 index = &be[0];
733 uc = 0;
734
735 switch (*(++fmt)) {
736 case 'L':
737 uc = 1; /* fall-through */
738 case 'l':
739 index = le;
740 break;
741 case 'B':
742 uc = 1;
743 break;
744 }
745
746 p = &uuid[0];
747 i = 0;
748 loop {
749
750 if (i >= 16)
751 break;
752 p = pack_hex_byte(p, addr[index[i]]);
753 switch (i) {
754 case 3:
755 case 5:
756 case 7:
757 case 9:
758 *p++ = '-';
759 break;
760 }
761 ++i;
762 }
763 *p = 0;
764
765 if (uc) {
766 p = &uuid[0];
767 loop {
768 *p = ulinux_2upper(*p);
769
770 if (*(++p) == 0)
771 break;
772 }
773 }
774 return string(buf, end, uuid, spec);
775 }
776
777 /*
778 * Show a '%p' thing. A kernel extension is that the '%p' is followed
779 * by an extra set of alphanumeric characters that are extended format
780 * specifiers.
781 *
782 * Right now we handle:
783 *
784 * - 'M' For a 6-byte MAC address, it prints the address in the
785 * usual colon-separated hex notation
786 * - 'm' For a 6-byte MAC address, it prints the hex address without colons
787 * - 'MF' For a 6-byte MAC FDDI address, it prints the address
788 * with a dash-separated hex notation
789 * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way
790 * IPv4 uses dot-separated decimal without leading 0's (1.2.3.4)
791 * IPv6 uses colon separated network-order 16 bit hex with leading 0's
792 * - 'i' [46] for 'raw' IPv4/IPv6 addresses
793 * IPv6 omits the colons (01020304...0f)
794 * IPv4 uses dot-separated decimal with leading 0's (010.123.045.006)
795 * - '[Ii]4[hnbl]' IPv4 addresses in host, network, big or little endian order
796 * - 'I6c' for IPv6 addresses printed as specified by
797 * http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-00
798 * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form
799 * "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
800 * Options for %pU are:
801 * b big endian lower case hex (default)
802 * B big endian UPPER case hex
803 * l little endian lower case hex
804 * L little endian UPPER case hex
805 * big endian output byte order is:
806 * [0][1][2][3]-[4][5]-[6][7]-[8][9]-[10][11][12][13][14][15]
807 * little endian output byte order is:
808 * [3][2][1][0]-[5][4]-[7][6]-[8][9]-[10][11][12][13][14][15]
809 *
810 * Note: The difference between 'S' and 'F' is that on ia64 and ppc64
811 * function pointers are really function descriptors, which contain a
812 * pointer to the real address.
813 */
814 static ulinux_u8 *pointer(ulinux_u8 *fmt, ulinux_u8 *buf, ulinux_u8 *end,
815 void *ptr, struct printf_spec spec)
816 {
817 #ifdef __GNUC__
818 /*
819 * pointer to integer cast is always whining if different size
820 * ABI:long is pointer size
821 */
822 ulinux_ul ptr_ul;
823 ulinux_u64 ptr_u64;
824 #endif
825
826 if (!ptr)
827 return string(buf, end, (ulinux_u8*)"(null)", spec);
828
829 switch (*fmt) {
830 case 'M': /* colon separated: 00:01:02:03:04:05 */
831 case 'm': /*contiguous: 000102030405 */
832 /* [mM]F (FDDI, bit reversed) */
833 return mac_address_string(buf, end, ptr, spec, fmt);
834 case 'I': /*
835 * Formatted IP supported
836 * 4: 1.2.3.4
837 * 6: 0001:0203:...:0708
838 * 6c: 1::708 or 1::1.2.3.4
839 */
840 case 'i': /*
841 * contiguous:
842 * 4: 001.002.003.004
843 * 6: 000102...0f
844 */
845 switch (fmt[1]) {
846 case '6':
847 return ip6_addr_string(buf, end, ptr, spec, fmt);
848 case '4':
849 return ip4_addr_string(buf, end, ptr, spec, fmt);
850 }
851 break;
852 case 'U':
853 return uuid_string(buf, end, ptr, spec, fmt);
854 }
855
856 spec.flags |= SMALL;
857 if (spec.field_width == -1) {
858 spec.field_width = 2 * sizeof(void*);
859 spec.flags |= ZEROPAD;
860 }
861 spec.base = 16;
862 #ifdef __GNUC__
863 ptr_ul = (ulinux_ul)ptr;
864 ptr_u64 = (ulinux_u64)ptr_ul;
865 return number(buf, end, ptr_u64, spec);
866 #else
867 return number(buf, end, (ulinux_u64)ptr, spec);
868 #endif
869 }
870
871 static inline ulinux_u16 a2u16(ulinux_u8 **s)
872 {
873 ulinux_u16 i;
874
875 i = 0;
876 loop {
877 if (!ulinux_is_digit(**s))
878 break;
879 i = i * 10 + *((*s)++) - '0';
880 }
881 return i;
882 }
883
884 /*
885 * Helper function to decode printf style format.
886 * Each call decode a token from the format and return the
887 * number of characters read (or likely the delta where it wants
888 * to go on the next call).
889 * The decoded token is returned through the parameters
890 *
891 * 'h', 'l', or 'L' for integer fields
892 * 'z' support added 23/7/1999 S.H.
893 * 'z' changed to 'Z' --davidm 1/25/99
894 * 't' added for ptrdiff_t
895 *
896 * @fmt: the format string
897 * @type of the token returned
898 * @flags: various flags such as +, -, # tokens..
899 * @field_width: overwritten width
900 * @base: base of the number (octal, hex, ...)
901 * @precision: precision of a number
902 * @qualifier: qualifier of a number (long, size_t, ...)
903 */
904 static ulinux_s64 format_decode(ulinux_u8 *fmt, struct printf_spec *spec)
905 {
906 ulinux_u8 *start;
907
908 start = fmt;
909
910 /*--------------------------------------------------------------------*/
911 /* we finished early by reading the field width */
912 if (spec->type == FMT_TYPE_WIDTH) {
913 if (spec->field_width < 0) {
914 spec->field_width =- spec->field_width;
915 spec->flags |= LEFT;
916 }
917 spec->type = FMT_TYPE_NONE;
918 goto precision;
919 }
920
921 /* we finished early by reading the precision */
922 if (spec->type == FMT_TYPE_PRECISION) {
923 if (spec->precision < 0)
924 spec->precision = 0;
925 spec->type = FMT_TYPE_NONE;
926 goto qualifier;
927 }
928 /*--------------------------------------------------------------------*/
929
930 spec->type = FMT_TYPE_NONE; /* by default */
931 loop {
932 if (*fmt == 0)
933 break;
934 if (*fmt == '%')
935 break;
936 ++fmt;
937 }
938
939 /* return the current non-format string */
940 if ((fmt != start) || !*fmt)
941 return fmt - start;
942
943 spec->flags = 0; /* process flags */
944
945 loop { /* this also skips first '%' */
946 ulinux_u8 found;
947
948 found = 1;
949 ++fmt;
950 switch (*fmt) {
951 case '-': spec->flags |= LEFT; break;
952 case '+': spec->flags |= PLUS; break;
953 case ' ': spec->flags |= SPACE; break;
954 case '#': spec->flags |= SPECIAL;break;
955 case '0': spec->flags |= ZEROPAD;break;
956 default: found = 0;
957 }
958 if (!found)
959 break;
960 }
961
962 /* get field width */
963 spec->field_width = -1;
964
965 if (ulinux_is_digit(*fmt))
966 spec->field_width = (ulinux_s16)a2u16(&fmt);
967 else if (*fmt == '*') {
968 spec->type = FMT_TYPE_WIDTH; /* get it from the argument list */
969 return ++fmt - start;
970 }
971
972 /* get the precision */
973 precision:
974 spec->precision = -1;
975 if (*fmt == '.') {
976 ++fmt;
977 if (ulinux_is_digit(*fmt)) {
978 spec->precision = (ulinux_s16)a2u16(&fmt);
979 if(spec->precision < 0)
980 spec->precision = 0;
981 } else if (*fmt == '*') { /* it's the next argument */
982 spec->type = FMT_TYPE_PRECISION;
983 return ++fmt - start;
984 }else
985 spec->precision = 0;
986 }
987
988 qualifier:
989 /* get the conversion qualifier */
990 spec->qualifier = -1;
991 if ((*fmt == 'h') || (TOLOWER(*fmt) == 'l') || (TOLOWER(*fmt) == 'z')
992 || (*fmt=='t')) {
993 spec->qualifier = *fmt++;
994 if (spec->qualifier == *fmt) {
995 if (spec->qualifier == 'l') {
996 spec->qualifier = 'L';
997 ++fmt;
998 } else if (spec->qualifier == 'h') {
999 spec->qualifier = 'H';
1000 ++fmt;
1001 }
1002 }
1003 }
1004
1005 spec->base = 10; /* default base:2/8/10/16 wanted? */
1006 switch (*fmt) {
1007 case 'c':
1008 spec->type = FMT_TYPE_CHAR;
1009 return ++fmt - start;
1010 case 's':
1011 spec->type = FMT_TYPE_STR;
1012 return ++fmt - start;
1013 case 'p':
1014 spec->type = FMT_TYPE_PTR;
1015 return fmt - start;
1016 /* skip alnum */
1017 case 'n':
1018 spec->type = FMT_TYPE_NRCHARS;
1019 return ++fmt - start;
1020 case '%':
1021 spec->type = FMT_TYPE_PERCENT_CHAR;
1022 return ++fmt - start;
1023 /* integer number formats - set up the flags and "break" */
1024 case 'o':
1025 spec->base = 8;
1026 break;
1027 case 'x':
1028 spec->flags |= SMALL;
1029 case 'X':
1030 spec->base = 16;
1031 break;
1032 case 'd':
1033 case 'i':
1034 spec->flags |= SIGN;
1035 case 'u':
1036 break;
1037 default:
1038 spec->type = FMT_TYPE_INVALID;
1039 return fmt - start;
1040 }
1041
1042 if (spec->qualifier == 'L')
1043 spec->type = FMT_TYPE_LONG_LONG;
1044 else if (spec->qualifier == 'l') {
1045 if (spec->flags & SIGN)
1046 spec->type = FMT_TYPE_LONG;
1047 else
1048 spec->type = FMT_TYPE_ULONG;
1049 } else if (TOLOWER(spec->qualifier) == 'z') {
1050 spec->type = FMT_TYPE_SIZE_T;
1051 }else if (spec->qualifier == 't') {
1052 spec->type = FMT_TYPE_PTRDIFF;
1053 }else if (spec->qualifier == 'H') {
1054 if(spec->flags & SIGN)
1055 spec->type = FMT_TYPE_BYTE;
1056 else
1057 spec->type = FMT_TYPE_UBYTE;
1058 }else if (spec->qualifier == 'h') {
1059 if (spec->flags & SIGN)
1060 spec->type = FMT_TYPE_SHORT;
1061 else
1062 spec->type = FMT_TYPE_USHORT;
1063 }else {
1064 if (spec->flags & SIGN)
1065 spec->type = FMT_TYPE_INT;
1066 else
1067 spec->type = FMT_TYPE_UINT;
1068 }
1069 return ++fmt - start;
1070 }
1071
1072 /*
1073 * vsnprintf - Format a string and place it in a buffer
1074 * @buf: The buffer to place the result into
1075 * @sz: The size of the buffer, including the trailing null space
1076 * @fmt: The format string to use
1077 * @args: Arguments for the format string
1078 *
1079 * This function follows C99 vsnprintf, but has some extensions:
1080 * %pM output a 6-byte MAC address with colons
1081 * %pm output a 6-byte MAC address without colons
1082 * %pI4 print an IPv4 address without leading zeros
1083 * %pi4 print an IPv4 address with leading zeros
1084 * %pI6 print an IPv6 address with colons
1085 * %pi6 print an IPv6 address without colons
1086 * %pI6c print an IPv6 address as specified by
1087 * http://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-00
1088 * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper
1089 * case.
1090 * %n is ignored
1091 *
1092 * The return value is the number of characters which would
1093 * be generated for the given input, excluding the trailing
1094 * '\0', as per ISO C99. If you want to have the exact
1095 * number of characters written into @buf as return value
1096 * (not including the trailing '\0'), use vscnprintf(). If the
1097 * return is greater than or equal to @size, the resulting
1098 * string is truncated.
1099 *
1100 * Call this function if you are already dealing with a va_list.
1101 * You probably want snprintf() instead.
1102 * SECURITY:fmt is **trusted**,argument related to %fmt are **trusted**
1103 */
1104 ULINUX_EXPORT ulinux_u64 ulinux_vsnprintf(ulinux_u8 *buf, ulinux_u64 sz,
1105 ulinux_u8 *fmt, va_list args)
1106 {
1107 ulinux_u64 num;
1108 struct printf_spec spec;
1109 ulinux_u8 *str;
1110 ulinux_u8 *end;
1111
1112 str = buf;
1113 end = buf + sz; /* point to the byte *after* the buffer last byte */
1114
1115 spec.type = 0;
1116 spec.flags = 0;
1117 spec.base = 0;
1118 spec.qualifier = 0;
1119 spec.field_width = 0;
1120 spec.precision = 0;
1121
1122 loop {
1123 ulinux_u8 *old_fmt;
1124 ulinux_u64 read;
1125
1126 if (*fmt == 0)
1127 break;
1128
1129 old_fmt = fmt;
1130 read = format_decode(fmt, &spec);
1131
1132 fmt += read;
1133
1134 switch (spec.type) {
1135 case FMT_TYPE_NONE:{
1136 ulinux_u64 copy;
1137
1138 copy = read;
1139 if (str < end) {
1140 if ((ulinux_s64)copy > (end - str))
1141 copy = end - str;
1142 ulinux_memcpy(str, old_fmt, copy);
1143 }
1144 str += read;
1145 break;
1146 }
1147 /* get field width from the argument list */
1148 case FMT_TYPE_WIDTH:
1149 spec.field_width = (ulinux_s16)va_arg(args, ulinux_si);
1150 break;
1151 /* get precision from the argument list */
1152 case FMT_TYPE_PRECISION:
1153 spec.precision = (ulinux_s16)va_arg(args, ulinux_si);
1154 break;
1155 case FMT_TYPE_CHAR: {
1156 ulinux_u8 c;
1157 if (!(spec.flags & LEFT)) {
1158 loop {
1159 if (--spec.field_width <= 0)
1160 break;
1161 if (str < end)
1162 *str = ' ';
1163 ++str;
1164 }
1165 }
1166 c = (ulinux_u8)va_arg(args, ulinux_si);
1167 if (str < end)
1168 *str = c;
1169 ++str;
1170 loop {
1171 if (--spec.field_width <= 0)
1172 break;
1173 if (str < end)
1174 *str = ' ';
1175 ++str;
1176 }
1177 break;
1178 }
1179 case FMT_TYPE_STR:
1180 str = string(str, end, va_arg(args, ulinux_u8*), spec);
1181 break;
1182 case FMT_TYPE_PTR:
1183 str = pointer(fmt + 1,str, end, va_arg(args, void*),
1184 spec);
1185 /* alnums are extension to pointer fmt (see cmts) */
1186 loop {
1187 if (!ulinux_is_alnum(*fmt))
1188 break;
1189 fmt++;
1190 }
1191 break;
1192 case FMT_TYPE_PERCENT_CHAR:
1193 if (str < end)
1194 *str = '%';
1195 ++str;
1196 break;
1197 case FMT_TYPE_INVALID:
1198 if (str < end)
1199 *str = '%';
1200 ++str;
1201 break;
1202 case FMT_TYPE_NRCHARS: {
1203 ulinux_u8 qualifier;
1204 qualifier = spec.qualifier;
1205
1206 if (qualifier == 'L') {
1207 ulinux_u64 *ip;
1208 ip = va_arg(args, ulinux_u64*);
1209 *ip = (str - buf);
1210 } else if (qualifier == 'l') {
1211 ulinux_u64 *ip;
1212 ip = va_arg(args, ulinux_u64*);
1213 *ip = (str - buf);
1214 } else if (TOLOWER(qualifier) == 'z') {
1215 ulinux_u64 *ip;
1216 ip = va_arg(args, ulinux_u64*);
1217 *ip = (str - buf);
1218 } else{
1219 ulinux_u64 *ip;
1220 ip = va_arg(args, ulinux_u64*);
1221 *ip = (str - buf);
1222 }
1223 break;
1224 }
1225 default:
1226 switch (spec.type) {
1227 case FMT_TYPE_LONG_LONG:
1228 num = va_arg(args, ulinux_s64);
1229 break;
1230 case FMT_TYPE_ULONG:
1231 if (BITS_PER_LONG == 64)
1232 num = va_arg(args, ulinux_u64);
1233 else
1234 num = va_arg(args, ulinux_u32);
1235 break;
1236 case FMT_TYPE_LONG:
1237 if (BITS_PER_LONG == 64)
1238 num = va_arg(args, ulinux_s64);
1239 else
1240 num = va_arg(args, ulinux_s32);
1241 break;
1242 case FMT_TYPE_SIZE_T:
1243 num = va_arg(args, ulinux_u64);
1244 break;
1245 case FMT_TYPE_PTRDIFF:
1246 num = va_arg(args, ulinux_u64);
1247 break;
1248 case FMT_TYPE_UBYTE:
1249 num = (ulinux_u8)va_arg(args, ulinux_u64);
1250 break;
1251 case FMT_TYPE_BYTE:
1252 num = (ulinux_s8)va_arg(args, ulinux_s64);
1253 break;
1254 case FMT_TYPE_USHORT:
1255 num = (ulinux_u16)va_arg(args, ulinux_u64);
1256 break;
1257 case FMT_TYPE_SHORT:
1258 num = (ulinux_s16)va_arg(args, ulinux_s64);
1259 break;
1260 case FMT_TYPE_INT:
1261 num = va_arg(args, ulinux_s32);
1262 break;
1263 default:
1264 num = va_arg(args, ulinux_u32);
1265 }
1266 str = number(str, end, num, spec);
1267 }
1268 }
1269
1270 if (sz > 0) { /* set the terminating null byte, if not truncated */
1271 /* if(str<end) *str=0;else end[-1]=0; */
1272 if (str < end)
1273 *str = 0;
1274 }
1275 /* the trailing null byte doesn't count towards the total */
1276 return str - buf;
1277 }
1278
1279 /*
1280 * snprintf - Format a string and place it in a buffer
1281 * @buf: The buffer to place the result into
1282 * @size: The size of the buffer, including the trailing null space
1283 * @fmt: The format string to use
1284 * @...: Arguments for the format string
1285 *
1286 * The return value is the number of characters which would be
1287 * generated for the given input, excluding the trailing null,
1288 * as per ISO C99. If the return is greater than or equal to
1289 * @size, the resulting string is truncated. We miss the trailing null
1290 * if equal.
1291 *
1292 * See the vsnprintf() documentation for format string extensions over C99.
1293 */
1294 ULINUX_EXPORT ulinux_u64 ulinux_snprintf(ulinux_u8 *buf, ulinux_u64 sz, ulinux_u8 *fmt,
1295 ...)
1296 {
1297 ulinux_u64 i;
1298 va_list args;
1299
1300 va_start(args, fmt);
1301 i = ulinux_vsnprintf(buf, sz, fmt, args);
1302 va_end(args);
1303 return i;
1304 }
1305
1306 /* dprintf, print formatted output to file */
1307 ULINUX_EXPORT bool ulinux_dprintf(ulinux_si f, ulinux_u8 *buf, ulinux_u64 sz,
1308 ulinux_u8 *fmt, ...)
1309 {
1310 ulinux_u64 len;
1311 va_list args;
1312 ulinux_sl r;
1313 ulinux_u64 written_bytes_n;
1314
1315 va_start(args,fmt);
1316 len = ulinux_vsnprintf(buf, sz, fmt, args);
1317 va_end(args);
1318
1319 written_bytes_n = 0;
1320 loop {
1321 r = ulinux_sysc(write, 3, f, buf + written_bytes_n,
1322 len - written_bytes_n);
1323 if ((r == -ULINUX_EINTR) || (r == -ULINUX_EAGAIN))
1324 continue;
1325
1326 if (ULINUX_ISERR(r))
1327 return false;
1328
1329 written_bytes_n += (ulinux_u64)r;
1330 if (written_bytes_n == len)
1331 return true;
1332 }
1333 }
1334 /*---------------------------------------------------------------------------*/
1335 /* cleanup */
1336 #undef loop
1337 #undef TOLOWER
1338 #undef ZEROPAD
1339 #undef SIGN
1340 #undef PLUS
1341 #undef SPACE
1342 #undef LEFT
1343 #undef SMALL
1344 #undef SPECIAL
1345 #undef FMT_TYPE_NONE
1346 #undef FMT_TYPE_WIDTH
1347 #undef FMT_TYPE_PRECISION
1348 #undef FMT_TYPE_CHAR
1349 #undef FMT_TYPE_STR
1350 #undef FMT_TYPE_PTR
1351 #undef FMT_TYPE_PERCENT_CHAR
1352 #undef FMT_TYPE_INVALID
1353 #undef FMT_TYPE_LONG_LONG
1354 #undef FMT_TYPE_ULONG
1355 #undef FMT_TYPE_LONG
1356 #undef FMT_TYPE_UBYTE
1357 #undef FMT_TYPE_BYTE
1358 #undef FMT_TYPE_USHORT
1359 #undef FMT_TYPE_SHORT
1360 #undef FMT_TYPE_UINT
1361 #undef FMT_TYPE_INT
1362 #undef FMT_TYPE_NRCHARS
1363 #undef FMT_TYPE_SIZE_T
1364 #undef FMT_TYPE_PTRDIFF
1365 #undef hex_asc_lo
1366 #undef hex_asc_hi
1367
1368 #undef printf_spec
1369 #undef put_dec_full
1370 #undef put_dec_trunc
1371 #undef put_dec
1372 #undef number
1373 #undef string
1374 #undef pack_hex_byte
1375 #undef mac_address_string
1376 #undef ip4_string
1377 #undef ip6_compressed_string
1378 #undef ip6_string
1379 #undef ip6_addr_string
1380 #undef ip4_addr_string
1381 #undef uuid_tbls_init
1382 #undef uuid_string
1383 #undef pointer
1384 #undef a2u16
1385 #undef format_decode
1386
1387 #undef ULINUX_EXPORT
1388 #endif
File ulinux/utils/ascii/string/vsprintf.h added (mode: 100644) (index 0000000..cc4d866)
1 #ifndef ULINUX_UTILS_ASCII_STRING_VSPRINTF_H
2 #define ULINUX_UTILS_ASCII_STRING_VSPRINTF_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7
8 /*----------------------------------------------------------------------------*/
9 /* "One Compilation Unit" support */
10 #ifdef ULINUX_UTILS_EXTERNAL
11 #define ULINUX_EXPORT extern
12 #else
13 #define ULINUX_EXPORT static
14 #endif
15 /*----------------------------------------------------------------------------*/
16
17 ULINUX_EXPORT ulinux_u64 ulinux_vsnprintf(ulinux_u8 *buf, ulinux_u64 sz,
18 ulinux_u8 *fmt, va_list args);
19 ULINUX_EXPORT ulinux_u64 ulinux_snprintf(ulinux_u8 *buf, ulinux_u64 sz,
20 ulinux_u8 *fmt, ...);
21 ULINUX_EXPORT bool ulinux_dprintf(ulinux_si f, ulinux_u8 *buf, ulinux_u64 sz,
22 ulinux_u8 *fmt, ...);
23 #undef ULINUX_EXPORT
24 #endif
File ulinux/utils/atomic.h added (mode: 100644) (index 0000000..d786512)
1 #ifndef ULINUX_ATOMIC
2 #define ULINUX_ATOMIC
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 /*----------------------------------------------------------------------------*/
8 /* atomic stuff (will probably move in arch.h, that's for x86-64) */
9 struct ulinux_atomic_u8 {
10 ulinux_u8 val;
11 };
12
13 static inline ulinux_u8 ulinux_atomic_u8_read(const struct ulinux_atomic_u8 *v)
14 {
15 return (*(volatile ulinux_u8*)&(v)->val);
16 }
17 static inline void ulinux_atomic_u8_set(struct ulinux_atomic_u8 *v, ulinux_u8 u)
18 {
19 v->val = u;
20 }
21 /*----------------------------------------------------------------------------*/
22 #endif
File ulinux/utils/div.h added (mode: 100644) (index 0000000..d5f445e)
1 #ifndef ULINUX_UTILS_DIV_H
2 #define ULINUX_UTILS_DIV_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 #define ulinux_do_div(n,base)({\
8 ulinux_u32 __base=(base);\
9 ulinux_u32 __rem;\
10 __rem = ((ulinux_u64)(n)) % __base;\
11 (n) = ((ulinux_u64)(n)) / __base;\
12 __rem;\
13 })
14 #endif
File ulinux/utils/endian.h added (mode: 100644) (index 0000000..5f08ff8)
1 #ifndef ULINUX_UTILS_ENDIAN_H
2 #define ULINUX_UTILS_ENDIAN_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 #include <ulinux/arch/utils/endian.h>
8 #endif
File ulinux/utils/ipv6.h added (mode: 100644) (index 0000000..5ab4fda)
1 #ifndef ULINUX_UTILS_IPV6
2 #define ULINUX_UTILS_IPV6
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 struct ulinux_in6_addr {
8 union {
9 ulinux_u8 u6_addr8[16];
10 ulinux_u16 u6_addr16[8];
11 ulinux_u32 u6_addr32[4];
12 } in6_u;
13 };
14 #define s6_addr in6_u.u6_addr8
15 #define s6_addr16 in6_u.u6_addr16
16 #define s6_addr32 in6_u.u6_addr32
17 static inline ulinux_u8 ulinux_ipv6_addr_any(struct ulinux_in6_addr *a)
18 {
19 return ((a->s6_addr32[0] | a->s6_addr32[1] | a->s6_addr32[2]
20 | a->s6_addr32[3]) == 0);
21 }
22
23 static inline ulinux_u8 ulinux_ipv6_addr_loopback(struct ulinux_in6_addr *a)
24 {
25 return ((a->s6_addr32[0] | a->s6_addr32[1] | a->s6_addr32[2]
26 | (a->s6_addr32[3] ^ ulinux_cpu_to_be32(1))) == 0);
27 }
28
29 static inline ulinux_u8 ulinux_ipv6_addr_v4mapped(struct ulinux_in6_addr *a)
30 {
31 return ((a->s6_addr32[0] | a->s6_addr32[1]
32 | (a->s6_addr32[2] ^ ulinux_cpu_to_be32(0x0000ffff))) == 0);
33 }
34
35 static inline ulinux_u8 ulinux_ipv6_addr_is_isatap(struct ulinux_in6_addr *addr)
36 {
37 return ((addr->s6_addr32[2] | ulinux_cpu_to_be32(0x02000000))
38 == ulinux_cpu_to_be32(0x02005EFE));
39 }
40 #endif
File ulinux/utils/maths.h added (mode: 100644) (index 0000000..c119995)
1 #ifndef ULINUX_UTILS_MATHS_H
2 #define ULINUX_UTILS_MATHS_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 /*
8 * will round to nearest integer
9 * .5 policy is round away from zero
10 */
11 static inline ulinux_f32 ulinux_f32_round_near(ulinux_f32 f)
12 {
13 ulinux_s8 e;
14 ulinux_s8 first_frac_bit_idx;
15 ulinux_u8 round_away_from_zero;
16
17 ulinux_u32 *u = (ulinux_u32*)&f;
18 ulinux_u8 e_biased = (*u >> 23) & 0xff; /* biased exponent */
19
20 if (e_biased == 0xff)
21 return f; /* +/-inf or nan, returned as is */
22 if (e_biased == 0x00)
23 return 0.0f; /* subnormal floats are in ]-0.5;0.5[ */
24
25 e = (ulinux_s8)((ulinux_s16)e_biased - 127);
26
27 /* no frac then integer */
28 if (e >= 23)
29 return f;
30 /* f in ]-0.5;0.5[ */
31 if (e < -1)
32 return 0.0f;
33 /*
34 * hidden bit always 1, f in ]-1;-0.5] U [0.5;1[, then round away from
35 * 0*/
36 if (e == -1)
37 return *u & 0x80000000 ? -1.0f : 1.0f;
38
39 first_frac_bit_idx = 22 - e;
40 round_away_from_zero = (*u >> first_frac_bit_idx) & 1;
41 /* zero frac from significand */
42 *u &= ~((1 << (first_frac_bit_idx + 1)) - 1);
43 if (round_away_from_zero)
44 f += (*u & 0x80000000 ? -1.0f : 1.0f);
45 return f;
46 }
47 #endif
File ulinux/utils/mem.c added (mode: 100644) (index 0000000..b52ff86)
1 #ifndef ULINUX_UTILS_MEM_C
2 #define ULINUX_UTILS_MEM_C
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 #include <stdbool.h>
8 #include <stddef.h> /* size_t */
9
10 #include <ulinux/compiler_types.h>
11 #include <ulinux/types.h>
12 /*----------------------------------------------------------------------------*/
13 /* "One Compilation Unit" support */
14 #ifdef ULINUX_UTILS_EXTERNAL
15 #define ULINUX_EXPORT
16 #else
17 #define ULINUX_EXPORT static
18 #endif
19 /*----------------------------------------------------------------------------*/
20 /* local */
21 #define loop for(;;)
22 /*******************************************************************************
23 * XXX: DO NOT USE GCC BUILTINS! Got tons of weird bugs with those specific
24 * builtins (gcc 7.3.0)
25 ******************************************************************************/
26 ULINUX_EXPORT void ulinux_memcpy(void *d, void *s, ulinux_u64 len)
27 {
28 ulinux_u8 *to;
29 ulinux_u8 *from;
30
31 to = d;
32 from = s;
33 loop {
34 if (len == 0)
35 break;
36 *to++ = *from++;
37 len--;
38 }
39 }
40
41 ULINUX_EXPORT void ulinux_memset(void *d, ulinux_u8 c, ulinux_u64 len)
42 {
43 ulinux_u8 *cur;
44
45 cur = d;
46 loop {
47 if (len == 0)
48 break;
49 *cur++ = c;
50 len--;
51 }
52 }
53
54 ULINUX_EXPORT bool ulinux_memcmp(void *d, void *c, ulinux_u64 len)
55 {
56 ulinux_u8 *su1;
57 ulinux_u8 *su2;
58
59 su1 = d;
60 su2 = c;
61 loop {
62 if (len == 0)
63 return true;
64
65 if (*su1 != *su2)
66 return false;
67
68 ++su1;
69 ++su2;
70 len--;
71 }
72 }
73 /*----------------------------------------------------------------------------*/
74 #undef loop
75 #undef ULINUX_EXPORT
76 /*----------------------------------------------------------------------------*/
77 #endif
File ulinux/utils/mem.h added (mode: 100644) (index 0000000..6b0e9cc)
1 #ifndef ULINUX_UTILS_MEM_H
2 #define ULINUX_UTILS_MEM_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 /*----------------------------------------------------------------------------*/
8 /* "One Compilation Unit" support */
9 #ifdef ULINUX_UTILS_EXTERNAL
10 #define ULINUX_EXPORT extern
11 #else
12 #define ULINUX_EXPORT static
13 #endif
14 /*----------------------------------------------------------------------------*/
15 ULINUX_EXPORT void ulinux_memcpy(void *d, void *s, ulinux_u64 len);
16 ULINUX_EXPORT void ulinux_memset(void *d, ulinux_u8 c, ulinux_u64 len);
17 ULINUX_EXPORT bool ulinux_memcmp(void *s1, void *s2, ulinux_u64 len);
18 #undef ULINUX_EXPORT
19 #endif
File ulinux/utils/qsort.c added (mode: 100644) (index 0000000..12d4fd4)
1 #ifndef ULINUX_UTILS_QSORT_C
2 #define ULINUX_UTILS_QSORT_C
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 #include <stdbool.h>
8
9 #include <ulinux/compiler_types.h>
10 #include <ulinux/types.h>
11
12 #include <ulinux/utils/qsort.h>
13 /*----------------------------------------------------------------------------*/
14 /* "One Compilation Unit" support */
15 #ifdef ULINUX_UTILS_EXTERNAL
16 #define ULINUX_EXPORT
17 #else
18 #define ULINUX_EXPORT static
19 #endif
20 /*----------------------------------------------------------------------------*/
21 #define loop for(;;)
22 #define swap ulinux_qsort_swap
23 /*----------------------------------------------------------------------------*/
24 static void swap(void *a, void *b, ulinux_u64 sz)
25 {
26 ulinux_u8 *a_byte;
27 ulinux_u8 *b_byte;
28
29 a_byte = a;
30 b_byte = b;
31 loop {
32 ulinux_u8 tmp;
33
34 if (sz == 0)
35 break;
36
37 tmp = *a_byte;
38 *a_byte = *b_byte;
39 *b_byte = tmp;
40
41 ++a_byte;
42 ++b_byte;
43 sz--;
44 }
45 }
46
47 #define LT ULINUX_QSORT_CMP_LT
48 #define LT_PIVOT ULINUX_QSORT_CMP_LT
49 #define EQ_PIVOT ULINUX_QSORT_CMP_EQ
50 #define GT_PIVOT ULINUX_QSORT_CMP_GT
51 ULINUX_EXPORT void ulinux_qsort(void *base, ulinux_u64 n, ulinux_u64 sz,
52 ulinux_s8 (*cmp)(void *a, void *b))
53 {
54 ulinux_u8 *left;
55 ulinux_u8 *right;
56 ulinux_u8 *pivot;
57 ulinux_u8 *last;
58
59 /* fast paths for the low values of n, 0 1 and 2 */
60 if (n < 2)
61 return;
62 else if (n == 2) {
63 if (cmp(base + sz, base) == LT)
64 swap(base, base + sz, sz);
65 return;
66 }
67
68 /* from here n >= 3 */
69
70 last = base + (n - 1) * sz;
71 left = base;
72 right = last;
73
74 /*
75 * setup a pivot which is the best-of-three median with the value from
76 * the middle. Do pre-partition the values from those 3 array slots.
77 * This setup natural bounds.
78 */
79 pivot = base + ((n - 1) / 2) * sz;
80
81 if (cmp(pivot, left) == LT_PIVOT)
82 swap(left, pivot, sz);
83 if (cmp(right, pivot) == LT_PIVOT) {
84 swap(pivot, right, sz);
85 if (cmp(pivot, left) == LT_PIVOT)
86 swap(left, pivot, sz);
87 }
88
89 /* the best-of-three median is a fast path for n = 3 */
90 if (n == 3)
91 return;
92
93 /* from here n >= 4 */
94
95 /*-------------------------------------------------------------------*/
96 /*
97 * do partition:
98 * - left side LT/EQ the pivot value.
99 * - right side EQ/GT the pivot value.
100 * both sides can contain slots with the pivot value.
101 */
102 left += sz; /* skip the pre-partitioned array left-most value */
103 right -= sz; /* skip the pre-partitioned array righ-most value */
104 loop {
105 ulinux_s8 left_cmp;
106 ulinux_s8 right_cmp;
107
108 /*
109 * this loop cannot go forever, the pre-partitioned right most
110 * slot contains a value higher or equal to the pivot
111 * value, and will not change.
112 */
113 loop {
114 left_cmp = cmp(left, pivot);
115 if (left_cmp != LT_PIVOT)
116 break;
117 left += sz;
118 }
119
120 /* same thing than above but backward */
121 loop {
122 right_cmp = cmp(pivot, right);
123 if (right_cmp != LT_PIVOT)
124 break;
125 right -= sz;
126 }
127
128 /*
129 * left points on a slot which contains:
130 * - the pivot value.
131 * - a value higher than the pivot value.
132 * all slots below left contains values
133 * lesser than or equal to the pivot value.
134 *
135 * right points on a slot which contains:
136 * - the pivot value.
137 * - a value lower than the pivot value.
138 * all slots above right contains values
139 * higher than or equal to the pivot value.
140 */
141
142 if (right <= left)
143 break;
144
145 /* left < right */
146
147 if ((left_cmp != EQ_PIVOT) || (right_cmp != EQ_PIVOT)) {
148 swap(left, right, sz);
149
150 /*
151 * we must keep track of the pivot value if it is
152 * swapped
153 */
154 if (left == pivot)
155 pivot = right;
156 else if (right == pivot)
157 pivot = left;
158 }
159
160 left += sz;
161 right -= sz;
162 }
163
164 /*
165 * if right < left rewind one slot for each which will be our
166 * boundaries of the partitions. if left == right, then rewind only
167 * left.
168 */
169 left -= sz;
170 if (right < left)
171 right += sz;
172 /*-------------------------------------------------------------------*/
173
174 ulinux_qsort(base, (left - (ulinux_u8*)base) / sz + 1, sz, cmp);
175 ulinux_qsort(right, (last - right) / sz + 1, sz, cmp);
176 }
177 #undef LT
178 #undef LT_PIVOT
179 #undef EQ_PIVOT
180 #undef GT_PIVOT
181 /*----------------------------------------------------------------------------*/
182 #undef loop
183 #undef swap
184 #endif
File ulinux/utils/qsort.h added (mode: 100644) (index 0000000..d0c05b0)
1 #ifndef ULINUX_UTILS_QSORT_MACROS_H
2 #define ULINUX_UTILS_QSORT_MACROS_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 #define ULINUX_QSORT_CMP_LT -1
8 #define ULINUX_QSORT_CMP_EQ 0
9 #define ULINUX_QSORT_CMP_GT 1
10 #endif /* ULINUX_UTILS_QSORT_MACROS_H */
11 /******************************************************************************/
12 /******************************************************************************/
13 /* protection for inclusion in qsort.c */
14 #ifndef ULINUX_UTILS_QSORT_C
15 #ifndef ULINUX_UTILS_QSORT_H
16 #define ULINUX_UTILS_QSORT_H
17 /*
18 * this code is protected by the GNU affero GPLv3
19 * author:Sylvain BERTRAND
20 */
21 /*----------------------------------------------------------------------------*/
22 /* "One Compilation Unit" support */
23 #ifdef ULINUX_UTILS_EXTERNAL
24 #define ULINUX_EXPORT extern
25 #else
26 #define ULINUX_EXPORT static
27 #endif
28 /*----------------------------------------------------------------------------*/
29 ULINUX_EXPORT void ulinux_qsort(void *base, ulinux_u64 n, ulinux_u64 sz,
30 ulinux_s8 (*cmp)(void *a, void *b));
31 /*----------------------------------------------------------------------------*/
32 #undef ULINUX_EXPORT
33 #endif /* ULINUX_UTILS_QSORT_C */
34 #endif /* ULINUX_UTILS_QSORT_H */
File ulinux/utsname.h added (mode: 100644) (index 0000000..59e836b)
1 #ifndef ULINUX_UTSNAME_H
2 #define ULINUX_UTSNAME_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 #define ULINUX_UTS_LEN 64
8
9 struct ulinux_utsname {
10 ulinux_u8 sysname[ULINUX_UTS_LEN + 1];
11 ulinux_u8 nodename[ULINUX_UTS_LEN + 1];
12 ulinux_u8 release[ULINUX_UTS_LEN + 1];
13 ulinux_u8 version[ULINUX_UTS_LEN + 1];
14 ulinux_u8 machine[ULINUX_UTS_LEN + 1];
15 ulinux_u8 domainname[ULINUX_UTS_LEN + 1];
16 };
17 #endif
File ulinux/vim/after/syntax/c.vim added (mode: 100644) (index 0000000..9cbca0a)
1 " Vim syntax file
2 " Language: C
3 " Maintainer: Sylvain BERTRAND <sylvain.bertrand@gmail.com>
4 " Last Change: 2015 May 27
5
6 "compiler types
7 syn keyword cType ulinux_sc ulinux_ss ulinux_si ulinux_sl
8 syn keyword cType ulinux_sll
9 syn keyword cType ulinux_uc ulinux_us ulinux_ui ulinux_ul
10 syn keyword cType ulinux_ull
11 syn keyword cType ulinux_f
12
13 "arch types
14 syn keyword cType ulinux_u1 ulinux_u8 ulinux_u16 ulinux_u32 ulinux_u64
15 syn keyword cType ulinux_s8 ulinux_s16 ulinux_s32 ulinux_s64
16 syn keyword cType ulinux_f32
17
18 syn keyword cType ulinux_sz ulinux_ptrdiff
19
20 "ulinux namespaced types
21 syn keyword cType uc us ui ul
22 syn keyword cType ull
23 syn keyword cType sc ss si sl
24 syn keyword cType sll
25 syn keyword cType u1 u8 u16 u32 u64
26 syn keyword cType s8 s16 s32 s64
27 syn keyword cType f32
28
29 "ulinux flow control
30 syn keyword cRepeat loop
31 syn keyword cRepeat ulinux_loop
File ulinux/wait.h added (mode: 100644) (index 0000000..0625497)
1 #ifndef ULINUX_WAIT_H
2 #define ULINUX_WAIT_H
3 /*
4 * this code is protected by the GNU affero GPLv3
5 * author:Sylvain BERTRAND
6 */
7 #define ULINUX_WNOHANG 0x00000001
8 #define ULINUX_WUNTRACED 0x00000002
9 #define ULINUX_WSTOPPED ULINUX_WUNTRACED
10 #define ULINUX_WEXITED 0x00000004
11 #define ULINUX_WCONTINUED 0x00000008
12 /* don't reap, just poll status */
13 #define ULINUX_WNOWAIT 0x01000000
14 /* don't wait on children of other threads in this group */
15 #define ULINUX_WNOTHREAD 0x20000000
16 /* wait on all children, regardless of type */
17 #define ULINUX_WALL 0x40000000
18 /* wait only on non-SIGCHLD children */
19 #define ULINUX_WCLONE 0x80000000
20
21 /* first argument to waitid */
22 #define ULINUX_P_ALL 0
23 #define ULINUX_P_PID 1
24 #define ULINUX_P_PGID 2
25 #endif
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/sylware/syncsm

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/sylware/syncsm

Clone this repository using git:
git clone git://git.rocketgit.com/user/sylware/syncsm

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main