• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/uqmi/uqmi/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 #include <arpa/inet.h>
 24 
 25 #include "qmi-message.h"
 26 
 27 static const struct {
 28         const char *auth_name;
 29         QmiWdsAuthentication auth;
 30 } auth_modes[] = {
 31         { "none", QMI_WDS_AUTHENTICATION_NONE },
 32         { "pap", QMI_WDS_AUTHENTICATION_PAP },
 33         { "chap", QMI_WDS_AUTHENTICATION_CHAP },
 34         { "both", QMI_WDS_AUTHENTICATION_PAP | QMI_WDS_AUTHENTICATION_CHAP },
 35 };
 36 
 37 static const struct {
 38         const char *ipfam_name;
 39         const QmiWdsIpFamily mode;
 40 } ipfam_modes[] = {
 41         { "ipv4", QMI_WDS_IP_FAMILY_IPV4 },
 42         { "ipv6", QMI_WDS_IP_FAMILY_IPV6 },
 43         { "unspecified", QMI_WDS_IP_FAMILY_UNSPECIFIED },
 44 };
 45 
 46 static const struct {
 47         const char *pdp_name;
 48         const QmiWdsPdpType type;
 49 } pdp_types[] = {
 50         { "ipv4", QMI_WDS_PDP_TYPE_IPV4 },
 51         { "ppp", QMI_WDS_PDP_TYPE_PPP },
 52         { "ipv6", QMI_WDS_PDP_TYPE_IPV6 },
 53         { "ipv4v6", QMI_WDS_PDP_TYPE_IPV4_OR_IPV6 },
 54 };
 55 
 56 static const struct {
 57         const char *profile_name;
 58         const QmiWdsProfileType profile;
 59 } profile_types[] = {
 60         { "3gpp", QMI_WDS_PROFILE_TYPE_3GPP },
 61         { "3gpp2", QMI_WDS_PROFILE_TYPE_3GPP2 },
 62 };
 63 
 64 struct uqmi_wds_profile_identifier {
 65         QmiWdsProfileType type;
 66         uint32_t index;
 67 };
 68 
 69 static struct qmi_wds_start_network_request wds_sn_req = {
 70         QMI_INIT(authentication_preference,
 71                  QMI_WDS_AUTHENTICATION_PAP | QMI_WDS_AUTHENTICATION_CHAP),
 72 };
 73 
 74 static struct qmi_wds_stop_network_request wds_stn_req;
 75 
 76 static struct qmi_wds_modify_profile_request wds_mp_req = {
 77         QMI_INIT_SEQUENCE(profile_identifier,
 78                 .profile_type = QMI_WDS_PROFILE_TYPE_3GPP,
 79                 .profile_index = 1,
 80         ),
 81         QMI_INIT(apn_disabled_flag, false),
 82 };
 83 
 84 static struct qmi_wds_create_profile_request wds_cp_req = {
 85         QMI_INIT(profile_type,QMI_WDS_PROFILE_TYPE_3GPP),
 86         QMI_INIT(apn_disabled_flag, false),
 87 };
 88 
 89 static int
 90 uqmi_wds_profile_type_parse(const char *type_string, QmiWdsProfileType *type)
 91 {
 92         int i;
 93 
 94         for (i = 0; i < ARRAY_SIZE(profile_types); i++) {
 95                 if (strcasecmp(profile_types[i].profile_name, type_string) != 0)
 96                         continue;
 97 
 98                 *type = profile_types[i].profile;
 99                 return 0;
100         }
101 
102         return -1;
103 }
104 
105 static int
106 uqmi_wds_profile_identifier_parse(char *arg, struct uqmi_wds_profile_identifier *profile)
107 {
108         char *s;
109         char *p_type;
110         int id;
111 
112         s = strchr(arg, ',');
113         if (!s)
114                 return -1;
115         *s = 0;
116         s++;
117 
118         id = strtoul(s, &s, 0);
119         if (s && *s)
120                 return -1;
121 
122         p_type = strtok(arg, ",");
123 
124         if (uqmi_wds_profile_type_parse(p_type, &profile->type))
125                 return -1;
126 
127         profile->index = id;
128 
129         return 0;
130 }
131 
132 #define cmd_wds_set_apn_cb no_cb
133 static enum qmi_cmd_result
134 cmd_wds_set_apn_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
135 {
136         qmi_set_ptr(&wds_sn_req, apn, arg);
137         qmi_set_ptr(&wds_mp_req, apn_name, arg);
138         qmi_set_ptr(&wds_cp_req, apn_name, arg);
139         return QMI_CMD_DONE;
140 }
141 
142 #define cmd_wds_set_auth_cb no_cb
143 static enum qmi_cmd_result
144 cmd_wds_set_auth_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
145 {
146         int i;
147         for (i = 0; i < ARRAY_SIZE(auth_modes); i++) {
148                 if (strcasecmp(auth_modes[i].auth_name, arg) != 0)
149                         continue;
150 
151                 qmi_set(&wds_sn_req, authentication_preference, auth_modes[i].auth);
152                 qmi_set(&wds_mp_req, authentication, auth_modes[i].auth);
153                 qmi_set(&wds_cp_req, authentication, auth_modes[i].auth);
154                 return QMI_CMD_DONE;
155         }
156 
157         uqmi_add_error("Invalid auth mode (valid: pap, chap, both, none)");
158         return QMI_CMD_EXIT;
159 }
160 
161 #define cmd_wds_set_username_cb no_cb
162 static enum qmi_cmd_result
163 cmd_wds_set_username_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
164 {
165         qmi_set_ptr(&wds_sn_req, username, arg);
166         qmi_set_ptr(&wds_mp_req, username, arg);
167         qmi_set_ptr(&wds_cp_req, username, arg);
168         return QMI_CMD_DONE;
169 }
170 
171 #define cmd_wds_set_password_cb no_cb
172 static enum qmi_cmd_result
173 cmd_wds_set_password_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
174 {
175         qmi_set_ptr(&wds_sn_req, password, arg);
176         qmi_set_ptr(&wds_mp_req, password, arg);
177         qmi_set_ptr(&wds_cp_req, password, arg);
178         return QMI_CMD_DONE;
179 }
180 
181 #define cmd_wds_set_autoconnect_cb no_cb
182 static enum qmi_cmd_result
183 cmd_wds_set_autoconnect_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
184 {
185         qmi_set(&wds_sn_req, enable_autoconnect, true);
186         qmi_set(&wds_stn_req, disable_autoconnect, true);
187         return QMI_CMD_DONE;
188 }
189 
190 #define cmd_wds_set_ip_family_pref_cb no_cb
191 static enum qmi_cmd_result
192 cmd_wds_set_ip_family_pref_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
193 {
194         int i;
195         for (i = 0; i < ARRAY_SIZE(ipfam_modes); i++) {
196                 if (strcasecmp(ipfam_modes[i].ipfam_name, arg) != 0)
197                         continue;
198 
199                 qmi_set(&wds_sn_req, ip_family_preference, ipfam_modes[i].mode);
200                 return QMI_CMD_DONE;
201         }
202 
203         uqmi_add_error("Invalid value (valid: ipv4, ipv6, unspecified)");
204         return QMI_CMD_EXIT;
205 }
206 
207 #define cmd_wds_set_pdp_type_cb no_cb
208 static enum qmi_cmd_result
209 cmd_wds_set_pdp_type_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
210 {
211         int i;
212 
213         for (i = 0; i < ARRAY_SIZE(pdp_types); i++) {
214                 if (strcasecmp(pdp_types[i].pdp_name, arg) != 0)
215                         continue;
216 
217                 qmi_set(&wds_mp_req, pdp_type, pdp_types[i].type);
218                 qmi_set(&wds_cp_req, pdp_type, pdp_types[i].type);
219                 return QMI_CMD_DONE;
220         }
221 
222         uqmi_add_error("Invalid value (valid: ipv4, ipv6, ipv4v6)");
223         return QMI_CMD_EXIT;
224 }
225 
226 #define cmd_wds_no_roaming_cb no_cb
227 static enum qmi_cmd_result
228 cmd_wds_no_roaming_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
229 {
230         if (strcmp(arg, "true") == 0) {
231                 qmi_set(&wds_mp_req, roaming_disallowed_flag, true);
232                 qmi_set(&wds_cp_req, roaming_disallowed_flag, true);
233         } else if (strcmp(arg, "false") == 0) {
234                 qmi_set(&wds_mp_req, roaming_disallowed_flag, false);
235                 qmi_set(&wds_cp_req, roaming_disallowed_flag, false);
236         } else {
237                 uqmi_add_error("Invalid value (true or false)");
238                 return QMI_CMD_EXIT;
239         }
240         return QMI_CMD_DONE;
241 }
242 
243 #define cmd_wds_set_profile_cb no_cb
244 static enum qmi_cmd_result
245 cmd_wds_set_profile_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
246 {
247         uint32_t idx = strtoul(arg, NULL, 10);
248 
249         qmi_set(&wds_sn_req, profile_index_3gpp, idx);
250         return QMI_CMD_DONE;
251 }
252 
253 static void
254 cmd_wds_start_network_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg)
255 {
256         struct qmi_wds_start_network_response res;
257 
258         qmi_parse_wds_start_network_response(msg, &res);
259         if (res.set.packet_data_handle)
260                 blobmsg_add_u32(&status, NULL, res.data.packet_data_handle);
261 }
262 
263 static enum qmi_cmd_result
264 cmd_wds_start_network_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
265 {
266         qmi_set_wds_start_network_request(msg, &wds_sn_req);
267         return QMI_CMD_REQUEST;
268 }
269 
270 #define cmd_wds_stop_network_cb no_cb
271 static enum qmi_cmd_result
272 cmd_wds_stop_network_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
273 {
274         uint32_t pdh = strtoul(arg, NULL, 0);
275 
276         qmi_set(&wds_stn_req, packet_data_handle, pdh);
277         qmi_set_wds_stop_network_request(msg, &wds_stn_req);
278         return QMI_CMD_REQUEST;
279 }
280 
281 static void
282 cmd_wds_modify_profile_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg)
283 {
284         struct qmi_wds_modify_profile_response res;
285         qmi_parse_wds_modify_profile_response(msg, &res);
286 }
287 
288 static enum qmi_cmd_result
289 cmd_wds_modify_profile_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
290 {
291         struct uqmi_wds_profile_identifier profile;
292 
293         if (uqmi_wds_profile_identifier_parse(arg, &profile) < 0) {
294                 fprintf(stderr, "Invalid argument\n");
295                 return QMI_CMD_EXIT;
296         }
297 
298         qmi_set_ptr(&wds_mp_req, profile_identifier.profile_type, profile.type);
299         qmi_set_ptr(&wds_mp_req, profile_identifier.profile_index, profile.index);
300         qmi_set_wds_modify_profile_request(msg, &wds_mp_req);
301 
302         return QMI_CMD_REQUEST;
303 }
304 
305 static void
306 cmd_wds_get_profile_list_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg)
307 {
308         struct qmi_wds_get_profile_list_response res;
309         void *p, *t, *root;
310         int i;
311 
312         qmi_parse_wds_get_profile_list_response(msg, &res);
313 
314         root = blobmsg_open_table(&status, NULL);
315         p = blobmsg_open_array(&status, "profiles");
316         for (i = 0; i < res.data.profile_list_n; i++) {
317                 t = blobmsg_open_table(&status, NULL);
318                 blobmsg_add_u32(&status, "index", res.data.profile_list[i].profile_index);
319                 blobmsg_add_string(&status, "name", res.data.profile_list[i].profile_name);
320                 blobmsg_close_table(&status, t);
321         }
322         blobmsg_close_array(&status, p);
323         blobmsg_close_table(&status, root);
324 }
325 
326 static enum qmi_cmd_result
327 cmd_wds_get_profile_list_prepare(struct qmi_dev *qmi, struct qmi_request *req,
328                                  struct qmi_msg *msg, char *arg)
329 {
330         struct qmi_wds_get_profile_list_request pl_req = {};
331         QmiWdsProfileType profile_type;
332 
333         if (uqmi_wds_profile_type_parse(arg, &profile_type) < 0) {
334                 uqmi_add_error("Invalid type (valid: 3gpp or 3gpp2)");
335                 return QMI_CMD_EXIT;
336         }
337 
338         qmi_set(&pl_req, profile_type, profile_type);
339 
340         qmi_set_wds_get_profile_list_request(msg, &pl_req);
341         return QMI_CMD_REQUEST;
342 }
343 
344 static void
345 cmd_wds_create_profile_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg)
346 {
347         struct qmi_wds_create_profile_response res;
348         void *p;
349 
350         qmi_parse_wds_create_profile_response(msg, &res);
351 
352         if (res.set.profile_identifier) {
353                 p = blobmsg_open_table(&status, NULL);
354                 blobmsg_add_u32(&status, "created-profile", res.data.profile_identifier.profile_index);
355                 blobmsg_close_table(&status, p);
356         }
357 }
358 
359 static enum qmi_cmd_result
360 cmd_wds_create_profile_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
361 {
362         int i;
363         for (i = 0; i < ARRAY_SIZE(profile_types); i++) {
364                 if (strcasecmp(profile_types[i].profile_name, arg) != 0)
365                         continue;
366 
367                 qmi_set_ptr(&wds_cp_req, profile_type, profile_types[i].profile);
368 
369                 qmi_set_wds_create_profile_request(msg, &wds_cp_req);
370                 return QMI_CMD_REQUEST;
371         }
372 
373         uqmi_add_error("Invalid value (valid: 3gpp or 3gpp2)");
374         return QMI_CMD_EXIT;
375 }
376 
377 static void
378 cmd_wds_get_packet_service_status_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg)
379 {
380         struct qmi_wds_get_packet_service_status_response res;
381         const char *data_status[] = {
382                 [QMI_WDS_CONNECTION_STATUS_UNKNOWN] = "unknown",
383                 [QMI_WDS_CONNECTION_STATUS_DISCONNECTED] = "disconnected",
384                 [QMI_WDS_CONNECTION_STATUS_CONNECTED] = "connected",
385                 [QMI_WDS_CONNECTION_STATUS_SUSPENDED] = "suspended",
386                 [QMI_WDS_CONNECTION_STATUS_AUTHENTICATING] = "authenticating",
387         };
388         int s = 0;
389 
390         qmi_parse_wds_get_packet_service_status_response(msg, &res);
391         if (res.set.connection_status &&
392             res.data.connection_status < ARRAY_SIZE(data_status))
393                 s = res.data.connection_status;
394 
395         blobmsg_add_string(&status, NULL, data_status[s]);
396 }
397 
398 static enum qmi_cmd_result
399 cmd_wds_get_packet_service_status_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
400 {
401         qmi_set_wds_get_packet_service_status_request(msg);
402         return QMI_CMD_REQUEST;
403 }
404 
405 #define cmd_wds_set_autoconnect_settings_cb no_cb
406 static enum qmi_cmd_result
407 cmd_wds_set_autoconnect_settings_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
408 {
409         struct qmi_wds_set_autoconnect_settings_request ac_req;
410         const char *modes[] = {
411                 [QMI_WDS_AUTOCONNECT_SETTING_DISABLED] = "disabled",
412                 [QMI_WDS_AUTOCONNECT_SETTING_ENABLED] = "enabled",
413                 [QMI_WDS_AUTOCONNECT_SETTING_PAUSED] = "paused",
414         };
415         int i;
416 
417         for (i = 0; i < ARRAY_SIZE(modes); i++) {
418                 if (strcasecmp(modes[i], arg) != 0)
419                         continue;
420 
421                 qmi_set(&ac_req, status, i);
422                 qmi_set_wds_set_autoconnect_settings_request(msg, &ac_req);
423                 return QMI_CMD_DONE;
424         }
425 
426         uqmi_add_error("Invalid value (valid: disabled, enabled, paused)");
427         return QMI_CMD_EXIT;
428 }
429 
430 #define cmd_wds_reset_cb no_cb
431 static enum qmi_cmd_result
432 cmd_wds_reset_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
433 {
434         qmi_set_wds_reset_request(msg);
435         return QMI_CMD_REQUEST;
436 }
437 
438 #define cmd_wds_set_ip_family_cb no_cb
439 static enum qmi_cmd_result
440 cmd_wds_set_ip_family_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
441 {
442         struct qmi_wds_set_ip_family_request ipf_req;
443 
444         int i;
445         for (i = 0; i < ARRAY_SIZE(ipfam_modes); i++) {
446                 if (strcasecmp(ipfam_modes[i].ipfam_name, arg) != 0)
447                         continue;
448 
449                 qmi_set(&ipf_req, preference, ipfam_modes[i].mode);
450                 qmi_set_wds_set_ip_family_request(msg, &ipf_req);
451                 return QMI_CMD_REQUEST;
452         }
453 
454         uqmi_add_error("Invalid value (valid: ipv4, ipv6, unspecified)");
455         return QMI_CMD_EXIT;
456 }
457 
458 static struct {
459         uint32_t type;
460         uint32_t iface;
461 } wds_endpoint_info;
462 
463 #define cmd_wds_bind_mux_cb no_cb
464 
465 static enum qmi_cmd_result
466 cmd_wds_bind_mux_prepare(struct qmi_dev *qmi, struct qmi_request *req,
467                          struct qmi_msg *msg, char *arg)
468 {
469         uint32_t mux_num = strtoul(arg, NULL, 10);
470         struct qmi_wds_bind_mux_data_port_request wds_mux_req = {
471                 QMI_INIT_SEQUENCE(
472                                 endpoint_info,
473                                 .endpoint_type = wds_endpoint_info.type,
474                                 .interface_number = wds_endpoint_info.iface,
475                 ),
476                 QMI_INIT(mux_id, mux_num),
477                 QMI_INIT(client_type, QMI_WDS_CLIENT_TYPE_TETHERED),
478         };
479 
480         qmi_set_wds_bind_mux_data_port_request(msg, &wds_mux_req);
481         return QMI_CMD_REQUEST;
482 }
483 
484 #define cmd_wds_ep_iface_cb no_cb
485 
486 static enum qmi_cmd_result
487 cmd_wds_ep_iface_prepare(struct qmi_dev *qmi, struct qmi_request *req,
488                          struct qmi_msg *msg, char *arg)
489 {
490         uint32_t iface_num = strtoul(arg, NULL, 10);
491 
492         wds_endpoint_info.iface = iface_num;
493         return QMI_CMD_DONE;
494 }
495 
496 #define cmd_wds_ep_type_cb no_cb
497 
498 static enum qmi_cmd_result
499 cmd_wds_ep_type_prepare(struct qmi_dev *qmi, struct qmi_request *req,
500                         struct qmi_msg *msg, char *arg)
501 {
502         if (strcmp(arg, "hsusb") == 0) {
503                 wds_endpoint_info.type = QMI_DATA_ENDPOINT_TYPE_HSUSB;
504         } else if (strcmp(arg, "pcie") == 0) {
505                 wds_endpoint_info.type = QMI_DATA_ENDPOINT_TYPE_PCIE;
506         } else {
507                 uqmi_add_error("Invalid value (valid: hsusb, pcie)");
508                 return QMI_CMD_EXIT;
509         }
510 
511         return QMI_CMD_DONE;
512 }
513 
514 static void wds_to_ipv4(const char *name, const uint32_t addr)
515 {
516         struct in_addr ip_addr;
517         char buf[INET_ADDRSTRLEN];
518 
519         ip_addr.s_addr = htonl(addr);
520         blobmsg_add_string(&status, name, inet_ntop(AF_INET, &ip_addr, buf, sizeof(buf)));
521 }
522 
523 static void wds_to_ipv6(const char *name, const uint16_t *addr)
524 {
525         char buf[INET6_ADDRSTRLEN];
526         uint16_t ip_addr[8];
527         int i;
528 
529         for (i = 0; i < ARRAY_SIZE(ip_addr); i++)
530                 ip_addr[i] = htons(addr[i]);
531 
532         blobmsg_add_string(&status, name, inet_ntop(AF_INET6, &ip_addr, buf, sizeof(buf)));
533 }
534 
535 static enum qmi_cmd_result
536 cmd_wds_get_profile_settings_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
537 {
538         struct uqmi_wds_profile_identifier profile;
539 
540         if (uqmi_wds_profile_identifier_parse(arg, &profile) < 0) {
541                 fprintf(stderr, "Invalid argument\n");
542                 return QMI_CMD_EXIT;
543         }
544 
545         struct qmi_wds_get_profile_settings_request p_num = {
546                         QMI_INIT_SEQUENCE(profile_id,
547                                 .profile_type = profile.type,
548                                 .profile_index = profile.index,
549                         )
550                 };
551 
552         qmi_set_wds_get_profile_settings_request(msg, &p_num);
553         return QMI_CMD_REQUEST;
554 }
555 
556 static void
557 cmd_wds_get_profile_settings_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg)
558 {
559         struct qmi_wds_get_profile_settings_response res;
560 
561         void *p;
562 
563         qmi_parse_wds_get_profile_settings_response(msg, &res);
564 
565         p = blobmsg_open_table(&status, NULL);
566 
567         blobmsg_add_string(&status, "apn", res.data.apn_name);
568         if (res.set.pdp_type && (int) res.data.pdp_type < ARRAY_SIZE(pdp_types))
569                 blobmsg_add_string(&status, "pdp-type", pdp_types[res.data.pdp_type].pdp_name);
570         blobmsg_add_string(&status, "username", res.data.username);
571         blobmsg_add_string(&status, "password", res.data.password);
572         if (res.set.authentication && (int) res.data.authentication < ARRAY_SIZE(auth_modes))
573                 blobmsg_add_string(&status, "auth", auth_modes[res.data.authentication].auth_name);
574         blobmsg_add_u8(&status, "no-roaming", res.data.roaming_disallowed_flag);
575         blobmsg_add_u8(&status, "apn-disabled", res.data.apn_disabled_flag);
576         blobmsg_close_table(&status, p);
577 }
578 
579 static void
580 cmd_wds_get_current_settings_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg)
581 {
582         void *v4, *v6, *d, *t;
583         struct qmi_wds_get_current_settings_response res;
584         int i;
585 
586         qmi_parse_wds_get_current_settings_response(msg, &res);
587 
588         t = blobmsg_open_table(&status, NULL);
589 
590         if (res.set.pdp_type && (int) res.data.pdp_type < ARRAY_SIZE(pdp_types))
591                 blobmsg_add_string(&status, "pdp-type", pdp_types[res.data.pdp_type].pdp_name);
592 
593         if (res.set.ip_family) {
594                 for (i = 0; i < ARRAY_SIZE(ipfam_modes); i++) {
595                         if (ipfam_modes[i].mode != res.data.ip_family)
596                                 continue;
597                         blobmsg_add_string(&status, "ip-family", ipfam_modes[i].ipfam_name);
598                         break;
599                 }
600         }
601 
602         if (res.set.mtu)
603                 blobmsg_add_u32(&status, "mtu", res.data.mtu);
604 
605         /* IPV4 */
606         v4 = blobmsg_open_table(&status, "ipv4");
607 
608         if (res.set.ipv4_address)
609                 wds_to_ipv4("ip", res.data.ipv4_address);
610         if (res.set.primary_ipv4_dns_address)
611                 wds_to_ipv4("dns1", res.data.primary_ipv4_dns_address);
612         if (res.set.secondary_ipv4_dns_address)
613                 wds_to_ipv4("dns2", res.data.secondary_ipv4_dns_address);
614         if (res.set.ipv4_gateway_address)
615                 wds_to_ipv4("gateway", res.data.ipv4_gateway_address);
616         if (res.set.ipv4_gateway_subnet_mask)
617                 wds_to_ipv4("subnet", res.data.ipv4_gateway_subnet_mask);
618         blobmsg_close_table(&status, v4);
619 
620         /* IPV6 */
621         v6 = blobmsg_open_table(&status, "ipv6");
622 
623         if (res.set.ipv6_address) {
624                 wds_to_ipv6("ip", res.data.ipv6_address.address);
625                 blobmsg_add_u32(&status, "ip-prefix-length", res.data.ipv6_address.prefix_length);
626         }
627         if (res.set.ipv6_gateway_address) {
628                 wds_to_ipv6("gateway", res.data.ipv6_gateway_address.address);
629                 blobmsg_add_u32(&status, "gw-prefix-length", res.data.ipv6_gateway_address.prefix_length);
630         }
631         if (res.set.ipv6_primary_dns_address)
632                 wds_to_ipv6("dns1", res.data.ipv6_primary_dns_address);
633         if (res.set.ipv6_secondary_dns_address)
634                 wds_to_ipv6("dns2", res.data.ipv6_secondary_dns_address);
635 
636         blobmsg_close_table(&status, v6);
637 
638         d = blobmsg_open_table(&status, "domain-names");
639         for (i = 0; i < res.data.domain_name_list_n; i++) {
640                 blobmsg_add_string(&status, NULL, res.data.domain_name_list[i]);
641         }
642         blobmsg_close_table(&status, d);
643 
644         blobmsg_close_table(&status, t);
645 }
646 
647 static enum qmi_cmd_result
648 cmd_wds_get_current_settings_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
649 {
650         struct qmi_wds_get_current_settings_request gcs_req;
651         memset(&gcs_req, '\0', sizeof(struct qmi_wds_get_current_settings_request));
652         qmi_set(&gcs_req, requested_settings,
653                 QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_PDP_TYPE |
654                 QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_DNS_ADDRESS |
655                 QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_GRANTED_QOS |
656                 QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_IP_ADDRESS |
657                 QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_GATEWAY_INFO |
658                 QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_MTU |
659                 QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_DOMAIN_NAME_LIST |
660                 QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_IP_FAMILY);
661         qmi_set_wds_get_current_settings_request(msg, &gcs_req);
662         return QMI_CMD_REQUEST;
663 }
664 
665 static enum qmi_cmd_result
666 cmd_wds_get_default_profile_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
667 {
668         int i;
669         for (i = 0; i < ARRAY_SIZE(profile_types); i++) {
670                 if (strcasecmp(profile_types[i].profile_name, arg) != 0)
671                         continue;
672 
673                 struct qmi_wds_get_default_profile_number_request type_family = {
674                         QMI_INIT_SEQUENCE(profile_type,
675                                 .type = profile_types[i].profile,
676                                 .family = QMI_WDS_PROFILE_FAMILY_TETHERED,
677                         )
678                 };
679 
680                 qmi_set_wds_get_default_profile_number_request(msg, &type_family);
681                 return QMI_CMD_REQUEST;
682         }
683 
684         uqmi_add_error("Invalid value (valid: 3gpp or 3gpp2)");
685         return QMI_CMD_EXIT;
686 }
687 
688 static void
689 cmd_wds_get_default_profile_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg)
690 {
691         struct qmi_wds_get_default_profile_number_response res;
692         void *p;
693         qmi_parse_wds_get_default_profile_number_response(msg, &res);
694 
695         p = blobmsg_open_table(&status, NULL);
696 
697         blobmsg_add_u32(&status, "default-profile", res.data.index);
698 
699         blobmsg_close_table(&status, p);
700 }
701 
702 #define cmd_wds_set_default_profile_cb no_cb
703 
704 static enum qmi_cmd_result
705 cmd_wds_set_default_profile_prepare(struct qmi_dev *qmi, struct qmi_request *req,
706                                     struct qmi_msg *msg, char *arg)
707 {
708         struct uqmi_wds_profile_identifier profile;
709 
710         if (uqmi_wds_profile_identifier_parse(arg, &profile) < 0) {
711                 fprintf(stderr, "Invalid argument\n");
712                 return QMI_CMD_EXIT;
713         }
714 
715         struct qmi_wds_set_default_profile_number_request set_default_profile = {
716                 QMI_INIT_SEQUENCE(profile_identifier,
717                         .family = QMI_WDS_PROFILE_FAMILY_TETHERED,
718                         .type = profile.type,
719                         .index = profile.index,
720                 )
721         };
722 
723         qmi_set_wds_set_default_profile_number_request(msg, &set_default_profile);
724         return QMI_CMD_REQUEST;
725 }
726 
727 #define cmd_wds_delete_profile_cb no_cb
728 
729 static enum qmi_cmd_result
730 cmd_wds_delete_profile_prepare(struct qmi_dev *qmi, struct qmi_request *req,
731                                struct qmi_msg *msg, char *arg)
732 {
733         struct qmi_wds_delete_profile_request delete_req = {
734                 QMI_INIT_SEQUENCE(profile_identifier,
735                         .profile_type = QMI_WDS_PROFILE_TYPE_3GPP,
736                         .profile_index = 1,
737                 )
738         };
739         struct uqmi_wds_profile_identifier profile;
740 
741         if (uqmi_wds_profile_identifier_parse(arg, &profile) < 0) {
742                 fprintf(stderr, "Invalid argument\n");
743                 return QMI_CMD_EXIT;
744         }
745 
746         qmi_set_ptr(&delete_req, profile_identifier.profile_type, profile.type);
747         qmi_set_ptr(&delete_req, profile_identifier.profile_index, profile.index);
748 
749         qmi_set_wds_delete_profile_request(msg, &delete_req);
750 
751         return QMI_CMD_REQUEST;
752 }
753 
754 #define cmd_wds_set_lte_attach_pdn_cb no_cb
755 
756 static enum qmi_cmd_result
757 cmd_wds_set_lte_attach_pdn_prepare(struct qmi_dev *qmi, struct qmi_request *req,
758                                    struct qmi_msg *msg, char *arg)
759 {
760         uint16_t list[8] = {0};
761 
762         char *s = arg;
763         int i = 0;
764 
765         while (s) {
766                 if (i >= 8) {
767                         fprintf(stderr, "Only 8 attach PDN supported\n");
768                         return QMI_CMD_EXIT;
769                 }
770 
771                 list[i] = strtoul(s, &s, 10);
772                 i++;
773                 if (*s == ',') {
774                         s++;
775                 } else {
776                         fprintf(stderr, "Invalid argument\n");
777                         return QMI_CMD_EXIT;
778                 }
779         }
780 
781 
782         struct qmi_wds_set_lte_attach_pdn_list_request lte_attach_pdn = {
783                 QMI_INIT_ARRAY(list, list, i),
784                 QMI_INIT(action, QMI_WDS_ATTACH_PDN_LIST_ACTION_DETACH_OR_PDN_DISCONNECT)
785         };
786 
787         qmi_set_wds_set_lte_attach_pdn_list_request(msg, &lte_attach_pdn);
788         return QMI_CMD_REQUEST;
789 }
790 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt