uqmi: Add IP family selection command-line switch
[project/uqmi.git] / commands-wds.c
1 /*
2  * uqmi -- tiny QMI support implementation
3  *
4  * Copyright (C) 2014-2015 Felix Fietkau <nbd@openwrt.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  * Boston, MA 02110-1301 USA.
20  */
21
22 #include <stdlib.h>
23
24 #include "qmi-message.h"
25
26 static struct qmi_wds_start_network_request wds_sn_req = {
27         QMI_INIT(authentication_preference,
28                  QMI_WDS_AUTHENTICATION_PAP | QMI_WDS_AUTHENTICATION_CHAP),
29 };
30 static struct qmi_wds_stop_network_request wds_stn_req;
31
32 #define cmd_wds_set_auth_cb no_cb
33 static enum qmi_cmd_result
34 cmd_wds_set_auth_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
35 {
36         static const struct {
37                 const char *name;
38                 QmiWdsAuthentication auth;
39         } modes[] = {
40                 { "pap", QMI_WDS_AUTHENTICATION_PAP },
41                 { "chap", QMI_WDS_AUTHENTICATION_CHAP },
42                 { "both", QMI_WDS_AUTHENTICATION_PAP | QMI_WDS_AUTHENTICATION_CHAP },
43                 { "none", QMI_WDS_AUTHENTICATION_NONE },
44         };
45         int i;
46
47         for (i = 0; i < ARRAY_SIZE(modes); i++) {
48                 if (strcasecmp(modes[i].name, arg) != 0)
49                         continue;
50
51                 qmi_set(&wds_sn_req, authentication_preference, modes[i].auth);
52                 return QMI_CMD_DONE;
53         }
54
55         uqmi_add_error("Invalid auth mode (valid: pap, chap, both, none)");
56         return QMI_CMD_EXIT;
57 }
58
59 #define cmd_wds_set_username_cb no_cb
60 static enum qmi_cmd_result
61 cmd_wds_set_username_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
62 {
63         qmi_set_ptr(&wds_sn_req, username, arg);
64         return QMI_CMD_DONE;
65 }
66
67 #define cmd_wds_set_password_cb no_cb
68 static enum qmi_cmd_result
69 cmd_wds_set_password_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
70 {
71         qmi_set_ptr(&wds_sn_req, password, arg);
72         return QMI_CMD_DONE;
73 }
74
75 #define cmd_wds_set_autoconnect_cb no_cb
76 static enum qmi_cmd_result
77 cmd_wds_set_autoconnect_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
78 {
79         qmi_set(&wds_sn_req, enable_autoconnect, true);
80         qmi_set(&wds_stn_req, disable_autoconnect, true);
81         return QMI_CMD_DONE;
82 }
83
84 static void
85 cmd_wds_start_network_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg)
86 {
87         struct qmi_wds_start_network_response res;
88
89         qmi_parse_wds_start_network_response(msg, &res);
90         if (res.set.packet_data_handle)
91                 blobmsg_add_u32(&status, NULL, res.data.packet_data_handle);
92 }
93
94 static enum qmi_cmd_result
95 cmd_wds_start_network_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
96 {
97         qmi_set_ptr(&wds_sn_req, apn, arg);
98         qmi_set_wds_start_network_request(msg, &wds_sn_req);
99         return QMI_CMD_REQUEST;
100 }
101
102 #define cmd_wds_stop_network_cb no_cb
103 static enum qmi_cmd_result
104 cmd_wds_stop_network_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
105 {
106         uint32_t pdh = strtoul(arg, NULL, 0);
107
108         qmi_set(&wds_stn_req, packet_data_handle, pdh);
109         qmi_set_wds_stop_network_request(msg, &wds_stn_req);
110         return QMI_CMD_REQUEST;
111 }
112
113 static void
114 cmd_wds_get_packet_service_status_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg)
115 {
116         struct qmi_wds_get_packet_service_status_response res;
117         const char *data_status[] = {
118                 [QMI_WDS_CONNECTION_STATUS_UNKNOWN] = "unknown",
119                 [QMI_WDS_CONNECTION_STATUS_DISCONNECTED] = "disconnected",
120                 [QMI_WDS_CONNECTION_STATUS_CONNECTED] = "connected",
121                 [QMI_WDS_CONNECTION_STATUS_SUSPENDED] = "suspended",
122                 [QMI_WDS_CONNECTION_STATUS_AUTHENTICATING] = "authenticating",
123         };
124         int s = 0;
125
126         qmi_parse_wds_get_packet_service_status_response(msg, &res);
127         if (res.set.connection_status &&
128             res.data.connection_status < ARRAY_SIZE(data_status))
129                 s = res.data.connection_status;
130
131         blobmsg_add_string(&status, NULL, data_status[s]);
132 }
133
134 static enum qmi_cmd_result
135 cmd_wds_get_packet_service_status_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
136 {
137         qmi_set_wds_get_packet_service_status_request(msg);
138         return QMI_CMD_REQUEST;
139 }
140
141 #define cmd_wds_set_autoconnect_setting_cb no_cb
142 static enum qmi_cmd_result
143 cmd_wds_set_autoconnect_setting_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
144 {
145         struct qmi_wds_set_autoconnect_setting_request ac_req;
146         const char *modes[] = {
147                 [QMI_WDS_AUTOCONNECT_DISABLED] = "disabled",
148                 [QMI_WDS_AUTOCONNECT_ENABLED] = "enabled",
149                 [QMI_WDS_AUTOCONNECT_PAUSED] = "paused",
150         };
151         int i;
152
153         for (i = 0; i < ARRAY_SIZE(modes); i++) {
154                 if (strcasecmp(modes[i], arg) != 0)
155                         continue;
156
157                 qmi_set(&ac_req, setting, i);
158                 qmi_set_wds_set_autoconnect_setting_request(msg, &ac_req);
159                 return QMI_CMD_DONE;
160         }
161
162         uqmi_add_error("Invalid value (valid: disabled, enabled, paused)");
163         return QMI_CMD_EXIT;
164 }
165
166 #define cmd_wds_reset_cb no_cb
167 static enum qmi_cmd_result
168 cmd_wds_reset_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
169 {
170         qmi_set_wds_reset_request(msg);
171         return QMI_CMD_REQUEST;
172 }
173
174 #define cmd_wds_set_ip_family_cb no_cb
175 static enum qmi_cmd_result
176 cmd_wds_set_ip_family_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
177 {
178         struct qmi_wds_set_ip_family_request ipf_req;
179         const struct ip_modes {
180                 const char *name;
181                 const QmiWdsIpFamily mode;
182         } modes[] = {
183                 { "ipv4", QMI_WDS_IP_FAMILY_IPV4 },
184                 { "ipv6", QMI_WDS_IP_FAMILY_IPV6 },
185                 { "unspecified", QMI_WDS_IP_FAMILY_UNSPECIFIED },
186         };
187         int i;
188
189         for (i = 0; i < ARRAY_SIZE(modes); i++) {
190                 if (strcasecmp(modes[i].name, arg) != 0)
191                         continue;
192
193                 qmi_set(&ipf_req, preference, modes[i].mode);
194                 qmi_set_wds_set_ip_family_request(msg, &ipf_req);
195                 return QMI_CMD_REQUEST;
196         }
197
198         uqmi_add_error("Invalid value (valid: ipv4, ipv6, unspecified)");
199         return QMI_CMD_EXIT;
200 }