libmnl  1.0.3
socket.c
00001 /*
00002  * (C) 2008-2010 by Pablo Neira Ayuso <pablo@netfilter.org>
00003  *
00004  * This program is free software; you can redistribute it and/or modify
00005  * it under the terms of the GNU Lesser General Public License as published
00006  * by the Free Software Foundation; either version 2.1 of the License, or
00007  * (at your option) any later version.
00008  */
00009 
00010 #include <libmnl/libmnl.h>
00011 #include <sys/types.h>
00012 #include <sys/socket.h>
00013 #include <stdlib.h>
00014 #include <unistd.h>
00015 #include <time.h>
00016 #include <errno.h>
00017 #include "internal.h"
00018 
00069 struct mnl_socket {
00070         int                     fd;
00071         struct sockaddr_nl      addr;
00072 };
00073 
00085 int mnl_socket_get_fd(const struct mnl_socket *nl)
00086 {
00087         return nl->fd;
00088 }
00089 EXPORT_SYMBOL(mnl_socket_get_fd);
00090 
00100 unsigned int mnl_socket_get_portid(const struct mnl_socket *nl)
00101 {
00102         return nl->addr.nl_pid;
00103 }
00104 EXPORT_SYMBOL(mnl_socket_get_portid);
00105 
00113 struct mnl_socket *mnl_socket_open(int bus)
00114 {
00115         struct mnl_socket *nl;
00116 
00117         nl = calloc(sizeof(struct mnl_socket), 1);
00118         if (nl == NULL)
00119                 return NULL;
00120 
00121         nl->fd = socket(AF_NETLINK, SOCK_RAW, bus);
00122         if (nl->fd == -1) {
00123                 free(nl);
00124                 return NULL;
00125         }
00126 
00127         return nl;
00128 }
00129 EXPORT_SYMBOL(mnl_socket_open);
00130 
00141 int mnl_socket_bind(struct mnl_socket *nl, unsigned int groups, pid_t pid)
00142 {
00143         int ret;
00144         socklen_t addr_len;
00145 
00146         nl->addr.nl_family = AF_NETLINK;
00147         nl->addr.nl_groups = groups;
00148         nl->addr.nl_pid = pid;
00149 
00150         ret = bind(nl->fd, (struct sockaddr *) &nl->addr, sizeof (nl->addr));
00151         if (ret < 0)
00152                 return ret;
00153 
00154         addr_len = sizeof(nl->addr);
00155         ret = getsockname(nl->fd, (struct sockaddr *) &nl->addr, &addr_len);
00156         if (ret < 0)    
00157                 return ret;
00158 
00159         if (addr_len != sizeof(nl->addr)) {
00160                 errno = EINVAL;
00161                 return -1;
00162         }
00163         if (nl->addr.nl_family != AF_NETLINK) {
00164                 errno = EINVAL;
00165                 return -1;
00166         }
00167         return 0;
00168 }
00169 EXPORT_SYMBOL(mnl_socket_bind);
00170 
00180 ssize_t
00181 mnl_socket_sendto(const struct mnl_socket *nl, const void *buf, size_t len)
00182 {
00183         static const struct sockaddr_nl snl = {
00184                 .nl_family = AF_NETLINK
00185         };
00186         return sendto(nl->fd, buf, len, 0, 
00187                       (struct sockaddr *) &snl, sizeof(snl));
00188 }
00189 EXPORT_SYMBOL(mnl_socket_sendto);
00190 
00205 ssize_t
00206 mnl_socket_recvfrom(const struct mnl_socket *nl, void *buf, size_t bufsiz)
00207 {
00208         ssize_t ret;
00209         struct sockaddr_nl addr;
00210         struct iovec iov = {
00211                 .iov_base       = buf,
00212                 .iov_len        = bufsiz,
00213         };
00214         struct msghdr msg = {
00215                 .msg_name       = &addr,
00216                 .msg_namelen    = sizeof(struct sockaddr_nl),
00217                 .msg_iov        = &iov,
00218                 .msg_iovlen     = 1,
00219                 .msg_control    = NULL,
00220                 .msg_controllen = 0,
00221                 .msg_flags      = 0,
00222         };
00223         ret = recvmsg(nl->fd, &msg, 0);
00224         if (ret == -1)
00225                 return ret;
00226 
00227         if (msg.msg_flags & MSG_TRUNC) {
00228                 errno = ENOSPC;
00229                 return -1;
00230         }
00231         if (msg.msg_namelen != sizeof(struct sockaddr_nl)) {
00232                 errno = EINVAL;
00233                 return -1;
00234         }
00235         return ret;
00236 }
00237 EXPORT_SYMBOL(mnl_socket_recvfrom);
00238 
00246 int mnl_socket_close(struct mnl_socket *nl)
00247 {
00248         int ret = close(nl->fd);
00249         free(nl);
00250         return ret;
00251 }
00252 EXPORT_SYMBOL(mnl_socket_close);
00253 
00279 int mnl_socket_setsockopt(const struct mnl_socket *nl, int type,
00280                           void *buf, socklen_t len)
00281 {
00282         return setsockopt(nl->fd, SOL_NETLINK, type, buf, len);
00283 }
00284 EXPORT_SYMBOL(mnl_socket_setsockopt);
00285 
00295 int mnl_socket_getsockopt(const struct mnl_socket *nl, int type,
00296                           void *buf, socklen_t *len)
00297 {
00298         return getsockopt(nl->fd, SOL_NETLINK, type, buf, len);
00299 }
00300 EXPORT_SYMBOL(mnl_socket_getsockopt);
00301