Browse Source

nl80211 hostapd driver: clean up netlink code

Put it into a single place instead of having it all over.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Johannes Berg 16 years ago
parent
commit
cafe38cae0
1 changed files with 139 additions and 282 deletions
  1. 139 282
      hostapd/driver_nl80211.c

+ 139 - 282
hostapd/driver_nl80211.c

@@ -135,15 +135,60 @@ static int have_ifidx(struct i802_driver_data *drv, int ifidx)
 }
 
 
-/* helper for netlink get routines */
-static int ack_wait_handler(struct nl_msg *msg, void *arg)
+/* nl80211 code */
+static int ack_handler(struct nl_msg *msg, void *arg)
 {
-	int *finished = arg;
-
-	*finished = 1;
+	int *err = arg;
+	*err = 0;
 	return NL_STOP;
 }
 
+static int finish_handler(struct nl_msg *msg, void *arg)
+{
+	return NL_SKIP;
+}
+
+static int error_handler(struct sockaddr_nl *nla, struct nlmsgerr *err,
+			 void *arg)
+{
+	int *ret = arg;
+	*ret = err->error;
+	return NL_SKIP;
+}
+
+static int send_and_recv_msgs(struct i802_driver_data *drv,
+			      struct nl_msg *msg,
+			      int (*valid_handler)(struct nl_msg *, void *),
+			      void *valid_data)
+{
+	struct nl_cb *cb;
+	int err = -ENOMEM;
+
+	cb = nl_cb_clone(drv->nl_cb);
+	if (!cb)
+		goto out;
+
+	err = nl_send_auto_complete(drv->nl_handle, msg);
+	if (err < 0)
+		goto out;
+
+	err = 1;
+
+	nl_cb_err(cb, NL_CB_CUSTOM, error_handler, &err);
+	nl_cb_set(cb, NL_CB_FINISH, NL_CB_CUSTOM, finish_handler, NULL);
+	nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_handler, &err);
+
+	if (valid_handler)
+		nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM,
+			  valid_handler, valid_data);
+
+	while (err > 0)
+		nl_recvmsgs(drv->nl_handle, cb);
+ out:
+	nl_cb_put(cb);
+	nlmsg_free(msg);
+	return err;
+}
 
 static int hostapd_set_iface_flags(struct i802_driver_data *drv,
 				   const char *ifname, int dev_up)
@@ -182,12 +227,11 @@ static int nl_set_encr(int ifindex, struct i802_driver_data *drv,
 		       size_t key_len, int txkey)
 {
 	struct nl_msg *msg;
-	int ret = -1;
-	int err = 0;
+	int ret;
 
 	msg = nlmsg_alloc();
 	if (!msg)
-		goto out;
+		return -ENOMEM;
 
 	if (strcmp(alg, "none") == 0) {
 		genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
@@ -212,7 +256,8 @@ static int nl_set_encr(int ifindex, struct i802_driver_data *drv,
 		else {
 			wpa_printf(MSG_ERROR, "%s: Unsupported encryption "
 				   "algorithm '%s'", __func__, alg);
-			goto out;
+			nlmsg_free(msg);
+			return -1;
 		}
 	}
 
@@ -221,28 +266,20 @@ static int nl_set_encr(int ifindex, struct i802_driver_data *drv,
 	NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, idx);
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
 
-	if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
-	    (err = nl_wait_for_ack(drv->nl_handle)) < 0) {
-		if (err != -ENOENT) {
-			ret = 0;
-			goto out;
-		}
-	}
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+	if (ret == -ENOENT)
+		ret = 0;
 
 	/*
-	 * If we need to set the default TX key we do that below,
-	 * otherwise we're done here.
+	 * If we failed or don't need to set the default TX key (below),
+	 * we're done here.
 	 */
-	if (!txkey || addr) {
-		ret = 0;
-		goto out;
-	}
-
-	nlmsg_free(msg);
+	if (ret || !txkey || addr)
+		return ret;
 
 	msg = nlmsg_alloc();
 	if (!msg)
-		goto out;
+		return -ENOMEM;
 
 	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
 		    0, NL80211_CMD_SET_KEY, 0);
