libmnl  1.0.4
socket.c
1 /*
2  * (C) 2008-2010 by Pablo Neira Ayuso <pablo@netfilter.org>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published
6  * by the Free Software Foundation; either version 2.1 of the License, or
7  * (at your option) any later version.
8  */
9 
10 #include <libmnl/libmnl.h>
11 #include <sys/types.h>
12 #include <sys/socket.h>
13 #include <stdlib.h>
14 #include <unistd.h>
15 #include <time.h>
16 #include <errno.h>
17 #include "internal.h"
18 
69 struct mnl_socket {
70  int fd;
71  struct sockaddr_nl addr;
72 };
73 
85 EXPORT_SYMBOL(mnl_socket_get_fd);
86 int mnl_socket_get_fd(const struct mnl_socket *nl)
87 {
88  return nl->fd;
89 }
90 
100 EXPORT_SYMBOL(mnl_socket_get_portid);
101 unsigned int mnl_socket_get_portid(const struct mnl_socket *nl)
102 {
103  return nl->addr.nl_pid;
104 }
105 
106 static struct mnl_socket *__mnl_socket_open(int bus, int flags)
107 {
108  struct mnl_socket *nl;
109 
110  nl = calloc(1, sizeof(struct mnl_socket));
111  if (nl == NULL)
112  return NULL;
113 
114  nl->fd = socket(AF_NETLINK, SOCK_RAW | flags, bus);
115  if (nl->fd == -1) {
116  free(nl);
117  return NULL;
118  }
119 
120  return nl;
121 }
122 
130 EXPORT_SYMBOL(mnl_socket_open);
131 struct mnl_socket *mnl_socket_open(int bus)
132 {
133  return __mnl_socket_open(bus, 0);
134 }
135 
148 EXPORT_SYMBOL(mnl_socket_open2);
149 struct mnl_socket *mnl_socket_open2(int bus, int flags)
150 {
151  return __mnl_socket_open(bus, flags);
152 }
153 
165 EXPORT_SYMBOL(mnl_socket_fdopen);
166 struct mnl_socket *mnl_socket_fdopen(int fd)
167 {
168  int ret;
169  struct mnl_socket *nl;
170  struct sockaddr_nl addr;
171  socklen_t addr_len = sizeof(struct sockaddr_nl);
172 
173  ret = getsockname(fd, (struct sockaddr *) &addr, &addr_len);
174  if (ret == -1)
175  return NULL;
176 
177  nl = calloc(1, sizeof(struct mnl_socket));
178  if (nl == NULL)
179  return NULL;
180 
181  nl->fd = fd;
182  if (addr.nl_family == AF_NETLINK)
183  nl->addr = addr;
184 
185  return nl;
186 }
187 
198 EXPORT_SYMBOL(mnl_socket_bind);
199 int mnl_socket_bind(struct mnl_socket *nl, unsigned int groups, pid_t pid)
200 {
201  int ret;
202  socklen_t addr_len;
203 
204  nl->addr.nl_family = AF_NETLINK;
205  nl->addr.nl_groups = groups;
206  nl->addr.nl_pid = pid;
207 
208  ret = bind(nl->fd, (struct sockaddr *) &nl->addr, sizeof (nl->addr));
209  if (ret < 0)
210  return ret;
211 
212  addr_len = sizeof(nl->addr);
213  ret = getsockname(nl->fd, (struct sockaddr *) &nl->addr, &addr_len);
214  if (ret < 0)
215  return ret;
216 
217  if (addr_len != sizeof(nl->addr)) {
218  errno = EINVAL;
219  return -1;
220  }
221  if (nl->addr.nl_family != AF_NETLINK) {
222  errno = EINVAL;
223  return -1;
224  }
225  return 0;
226 }
227 
237 EXPORT_SYMBOL(mnl_socket_sendto);
238 ssize_t mnl_socket_sendto(const struct mnl_socket *nl, const void *buf,
239  size_t len)
240 {
241  static const struct sockaddr_nl snl = {
242  .nl_family = AF_NETLINK
243  };
244  return sendto(nl->fd, buf, len, 0,
245  (struct sockaddr *) &snl, sizeof(snl));
246 }
247 
262 EXPORT_SYMBOL(mnl_socket_recvfrom);
263 ssize_t mnl_socket_recvfrom(const struct mnl_socket *nl, void *buf,
264  size_t bufsiz)
265 {
266  ssize_t ret;
267  struct sockaddr_nl addr;
268  struct iovec iov = {
269  .iov_base = buf,
270  .iov_len = bufsiz,
271  };
272  struct msghdr msg = {
273  .msg_name = &addr,
274  .msg_namelen = sizeof(struct sockaddr_nl),
275  .msg_iov = &iov,
276  .msg_iovlen = 1,
277  .msg_control = NULL,
278  .msg_controllen = 0,
279  .msg_flags = 0,
280  };
281  ret = recvmsg(nl->fd, &msg, 0);
282  if (ret == -1)
283  return ret;
284 
285  if (msg.msg_flags & MSG_TRUNC) {
286  errno = ENOSPC;
287  return -1;
288  }
289  if (msg.msg_namelen != sizeof(struct sockaddr_nl)) {
290  errno = EINVAL;
291  return -1;
292  }
293  return ret;
294 }
295 
303 EXPORT_SYMBOL(mnl_socket_close);
304 int mnl_socket_close(struct mnl_socket *nl)
305 {
306  int ret = close(nl->fd);
307  free(nl);
308  return ret;
309 }
310 
336 EXPORT_SYMBOL(mnl_socket_setsockopt);
337 int mnl_socket_setsockopt(const struct mnl_socket *nl, int type,
338  void *buf, socklen_t len)
339 {
340  return setsockopt(nl->fd, SOL_NETLINK, type, buf, len);
341 }
342 
352 EXPORT_SYMBOL(mnl_socket_getsockopt);
353 int mnl_socket_getsockopt(const struct mnl_socket *nl, int type,
354  void *buf, socklen_t *len)
355 {
356  return getsockopt(nl->fd, SOL_NETLINK, type, buf, len);
357 }
358