]> git.ipfire.org Git - network.git/blame - src/libnetwork/libnetwork.c
libnetwork: Initialise netlink connection when initialising context
[network.git] / src / libnetwork / libnetwork.c
CommitLineData
01f2b2e4
MT
1/*#############################################################################
2# #
3# IPFire.org - A linux based firewall #
4# Copyright (C) 2017 IPFire Network Development Team #
5# #
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. #
10# #
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. #
15# #
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/>. #
18# #
19#############################################################################*/
20
6f4814db 21#include <ctype.h>
0e880048 22#include <errno.h>
83d23950
MT
23#include <netlink/genl/ctrl.h>
24#include <netlink/genl/genl.h>
25#include <netlink/netlink.h>
6f4814db
MT
26#include <stdarg.h>
27#include <stdio.h>
0e880048 28#include <stdlib.h>
6f4814db
MT
29#include <string.h>
30#include <syslog.h>
0e880048 31
01f2b2e4 32#include <network/libnetwork.h>
6f4814db 33#include <network/logging.h>
01f2b2e4
MT
34#include "libnetwork-private.h"
35
0e880048
MT
36struct network_ctx {
37 int refcount;
6f4814db
MT
38
39 // Logging
40 void (*log_fn)(struct network_ctx* ctx,
41 int priority, const char *file, int line, const char *fn,
42 const char *format, va_list args);
43 int log_priority;
83d23950
MT
44
45 // Netlink
46 struct nl_sock* nl_socket;
47 int nl80211_id;
0e880048
MT
48};
49
6f4814db
MT
50void network_log(struct network_ctx* ctx,
51 int priority, const char* file, int line, const char* fn,
52 const char* format, ...) {
53 va_list args;
54
55 va_start(args, format);
56 ctx->log_fn(ctx, priority, file, line, fn, format, args);
57 va_end(args);
58}
59
60static void log_stderr(struct network_ctx* ctx,
61 int priority, const char* file, int line, const char* fn,
62 const char* format, va_list args) {
63 fprintf(stderr, "libnetwork: %s: ", fn);
64 vfprintf(stderr, format, args);
65}
66
67static int log_priority(const char* priority) {
68 char *endptr;
69
70 int prio = strtol(priority, &endptr, 10);
71
72 if (endptr[0] == '\0' || isspace(endptr[0]))
73 return prio;
74
75 if (strncmp(priority, "err", 3) == 0)
76 return LOG_ERR;
77
78 if (strncmp(priority, "info", 4) == 0)
79 return LOG_INFO;
80
81 if (strncmp(priority, "debug", 5) == 0)
82 return LOG_DEBUG;
83
84 return 0;
85}
86
83d23950
MT
87static int init_netlink(struct network_ctx* ctx) {
88 // Allocate netlink socket
89 ctx->nl_socket = nl_socket_alloc();
90 if (!ctx->nl_socket) {
91 ERROR(ctx, "Failed to allocate netlink socket\n");
92 return -ENOMEM;
93 }
94
95 // Connect the socket
96 if (genl_connect(ctx->nl_socket)) {
97 ERROR(ctx, "Failed to connect to generic netlink");
98 return -ENOLINK;
99 }
100
101 // Set buffer size
102 nl_socket_set_buffer_size(ctx->nl_socket, 8192, 8192);
103
104 // Get nl80211 id
105 ctx->nl80211_id = genl_ctrl_resolve(ctx->nl_socket, "nl80211");
106 if (ctx->nl80211_id < 0) {
107 ERROR(ctx, "Could not find nl80211\n");
108 return -ENOENT;
109 }
110
111 return 0;
112}
113
114static void network_free(struct network_ctx* ctx) {
115 DEBUG(ctx, "network ctx %p released\n", ctx);
116
117 // Free netlink socket
118 if (ctx->nl_socket)
119 nl_socket_free(ctx->nl_socket);
120
121 free(ctx);
122}
123
0e880048
MT
124NETWORK_EXPORT int network_new(struct network_ctx** ctx) {
125 struct network_ctx* c = calloc(1, sizeof(*c));
126 if (!c)
127 return -ENOMEM;
128
129 // Initialise basic variables
130 c->refcount = 1;
131
6f4814db
MT
132 // Initialise logging
133 c->log_fn = log_stderr;
134 c->log_priority = LOG_ERR;
135
136 const char* env = secure_getenv("NETWORK_LOG");
137 if (env)
138 network_set_log_priority(c, log_priority(env));
139
83d23950
MT
140 // Initiate netlink connection
141 int r = init_netlink(c);
142 if (r) {
143 network_free(c);
144 return r;
145 }
146
6f4814db
MT
147 INFO(c, "network ctx %p created\n", c);
148 DEBUG(c, "log_priority=%d\n", c->log_priority);
149
0e880048
MT
150 *ctx = c;
151 return 0;
152}
153
154NETWORK_EXPORT struct network_ctx* network_ref(struct network_ctx* ctx) {
155 if (!ctx)
156 return NULL;
157
158 ctx->refcount++;
159 return ctx;
160}
161
0e880048
MT
162NETWORK_EXPORT struct network_ctx* network_unref(struct network_ctx* ctx) {
163 if (!ctx)
164 return NULL;
165
166 if (--ctx->refcount > 0)
167 return ctx;
168
169 network_free(ctx);
170 return NULL;
171}
172
6f4814db
MT
173NETWORK_EXPORT void network_set_log_fn(struct network_ctx* ctx,
174 void (*log_fn)(struct network_ctx* ctx, int priority, const char* file,
175 int line, const char* fn, const char* format, va_list args)) {
176 ctx->log_fn = log_fn;
177 INFO(ctx, "custom logging function %p registered\n", log_fn);
178}
179
180NETWORK_EXPORT int network_get_log_priority(struct network_ctx* ctx) {
181 return ctx->log_priority;
182}
183
184NETWORK_EXPORT void network_set_log_priority(struct network_ctx* ctx, int priority) {
185 ctx->log_priority = priority;
186}
187
01f2b2e4
MT
188NETWORK_EXPORT const char* network_version() {
189 return "network " VERSION;
190}