Coverage Report

Created: 2026-03-31 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}