3 * PPP library with GLib integration
5 * Copyright (C) 2009-2011 Intel Corporation. All rights reserved.
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.
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.
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
31 #include <arpa/inet.h>
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))
46 enum ipcp_option_types {
48 IP_COMPRESSION_PROTO = 2,
51 PRIMARY_DNS_SERVER = 129,
52 PRIMARY_NBNS_SERVER = 130,
53 SECONDARY_DNS_SERVER = 131,
54 SECONDARY_NBNS_SERVER = 132,
57 /* We request IP_ADDRESS, PRIMARY/SECONDARY DNS & NBNS */
58 #define MAX_CONFIG_OPTION_SIZE 5*6
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
66 #define MAX_IPCP_FAILURE 100
69 guint8 options[MAX_CONFIG_OPTION_SIZE];
81 #define FILL_IP(options, req, type, var) \
83 options[len] = type; \
84 options[len + 1] = 6; \
85 memcpy(options + len + 2, var, 4); \
90 static void ipcp_generate_config_options(struct ipcp_data *ipcp)
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);
105 ipcp->options_len = len;
108 static void ipcp_reset_client_config_options(struct ipcp_data *ipcp)
110 ipcp->req_options = REQ_OPTION_IPADDR | REQ_OPTION_DNS1 |
111 REQ_OPTION_DNS2 | REQ_OPTION_NBNS1 |
114 ipcp->local_addr = 0;
121 ipcp_generate_config_options(ipcp);
124 static void ipcp_reset_server_config_options(struct ipcp_data *ipcp)
126 if (ipcp->local_addr != 0)
127 ipcp->req_options = REQ_OPTION_IPADDR;
129 ipcp->req_options = 0;
131 ipcp_generate_config_options(ipcp);
134 void ipcp_set_server_info(struct pppcp_data *pppcp, guint32 peer_addr,
135 guint32 dns1, guint32 dns2)
137 struct ipcp_data *ipcp = pppcp_get_data(pppcp);
139 ipcp->peer_addr = peer_addr;
144 static void ipcp_up(struct pppcp_data *pppcp)
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];
153 memset(local, 0, sizeof(local));
154 addr.s_addr = ipcp->local_addr;
155 inet_ntop(AF_INET, &addr, local, INET_ADDRSTRLEN);
157 memset(peer, 0, sizeof(peer));
158 addr.s_addr = ipcp->peer_addr;
159 inet_ntop(AF_INET, &addr, peer, INET_ADDRSTRLEN);
161 memset(dns1, 0, sizeof(dns1));
162 addr.s_addr = ipcp->dns1;
163 inet_ntop(AF_INET, &addr, dns1, INET_ADDRSTRLEN);
165 memset(dns2, 0, sizeof(dns2));
166 addr.s_addr = ipcp->dns2;
167 inet_ntop(AF_INET, &addr, dns2, INET_ADDRSTRLEN);
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);
175 static void ipcp_down(struct pppcp_data *pppcp)
177 struct ipcp_data *ipcp = pppcp_get_data(pppcp);
180 ipcp_reset_server_config_options(ipcp);
182 ipcp_reset_client_config_options(ipcp);
184 pppcp_set_local_options(pppcp, ipcp->options, ipcp->options_len);
185 ppp_ipcp_down_notify(pppcp_get_ppp(pppcp));
188 static void ipcp_finished(struct pppcp_data *pppcp)
190 ppp_ipcp_finished_notify(pppcp_get_ppp(pppcp));
193 static void ipcp_rca(struct pppcp_data *pppcp,
194 const struct pppcp_packet *packet)
196 struct ipcp_data *ipcp = pppcp_get_data(pppcp);
197 struct ppp_option_iter iter;
202 ppp_option_iter_init(&iter, packet);
204 while (ppp_option_iter_next(&iter) == TRUE) {
205 const guint8 *data = ppp_option_iter_get_data(&iter);
207 switch (ppp_option_iter_get_type(&iter)) {
209 memcpy(&ipcp->local_addr, data, 4);
211 case PRIMARY_DNS_SERVER:
212 memcpy(&ipcp->dns1, data, 4);
214 case PRIMARY_NBNS_SERVER:
215 memcpy(&ipcp->nbns1, data, 4);
217 case SECONDARY_DNS_SERVER:
218 memcpy(&ipcp->dns2, data, 4);
220 case SECONDARY_NBNS_SERVER:
221 memcpy(&ipcp->nbns2, data, 4);
229 static void ipcp_rcn_nak(struct pppcp_data *pppcp,
230 const struct pppcp_packet *packet)
232 struct ipcp_data *ipcp = pppcp_get_data(pppcp);
233 struct ppp_option_iter iter;
238 ppp_option_iter_init(&iter, packet);
240 while (ppp_option_iter_next(&iter) == TRUE) {
241 const guint8 *data = ppp_option_iter_get_data(&iter);
243 switch (ppp_option_iter_get_type(&iter)) {
245 ipcp->req_options |= REQ_OPTION_IPADDR;
246 memcpy(&ipcp->local_addr, data, 4);
248 case PRIMARY_DNS_SERVER:
249 ipcp->req_options |= REQ_OPTION_DNS1;
250 memcpy(&ipcp->dns1, data, 4);
252 case PRIMARY_NBNS_SERVER:
253 ipcp->req_options |= REQ_OPTION_NBNS1;
254 memcpy(&ipcp->nbns1, data, 4);
256 case SECONDARY_DNS_SERVER:
257 ipcp->req_options |= REQ_OPTION_DNS2;
258 memcpy(&ipcp->dns2, data, 4);
260 case SECONDARY_NBNS_SERVER:
261 ipcp->req_options |= REQ_OPTION_NBNS2;
262 memcpy(&ipcp->nbns2, data, 4);
269 ipcp_generate_config_options(ipcp);
270 pppcp_set_local_options(pppcp, ipcp->options, ipcp->options_len);
273 static void ipcp_rcn_rej(struct pppcp_data *pppcp,
274 const struct pppcp_packet *packet)
276 struct ipcp_data *ipcp = pppcp_get_data(pppcp);
277 struct ppp_option_iter iter;
279 ppp_option_iter_init(&iter, packet);
281 while (ppp_option_iter_next(&iter) == TRUE) {
282 switch (ppp_option_iter_get_type(&iter)) {
284 ipcp->req_options &= ~REQ_OPTION_IPADDR;
286 case PRIMARY_DNS_SERVER:
287 ipcp->req_options &= ~REQ_OPTION_DNS1;
289 case PRIMARY_NBNS_SERVER:
290 ipcp->req_options &= ~REQ_OPTION_NBNS1;
292 case SECONDARY_DNS_SERVER:
293 ipcp->req_options &= ~REQ_OPTION_DNS2;
295 case SECONDARY_NBNS_SERVER:
296 ipcp->req_options &= ~REQ_OPTION_NBNS2;
303 ipcp_generate_config_options(ipcp);
304 pppcp_set_local_options(pppcp, ipcp->options, ipcp->options_len);
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)
311 struct ppp_option_iter iter;
312 guint8 nak_options[MAX_CONFIG_OPTION_SIZE];
314 guint8 *rej_options = NULL;
318 ppp_option_iter_init(&iter, packet);
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);
326 memcpy(&addr, data, 4);
329 addr != ipcp->peer_addr || addr == 0,
330 type, &ipcp->peer_addr);
332 case PRIMARY_DNS_SERVER:
333 memcpy(&addr, data, 4);
335 FILL_IP(nak_options, addr != ipcp->dns1 || addr == 0,
338 case SECONDARY_DNS_SERVER:
339 memcpy(&addr, data, 4);
341 FILL_IP(nak_options, addr != ipcp->dns2 || addr == 0,
346 if (rej_options == NULL) {
347 guint16 max_len = ntohs(packet->length) - 4;
348 rej_options = g_new0(guint8, max_len);
351 if (rej_options != NULL) {
353 ppp_option_iter_get_length(&iter);
355 rej_options[rej_len] = type;
356 rej_options[rej_len + 1] = opt_len + 2;
357 memcpy(rej_options + rej_len + 2,
359 rej_len += opt_len + 2;
367 *new_options = rej_options;
374 *new_options = g_memdup(nak_options, len);
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)
386 guint8 *options = NULL;
387 struct ppp_option_iter iter;
390 ppp_option_iter_init(&iter, packet);
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);
398 memcpy(&ipcp->peer_addr, data, 4);
400 if (ipcp->peer_addr != 0)
404 * Fall through, reject IP_ADDRESS if peer sends
405 * us 0 (expecting us to provide its IP address)
408 if (options == NULL) {
409 guint16 max_len = ntohs(packet->length) - 4;
410 options = g_new0(guint8, max_len);
413 if (options != NULL) {
415 ppp_option_iter_get_length(&iter);
418 options[len + 1] = opt_len + 2;
419 memcpy(options + len + 2, data, opt_len);
429 *new_options = options;
437 static enum rcr_result ipcp_rcr(struct pppcp_data *pppcp,
438 const struct pppcp_packet *packet,
439 guint8 **new_options, guint16 *new_len)
441 struct ipcp_data *ipcp = pppcp_get_data(pppcp);
444 return ipcp_server_rcr(ipcp, packet, new_options, new_len);
446 return ipcp_client_rcr(ipcp, packet, new_options, new_len);
449 struct pppcp_proto ipcp_proto = {
452 .supported_codes = IPCP_SUPPORTED_CODES,
453 .this_layer_up = ipcp_up,
454 .this_layer_down = ipcp_down,
455 .this_layer_finished = ipcp_finished,
457 .rcn_nak = ipcp_rcn_nak,
458 .rcn_rej = ipcp_rcn_rej,
462 struct pppcp_data *ipcp_new(GAtPPP *ppp, gboolean is_server, guint32 ip)
464 struct ipcp_data *ipcp;
465 struct pppcp_data *pppcp;
467 ipcp = g_try_new0(struct ipcp_data, 1);
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
477 pppcp = pppcp_new(ppp, &ipcp_proto, FALSE, MAX_IPCP_FAILURE);
483 pppcp_set_data(pppcp, ipcp);
484 ipcp->is_server = is_server;
487 ipcp->local_addr = ip;
488 ipcp_reset_server_config_options(ipcp);
490 ipcp_reset_client_config_options(ipcp);
492 pppcp_set_local_options(pppcp, ipcp->options, ipcp->options_len);
497 void ipcp_free(struct pppcp_data *data)
499 struct ipcp_data *ipcp = pppcp_get_data(data);