]> git.ipfire.org Git - thirdparty/iw.git/blob - interface.c
efc2d93280a21b55c16899f2c874e1db14d21c9e
[thirdparty/iw.git] / interface.c
1
2 #include <errno.h>
3 #include <netlink/genl/genl.h>
4 #include <netlink/genl/family.h>
5 #include <netlink/genl/ctrl.h>
6 #include <netlink/msg.h>
7 #include <netlink/attr.h>
8 #include <linux/nl80211.h>
9
10 #include <net/if.h>
11
12 #include "iw.h"
13
14 /* return 0 if not found, 1 if ok, -1 on error */
15 static int get_if_type(int *argc, char ***argv, enum nl80211_iftype *type)
16 {
17 char *tpstr;
18
19 if (*argc < 2)
20 return 0;
21
22 if (strcmp((*argv)[0], "type"))
23 return 0;
24
25 tpstr = (*argv)[1];
26 *argc -= 2;
27 *argv += 2;
28
29 if (strcmp(tpstr, "adhoc") == 0 ||
30 strcmp(tpstr, "ibss") == 0) {
31 *type = NL80211_IFTYPE_ADHOC;
32 return 1;
33 } else if (strcmp(tpstr, "monitor") == 0) {
34 *type = NL80211_IFTYPE_MONITOR;
35 return 1;
36 } else if (strcmp(tpstr, "ap") == 0 || strcmp(tpstr, "master") == 0) {
37 *type = NL80211_IFTYPE_AP;
38 return 1;
39 } else if (strcmp(tpstr, "ap_vlan") == 0) {
40 *type = NL80211_IFTYPE_AP_VLAN;
41 return 1;
42 } else if (strcmp(tpstr, "wds") == 0) {
43 *type = NL80211_IFTYPE_WDS;
44 return 1;
45 } else if (strcmp(tpstr, "station") == 0) {
46 *type = NL80211_IFTYPE_STATION;
47 return 1;
48 }
49
50
51 fprintf(stderr, "invalid interface type %s\n", tpstr);
52 return -1;
53 }
54
55 static int handle_interface_add(struct nl80211_state *state,
56 char *phy, char *dev, int argc, char **argv)
57 {
58 char *name;
59 enum nl80211_iftype type;
60 int tpset, err;
61 struct nl_msg *msg;
62
63 if (argc < 1) {
64 fprintf(stderr, "not enough arguments\n");
65 return -1;
66 }
67
68 name = argv[0];
69 argc--;
70 argv++;
71
72 tpset = get_if_type(&argc, &argv, &type);
73 if (tpset == 0)
74 fprintf(stderr, "you must specify an interface type\n");
75 if (tpset <= 0)
76 return -1;
77
78 if (argc) {
79 fprintf(stderr, "too many arguments\n");
80 return -1;
81 }
82
83 msg = nlmsg_alloc();
84 if (!msg) {
85 fprintf(stderr, "failed to allocate netlink msg\n");
86 return -1;
87 }
88
89 genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0,
90 0, NL80211_CMD_NEW_INTERFACE, 0);
91 if (dev)
92 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(dev));
93 if (phy)
94 return -1; /* XXX TODO */
95 NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, name);
96 if (tpset)
97 NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, type);
98
99 if ((err = nl_send_auto_complete(state->nl_handle, msg)) < 0 ||
100 (err = nl_wait_for_ack(state->nl_handle)) < 0) {
101 nla_put_failure:
102 fprintf(stderr, "failed to create interface: %d\n", err);
103 nlmsg_free(msg);
104 return -1;
105 }
106
107 nlmsg_free(msg);
108
109 return 0;
110 }
111
112 static int handle_interface_del(struct nl80211_state *state,
113 char *phy, char *dev, int argc, char **argv)
114 {
115 int err;
116 struct nl_msg *msg;
117
118 if (argc) {
119 fprintf(stderr, "too many arguments\n");
120 return -1;
121 }
122
123 msg = nlmsg_alloc();
124 if (!msg)
125 return -1;
126
127 genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0,
128 0, NL80211_CMD_DEL_INTERFACE, 0);
129 if (!dev) {
130 fprintf(stderr, "need device\n");
131 nlmsg_free(msg);
132 return -1;
133 }
134 NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, if_nametoindex(dev));
135
136 if ((err = nl_send_auto_complete(state->nl_handle, msg)) < 0 ||
137 (err = nl_wait_for_ack(state->nl_handle)) < 0) {
138 nla_put_failure:
139 fprintf(stderr, "failed to remove interface: %d\n", err);
140 nlmsg_free(msg);
141 return -1;
142 }
143
144 nlmsg_free(msg);
145
146 return 0;
147 }
148
149 int handle_interface(struct nl80211_state *state,
150 char *phy, char *dev, int argc, char **argv)
151 {
152 char *cmd = argv[0];
153
154 if (argc < 1) {
155 fprintf(stderr, "you must specify an interface command\n");
156 return -1;
157 }
158
159 argc--;
160 argv++;
161
162 if (strcmp(cmd, "add") == 0)
163 return handle_interface_add(state, phy, dev, argc, argv);
164 else if (strcmp(cmd, "del") == 0)
165 return handle_interface_del(state, phy, dev, argc, argv);
166
167 printf("invalid interface command %s\n", cmd);
168 return -1;
169 }