libmnl  1.0.5
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 int mnl_socket_get_fd(const struct mnl_socket *nl)
86 {
87  return nl->fd;
88 }
89 
99 EXPORT_SYMBOL unsigned int mnl_socket_get_portid(const struct mnl_socket *nl)
100 {
101  return nl->addr.nl_pid;
102 }
103 
104 static struct mnl_socket *__mnl_socket_open(int bus, int flags)
105 {
106  struct mnl_socket *nl;
107 
108  nl = calloc(1, sizeof(struct mnl_socket));
109  if (nl == NULL)
110  return NULL;
111 
112  nl->fd = socket(AF_NETLINK, SOCK_RAW | flags, bus);
113  if (nl->fd == -1) {
114  free(nl);
115  return NULL;
116  }
117 
118  return nl;
119 }
120 
128 EXPORT_SYMBOL struct mnl_socket *mnl_socket_open(int bus)
129 {
130  return __mnl_socket_open(bus, 0);
131 }
132 
145 EXPORT_SYMBOL struct mnl_socket *mnl_socket_open2(int bus, int flags)
146 {
147  return __mnl_socket_open(bus, flags);
148 }
149 
161 EXPORT_SYMBOL struct mnl_socket *mnl_socket_fdopen(int fd)
162 {
163  int ret;
164  struct mnl_socket *nl;
165  struct sockaddr_nl addr;
166  socklen_t addr_len = sizeof(struct sockaddr_nl);
167 
168  ret = getsockname(fd, (struct sockaddr *) &addr, &addr_len);
169  if (ret == -1)
170  return NULL;
171 
172  nl = calloc(1, sizeof(struct mnl_socket));
173  if (nl == NULL)
174  return NULL;
175 
176  nl->fd = fd;
177  if (addr.nl_family == AF_NETLINK)
178  nl->addr = addr;
179 
180  return nl;
181 }
182 
193 EXPORT_SYMBOL int mnl_socket_bind(struct mnl_socket *nl, unsigned int groups,
194  pid_t pid)
195 {
196  int ret;
197  socklen_t addr_len;
198 
199  nl->addr.nl_family = AF_NETLINK;
200  nl->addr.nl_groups = groups;
201  nl->addr.nl_pid = pid;
202 
203  ret = bind(nl->fd, (struct sockaddr *) &nl->addr, sizeof (nl->addr));
204  if (ret < 0)
205  return ret;
206 
207  addr_len = sizeof(nl->addr);
208  ret = getsockname(nl->fd, (struct sockaddr *) &nl->addr, &addr_len);
209  if (ret < 0)
210  return ret;
211 
212  if (addr_len != sizeof(nl->addr)) {
213  errno = EINVAL;
214  return -1;
215  }
216  if (nl->addr.nl_family != AF_NETLINK) {
217  errno = EINVAL;
218  return -1;
219  }
220  return 0;
221 }
222 
232 EXPORT_SYMBOL ssize_t mnl_socket_sendto(const struct mnl_socket *nl,
233  const void *buf, size_t len)
234 {
235  static const struct sockaddr_nl snl = {
236  .nl_family = AF_NETLINK
237  };
238  return sendto(nl->fd, buf, len, 0,
239  (struct sockaddr *) &snl, sizeof(snl));
240 }
241 
256 EXPORT_SYMBOL ssize_t mnl_socket_recvfrom(const struct mnl_socket *nl,
257  void *buf, size_t bufsiz)
258 {
259  ssize_t ret;
260  struct sockaddr_nl addr;
261  struct iovec iov = {
262  .iov_base = buf,
263  .iov_len = bufsiz,
264  };
265  struct msghdr msg = {
266  .msg_name = &addr,
267  .msg_namelen = sizeof(struct sockaddr_nl),
268  .msg_iov = &iov,
269  .msg_iovlen = 1,
270  .msg_control = NULL,
271  .msg_controllen = 0,
272  .msg_flags = 0,
273  };
274  ret = recvmsg(nl->fd, &msg, 0);
275  if (ret == -1)
276  return ret;
277 
278  if (msg.msg_flags & MSG_TRUNC) {
279  errno = ENOSPC;
280  return -1;
281  }
282  if (msg.msg_namelen != sizeof(struct sockaddr_nl)) {
283  errno = EINVAL;
284  return -1;
285  }
286  return ret;
287 }
288 
296 EXPORT_SYMBOL int mnl_socket_close(struct mnl_socket *nl)
297 {
298  int ret = close(nl->fd);
299  free(nl);
300  return ret;
301 }
302 
328 EXPORT_SYMBOL int mnl_socket_setsockopt(const struct mnl_socket *nl, int type,
329  void *buf, socklen_t len)
330 {
331  return setsockopt(nl->fd, SOL_NETLINK, type, buf, len);
332 }
333 
343 EXPORT_SYMBOL int mnl_socket_getsockopt(const struct mnl_socket *nl, int type,
344  void *buf, socklen_t *len)
345 {
346  return getsockopt(nl->fd, SOL_NETLINK, type, buf, len);
347 }
348 
struct mnl_socket * mnl_socket_open2(int bus, int flags)
Definition: socket.c:145
struct mnl_socket * mnl_socket_open(int bus)
Definition: socket.c:128
unsigned int mnl_socket_get_portid(const struct mnl_socket *nl)
Definition: socket.c:99
ssize_t mnl_socket_recvfrom(const struct mnl_socket *nl, void *buf, size_t bufsiz)
Definition: socket.c:256
int mnl_socket_bind(struct mnl_socket *nl, unsigned int groups, pid_t pid)
Definition: socket.c:193
int mnl_socket_close(struct mnl_socket *nl)
Definition: socket.c:296
int mnl_socket_getsockopt(const struct mnl_socket *nl, int type, void *buf, socklen_t *len)
Definition: socket.c:343
ssize_t mnl_socket_sendto(const struct mnl_socket *nl, const void *buf, size_t len)
Definition: socket.c:232
int mnl_socket_get_fd(const struct mnl_socket *nl)
Definition: socket.c:85
int mnl_socket_setsockopt(const struct mnl_socket *nl, int type, void *buf, socklen_t len)
Definition: socket.c:328
struct mnl_socket * mnl_socket_fdopen(int fd)
Definition: socket.c:161