]>
git.ipfire.org Git - people/ms/network.git/blob - src/libnetwork/libnetwork.c
1 /*#############################################################################
3 # IPFire.org - A linux based firewall #
4 # Copyright (C) 2017 IPFire Network Development Team #
6 # This program is free software: you can redistribute it and/or modify #
7 # it under the terms of the GNU General Public License as published by #
8 # the Free Software Foundation, either version 3 of the License, or #
9 # (at your option) any later version. #
11 # This program is distributed in the hope that it will be useful, #
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14 # GNU General Public License for more details. #
16 # You should have received a copy of the GNU General Public License #
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
19 #############################################################################*/
23 #include <linux/nl80211.h>
24 #include <netlink/genl/ctrl.h>
25 #include <netlink/genl/genl.h>
26 #include <netlink/netlink.h>
33 #include <network/libnetwork.h>
34 #include <network/logging.h>
35 #include "libnetwork-private.h"
41 void (*log_fn
)(struct network_ctx
* ctx
,
42 int priority
, const char *file
, int line
, const char *fn
,
43 const char *format
, va_list args
);
47 struct nl_sock
* nl_socket
;
51 void network_log(struct network_ctx
* ctx
,
52 int priority
, const char* file
, int line
, const char* fn
,
53 const char* format
, ...) {
56 va_start(args
, format
);
57 ctx
->log_fn(ctx
, priority
, file
, line
, fn
, format
, args
);
61 static void log_stderr(struct network_ctx
* ctx
,
62 int priority
, const char* file
, int line
, const char* fn
,
63 const char* format
, va_list args
) {
64 fprintf(stderr
, "libnetwork: %s: ", fn
);
65 vfprintf(stderr
, format
, args
);
68 static int log_priority(const char* priority
) {
71 int prio
= strtol(priority
, &endptr
, 10);
73 if (endptr
[0] == '\0' || isspace(endptr
[0]))
76 if (strncmp(priority
, "err", 3) == 0)
79 if (strncmp(priority
, "info", 4) == 0)
82 if (strncmp(priority
, "debug", 5) == 0)
88 static int init_netlink(struct network_ctx
* ctx
) {
89 // Allocate netlink socket
90 ctx
->nl_socket
= nl_socket_alloc();
91 if (!ctx
->nl_socket
) {
92 ERROR(ctx
, "Failed to allocate netlink socket\n");
97 if (genl_connect(ctx
->nl_socket
)) {
98 ERROR(ctx
, "Failed to connect to generic netlink");
103 nl_socket_set_buffer_size(ctx
->nl_socket
, 8192, 8192);
105 // Register socket callback
106 struct nl_cb
* callback
= nl_cb_alloc(NL_CB_DEFAULT
);
108 ERROR(ctx
, "Could not allocate socket callback\n");
112 nl_socket_set_cb(ctx
->nl_socket
, callback
);
115 ctx
->nl80211_id
= genl_ctrl_resolve(ctx
->nl_socket
, "nl80211");
116 if (ctx
->nl80211_id
< 0) {
117 ERROR(ctx
, "Could not find nl80211\n");
124 static void network_free(struct network_ctx
* ctx
) {
125 DEBUG(ctx
, "network ctx %p released\n", ctx
);
127 // Free netlink socket
129 nl_socket_free(ctx
->nl_socket
);
134 NETWORK_EXPORT
int network_new(struct network_ctx
** ctx
) {
135 struct network_ctx
* c
= calloc(1, sizeof(*c
));
139 // Initialise basic variables
142 // Initialise logging
143 c
->log_fn
= log_stderr
;
144 c
->log_priority
= LOG_ERR
;
146 const char* env
= secure_getenv("NETWORK_LOG");
148 network_set_log_priority(c
, log_priority(env
));
150 // Initiate netlink connection
151 int r
= init_netlink(c
);
157 INFO(c
, "network ctx %p created\n", c
);
158 DEBUG(c
, "log_priority=%d\n", c
->log_priority
);
164 NETWORK_EXPORT
struct network_ctx
* network_ref(struct network_ctx
* ctx
) {
172 NETWORK_EXPORT
struct network_ctx
* network_unref(struct network_ctx
* ctx
) {
176 if (--ctx
->refcount
> 0)
183 NETWORK_EXPORT
void network_set_log_fn(struct network_ctx
* ctx
,
184 void (*log_fn
)(struct network_ctx
* ctx
, int priority
, const char* file
,
185 int line
, const char* fn
, const char* format
, va_list args
)) {
186 ctx
->log_fn
= log_fn
;
187 INFO(ctx
, "custom logging function %p registered\n", log_fn
);
190 NETWORK_EXPORT
int network_get_log_priority(struct network_ctx
* ctx
) {
191 return ctx
->log_priority
;
194 NETWORK_EXPORT
void network_set_log_priority(struct network_ctx
* ctx
, int priority
) {
195 ctx
->log_priority
= priority
;
198 NETWORK_EXPORT
const char* network_version() {
199 return "network " VERSION
;
202 // Creates a netlink message that can be sent with network_send_netlink_message
203 struct nl_msg
* network_make_netlink_message(struct network_ctx
* ctx
,
204 enum nl80211_commands cmd
, int flags
) {
206 struct nl_msg
* msg
= nlmsg_alloc();
210 genlmsg_put(msg
, 0, 0, ctx
->nl80211_id
, 0, flags
, cmd
, 0);
212 DEBUG(ctx
, "Created new netlink message %p\n", msg
);
217 static int __nl_ack_handler(struct nl_msg
* msg
, void* data
) {
224 static int __nl_finish_handler(struct nl_msg
* msg
, void* data
) {
231 // Sends a netlink message and calls the handler to handle the result
232 int network_send_netlink_message(struct network_ctx
* ctx
, struct nl_msg
* msg
,
233 int(*handler
)(struct nl_msg
* msg
, void* data
), void* data
) {
234 DEBUG(ctx
, "Sending netlink message %p\n", msg
);
236 // Sending the message
237 int r
= nl_send_auto(ctx
->nl_socket
, msg
);
239 ERROR(ctx
, "Error sending netlink message: %d\n", r
);
244 struct nl_cb
* callback
= nl_cb_alloc(NL_CB_DEFAULT
);
246 ERROR(ctx
, "Could not allocate callback\n");
254 nl_cb_set(callback
, NL_CB_VALID
, NL_CB_CUSTOM
, handler
, data
);
255 nl_cb_set(callback
, NL_CB_ACK
, NL_CB_CUSTOM
, __nl_ack_handler
, &r
);
256 nl_cb_set(callback
, NL_CB_FINISH
, NL_CB_CUSTOM
, __nl_finish_handler
, &r
);
259 nl_recvmsgs(ctx
->nl_socket
, callback
);
261 DEBUG(ctx
, "Netlink message returned with status %d\n", r
);