1515#include <zephyr/net/socket.h>
1616#include <zephyr/sys/slist.h>
1717#include <zephyr/logging/log.h>
18- #include <zephyr/posix/arpa/inet.h>
1918#include <nrf_modem_at.h>
2019#include <modem/pdn.h>
2120#include <modem/at_monitor.h>
@@ -36,15 +35,22 @@ LOG_MODULE_REGISTER(pdn, CONFIG_PDN_LOG_LEVEL);
3635#define MODEM_CFUN_NORMAL 1
3736#define MODEM_CFUN_ACTIVATE_LTE 21
3837
39- #define AT_CMD_PDN_CONTEXT_READ_IP_ADDR_STR_MAX_LEN (255)
40-
41- #define AT_CMD_PDN_CONTEXT_READ_INFO "AT+CGCONTRDP=%d"
38+ #define AT_CMD_PDN_CONTEXT_READ_INFO "AT+CGCONTRDP=%u"
4239#define AT_CMD_PDN_CONTEXT_READ_INFO_DNS_ADDR_PRIMARY_INDEX 6
4340#define AT_CMD_PDN_CONTEXT_READ_INFO_DNS_ADDR_SECONDARY_INDEX 7
4441#define AT_CMD_PDN_CONTEXT_READ_INFO_MTU_INDEX 12
4542
4643#define AT_CMD_PDN_CONTEXT_READ_RSP_DELIM "\r\n"
4744
45+ /* "+CGCONTRDP: 0,,"example.com","","","198.276.154.230","12.34.56.78",,,,,1464\r\n
46+ * +CGCONTRDP: 0,,"example.com","","","1111:2222:3:FFF::55","1111:2222:3:FFF::55",,,,,1464"
47+ */
48+ #define AT_CMD_PDN_CONTEXT_READ_INFO_PARSE_LINE1 \
49+ "+CGCONTRDP: %*u,,\"%*[^\"]\",\"\",\"\",\"%15[0-9.]\",\"%15[0-9.]\",,,,,%u"
50+ #define AT_CMD_PDN_CONTEXT_READ_INFO_PARSE_LINE2 \
51+ "+%*[^+]"\
52+ "+CGCONTRDP: %*u,,\"%*[^\"]\",\"\",\"\",\"%39[0-9A-Fa-f:]\",\"%39[0-9A-Fa-f:]\",,,,,%u"
53+
4854static K_MUTEX_DEFINE (list_mutex );
4955
5056static sys_slist_t pdn_contexts = SYS_SLIST_STATIC_INIT (& pdn_context );
@@ -633,13 +639,13 @@ int pdn_dynamic_params_get(uint8_t cid, struct in_addr *dns4_pri,
633639 unsigned int mtu ;
634640 char dns4_pri_str [INET_ADDRSTRLEN ];
635641 char dns4_sec_str [INET_ADDRSTRLEN ];
636- char at_cmd [sizeof ("AT+CGCONTRDP=10 " )];
642+ char at_cmd [sizeof ("AT+CGCONTRDP=### " )];
637643
638- if (snprintf (at_cmd , sizeof (at_cmd ), "AT+CGCONTRDP=%u" , cid ) >= sizeof (at_cmd )) {
644+ if (snprintf (at_cmd , sizeof (at_cmd ), AT_CMD_PDN_CONTEXT_READ_INFO , cid ) >= sizeof (at_cmd )) {
639645 return - E2BIG ;
640646 }
641- /* "+CGCONTRDP: 0,,"example.com","","","198.276.154.230","12.34.56.78",,,,,1464" */
642- fmt = "+CGCONTRDP: %*u,,\"%*[^\"]\",\"\",\"\",\"%15[0-9.]\",\"%15[0-9.]\",,,,,%u" ;
647+
648+ fmt = AT_CMD_PDN_CONTEXT_READ_INFO_PARSE_LINE1 ;
643649
644650 /* If IPv4 is enabled, it will be the first response line. */
645651 matched = nrf_modem_at_scanf (at_cmd , fmt , & dns4_pri_str , & dns4_sec_str , & mtu );
@@ -674,153 +680,79 @@ static int pdn_sa_family_from_ip_string(const char *src)
674680{
675681 char buf [INET6_ADDRSTRLEN ];
676682
677- if (inet_pton (AF_INET , src , buf )) {
683+ if (zsock_inet_pton (AF_INET , src , buf )) {
678684 return AF_INET ;
679- } else if (inet_pton (AF_INET6 , src , buf )) {
685+ } else if (zsock_inet_pton (AF_INET6 , src , buf )) {
680686 return AF_INET6 ;
681687 }
682688 return -1 ;
683689}
684690
685- int pdn_dynamic_info_get (uint32_t cid , struct pdn_dynamic_info * pdn_info )
691+ /** @brief Fill PDN dynamic info with DNS addresses adnd mtu. */
692+ static void pdn_dynamic_info_dns_addr_fill (struct pdn_dynamic_info * pdn_info , uint32_t mtu ,
693+ const char * dns_addr_str_primary ,
694+ const char * dns_addr_str_secondary )
686695{
687- int ret = 0 ;
688- struct at_parser parser ;
689- size_t param_str_len ;
690-
691- char * cgcontrdp_at_rsp_buf ;
692-
693- char * at_ptr ;
694- char * tmp_ptr ;
695- int lines = 0 ;
696- int iterator = 0 ;
697- char dns_addr_str [AT_CMD_PDN_CONTEXT_READ_IP_ADDR_STR_MAX_LEN ];
696+ const int family = pdn_sa_family_from_ip_string (dns_addr_str_primary );
698697
699- char at_cmd_pdn_context_read_info_cmd_str [15 ];
698+ if (family == AF_INET ) {
699+ (void )zsock_inet_pton (AF_INET , dns_addr_str_primary ,
700+ & (pdn_info -> dns_addr4_primary ));
701+ (void )zsock_inet_pton (AF_INET , dns_addr_str_secondary ,
702+ & (pdn_info -> dns_addr4_secondary ));
703+ pdn_info -> ipv4_mtu = mtu ;
704+ } else if (family == AF_INET6 ) {
705+ (void )zsock_inet_pton (AF_INET6 , dns_addr_str_primary ,
706+ & (pdn_info -> dns_addr6_primary ));
707+ (void )zsock_inet_pton (AF_INET6 , dns_addr_str_secondary ,
708+ & (pdn_info -> dns_addr6_secondary ));
709+ pdn_info -> ipv6_mtu = mtu ;
710+ }
711+ }
700712
701- int family ;
702- struct in_addr * addr ;
703- struct in6_addr * addr6 ;
713+ int pdn_dynamic_info_get (uint8_t cid , struct pdn_dynamic_info * pdn_info )
714+ {
715+ int ret ;
716+ char at_cmd_buf [sizeof ("AT+CGCONTRDP=###" )];
717+ char dns_addr_str_primary [INET6_ADDRSTRLEN ];
718+ char dns_addr_str_secondary [INET6_ADDRSTRLEN ];
719+ uint32_t mtu = 0 ;
704720
705721 if (!pdn_info ) {
706722 return - EINVAL ;
707723 }
708724
709- cgcontrdp_at_rsp_buf = k_malloc (CONFIG_PDN_DYNAMIC_INFO_AT_BUF_SIZE );
710- if (!cgcontrdp_at_rsp_buf ) {
711- LOG_ERR ("k_malloc failed for CGDCONTRDP response buffer" );
712- return - ENOMEM ;
713- }
725+ /* Reset PDN dynamic info. */
726+ memset (pdn_info , 0 , sizeof (struct pdn_dynamic_info ));
714727
715- at_ptr = cgcontrdp_at_rsp_buf ;
716- tmp_ptr = cgcontrdp_at_rsp_buf ;
728+ /* Clear secondary DNS address buffer. */
729+ memset ( dns_addr_str_secondary , 0 , sizeof ( dns_addr_str_secondary )) ;
717730
718- sprintf (at_cmd_pdn_context_read_info_cmd_str , AT_CMD_PDN_CONTEXT_READ_INFO , cid );
719- ret = nrf_modem_at_cmd (cgcontrdp_at_rsp_buf , CONFIG_PDN_DYNAMIC_INFO_AT_BUF_SIZE , "%s" ,
720- at_cmd_pdn_context_read_info_cmd_str );
721- if (ret ) {
722- LOG_ERR (
723- "nrf_modem_at_cmd returned err: %d for %s" ,
724- ret ,
725- at_cmd_pdn_context_read_info_cmd_str );
726- goto clean_exit ;
731+ (void )snprintf (at_cmd_buf , sizeof (at_cmd_buf ), AT_CMD_PDN_CONTEXT_READ_INFO , cid );
732+ ret = nrf_modem_at_scanf (at_cmd_buf , AT_CMD_PDN_CONTEXT_READ_INFO_PARSE_LINE1 ,
733+ dns_addr_str_primary , dns_addr_str_secondary , & mtu );
734+ if (ret < 1 ) {
735+ LOG_ERR ("nrf_modem_at_scanf failed, ret: %d" , ret );
736+ return ret ;
727737 }
728738
729- /* Check how many rows of info do we have */
730- while (strncmp (tmp_ptr , "OK" , 2 ) &&
731- (tmp_ptr = strstr (tmp_ptr , AT_CMD_PDN_CONTEXT_READ_RSP_DELIM )) != NULL ) {
732- tmp_ptr += 2 ;
733- lines ++ ;
734- }
739+ pdn_dynamic_info_dns_addr_fill (pdn_info , mtu , dns_addr_str_primary , dns_addr_str_secondary );
735740
736- /* Parse the response */
737- ret = at_parser_init (& parser , at_ptr );
738- if (ret ) {
739- LOG_ERR ("Could not init AT parser for %s, error: %d\n" ,
740- at_cmd_pdn_context_read_info_cmd_str , ret );
741- goto clean_exit ;
742- }
741+ /* Reset secondary DNS address buffer and mtu. */
742+ memset (dns_addr_str_secondary , 0 , sizeof (dns_addr_str_secondary ));
743+ mtu = 0 ;
743744
744- parse :
745- /* Read primary DNS address */
746- param_str_len = sizeof (dns_addr_str );
747- ret = at_parser_string_get (
748- & parser ,
749- AT_CMD_PDN_CONTEXT_READ_INFO_DNS_ADDR_PRIMARY_INDEX ,
750- dns_addr_str , & param_str_len );
751- if (ret ) {
752- LOG_ERR ("Could not parse dns str for cid %d, err: %d" , cid , ret );
753- goto clean_exit ;
745+ /* Scan second line if PDN has dual stack capabilities. */
746+ ret = nrf_modem_at_scanf (at_cmd_buf , AT_CMD_PDN_CONTEXT_READ_INFO_PARSE_LINE2 ,
747+ dns_addr_str_primary , dns_addr_str_secondary , & mtu );
748+ if (ret < 1 ) {
749+ /* We only got one entry, but that is ok. */
750+ return 0 ;
754751 }
755- dns_addr_str [param_str_len ] = '\0' ;
756752
757- family = pdn_sa_family_from_ip_string ( dns_addr_str );
753+ pdn_dynamic_info_dns_addr_fill ( pdn_info , mtu , dns_addr_str_primary , dns_addr_str_secondary );
758754
759- if (family == AF_INET ) {
760- addr = & (pdn_info -> dns_addr4_primary );
761- (void )inet_pton (AF_INET , dns_addr_str , addr );
762- } else if (family == AF_INET6 ) {
763- addr6 = & (pdn_info -> dns_addr6_primary );
764- (void )inet_pton (AF_INET6 , dns_addr_str , addr6 );
765- }
766-
767- /* Read secondary DNS address */
768- param_str_len = sizeof (dns_addr_str );
769-
770- ret = at_parser_string_get (
771- & parser ,
772- AT_CMD_PDN_CONTEXT_READ_INFO_DNS_ADDR_SECONDARY_INDEX ,
773- dns_addr_str , & param_str_len );
774- if (ret ) {
775- LOG_ERR ("Could not parse dns str, err: %d" , ret );
776- goto clean_exit ;
777- }
778- dns_addr_str [param_str_len ] = '\0' ;
779-
780- family = pdn_sa_family_from_ip_string (dns_addr_str );
781-
782- if (family == AF_INET ) {
783- addr = & (pdn_info -> dns_addr4_secondary );
784- (void )inet_pton (AF_INET , dns_addr_str , addr );
785- } else if (family == AF_INET6 ) {
786- addr6 = & (pdn_info -> dns_addr6_secondary );
787- (void )inet_pton (AF_INET6 , dns_addr_str , addr6 );
788- }
789-
790- /* Read link MTU if exists:
791- * AT command spec:
792- * Note: If the PDN connection has dual stack capabilities, at least one pair of
793- * lines with information is returned per <cid>: First one line with the IPv4
794- * parameters followed by one line with the IPv6 parameters.
795- */
796- if (iterator == 1 ) {
797- ret = at_parser_num_get (& parser , AT_CMD_PDN_CONTEXT_READ_INFO_MTU_INDEX ,
798- & (pdn_info -> ipv6_mtu ));
799- if (ret ) {
800- /* Don't care if it fails */
801- ret = 0 ;
802- pdn_info -> ipv6_mtu = 0 ;
803- }
804- } else {
805- ret = at_parser_num_get (& parser , AT_CMD_PDN_CONTEXT_READ_INFO_MTU_INDEX ,
806- & (pdn_info -> ipv4_mtu ));
807- if (ret ) {
808- /* Don't care if it fails */
809- ret = 0 ;
810- pdn_info -> ipv4_mtu = 0 ;
811- }
812- }
813-
814- if (at_parser_cmd_next (& parser ) == 0 ) {
815- iterator ++ ;
816- if (iterator < lines ) {
817- goto parse ;
818- }
819- }
820-
821- clean_exit :
822- k_free (cgcontrdp_at_rsp_buf );
823- return ret ;
755+ return 0 ;
824756}
825757
826758int pdn_default_apn_get (char * buf , size_t len )
0 commit comments