@@ -257,20 +294,12 @@ static int nl_set_encr(int ifindex, struct i802_driver_data *drv,
 	NLA_PUT_FLAG(msg, NL80211_ATTR_KEY_DEFAULT);
 #endif /* NL80211_MFP_PENDING */
 
-	if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
-	    (err = nl_wait_for_ack(drv->nl_handle)) < 0) {
-		if (err != -ENOENT) {
-			ret = 0;
-			goto out;
-		}
-	}
-
-	ret = 0;
-
- out:
- nla_put_failure:
-	nlmsg_free(msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+	if (ret == -ENOENT)
+		ret = 0;
 	return ret;
+ nla_put_failure:
+	return -ENOBUFS;
 }
 
 
@@ -329,14 +358,10 @@ static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr,
 {
 	struct i802_driver_data *drv = priv;
 	struct nl_msg *msg;
-	struct nl_cb *cb = NULL;
-	int ret = -1;
-	int err = 0;
-	int finished = 0;
 
 	msg = nlmsg_alloc();
 	if (!msg)
-		goto out;
+		return -ENOMEM;
 
 	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
 		    0, NL80211_CMD_GET_KEY, 0);
@@ -346,33 +371,11 @@ static int i802_get_seqnum(const char *iface, void *priv, const u8 *addr,
 	NLA_PUT_U8(msg, NL80211_ATTR_KEY_IDX, idx);
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(iface));
 
-	cb = nl_cb_clone(drv->nl_cb);
-	if (!cb)
-		goto out;
-
 	memset(seq, 0, 6);
 
-	if (nl_send_auto_complete(drv->nl_handle, msg) < 0)
-		goto out;
-
-	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, get_key_handler, seq);
-	nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_wait_handler, &finished);
-
-	err = nl_recvmsgs(drv->nl_handle, cb);
-
-	if (!finished)
-		err = nl_wait_for_ack(drv->nl_handle);
-
-	if (err < 0)
-		goto out;
-
-	ret = 0;
-
- out:
-	nl_cb_put(cb);
+	return send_and_recv_msgs(drv, msg, get_key_handler, seq);
  nla_put_failure:
-	nlmsg_free(msg);
-	return ret;
+	return -ENOBUFS;
 }
 
 
@@ -602,11 +605,10 @@ static int i802_flush(void *priv)
 {
 	struct i802_driver_data *drv = priv;
 	struct nl_msg *msg;
-	int ret = -1;
 
 	msg = nlmsg_alloc();
 	if (!msg)
-		goto out;
+		return -1;
 
 	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
 		    0, NL80211_CMD_DEL_STATION, 0);
@@ -617,18 +619,9 @@ static int i802_flush(void *priv)
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
 		    if_nametoindex(drv->iface));
 
-	ret = 0;
-
-	if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
-	    nl_wait_for_ack(drv->nl_handle) < 0) {
-		ret = -1;
-	}
-
+	return send_and_recv_msgs(drv, msg, NULL, NULL);
  nla_put_failure:
-	nlmsg_free(msg);
-
- out:
-	return ret;
+	return -ENOBUFS;
 }
 
 
@@ -680,14 +673,10 @@ static int i802_read_sta_data(void *priv, struct hostap_sta_driver_data *data,
 {
 	struct i802_driver_data *drv = priv;
 	struct nl_msg *msg;
-	struct nl_cb *cb = NULL;
-	int ret = -1;
-	int err = 0;
-	int finished = 0;
 
 	msg = nlmsg_alloc();
 	if (!msg)
-		goto out;
+		return -ENOMEM;
 
 	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
 		    0, NL80211_CMD_GET_STATION, 0);
@@ -695,32 +684,9 @@ static int i802_read_sta_data(void *priv, struct hostap_sta_driver_data *data,
 	NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface));
 
