blob: 7c019dd78a4a132c270a5787810ae9adb1607bbb [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001
2/******************************************************************************
3*(C) Copyright 2015 Marvell International Ltd.
4* All Rights Reserved
5******************************************************************************/
6
7#include <errno.h>
8#include <unistd.h>
9#include <stdio.h>
10#include <string.h>
11#include <stdlib.h>
12#include <include/log.h>
13#include <uci.h>
14#include <limits.h>
15#include <cm.h>
16#include "ril.h"
17#include "ml_utils.h"
18#include "chl.h"
19#include "chl_db.h"
20#include "chl_ril.h"
21#include "chl_ubus.h"
22#include "chl_main.h"
23#include "chl_uci.h"
24#include "chl_network.h"
25
26#define IPV6_POLL_RETRIES 15
27#define IPV6_POLL_INTERVAL 1000
28#define CHL_ACT_RETRIES 5
29
30static void __chl_poll_ipv6(struct uloop_timeout *t);
31
32static struct chl_conf chl_conf = {
33 .internet = NULL,
34 .autoconf = false,
35 .ipv6_poll_interval = IPV6_POLL_INTERVAL,
36 .activation_retries = CHL_ACT_RETRIES,
37};
38
39static struct uloop_timeout ip6_to = {
40 .cb = __chl_poll_ipv6,
41};
42
43struct chl_conf *chl_get_conf()
44{
45 return &chl_conf;
46}
47
48static void chl_set_internet(struct chl_pdp *pdp)
49{
50 struct chl_conf *conf = chl_get_conf();
51 conf->internet = pdp;
52
53 CHL_INFO("New default gateway is [%s]\n", pdp->apn);
54}
55
56static bool chl_has_internet()
57{
58 struct chl_conf *conf = chl_get_conf();
59 return conf->internet != NULL;
60}
61
62static bool chl_is_internet(struct chl_pdp *pdp)
63{
64 struct chl_conf *conf = chl_get_conf();
65 return conf->internet == pdp;
66}
67
68static struct chl_pdp *chl_get_internet()
69{
70 struct chl_conf *conf = chl_get_conf();
71 return conf->internet;
72}
73
74static void chl_del_internet()
75{
76 struct chl_conf *conf = chl_get_conf();
77
78 if (conf->internet) {
79 CHL_INFO("Deleting internet pdp [%s]\n", conf->internet->apn);
80 conf->internet = NULL;
81 }
82}
83
84static int chl_del_all_routes(struct chl_client *cl)
85{
86 struct uci_context *c = NULL;
87
88 CHL_INFO("deleting all routes for [%s]\n", cl->name);
89
90 if (chl_uci_init(&c))
91 goto err;
92
93 if (chl_uci_del_spec_route(c, cl, NULL))
94 goto err;
95
96 chl_uci_done(c, true);
97 chl_network_reload();
98
99 return 0;
100err:
101 chl_uci_done(c, false);
102 CHL_ERR("chl_del_all_routes failed\n");
103 return -1;
104}
105
106static int chl_unconfig_ipv6(struct uci_context *c, struct chl_pdp *gw)
107{
108 CHL_INFO("Uconfiguring ipv6 for [%s]\n", gw->apn);
109
110 chl_uci_del_prefix(c, gw);
111
112 chl_uci_del_lan_route(c, gw);
113
114 memset(gw->gb6addr, 0, sizeof(gw->gb6addr));
115 gw->prefix_len = 0;
116 gw->ipv6_state = CHL_IPV6_IDLE;
117
118 return 0;
119}
120
121static int chl_config_ipv6(struct chl_pdp *gw)
122{
123 struct uci_context *c = NULL;
124
125 CHL_INFO("Configuring ipv6 for [%s]\n", gw->apn);
126
127 if (chl_uci_init(&c))
128 goto err;
129
130 if (chl_uci_add_prefix(c, gw))
131 goto err;
132
133 if (chl_uci_add_lan_route(c, gw))
134 goto err;
135
136 chl_uci_done(c, true);
137
138 chl_network_reload();
139
140 return 0;
141err:
142 CHL_ERR("chl_config_ipv6 failed\n");
143 chl_uci_done(c, false);
144 return -1;
145}
146
147static void __chl_poll_ipv6(struct uloop_timeout *t)
148{
149 char ccinet[MAX_IFNAME_STR];
150 char address[MAX_IPV6_STR];
151 int prefix;
152 static int retries = IPV6_POLL_RETRIES;
153
154 struct chl_conf *conf = chl_get_conf();
155 struct chl_pdp *gw = chl_get_internet();
156
157 if (!gw || gw->nw_status != DATA_AVAILABLE ||
158 gw->ipv6_state != CHL_IPV6_SEARCHING) {
159 CHL_INFO("ipv6 prefix no longer needed\n");
160 goto reset;
161 }
162
163 CHL_INFO("Searching global ipv6 address for [%s]\n", gw->apn);
164
165 if (!retries) {
166 CHL_ERR("could not find gb ipv6 after [%d] retries\n",
167 IPV6_POLL_RETRIES);
168 goto reset;
169 }
170
171 retries--;
172
173 cid_to_ccinet(gw->cid, ccinet);
174
175 if (get_global_ipv6(ccinet, address, &prefix))
176 goto retry;
177
178 CHL_INFO("found global ipv6 for [%s]: [%s/%d]\n", ccinet, address, prefix);
179
180 strcpy(gw->gb6addr, address);
181 gw->prefix_len = prefix;
182 gw->ipv6_state = CHL_IPV6_FOUND;
183
184 if (chl_config_ipv6(gw))
185 CHL_ERR("chl_add_del_ipv6 failed for [%s]\n", ccinet);
186
187reset:
188 retries = IPV6_POLL_RETRIES;
189 return;
190
191retry:
192 uloop_timeout_set(t, conf->ipv6_poll_interval);
193
194}
195
196static void chl_poll_ipv6_start(struct chl_pdp *pdp)
197{
198 pdp->ipv6_state = CHL_IPV6_SEARCHING;
199 __chl_poll_ipv6(&ip6_to);
200}
201
202static void chl_send_pdp_ind(struct chl_pdp *pdp, struct chl_client *except)
203{
204 struct chl_client *cl;
205 struct chl_indication ind;
206
207 list_for_each_entry(cl, &pdp->clients, list) {
208 if (cl == except)
209 continue;
210
211 CHL_INFO("Sending indication [%s], [%s]\n",
212 nw_status_to_str(pdp->nw_status), cl->name);
213
214 ind.id = cl->id;
215 ind.nw_status = pdp->nw_status;
216 if (chl_ubus_send_ind(true, &ind))
217 CHL_ERR("failed to send state ind for [%s]\n", cl->name);
218 }
219}
220
221
222static int chl_handle_pdp_deactivation(struct chl_pdp *pdp)
223{
224 int ril_err = 0;
225 CHL_INFO("Deactivating pdp [%s]\n", pdp->apn);
226
227 if (chl_ril_setup_data_call(pdp, false, NULL, &ril_err))
228 goto err;
229 return 0;
230err:
231 CHL_ERR("chl_handle_data_call failed\n");
232 return -1;
233}
234
235static int chl_handle_pdp_activation(struct chl_pdp *pdp)
236{
237 int retries, ril_err = 0, ret = 0;
238 Ubus_Data_Call_Response rsp;
239 struct chl_conf *conf = chl_get_conf();
240
241 CHL_INFO("Activating pdp [%s]\n", pdp->apn);
242
243 retries = conf->activation_retries;
244
245 while (retries--) {
246 ret = chl_ril_setup_data_call(pdp, true, &rsp, &ril_err);
247 if (ret == UBUS_STATUS_TIMEOUT) {
248 CHL_WARN("data call timeout, setting pdp [%s] as pending\n",
249 pdp->apn);
250 pdp->last_ril_status = PDP_FAIL_ERROR_UNSPECIFIED;
251 pdp->nw_status = DATA_PENDING;
252 goto done;
253 } else if (ret) {
254 goto err;
255 }
256
257 switch (ril_err) {
258 case RIL_E_SUCCESS:
259 break;
260 case RIL_E_OP_NOT_ALLOWED_BEFORE_REG_TO_NW:
261 pdp->last_ril_status = PDP_FAIL_DATA_REGISTRATION_FAIL;
262 pdp->nw_status = DATA_PENDING;
263 goto done;
264 case RIL_E_RADIO_NOT_AVAILABLE:
265 pdp->last_ril_status = PDP_FAIL_RADIO_POWER_OFF;
266 pdp->nw_status = DATA_PENDING;
267 goto done;
268 default:
269 pdp->last_ril_status = PDP_FAIL_ERROR_UNSPECIFIED;
270 pdp->nw_status = DATA_UNAVAILABLE;
271 goto done;
272 }
273
274 pdp->last_ril_status = rsp.status;
275
276 if (rsp.status == PDP_FAIL_NONE) {
277 chl_db_update_pdp(&rsp, pdp, DATA_AVAILABLE);
278 goto done;
279 }
280
281 if (rsp.suggestedRetryTime == INT_MAX ||
282 rsp.suggestedRetryTime == -1) {
283 CHL_ERR("pdp act failed with [%d]\n", rsp.status);
284 pdp->nw_status = DATA_UNAVAILABLE;
285 goto done;
286 } else if (rsp.suggestedRetryTime) {
287 CHL_ERR("pdp act failed with timeout [%d], err [%s]\n",
288 rsp.suggestedRetryTime,
289 data_call_fail_to_str(rsp.status));
290 pdp->nw_status = DATA_PENDING;
291 goto done;
292 } else {
293
294 CHL_ERR("Retrying to open pdp [%s] immediatly\n", pdp->apn);
295 continue;
296 }
297 }
298 pdp->nw_status = DATA_UNAVAILABLE;
299done:
300 return 0;
301err:
302 CHL_ERR("chl_handle_data_call failed\n");
303 return -1;
304}
305
306static int chl_unconfig_gw(struct chl_pdp *pdp)
307{
308 struct uci_context *c = NULL;
309
310 CHL_INFO("Unconfiguring Gateway for [%s]\n", pdp->apn);
311
312 if (chl_uci_init(&c))
313 goto err;
314
315 if (chl_uci_del_gw(c, pdp))
316 goto err;
317
318 if (pdp->ipv6_state == CHL_IPV6_FOUND)
319 chl_unconfig_ipv6(c, pdp);
320
321 chl_uci_done(c, true);
322
323 chl_network_reload();
324
325 return 0;
326err:
327 CHL_ERR("chl_unconfig_gw failed for [%d]\n", pdp->cid);
328 chl_uci_done(c, false);
329 return -1;
330}
331
332static int chl_config_gw(struct chl_pdp *pdp)
333{
334 struct uci_context *c = NULL;
335
336 CHL_INFO("Configuring Gateway for [%s]\n", pdp->apn);
337
338 if (chl_uci_init(&c))
339 goto err;
340
341 if (chl_uci_add_gw(c, pdp))
342 goto err;
343
344 if (pdp->type != IPV4)
345 chl_poll_ipv6_start(pdp);
346
347 chl_uci_done(c, true);
348
349 chl_network_reload();
350
351 return 0;
352err:
353 CHL_ERR("chl_config_gw failed for [%d]\n", pdp->cid);
354 chl_uci_done(c, false);
355 return -1;
356}
357
358static int chl_find_new_gw(struct uci_context *c, struct chl_pdp *except)
359{
360 struct chl_pdp *pdp;
361
362 CHL_INFO("Looking for new gw\n");
363
364 pdp = chl_db_get_autoconf_pdp(except);
365
366 if (!pdp)
367 return 0;
368
369 CHL_INFO("found new gw [%s]\n", pdp->apn);
370
371 if (chl_uci_add_gw(c, pdp))
372 goto err;
373
374 if (pdp->type != IPV4)
375 chl_poll_ipv6_start(pdp);
376
377 return 0;
378err:
379 CHL_ERR("chl_find_new_gw failed\n");
380 return -1;
381}
382
383static int chl_unconfig_pdp(struct chl_pdp *pdp)
384{
385 struct uci_context *c = NULL;
386
387 CHL_INFO("Unconfiguring pdp, apn [%s]\n", pdp->apn);
388
389 if (chl_uci_init(&c))
390 goto err;
391
392 if (pdp->autoconf_pdp && pdp->req_gw)
393 chl_find_new_gw(c, pdp);
394
395 chl_uci_del_addr(c, pdp);
396
397 chl_uci_del_dns(c,pdp);
398
399 chl_uci_del_dns_route(c, pdp);
400
401 if (pdp->req_gw && chl_uci_del_gw(c, pdp))
402 goto err;
403
404 if (pdp->req_gw && pdp->ipv6_state == CHL_IPV6_FOUND)
405 chl_unconfig_ipv6(c, pdp);
406
407 chl_uci_del_mask(c, pdp);
408
409 chl_uci_done(c, true);
410
411 chl_network_ifdown(pdp);
412
413 chl_network_reload();
414
415 return 0;
416err:
417 CHL_ERR("chl_unconfig_pdp failed for [%d]\n", pdp->cid);
418 chl_uci_done(c, false);
419 return -1;
420}
421
422static int chl_config_pdp(struct chl_pdp *pdp)
423{
424 struct uci_context *c = NULL;
425
426 CHL_INFO("Configuring pdp, apn [%s]\n", pdp->apn);
427
428 if (chl_uci_init(&c))
429 goto err;
430
431 if (chl_uci_add_addr(c, pdp))
432 goto err;
433
434 if (chl_uci_add_dns(c, pdp))
435 goto err;
436
437 if (chl_uci_add_dns_route(c, pdp))
438 goto err;
439
440 if (pdp->req_gw && chl_uci_add_gw(c, pdp))
441 goto err;
442
443 if (pdp->req_gw && pdp->type != IPV4)
444 chl_poll_ipv6_start(pdp);
445
446 if (chl_uci_add_mask(c, pdp))
447 goto err;
448
449 chl_uci_done(c, true);
450
451 if (chl_network_reload())
452 goto err;
453
454 chl_network_ifup(pdp);
455
456 return 0;
457err:
458 CHL_ERR("chl_config_pdp failed for [%d]\n", pdp->cid);
459 chl_uci_done(c, false);
460 return -1;
461
462}
463
464void chl_close(int id, struct chl_response *rsp)
465{
466 int org_nw_status;
467 struct chl_client *cl;
468 struct chl_pdp *pdp;
469
470
471 cl = chl_db_get_client_by_id(id);
472 if (!cl) {
473 rsp->req_status = CHL_ID_NOT_FOUND;
474 CHL_ERR("failed to get client [%d]\n", id);
475 return;
476 }
477
478 CHL_INFO("Closing client [%s]\n", cl->name);
479
480 pdp = cl->pdp;
481 org_nw_status = pdp->nw_status;
482
483 if (!cl->req_open)
484 goto done;
485
486 cl->req_open = false;
487 pdp->open_count--;
488
489 if (pdp->autoconf_pdp)
490 goto done;
491
492 if (pdp->nw_status != DATA_AVAILABLE)
493 goto clear;
494
495 if (pdp->open_count) {
496 if (cl->req_gw)
497 chl_unconfig_gw(pdp);
498 goto done;
499 }
500
501 if (chl_handle_pdp_deactivation(pdp))
502 goto err;
503
504 if (chl_unconfig_pdp(pdp))
505 goto err;
506clear:
507 chl_db_clear_pdp(pdp, DATA_UNAVAILABLE);
508done:
509 if (cl->req_gw)
510 pdp->req_gw = false;
511
512 rsp->nw_status = pdp->nw_status;
513 if (org_nw_status != pdp->nw_status)
514 chl_send_pdp_ind(pdp, cl);
515 return;
516err:
517 rsp->req_status = CHL_INTERNAL_ERROR;
518 CHL_ERR("chl_close failed for [%s]\n", cl->name);
519 chl_db_status();
520}
521
522static inline int chl_type_conflict(struct chl_pdp *pdp, struct chl_client *cl)
523{
524 if (!cl->type)
525 return 0;
526 if (pdp->type == cl->type)
527 return 0;
528 if (!(pdp->type & cl->type))
529 return 1;
530 if (pdp->type == IPV4V6)
531 return 1;
532 return 0;
533}
534
535static int chl_handle_type_conflict(struct chl_pdp *pdp, struct chl_client *cl)
536{
537
538 CHL_INFO("Ip type conflict for [%s] - [%s] != [%s]\n", cl->name,
539 ip_type_to_str(cl->type), ip_type_to_str(pdp->type));
540
541 if (pdp->nw_status != DATA_AVAILABLE)
542 return 0;
543
544 if (chl_handle_pdp_deactivation(pdp))
545 goto err;
546
547 if (chl_unconfig_pdp(pdp))
548 goto err;
549
550 pdp->type = cl->type;
551
552 chl_db_clear_pdp(pdp, DATA_UNAVAILABLE);
553
554 return 0;
555
556err:
557 CHL_ERR("chl_close failed for [%s]\n", cl->name);
558 chl_db_status();
559 return -1;
560}
561
562void chl_open(int id, struct chl_response *rsp)
563{
564 int org_nw_status;
565 struct chl_client *cl;
566 struct chl_pdp *pdp;
567
568 cl = chl_db_get_client_by_id(id);
569 if (!cl) {
570 rsp->req_status = CHL_ID_NOT_FOUND;
571 CHL_ERR("failed to get client [%d]\n", id);
572 return;
573 }
574
575 CHL_INFO("Opening client [%s]\n", cl->name);
576
577 pdp = cl->pdp;
578 org_nw_status = pdp->nw_status;
579
580 if (cl->req_open)
581 goto done;
582
583 cl->req_open = true;
584 pdp->open_count++;
585
586 /* if ip types conflict, last one to open decides on type */
587 if (chl_type_conflict(pdp, cl)) {
588 if (chl_handle_type_conflict(pdp, cl))
589 goto err;
590 } else if (pdp->autoconf_pdp) {
591 goto done;
592 } else if (pdp->open_count > 1) {
593 if (cl->req_gw) {
594 pdp->req_gw = true;
595 if (pdp->nw_status == DATA_AVAILABLE)
596 chl_config_gw(pdp);
597 }
598 goto done;
599 }
600
601 if (cl->req_gw)
602 pdp->req_gw = true;
603
604 if (chl_handle_pdp_activation(pdp))
605 goto err;
606
607 if (pdp->nw_status != DATA_AVAILABLE) {
608 if (pdp->nw_status == DATA_UNAVAILABLE)
609 rsp->req_status = RIL_ERROR_OCCURED;
610 goto done;
611 }
612
613 if (chl_config_pdp(pdp))
614 goto err;
615done:
616 rsp->ril_status = pdp->last_ril_status;
617 rsp->nw_status = pdp->nw_status;
618 if (org_nw_status != pdp->nw_status)
619 chl_send_pdp_ind(pdp, cl);
620 return;
621err:
622 rsp->req_status = CHL_INTERNAL_ERROR;
623 CHL_ERR("chl_open failed for [%s]\n", cl->name);
624 chl_db_status();
625}
626
627static void chl_retry_open_pdp(struct chl_pdp *pdp, enum chl_nw_status org)
628{
629 CHL_INFO("Retrying pdp [%s]\n", pdp->apn);
630
631 if (chl_handle_pdp_activation(pdp)) {
632 CHL_ERR("chl_handle_pdp_activation failed for cid [%d]\n",
633 pdp->cid);
634 return;
635 }
636
637 if (pdp->nw_status != DATA_AVAILABLE) {
638 CHL_INFO("pdp open failed, retry later\n");
639 goto done;
640 }
641 if (chl_config_pdp(pdp)) {
642 CHL_ERR("chl_config_pdp failed for cid [%d]\n", pdp->cid);
643 return;
644 }
645
646done:
647 if (pdp->nw_status != org)
648 chl_send_pdp_ind(pdp, NULL);
649}
650
651void chl_get_status(int id, struct chl_response *rsp)
652{
653 struct chl_client *cl;
654 struct chl_pdp *pdp;
655
656 cl = chl_db_get_client_by_id(id);
657 if (!cl) {
658 CHL_ERR("failed to get client [%d]\n", id);
659 rsp->req_status = CHL_ID_NOT_FOUND;
660 return;
661 }
662
663 pdp = cl->pdp;
664
665 rsp->nw_status = pdp->nw_status;
666
667 if (pdp->nw_status == DATA_AVAILABLE) {
668 if (pdp->type & IPV4)
669 rsp->ipv4 = pdp->ipv4;
670 if ((pdp->type & IPV6) && (pdp->ipv6_state == CHL_IPV6_FOUND))
671 rsp->ipv6 = pdp->gb6addr;
672 }
673}
674
675void chl_unregister(int id, struct chl_response *rsp)
676{
677 struct chl_client *cl;
678 struct chl_pdp *pdp;
679 struct chl_response close_rsp;
680
681 memset(&close_rsp, 0, sizeof (struct chl_response));
682 cl = chl_db_get_client_by_id(id);
683 if (!cl) {
684 rsp->req_status = CHL_ID_NOT_FOUND;
685 CHL_ERR("failed to get client [%d]\n", id);
686 return;
687 }
688
689 CHL_INFO("Unregistering client [%s]\n", cl->name);
690
691 chl_close(id, &close_rsp);
692
693 if (close_rsp.req_status)
694 goto err;
695
696 pdp = cl->pdp;
697
698
699 if (cl->req_gw && chl_is_internet(pdp))
700 chl_del_internet();
701
702 if (cl->rt_idx)
703 chl_del_all_routes(cl);
704
705 chl_db_del_client(cl);
706
707 if (!pdp->client_count) {
708 chl_db_del_pdp(pdp);
709 rsp->nw_status = DATA_UNAVAILABLE;
710 return;
711 }
712
713 rsp->nw_status = pdp->nw_status;
714 return;
715err:
716 rsp->req_status = close_rsp.req_status;
717 CHL_ERR("chl_unregister failed for [%s]\n", cl->name);
718}
719
720void chl_share_internet(struct reg_param *rp, struct chl_reg_response *rsp)
721{
722 struct chl_client *cl;
723 struct chl_pdp *internet;
724
725 CHL_INFO("Sharing internet for [%s]\n", rp->name);
726
727 internet = chl_get_internet();
728
729 if (!internet || internet->nw_status != DATA_AVAILABLE) {
730 rsp->req_status = PDP_UNAVAILABLE;
731 CHL_INFO("data unavailable for [%s]\n", rp->name);
732 return;
733 }
734
735 cl = chl_db_add_client(rp, internet);
736 if (!cl) {
737 rsp->req_status = CHL_REG_INTERNAL_ERROR;
738 CHL_ERR("chl_db_add_client failed\n");
739 return;
740 }
741
742 rsp->id = cl->id;
743 return;
744}
745
746static struct chl_client *chl_reg_exists(struct chl_pdp *pdp,
747 struct reg_param *rp,
748 struct chl_reg_response *rsp)
749{
750 enum chl_reg_req_status conflict;
751 struct chl_client *cl;
752
753 /*
754 * pdp already in database. check for extra param conflict, and
755 * add the client.
756 */
757
758 if ((conflict = pdp_match_ext_param(rp, pdp))) {
759 CHL_ERR("reg request conflicts with [%s], conflict [%d]\n",
760 rp->apn, conflict);
761 rsp->req_status = conflict;
762 goto err;
763 }
764
765 cl = chl_db_add_client(rp, pdp);
766 if (!cl) {
767 rsp->req_status = CHL_REG_INTERNAL_ERROR;
768 goto err;
769 }
770
771 memcpy(&pdp->extra, rp->ext, sizeof(struct extra_param));
772
773 if (pdp->untracked)
774 chl_db_take_over_pdp(pdp);
775
776 return cl;
777err:
778 CHL_ERR("chl_reg_gw failed for [%s]\n", rp->apn);
779 return NULL;
780}
781
782static struct chl_client *chl_reg_create(struct reg_param *rp,
783 struct chl_reg_response *rsp)
784{
785 struct chl_pdp *pdp;
786 struct chl_client *cl;
787
788 /* APN does not exist in database. add pdp and then add the client */
789
790 pdp = chl_db_add_pdp(rp);
791 if (!pdp) {
792 rsp->req_status = CHL_REG_INTERNAL_ERROR;
793 goto err;
794 }
795
796 cl = chl_db_add_client(rp, pdp);
797 if (!cl) {
798 rsp->req_status = CHL_REG_INTERNAL_ERROR;
799 chl_db_del_pdp(pdp);
800 goto err;
801 }
802
803 return cl;
804err:
805 CHL_ERR("chl_reg_create failed for [%s]\n", rp->apn);
806 return NULL;
807}
808
809void chl_register(struct reg_param *rp, struct chl_reg_response *rsp)
810{
811 struct chl_pdp *pdp = NULL;
812 struct chl_client *cl = NULL;
813 struct chl_conf *conf = chl_get_conf();
814
815 CHL_INFO("Register apn [%s], ip type [%s]\n", rp->apn,
816 ip_type_to_str(rp->ip_type));
817
818 if (rp->internet && conf->autoconf) {
819 rsp->req_status = CHL_REG_INVALID_REQ;
820 CHL_WARN("cannot request internet pdp in autoconf");
821 goto err;
822 }
823
824 if (rp->internet && chl_has_internet()) {
825 rsp->req_status = GW_EXISTS;
826 CHL_WARN("internet pdp already taken\n");
827 goto err;
828 }
829
830 pdp = chl_db_get_pdp_by_apn(rp->apn);
831 if (!pdp)
832 cl = chl_reg_create(rp, rsp);
833 else
834 cl = chl_reg_exists(pdp, rp, rsp);
835
836 if (!cl)
837 goto err;
838
839 pdp = cl->pdp;
840
841 if (rp->internet)
842 chl_set_internet(pdp);
843
844 rsp->id = cl->id;
845 return;
846err:
847 CHL_ERR("chl_register failed for [%s]\n", rp->apn);
848 return;
849}
850
851void chl_set_lte_default(struct reg_param *rp, struct chl_response *rsp)
852{
853 int ril_err = 0;
854
855 if (chl_ril_set_lte_dflt(rp, &ril_err))
856 rsp->req_status = CHL_INTERNAL_ERROR;
857 else if (ril_err)
858 rsp->req_status = LTE_DEFAULT_REQ_FAIL;
859
860 /* RIL_REQUEST_DATA_REGISTRATION_STATE here*/
861}
862
863static void chl_handle_autoconf_inactive(struct chl_pdp *pdp)
864{
865 CHL_INFO("handle_autoconf_inactive, apn [%s]\n", pdp->apn);
866
867 chl_unconfig_pdp(pdp);
868
869 if (chl_is_internet(pdp))
870 chl_del_internet();
871
872 chl_db_clear_pdp(pdp, DATA_UNAVAILABLE);
873
874 pdp->autoconf_pdp = false;
875 pdp->req_gw = false;
876
877 if (pdp->open_count)
878 chl_retry_open_pdp(pdp, DATA_AVAILABLE);
879 else if (pdp->client_count)
880 chl_send_pdp_ind(pdp, NULL);
881 else
882 chl_db_del_pdp(pdp);
883}
884
885static void chl_handle_untracked_inactive(struct chl_pdp *pdp)
886{
887
888 CHL_INFO("handle_untracked_inactive pdp, apn [%s]\n", pdp->apn);
889
890 chl_db_del_pdp(pdp);
891}
892
893static void chl_handle_inactive(struct chl_pdp *pdp)
894{
895 CHL_INFO("handle_inactive pdp, apn [%s]\n", pdp->apn);
896
897 if (pdp->untracked)
898 return chl_handle_untracked_inactive(pdp);
899
900 if (pdp->autoconf_pdp)
901 return chl_handle_autoconf_inactive(pdp);
902
903 if (pdp->nw_status != DATA_AVAILABLE) {
904 CHL_INFO("pdp already inactive [%s], cid [%d]\n",pdp->apn,
905 pdp->cid);
906 chl_db_clear_pdp(pdp, DATA_UNAVAILABLE);
907 return;
908 }
909
910 chl_unconfig_pdp(pdp);
911
912 chl_db_clear_pdp(pdp, DATA_UNAVAILABLE);
913
914 /* if pdp is still requested - retry open */
915 if (pdp->open_count)
916 chl_retry_open_pdp(pdp, DATA_AVAILABLE);
917 else
918 chl_send_pdp_ind(pdp, NULL);
919
920 return;
921}
922
923static void chl_handle_autoconf_active(Ubus_Data_Call_Response *rsp,
924 struct chl_pdp *pdp)
925{
926 struct reg_param rp;
927
928 CHL_INFO("handle_autoconf_active pdp, apn [%s]\n", rsp->apn);
929
930 if (pdp)
931 goto config;
932
933 memset(&rp, 0, sizeof(struct reg_param));
934
935 rp.apn = rsp->apn;
936 rp.ip_type = chl_ril_type_to_int(rsp->type);
937
938 pdp = chl_db_add_pdp(&rp);
939 if (!pdp) {
940 CHL_ERR("failed to add pdp for cid [%d]\n", rsp->cid);
941 return;
942 }
943config:
944 chl_db_update_pdp(rsp, pdp, DATA_AVAILABLE);
945
946 /* in autoconf - select default gw according to FIFO */
947 if (!chl_has_internet())
948 chl_set_internet(pdp);
949
950 pdp->req_gw = true;
951
952 if (chl_config_pdp(pdp)) {
953 CHL_ERR("failed to config pdp [%s]\n", rsp->apn);
954 return;
955 }
956
957 pdp->autoconf_pdp = true;
958
959 if (pdp->client_count)
960 chl_send_pdp_ind(pdp, NULL);
961
962}
963
964static void chl_handle_untracked_active(Ubus_Data_Call_Response *rsp)
965{
966 struct chl_pdp *pdp;
967 struct reg_param rp;
968
969 CHL_INFO("handle_untracked_active pdp, apn [%s]\n", rsp->apn);
970
971 memset(&rp, 0, sizeof(struct reg_param));
972
973 rp.apn = rsp->apn;
974 rp.ip_type = chl_ril_type_to_int(rsp->type);
975
976 pdp = chl_db_add_pdp(&rp);
977 if (!pdp) {
978 CHL_ERR("failed to add pdp for cid [%d]\n", rsp->cid);
979 return;
980 }
981
982 pdp->untracked = true;
983 chl_db_update_pdp(rsp, pdp, DATA_UNAVAILABLE);
984}
985
986static void chl_handle_active(Ubus_Data_Call_Response *rsp)
987{
988 struct chl_pdp *pdp;
989 struct chl_conf *conf = chl_get_conf();
990
991 CHL_INFO("handle_active pdp, apn [%s]\n", rsp->apn);
992
993 /* pdp has a matching CID - it is active in database*/
994 pdp = chl_db_get_pdp_by_cid(rsp->cid);
995 if (pdp) {
996 /* pdp changed but same cid - handle new cid here */
997 if (!str_starts_with(pdp->apn, rsp->apn)) {
998 CHL_INFO("PDP info changed! reconfigure\n");
999 goto check_apn;
1000 }
1001
1002 if (pdp->untracked) {
1003 CHL_INFO("untracked pdp is active again! [%s]\n",
1004 pdp->apn);
1005 return;
1006 }
1007
1008
1009 CHL_INFO("apn [%s] was already opened by CHL\n", pdp->apn);
1010
1011 /* copy the apn in case a suffix was added by network */
1012 strcpy(pdp->apn, rsp->apn);
1013 return;
1014 }
1015
1016 /* pdp exists in db but not active - it was registered by is not
1017 * currently open
1018 */
1019check_apn:
1020 pdp = chl_db_get_pdp_by_apn(rsp->apn);
1021 if (pdp) {
1022 CHL_INFO("[%s] pdp activated!\n", pdp->apn);
1023 if (pdp->open_count) {
1024 chl_db_update_pdp(rsp, pdp, DATA_AVAILABLE);
1025 chl_config_pdp(pdp);
1026 chl_send_pdp_ind(pdp, NULL);
1027 } else {
1028 if (conf->autoconf) {
1029 chl_handle_autoconf_active(rsp, pdp);
1030 } else {
1031 chl_db_update_pdp(rsp, pdp, DATA_UNAVAILABLE);
1032 chl_db_take_over_pdp(pdp);
1033 }
1034 }
1035 return;
1036 }
1037
1038 /* APN is not in database - create new untracked/autoconf pdp*/
1039
1040 if (conf->autoconf)
1041 chl_handle_autoconf_active(rsp, NULL);
1042 else
1043 chl_handle_untracked_active(rsp);
1044}
1045
1046void chl_handle_dcl_changed(Ubus_Data_Call_Response *pdps, int num)
1047{
1048 int i;
1049 bool found;
1050
1051 struct list_head *db;
1052 struct chl_pdp *pdp, *iter;
1053
1054 if(pdps == NULL || num == 0) {
1055 CHL_INFO("num:%d\n",num);
1056 return;
1057 }
1058
1059 for (i = 0; i < num; i++) {
1060 if (pdps[i].status == PDP_FAIL_NONE)
1061 chl_handle_active(&pdps[i]);
1062
1063 }
1064
1065 db = chl_db_get_list();
1066 list_for_each_entry_safe(pdp, iter, db, list) {
1067
1068 found = false;
1069 /* look for all pdps that are active in CHL but not in dcl */
1070 for (i = 0; i < num; i++) {
1071
1072 if (str_starts_with(pdp->apn, pdps[i].apn))
1073 found = true;
1074 }
1075
1076 if (!found)
1077 chl_handle_inactive(pdp);
1078 }
1079}
1080
1081void chl_close_all(void)
1082{
1083 struct chl_pdp *pdp;
1084 struct list_head *db = chl_db_get_list();
1085
1086 CHL_INFO("Closing all clients\n");
1087
1088 list_for_each_entry(pdp, db, list) {
1089 if (pdp->nw_status != DATA_AVAILABLE)
1090 continue;
1091 chl_handle_inactive(pdp);
1092 }
1093}
1094
1095void chl_retry_open_all(void)
1096{
1097 struct chl_pdp *pdp;
1098 struct list_head *db = chl_db_get_list();
1099
1100 list_for_each_entry(pdp, db, list) {
1101 if (pdp->nw_status == DATA_PENDING)
1102 chl_retry_open_pdp(pdp, DATA_PENDING);
1103 }
1104}
1105
1106void chl_add_del_spec_route(int id, char *ip, bool add,
1107 struct chl_response *rsp)
1108{
1109 struct chl_client *cl;
1110 struct uci_context *c = NULL;
1111
1112 cl = chl_db_get_client_by_id(id);
1113 if(!cl) {
1114 rsp->req_status = CHL_ID_NOT_FOUND;
1115 CHL_ERR("failed to get client [%d]\n", id);
1116 return;
1117 }
1118
1119 CHL_INFO("[%s] route for [%s]\n", add ? "Adding" : "Deleting", cl->name);
1120
1121 if (add && cl->pdp->nw_status != DATA_AVAILABLE) {
1122 CHL_ERR("cannot set route of on a closed PDP\n");
1123 rsp->req_status = CHL_INVALID_REQ;
1124 return;
1125 }
1126
1127 if (chl_uci_init(&c))
1128 goto err;
1129
1130
1131 if (add && chl_uci_add_spec_route(c, cl, ip))
1132 goto err;
1133 if (!add && chl_uci_del_spec_route(c, cl, ip))
1134 goto err;
1135
1136 chl_uci_done(c, true);
1137
1138 chl_network_reload();
1139
1140 rsp->nw_status = cl->pdp->nw_status;
1141 return;
1142
1143err:
1144 rsp->req_status = CHL_INTERNAL_ERROR;
1145 CHL_ERR("chl_add_del_spec_route failed for [%s]\n", cl->name);
1146 chl_uci_done(c, false);
1147}
1148
1149int main(int argc, char *argv[])
1150{
1151 int c = 0;
1152 int ret = 0;
1153 struct chl_conf *conf = chl_get_conf();
1154
1155 if (argc > 2) {
1156 CHL_ERR("invalid argument\n");
1157 exit(1);
1158 }
1159
1160 set_service_log_level(8);
1161
1162 do {
1163 c = getopt(argc, argv, "d");
1164 if (c == EOF)
1165 break;
1166 switch (c) {
1167 case 'd':
1168 set_service_log_level(ANDROID_LOG_DEBUG);
1169 break;
1170 }
1171 } while (1);
1172
1173 conf->autoconf = ml_get_property("persist.chl.autoconf");
1174
1175 set_service_log_tag("chl");
1176
1177 CHL_INFO("starting CHL with aoutoconf [%d]\n", conf->autoconf);
1178
1179 if ((ret = chl_ubus_init())) {
1180 CHL_ERR("Failed to init ubus. ret=[%d]\n", ret);
1181 exit(1);
1182 }
1183
1184 if (chl_network_register()) {
1185 CHL_ERR("Failed to register to network\n");
1186 exit(1);
1187 }
1188
1189 if (chl_ril_register()) {
1190 CHL_ERR("Failed to register to RIL\n");
1191 exit(1);
1192 }
1193
1194 if ((ret = chl_ril_enable_indications())) {
1195 CHL_ERR("Failed to enable RIL indications. ret=[%s]\n",
1196 ubus_strerror(ret));
1197 exit(1);
1198 }
1199
1200 if (chl_wait_for_sim()) {
1201 CHL_ERR("sim not ready\n");
1202 exit(1);
1203 }
1204
1205 chl_ril_request_ps_status();
1206
1207 chl_ril_request_dcl();
1208
1209 chl_ubus_run();
1210
1211 chl_ril_disable_indications();
1212 chl_ubus_exit();
1213
1214 return 0;
1215}