00001
00002
00003
00004
00005
00006
00007
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 EXPORT_SYMBOL int mnl_socket_get_fd(const struct mnl_socket *nl)
00086 {
00087 return nl->fd;
00088 }
00089
00099 EXPORT_SYMBOL unsigned int mnl_socket_get_portid(const struct mnl_socket *nl)
00100 {
00101 return nl->addr.nl_pid;
00102 }
00103
00111 EXPORT_SYMBOL struct mnl_socket *mnl_socket_open(int bus)
00112 {
00113 struct mnl_socket *nl;
00114
00115 nl = calloc(sizeof(struct mnl_socket), 1);
00116 if (nl == NULL)
00117 return NULL;
00118
00119 nl->fd = socket(AF_NETLINK, SOCK_RAW, bus);
00120 if (nl->fd == -1) {
00121 free(nl);
00122 return NULL;
00123 }
00124
00125 return nl;
00126 }
00127
00138 EXPORT_SYMBOL int
00139 mnl_socket_bind(struct mnl_socket *nl, unsigned int groups, pid_t pid)
00140 {
00141 int ret;
00142 socklen_t addr_len;
00143
00144 nl->addr.nl_family = AF_NETLINK;
00145 nl->addr.nl_groups = groups;
00146 nl->addr.nl_pid = pid;
00147
00148 ret = bind(nl->fd, (struct sockaddr *) &nl->addr, sizeof (nl->addr));
00149 if (ret < 0)
00150 return ret;
00151
00152 addr_len = sizeof(nl->addr);
00153 ret = getsockname(nl->fd, (struct sockaddr *) &nl->addr, &addr_len);
00154 if (ret < 0)
00155 return ret;
00156
00157 if (addr_len != sizeof(nl->addr)) {
00158 errno = EINVAL;
00159 return -1;
00160 }
00161 if (nl->addr.nl_family != AF_NETLINK) {
00162 errno = EINVAL;
00163 return -1;
00164 }
00165 return 0;
00166 }
00167
00177 EXPORT_SYMBOL ssize_t
00178 mnl_socket_sendto(const struct mnl_socket *nl, const void *buf, size_t len)
00179 {
00180 static const struct sockaddr_nl snl = {
00181 .nl_family = AF_NETLINK
00182 };
00183 return sendto(nl->fd, buf, len, 0,
00184 (struct sockaddr *) &snl, sizeof(snl));
00185 }
00186
00201 EXPORT_SYMBOL ssize_t
00202 mnl_socket_recvfrom(const struct mnl_socket *nl, void *buf, size_t bufsiz)
00203 {
00204 ssize_t ret;
00205 struct sockaddr_nl addr;
00206 struct iovec iov = {
00207 .iov_base = buf,
00208 .iov_len = bufsiz,
00209 };
00210 struct msghdr msg = {
00211 .msg_name = &addr,
00212 .msg_namelen = sizeof(struct sockaddr_nl),
00213 .msg_iov = &iov,
00214 .msg_iovlen = 1,
00215 .msg_control = NULL,
00216 .msg_controllen = 0,
00217 .msg_flags = 0,
00218 };
00219 ret = recvmsg(nl->fd, &msg, 0);
00220 if (ret == -1)
00221 return ret;
00222
00223 if (msg.msg_flags & MSG_TRUNC) {
00224 errno = ENOSPC;
00225 return -1;
00226 }
00227 if (msg.msg_namelen != sizeof(struct sockaddr_nl)) {
00228 errno = EINVAL;
00229 return -1;
00230 }
00231 return ret;
00232 }
00233
00241 EXPORT_SYMBOL int mnl_socket_close(struct mnl_socket *nl)
00242 {
00243 int ret = close(nl->fd);
00244 free(nl);
00245 return ret;
00246 }
00247
00273 EXPORT_SYMBOL int mnl_socket_setsockopt(const struct mnl_socket *nl, int type,
00274 void *buf, socklen_t len)
00275 {
00276 return setsockopt(nl->fd, SOL_NETLINK, type, buf, len);
00277 }
00278
00288 EXPORT_SYMBOL int mnl_socket_getsockopt(const struct mnl_socket *nl, int type,
00289 void *buf, socklen_t *len)
00290 {
00291 return getsockopt(nl->fd, SOL_NETLINK, type, buf, len);
00292 }
00293