-	cb = nl_cb_clone(drv->nl_cb);
-	if (!cb)
-		goto out;
-
-	if (nl_send_auto_complete(drv->nl_handle, msg) < 0)
-		goto out;
-
-	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, get_sta_handler, data);
-	nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_wait_handler, &finished);
-
-	err = nl_recvmsgs(drv->nl_handle, cb);
-
-	if (!finished)
-		err = nl_wait_for_ack(drv->nl_handle);
-
-	if (err < 0)
-		goto out;
-
-	ret = 0;
-
- out:
-	nl_cb_put(cb);
+	return send_and_recv_msgs(drv, msg, get_sta_handler, data);
  nla_put_failure:
-	nlmsg_free(msg);
-	return ret;
-
+	return -ENOBUFS;
 }
 
 
@@ -797,11 +763,11 @@ static int i802_sta_add2(const char *ifname, void *priv,
 {
 	struct i802_driver_data *drv = priv;
 	struct nl_msg *msg;
-	int ret = -1;
+	int ret = -ENOBUFS;
 
 	msg = nlmsg_alloc();
 	if (!msg)
-		goto out;
+		return -ENOMEM;
 
 	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
 		    0, NL80211_CMD_NEW_STATION, 0);
@@ -825,19 +791,10 @@ static int i802_sta_add2(const char *ifname, void *priv,
 #endif /* NL80211_ATTR_HT_CAPABILITY */
 #endif /* CONFIG_IEEE80211N */
 
-	ret = nl_send_auto_complete(drv->nl_handle, msg);
-	if (ret < 0)
-		goto nla_put_failure;
-
-	ret = nl_wait_for_ack(drv->nl_handle);
-	/* ignore EEXIST, this happens if a STA associates while associated */
-	if (ret == -EEXIST || ret >= 0)
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+	if (ret == -EEXIST)
 		ret = 0;
-
  nla_put_failure:
-	nlmsg_free(msg);
-
- out:
 	return ret;
 }
 
@@ -846,11 +803,11 @@ static int i802_sta_remove(void *priv, const u8 *addr)
 {
 	struct i802_driver_data *drv = priv;
 	struct nl_msg *msg;
-	int ret = -1;
+	int ret;
 
 	msg = nlmsg_alloc();
 	if (!msg)
-		goto out;
+		return -ENOMEM;
 
 	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
 		    0, NL80211_CMD_DEL_STATION, 0);
@@ -859,18 +816,12 @@ static int i802_sta_remove(void *priv, const u8 *addr)
 		    if_nametoindex(drv->iface));
 	NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
 
-	ret = 0;
-
-	if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
-	    nl_wait_for_ack(drv->nl_handle) < 0) {
-		ret = -1;
-	}
-
- nla_put_failure:
-	nlmsg_free(msg);
-
- out:
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+	if (ret == -ENOENT)
+		return 0;
 	return ret;
+ nla_put_failure:
+	return -ENOBUFS;
 }
 
 
@@ -879,15 +830,16 @@ static int i802_sta_set_flags(void *priv, const u8 *addr,
 {
 	struct i802_driver_data *drv = priv;
 	struct nl_msg *msg, *flags = NULL;
-	int ret = -1;
 
 	msg = nlmsg_alloc();
 	if (!msg)
-		goto out;
+		return -ENOMEM;
 
 	flags = nlmsg_alloc();
-	if (!flags)
-		goto free_msg;
+	if (!flags) {
+		nlmsg_free(msg);
+		return -ENOMEM;
+	}
 
 	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
 		    0, NL80211_CMD_SET_STATION, 0);
@@ -913,21 +865,12 @@ static int i802_sta_set_flags(void *priv, const u8 *addr,
 	if (nla_put_nested(msg, NL80211_ATTR_STA_FLAGS, flags))
 		goto nla_put_failure;
 
-	ret = 0;
-
-	if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
-	    nl_wait_for_ack(drv->nl_handle) < 0) {
-		ret = -1;
-	}
-
- nla_put_failure:
 	nlmsg_free(flags);
 
- free_msg:
-	nlmsg_free(msg);
-
- out:
-	return ret;
+	return send_and_recv_msgs(drv, msg, NULL, NULL);
+ nla_put_failure:
+ 	nlmsg_free(flags);
+	return -ENOBUFS;
 }
 
 
