]> git.proxmox.com Git - mirror_frr.git/blame - nhrpd/znl.c
zebra: update local ns_id field
[mirror_frr.git] / nhrpd / znl.c
CommitLineData
2fb975da
TT
1/* Netlink helpers for zbuf
2 * Copyright (c) 2014-2015 Timo Teräs
3 *
4 * This file is free software: you may copy, redistribute and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 */
9
10#include <fcntl.h>
11#include <errno.h>
12#include <string.h>
13#include <unistd.h>
14#include <sys/types.h>
15#include <sys/socket.h>
16#include <linux/netlink.h>
17#include <linux/rtnetlink.h>
18
19#include "znl.h"
20
21#define ZNL_ALIGN(len) (((len)+3) & ~3)
22
23void *znl_push(struct zbuf *zb, size_t n)
24{
25 return zbuf_pushn(zb, ZNL_ALIGN(n));
26}
27
28void *znl_pull(struct zbuf *zb, size_t n)
29{
30 return zbuf_pulln(zb, ZNL_ALIGN(n));
31}
32
33struct nlmsghdr *znl_nlmsg_push(struct zbuf *zb, uint16_t type, uint16_t flags)
34{
35 struct nlmsghdr *n;
36
37 n = znl_push(zb, sizeof(*n));
996c9314
LB
38 if (!n)
39 return NULL;
2fb975da 40
996c9314
LB
41 *n = (struct nlmsghdr){
42 .nlmsg_type = type, .nlmsg_flags = flags,
2fb975da
TT
43 };
44 return n;
45}
46
47void znl_nlmsg_complete(struct zbuf *zb, struct nlmsghdr *n)
48{
996c9314 49 n->nlmsg_len = zb->tail - (uint8_t *)n;
2fb975da
TT
50}
51
52struct nlmsghdr *znl_nlmsg_pull(struct zbuf *zb, struct zbuf *payload)
53{
54 struct nlmsghdr *n;
55 size_t plen;
56
57 n = znl_pull(zb, sizeof(*n));
996c9314
LB
58 if (!n)
59 return NULL;
2fb975da
TT
60
61 plen = n->nlmsg_len - sizeof(*n);
62 zbuf_init(payload, znl_pull(zb, plen), plen, plen);
63 zbuf_may_pulln(zb, ZNL_ALIGN(plen) - plen);
64
65 return n;
66}
67
996c9314
LB
68struct rtattr *znl_rta_push(struct zbuf *zb, uint16_t type, const void *val,
69 size_t len)
2fb975da
TT
70{
71 struct rtattr *rta;
72 uint8_t *dst;
73
74 rta = znl_push(zb, ZNL_ALIGN(sizeof(*rta)) + ZNL_ALIGN(len));
996c9314
LB
75 if (!rta)
76 return NULL;
2fb975da 77
996c9314
LB
78 *rta = (struct rtattr){
79 .rta_type = type, .rta_len = ZNL_ALIGN(sizeof(*rta)) + len,
2fb975da
TT
80 };
81
996c9314 82 dst = (uint8_t *)(rta + 1);
2fb975da 83 memcpy(dst, val, len);
996c9314 84 memset(dst + len, 0, ZNL_ALIGN(len) - len);
2fb975da
TT
85
86 return rta;
87}
88
89struct rtattr *znl_rta_push_u32(struct zbuf *zb, uint16_t type, uint32_t val)
90{
91 return znl_rta_push(zb, type, &val, sizeof(val));
92}
93
94struct rtattr *znl_rta_nested_push(struct zbuf *zb, uint16_t type)
95{
96 struct rtattr *rta;
97
98 rta = znl_push(zb, sizeof(*rta));
996c9314
LB
99 if (!rta)
100 return NULL;
2fb975da 101
996c9314 102 *rta = (struct rtattr){
2fb975da
TT
103 .rta_type = type,
104 };
105 return rta;
106}
107
108void znl_rta_nested_complete(struct zbuf *zb, struct rtattr *rta)
109{
996c9314 110 size_t len = zb->tail - (uint8_t *)rta;
2fb975da
TT
111 size_t align = ZNL_ALIGN(len) - len;
112
113 if (align) {
114 void *dst = zbuf_pushn(zb, align);
996c9314
LB
115 if (dst)
116 memset(dst, 0, align);
2fb975da
TT
117 }
118 rta->rta_len = len;
119}
120
121struct rtattr *znl_rta_pull(struct zbuf *zb, struct zbuf *payload)
122{
123 struct rtattr *rta;
124 size_t plen;
125
126 rta = znl_pull(zb, sizeof(*rta));
996c9314
LB
127 if (!rta)
128 return NULL;
2fb975da
TT
129
130 if (rta->rta_len > sizeof(*rta)) {
131 plen = rta->rta_len - sizeof(*rta);
132 zbuf_init(payload, znl_pull(zb, plen), plen, plen);
133 } else {
134 zbuf_init(payload, NULL, 0, 0);
135 }
136
137 return rta;
138}
139
140int znl_open(int protocol, int groups)
141{
142 struct sockaddr_nl addr;
143 int fd, buf = 128 * 1024;
144
145 fd = socket(AF_NETLINK, SOCK_RAW, protocol);
146 if (fd < 0)
147 return -1;
148
6c8ca260
JB
149 if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK) < 0)
150 goto error;
151 if (fcntl(fd, F_SETFD, FD_CLOEXEC) < 0)
152 goto error;
2fb975da
TT
153 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &buf, sizeof(buf)) < 0)
154 goto error;
155
156 memset(&addr, 0, sizeof(addr));
157 addr.nl_family = AF_NETLINK;
158 addr.nl_groups = groups;
996c9314 159 if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
2fb975da
TT
160 goto error;
161
162 return fd;
163error:
164 close(fd);
165 return -1;
166}