1abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt/*
2abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt * Common functions for Wired Ethernet driver interfaces
3abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi>
4abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt * Copyright (c) 2004, Gunter Burchardt <tira@isx.de>
5abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt *
6abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
7abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt * See README for more details.
8abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt */
9abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
10abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#include "includes.h"
11abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
12abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#include "common.h"
13abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#include "eloop.h"
14abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#include "driver.h"
15abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#include "driver_wired_common.h"
16abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
17abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#include <sys/ioctl.h>
18abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#include <net/if.h>
19abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#ifdef __linux__
20abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#include <netpacket/packet.h>
21abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#include <net/if_arp.h>
22abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#include <net/if.h>
23abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#endif /* __linux__ */
24abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
25abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#include <net/if_dl.h>
26abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#include <net/if_media.h>
27abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__) */
28abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#ifdef __sun__
29abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#include <sys/sockio.h>
30abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#endif /* __sun__ */
31abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
32abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
33abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtstatic int driver_wired_get_ifflags(const char *ifname, int *flags)
34abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt{
35abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	struct ifreq ifr;
36abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	int s;
37abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
38abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	s = socket(PF_INET, SOCK_DGRAM, 0);
39abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	if (s < 0) {
40abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		wpa_printf(MSG_ERROR, "socket: %s", strerror(errno));
41abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		return -1;
42abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	}
43abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
44abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	os_memset(&ifr, 0, sizeof(ifr));
45abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
46abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	if (ioctl(s, SIOCGIFFLAGS, (caddr_t) &ifr) < 0) {
47abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		wpa_printf(MSG_ERROR, "ioctl[SIOCGIFFLAGS]: %s",
48abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt			   strerror(errno));
49abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		close(s);
50abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		return -1;
51abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	}
52abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	close(s);
53abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	*flags = ifr.ifr_flags & 0xffff;
54abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	return 0;
55abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt}
56abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
57abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
58abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtstatic int driver_wired_set_ifflags(const char *ifname, int flags)
59abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt{
60abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	struct ifreq ifr;
61abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	int s;
62abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
63abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	s = socket(PF_INET, SOCK_DGRAM, 0);
64abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	if (s < 0) {
65abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		wpa_printf(MSG_ERROR, "socket: %s", strerror(errno));
66abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		return -1;
67abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	}
68abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
69abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	os_memset(&ifr, 0, sizeof(ifr));
70abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
71abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	ifr.ifr_flags = flags & 0xffff;
72abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	if (ioctl(s, SIOCSIFFLAGS, (caddr_t) &ifr) < 0) {
73abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		wpa_printf(MSG_ERROR, "ioctl[SIOCSIFFLAGS]: %s",
74abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt			   strerror(errno));
75abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		close(s);
76abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		return -1;
77abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	}
78abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	close(s);
79abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	return 0;
80abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt}
81abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
82abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
83abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtstatic int driver_wired_multi(const char *ifname, const u8 *addr, int add)
84abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt{
85abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	struct ifreq ifr;
86abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	int s;
87abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
88abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#ifdef __sun__
89abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	return -1;
90abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#endif /* __sun__ */
91abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
92abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	s = socket(PF_INET, SOCK_DGRAM, 0);
93abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	if (s < 0) {
94abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		wpa_printf(MSG_ERROR, "socket: %s", strerror(errno));
95abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		return -1;
96abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	}
97abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
98abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	os_memset(&ifr, 0, sizeof(ifr));
99abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	os_strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
100abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#ifdef __linux__
101abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	ifr.ifr_hwaddr.sa_family = AF_UNSPEC;
102abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	os_memcpy(ifr.ifr_hwaddr.sa_data, addr, ETH_ALEN);
103abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#endif /* __linux__ */
104abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
105abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	{
106abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		struct sockaddr_dl *dlp;
107abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
108abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		dlp = (struct sockaddr_dl *) &ifr.ifr_addr;
109abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		dlp->sdl_len = sizeof(struct sockaddr_dl);
110abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		dlp->sdl_family = AF_LINK;
111abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		dlp->sdl_index = 0;
112abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		dlp->sdl_nlen = 0;
113abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		dlp->sdl_alen = ETH_ALEN;
114abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		dlp->sdl_slen = 0;
115abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		os_memcpy(LLADDR(dlp), addr, ETH_ALEN);
116abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	}
117abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(FreeBSD_kernel__) */
118abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
119abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	{
120abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		struct sockaddr *sap;
121abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
122abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		sap = (struct sockaddr *) &ifr.ifr_addr;
123abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		sap->sa_len = sizeof(struct sockaddr);
124abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		sap->sa_family = AF_UNSPEC;
125abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		os_memcpy(sap->sa_data, addr, ETH_ALEN);
126abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	}
127abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#endif /* defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__) */
128abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
129abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	if (ioctl(s, add ? SIOCADDMULTI : SIOCDELMULTI, (caddr_t) &ifr) < 0) {
130abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		wpa_printf(MSG_ERROR, "ioctl[SIOC{ADD/DEL}MULTI]: %s",
131abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt			   strerror(errno));
132abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		close(s);
133abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		return -1;
134abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	}
135abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	close(s);
136abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	return 0;
137abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt}
138abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
139abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
140abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtint wired_multicast_membership(int sock, int ifindex, const u8 *addr, int add)
141abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt{
142abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#ifdef __linux__
143abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	struct packet_mreq mreq;
144abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
145abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	if (sock < 0)
146abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		return -1;
147abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
148abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	os_memset(&mreq, 0, sizeof(mreq));
149abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	mreq.mr_ifindex = ifindex;
150abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	mreq.mr_type = PACKET_MR_MULTICAST;
151abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	mreq.mr_alen = ETH_ALEN;
152abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	os_memcpy(mreq.mr_address, addr, ETH_ALEN);
153abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
154abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	if (setsockopt(sock, SOL_PACKET,
155abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		       add ? PACKET_ADD_MEMBERSHIP : PACKET_DROP_MEMBERSHIP,
156abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		       &mreq, sizeof(mreq)) < 0) {
157abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		wpa_printf(MSG_ERROR, "setsockopt: %s", strerror(errno));
158abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		return -1;
159abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	}
160abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	return 0;
161abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#else /* __linux__ */
162abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	return -1;
163abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#endif /* __linux__ */
164abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt}
165abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
166abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
167abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtint driver_wired_get_ssid(void *priv, u8 *ssid)
168abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt{
169abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	ssid[0] = 0;
170abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	return 0;
171abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt}
172abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
173abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
174abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtint driver_wired_get_bssid(void *priv, u8 *bssid)
175abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt{
176abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	/* Report PAE group address as the "BSSID" for wired connection. */
177abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	os_memcpy(bssid, pae_group_addr, ETH_ALEN);
178abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	return 0;
179abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt}
180abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
181abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
182abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtint driver_wired_get_capa(void *priv, struct wpa_driver_capa *capa)
183abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt{
184abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	os_memset(capa, 0, sizeof(*capa));
185abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	capa->flags = WPA_DRIVER_FLAGS_WIRED;
186abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	return 0;
187abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt}
188abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
189abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
190abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
191abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtstatic int driver_wired_get_ifstatus(const char *ifname, int *status)
192abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt{
193abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	struct ifmediareq ifmr;
194abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	int s;
195abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
196abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	s = socket(PF_INET, SOCK_DGRAM, 0);
197abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	if (s < 0) {
198abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		wpa_printf(MSG_ERROR, "socket: %s", strerror(errno));
199abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		return -1;
200abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	}
201abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
202abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	os_memset(&ifmr, 0, sizeof(ifmr));
203abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	os_strlcpy(ifmr.ifm_name, ifname, IFNAMSIZ);
204abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	if (ioctl(s, SIOCGIFMEDIA, (caddr_t) &ifmr) < 0) {
205abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		wpa_printf(MSG_ERROR, "ioctl[SIOCGIFMEDIA]: %s",
206abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt			   strerror(errno));
207abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		close(s);
208abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		return -1;
209abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	}
210abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	close(s);
211abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	*status = (ifmr.ifm_status & (IFM_ACTIVE | IFM_AVALID)) ==
212abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		(IFM_ACTIVE | IFM_AVALID);
213abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
214abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	return 0;
215abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt}
216abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(FreeBSD_kernel__) */
217abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
218abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
219abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtint driver_wired_init_common(struct driver_wired_common_data *common,
220abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt			     const char *ifname, void *ctx)
221abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt{
222abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	int flags;
223abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
224abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	os_strlcpy(common->ifname, ifname, sizeof(common->ifname));
225abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	common->ctx = ctx;
226abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
227abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#ifdef __linux__
228abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	common->pf_sock = socket(PF_PACKET, SOCK_DGRAM, 0);
229abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	if (common->pf_sock < 0)
230abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		wpa_printf(MSG_ERROR, "socket(PF_PACKET): %s", strerror(errno));
231abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#else /* __linux__ */
232abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	common->pf_sock = -1;
233abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#endif /* __linux__ */
234abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
235abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	if (driver_wired_get_ifflags(ifname, &flags) == 0 &&
236abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	    !(flags & IFF_UP) &&
237abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	    driver_wired_set_ifflags(ifname, flags | IFF_UP) == 0)
238abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		common->iff_up = 1;
239abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
240abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	if (wired_multicast_membership(common->pf_sock,
241abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt				       if_nametoindex(common->ifname),
242abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt				       pae_group_addr, 1) == 0) {
243abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		wpa_printf(MSG_DEBUG,
244abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt			   "%s: Added multicast membership with packet socket",
245abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt			   __func__);
246abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		common->membership = 1;
247abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	} else if (driver_wired_multi(ifname, pae_group_addr, 1) == 0) {
248abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		wpa_printf(MSG_DEBUG,
249abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt			   "%s: Added multicast membership with SIOCADDMULTI",
250abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt			   __func__);
251abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		common->multi = 1;
252abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	} else if (driver_wired_get_ifflags(ifname, &flags) < 0) {
253abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		wpa_printf(MSG_INFO, "%s: Could not get interface flags",
254abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt			   __func__);
255abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		return -1;
256abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	} else if (flags & IFF_ALLMULTI) {
257abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		wpa_printf(MSG_DEBUG,
258abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt			   "%s: Interface is already configured for multicast",
259abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt			   __func__);
260abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	} else if (driver_wired_set_ifflags(ifname,
261abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt						flags | IFF_ALLMULTI) < 0) {
262abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		wpa_printf(MSG_INFO, "%s: Failed to enable allmulti", __func__);
263abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		return -1;
264abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	} else {
265abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		wpa_printf(MSG_DEBUG, "%s: Enabled allmulti mode", __func__);
266abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		common->iff_allmulti = 1;
267abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	}
268abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
269abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	{
270abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		int status;
271abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
272abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		wpa_printf(MSG_DEBUG, "%s: waiting for link to become active",
273abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt			   __func__);
274abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		while (driver_wired_get_ifstatus(ifname, &status) == 0 &&
275abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		       status == 0)
276abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt			sleep(1);
277abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	}
278abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt#endif /* defined(__FreeBSD__) || defined(__DragonFly__) || defined(FreeBSD_kernel__) */
279abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
280abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	return 0;
281abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt}
282abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
283abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
284abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidtvoid driver_wired_deinit_common(struct driver_wired_common_data *common)
285abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt{
286abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	int flags;
287abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
288abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	if (common->membership &&
289abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	    wired_multicast_membership(common->pf_sock,
290abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt				       if_nametoindex(common->ifname),
291abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt				       pae_group_addr, 0) < 0) {
292abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		wpa_printf(MSG_DEBUG,
293abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt			   "%s: Failed to remove PAE multicast group (PACKET)",
294abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt			   __func__);
295abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	}
296abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
297abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	if (common->multi &&
298abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	    driver_wired_multi(common->ifname, pae_group_addr, 0) < 0) {
299abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		wpa_printf(MSG_DEBUG,
300abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt			   "%s: Failed to remove PAE multicast group (SIOCDELMULTI)",
301abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt			   __func__);
302abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	}
303abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
304abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	if (common->iff_allmulti &&
305abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	    (driver_wired_get_ifflags(common->ifname, &flags) < 0 ||
306abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	     driver_wired_set_ifflags(common->ifname,
307abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt				      flags & ~IFF_ALLMULTI) < 0)) {
308abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		wpa_printf(MSG_DEBUG, "%s: Failed to disable allmulti mode",
309abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt			   __func__);
310abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	}
311abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
312abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	if (common->iff_up &&
313abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	    driver_wired_get_ifflags(common->ifname, &flags) == 0 &&
314abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	    (flags & IFF_UP) &&
315abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	    driver_wired_set_ifflags(common->ifname, flags & ~IFF_UP) < 0) {
316abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		wpa_printf(MSG_DEBUG, "%s: Failed to set the interface down",
317abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt			   __func__);
318abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	}
319abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt
320abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt	if (common->pf_sock != -1)
321abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt		close(common->pf_sock);
322abb90a3fc1917e628167827cb14e742000605332Dmitry Shmidt}
323