2 * Netlink helper functions for driver wrappers
3 * Copyright (c) 2002-2009, Jouni Malinen <j@w1.fi>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
9 * Alternatively, this software may be distributed under the terms of BSD
12 * See README and COPYING for more details.
19 #include "priv_netlink.h"
24 struct netlink_config
*cfg
;
29 static void netlink_receive_link(struct netlink_data
*netlink
,
30 void (*cb
)(void *ctx
, struct ifinfomsg
*ifi
,
34 if (cb
== NULL
|| NLMSG_PAYLOAD(h
, 0) < sizeof(struct ifinfomsg
))
36 cb(netlink
->cfg
->ctx
, NLMSG_DATA(h
),
37 NLMSG_DATA(h
) + NLMSG_ALIGN(sizeof(struct ifinfomsg
)),
38 NLMSG_PAYLOAD(h
, sizeof(struct ifinfomsg
)));
42 static void netlink_receive(int sock
, void *eloop_ctx
, void *sock_ctx
)
44 struct netlink_data
*netlink
= eloop_ctx
;
47 struct sockaddr_nl from
;
53 fromlen
= sizeof(from
);
54 left
= recvfrom(sock
, buf
, sizeof(buf
), MSG_DONTWAIT
,
55 (struct sockaddr
*) &from
, &fromlen
);
57 if (errno
!= EINTR
&& errno
!= EAGAIN
)
58 wpa_printf(MSG_INFO
, "netlink: recvfrom failed: %s",
63 h
= (struct nlmsghdr
*) buf
;
64 while (NLMSG_OK(h
, left
)) {
65 switch (h
->nlmsg_type
) {
67 netlink_receive_link(netlink
, netlink
->cfg
->newlink_cb
,
71 netlink_receive_link(netlink
, netlink
->cfg
->dellink_cb
,
76 h
= NLMSG_NEXT(h
, left
);
80 wpa_printf(MSG_DEBUG
, "netlink: %d extra bytes in the end of "
81 "netlink message", left
);
84 if (--max_events
> 0) {
86 * Try to receive all events in one eloop call in order to
87 * limit race condition on cases where AssocInfo event, Assoc
88 * event, and EAPOL frames are received more or less at the
89 * same time. We want to process the event messages first
90 * before starting EAPOL processing.
97 struct netlink_data
* netlink_init(struct netlink_config
*cfg
)
99 struct netlink_data
*netlink
;
100 struct sockaddr_nl local
;
102 netlink
= os_zalloc(sizeof(*netlink
));
108 netlink
->sock
= socket(PF_NETLINK
, SOCK_RAW
, NETLINK_ROUTE
);
109 if (netlink
->sock
< 0) {
110 wpa_printf(MSG_ERROR
, "netlink: Failed to open netlink "
111 "socket: %s", strerror(errno
));
112 netlink_deinit(netlink
);
116 os_memset(&local
, 0, sizeof(local
));
117 local
.nl_family
= AF_NETLINK
;
118 local
.nl_groups
= RTMGRP_LINK
;
119 if (bind(netlink
->sock
, (struct sockaddr
*) &local
, sizeof(local
)) < 0)
121 wpa_printf(MSG_ERROR
, "netlink: Failed to bind netlink "
122 "socket: %s", strerror(errno
));
123 netlink_deinit(netlink
);
127 eloop_register_read_sock(netlink
->sock
, netlink_receive
, netlink
,
134 void netlink_deinit(struct netlink_data
*netlink
)
138 if (netlink
->sock
>= 0) {
139 eloop_unregister_read_sock(netlink
->sock
);
140 close(netlink
->sock
);
142 os_free(netlink
->cfg
);
146 int netlink_send_oper_ifla(struct netlink_data
*netlink
, int ifindex
,
147 int linkmode
, int operstate
)
151 struct ifinfomsg ifinfo
;
158 os_memset(&req
, 0, sizeof(req
));
160 req
.hdr
.nlmsg_len
= NLMSG_LENGTH(sizeof(struct ifinfomsg
));
161 req
.hdr
.nlmsg_type
= RTM_SETLINK
;
162 req
.hdr
.nlmsg_flags
= NLM_F_REQUEST
;
163 req
.hdr
.nlmsg_seq
= ++nl_seq
;
164 req
.hdr
.nlmsg_pid
= 0;
166 req
.ifinfo
.ifi_family
= AF_UNSPEC
;
167 req
.ifinfo
.ifi_type
= 0;
168 req
.ifinfo
.ifi_index
= ifindex
;
169 req
.ifinfo
.ifi_flags
= 0;
170 req
.ifinfo
.ifi_change
= 0;
172 if (linkmode
!= -1) {
173 rta
= aliasing_hide_typecast(
174 ((char *) &req
+ NLMSG_ALIGN(req
.hdr
.nlmsg_len
)),
176 rta
->rta_type
= IFLA_LINKMODE
;
177 rta
->rta_len
= RTA_LENGTH(sizeof(char));
178 *((char *) RTA_DATA(rta
)) = linkmode
;
179 req
.hdr
.nlmsg_len
= NLMSG_ALIGN(req
.hdr
.nlmsg_len
) +
180 RTA_LENGTH(sizeof(char));
182 if (operstate
!= -1) {
183 rta
= aliasing_hide_typecast(
184 ((char *) &req
+ NLMSG_ALIGN(req
.hdr
.nlmsg_len
)),
186 rta
->rta_type
= IFLA_OPERSTATE
;
187 rta
->rta_len
= RTA_LENGTH(sizeof(char));
188 *((char *) RTA_DATA(rta
)) = operstate
;
189 req
.hdr
.nlmsg_len
= NLMSG_ALIGN(req
.hdr
.nlmsg_len
) +
190 RTA_LENGTH(sizeof(char));
193 wpa_printf(MSG_DEBUG
, "netlink: Operstate: linkmode=%d, operstate=%d",
194 linkmode
, operstate
);
196 ret
= send(netlink
->sock
, &req
, req
.hdr
.nlmsg_len
, 0);
198 wpa_printf(MSG_DEBUG
, "netlink: Sending operstate IFLA "
199 "failed: %s (assume operstate is not supported)",
203 return ret
< 0 ? -1 : 0;