Upgrade ofono to 1.2
[profile/ivi/ofono.git] / gatchat / ppp_ipcp.c
1 /*
2  *
3  *  PPP library with GLib integration
4  *
5  *  Copyright (C) 2009-2011  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program 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
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <fcntl.h>
28 #include <unistd.h>
29 #include <string.h>
30 #include <termios.h>
31 #include <arpa/inet.h>
32 #include <glib.h>
33
34 #include "gatutil.h"
35 #include "gatppp.h"
36 #include "ppp.h"
37
38 #define IPCP_SUPPORTED_CODES    ((1 << PPPCP_CODE_TYPE_CONFIGURE_REQUEST) | \
39                                 (1 << PPPCP_CODE_TYPE_CONFIGURE_ACK) | \
40                                 (1 << PPPCP_CODE_TYPE_CONFIGURE_NAK) | \
41                                 (1 << PPPCP_CODE_TYPE_CONFIGURE_REJECT) | \
42                                 (1 << PPPCP_CODE_TYPE_TERMINATE_REQUEST) | \
43                                 (1 << PPPCP_CODE_TYPE_TERMINATE_ACK) | \
44                                 (1 << PPPCP_CODE_TYPE_CODE_REJECT))
45
46 enum ipcp_option_types {
47         IP_ADDRESSES            = 1,
48         IP_COMPRESSION_PROTO    = 2,
49         IP_ADDRESS              = 3,
50         MOBILE_IPV4             = 4,
51         PRIMARY_DNS_SERVER      = 129,
52         PRIMARY_NBNS_SERVER     = 130,
53         SECONDARY_DNS_SERVER    = 131,
54         SECONDARY_NBNS_SERVER   = 132,
55 };
56
57 /* We request IP_ADDRESS, PRIMARY/SECONDARY DNS & NBNS */
58 #define MAX_CONFIG_OPTION_SIZE 5*6
59
60 #define REQ_OPTION_IPADDR       0x01
61 #define REQ_OPTION_DNS1         0x02
62 #define REQ_OPTION_DNS2         0x04
63 #define REQ_OPTION_NBNS1        0x08
64 #define REQ_OPTION_NBNS2        0x10
65
66 #define MAX_IPCP_FAILURE        100
67
68 struct ipcp_data {
69         guint8 options[MAX_CONFIG_OPTION_SIZE];
70         guint16 options_len;
71         guint8 req_options;
72         guint32 local_addr;
73         guint32 peer_addr;
74         guint32 dns1;
75         guint32 dns2;
76         guint32 nbns1;
77         guint32 nbns2;
78         gboolean is_server;
79 };
80
81 #define FILL_IP(options, req, type, var)                \
82         if (req) {                                      \
83                 options[len] = type;                    \
84                 options[len + 1] = 6;                   \
85                 memcpy(options + len + 2, var, 4);      \
86                                                         \
87                 len += 6;                               \
88         }                                               \
89
90 static void ipcp_generate_config_options(struct ipcp_data *ipcp)
91 {
92         guint16 len = 0;
93
94         FILL_IP(ipcp->options, ipcp->req_options & REQ_OPTION_IPADDR,
95                                         IP_ADDRESS, &ipcp->local_addr);
96         FILL_IP(ipcp->options, ipcp->req_options & REQ_OPTION_DNS1,
97                                         PRIMARY_DNS_SERVER, &ipcp->dns1);
98         FILL_IP(ipcp->options, ipcp->req_options & REQ_OPTION_DNS2,
99                                         SECONDARY_DNS_SERVER, &ipcp->dns2);
100         FILL_IP(ipcp->options, ipcp->req_options & REQ_OPTION_NBNS1,
101                                         PRIMARY_NBNS_SERVER, &ipcp->nbns1);
102         FILL_IP(ipcp->options, ipcp->req_options & REQ_OPTION_NBNS2,
103                                         SECONDARY_NBNS_SERVER, &ipcp->nbns2);
104
105         ipcp->options_len = len;
106 }
107
108 static void ipcp_reset_client_config_options(struct ipcp_data *ipcp)
109 {
110         ipcp->req_options = REQ_OPTION_IPADDR | REQ_OPTION_DNS1 |
111                                 REQ_OPTION_DNS2 | REQ_OPTION_NBNS1 |
112                                 REQ_OPTION_NBNS2;
113
114         ipcp->local_addr = 0;
115         ipcp->peer_addr = 0;
116         ipcp->dns1 = 0;
117         ipcp->dns2 = 0;
118         ipcp->nbns1 = 0;
119         ipcp->nbns2 = 0;
120
121         ipcp_generate_config_options(ipcp);
122 }
123
124 static void ipcp_reset_server_config_options(struct ipcp_data *ipcp)
125 {
126         if (ipcp->local_addr != 0)
127                 ipcp->req_options = REQ_OPTION_IPADDR;
128         else
129                 ipcp->req_options = 0;
130
131         ipcp_generate_config_options(ipcp);
132 }
133
134 void ipcp_set_server_info(struct pppcp_data *pppcp, guint32 peer_addr,
135                                 guint32 dns1, guint32 dns2)
136 {
137         struct ipcp_data *ipcp = pppcp_get_data(pppcp);
138
139         ipcp->peer_addr = peer_addr;
140         ipcp->dns1 = dns1;
141         ipcp->dns2 = dns2;
142 }
143
144 static void ipcp_up(struct pppcp_data *pppcp)
145 {
146         struct ipcp_data *ipcp = pppcp_get_data(pppcp);
147         char local[INET_ADDRSTRLEN];
148         char peer[INET_ADDRSTRLEN];
149         char dns1[INET_ADDRSTRLEN];
150         char dns2[INET_ADDRSTRLEN];
151         struct in_addr addr;
152
153         memset(local, 0, sizeof(local));
154         addr.s_addr = ipcp->local_addr;
155         inet_ntop(AF_INET, &addr, local, INET_ADDRSTRLEN);
156
157         memset(peer, 0, sizeof(peer));
158         addr.s_addr = ipcp->peer_addr;
159         inet_ntop(AF_INET, &addr, peer, INET_ADDRSTRLEN);
160
161         memset(dns1, 0, sizeof(dns1));
162         addr.s_addr = ipcp->dns1;
163         inet_ntop(AF_INET, &addr, dns1, INET_ADDRSTRLEN);
164
165         memset(dns2, 0, sizeof(dns2));
166         addr.s_addr = ipcp->dns2;
167         inet_ntop(AF_INET, &addr, dns2, INET_ADDRSTRLEN);
168
169         ppp_ipcp_up_notify(pppcp_get_ppp(pppcp), local[0] ? local : NULL,
170                                         peer[0] ? peer : NULL,
171                                         dns1[0] ? dns1 : NULL,
172                                         dns2[0] ? dns2 : NULL);
173 }
174
175 static void ipcp_down(struct pppcp_data *pppcp)
176 {
177         struct ipcp_data *ipcp = pppcp_get_data(pppcp);
178
179         if (ipcp->is_server)
180                 ipcp_reset_server_config_options(ipcp);
181         else
182                 ipcp_reset_client_config_options(ipcp);
183
184         pppcp_set_local_options(pppcp, ipcp->options, ipcp->options_len);
185         ppp_ipcp_down_notify(pppcp_get_ppp(pppcp));
186 }
187
188 static void ipcp_finished(struct pppcp_data *pppcp)
189 {
190         ppp_ipcp_finished_notify(pppcp_get_ppp(pppcp));
191 }
192
193 static void ipcp_rca(struct pppcp_data *pppcp,
194                                         const struct pppcp_packet *packet)
195 {
196         struct ipcp_data *ipcp = pppcp_get_data(pppcp);
197         struct ppp_option_iter iter;
198
199         if (ipcp->is_server)
200                 return;
201
202         ppp_option_iter_init(&iter, packet);
203
204         while (ppp_option_iter_next(&iter) == TRUE) {
205                 const guint8 *data = ppp_option_iter_get_data(&iter);
206
207                 switch (ppp_option_iter_get_type(&iter)) {
208                 case IP_ADDRESS:
209                         memcpy(&ipcp->local_addr, data, 4);
210                         break;
211                 case PRIMARY_DNS_SERVER:
212                         memcpy(&ipcp->dns1, data, 4);
213                         break;
214                 case PRIMARY_NBNS_SERVER:
215                         memcpy(&ipcp->nbns1, data, 4);
216                         break;
217                 case SECONDARY_DNS_SERVER:
218                         memcpy(&ipcp->dns2, data, 4);
219                         break;
220                 case SECONDARY_NBNS_SERVER:
221                         memcpy(&ipcp->nbns2, data, 4);
222                         break;
223                 default:
224                         break;
225                 }
226         }
227 }
228
229 static void ipcp_rcn_nak(struct pppcp_data *pppcp,
230                                 const struct pppcp_packet *packet)
231 {
232         struct ipcp_data *ipcp = pppcp_get_data(pppcp);
233         struct ppp_option_iter iter;
234
235         if (ipcp->is_server)
236                 return;
237
238         ppp_option_iter_init(&iter, packet);
239
240         while (ppp_option_iter_next(&iter) == TRUE) {
241                 const guint8 *data = ppp_option_iter_get_data(&iter);
242
243                 switch (ppp_option_iter_get_type(&iter)) {
244                 case IP_ADDRESS:
245                         ipcp->req_options |= REQ_OPTION_IPADDR;
246                         memcpy(&ipcp->local_addr, data, 4);
247                         break;
248                 case PRIMARY_DNS_SERVER:
249                         ipcp->req_options |= REQ_OPTION_DNS1;
250                         memcpy(&ipcp->dns1, data, 4);
251                         break;
252                 case PRIMARY_NBNS_SERVER:
253                         ipcp->req_options |= REQ_OPTION_NBNS1;
254                         memcpy(&ipcp->nbns1, data, 4);
255                         break;
256                 case SECONDARY_DNS_SERVER:
257                         ipcp->req_options |= REQ_OPTION_DNS2;
258                         memcpy(&ipcp->dns2, data, 4);
259                         break;
260                 case SECONDARY_NBNS_SERVER:
261                         ipcp->req_options |= REQ_OPTION_NBNS2;
262                         memcpy(&ipcp->nbns2, data, 4);
263                         break;
264                 default:
265                         break;
266                 }
267         }
268
269         ipcp_generate_config_options(ipcp);
270         pppcp_set_local_options(pppcp, ipcp->options, ipcp->options_len);
271 }
272
273 static void ipcp_rcn_rej(struct pppcp_data *pppcp,
274                                 const struct pppcp_packet *packet)
275 {
276         struct ipcp_data *ipcp = pppcp_get_data(pppcp);
277         struct ppp_option_iter iter;
278
279         ppp_option_iter_init(&iter, packet);
280
281         while (ppp_option_iter_next(&iter) == TRUE) {
282                 switch (ppp_option_iter_get_type(&iter)) {
283                 case IP_ADDRESS:
284                         ipcp->req_options &= ~REQ_OPTION_IPADDR;
285                         break;
286                 case PRIMARY_DNS_SERVER:
287                         ipcp->req_options &= ~REQ_OPTION_DNS1;
288                         break;
289                 case PRIMARY_NBNS_SERVER:
290                         ipcp->req_options &= ~REQ_OPTION_NBNS1;
291                         break;
292                 case SECONDARY_DNS_SERVER:
293                         ipcp->req_options &= ~REQ_OPTION_DNS2;
294                         break;
295                 case SECONDARY_NBNS_SERVER:
296                         ipcp->req_options &= ~REQ_OPTION_NBNS2;
297                         break;
298                 default:
299                         break;
300                 }
301         }
302
303         ipcp_generate_config_options(ipcp);
304         pppcp_set_local_options(pppcp, ipcp->options, ipcp->options_len);
305 }
306
307 static enum rcr_result ipcp_server_rcr(struct ipcp_data *ipcp,
308                                         const struct pppcp_packet *packet,
309                                         guint8 **new_options, guint16 *new_len)
310 {
311         struct ppp_option_iter iter;
312         guint8 nak_options[MAX_CONFIG_OPTION_SIZE];
313         guint16 len = 0;
314         guint8 *rej_options = NULL;
315         guint16 rej_len = 0;
316         guint32 addr;
317
318         ppp_option_iter_init(&iter, packet);
319
320         while (ppp_option_iter_next(&iter) == TRUE) {
321                 const guint8 *data = ppp_option_iter_get_data(&iter);
322                 guint8 type = ppp_option_iter_get_type(&iter);
323
324                 switch (type) {
325                 case IP_ADDRESS:
326                         memcpy(&addr, data, 4);
327
328                         FILL_IP(nak_options,
329                                         addr != ipcp->peer_addr || addr == 0,
330                                         type, &ipcp->peer_addr);
331                         break;
332                 case PRIMARY_DNS_SERVER:
333                         memcpy(&addr, data, 4);
334
335                         FILL_IP(nak_options, addr != ipcp->dns1 || addr == 0,
336                                         type, &ipcp->dns1);
337                         break;
338                 case SECONDARY_DNS_SERVER:
339                         memcpy(&addr, data, 4);
340
341                         FILL_IP(nak_options, addr != ipcp->dns2 || addr == 0,
342                                         type, &ipcp->dns2);
343                         break;
344                 default:
345                         /* Reject */
346                         if (rej_options == NULL) {
347                                 guint16 max_len = ntohs(packet->length) - 4;
348                                 rej_options = g_new0(guint8, max_len);
349                         }
350
351                         if (rej_options != NULL) {
352                                 guint8 opt_len =
353                                         ppp_option_iter_get_length(&iter);
354
355                                 rej_options[rej_len] = type;
356                                 rej_options[rej_len + 1] = opt_len + 2;
357                                 memcpy(rej_options + rej_len + 2,
358                                                                 data, opt_len);
359                                 rej_len += opt_len + 2;
360                         }
361                         break;
362                 }
363         }
364
365         if (rej_len > 0) {
366                 *new_len = rej_len;
367                 *new_options = rej_options;
368
369                 return RCR_REJECT;
370         }
371
372         if (len > 0) {
373                 *new_len = len;
374                 *new_options = g_memdup(nak_options, len);
375
376                 return RCR_NAK;
377         }
378
379         return RCR_ACCEPT;
380 }
381
382 static enum rcr_result ipcp_client_rcr(struct ipcp_data *ipcp,
383                                         const struct pppcp_packet *packet,
384                                         guint8 **new_options, guint16 *new_len)
385 {
386         guint8 *options = NULL;
387         struct ppp_option_iter iter;
388         guint8 len = 0;
389
390         ppp_option_iter_init(&iter, packet);
391
392         while (ppp_option_iter_next(&iter) == TRUE) {
393                 const guint8 *data = ppp_option_iter_get_data(&iter);
394                 guint8 type = ppp_option_iter_get_type(&iter);
395
396                 switch (type) {
397                 case IP_ADDRESS:
398                         memcpy(&ipcp->peer_addr, data, 4);
399
400                         if (ipcp->peer_addr != 0)
401                                 break;
402
403                         /*
404                          * Fall through, reject IP_ADDRESS if peer sends
405                          * us 0 (expecting us to provide its IP address)
406                          */
407                 default:
408                         if (options == NULL) {
409                                 guint16 max_len = ntohs(packet->length) - 4;
410                                 options = g_new0(guint8, max_len);
411                         }
412
413                         if (options != NULL) {
414                                 guint8 opt_len =
415                                         ppp_option_iter_get_length(&iter);
416
417                                 options[len] = type;
418                                 options[len + 1] = opt_len + 2;
419                                 memcpy(options + len + 2, data, opt_len);
420                                 len += opt_len + 2;
421                         }
422
423                         break;
424                 }
425         }
426
427         if (len > 0) {
428                 *new_len = len;
429                 *new_options = options;
430
431                 return RCR_REJECT;
432         }
433
434         return RCR_ACCEPT;
435 }
436
437 static enum rcr_result ipcp_rcr(struct pppcp_data *pppcp,
438                                         const struct pppcp_packet *packet,
439                                         guint8 **new_options, guint16 *new_len)
440 {
441         struct ipcp_data *ipcp = pppcp_get_data(pppcp);
442
443         if (ipcp->is_server)
444                 return ipcp_server_rcr(ipcp, packet, new_options, new_len);
445         else
446                 return ipcp_client_rcr(ipcp, packet, new_options, new_len);
447 }
448
449 struct pppcp_proto ipcp_proto = {
450         .proto                  = IPCP_PROTO,
451         .name                   = "ipcp",
452         .supported_codes        = IPCP_SUPPORTED_CODES,
453         .this_layer_up          = ipcp_up,
454         .this_layer_down        = ipcp_down,
455         .this_layer_finished    = ipcp_finished,
456         .rca                    = ipcp_rca,
457         .rcn_nak                = ipcp_rcn_nak,
458         .rcn_rej                = ipcp_rcn_rej,
459         .rcr                    = ipcp_rcr,
460 };
461
462 struct pppcp_data *ipcp_new(GAtPPP *ppp, gboolean is_server, guint32 ip)
463 {
464         struct ipcp_data *ipcp;
465         struct pppcp_data *pppcp;
466
467         ipcp = g_try_new0(struct ipcp_data, 1);
468         if (ipcp == NULL)
469                 return NULL;
470
471         /*
472          * Some 3G modems use repeated IPCP NAKs as the way of stalling
473          * util sending us the client IP address. So we increase the
474          * default number of NAKs we accept before start treating them
475          * as rejects.
476          */
477         pppcp = pppcp_new(ppp, &ipcp_proto, FALSE, MAX_IPCP_FAILURE);
478         if (pppcp == NULL) {
479                 g_free(ipcp);
480                 return NULL;
481         }
482
483         pppcp_set_data(pppcp, ipcp);
484         ipcp->is_server = is_server;
485
486         if (is_server) {
487                 ipcp->local_addr = ip;
488                 ipcp_reset_server_config_options(ipcp);
489         } else
490                 ipcp_reset_client_config_options(ipcp);
491
492         pppcp_set_local_options(pppcp, ipcp->options, ipcp->options_len);
493
494         return pppcp;
495 }
496
497 void ipcp_free(struct pppcp_data *data)
498 {
499         struct ipcp_data *ipcp = pppcp_get_data(data);
500
501         g_free(ipcp);
502         pppcp_free(data);
503 }