2010-04-02 17:42:04 +00:00
|
|
|
/*
|
|
|
|
*
|
|
|
|
* PPP library with GLib integration
|
|
|
|
*
|
|
|
|
* Copyright (C) 2009-2010 Intel Corporation. All rights reserved.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
|
|
* published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include <config.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <termios.h>
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <glib.h>
|
|
|
|
|
|
|
|
#include "gatutil.h"
|
|
|
|
#include "gatppp.h"
|
|
|
|
#include "ppp.h"
|
|
|
|
|
|
|
|
struct ipcp_data {
|
|
|
|
guint8 ip_address[4];
|
|
|
|
guint8 primary_dns[4];
|
|
|
|
guint8 secondary_dns[4];
|
|
|
|
guint8 primary_nbns[4];
|
|
|
|
guint8 secondary_nbns[4];
|
|
|
|
struct pppcp_data *pppcp;
|
|
|
|
};
|
|
|
|
|
|
|
|
enum ipcp_option_types {
|
|
|
|
IP_ADDRESSES = 1,
|
|
|
|
IP_COMPRESSION_PROTO = 2,
|
|
|
|
IP_ADDRESS = 3,
|
|
|
|
MOBILE_IPV4 = 4,
|
|
|
|
PRIMARY_DNS_SERVER = 129,
|
|
|
|
PRIMARY_NBNS_SERVER = 130,
|
|
|
|
SECONDARY_DNS_SERVER = 131,
|
|
|
|
SECONDARY_NBNS_SERVER = 132,
|
|
|
|
};
|
|
|
|
|
|
|
|
static void ipcp_up(struct pppcp_data *pppcp)
|
|
|
|
{
|
2010-04-05 19:16:00 +00:00
|
|
|
struct ipcp_data *data = pppcp_get_data(pppcp);
|
2010-04-02 17:42:04 +00:00
|
|
|
char ip[INET_ADDRSTRLEN];
|
|
|
|
char dns1[INET_ADDRSTRLEN];
|
|
|
|
char dns2[INET_ADDRSTRLEN];
|
|
|
|
struct in_addr addr;
|
|
|
|
|
|
|
|
memset(ip, 0, sizeof(ip));
|
|
|
|
addr.s_addr = __get_unaligned_long(data->ip_address);
|
|
|
|
inet_ntop(AF_INET, &addr, ip, INET_ADDRSTRLEN);
|
|
|
|
|
|
|
|
memset(dns1, 0, sizeof(dns1));
|
|
|
|
addr.s_addr = __get_unaligned_long(data->primary_dns);
|
|
|
|
inet_ntop(AF_INET, &addr, dns1, INET_ADDRSTRLEN);
|
|
|
|
|
|
|
|
memset(dns2, 0, sizeof(dns2));
|
|
|
|
addr.s_addr = __get_unaligned_long(data->secondary_dns);
|
|
|
|
inet_ntop(AF_INET, &addr, dns2, INET_ADDRSTRLEN);
|
|
|
|
|
2010-04-04 05:25:09 +00:00
|
|
|
ppp_connect_cb(pppcp->ppp, G_AT_PPP_CONNECT_SUCCESS,
|
|
|
|
ip[0] ? ip : NULL,
|
|
|
|
dns1[0] ? dns1 : NULL,
|
|
|
|
dns2[0] ? dns2 : NULL);
|
2010-04-02 17:42:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void ipcp_down(struct pppcp_data *data)
|
|
|
|
{
|
|
|
|
g_print("ipcp down\n");
|
|
|
|
|
|
|
|
/* re-add what default config options we want negotiated */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Tell the protocol to start the handshake
|
|
|
|
*/
|
|
|
|
static void ipcp_started(struct pppcp_data *data)
|
|
|
|
{
|
2010-04-05 18:05:08 +00:00
|
|
|
pppcp_signal_up(data);
|
2010-04-02 17:42:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void ipcp_finished(struct pppcp_data *data)
|
|
|
|
{
|
|
|
|
g_print("ipcp finished\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Scan the option to see if it is acceptable, unacceptable, or rejected
|
|
|
|
*/
|
2010-04-05 19:32:11 +00:00
|
|
|
static guint ipcp_option_scan(struct pppcp_data *pppcp,
|
|
|
|
struct ppp_option *option)
|
2010-04-02 17:42:04 +00:00
|
|
|
{
|
|
|
|
switch (option->type) {
|
|
|
|
case IP_ADDRESS:
|
|
|
|
case PRIMARY_DNS_SERVER:
|
|
|
|
case PRIMARY_NBNS_SERVER:
|
|
|
|
case SECONDARY_DNS_SERVER:
|
|
|
|
case SECONDARY_NBNS_SERVER:
|
|
|
|
return OPTION_ACCEPT;
|
|
|
|
default:
|
|
|
|
g_printerr("Unknown ipcp option type %d\n", option->type);
|
|
|
|
return OPTION_REJECT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* act on an acceptable option
|
|
|
|
*/
|
2010-04-05 19:25:14 +00:00
|
|
|
static void ipcp_option_process(struct pppcp_data *pppcp,
|
|
|
|
struct ppp_option *option)
|
2010-04-02 17:42:04 +00:00
|
|
|
{
|
2010-04-05 19:16:00 +00:00
|
|
|
struct ipcp_data *ipcp = pppcp_get_data(pppcp);
|
2010-04-02 17:42:04 +00:00
|
|
|
|
|
|
|
switch (option->type) {
|
|
|
|
case IP_ADDRESS:
|
|
|
|
memcpy(ipcp->ip_address, option->data, 4);
|
|
|
|
break;
|
|
|
|
case PRIMARY_DNS_SERVER:
|
|
|
|
memcpy(ipcp->primary_dns, option->data, 4);
|
|
|
|
break;
|
|
|
|
case PRIMARY_NBNS_SERVER:
|
|
|
|
memcpy(ipcp->primary_nbns, option->data, 4);
|
|
|
|
break;
|
|
|
|
case SECONDARY_DNS_SERVER:
|
|
|
|
memcpy(ipcp->secondary_dns, option->data, 4);
|
|
|
|
break;
|
|
|
|
case SECONDARY_NBNS_SERVER:
|
|
|
|
memcpy(ipcp->secondary_nbns, option->data, 4);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_printerr("Unable to process unknown option %d\n", option->type);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct pppcp_action ipcp_action = {
|
2010-04-03 02:01:38 +00:00
|
|
|
.this_layer_up = ipcp_up,
|
|
|
|
.this_layer_down = ipcp_down,
|
|
|
|
.this_layer_started = ipcp_started,
|
|
|
|
.this_layer_finished = ipcp_finished,
|
|
|
|
.option_scan = ipcp_option_scan,
|
|
|
|
.option_process = ipcp_option_process,
|
2010-04-02 17:42:04 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static const char *ipcp_option_strings[256] = {
|
|
|
|
[IP_ADDRESSES] = "IP-Addresses (deprecated)",
|
|
|
|
[IP_COMPRESSION_PROTO] = "IP-Compression-Protocol",
|
|
|
|
[IP_ADDRESS] = "IP-Address",
|
|
|
|
[MOBILE_IPV4] = "Mobile-IPv4",
|
|
|
|
[PRIMARY_DNS_SERVER] = "Primary DNS Server Address",
|
|
|
|
[PRIMARY_NBNS_SERVER] = "Primary NBNS Server Address",
|
|
|
|
[SECONDARY_DNS_SERVER] = "Secondary DNS Server Address",
|
|
|
|
[SECONDARY_NBNS_SERVER] = "Secondary NBNS Server Address",
|
|
|
|
};
|
|
|
|
|
|
|
|
struct pppcp_data *ipcp_new(GAtPPP *ppp)
|
|
|
|
{
|
|
|
|
struct ipcp_data *data;
|
|
|
|
struct pppcp_data *pppcp;
|
|
|
|
struct ppp_option *ipcp_option;
|
|
|
|
|
|
|
|
data = g_try_malloc0(sizeof(*data));
|
|
|
|
if (!data)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
pppcp = pppcp_new(ppp, IPCP_PROTO);
|
|
|
|
if (!pppcp) {
|
|
|
|
g_printerr("Failed to allocate PPPCP struct\n");
|
|
|
|
g_free(data);
|
|
|
|
return NULL;
|
|
|
|
}
|
2010-04-05 18:12:43 +00:00
|
|
|
|
2010-04-02 17:42:04 +00:00
|
|
|
pppcp->option_strings = ipcp_option_strings;
|
|
|
|
pppcp->prefix = "ipcp";
|
2010-04-05 19:16:00 +00:00
|
|
|
|
|
|
|
pppcp_set_data(pppcp, data);
|
2010-04-02 17:42:04 +00:00
|
|
|
|
|
|
|
/* set the actions */
|
|
|
|
pppcp->action = &ipcp_action;
|
|
|
|
|
|
|
|
/* add the default config options */
|
|
|
|
ipcp_option = g_try_malloc0(6);
|
|
|
|
if (!ipcp_option) {
|
|
|
|
pppcp_free(pppcp);
|
|
|
|
g_free(data);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
ipcp_option->type = IP_ADDRESS;
|
|
|
|
ipcp_option->length= 6;
|
|
|
|
pppcp_add_config_option(pppcp, ipcp_option);
|
|
|
|
|
|
|
|
return pppcp;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ipcp_free(struct pppcp_data *data)
|
|
|
|
{
|
2010-04-05 19:16:00 +00:00
|
|
|
struct ipcp_data *ipcp = pppcp_get_data(data);
|
2010-04-02 17:42:04 +00:00
|
|
|
|
|
|
|
g_free(ipcp);
|
|
|
|
pppcp_free(data);
|
|
|
|
}
|