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
32 #include <arpa/inet.h>
37 static const char *pppcp_state_strings[] = {
38 "INITIAL", "STARTING", "CLOSED", "STOPPED", "CLOSING", "STOPPING",
39 "REQSENT", "ACKRCVD", "ACKSENT", "OPENED"
42 static const char *pppcp_event_strings[] = {
43 "Up", "Down", "Open", "Close", "TO+", "TO-", "RCR+", "RCR-",
44 "RCA", "RCN", "RTR", "RTA", "RUC", "RXJ+", "RXJ-", "RXR"
47 #define pppcp_trace(p) do { \
48 char *str = g_strdup_printf("%s: %s: current state %d:%s", \
49 p->driver->name, __FUNCTION__, \
50 p->state, pppcp_state_strings[p->state]); \
51 ppp_debug(p->ppp, str); \
55 #define pppcp_trace_event(p, type, actions, state) do { \
56 char *str = g_strdup_printf("event: %d (%s), " \
57 "action: %x, new_state: %d (%s)", \
58 type, pppcp_event_strings[type], \
59 actions, state, pppcp_state_strings[state]); \
60 ppp_debug(p->ppp, str); \
64 #define pppcp_to_ppp_packet(p) \
65 (((guint8 *) p) - sizeof(struct ppp_header))
67 #define INITIAL_RESTART_TIMEOUT 3 /* restart interval in seconds */
68 #define MAX_TERMINATE 2
69 #define MAX_CONFIGURE 10
71 #define CP_HEADER_SZ 4
104 * Transition table straight from RFC 1661 Section 4.1
105 * Y coordinate is the events, while X coordinate is the state
107 * Magic of bitwise operations allows the table to describe all state
108 * transitions defined in the specification
110 static int cp_transitions[16][10] = {
112 { 2, IRC|SCR|6, INV, INV, INV, INV, INV, INV, INV, INV },
114 { INV, INV, 0, TLS|1, 0, 1, 1, 1, 1, TLD|1 },
116 { TLS|1, 1, IRC|SCR|6, 3, 5, 5, 6, 7, 8, 9 },
118 { 0, TLF|0, 2, 2, 4, 4, IRC|STR|4, IRC|STR|4, IRC|STR|4, TLD|IRC|STR|4 },
120 { INV, INV, INV, INV, STR|4, STR|5, SCR|6, SCR|6, SCR|8, INV },
122 { INV, INV, INV, INV, TLF|2, TLF|3, TLF|3, TLF|3, TLF|3, INV },
124 { INV, INV, STA|2, IRC|SCR|SCA|8, 4, 5, SCA|8, SCA|TLU|9, SCA|8, TLD|SCR|SCA|8 },
126 { INV, INV, STA|2, IRC|SCR|SCN|6, 4, 5, SCN|6, SCN|7, SCN|6, TLD|SCR|SCN|6 },
128 { INV, INV, STA|2, STA|3, 4, 5, IRC|7, SCR|6, IRC|TLU|9, TLD|SCR|6 },
130 { INV, INV, STA|2, STA|3, 4, 5, IRC|SCR|6, SCR|6, IRC|SCR|8, TLD|SCR|6 },
132 { INV, INV, STA|2, STA|3, STA|4, STA|5, STA|6, STA|6, STA|6, TLD|ZRC|STA|5 },
134 { INV, INV, 2, 3, TLF|2, TLF|3, 6, 6, 8, TLD|SCR|6 },
136 { INV, INV, SCJ|2, SCJ|3, SCJ|4, SCJ|5, SCJ|6, SCJ|7, SCJ|8, SCJ|9 },
138 { INV, INV, 2, 3, 4, 5, 6, 6, 8, 9 },
140 { INV, INV, TLF|2, TLF|3, TLF|2, TLF|3, TLF|3, TLF|3, TLF|3, TLD|IRC|STR|5 },
142 { INV, INV, 2, 3, 4, 5, 6, 7, 8, SER|9 },
145 enum pppcp_event_type {
164 struct pppcp_timer_data {
165 struct pppcp_data *data;
166 guint restart_counter;
167 guint restart_interval;
174 struct pppcp_timer_data config_timer_data;
175 struct pppcp_timer_data terminate_timer_data;
177 guint failure_counter;
179 guint8 config_identifier;
180 guint8 terminate_identifier;
181 guint8 reject_identifier;
182 const guint8 *local_options;
183 guint16 local_options_len;
184 guint8 *peer_options;
185 guint16 peer_options_len;
186 gboolean send_reject;
187 const struct pppcp_proto *driver;
191 static void pppcp_generate_event(struct pppcp_data *data,
192 enum pppcp_event_type event_type,
193 const guint8 *packet, guint len);
195 static void pppcp_packet_free(struct pppcp_packet *packet)
197 g_free(pppcp_to_ppp_packet(packet));
200 static struct pppcp_packet *pppcp_packet_new(struct pppcp_data *data,
201 guint type, guint bufferlen)
203 struct pppcp_packet *packet;
204 struct ppp_header *ppp_packet;
205 guint16 packet_length = bufferlen + sizeof(*packet);
207 ppp_packet = ppp_packet_new(packet_length, data->driver->proto);
208 if (ppp_packet == NULL)
211 /* advance past protocol to add CP header information */
212 packet = (struct pppcp_packet *) (ppp_packet->info);
214 packet->length = htons(packet_length);
219 void ppp_option_iter_init(struct ppp_option_iter *iter,
220 const struct pppcp_packet *packet)
222 iter->max = ntohs(packet->length) - CP_HEADER_SZ;
223 iter->pdata = packet->data;
227 iter->option_data = NULL;
230 gboolean ppp_option_iter_next(struct ppp_option_iter *iter)
232 const guint8 *cur = iter->pdata + iter->pos;
233 const guint8 *end = iter->pdata + iter->max;
238 if (cur + cur[1] > end)
242 iter->len = cur[1] - 2;
243 iter->option_data = cur + 2;
250 guint8 ppp_option_iter_get_type(struct ppp_option_iter *iter)
255 guint8 ppp_option_iter_get_length(struct ppp_option_iter *iter)
260 const guint8 *ppp_option_iter_get_data(struct ppp_option_iter *iter)
262 return iter->option_data;
265 guint8 pppcp_get_code(const guint8 *data)
267 struct ppp_header *ppp_packet = (struct ppp_header *) data;
268 struct pppcp_packet *packet = (struct pppcp_packet *) ppp_packet->info;
273 static gboolean pppcp_timeout(gpointer user_data)
275 struct pppcp_timer_data *timer_data = user_data;
277 pppcp_trace(timer_data->data);
279 timer_data->restart_timer = 0;
281 if (timer_data->restart_counter > 0)
282 pppcp_generate_event(timer_data->data, TO_PLUS, NULL, 0);
284 pppcp_generate_event(timer_data->data, TO_MINUS, NULL, 0);
289 static void pppcp_stop_timer(struct pppcp_timer_data *timer_data)
291 if (timer_data->restart_timer > 0) {
292 g_source_remove(timer_data->restart_timer);
293 timer_data->restart_timer = 0;
297 static void pppcp_start_timer(struct pppcp_timer_data *timer_data)
299 pppcp_stop_timer(timer_data);
301 timer_data->restart_timer =
302 g_timeout_add_seconds(timer_data->restart_interval,
303 pppcp_timeout, timer_data);
306 static gboolean is_first_request(struct pppcp_timer_data *timer_data)
308 return (timer_data->restart_counter == timer_data->max_counter);
312 /* log an illegal event, but otherwise do nothing */
313 static void pppcp_illegal_event(GAtPPP *ppp, guint8 state, guint8 type)
315 DBG(ppp, "Illegal event %d while in state %d", type, state);
318 static void pppcp_this_layer_up(struct pppcp_data *data)
320 if (data->driver->this_layer_up)
321 data->driver->this_layer_up(data);
324 static void pppcp_this_layer_down(struct pppcp_data *data)
326 if (data->driver->this_layer_down)
327 data->driver->this_layer_down(data);
330 static void pppcp_this_layer_started(struct pppcp_data *data)
332 if (data->driver->this_layer_started)
333 data->driver->this_layer_started(data);
336 static void pppcp_this_layer_finished(struct pppcp_data *data)
339 if (data->driver->this_layer_finished)
340 data->driver->this_layer_finished(data);
344 * set the restart counter to either max-terminate
345 * or max-configure. The counter is decremented for
346 * each transmission, including the first.
348 static void pppcp_initialize_restart_count(struct pppcp_timer_data *timer_data)
350 struct pppcp_data *data = timer_data->data;
354 timer_data->restart_counter = timer_data->max_counter;
358 * set restart counter to zero
360 static void pppcp_zero_restart_count(struct pppcp_timer_data *timer_data)
362 timer_data->restart_counter = 0;
366 * TBD - generate new identifier for packet
368 static guint8 new_identity(struct pppcp_data *data, guint prev_identifier)
370 return prev_identifier + 1;
374 * transmit a Configure-Request packet
375 * start the restart timer
376 * decrement the restart counter
378 static void pppcp_send_configure_request(struct pppcp_data *pppcp)
380 struct pppcp_packet *packet;
381 struct pppcp_timer_data *timer_data = &pppcp->config_timer_data;
385 packet = pppcp_packet_new(pppcp, PPPCP_CODE_TYPE_CONFIGURE_REQUEST,
386 pppcp->local_options_len);
387 memcpy(packet->data, pppcp->local_options, pppcp->local_options_len);
390 * if this is the first request, we need a new identifier.
391 * if this is a retransmission, leave the identifier alone.
393 if (is_first_request(timer_data))
394 pppcp->config_identifier =
395 new_identity(pppcp, pppcp->config_identifier);
396 packet->identifier = pppcp->config_identifier;
398 ppp_transmit(pppcp->ppp, pppcp_to_ppp_packet(packet),
399 ntohs(packet->length));
401 pppcp_packet_free(packet);
403 /* start timer for retransmission */
404 timer_data->restart_counter--;
405 pppcp_start_timer(timer_data);
409 * transmit a Configure-Ack packet
411 static void pppcp_send_configure_ack(struct pppcp_data *pppcp,
412 const guint8 *request)
414 struct pppcp_packet *packet;
415 struct pppcp_packet *cr_req = (struct pppcp_packet *) request;
420 pppcp->failure_counter = 0;
422 /* subtract for header. */
423 len = ntohs(cr_req->length) - CP_HEADER_SZ;
425 packet = pppcp_packet_new(pppcp, PPPCP_CODE_TYPE_CONFIGURE_ACK, len);
427 memcpy(packet->data, cr_req->data, len);
428 packet->identifier = cr_req->identifier;
429 ppp_transmit(pppcp->ppp, pppcp_to_ppp_packet(packet),
430 ntohs(packet->length));
431 pppcp_packet_free(packet);
435 * transmit a Configure-Nak or Configure-Reject packet
437 static void pppcp_send_configure_nak(struct pppcp_data *pppcp,
438 const guint8 *request)
440 struct pppcp_packet *packet;
441 struct pppcp_packet *cr_req = (struct pppcp_packet *) request;
446 * if we have exceeded our Max-Failure counter, we simply reject all
449 if (pppcp->failure_counter >= pppcp->max_failure) {
450 guint16 len = ntohs(cr_req->length) - CP_HEADER_SZ;
452 packet = pppcp_packet_new(pppcp,
453 PPPCP_CODE_TYPE_CONFIGURE_REJECT, len);
454 memcpy(packet->data, cr_req->data, len);
456 enum pppcp_code code = PPPCP_CODE_TYPE_CONFIGURE_NAK;
458 if (pppcp->send_reject == TRUE)
459 code = PPPCP_CODE_TYPE_CONFIGURE_REJECT;
461 pppcp->failure_counter++;
463 packet = pppcp_packet_new(pppcp, code, pppcp->peer_options_len);
464 memcpy(packet->data, pppcp->peer_options,
465 pppcp->peer_options_len);
468 packet->identifier = cr_req->identifier;
469 ppp_transmit(pppcp->ppp, pppcp_to_ppp_packet(packet),
470 ntohs(packet->length));
472 pppcp_packet_free(packet);
474 g_free(pppcp->peer_options);
475 pppcp->peer_options = NULL;
476 pppcp->peer_options_len = 0;
480 * transmit a Terminate-Request packet.
481 * start the restart timer.
482 * decrement the restart counter
484 static void pppcp_send_terminate_request(struct pppcp_data *data)
486 struct pppcp_packet *packet;
487 struct pppcp_timer_data *timer_data = &data->terminate_timer_data;
492 * the data field can be used by the sender (us).
493 * leave this empty for now.
495 packet = pppcp_packet_new(data, PPPCP_CODE_TYPE_TERMINATE_REQUEST, 0);
498 * Is this a retransmission? If so, do not change
499 * the identifier. If not, we need a fresh identity.
501 if (is_first_request(timer_data))
502 data->terminate_identifier =
503 new_identity(data, data->terminate_identifier);
504 packet->identifier = data->terminate_identifier;
505 ppp_transmit(data->ppp, pppcp_to_ppp_packet(packet),
506 ntohs(packet->length));
508 pppcp_packet_free(packet);
509 timer_data->restart_counter--;
510 pppcp_start_timer(timer_data);
514 * transmit a Terminate-Ack packet
516 static void pppcp_send_terminate_ack(struct pppcp_data *data,
517 const guint8 *request)
519 struct pppcp_packet *packet;
520 struct pppcp_packet *pppcp_header = (struct pppcp_packet *) request;
521 struct pppcp_timer_data *timer_data = &data->terminate_timer_data;
525 packet = pppcp_packet_new(data, PPPCP_CODE_TYPE_TERMINATE_ACK, 0);
527 /* match identifier of the request */
528 packet->identifier = pppcp_header->identifier;
530 ppp_transmit(data->ppp, pppcp_to_ppp_packet(packet),
531 ntohs(pppcp_header->length));
533 pppcp_packet_free(packet);
534 pppcp_start_timer(timer_data);
538 * transmit a Code-Reject packet
540 * XXX this seg faults.
542 static void pppcp_send_code_reject(struct pppcp_data *data,
543 const guint8 *rejected_packet)
545 struct pppcp_packet *packet;
546 const struct pppcp_packet *old_packet =
547 (const struct pppcp_packet *) rejected_packet;
551 packet = pppcp_packet_new(data, PPPCP_CODE_TYPE_CODE_REJECT,
552 ntohs(old_packet->length));
555 * Identifier must be changed for each Code-Reject sent
557 packet->identifier = new_identity(data, data->reject_identifier);
560 * rejected packet should be copied in, but it should be
561 * truncated if it needs to be to comply with mtu requirement
563 memcpy(packet->data, rejected_packet,
564 ntohs(packet->length) - CP_HEADER_SZ);
566 ppp_transmit(data->ppp, pppcp_to_ppp_packet(packet),
567 ntohs(packet->length));
569 pppcp_packet_free(packet);
573 * transmit an Echo-Reply packet
575 static void pppcp_send_echo_reply(struct pppcp_data *data,
576 const guint8 *request)
578 struct pppcp_packet *packet;
579 struct pppcp_packet *header = (struct pppcp_packet *) request;
582 * 0 bytes for data, 4 bytes for magic number
584 packet = pppcp_packet_new(data, PPPCP_CODE_TYPE_ECHO_REPLY, 4);
587 * match identifier of request
589 packet->identifier = header->identifier;
591 /* magic number will always be zero */
592 ppp_transmit(data->ppp, pppcp_to_ppp_packet(packet),
593 ntohs(packet->length));
595 pppcp_packet_free(packet);
598 static void pppcp_transition_state(enum pppcp_state new_state,
599 struct pppcp_data *data)
602 * if switching from a state where
603 * TO events occur, to one where they
604 * may not, shut off the timer
612 pppcp_stop_timer(&data->config_timer_data);
613 pppcp_stop_timer(&data->terminate_timer_data);
622 data->state = new_state;
626 * send the event handler a new event to process
628 static void pppcp_generate_event(struct pppcp_data *data,
629 enum pppcp_event_type event_type,
630 const guint8 *packet, guint len)
633 unsigned char new_state;
635 if (event_type > RXR)
640 actions = cp_transitions[event_type][data->state];
641 new_state = actions & 0xf;
643 pppcp_trace_event(data, event_type, actions, new_state);
649 struct pppcp_timer_data *timer_data;
651 if (new_state == CLOSING || new_state == STOPPING)
652 timer_data = &data->terminate_timer_data;
654 timer_data = &data->config_timer_data;
656 pppcp_initialize_restart_count(timer_data);
657 } else if (actions & ZRC)
658 pppcp_zero_restart_count(&data->terminate_timer_data);
661 pppcp_send_configure_request(data);
664 pppcp_send_configure_ack(data, packet);
665 else if (actions & SCN)
666 pppcp_send_configure_nak(data, packet);
669 pppcp_send_terminate_request(data);
670 else if (actions & STA)
671 pppcp_send_terminate_ack(data, packet);
674 pppcp_send_code_reject(data, packet);
677 pppcp_send_echo_reply(data, packet);
679 pppcp_transition_state(new_state, data);
682 pppcp_this_layer_started(data);
683 else if (actions & TLU)
684 pppcp_this_layer_up(data);
685 else if (actions & TLD)
686 pppcp_this_layer_down(data);
687 else if (actions & TLF)
688 pppcp_this_layer_finished(data);
693 pppcp_illegal_event(data->ppp, data->state, event_type);
696 void pppcp_signal_open(struct pppcp_data *data)
698 pppcp_generate_event(data, OPEN, NULL, 0);
701 void pppcp_signal_close(struct pppcp_data *data)
703 pppcp_generate_event(data, CLOSE, NULL, 0);
706 void pppcp_signal_up(struct pppcp_data *data)
708 pppcp_generate_event(data, UP, NULL, 0);
711 void pppcp_signal_down(struct pppcp_data *data)
713 pppcp_generate_event(data, DOWN, NULL, 0);
716 static guint8 pppcp_process_configure_request(struct pppcp_data *pppcp,
717 const struct pppcp_packet *packet)
721 if (pppcp->failure_counter >= pppcp->max_failure)
724 if (pppcp->driver->rcr) {
727 res = pppcp->driver->rcr(pppcp, packet,
728 &pppcp->peer_options,
729 &pppcp->peer_options_len);
731 if (res == RCR_REJECT) {
732 pppcp->send_reject = TRUE;
734 } else if (res == RCR_NAK) {
735 pppcp->send_reject = FALSE;
743 static guint8 pppcp_process_configure_ack(struct pppcp_data *pppcp,
744 const struct pppcp_packet *packet)
750 len = ntohs(packet->length) - CP_HEADER_SZ;
752 /* if identifiers don't match, we should silently discard */
753 if (packet->identifier != pppcp->config_identifier) {
758 * First we must sanity check that all config options acked are
759 * equal to the config options sent and are in the same order.
760 * If this is not the case, then silently drop the packet
762 if (pppcp->local_options_len != len)
765 if (memcmp(pppcp->local_options, packet->data, len))
768 /* Otherwise, apply local options */
769 if (pppcp->driver->rca)
770 pppcp->driver->rca(pppcp, packet);
775 static guint8 pppcp_process_configure_nak(struct pppcp_data *pppcp,
776 const struct pppcp_packet *packet)
780 /* if identifiers don't match, we should silently discard */
781 if (packet->identifier != pppcp->config_identifier)
784 if (pppcp->driver->rcn_nak)
785 pppcp->driver->rcn_nak(pppcp, packet);
790 static guint8 pppcp_process_configure_reject(struct pppcp_data *pppcp,
791 const struct pppcp_packet *packet)
796 * make sure identifier matches that of last sent configure
799 if (packet->identifier != pppcp->config_identifier)
803 * check to see which options were rejected
804 * Rejected options must be a subset of requested
805 * options and in the same order.
807 * when a new configure-request is sent, we may
808 * not request any of these options be negotiated
810 if (pppcp->driver->rcn_rej)
811 pppcp->driver->rcn_rej(pppcp, packet);
816 static guint8 pppcp_process_terminate_request(struct pppcp_data *data,
817 const struct pppcp_packet *packet)
824 static guint8 pppcp_process_terminate_ack(struct pppcp_data *data,
825 const struct pppcp_packet *packet)
828 * if we wind up using the data field for anything, then
829 * we'd want to check the identifier.
830 * even if the identifiers don't match, we still handle
831 * a terminate ack, as it is allowed to be unelicited
838 static guint8 pppcp_process_code_reject(struct pppcp_data *data,
839 const struct pppcp_packet *packet)
842 * determine if the code reject is catastrophic or not.
843 * return RXJ_PLUS if this reject is acceptable, RXJ_MINUS if
844 * it is catastrophic.
846 * for now we always return RXJ_MINUS. Any code
847 * reject will be catastrophic, since we only support the
848 * bare minimum number of codes necessary to function.
853 static guint8 pppcp_process_protocol_reject(struct pppcp_data *data,
854 const struct pppcp_packet *packet)
857 * determine if the protocol reject is catastrophic or not.
858 * return RXJ_PLUS if this reject is acceptable, RXJ_MINUS if
859 * it is catastrophic.
861 * for now we always return RXJ_MINUS. Any protocol
862 * reject will be catastrophic, since we only support the
863 * bare minimum number of protocols necessary to function.
869 * For Echo-Request, Echo-Reply, and Discard-Request, we will not
870 * bother checking the magic number of the packet, because we will
871 * never send an echo or discard request. We can't reliably detect
872 * loop back anyway, since we don't negotiate a magic number.
874 static guint8 pppcp_process_echo_request(struct pppcp_data *data,
875 const struct pppcp_packet *packet)
880 static guint8 pppcp_process_echo_reply(struct pppcp_data *data,
881 const struct pppcp_packet *packet)
886 static guint8 pppcp_process_discard_request(struct pppcp_data *data,
887 const struct pppcp_packet *packet)
892 static guint8 (*packet_ops[11])(struct pppcp_data *data,
893 const struct pppcp_packet *packet) = {
894 pppcp_process_configure_request,
895 pppcp_process_configure_ack,
896 pppcp_process_configure_nak,
897 pppcp_process_configure_reject,
898 pppcp_process_terminate_request,
899 pppcp_process_terminate_ack,
900 pppcp_process_code_reject,
901 pppcp_process_protocol_reject,
902 pppcp_process_echo_request,
903 pppcp_process_echo_reply,
904 pppcp_process_discard_request,
907 void pppcp_send_protocol_reject(struct pppcp_data *data,
908 const guint8 *rejected_packet, gsize len)
910 struct pppcp_packet *packet;
915 * Protocol-Reject can only be sent when we are in
916 * the OPENED state. If in any other state, silently discard.
918 if (data->state != OPENED)
922 * info should contain the old packet info, plus the 16bit
923 * protocol number we are rejecting.
925 packet = pppcp_packet_new(data, PPPCP_CODE_TYPE_PROTOCOL_REJECT,
929 * Identifier must be changed for each Protocol-Reject sent
931 packet->identifier = new_identity(data, data->reject_identifier);
934 * rejected packet should be copied in, but it should be
935 * truncated if it needs to be to comply with mtu requirement
937 memcpy(packet->data, rejected_packet + 2, len - 2);
939 ppp_transmit(data->ppp, pppcp_to_ppp_packet(packet),
940 ntohs(packet->length));
942 pppcp_packet_free(packet);
946 * parse the packet and determine which event this packet caused
948 void pppcp_process_packet(gpointer priv, const guint8 *new_packet, gsize len)
950 struct pppcp_data *data = priv;
951 const struct pppcp_packet *packet =
952 (const struct pppcp_packet *) new_packet;
956 if (len < sizeof(struct pppcp_packet))
959 /* check flags to see if we support this code */
960 if (!(data->driver->supported_codes & (1 << packet->code)))
963 event_type = packet_ops[packet->code-1](data, packet);
966 data_len = ntohs(packet->length);
967 pppcp_generate_event(data, event_type, new_packet, data_len);
971 void pppcp_free(struct pppcp_data *pppcp)
973 pppcp_stop_timer(&pppcp->config_timer_data);
974 pppcp_stop_timer(&pppcp->terminate_timer_data);
975 g_free(pppcp->peer_options);
979 void pppcp_set_data(struct pppcp_data *pppcp, gpointer data)
984 gpointer pppcp_get_data(struct pppcp_data *pppcp)
989 GAtPPP *pppcp_get_ppp(struct pppcp_data *pppcp)
994 void pppcp_set_local_options(struct pppcp_data *pppcp,
995 const guint8 *options, guint16 len)
997 pppcp->local_options = options;
998 pppcp->local_options_len = len;
1001 struct pppcp_data *pppcp_new(GAtPPP *ppp, const struct pppcp_proto *proto,
1002 gboolean dormant, guint max_failure)
1004 struct pppcp_data *data;
1006 data = g_try_malloc0(sizeof(struct pppcp_data));
1011 data->state = STOPPED;
1013 data->state = INITIAL;
1015 data->config_timer_data.restart_interval = INITIAL_RESTART_TIMEOUT;
1016 data->terminate_timer_data.restart_interval = INITIAL_RESTART_TIMEOUT;
1017 data->config_timer_data.max_counter = MAX_CONFIGURE;
1018 data->terminate_timer_data.max_counter = MAX_TERMINATE;
1019 data->config_timer_data.data = data;
1020 data->terminate_timer_data.data = data;
1023 data->max_failure = max_failure;
1025 data->max_failure = MAX_FAILURE;
1028 data->driver = proto;