The FreeRADIUS server
$Id: a4e7f8c94e8038b7627bcf52356b7ed15955c1d7 $
Loading...
Searching...
No Matches
src
lib
bio
fd_errno.h
Go to the documentation of this file.
1
#pragma once
2
/*
3
* This program is free software; you can redistribute it and/or modify
4
* it under the terms of the GNU General Public License as published by
5
* the Free Software Foundation; either version 2 of the License, or
6
* (at your option) any later version.
7
*
8
* This program is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
* GNU General Public License for more details.
12
*
13
* You should have received a copy of the GNU General Public License
14
* along with this program; if not, write to the Free Software
15
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
16
*/
17
18
/**
19
* $Id: 9a884b08baabab3c5ae5f44246186e28456b9ad1 $
20
* @file lib/bio/fd_errno.h
21
* @brief Common errno handling for FD bio reads and writes.
22
*
23
* @copyright 2024 Network RADIUS SAS (legal@networkradius.com)
24
*/
25
RCSIDH
(lib_bio_fd_errno_h,
"$Id: 9a884b08baabab3c5ae5f44246186e28456b9ad1 $"
)
26
27
#include <freeradius-devel/bio/fd_priv.h>
28
29
/** Turn a failed read / write into a bio return code.
30
*
31
* Only called when the syscall failed, i.e. when rcode is negative.
32
*
33
* @param my the FD bio.
34
* @param[in,out] rcode_p in: the failed syscall return code. out: what to return to the application.
35
* @param[in,out] tries_p how many times we have retried on EINTR.
36
* @param is_write true for the write path, false for the read path.
37
* @return
38
* - false return *rcode_p to the application.
39
* - true the syscall was interrupted, redo it.
40
*/
41
static
inline
CC_HINT(always_inline)
bool
fr_bio_fd_errno_retry
(
fr_bio_fd_t
*my,
ssize_t
*rcode_p,
int
*tries_p,
bool
is_write)
42
{
43
bool
*blocked = is_write ? &my->
info
.
write_blocked
: &my->
info
.
read_blocked
;
44
fr_bio_io_t
blocked_cb = is_write ? my->cb.write_blocked : my->cb.read_blocked;
45
46
switch
(errno) {
47
case
EINTR:
48
/*
49
* Try a few times before giving up.
50
*/
51
(*tries_p)++;
52
if
(*tries_p <= my->max_tries)
return
true
;
53
54
*rcode_p =
fr_bio_error
(IO);
55
return
false
;
56
57
#if defined(EWOULDBLOCK) && (EWOULDBLOCK != EAGAIN)
58
case
EWOULDBLOCK:
59
#endif
60
case
EAGAIN:
61
/*
62
* The operation would block, return that.
63
*/
64
if
(!*blocked) {
65
*blocked =
true
;
66
67
if
(blocked_cb) {
68
int
error;
69
70
error = blocked_cb((
fr_bio_t
*) my);
71
if
(error < 0) {
72
*rcode_p = error;
73
return
false
;
74
}
75
}
76
}
77
78
*rcode_p =
fr_bio_error
(IO_WOULD_BLOCK);
79
return
false
;
80
81
/*
82
* We're reading / writing a connected UDP socket, and the other end has gone away.
83
*/
84
case
ENOTCONN:
85
86
/*
87
* The other end of a socket has closed the connection.
88
*/
89
case
ECONNRESET:
90
91
/*
92
* The other end of a pipe has closed the connection.
93
*/
94
case
EPIPE:
95
/*
96
* The connection is no longer usable, so we call shutdown, rather than just marking it
97
* as being at EOF.
98
*/
99
(void)
fr_bio_shutdown
(&my->bio);
100
*rcode_p = 0;
101
return
false
;
102
103
/*
104
* PMTU has been exceeded. Return a generic IO error.
105
*
106
* Only a write can exceed the PMTU, so a read which somehow reports EMSGSIZE is fatal.
107
*
108
* @todo - do this only for connected UDP sockets.
109
*
110
* However, recvmsg() can also return EMSGSIZE, if the msg_iovlen field has a bad value.
111
*/
112
case
EMSGSIZE:
113
*rcode_p =
fr_bio_error
(IO);
114
return
false
;
115
116
/*
117
* The underlying network has gone away. This is a fatal error for connected sockets,
118
* but a recoverable one for unconnected sockets.
119
*/
120
case
ENETDOWN:
121
case
ENETUNREACH:
122
*rcode_p =
fr_bio_error
(IO);
123
return
false
;
124
125
default
:
126
/*
127
* Some other error, it's fatal.
128
*/
129
break
;
130
}
131
132
/*
133
* Shut down the BIO. It's no longer useable.
134
*/
135
(void)
fr_bio_shutdown
(&my->bio);
136
137
*rcode_p =
fr_bio_error
(IO);
138
return
false
;
139
}
140
141
/*
142
* Common code to suppress network failures on sendto / sendfromto for unconnected UDP sockets.
143
*
144
* If the destination network is down or is unreachable, we want to simply discard the packet. The error
145
* isn't fatal, so we don't close the socket.
146
*/
147
#define FD_ENET_SUPPRESS \
148
do { \
149
if ((rcode == fr_bio_error(IO)) && ((errno == ENETDOWN) || (errno == ENETUNREACH))) return 0; \
150
} while (0)
fr_bio_io_t
int(* fr_bio_io_t)(fr_bio_t *bio)
Definition
base.h:84
fr_bio_error
#define fr_bio_error(_x)
Definition
base.h:200
fr_bio_s
Definition
base.h:113
RCSIDH
#define RCSIDH(h, id)
Definition
build.h:604
fr_bio_fd_info_t::read_blocked
bool read_blocked
did we block on read?
Definition
fd.h:152
fr_bio_fd_info_t::write_blocked
bool write_blocked
did we block on write?
Definition
fd.h:153
fr_bio_fd_errno_retry
static bool fr_bio_fd_errno_retry(fr_bio_fd_t *my, ssize_t *rcode_p, int *tries_p, bool is_write)
Turn a failed read / write into a bio return code.
Definition
fd_errno.h:41
fr_bio_fd_s::info
fr_bio_fd_info_t info
Definition
fd_priv.h:38
fr_bio_fd_s
Our FD bio structure.
Definition
fd_priv.h:35
fr_bio_shutdown
int fr_bio_shutdown(fr_bio_t *bio)
Shut down a set of BIOs.
Definition
base.c:158
ssize_t
long int ssize_t
Definition
merged_model.c:21
Generated by
1.9.8