@@ -966,11 +909,11 @@ static void nl80211_remove_iface(struct i802_driver_data *drv, int ifidx)
 	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
 		    0, NL80211_CMD_DEL_INTERFACE, 0);
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifidx);
-	if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
-	    nl_wait_for_ack(drv->nl_handle) < 0)
-	nla_put_failure:
-		printf("Failed to remove interface.\n");
-	nlmsg_free(msg);
+
+	if (send_and_recv_msgs(drv, msg, NULL, NULL) == 0)
+		return;
+ nla_put_failure:
+	printf("Failed to remove interface.\n");
 }
 
 
@@ -983,6 +926,7 @@ static int nl80211_create_iface(struct i802_driver_data *drv,
 	int ifidx;
 	struct ifreq ifreq;
 	struct iwreq iwr;
+	int ret = -ENOBUFS;
 
 	msg = nlmsg_alloc();
 	if (!msg)
@@ -1012,16 +956,13 @@ static int nl80211_create_iface(struct i802_driver_data *drv,
 			goto nla_put_failure;
 	}
 
-	if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
-	    nl_wait_for_ack(drv->nl_handle) < 0) {
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+	if (ret) {
  nla_put_failure:
 		printf("Failed to create interface %s.\n", ifname);
-		nlmsg_free(msg);
-		return -1;
+		return ret;
 	}
 
-	nlmsg_free(msg);
-
 	ifidx = if_nametoindex(ifname);
 
 	if (ifidx <= 0)
@@ -1096,11 +1037,11 @@ static int i802_set_beacon(const char *iface, void *priv,
 	struct i802_driver_data *drv = priv;
 	struct nl_msg *msg;
 	u8 cmd = NL80211_CMD_NEW_BEACON;
-	int ret = -1;
+	int ret;
 
 	msg = nlmsg_alloc();
 	if (!msg)
-		goto out;
+		return -ENOMEM;
 
 	if (drv->beacon_set)
 		cmd = NL80211_CMD_SET_BEACON;
@@ -1116,44 +1057,30 @@ static int i802_set_beacon(const char *iface, void *priv,
 		drv->dtim_period = 2;
 	NLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, drv->dtim_period);
 
-	if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
-	    nl_wait_for_ack(drv->nl_handle) < 0)
-		goto out;
-
-	ret = 0;
-
-	drv->beacon_set = 1;
-
- out:
- nla_put_failure:
-	nlmsg_free(msg);
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+	if (!ret)
+		drv->beacon_set = 1;
 	return ret;
+ nla_put_failure:
+	return -ENOBUFS;
 }
 
 
 static int i802_del_beacon(struct i802_driver_data *drv)
 {
 	struct nl_msg *msg;
-	int ret = -1;
 
 	msg = nlmsg_alloc();
 	if (!msg)
-		goto out;
+		return -ENOMEM;
 
 	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
 		    0, NL80211_CMD_DEL_BEACON, 0);
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface));
 
-	if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
-	    nl_wait_for_ack(drv->nl_handle) < 0)
-		goto out;
-
-	ret = 0;
-
- out:
+	return send_and_recv_msgs(drv, msg, NULL, NULL);
  nla_put_failure:
-	nlmsg_free(msg);
-	return ret;
+	return -ENOBUFS;
 }
 
 
