X-Git-Url: http://git.openwrt.org/?a=blobdiff_plain;f=wg-linux.c;h=0a17c90bac7a79fc28335cba4391ce4fa69f511c;hb=HEAD;hp=a9f37b9d443b1ba54c50119b7f5131c5ca38120b;hpb=abfebece0af1c97a8d063d9e83080a1ee88cf20d;p=project%2Funetd.git diff --git a/wg-linux.c b/wg-linux.c index a9f37b9..0a17c90 100644 --- a/wg-linux.c +++ b/wg-linux.c @@ -36,7 +36,7 @@ struct timespec64 { struct wg_linux_peer_req { struct nl_msg *msg; - struct nlattr *peers, *entry; + struct nlattr *peers, *entry, *ips; }; static struct unl unl; @@ -44,10 +44,19 @@ static struct unl unl; static int wg_nl_init(void) { + int ret; + if (unl.sock) return 0; - return unl_genl_init(&unl, "wireguard"); + ret = unl_genl_init(&unl, "wireguard"); + if (ret) + return ret; + + nl_socket_set_buffer_size(unl.sock, 32768, 32768); + nlmsg_set_default_size(32768); + + return 0; } static struct nl_msg * @@ -102,7 +111,7 @@ wg_linux_init_local(struct network *net, struct network_peer *peer) struct nl_msg *msg; msg = wg_genl_msg(net, true); - nla_put_u16(msg, WGDEVICE_A_LISTEN_PORT, peer->port); + nla_put_u16(msg, WGDEVICE_A_LISTEN_PORT, peer ? peer->port : 0); return wg_genl_call(msg); } @@ -147,13 +156,33 @@ wg_linux_peer_req_done(struct wg_linux_peer_req *req) return wg_genl_call(req->msg); } +static struct nl_msg * +wg_linux_peer_msg_size_check(struct wg_linux_peer_req *req, struct network *net, + struct network_peer *peer) +{ + if (nlmsg_get_max_size(req->msg) > + nlmsg_total_size(nlmsg_hdr(req->msg)->nlmsg_len) + 256) + return req->msg; + + nla_nest_end(req->msg, req->ips); + wg_linux_peer_req_done(req); + + wg_linux_peer_req_init(net, peer, req); + req->ips = nla_nest_start(req->msg, WGPEER_A_ALLOWEDIPS); + + return req->msg; +} + static void -wg_linux_peer_msg_add_allowed_ip(struct nl_msg *msg, struct network_peer *peer) +wg_linux_peer_msg_add_allowed_ip(struct wg_linux_peer_req *req, struct network *net, + struct network_peer *peer) { + struct nl_msg *msg = req->msg; struct blob_attr *cur; int rem; wg_linux_msg_add_ip(msg, AF_INET6, &peer->local_addr.in6, 128); + msg = wg_linux_peer_msg_size_check(req, net, peer); blobmsg_for_each_attr(cur, peer->ipaddr, rem) { const char *str = blobmsg_get_string(cur); @@ -172,6 +201,7 @@ wg_linux_peer_msg_add_allowed_ip(struct nl_msg *msg, struct network_peer *peer) continue; wg_linux_msg_add_ip(msg, af, &in6, mask); + msg = wg_linux_peer_msg_size_check(req, net, peer); } blobmsg_for_each_attr(cur, peer->subnet, rem) { @@ -185,8 +215,8 @@ wg_linux_peer_msg_add_allowed_ip(struct nl_msg *msg, struct network_peer *peer) continue; wg_linux_msg_add_ip(msg, af, &addr, mask); + msg = wg_linux_peer_msg_size_check(req, net, peer); } - } static int @@ -194,25 +224,24 @@ wg_linux_peer_update(struct network *net, struct network_peer *peer, enum wg_upd { struct wg_linux_peer_req req; struct network_host *host; - struct nl_msg *msg; - struct nlattr *ips; - msg = wg_linux_peer_req_init(net, peer, &req); + wg_linux_peer_req_init(net, peer, &req); if (cmd == WG_PEER_DELETE) { - nla_put_u32(msg, WGPEER_A_FLAGS, WGPEER_F_REMOVE_ME); + nla_put_u32(req.msg, WGPEER_A_FLAGS, WGPEER_F_REMOVE_ME); goto out; } - nla_put_u32(msg, WGPEER_A_FLAGS, WGPEER_F_REPLACE_ALLOWEDIPS); + nla_put_u32(req.msg, WGPEER_A_FLAGS, WGPEER_F_REPLACE_ALLOWEDIPS); + + req.ips = nla_nest_start(req.msg, WGPEER_A_ALLOWEDIPS); - ips = nla_nest_start(msg, WGPEER_A_ALLOWEDIPS); + wg_linux_peer_msg_add_allowed_ip(&req, net, peer); - wg_linux_peer_msg_add_allowed_ip(msg, peer); for_each_routed_host(host, net, peer) - wg_linux_peer_msg_add_allowed_ip(msg, &host->peer); + wg_linux_peer_msg_add_allowed_ip(&req, net, &host->peer); - nla_nest_end(msg, ips); + nla_nest_end(req.msg, req.ips); out: return wg_linux_peer_req_done(&req);