blob: ccf36b99e727f944c6c7e6b04984407decd98c5f [file] [log] [blame]
Harald Welte908085c2014-10-01 16:18:11 +08001#include <stdio.h>
2#include <stdint.h>
3#include <stdlib.h>
4#include <string.h>
5
6#include <osmocom/gsm/apn.h>
7
8#define APN_OI_GPRS_FMT "mnc%03u.mcc%03u.gprs"
9#define APN_GPRS_FMT "%s.mnc%03u.mcc%03u.gprs"
10
11static char apn_strbuf[APN_MAXLEN+1];
12
13char *osmo_apn_qualify(unsigned int mcc, unsigned int mnc, const char *ni)
14{
15 snprintf(apn_strbuf, sizeof(apn_strbuf)-1, APN_GPRS_FMT,
16 ni, mnc, mcc);
17 apn_strbuf[sizeof(apn_strbuf)-1] = '\0';
18
19 return apn_strbuf;
20}
21
22char *osmo_apn_qualify_from_imsi(const char *imsi,
23 const char *ni, int have_3dig_mnc)
24{
25 char cbuf[3+1], nbuf[3+1];
26
27 strncpy(cbuf, imsi, 3);
28 cbuf[3] = '\0';
29
30 if (have_3dig_mnc) {
31 strncpy(nbuf, imsi+3, 3);
32 nbuf[3] = '\0';
33 } else {
34 strncpy(nbuf, imsi+3, 2);
35 nbuf[2] = '\0';
36 }
37 return osmo_apn_qualify(atoi(cbuf), atoi(nbuf), ni);
38}
Jacob Erlbeck81142942015-11-17 08:42:05 +010039
40/**
41 * Convert an encoded APN into a dot-separated string.
42 *
43 * \param out_str the destination buffer (size must be >= max(app_enc_len,1))
44 * \param apn_enc the encoded APN
45 * \param apn_enc_len the length of the encoded APN
46 *
47 * \returns out_str on success and NULL otherwise
48 */
49char * osmo_apn_to_str(char *out_str, const uint8_t *apn_enc, size_t apn_enc_len)
50{
51 char *str = out_str;
52 size_t rest_chars = apn_enc_len;
53
54 while (rest_chars > 0 && apn_enc[0]) {
55 size_t label_size = apn_enc[0];
56 if (label_size + 1 > rest_chars)
57 return NULL;
58
59 memmove(str, apn_enc + 1, label_size);
60 str += label_size;
61 rest_chars -= label_size + 1;
62 apn_enc += label_size + 1;
63
64 if (rest_chars)
65 *(str++) = '.';
66 }
67 str[0] = '\0';
68
69 return out_str;
70}
71
72/**
73 * Convert a dot-separated string into an encoded APN.
74 *
75 * \param apn_enc the encoded APN
76 * \param max_apn_enc_len the size of the apn_enc buffer
77 * \param str the source string
78 *
79 * \returns out_str on success and NULL otherwise
80 */
81int osmo_apn_from_str(uint8_t *apn_enc, size_t max_apn_enc_len, const char *str)
82{
83 uint8_t *last_len_field;
84 int len;
85
86 /* Can we even write the length field to the output? */
87 if (max_apn_enc_len == 0)
88 return -1;
89
90 /* Remember where we need to put the length once we know it */
91 last_len_field = apn_enc;
92 len = 1;
93 apn_enc += 1;
94
95 while (str[0]) {
96 if (len >= max_apn_enc_len)
97 return -1;
98
99 if (str[0] == '.') {
100 *last_len_field = (apn_enc - last_len_field) - 1;
101 last_len_field = apn_enc;
102 } else {
103 *apn_enc = str[0];
104 }
105 apn_enc += 1;
106 str += 1;
107 len += 1;
108 }
109
110 *last_len_field = (apn_enc - last_len_field) - 1;
111
112 return len;
113}