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