commands-wds.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  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. #include <stdlib.h>
  22. #include <arpa/inet.h>
  23. #include "qmi-message.h"
  24. static const struct {
  25. const char *auth_name;
  26. QmiWdsAuthentication auth;
  27. } auth_modes[] = {
  28. { "none", QMI_WDS_AUTHENTICATION_NONE },
  29. { "pap", QMI_WDS_AUTHENTICATION_PAP },
  30. { "chap", QMI_WDS_AUTHENTICATION_CHAP },
  31. { "both", QMI_WDS_AUTHENTICATION_PAP | QMI_WDS_AUTHENTICATION_CHAP },
  32. };
  33. static const struct {
  34. const char *ipfam_name;
  35. const QmiWdsIpFamily mode;
  36. } ipfam_modes[] = {
  37. { "ipv4", QMI_WDS_IP_FAMILY_IPV4 },
  38. { "ipv6", QMI_WDS_IP_FAMILY_IPV6 },
  39. { "unspecified", QMI_WDS_IP_FAMILY_UNSPECIFIED },
  40. };
  41. static const struct {
  42. const char *pdp_name;
  43. const QmiWdsPdpType type;
  44. } pdp_types[] = {
  45. { "ipv4", QMI_WDS_PDP_TYPE_IPV4 },
  46. { "ppp", QMI_WDS_PDP_TYPE_PPP },
  47. { "ipv6", QMI_WDS_PDP_TYPE_IPV6 },
  48. { "ipv4v6", QMI_WDS_PDP_TYPE_IPV4_OR_IPV6 },
  49. };
  50. static const struct {
  51. const char *profile_name;
  52. const QmiWdsProfileType profile;
  53. } profile_types[] = {
  54. { "3gpp", QMI_WDS_PROFILE_TYPE_3GPP },
  55. { "3gpp2", QMI_WDS_PROFILE_TYPE_3GPP2 },
  56. };
  57. static struct qmi_wds_start_network_request wds_sn_req = {
  58. QMI_INIT(authentication_preference,
  59. QMI_WDS_AUTHENTICATION_PAP | QMI_WDS_AUTHENTICATION_CHAP),
  60. };
  61. static struct qmi_wds_stop_network_request wds_stn_req;
  62. static struct qmi_wds_modify_profile_request wds_mp_req = {
  63. QMI_INIT_SEQUENCE(profile_identifier,
  64. .profile_type = QMI_WDS_PROFILE_TYPE_3GPP,
  65. .profile_index = 1,
  66. ),
  67. QMI_INIT(apn_disabled_flag, false),
  68. };
  69. static struct qmi_wds_create_profile_request wds_cp_req = {
  70. QMI_INIT(profile_type,QMI_WDS_PROFILE_TYPE_3GPP),
  71. QMI_INIT(apn_disabled_flag, false),
  72. };
  73. #define cmd_wds_set_apn_cb no_cb
  74. static enum qmi_cmd_result
  75. cmd_wds_set_apn_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
  76. {
  77. qmi_set_ptr(&wds_sn_req, apn, arg);
  78. qmi_set_ptr(&wds_mp_req, apn_name, arg);
  79. qmi_set_ptr(&wds_cp_req, apn_name, arg);
  80. return QMI_CMD_DONE;
  81. }
  82. #define cmd_wds_set_auth_cb no_cb
  83. static enum qmi_cmd_result
  84. cmd_wds_set_auth_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
  85. {
  86. int i;
  87. for (i = 0; i < ARRAY_SIZE(auth_modes); i++) {
  88. if (strcasecmp(auth_modes[i].auth_name, arg) != 0)
  89. continue;
  90. qmi_set(&wds_sn_req, authentication_preference, auth_modes[i].auth);
  91. qmi_set(&wds_mp_req, authentication, auth_modes[i].auth);
  92. qmi_set(&wds_cp_req, authentication, auth_modes[i].auth);
  93. return QMI_CMD_DONE;
  94. }
  95. uqmi_add_error("Invalid auth mode (valid: pap, chap, both, none)");
  96. return QMI_CMD_EXIT;
  97. }
  98. #define cmd_wds_set_username_cb no_cb
  99. static enum qmi_cmd_result
  100. cmd_wds_set_username_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
  101. {
  102. qmi_set_ptr(&wds_sn_req, username, arg);
  103. qmi_set_ptr(&wds_mp_req, username, arg);
  104. qmi_set_ptr(&wds_cp_req, username, arg);
  105. return QMI_CMD_DONE;
  106. }
  107. #define cmd_wds_set_password_cb no_cb
  108. static enum qmi_cmd_result
  109. cmd_wds_set_password_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
  110. {
  111. qmi_set_ptr(&wds_sn_req, password, arg);
  112. qmi_set_ptr(&wds_mp_req, password, arg);
  113. qmi_set_ptr(&wds_cp_req, password, arg);
  114. return QMI_CMD_DONE;
  115. }
  116. #define cmd_wds_set_autoconnect_cb no_cb
  117. static enum qmi_cmd_result
  118. cmd_wds_set_autoconnect_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
  119. {
  120. qmi_set(&wds_sn_req, enable_autoconnect, true);
  121. qmi_set(&wds_stn_req, disable_autoconnect, true);
  122. return QMI_CMD_DONE;
  123. }
  124. #define cmd_wds_set_ip_family_pref_cb no_cb
  125. static enum qmi_cmd_result
  126. cmd_wds_set_ip_family_pref_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
  127. {
  128. int i;
  129. for (i = 0; i < ARRAY_SIZE(ipfam_modes); i++) {
  130. if (strcasecmp(ipfam_modes[i].ipfam_name, arg) != 0)
  131. continue;
  132. qmi_set(&wds_sn_req, ip_family_preference, ipfam_modes[i].mode);
  133. return QMI_CMD_DONE;
  134. }
  135. uqmi_add_error("Invalid value (valid: ipv4, ipv6, unspecified)");
  136. return QMI_CMD_EXIT;
  137. }
  138. #define cmd_wds_set_pdp_type_cb no_cb
  139. static enum qmi_cmd_result
  140. cmd_wds_set_pdp_type_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
  141. {
  142. int i;
  143. for (i = 0; i < ARRAY_SIZE(pdp_types); i++) {
  144. if (strcasecmp(pdp_types[i].pdp_name, arg) != 0)
  145. continue;
  146. qmi_set(&wds_mp_req, pdp_type, pdp_types[i].type);
  147. qmi_set(&wds_cp_req, pdp_type, pdp_types[i].type);
  148. return QMI_CMD_DONE;
  149. }
  150. uqmi_add_error("Invalid value (valid: ipv4, ipv6, ipv4v6)");
  151. return QMI_CMD_EXIT;
  152. }
  153. #define cmd_wds_no_roaming_cb no_cb
  154. static enum qmi_cmd_result
  155. cmd_wds_no_roaming_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
  156. {
  157. if (strcmp(arg, "true") == 0) {
  158. qmi_set(&wds_mp_req, roaming_disallowed_flag, true);
  159. qmi_set(&wds_cp_req, roaming_disallowed_flag, true);
  160. } else if (strcmp(arg, "false") == 0) {
  161. qmi_set(&wds_mp_req, roaming_disallowed_flag, false);
  162. qmi_set(&wds_cp_req, roaming_disallowed_flag, false);
  163. } else {
  164. uqmi_add_error("Invalid value (true or false)");
  165. return QMI_CMD_EXIT;
  166. }
  167. return QMI_CMD_DONE;
  168. }
  169. #define cmd_wds_set_profile_cb no_cb
  170. static enum qmi_cmd_result
  171. cmd_wds_set_profile_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
  172. {
  173. uint32_t idx = strtoul(arg, NULL, 10);
  174. qmi_set(&wds_sn_req, profile_index_3gpp, idx);
  175. return QMI_CMD_DONE;
  176. }
  177. static void
  178. cmd_wds_start_network_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg)
  179. {
  180. struct qmi_wds_start_network_response res;
  181. qmi_parse_wds_start_network_response(msg, &res);
  182. if (res.set.packet_data_handle)
  183. blobmsg_add_u32(&status, NULL, res.data.packet_data_handle);
  184. }
  185. static enum qmi_cmd_result
  186. cmd_wds_start_network_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
  187. {
  188. qmi_set_wds_start_network_request(msg, &wds_sn_req);
  189. return QMI_CMD_REQUEST;
  190. }
  191. #define cmd_wds_stop_network_cb no_cb
  192. static enum qmi_cmd_result
  193. cmd_wds_stop_network_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
  194. {
  195. uint32_t pdh = strtoul(arg, NULL, 0);
  196. qmi_set(&wds_stn_req, packet_data_handle, pdh);
  197. qmi_set_wds_stop_network_request(msg, &wds_stn_req);
  198. return QMI_CMD_REQUEST;
  199. }
  200. static void
  201. cmd_wds_modify_profile_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg)
  202. {
  203. struct qmi_wds_modify_profile_response res;
  204. qmi_parse_wds_modify_profile_response(msg, &res);
  205. }
  206. static enum qmi_cmd_result
  207. cmd_wds_modify_profile_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
  208. {
  209. int id;
  210. char *s;
  211. char *p_type;
  212. s = strchr(arg, ',');
  213. if (!s) {
  214. fprintf(stderr, "Invalid argument\n");
  215. return QMI_CMD_EXIT;
  216. }
  217. *s = 0;
  218. s++;
  219. id = strtoul(s, &s, 0);
  220. if (s && *s) {
  221. fprintf(stderr, "Invalid argument\n");
  222. return QMI_CMD_EXIT;
  223. }
  224. p_type = strtok(arg, ",");
  225. int i;
  226. for (i = 0; i < ARRAY_SIZE(profile_types); i++) {
  227. if (strcasecmp(profile_types[i].profile_name, p_type) != 0)
  228. continue;
  229. qmi_set_ptr(&wds_mp_req, profile_identifier.profile_type, profile_types[i].profile);
  230. qmi_set_ptr(&wds_mp_req, profile_identifier.profile_index, id);
  231. qmi_set_wds_modify_profile_request(msg, &wds_mp_req);
  232. return QMI_CMD_REQUEST;
  233. }
  234. uqmi_add_error("Invalid value (valid: 3gpp or 3gpp2)");
  235. return QMI_CMD_EXIT;
  236. }
  237. static void
  238. cmd_wds_create_profile_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg)
  239. {
  240. struct qmi_wds_create_profile_response res;
  241. void *p;
  242. qmi_parse_wds_create_profile_response(msg, &res);
  243. if (res.set.profile_identifier) {
  244. p = blobmsg_open_table(&status, NULL);
  245. blobmsg_add_u32(&status, "created-profile", res.data.profile_identifier.profile_index);
  246. blobmsg_close_table(&status, p);
  247. }
  248. }
  249. static enum qmi_cmd_result
  250. cmd_wds_create_profile_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
  251. {
  252. int i;
  253. for (i = 0; i < ARRAY_SIZE(profile_types); i++) {
  254. if (strcasecmp(profile_types[i].profile_name, arg) != 0)
  255. continue;
  256. qmi_set_ptr(&wds_cp_req, profile_type, profile_types[i].profile);
  257. qmi_set_wds_create_profile_request(msg, &wds_cp_req);
  258. return QMI_CMD_REQUEST;
  259. }
  260. uqmi_add_error("Invalid value (valid: 3gpp or 3gpp2)");
  261. return QMI_CMD_EXIT;
  262. }
  263. static void
  264. cmd_wds_get_packet_service_status_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg)
  265. {
  266. struct qmi_wds_get_packet_service_status_response res;
  267. const char *data_status[] = {
  268. [QMI_WDS_CONNECTION_STATUS_UNKNOWN] = "unknown",
  269. [QMI_WDS_CONNECTION_STATUS_DISCONNECTED] = "disconnected",
  270. [QMI_WDS_CONNECTION_STATUS_CONNECTED] = "connected",
  271. [QMI_WDS_CONNECTION_STATUS_SUSPENDED] = "suspended",
  272. [QMI_WDS_CONNECTION_STATUS_AUTHENTICATING] = "authenticating",
  273. };
  274. int s = 0;
  275. qmi_parse_wds_get_packet_service_status_response(msg, &res);
  276. if (res.set.connection_status &&
  277. res.data.connection_status < ARRAY_SIZE(data_status))
  278. s = res.data.connection_status;
  279. blobmsg_add_string(&status, NULL, data_status[s]);
  280. }
  281. static enum qmi_cmd_result
  282. cmd_wds_get_packet_service_status_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
  283. {
  284. qmi_set_wds_get_packet_service_status_request(msg);
  285. return QMI_CMD_REQUEST;
  286. }
  287. #define cmd_wds_set_autoconnect_settings_cb no_cb
  288. static enum qmi_cmd_result
  289. cmd_wds_set_autoconnect_settings_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
  290. {
  291. struct qmi_wds_set_autoconnect_settings_request ac_req;
  292. const char *modes[] = {
  293. [QMI_WDS_AUTOCONNECT_SETTING_DISABLED] = "disabled",
  294. [QMI_WDS_AUTOCONNECT_SETTING_ENABLED] = "enabled",
  295. [QMI_WDS_AUTOCONNECT_SETTING_PAUSED] = "paused",
  296. };
  297. int i;
  298. for (i = 0; i < ARRAY_SIZE(modes); i++) {
  299. if (strcasecmp(modes[i], arg) != 0)
  300. continue;
  301. qmi_set(&ac_req, status, i);
  302. qmi_set_wds_set_autoconnect_settings_request(msg, &ac_req);
  303. return QMI_CMD_DONE;
  304. }
  305. uqmi_add_error("Invalid value (valid: disabled, enabled, paused)");
  306. return QMI_CMD_EXIT;
  307. }
  308. #define cmd_wds_reset_cb no_cb
  309. static enum qmi_cmd_result
  310. cmd_wds_reset_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
  311. {
  312. qmi_set_wds_reset_request(msg);
  313. return QMI_CMD_REQUEST;
  314. }
  315. #define cmd_wds_set_ip_family_cb no_cb
  316. static enum qmi_cmd_result
  317. cmd_wds_set_ip_family_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
  318. {
  319. struct qmi_wds_set_ip_family_request ipf_req;
  320. int i;
  321. for (i = 0; i < ARRAY_SIZE(ipfam_modes); i++) {
  322. if (strcasecmp(ipfam_modes[i].ipfam_name, arg) != 0)
  323. continue;
  324. qmi_set(&ipf_req, preference, ipfam_modes[i].mode);
  325. qmi_set_wds_set_ip_family_request(msg, &ipf_req);
  326. return QMI_CMD_REQUEST;
  327. }
  328. uqmi_add_error("Invalid value (valid: ipv4, ipv6, unspecified)");
  329. return QMI_CMD_EXIT;
  330. }
  331. static void wds_to_ipv4(const char *name, const uint32_t addr)
  332. {
  333. struct in_addr ip_addr;
  334. char buf[INET_ADDRSTRLEN];
  335. ip_addr.s_addr = htonl(addr);
  336. blobmsg_add_string(&status, name, inet_ntop(AF_INET, &ip_addr, buf, sizeof(buf)));
  337. }
  338. static void wds_to_ipv6(const char *name, const uint16_t *addr)
  339. {
  340. char buf[INET6_ADDRSTRLEN];
  341. uint16_t ip_addr[8];
  342. int i;
  343. for (i = 0; i < ARRAY_SIZE(ip_addr); i++)
  344. ip_addr[i] = htons(addr[i]);
  345. blobmsg_add_string(&status, name, inet_ntop(AF_INET6, &ip_addr, buf, sizeof(buf)));
  346. }
  347. static enum qmi_cmd_result
  348. cmd_wds_get_profile_settings_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
  349. {
  350. int id;
  351. char *s;
  352. char *p_type;
  353. s = strchr(arg, ',');
  354. if (!s) {
  355. fprintf(stderr, "Invalid argument\n");
  356. return QMI_CMD_EXIT;
  357. }
  358. *s = 0;
  359. s++;
  360. id = strtoul(s, &s, 0);
  361. if (s && *s) {
  362. fprintf(stderr, "Invalid argument\n");
  363. return QMI_CMD_EXIT;
  364. }
  365. p_type = strtok(arg, ",");
  366. int i;
  367. for (i = 0; i < ARRAY_SIZE(profile_types); i++) {
  368. if (strcasecmp(profile_types[i].profile_name, p_type) != 0)
  369. continue;
  370. struct qmi_wds_get_profile_settings_request p_num = {
  371. QMI_INIT_SEQUENCE(profile_id,
  372. .profile_type = profile_types[i].profile,
  373. .profile_index = id,
  374. )
  375. };
  376. qmi_set_wds_get_profile_settings_request(msg, &p_num);
  377. return QMI_CMD_REQUEST;
  378. }
  379. uqmi_add_error("Invalid value (valid: 3gpp or 3gpp2)");
  380. return QMI_CMD_EXIT;
  381. }
  382. static void
  383. cmd_wds_get_profile_settings_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg)
  384. {
  385. struct qmi_wds_get_profile_settings_response res;
  386. void *p;
  387. qmi_parse_wds_get_profile_settings_response(msg, &res);
  388. p = blobmsg_open_table(&status, NULL);
  389. blobmsg_add_string(&status, "apn", res.data.apn_name);
  390. if (res.set.pdp_type && (int) res.data.pdp_type < ARRAY_SIZE(pdp_types))
  391. blobmsg_add_string(&status, "pdp-type", pdp_types[res.data.pdp_type].pdp_name);
  392. blobmsg_add_string(&status, "username", res.data.username);
  393. blobmsg_add_string(&status, "password", res.data.password);
  394. if (res.set.authentication && (int) res.data.authentication < ARRAY_SIZE(auth_modes))
  395. blobmsg_add_string(&status, "auth", auth_modes[res.data.authentication].auth_name);
  396. blobmsg_add_u8(&status, "no-roaming", res.data.roaming_disallowed_flag);
  397. blobmsg_add_u8(&status, "apn-disabled", res.data.apn_disabled_flag);
  398. blobmsg_close_table(&status, p);
  399. }
  400. static void
  401. cmd_wds_get_current_settings_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg)
  402. {
  403. void *v4, *v6, *d, *t;
  404. struct qmi_wds_get_current_settings_response res;
  405. int i;
  406. qmi_parse_wds_get_current_settings_response(msg, &res);
  407. t = blobmsg_open_table(&status, NULL);
  408. if (res.set.pdp_type && (int) res.data.pdp_type < ARRAY_SIZE(pdp_types))
  409. blobmsg_add_string(&status, "pdp-type", pdp_types[res.data.pdp_type].pdp_name);
  410. if (res.set.ip_family) {
  411. for (i = 0; i < ARRAY_SIZE(ipfam_modes); i++) {
  412. if (ipfam_modes[i].mode != res.data.ip_family)
  413. continue;
  414. blobmsg_add_string(&status, "ip-family", ipfam_modes[i].ipfam_name);
  415. break;
  416. }
  417. }
  418. if (res.set.mtu)
  419. blobmsg_add_u32(&status, "mtu", res.data.mtu);
  420. /* IPV4 */
  421. v4 = blobmsg_open_table(&status, "ipv4");
  422. if (res.set.ipv4_address)
  423. wds_to_ipv4("ip", res.data.ipv4_address);
  424. if (res.set.primary_ipv4_dns_address)
  425. wds_to_ipv4("dns1", res.data.primary_ipv4_dns_address);
  426. if (res.set.secondary_ipv4_dns_address)
  427. wds_to_ipv4("dns2", res.data.secondary_ipv4_dns_address);
  428. if (res.set.ipv4_gateway_address)
  429. wds_to_ipv4("gateway", res.data.ipv4_gateway_address);
  430. if (res.set.ipv4_gateway_subnet_mask)
  431. wds_to_ipv4("subnet", res.data.ipv4_gateway_subnet_mask);
  432. blobmsg_close_table(&status, v4);
  433. /* IPV6 */
  434. v6 = blobmsg_open_table(&status, "ipv6");
  435. if (res.set.ipv6_address) {
  436. wds_to_ipv6("ip", res.data.ipv6_address.address);
  437. blobmsg_add_u32(&status, "ip-prefix-length", res.data.ipv6_address.prefix_length);
  438. }
  439. if (res.set.ipv6_gateway_address) {
  440. wds_to_ipv6("gateway", res.data.ipv6_gateway_address.address);
  441. blobmsg_add_u32(&status, "gw-prefix-length", res.data.ipv6_gateway_address.prefix_length);
  442. }
  443. if (res.set.ipv6_primary_dns_address)
  444. wds_to_ipv6("dns1", res.data.ipv6_primary_dns_address);
  445. if (res.set.ipv6_secondary_dns_address)
  446. wds_to_ipv6("dns2", res.data.ipv6_secondary_dns_address);
  447. blobmsg_close_table(&status, v6);
  448. d = blobmsg_open_table(&status, "domain-names");
  449. for (i = 0; i < res.data.domain_name_list_n; i++) {
  450. blobmsg_add_string(&status, NULL, res.data.domain_name_list[i]);
  451. }
  452. blobmsg_close_table(&status, d);
  453. blobmsg_close_table(&status, t);
  454. }
  455. static enum qmi_cmd_result
  456. cmd_wds_get_current_settings_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
  457. {
  458. struct qmi_wds_get_current_settings_request gcs_req;
  459. memset(&gcs_req, '\0', sizeof(struct qmi_wds_get_current_settings_request));
  460. qmi_set(&gcs_req, requested_settings,
  461. QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_PDP_TYPE |
  462. QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_DNS_ADDRESS |
  463. QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_GRANTED_QOS |
  464. QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_IP_ADDRESS |
  465. QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_GATEWAY_INFO |
  466. QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_MTU |
  467. QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_DOMAIN_NAME_LIST |
  468. QMI_WDS_GET_CURRENT_SETTINGS_REQUESTED_SETTINGS_IP_FAMILY);
  469. qmi_set_wds_get_current_settings_request(msg, &gcs_req);
  470. return QMI_CMD_REQUEST;
  471. }
  472. static enum qmi_cmd_result
  473. cmd_wds_get_default_profile_prepare(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg, char *arg)
  474. {
  475. int i;
  476. for (i = 0; i < ARRAY_SIZE(profile_types); i++) {
  477. if (strcasecmp(profile_types[i].profile_name, arg) != 0)
  478. continue;
  479. struct qmi_wds_get_default_profile_number_request type_family = {
  480. QMI_INIT_SEQUENCE(profile_type,
  481. .type = profile_types[i].profile,
  482. .family = QMI_WDS_PROFILE_FAMILY_TETHERED,
  483. )
  484. };
  485. qmi_set_wds_get_default_profile_number_request(msg, &type_family);
  486. return QMI_CMD_REQUEST;
  487. }
  488. uqmi_add_error("Invalid value (valid: 3gpp or 3gpp2)");
  489. return QMI_CMD_EXIT;
  490. }
  491. static void
  492. cmd_wds_get_default_profile_cb(struct qmi_dev *qmi, struct qmi_request *req, struct qmi_msg *msg)
  493. {
  494. struct qmi_wds_get_default_profile_number_response res;
  495. void *p;
  496. qmi_parse_wds_get_default_profile_number_response(msg, &res);
  497. p = blobmsg_open_table(&status, NULL);
  498. blobmsg_add_u32(&status, "default-profile", res.data.index);
  499. blobmsg_close_table(&status, p);
  500. }