The FreeRADIUS server  $Id: 15bac2a4c627c01d1aa2047687b3418955ac7f00 $
packet.c
Go to the documentation of this file.
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 RCSID("$Id: 2882adc211306f4b45c705eac0f54f2331a68eb7 $")
24 
25 #include <freeradius-devel/server/packet.h>
26 #include <freeradius-devel/util/pair_legacy.h>
27 
28 static fr_dict_t const *dict_freeradius;
29 
32  { .out = &dict_freeradius, .proto = "freeradius" },
33  { NULL }
34 };
35 
36 static fr_dict_attr_t const *attr_net;
44 
47  { .out = &attr_net, .name = "Net", .type = FR_TYPE_TLV, .dict = &dict_freeradius },
48  { .out = &attr_net_src, .name = "Net.Src", .type = FR_TYPE_TLV, .dict = &dict_freeradius },
49  { .out = &attr_net_dst, .name = "Net.Dst", .type = FR_TYPE_TLV, .dict = &dict_freeradius },
50  { .out = &attr_net_src_ip, .name = "Net.Src.IP", .type = FR_TYPE_COMBO_IP_ADDR, .dict = &dict_freeradius },
51  { .out = &attr_net_src_port, .name = "Net.Src.Port", .type = FR_TYPE_UINT16, .dict = &dict_freeradius },
52  { .out = &attr_net_dst_ip, .name = "Net.Dst.IP", .type = FR_TYPE_COMBO_IP_ADDR, .dict = &dict_freeradius },
53  { .out = &attr_net_dst_port, .name = "Net.Dst.Port", .type = FR_TYPE_UINT16, .dict = &dict_freeradius },
54  { .out = &attr_net_timestamp, .name = "Net.Timestamp", .type = FR_TYPE_DATE, .dict = &dict_freeradius },
55 
56  { NULL }
57 };
58 
59 static int inet2pairs(TALLOC_CTX *ctx, fr_pair_list_t *list,
60  fr_dict_attr_t const *attr_ip, fr_dict_attr_t const *attr_port,
61  fr_ipaddr_t const *ipaddr, uint16_t port)
62 {
63  fr_pair_t *vp;
64 
65  if (fr_pair_find_or_append_by_da(ctx, &vp, list, attr_ip) < 0) return -1;
66  fr_value_box_ipaddr(&vp->data, attr_ip, ipaddr, false);
68 
69  if (fr_pair_find_or_append_by_da(ctx, &vp, list, attr_port) < 0) return -1;
70  vp->vp_uint16 = port;
72 
73  return 0;
74 }
75 
76 /** Allocate a "Net." struct with src/dst host and port.
77  *
78  * @param ctx The context in which the packet is allocated.
79  * @param[in] list #fr_pair_list_t value to resolve to #fr_packet_t.
80  * @param[out] packet The request packet.
81  *
82  * @return
83  * - 0 on success
84  * - <0 on error.
85  */
86 int fr_packet_pairs_from_packet(TALLOC_CTX *ctx, fr_pair_list_t *list, fr_packet_t const *packet)
87 {
88  fr_pair_t *vp, *net, *tlv;
89 
90  /*
91  * Net
92  */
93  if (fr_pair_find_or_append_by_da(ctx, &net, list, attr_net) < 0) return -1;
94 
95  /*
96  * Net.Src
97  */
98  if (fr_pair_find_or_append_by_da(net, &tlv, &net->vp_group, attr_net_src) < 0) return -1;
99 
100  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;
101 
102  /*
103  * Net.Dst
104  */
105  if (fr_pair_find_or_append_by_da(net, &tlv, &net->vp_group, attr_net_dst) < 0) return -1;
106 
107  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;
108 
109  /*
110  * Timestamp
111  */
112  if (fr_pair_find_or_append_by_da(net, &vp, &net->vp_group, attr_net_timestamp) < 0) return -1;
113  vp->vp_date = fr_time_to_unix_time(packet->timestamp);
115 
116  return 0;
117 }
118 
119 static void pairs2inet(fr_ipaddr_t *ipaddr, uint16_t *port, fr_pair_list_t const *list,
120  fr_dict_attr_t const *attr_ip, fr_dict_attr_t const *attr_port)
121 {
122  fr_pair_t *vp;
123 
124  vp = fr_pair_find_by_da(list, NULL, attr_ip);
125  if (vp) *ipaddr = vp->vp_ip;
126 
127  vp = fr_pair_find_by_da(list, NULL, attr_port);
128  if (vp) *port = vp->vp_uint16;
129 }
130 
131 /** Convert pairs to information in a packet.
132  *
133  * @param packet the packet to send
134  * @param list the list to check for Net.*
135  */
137 {
138  fr_pair_t *net, *tlv;
139 
140  net = fr_pair_find_by_da(list, NULL, attr_net);
141  if (!net) return;
142 
143  tlv = fr_pair_find_by_da(&net->vp_group, NULL, attr_net_src);
144  if (tlv) {
145  pairs2inet(&packet->socket.inet.src_ipaddr, &packet->socket.inet.src_port, &tlv->vp_group,
147  }
148 
149  tlv = fr_pair_find_by_da(&net->vp_group, NULL, attr_net_dst);
150  if (tlv) {
151  pairs2inet(&packet->socket.inet.dst_ipaddr, &packet->socket.inet.dst_port, &tlv->vp_group,
153  }
154 }
155 
156 /** Initialises the Net. packet attributes.
157  *
158  * @note Call packet_global_free() when the server is done to avoid leaks.
159  * @return
160  * - 0 on success.
161  * - -1 on failure.
162  */
164 {
166  error:
167  fr_perror("packet_global_init");
168  return -1;
169  }
170 
171  if (fr_dict_attr_autoload(util_packet_dict_attr) < 0) goto error;
172 
173  return 0;
174 }
175 
177 {
179 }
#define RCSID(id)
Definition: build.h:444
#define fr_dict_autofree(_to_free)
Definition: dict.h:674
fr_dict_attr_t const ** out
Where to write a pointer to the resolved fr_dict_attr_t.
Definition: dict.h:250
fr_dict_t const ** out
Where to write a pointer to the loaded/resolved fr_dict_t.
Definition: dict.h:263
int fr_dict_attr_autoload(fr_dict_attr_autoload_t const *to_load)
Process a dict_attr_autoload element to load/verify a dictionary attribute.
Definition: dict_util.c:3647
#define fr_dict_autoload(_to_load)
Definition: dict.h:671
Specifies an attribute which must be present for the module to function.
Definition: dict.h:249
Specifies a dictionary which must be loaded/loadable for the module to function.
Definition: dict.h:262
IPv4/6 prefix.
Definition: merged_model.c:272
int packet_global_init(void)
Initialises the Net.
Definition: packet.c:163
void fr_packet_pairs_to_packet(fr_packet_t *packet, fr_pair_list_t const *list)
Convert pairs to information in a packet.
Definition: packet.c:136
static fr_dict_attr_t const * attr_net_src
Definition: packet.c:37
static void pairs2inet(fr_ipaddr_t *ipaddr, uint16_t *port, fr_pair_list_t const *list, fr_dict_attr_t const *attr_ip, fr_dict_attr_t const *attr_port)
Definition: packet.c:119
static int inet2pairs(TALLOC_CTX *ctx, fr_pair_list_t *list, fr_dict_attr_t const *attr_ip, fr_dict_attr_t const *attr_port, fr_ipaddr_t const *ipaddr, uint16_t port)
Definition: packet.c:59
static fr_dict_attr_t const * attr_net_dst_port
Definition: packet.c:42
static fr_dict_t const * dict_freeradius
Definition: packet.c:28
static fr_dict_attr_t const * attr_net_timestamp
Definition: packet.c:43
fr_dict_autoload_t util_packet_dict[]
Definition: packet.c:31
static fr_dict_attr_t const * attr_net
Definition: packet.c:36
int fr_packet_pairs_from_packet(TALLOC_CTX *ctx, fr_pair_list_t *list, fr_packet_t const *packet)
Allocate a "Net." struct with src/dst host and port.
Definition: packet.c:86
static fr_dict_attr_t const * attr_net_dst
Definition: packet.c:40
void packet_global_free(void)
Definition: packet.c:176
fr_dict_attr_autoload_t util_packet_dict_attr[]
Definition: packet.c:46
static fr_dict_attr_t const * attr_net_src_ip
Definition: packet.c:38
static fr_dict_attr_t const * attr_net_dst_ip
Definition: packet.c:41
static fr_dict_attr_t const * attr_net_src_port
Definition: packet.c:39
unsigned short uint16_t
Definition: merged_model.c:31
@ FR_TYPE_TLV
Contains nested attributes.
Definition: merged_model.c:118
@ FR_TYPE_UINT16
16 Bit unsigned integer.
Definition: merged_model.c:98
@ FR_TYPE_DATE
Unix time stamp, always has value >2^31.
Definition: merged_model.c:111
@ FR_TYPE_COMBO_IP_ADDR
IPv4 or IPv6 address depending on length.
Definition: merged_model.c:91
fr_pair_t * fr_pair_find_by_da(fr_pair_list_t const *list, fr_pair_t const *prev, fr_dict_attr_t const *da)
Find the first pair with a matching da.
Definition: pair.c:688
fr_pair_t * vp
Stores an attribute, a value and various bits of other data.
Definition: pair.h:68
static fr_unix_time_t fr_time_to_unix_time(fr_time_t when)
Convert an fr_time_t (internal time) to our version of unix time (wallclock time)
Definition: time.h:686
fr_socket_t socket
This packet was received on.
Definition: packet.h:57
fr_time_t timestamp
When we received the packet.
Definition: packet.h:58
static int fr_pair_find_or_append_by_da(TALLOC_CTX *ctx, fr_pair_t **out, fr_pair_list_t *list, fr_dict_attr_t const *da)
Definition: pair.h:522
static void fr_pair_set_immutable(fr_pair_t *vp)
Definition: pair.h:687
void fr_perror(char const *fmt,...)
Print the current error to stderr with a prefix.
Definition: strerror.c:733
int fr_value_box_ipaddr(fr_value_box_t *dst, fr_dict_attr_t const *enumv, fr_ipaddr_t const *ipaddr, bool tainted)
Assign a fr_value_box_t value from an fr_ipaddr_t.
Definition: value.c:3579