@@ -1197,7 +1124,6 @@ static int i802_set_beacon_int(void *priv, int value)
 {
 	struct i802_driver_data *drv = priv;
 	struct nl_msg *msg;
-	int ret = -1;
 
 	drv->beacon_int = value;
 
@@ -1206,7 +1132,7 @@ static int i802_set_beacon_int(void *priv, int value)
 
 	msg = nlmsg_alloc();
 	if (!msg)
-		goto out;
+		return -ENOMEM;
 
 	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
 		    0, NL80211_CMD_SET_BEACON, 0);
@@ -1214,16 +1140,9 @@ static int i802_set_beacon_int(void *priv, int value)
 
 	NLA_PUT_U32(msg, NL80211_ATTR_BEACON_INTERVAL, value);
 
-	if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
-	    nl_wait_for_ack(drv->nl_handle) < 0)
-		goto out;
-
-	ret = 0;
-
- out:
+	return send_and_recv_msgs(drv, msg, NULL, NULL);
  nla_put_failure:
-	nlmsg_free(msg);
-	return ret;
+	return -ENOBUFS;
 }
 
 
@@ -1231,11 +1150,10 @@ static int i802_set_dtim_period(const char *iface, void *priv, int value)
 {
 	struct i802_driver_data *drv = priv;
 	struct nl_msg *msg;
-	int ret = -1;
 
 	msg = nlmsg_alloc();
 	if (!msg)
-		goto out;
+		return -ENOMEM;
 
 	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
 		    0, NL80211_CMD_SET_BEACON, 0);
@@ -1244,16 +1162,9 @@ static int i802_set_dtim_period(const char *iface, void *priv, int value)
 	drv->dtim_period = value;
 	NLA_PUT_U32(msg, NL80211_ATTR_DTIM_PERIOD, drv->dtim_period);
 
-	if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
-	    nl_wait_for_ack(drv->nl_handle) < 0)
-		goto out;
-
-	ret = 0;
-
- out:
+	return send_and_recv_msgs(drv, msg, NULL, NULL);
  nla_put_failure:
-	nlmsg_free(msg);
-	return ret;
+	return -ENOBUFS;
 }
 
 
@@ -1262,11 +1173,10 @@ static int i802_set_bss(void *priv, int cts, int preamble, int slot)
 #ifdef NL80211_CMD_SET_BSS
 	struct i802_driver_data *drv = priv;
 	struct nl_msg *msg;
-	int ret = -1;
 
 	msg = nlmsg_alloc();
 	if (!msg)
-		goto out;
+		return -ENOMEM;
 
 	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0, 0,
 		    NL80211_CMD_SET_BSS, 0);
@@ -1278,21 +1188,12 @@ static int i802_set_bss(void *priv, int cts, int preamble, int slot)
 	if (slot >= 0)
 		NLA_PUT_U8(msg, NL80211_ATTR_BSS_SHORT_SLOT_TIME, slot);
 
-	ret = 0;
-
 	/* TODO: multi-BSS support */
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface));
 
-	if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
-	    nl_wait_for_ack(drv->nl_handle) < 0) {
-		ret = -1;
-	}
-
-nla_put_failure:
-	nlmsg_free(msg);
-
-out:
-	return ret;
+	return send_and_recv_msgs(drv, msg, NULL, NULL);
+ nla_put_failure:
+	return -ENOBUFS;
 #else /* NL80211_CMD_SET_BSS */
 	return -1;
 #endif /* NL80211_CMD_SET_BSS */
@@ -1358,7 +1259,6 @@ static int i802_if_remove(void *priv, enum hostapd_driver_if_type type,
 struct phy_info_arg {
 	u16 *num_modes;
 	struct hostapd_hw_modes *modes;
-	int error;
 };
 
 static int phy_info_handler(struct nl_msg *msg, void *arg)
@@ -1497,8 +1397,6 @@ static int phy_info_handler(struct nl_msg *msg, void *arg)
 		}
 	}
 
-	phy_info->error = 0;
-
 	return NL_SKIP;
 }
 
