1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
#ifndef __IP_UTIL_H__
#define __IP_UTIL_H__
#include <arpa/inet.h>
#include <printf.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#pragma GCC diagnostic ignored "-Wformat"
#pragma GCC diagnostic ignored "-Wformat-extra-args"
static int __printf_arginfo(const struct printf_info *info, size_t n,
int *argtypes, int *sz)
{
if (n > 0)
argtypes[0] = PA_POINTER;
return 1;
}
static int __printf_output_b(FILE *stream, const struct printf_info *info,
const void *const *args)
{
uint64_t value = 0;
char buf[8 * sizeof(uintmax_t) + 1] = { 0 };
if (info->width == 0 || info->width % 8 != 0)
return -1;
memcpy(&value, *(unsigned char **)(args[0]), info->width / 8);
for (int i = 0; i < info->width; ++i)
buf[info->width - 1 - i] = '0' + ((value >> i) & 0x1);
return fprintf(stream, "%s", buf);
}
static int __printf_output_y(FILE *stream, const struct printf_info *info,
const void *const *args)
{
char buf[INET_ADDRSTRLEN];
struct in_addr ip;
if (!*(unsigned char **)(args[0]))
return fprintf(stream, "(nil)", buf);
memcpy(&ip, *(unsigned char **)(args[0]), sizeof ip);
inet_ntop(AF_INET, &ip.s_addr, buf, sizeof buf);
return fprintf(stream, "%s", buf);
}
static int __printf_output_Y(FILE *stream, const struct printf_info *info,
const void *const *args)
{
char buf[INET6_ADDRSTRLEN];
struct in6_addr ip;
if (!*(unsigned char **)(args[0]))
return fprintf(stream, "(nil)", buf);
memcpy(&ip, *(unsigned char **)(args[0]), sizeof ip);
inet_ntop(AF_INET6, &ip.s6_addr, buf, sizeof buf);
return fprintf(stream, "%s", buf);
}
static void __attribute__((constructor)) __custom_printf_init()
{
register_printf_specifier('b', __printf_output_b, __printf_arginfo);
register_printf_specifier('y', __printf_output_y, __printf_arginfo);
register_printf_specifier('Y', __printf_output_Y, __printf_arginfo);
}
struct ip_from {
unsigned char ip[16];
struct ip_from *next;
};
static struct ip_from *start = NULL;
static struct ip_from *end = NULL;
static unsigned char *ip_from(uint8_t bits, char *ip_str)
{
struct ip_from *res = malloc(sizeof *res);
inet_pton(bits == 32 ? AF_INET : AF_INET6, ip_str, &res->ip);
if (!end)
start = end = res;
else
end->next = res;
end = res;
res->next = NULL;
return res->ip;
}
static struct in_addr *ip4_from(char *ip_str)
{
return (struct in_addr *)ip_from(32, ip_str);
}
static struct in6_addr *ip6_from(char *ip_str)
{
return (struct in6_addr *)ip_from(128, ip_str);
}
static void __attribute__((destructor)) __free_ip_froms()
{
struct ip_from *cur = start, *next;
while (cur) {
next = cur->next;
free(cur);
cur = next;
}
}
#endif
|