return fr_bio_error(IO);
}
+/** Files are a special case of connected sockets.
+ *
+ */
+static int fr_bio_fd_init_file(fr_bio_fd_t *my)
+{
+ my->info.state = FR_BIO_FD_STATE_OPEN;
+ my->info.eof = false;
+ my->info.read_blocked = false;
+ my->info.write_blocked = false;
+
+ switch (my->info.cfg->flags) {
+ case O_RDONLY:
+ my->bio.read = fr_bio_fd_read_stream;
+ my->bio.write = fr_bio_null_write; /* @todo - error on write? */
+ break;
+
+ case O_WRONLY:
+ my->bio.read = fr_bio_null_read; /* @todo - error on read? */
+ my->bio.write = fr_bio_fd_write;
+ break;
+
+ case O_RDWR:
+ my->bio.read = fr_bio_fd_read_stream;
+ my->bio.write = fr_bio_fd_write;
+ break;
+
+ default:
+ fr_strerror_const("Invalid flag for opening file");
+ return -1;
+ }
+
+ return 0;
+}
+
int fr_bio_fd_init_connected(fr_bio_fd_t *my)
{
+ if (my->info.socket.af == AF_FILE) return fr_bio_fd_init_file(my);
+
/*
* Connected datagrams must have real IPs
*/
return 0;
}
-
/** Allocate a FD bio
*
* The caller is responsible for tracking the FD, and all associated management of it. The bio API is
} else {
my->info.state = FR_BIO_FD_STATE_CLOSED;
- if (fr_bio_fd_socket_open(&my->bio, cfg) < 0) {
+ if (fr_bio_fd_open(&my->bio, cfg) < 0) {
talloc_free(my);
return NULL;
}
return 0;
}
-/** re-open the bio
- */
-int fr_bio_fd_init(fr_bio_t *bio, fr_socket_t const *sock)
-{
- fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
-
- fr_assert(my->info.socket.inet.src_ipaddr.af == my->info.socket.inet.dst_ipaddr.af);
-
- /*
- * The bio can't be open if we're re-initializing it.
- */
- if (my->info.state == FR_BIO_FD_STATE_OPEN) return -1;
-
- my->info.socket = *sock;
-
- switch (my->info.type) {
- case FR_BIO_FD_UNCONNECTED:
- return fr_bio_fd_init_common(my);
-
- case FR_BIO_FD_CONNECTED:
- return fr_bio_fd_init_connected(my);
-
- case FR_BIO_FD_ACCEPT:
- return fr_bio_fd_init_accept(my);
- }
-
- return -1;
-}
-
/** Finalize a connect()
*
* connect() said "come back when the socket is writeable". It's now writeable, so we check if there was a
#include <freeradius-devel/bio/base.h>
#include <freeradius-devel/util/socket.h>
+#include <fcntl.h>
+
+/*
+ * Local hack.
+ */
+#define AF_FILE (INT_MAX)
+
/** Per-packet context
*
* For reading packets src_ip is *their* IP, and dst_ip is *our* IP.
uid_t uid; //!< who owns the socket
gid_t gid; //!< who owns the socket
+ char const *filename; //!< for files
+ int flags; //!< O_RDONLY, etc.
+
bool async; //!< is it async
} fr_bio_fd_config_t;
int fr_bio_fd_close(fr_bio_t *bio) CC_HINT(nonnull);
-int fr_bio_fd_init(fr_bio_t *bio, fr_socket_t const *sock) CC_HINT(nonnull);
-
int fr_bio_fd_connect(fr_bio_t *bio) CC_HINT(nonnull);
fr_bio_fd_info_t const *fr_bio_fd_info(fr_bio_t *bio) CC_HINT(nonnull);
-int fr_bio_fd_socket_open(fr_bio_t *bio, fr_bio_fd_config_t const *cfg) CC_HINT(nonnull);
+int fr_bio_fd_open(fr_bio_t *bio, fr_bio_fd_config_t const *cfg) CC_HINT(nonnull);
int fr_bio_fd_write_only(fr_bio_t *bio);
*
* Note that it does not call connect()!
*/
-int fr_bio_fd_socket_open(fr_bio_t *bio, fr_bio_fd_config_t const *cfg)
+int fr_bio_fd_open(fr_bio_t *bio, fr_bio_fd_config_t const *cfg)
{
- int fd, protocol;
+ int fd;
int rcode;
fr_bio_fd_t *my = talloc_get_type_abort(bio, fr_bio_fd_t);
.cfg = cfg,
};
- if (!cfg->path) {
+ if (!cfg->path && !cfg->filename) {
+ int protocol;
+
my->info.socket.af = cfg->src_ipaddr.af;
my->info.socket.inet.src_ipaddr = cfg->src_ipaddr;
my->info.socket.inet.dst_ipaddr = cfg->dst_ipaddr;
return -1;
}
}
- } else {
- my->info.socket.af = AF_UNIX;
+
+ fd = socket(my->info.socket.af, my->info.socket.type, protocol);
+ if (fd < 0) {
+ fr_strerror_printf("Failed opening socket: %s", fr_syserror(errno));
+ return -1;
+ }
+
+ } else if (cfg->path) {
+ my->info.socket.af = AF_LOCAL;
my->info.socket.type = SOCK_STREAM;
my->info.socket.unix.path = cfg->path;
- protocol = 0;
- }
- /*
- * Open the socket.
- */
- fd = socket(my->info.socket.af, my->info.socket.type, protocol);
- if (fd < 0) {
- fr_strerror_printf("Failed opening socket: %s", fr_syserror(errno));
- return -1;
+ fd = socket(my->info.socket.af, my->info.socket.type, 0);
+ if (fd < 0) {
+ fr_strerror_printf("Failed opening domain socket %s: %s", cfg->path, fr_syserror(errno));
+ return -1;
+ }
+
+ } else {
+ /*
+ * Filenames overload the #fr_socket_t for now.
+ */
+ my->info.socket.af = AF_FILE;
+ my->info.socket.type = SOCK_STREAM;
+ my->info.socket.unix.path = cfg->filename;
+
+ fd = open(cfg->filename, cfg->flags);
+ if (fd < 0) {
+ fr_strerror_printf("Failed opening file %s: %s", cfg->filename, fr_syserror(errno));
+ return -1;
+ }
}
/*