blob: fe8c1bc7feabfcf364f1f5ddd05559239a593693 [file] [log] [blame]
Johannes Berg2ef1be62008-04-02 17:40:11 +02001#include <linux/nl80211.h>
2#include <net/if.h>
Johannes Berg45c72122007-09-28 23:47:38 +02003#include <errno.h>
Johannes Berg2ef1be62008-04-02 17:40:11 +02004
Johannes Berg45c72122007-09-28 23:47:38 +02005#include <netlink/genl/genl.h>
6#include <netlink/genl/family.h>
7#include <netlink/genl/ctrl.h>
8#include <netlink/msg.h>
9#include <netlink/attr.h>
Johannes Berg45c72122007-09-28 23:47:38 +020010
11#include "iw.h"
12
13/* return 0 if not found, 1 if ok, -1 on error */
14static int get_if_type(int *argc, char ***argv, enum nl80211_iftype *type)
15{
16 char *tpstr;
17
18 if (*argc < 2)
19 return 0;
20
21 if (strcmp((*argv)[0], "type"))
22 return 0;
23
24 tpstr = (*argv)[1];
25 *argc -= 2;
26 *argv += 2;
27
28 if (strcmp(tpstr, "adhoc") == 0 ||
29 strcmp(tpstr, "ibss") == 0) {
30 *type = NL80211_IFTYPE_ADHOC;
31 return 1;
32 } else if (strcmp(tpstr, "monitor") == 0) {
33 *type = NL80211_IFTYPE_MONITOR;
34 return 1;
Mike Kershaw1cdd9012007-09-29 19:17:20 -040035 } else if (strcmp(tpstr, "ap") == 0 || strcmp(tpstr, "master") == 0) {
Johannes Berg45c72122007-09-28 23:47:38 +020036 *type = NL80211_IFTYPE_AP;
37 return 1;
38 } else if (strcmp(tpstr, "ap_vlan") == 0) {
39 *type = NL80211_IFTYPE_AP_VLAN;
40 return 1;
41 } else if (strcmp(tpstr, "wds") == 0) {
42 *type = NL80211_IFTYPE_WDS;
43 return 1;
44 } else if (strcmp(tpstr, "station") == 0) {
45 *type = NL80211_IFTYPE_STATION;
46 return 1;
Luis Carlos Cobo3d1e8702008-04-01 12:03:41 -070047 } else if (strcmp(tpstr, "mp") == 0 ||
48 strcmp(tpstr, "mesh") == 0) {
49 *type = NL80211_IFTYPE_MESH_POINT;
50 return 1;
Johannes Berg45c72122007-09-28 23:47:38 +020051 }
52
53
54 fprintf(stderr, "invalid interface type %s\n", tpstr);
55 return -1;
56}
57
58static int handle_interface_add(struct nl80211_state *state,
59 char *phy, char *dev, int argc, char **argv)
60{
Andrew Lutomirski2dfd6bf2007-12-20 18:50:07 +010061 char *name;
Luis Carlos Cobo3d1e8702008-04-01 12:03:41 -070062 char *mesh_id = NULL;
Johannes Berg45c72122007-09-28 23:47:38 +020063 enum nl80211_iftype type;
64 int tpset, err;
65 struct nl_msg *msg;
66
67 if (argc < 1) {
68 fprintf(stderr, "not enough arguments\n");
69 return -1;
70 }
71
Andrew Lutomirski2dfd6bf2007-12-20 18:50:07 +010072 name = argv[0];
Johannes Berg45c72122007-09-28 23:47:38 +020073 argc--;
74 argv++;
75
Andrew Lutomirski2dfd6bf2007-12-20 18:50:07 +010076 tpset = get_if_type(&argc, &argv, &type);
77 if (tpset == 0)
78 fprintf(stderr, "you must specify an interface type\n");
79 if (tpset <= 0)
80 return -1;
Johannes Berg45c72122007-09-28 23:47:38 +020081
82 if (argc) {
Luis Carlos Cobo3d1e8702008-04-01 12:03:41 -070083 if (strcmp(argv[0], "mesh_id") != 0) {
84 fprintf(stderr, "option %s not supported\n", argv[0]);
85 return -1;
86 }
87 argc--;
88 argv++;
89
90 if (!argc) {
91 fprintf(stderr, "not enough arguments\n");
92 return -1;
93 }
94 mesh_id = argv[0];
95 argc--;
96 argv++;
97 }
98
99 if (argc) {
Johannes Berg45c72122007-09-28 23:47:38 +0200100 fprintf(stderr, "too many arguments\n");
101 return -1;
102 }
103
Mike Kershaw1cdd9012007-09-29 19:17:20 -0400104 msg = nlmsg_alloc();
105 if (!msg) {
106 fprintf(stderr, "failed to allocate netlink msg\n");
107 return -1;
108 }
Johannes Berg45c72122007-09-28 23:47:38 +0200109
110 genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0,
111 0, NL80211_CMD_NEW_INTERFACE, 0);
112 if (dev)
113 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(dev));
114 if (phy)
115 return -1; /* XXX TODO */
116 NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, name);
117 if (tpset)
118 NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, type);
Luis Carlos Cobo3d1e8702008-04-01 12:03:41 -0700119 if (mesh_id)
120 NLA_PUT(msg, NL80211_ATTR_MESH_ID, strlen(mesh_id), mesh_id);
Johannes Berg45c72122007-09-28 23:47:38 +0200121
122 if ((err = nl_send_auto_complete(state->nl_handle, msg)) < 0 ||
123 (err = nl_wait_for_ack(state->nl_handle)) < 0) {
124 nla_put_failure:
125 fprintf(stderr, "failed to create interface: %d\n", err);
126 nlmsg_free(msg);
127 return -1;
128 }
129
130 nlmsg_free(msg);
131
132 return 0;
133}
134
Johannes Berg3fcfe402007-09-28 23:50:25 +0200135static int handle_interface_del(struct nl80211_state *state,
136 char *phy, char *dev, int argc, char **argv)
137{
138 int err;
139 struct nl_msg *msg;
140
141 if (argc) {
142 fprintf(stderr, "too many arguments\n");
143 return -1;
144 }
145
146 msg = nlmsg_alloc();
147 if (!msg)
148 return -1;
149
150 genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0,
151 0, NL80211_CMD_DEL_INTERFACE, 0);
152 if (!dev) {
153 fprintf(stderr, "need device\n");
154 nlmsg_free(msg);
155 return -1;
156 }
157 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(dev));
158
159 if ((err = nl_send_auto_complete(state->nl_handle, msg)) < 0 ||
160 (err = nl_wait_for_ack(state->nl_handle)) < 0) {
161 nla_put_failure:
162 fprintf(stderr, "failed to remove interface: %d\n", err);
163 nlmsg_free(msg);
164 return -1;
165 }
166
167 nlmsg_free(msg);
168
169 return 0;
170}
171
Johannes Berg45c72122007-09-28 23:47:38 +0200172int handle_interface(struct nl80211_state *state,
173 char *phy, char *dev, int argc, char **argv)
174{
175 char *cmd = argv[0];
176
Andrew Lutomirski2dfd6bf2007-12-20 18:50:07 +0100177 if (argc < 1) {
178 fprintf(stderr, "you must specify an interface command\n");
Johannes Berg45c72122007-09-28 23:47:38 +0200179 return -1;
Andrew Lutomirski2dfd6bf2007-12-20 18:50:07 +0100180 }
Johannes Berg45c72122007-09-28 23:47:38 +0200181
182 argc--;
183 argv++;
184
185 if (strcmp(cmd, "add") == 0)
186 return handle_interface_add(state, phy, dev, argc, argv);
Johannes Berg3fcfe402007-09-28 23:50:25 +0200187 else if (strcmp(cmd, "del") == 0)
188 return handle_interface_del(state, phy, dev, argc, argv);
Johannes Berg45c72122007-09-28 23:47:38 +0200189
190 printf("invalid interface command %s\n", cmd);
191 return -1;
192}