/src/freeradius-server/src/lib/server/packet.c
Line | Count | Source |
1 | | /* |
2 | | * This library is free software; you can redistribute it and/or |
3 | | * modify it under the terms of the GNU Lesser General Public |
4 | | * License as published by the Free Software Foundation; either |
5 | | * version 2.1 of the License, or (at your option) any later version. |
6 | | * |
7 | | * This library is distributed in the hope that it will be useful, |
8 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
9 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
10 | | * Lesser General Public License for more details. |
11 | | * |
12 | | * You should have received a copy of the GNU Lesser General Public |
13 | | * License along with this library; if not, write to the Free Software |
14 | | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA |
15 | | */ |
16 | | |
17 | | /** fr_packet_t alloc/free functions |
18 | | * |
19 | | * @file src/lib/server/packet.c |
20 | | * |
21 | | * @copyright 2023 Network RADIUS SAS (legal@networkradius.com) |
22 | | */ |
23 | | |
24 | | RCSID("$Id: d23eb9001e7c67c3504eb07c65c9aa29135e0e75 $") |
25 | | |
26 | | #include <freeradius-devel/util/atexit.h> |
27 | | #include <freeradius-devel/util/pair_legacy.h> |
28 | | |
29 | | #include <freeradius-devel/server/packet.h> |
30 | | |
31 | | static fr_dict_t const *dict_freeradius; |
32 | | |
33 | | extern fr_dict_autoload_t util_packet_dict[]; |
34 | | fr_dict_autoload_t util_packet_dict[] = { |
35 | | { .out = &dict_freeradius, .proto = "freeradius" }, |
36 | | DICT_AUTOLOAD_TERMINATOR |
37 | | }; |
38 | | |
39 | | static fr_dict_attr_t const *attr_net; |
40 | | static fr_dict_attr_t const *attr_net_src; |
41 | | static fr_dict_attr_t const *attr_net_src_ip; |
42 | | static fr_dict_attr_t const *attr_net_src_port; |
43 | | static fr_dict_attr_t const *attr_net_dst; |
44 | | static fr_dict_attr_t const *attr_net_dst_ip; |
45 | | static fr_dict_attr_t const *attr_net_dst_port; |
46 | | static fr_dict_attr_t const *attr_net_timestamp; |
47 | | static fr_dict_attr_t const *attr_net_interface; |
48 | | |
49 | | extern fr_dict_attr_autoload_t util_packet_dict_attr[]; |
50 | | fr_dict_attr_autoload_t util_packet_dict_attr[] = { |
51 | | { .out = &attr_net, .name = "Net", .type = FR_TYPE_TLV, .dict = &dict_freeradius }, |
52 | | { .out = &attr_net_src, .name = "Net.Src", .type = FR_TYPE_TLV, .dict = &dict_freeradius }, |
53 | | { .out = &attr_net_dst, .name = "Net.Dst", .type = FR_TYPE_TLV, .dict = &dict_freeradius }, |
54 | | { .out = &attr_net_src_ip, .name = "Net.Src.IP", .type = FR_TYPE_COMBO_IP_ADDR, .dict = &dict_freeradius }, |
55 | | { .out = &attr_net_src_port, .name = "Net.Src.Port", .type = FR_TYPE_UINT16, .dict = &dict_freeradius }, |
56 | | { .out = &attr_net_dst_ip, .name = "Net.Dst.IP", .type = FR_TYPE_COMBO_IP_ADDR, .dict = &dict_freeradius }, |
57 | | { .out = &attr_net_dst_port, .name = "Net.Dst.Port", .type = FR_TYPE_UINT16, .dict = &dict_freeradius }, |
58 | | { .out = &attr_net_timestamp, .name = "Net.Timestamp", .type = FR_TYPE_DATE, .dict = &dict_freeradius }, |
59 | | { .out = &attr_net_interface, .name = "Net.Interface", .type = FR_TYPE_STRING, .dict = &dict_freeradius }, |
60 | | |
61 | | DICT_AUTOLOAD_TERMINATOR |
62 | | }; |
63 | | |
64 | | static int inet2pairs(TALLOC_CTX *ctx, fr_pair_list_t *list, |
65 | | fr_dict_attr_t const *attr_ip, fr_dict_attr_t const *attr_port, |
66 | | fr_ipaddr_t const *ipaddr, uint16_t port) |
67 | 0 | { |
68 | 0 | fr_pair_t *vp; |
69 | |
|
70 | 0 | if (fr_pair_find_or_append_by_da(ctx, &vp, list, attr_ip) < 0) return -1; |
71 | 0 | fr_value_box_ipaddr(&vp->data, attr_ip, ipaddr, false); |
72 | 0 | fr_pair_set_immutable(vp); |
73 | |
|
74 | 0 | if (fr_pair_find_or_append_by_da(ctx, &vp, list, attr_port) < 0) return -1; |
75 | 0 | vp->vp_uint16 = port; |
76 | 0 | fr_pair_set_immutable(vp); |
77 | |
|
78 | 0 | return 0; |
79 | 0 | } |
80 | | |
81 | | /** Allocate a "Net." struct with src/dst host and port. |
82 | | * |
83 | | * @param ctx The context in which the packet is allocated. |
84 | | * @param[in] list #fr_pair_list_t value to resolve to #fr_packet_t. |
85 | | * @param[out] packet The request packet. |
86 | | * |
87 | | * @return |
88 | | * - 0 on success |
89 | | * - <0 on error. |
90 | | */ |
91 | | int fr_packet_pairs_from_packet(TALLOC_CTX *ctx, fr_pair_list_t *list, fr_packet_t const *packet) |
92 | 0 | { |
93 | 0 | fr_pair_t *vp, *net, *tlv; |
94 | 0 | #ifdef WITH_IFINDEX_NAME_RESOLUTION |
95 | 0 | char if_name[IFNAMSIZ]; |
96 | 0 | #endif |
97 | | |
98 | | /* |
99 | | * Net |
100 | | */ |
101 | 0 | if (fr_pair_find_or_append_by_da(ctx, &net, list, attr_net) < 0) return -1; |
102 | | |
103 | | /* |
104 | | * Net.Src |
105 | | */ |
106 | 0 | if (fr_pair_find_or_append_by_da(net, &tlv, &net->vp_group, attr_net_src) < 0) return -1; |
107 | | |
108 | 0 | if (inet2pairs(tlv, &tlv->vp_group, attr_net_src_ip, attr_net_src_port, &packet->socket.inet.src_ipaddr, packet->socket.inet.src_port) < 0) return -1; |
109 | | |
110 | | /* |
111 | | * Net.Dst |
112 | | */ |
113 | 0 | if (fr_pair_find_or_append_by_da(net, &tlv, &net->vp_group, attr_net_dst) < 0) return -1; |
114 | | |
115 | 0 | if (inet2pairs(tlv, &tlv->vp_group, attr_net_dst_ip, attr_net_dst_port, &packet->socket.inet.dst_ipaddr, packet->socket.inet.dst_port) < 0) return -1; |
116 | | |
117 | | /* |
118 | | * Timestamp |
119 | | */ |
120 | 0 | if (fr_pair_find_or_append_by_da(net, &vp, &net->vp_group, attr_net_timestamp) < 0) return -1; |
121 | 0 | vp->vp_date = fr_time_to_unix_time(packet->timestamp); |
122 | 0 | fr_pair_set_immutable(vp); |
123 | |
|
124 | 0 | #ifdef WITH_IFINDEX_NAME_RESOLUTION |
125 | | /* |
126 | | * Interface |
127 | | */ |
128 | 0 | if (!packet->socket.inet.ifindex) return 0; |
129 | 0 | if (fr_pair_find_or_append_by_da(net, &vp, &net->vp_group, attr_net_interface) < 0) return -1; |
130 | 0 | fr_ifname_from_ifindex(if_name, packet->socket.inet.ifindex); |
131 | 0 | fr_value_box_strdup(vp, &vp->data, NULL, if_name, false); |
132 | 0 | #endif |
133 | |
|
134 | 0 | return 0; |
135 | 0 | } |
136 | | |
137 | | static void pairs2inet(fr_ipaddr_t *ipaddr, uint16_t *port, fr_pair_list_t const *list, |
138 | | fr_dict_attr_t const *attr_ip, fr_dict_attr_t const *attr_port) |
139 | 0 | { |
140 | 0 | fr_pair_t *vp; |
141 | |
|
142 | 0 | vp = fr_pair_find_by_da(list, NULL, attr_ip); |
143 | 0 | if (vp) *ipaddr = vp->vp_ip; |
144 | |
|
145 | 0 | vp = fr_pair_find_by_da(list, NULL, attr_port); |
146 | 0 | if (vp) *port = vp->vp_uint16; |
147 | 0 | } |
148 | | |
149 | | /** Convert pairs to information in a packet. |
150 | | * |
151 | | * @param packet the packet to send |
152 | | * @param list the list to check for Net.* |
153 | | */ |
154 | | void fr_packet_net_from_pairs(fr_packet_t *packet, fr_pair_list_t const *list) |
155 | 0 | { |
156 | 0 | fr_pair_t *net, *tlv; |
157 | |
|
158 | 0 | net = fr_pair_find_by_da(list, NULL, attr_net); |
159 | 0 | if (!net) return; |
160 | | |
161 | 0 | tlv = fr_pair_find_by_da(&net->vp_group, NULL, attr_net_src); |
162 | 0 | if (tlv) { |
163 | 0 | pairs2inet(&packet->socket.inet.src_ipaddr, &packet->socket.inet.src_port, &tlv->vp_group, |
164 | 0 | attr_net_src_ip, attr_net_src_port); |
165 | 0 | } |
166 | |
|
167 | 0 | tlv = fr_pair_find_by_da(&net->vp_group, NULL, attr_net_dst); |
168 | 0 | if (tlv) { |
169 | 0 | pairs2inet(&packet->socket.inet.dst_ipaddr, &packet->socket.inet.dst_port, &tlv->vp_group, |
170 | 0 | attr_net_dst_ip, attr_net_dst_port); |
171 | 0 | } |
172 | 0 | } |
173 | | |
174 | | static int _packet_global_free(UNUSED void *uctx) |
175 | 0 | { |
176 | 0 | fr_dict_autofree(util_packet_dict); |
177 | |
|
178 | 0 | return 0; |
179 | 0 | } |
180 | | |
181 | | static int _packet_global_init(UNUSED void *uctx) |
182 | 0 | { |
183 | 0 | if (fr_dict_autoload(util_packet_dict) < 0) { |
184 | 0 | error: |
185 | 0 | fr_perror("packet_global_init"); |
186 | 0 | return -1; |
187 | 0 | } |
188 | | |
189 | 0 | if (fr_dict_attr_autoload(util_packet_dict_attr) < 0) goto error; |
190 | | |
191 | 0 | return 0; |
192 | 0 | } |
193 | | |
194 | | /** Initialises the Net. packet attributes. |
195 | | * |
196 | | * @return |
197 | | * - 0 on success. |
198 | | * - -1 on failure. |
199 | | */ |
200 | | int packet_global_init(void) |
201 | 0 | { |
202 | 0 | int ret; |
203 | |
|
204 | 0 | fr_atexit_global_once_ret(&ret, _packet_global_init, _packet_global_free, NULL); |
205 | |
|
206 | 0 | return ret; |
207 | 0 | } |