@@ -1508,13 +1406,9 @@ static struct hostapd_hw_modes *i802_get_hw_feature_data(void *priv,
 {
 	struct i802_driver_data *drv = priv;
 	struct nl_msg *msg;
-	int err = -1;
-	struct nl_cb *cb = NULL;
-	int finished = 0;
 	struct phy_info_arg result = {
 		.num_modes = num_modes,
 		.modes = NULL,
-		.error = 1,
 	};
 
 	*num_modes = 0;
@@ -1529,33 +1423,10 @@ static struct hostapd_hw_modes *i802_get_hw_feature_data(void *priv,
 
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(drv->iface));
 
-	cb = nl_cb_clone(drv->nl_cb);
-	if (!cb)
-		goto out;
-
-	if (nl_send_auto_complete(drv->nl_handle, msg) < 0)
-		goto out;
-
-	nl_cb_set(cb, NL_CB_VALID, NL_CB_CUSTOM, phy_info_handler, &result);
-	nl_cb_set(cb, NL_CB_ACK, NL_CB_CUSTOM, ack_wait_handler, &finished);
-
-	err = nl_recvmsgs(drv->nl_handle, cb);
-
-	if (!finished)
-		err = nl_wait_for_ack(drv->nl_handle);
-
-	if (err < 0 || result.error) {
-		hostapd_free_hw_features(result.modes, *num_modes);
-		result.modes = NULL;
-	}
-
- out:
-	nl_cb_put(cb);
+	if (send_and_recv_msgs(drv, msg, phy_info_handler, &result) == 0)
+		return result.modes;
  nla_put_failure:
-	if (err)
-		fprintf(stderr, "failed to get information: %d\n", err);
-	nlmsg_free(msg);
-	return result.modes;
+	return NULL;
 }
 
 
@@ -1564,11 +1435,10 @@ static int i802_set_sta_vlan(void *priv, const u8 *addr,
 {
 	struct i802_driver_data *drv = priv;
 	struct nl_msg *msg;
-	int ret = -1;
 
 	msg = nlmsg_alloc();
 	if (!msg)
-		goto out;
+		return -ENOMEM;
 
 	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
 		    0, NL80211_CMD_SET_STATION, 0);
@@ -1579,18 +1449,9 @@ static int i802_set_sta_vlan(void *priv, const u8 *addr,
 	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX,
 		    if_nametoindex(ifname));
 
-	ret = 0;
-
-	if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
-	    (errno = nl_wait_for_ack(drv->nl_handle) < 0)) {
-		ret = -1;
-	}
-
+	return send_and_recv_msgs(drv, msg, NULL, NULL);
  nla_put_failure:
-	nlmsg_free(msg);
-
- out:
-	return ret;
+	return -ENOBUFS;
 }
 
 
@@ -1931,10 +1792,11 @@ static int nl80211_set_master_mode(struct i802_driver_data *drv,
 				   const char *ifname)
 {
 	struct nl_msg *msg;
+	int ret = -ENOBUFS;
 
 	msg = nlmsg_alloc();
 	if (!msg)
-		return -1;
+		return -ENOMEM;
 
 	genlmsg_put(msg, 0, 0, genl_family_get_id(drv->nl80211), 0,
 		    0, NL80211_CMD_SET_INTERFACE, 0);
@@ -1942,18 +1804,13 @@ static int nl80211_set_master_mode(struct i802_driver_data *drv,
 		    if_nametoindex(ifname));
 	NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_AP);
 
-	if (nl_send_auto_complete(drv->nl_handle, msg) < 0 ||
-	    nl_wait_for_ack(drv->nl_handle) < 0) {
+	ret = send_and_recv_msgs(drv, msg, NULL, NULL);
+	if (!ret)
+		return 0;
  nla_put_failure:
-		wpa_printf(MSG_ERROR, "Failed to set interface %s to master "
-			   "mode.", ifname);
-		nlmsg_free(msg);
-		return -1;
-	}
-
-	nlmsg_free(msg);
-
-	return 0;
+	wpa_printf(MSG_ERROR, "Failed to set interface %s to master "
+		   "mode.", ifname);
+	return ret;
 }