libmnl
1.0.3
|
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