* [PATCH 1/5] gatppp: Add PPP server extension @ 2010-06-21 9:47 Zhenhua Zhang 2010-06-21 9:47 ` [PATCH 2/5] atmodem: Fix GAtPPPConnectFunc interface change Zhenhua Zhang 2010-06-22 4:36 ` [PATCH 1/5] gatppp: Add PPP server extension Denis Kenzior 0 siblings, 2 replies; 8+ messages in thread From: Zhenhua Zhang @ 2010-06-21 9:47 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 11745 bytes --] 1. Add interface to set PPP server info by g_at_ppp_set_server_info. 2. Pass local and peer address through IPCP handshaking. --- gatchat/gatppp.c | 13 +++- gatchat/gatppp.h | 7 ++- gatchat/ppp.h | 6 ++- gatchat/ppp_ipcp.c | 177 +++++++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 171 insertions(+), 32 deletions(-) diff --git a/gatchat/gatppp.c b/gatchat/gatppp.c index e92fe5d..05136e0 100644 --- a/gatchat/gatppp.c +++ b/gatchat/gatppp.c @@ -246,7 +246,7 @@ void ppp_auth_notify(GAtPPP *ppp, gboolean success) pppcp_signal_up(ppp->ipcp); } -void ppp_ipcp_up_notify(GAtPPP *ppp, const char *ip, +void ppp_ipcp_up_notify(GAtPPP *ppp, const char *local, const char *peer, const char *dns1, const char *dns2) { ppp->net = ppp_net_new(ppp); @@ -264,7 +264,8 @@ void ppp_ipcp_up_notify(GAtPPP *ppp, const char *ip, if (ppp->connect_cb) ppp->connect_cb(ppp_net_get_interface(ppp->net), - ip, dns1, dns2, ppp->connect_data); + local, peer, dns1, dns2, + ppp->connect_data); } void ppp_ipcp_down_notify(GAtPPP *ppp) @@ -464,6 +465,14 @@ void g_at_ppp_unref(GAtPPP *ppp) g_free(ppp); } +void g_at_ppp_set_server_info(GAtPPP *ppp, guint32 local, guint32 peer, + guint32 dns1, guint32 dns2, + guint32 nbns1, guint32 nbns2) +{ + ipcp_set_server_info(ppp->ipcp, local, peer, dns1, dns2, + nbns1, nbns2); +} + static GAtPPP *ppp_init_common(GAtHDLC *hdlc) { GAtPPP *ppp; diff --git a/gatchat/gatppp.h b/gatchat/gatppp.h index 438b952..86b3081 100644 --- a/gatchat/gatppp.h +++ b/gatchat/gatppp.h @@ -43,7 +43,8 @@ typedef enum _GAtPPPDisconnectReason { G_AT_PPP_REASON_LOCAL_CLOSE, /* Normal user close */ } GAtPPPDisconnectReason; -typedef void (*GAtPPPConnectFunc)(const char *iface, const char *ip, +typedef void (*GAtPPPConnectFunc)(const char *iface, const char *local, + const char *peer, const char *dns1, const char *dns2, gpointer user_data); typedef void (*GAtPPPDisconnectFunc)(GAtPPPDisconnectReason reason, @@ -68,6 +69,10 @@ const char *g_at_ppp_get_password(GAtPPP *ppp); void g_at_ppp_set_recording(GAtPPP *ppp, const char *filename); +void g_at_ppp_set_server_info(GAtPPP *ppp, guint32 local, guint32 peer, + guint32 dns1, guint32 dns2, + guint32 nbns1, guint32 nbns2); + #ifdef __cplusplus } #endif diff --git a/gatchat/ppp.h b/gatchat/ppp.h index b6c5f4a..56da8a9 100644 --- a/gatchat/ppp.h +++ b/gatchat/ppp.h @@ -86,6 +86,10 @@ void lcp_protocol_reject(struct pppcp_data *lcp, guint8 *packet, gsize len); /* IPCP related functions */ struct pppcp_data *ipcp_new(GAtPPP *ppp); void ipcp_free(struct pppcp_data *data); +void ipcp_set_server_info(struct pppcp_data *ipcp, guint32 local_addr, + guint32 peer_addr, + guint32 dns1, guint32 dns2, + guint32 nbns1, guint32 nbns2); /* CHAP related functions */ struct ppp_chap *ppp_chap_new(GAtPPP *ppp, guint8 method); @@ -104,7 +108,7 @@ void ppp_debug(GAtPPP *ppp, const char *str); void ppp_transmit(GAtPPP *ppp, guint8 *packet, guint infolen); void ppp_set_auth(GAtPPP *ppp, const guint8 *auth_data); void ppp_auth_notify(GAtPPP *ppp, gboolean success); -void ppp_ipcp_up_notify(GAtPPP *ppp, const char *ip, +void ppp_ipcp_up_notify(GAtPPP *ppp, const char *local, const char *peer, const char *dns1, const char *dns2); void ppp_ipcp_down_notify(GAtPPP *ppp); void ppp_ipcp_finished_notify(GAtPPP *ppp); diff --git a/gatchat/ppp_ipcp.c b/gatchat/ppp_ipcp.c index a1eacdf..bf30803 100644 --- a/gatchat/ppp_ipcp.c +++ b/gatchat/ppp_ipcp.c @@ -67,46 +67,49 @@ struct ipcp_data { guint8 options[MAX_CONFIG_OPTION_SIZE]; guint16 options_len; guint8 req_options; - guint32 ipaddr; + guint32 local_addr; + guint32 peer_addr; guint32 dns1; guint32 dns2; guint32 nbns1; guint32 nbns2; + gboolean is_server; }; -#define FILL_IP(req, type, var) \ - if (req) { \ - ipcp->options[len] = type; \ - ipcp->options[len + 1] = 6; \ - memcpy(ipcp->options + len + 2, var, 4); \ - \ - len += 6; \ - } \ +#define FILL_IP(options, req, type, var) \ + if (req) { \ + options[len] = type; \ + options[len + 1] = 6; \ + memcpy(options + len + 2, var, 4); \ + \ + len += 6; \ + } \ static void ipcp_generate_config_options(struct ipcp_data *ipcp) { guint16 len = 0; - FILL_IP(ipcp->req_options & REQ_OPTION_IPADDR, - IP_ADDRESS, &ipcp->ipaddr); - FILL_IP(ipcp->req_options & REQ_OPTION_DNS1, + FILL_IP(ipcp->options, ipcp->req_options & REQ_OPTION_IPADDR, + IP_ADDRESS, &ipcp->local_addr); + FILL_IP(ipcp->options, ipcp->req_options & REQ_OPTION_DNS1, PRIMARY_DNS_SERVER, &ipcp->dns1); - FILL_IP(ipcp->req_options & REQ_OPTION_DNS2, + FILL_IP(ipcp->options, ipcp->req_options & REQ_OPTION_DNS2, SECONDARY_DNS_SERVER, &ipcp->dns2); - FILL_IP(ipcp->req_options & REQ_OPTION_NBNS1, + FILL_IP(ipcp->options, ipcp->req_options & REQ_OPTION_NBNS1, PRIMARY_NBNS_SERVER, &ipcp->nbns1); - FILL_IP(ipcp->req_options & REQ_OPTION_NBNS2, + FILL_IP(ipcp->options, ipcp->req_options & REQ_OPTION_NBNS2, SECONDARY_NBNS_SERVER, &ipcp->nbns2); ipcp->options_len = len; } -static void ipcp_reset_config_options(struct ipcp_data *ipcp) +static void ipcp_reset_client_config_options(struct ipcp_data *ipcp) { ipcp->req_options = REQ_OPTION_IPADDR | REQ_OPTION_DNS1 | REQ_OPTION_DNS2 | REQ_OPTION_NBNS1 | REQ_OPTION_NBNS2; - ipcp->ipaddr = 0; + ipcp->local_addr = 0; + ipcp->peer_addr = 0; ipcp->dns1 = 0; ipcp->dns2 = 0; ipcp->nbns1 = 0; @@ -115,17 +118,49 @@ static void ipcp_reset_config_options(struct ipcp_data *ipcp) ipcp_generate_config_options(ipcp); } +static void ipcp_reset_server_config_options(struct ipcp_data *ipcp) +{ + ipcp->req_options = REQ_OPTION_IPADDR; + + ipcp_generate_config_options(ipcp); +} + +void ipcp_set_server_info(struct pppcp_data *pppcp, guint32 local_addr, + guint32 peer_addr, + guint32 dns1, guint32 dns2, + guint32 nbns1, guint32 nbns2) +{ + struct ipcp_data *ipcp = pppcp_get_data(pppcp); + + ipcp->req_options = REQ_OPTION_IPADDR; + ipcp->local_addr = local_addr; + ipcp->peer_addr = peer_addr; + ipcp->dns1 = dns1; + ipcp->dns2 = dns2; + ipcp->nbns1 = nbns1; + ipcp->nbns2 = nbns2; + ipcp->is_server = TRUE; + + ipcp_generate_config_options(ipcp); + pppcp_set_local_options(pppcp, ipcp->options, ipcp->options_len); +} + static void ipcp_up(struct pppcp_data *pppcp) { struct ipcp_data *ipcp = pppcp_get_data(pppcp); - char ip[INET_ADDRSTRLEN]; + char local[INET_ADDRSTRLEN]; + char peer[INET_ADDRSTRLEN]; char dns1[INET_ADDRSTRLEN]; char dns2[INET_ADDRSTRLEN]; struct in_addr addr; - memset(ip, 0, sizeof(ip)); - addr.s_addr = ipcp->ipaddr; - inet_ntop(AF_INET, &addr, ip, INET_ADDRSTRLEN); + memset(local, 0, sizeof(local)); + addr.s_addr = ipcp->local_addr; + inet_ntop(AF_INET, &addr, local, INET_ADDRSTRLEN); + + memset(peer, 0, sizeof(peer)); + addr.s_addr = ipcp->peer_addr; + inet_ntop(AF_INET, &addr, peer, INET_ADDRSTRLEN); memset(dns1, 0, sizeof(dns1)); addr.s_addr = ipcp->dns1; @@ -135,7 +170,8 @@ static void ipcp_up(struct pppcp_data *pppcp) addr.s_addr = ipcp->dns2; inet_ntop(AF_INET, &addr, dns2, INET_ADDRSTRLEN); - ppp_ipcp_up_notify(pppcp_get_ppp(pppcp), ip[0] ? ip : NULL, + ppp_ipcp_up_notify(pppcp_get_ppp(pppcp), local[0] ? local : NULL, + peer[0] ? peer : NULL, dns1[0] ? dns1 : NULL, dns2[0] ? dns2 : NULL); } @@ -144,7 +180,11 @@ static void ipcp_down(struct pppcp_data *pppcp) { struct ipcp_data *ipcp = pppcp_get_data(pppcp); - ipcp_reset_config_options(ipcp); + if (ipcp->is_server) + ipcp_reset_server_config_options(ipcp); + else + ipcp_reset_client_config_options(ipcp); + pppcp_set_local_options(pppcp, ipcp->options, ipcp->options_len); ppp_ipcp_down_notify(pppcp_get_ppp(pppcp)); } @@ -167,7 +207,7 @@ static void ipcp_rca(struct pppcp_data *pppcp, switch (ppp_option_iter_get_type(&iter)) { case IP_ADDRESS: - memcpy(&ipcp->ipaddr, data, 4); + memcpy(&ipcp->local_addr, data, 4); break; case PRIMARY_DNS_SERVER: memcpy(&ipcp->dns1, data, 4); @@ -204,7 +244,7 @@ static void ipcp_rcn_nak(struct pppcp_data *pppcp, case IP_ADDRESS: g_print("Setting suggested ip addr\n"); ipcp->req_options |= REQ_OPTION_IPADDR; - memcpy(&ipcp->ipaddr, data, 4); + memcpy(&ipcp->local_addr, data, 4); break; case PRIMARY_DNS_SERVER: g_print("Setting suggested dns1\n"); @@ -269,17 +309,98 @@ static void ipcp_rcn_rej(struct pppcp_data *pppcp, pppcp_set_local_options(pppcp, ipcp->options, ipcp->options_len); } +static guint8 *ipcp_generate_peer_config_options(struct ipcp_data *ipcp, + guint16 *new_len) +{ + guint8 *options; + guint16 len = 0; + + options = g_try_new0(guint8, MAX_CONFIG_OPTION_SIZE); + if (!options) + return NULL; + + FILL_IP(options, TRUE, IP_ADDRESS, &ipcp->peer_addr); + FILL_IP(options, TRUE, PRIMARY_DNS_SERVER, &ipcp->dns1); + FILL_IP(options, TRUE, SECONDARY_DNS_SERVER, &ipcp->dns2); + FILL_IP(options, TRUE, PRIMARY_NBNS_SERVER, &ipcp->nbns1); + FILL_IP(options, TRUE, SECONDARY_NBNS_SERVER, &ipcp->nbns2); + + *new_len = MAX_CONFIG_OPTION_SIZE; + + return options; +} + static enum rcr_result ipcp_rcr(struct pppcp_data *pppcp, const struct pppcp_packet *packet, guint8 **new_options, guint16 *new_len) { struct ppp_option_iter iter; + struct ipcp_data *ipcp = pppcp_get_data(pppcp); + guint32 peer_addr = 0; + guint32 dns1 = 0; + guint32 dns2 = 0; + guint32 nbns1 = 0; + guint32 nbns2 = 0; ppp_option_iter_init(&iter, packet); - if (ppp_option_iter_next(&iter) == FALSE) - return RCR_ACCEPT; + while (ppp_option_iter_next(&iter) == TRUE) { + const guint8 *data = ppp_option_iter_get_data(&iter); + + switch (ppp_option_iter_get_type(&iter)) { + case IP_ADDRESS: + memcpy(&peer_addr, data, 4); + break; + case PRIMARY_DNS_SERVER: + memcpy(&dns1, data, 4); + break; + case SECONDARY_DNS_SERVER: + memcpy(&dns2, data, 4); + break; + case PRIMARY_NBNS_SERVER: + memcpy(&nbns1, data, 4); + break; + case SECONDARY_NBNS_SERVER: + memcpy(&nbns2, data, 4); + break; + default: + break; + } + } + + if (peer_addr) { + if (ipcp->peer_addr == 0) { + /* RFC 1332 section 3.3 + * As client, accept the server IP as peer's address + */ + ipcp->peer_addr = peer_addr; + + return RCR_ACCEPT; + } else if (ipcp->peer_addr == peer_addr && ipcp->dns1 == dns1 + && ipcp->nbns1 == nbns1 && ipcp->nbns2 == nbns2) + /* As server, verify the client's info and then send + * acknowledgement back + */ + return RCR_ACCEPT; + } else { + /* Client requests server to send IP/DNS/NBNS information in the + * config options + */ + if (ipcp->peer_addr) { + guint8 *options; + guint16 len; + + options = ipcp_generate_peer_config_options(ipcp, &len); + if (!options) + goto reject; + + *new_len = len; + *new_options = options; + return RCR_NAK; + } + } +reject: /* Reject all options */ *new_len = packet->length - sizeof(*packet); *new_options = g_memdup(packet->data, *new_len); @@ -317,7 +438,7 @@ struct pppcp_data *ipcp_new(GAtPPP *ppp) } pppcp_set_data(pppcp, ipcp); - ipcp_reset_config_options(ipcp); + ipcp_reset_client_config_options(ipcp); pppcp_set_local_options(pppcp, ipcp->options, ipcp->options_len); return pppcp; -- 1.6.3.3 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 2/5] atmodem: Fix GAtPPPConnectFunc interface change 2010-06-21 9:47 [PATCH 1/5] gatppp: Add PPP server extension Zhenhua Zhang @ 2010-06-21 9:47 ` Zhenhua Zhang 2010-06-21 9:48 ` [PATCH 3/5] test-server: Add PPP server support Zhenhua Zhang 2010-06-22 4:36 ` [PATCH 1/5] gatppp: Add PPP server extension Denis Kenzior 1 sibling, 1 reply; 8+ messages in thread From: Zhenhua Zhang @ 2010-06-21 9:47 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 1730 bytes --] --- drivers/atmodem/gprs-context.c | 5 +++-- gatchat/gsmdial.c | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/atmodem/gprs-context.c b/drivers/atmodem/gprs-context.c index 4ddf88e..fea80b0 100644 --- a/drivers/atmodem/gprs-context.c +++ b/drivers/atmodem/gprs-context.c @@ -65,7 +65,8 @@ struct gprs_context_data { void *cb_data; /* Callback data */ }; -static void ppp_connect(const char *interface, const char *ip, +static void ppp_connect(const char *interface, const char *local, + const char *remote, const char *dns1, const char *dns2, gpointer user_data) { @@ -78,7 +79,7 @@ static void ppp_connect(const char *interface, const char *ip, dns[2] = 0; gcd->state = STATE_ACTIVE; - CALLBACK_WITH_SUCCESS(gcd->up_cb, interface, TRUE, ip, + CALLBACK_WITH_SUCCESS(gcd->up_cb, interface, TRUE, local, STATIC_IP_NETMASK, NULL, dns, gcd->cb_data); } diff --git a/gatchat/gsmdial.c b/gatchat/gsmdial.c index 62c3b3d..a69a610 100644 --- a/gatchat/gsmdial.c +++ b/gatchat/gsmdial.c @@ -221,13 +221,14 @@ out: return FALSE; } -static void ppp_connect(const char *iface, const char *ip, +static void ppp_connect(const char *iface, const char *local, const char *peer, const char *dns1, const char *dns2, gpointer user_data) { /* print out the negotiated address and dns server */ g_print("Network Device: %s\n", iface); - g_print("IP Address: %s\n", ip); + g_print("IP Address: %s\n", local); + g_print("Peer IP Address: %s\n", peer); g_print("Primary DNS Server: %s\n", dns1); g_print("Secondary DNS Server: %s\n", dns2); } -- 1.6.3.3 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 3/5] test-server: Add PPP server support 2010-06-21 9:47 ` [PATCH 2/5] atmodem: Fix GAtPPPConnectFunc interface change Zhenhua Zhang @ 2010-06-21 9:48 ` Zhenhua Zhang 2010-06-21 9:48 ` [PATCH 4/5] test-server: Configure network interface Zhenhua Zhang 0 siblings, 1 reply; 8+ messages in thread From: Zhenhua Zhang @ 2010-06-21 9:48 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 5514 bytes --] So that gsmdial and wvdial could talk to test-server and establish PPP connection. --- gatchat/test-server.c | 131 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 files changed, 123 insertions(+), 8 deletions(-) diff --git a/gatchat/test-server.c b/gatchat/test-server.c index 5c1cfa4..68371c2 100644 --- a/gatchat/test-server.c +++ b/gatchat/test-server.c @@ -35,6 +35,7 @@ #include <arpa/inet.h> #include <signal.h> #include <sys/signalfd.h> +#include <errno.h> #include <glib.h> #include <utmp.h> @@ -44,6 +45,7 @@ #include <sys/stat.h> #include "gatserver.h" +#include "gatppp.h" #include "ringbuffer.h" #define DEFAULT_TCP_PORT 12346 @@ -61,6 +63,7 @@ struct sock_server{ static GMainLoop *mainloop; static GAtServer *server; +static GAtPPP *ppp; unsigned int server_watch; static gboolean server_cleanup() @@ -68,6 +71,11 @@ static gboolean server_cleanup() if (server_watch) g_source_remove(server_watch); + if (ppp) { + g_at_ppp_unref(ppp); + ppp = NULL; + } + g_at_server_unref(server); server = NULL; @@ -83,6 +91,81 @@ static void server_debug(const char *str, void *data) g_print("%s: %s\n", (char *) data, str); } +static void ppp_connect(const char *iface, const char *local, const char *peer, + const char *dns1, const char *dns2, + gpointer user) +{ + g_print("Network Device: %s\n", iface); + g_print("IP Address: %s\n", local); + g_print("Peer IP Address: %s\n", peer); + g_print("Primary DNS Server: %s\n", dns1); + g_print("Secondary DNS Server: %s\n", dns2); +} + +static void ppp_disconnect(GAtPPPDisconnectReason reason, gpointer user) +{ + GAtServer *server = user; + + g_print("PPP Link down: %d\n", reason); + + g_at_ppp_unref(ppp); + ppp = NULL; + + g_at_server_resume(server); + g_at_server_set_debug(server, server_debug, "Server"); +} + +static gboolean update_ppp(gpointer user) +{ + GAtPPP *ppp = user; + char local_ip[INET_ADDRSTRLEN] = "192.168.1.1"; + char remote_ip[INET_ADDRSTRLEN] = "192.168.1.2"; + char dns1[INET_ADDRSTRLEN] = "10.10.10.0"; + char dns2[INET_ADDRSTRLEN] = "127.0.0.1"; + guint32 l, r, d1, d2; + + inet_pton(AF_INET, local_ip, &l); + inet_pton(AF_INET, remote_ip, &r); + inet_pton(AF_INET, dns1, &d1); + inet_pton(AF_INET, dns2, &d2); + + g_at_ppp_set_server_info(ppp, l, r, d1, d2, 0, 0); + + return FALSE; +} + +static gboolean setup_ppp(gpointer user) +{ + GAtServer *server = user; + GAtIO *io; + + io = g_at_server_get_io(server); + + g_at_server_suspend(server); + + /* open ppp */ + ppp = g_at_ppp_new_from_io(io); + if (ppp == NULL) { + g_at_server_resume(server); + return FALSE; + } + + g_at_ppp_set_debug(ppp, server_debug, "PPP"); + + g_at_ppp_set_credentials(ppp, "", ""); + + /* set connect and disconnect callbacks */ + g_at_ppp_set_connect_function(ppp, ppp_connect, server); + g_at_ppp_set_disconnect_function(ppp, ppp_disconnect, server); + + /* open the ppp connection */ + g_at_ppp_open(ppp); + + g_idle_add(update_ppp, ppp); + + return FALSE; +} + static void cgmi_cb(GAtServerRequestType type, GAtResult *cmd, gpointer user) { GAtServer *server = user; @@ -468,6 +551,7 @@ static void cgdata_cb(GAtServerRequestType type, GAtResult *cmd, gpointer user) break; case G_AT_SERVER_REQUEST_TYPE_SET: g_at_server_send_final(server, G_AT_SERVER_RESULT_CONNECT); + g_idle_add(setup_ppp, server); break; default: g_at_server_send_final(server, G_AT_SERVER_RESULT_ERROR); @@ -671,6 +755,40 @@ static void cpbs_cb(GAtServerRequestType type, GAtResult *cmd, gpointer user) } } +static void dial_cb(GAtServerRequestType type, GAtResult *cmd, gpointer user) +{ + GAtServer *server = user; + GAtServerResult res = G_AT_SERVER_RESULT_ERROR; + GAtResultIter iter; + const char *dial_str; + char c; + + if (type != G_AT_SERVER_REQUEST_TYPE_SET) + goto error; + + g_at_result_iter_init(&iter, cmd); + + if (!g_at_result_iter_next(&iter, "D")) + goto error; + + dial_str = g_at_result_iter_raw_line(&iter); + if (!dial_str) + goto error; + + g_print("dial call %s\n", dial_str); + + c = *dial_str; + if (c == '*' || c == '#' || c == 'T' || c == 't') { + g_at_server_send_final(server, G_AT_SERVER_RESULT_CONNECT); + g_idle_add(setup_ppp, server); + } + + return; + +error: + g_at_server_send_final(server, res); +} + static void add_handler(GAtServer *server) { g_at_server_set_debug(server, server_debug, "Server"); @@ -695,6 +813,7 @@ static void add_handler(GAtServer *server) g_at_server_register(server, "+CSCS", cscs_cb, server, NULL); g_at_server_register(server, "+CMGL", cmgl_cb, server, NULL); g_at_server_register(server, "+CPBS", cpbs_cb, server, NULL); + g_at_server_register(server, "D", dial_cb, server, NULL); } static void server_destroy(gpointer user) @@ -706,15 +825,11 @@ static void server_destroy(gpointer user) static void set_raw_mode(int fd) { - struct termios options; - - tcgetattr(fd, &options); - - /* Set TTY as raw mode to disable echo back of input characters - * when they are received from Modem to avoid feedback loop */ - options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); + struct termios ti; - tcsetattr(fd, TCSANOW, &options); + tcflush(fd, TCIOFLUSH); + cfmakeraw(&ti); + tcsetattr(fd, TCSANOW, &ti); } static gboolean create_tty(const char *modem_path) -- 1.6.3.3 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 4/5] test-server: Configure network interface 2010-06-21 9:48 ` [PATCH 3/5] test-server: Add PPP server support Zhenhua Zhang @ 2010-06-21 9:48 ` Zhenhua Zhang 2010-06-21 9:48 ` [PATCH 5/5] gsmdial: Configure network interface for PPP Zhenhua Zhang 0 siblings, 1 reply; 8+ messages in thread From: Zhenhua Zhang @ 2010-06-21 9:48 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 2025 bytes --] Require ROOT priviledge to: 1. Run external command to configure and bring up network interface. 2. Enable kernel IP forwarding. --- gatchat/test-server.c | 31 +++++++++++++++++++++++++++++++ 1 files changed, 31 insertions(+), 0 deletions(-) diff --git a/gatchat/test-server.c b/gatchat/test-server.c index 68371c2..df0bab8 100644 --- a/gatchat/test-server.c +++ b/gatchat/test-server.c @@ -50,6 +50,7 @@ #define DEFAULT_TCP_PORT 12346 #define DEFAULT_SOCK_PATH "./server_sock" +#define IFCONFIG_PATH "/sbin/ifconfig" static int modem_mode = 0; static int modem_creg = 0; @@ -91,15 +92,40 @@ static void server_debug(const char *str, void *data) g_print("%s: %s\n", (char *) data, str); } +static gboolean execute(const char *cmd) +{ + int status; + + status = system(cmd); + if (status < 0) { + g_print("Failed to execute command: %s\n", strerror(errno)); + return FALSE; + } + + return TRUE; +} + static void ppp_connect(const char *iface, const char *local, const char *peer, const char *dns1, const char *dns2, gpointer user) { + char buf[512]; + g_print("Network Device: %s\n", iface); g_print("IP Address: %s\n", local); g_print("Peer IP Address: %s\n", peer); g_print("Primary DNS Server: %s\n", dns1); g_print("Secondary DNS Server: %s\n", dns2); + + snprintf(buf, sizeof(buf), "%s %s up", IFCONFIG_PATH, iface); + execute(buf); + + snprintf(buf, sizeof(buf), "%s %s %s pointopoint %s", IFCONFIG_PATH, + iface, local, peer); + execute(buf); + + snprintf(buf, sizeof(buf), "echo 1 > /proc/sys/net/ipv4/ip_forward"); + execute(buf); } static void ppp_disconnect(GAtPPPDisconnectReason reason, gpointer user) @@ -139,6 +165,11 @@ static gboolean setup_ppp(gpointer user) GAtServer *server = user; GAtIO *io; + if (getuid() != 0) { + g_print("Need root priviledge for PPP connection\n"); + return FALSE; + } + io = g_at_server_get_io(server); g_at_server_suspend(server); -- 1.6.3.3 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* [PATCH 5/5] gsmdial: Configure network interface for PPP 2010-06-21 9:48 ` [PATCH 4/5] test-server: Configure network interface Zhenhua Zhang @ 2010-06-21 9:48 ` Zhenhua Zhang 0 siblings, 0 replies; 8+ messages in thread From: Zhenhua Zhang @ 2010-06-21 9:48 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 1660 bytes --] --- gatchat/gsmdial.c | 29 +++++++++++++++++++++++++++++ 1 files changed, 29 insertions(+), 0 deletions(-) diff --git a/gatchat/gsmdial.c b/gatchat/gsmdial.c index a69a610..59f1a5c 100644 --- a/gatchat/gsmdial.c +++ b/gatchat/gsmdial.c @@ -38,6 +38,8 @@ #include <gattty.h> #include <gatppp.h> +#define IFCONFIG_PATH "/sbin/ifconfig" + static const char *none_prefix[] = { NULL }; static const char *cfun_prefix[] = { "+CFUN:", NULL }; static const char *creg_prefix[] = { "+CREG:", NULL }; @@ -221,16 +223,43 @@ out: return FALSE; } +static gboolean execute(const char *cmd) +{ + int status; + + status = system(cmd); + if (status < 0) { + g_print("Failed to execute command: %s\n", strerror(errno)); + return FALSE; + } + + return TRUE; +} + static void ppp_connect(const char *iface, const char *local, const char *peer, const char *dns1, const char *dns2, gpointer user_data) { + char buf[512]; + /* print out the negotiated address and dns server */ g_print("Network Device: %s\n", iface); g_print("IP Address: %s\n", local); g_print("Peer IP Address: %s\n", peer); g_print("Primary DNS Server: %s\n", dns1); g_print("Secondary DNS Server: %s\n", dns2); + + if (getuid() != 0) { + g_print("Need root priviledge to config PPP interface\n"); + return; + } + + snprintf(buf, sizeof(buf), "%s %s up", IFCONFIG_PATH, iface); + execute(buf); + + snprintf(buf, sizeof(buf), "%s %s %s pointopoint %s", IFCONFIG_PATH, + iface, local, peer); + execute(buf); } static void ppp_disconnect(GAtPPPDisconnectReason reason, gpointer user_data) -- 1.6.3.3 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 1/5] gatppp: Add PPP server extension 2010-06-21 9:47 [PATCH 1/5] gatppp: Add PPP server extension Zhenhua Zhang 2010-06-21 9:47 ` [PATCH 2/5] atmodem: Fix GAtPPPConnectFunc interface change Zhenhua Zhang @ 2010-06-22 4:36 ` Denis Kenzior 2010-06-22 6:24 ` Zhang, Zhenhua 1 sibling, 1 reply; 8+ messages in thread From: Denis Kenzior @ 2010-06-22 4:36 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 2451 bytes --] Hi Zhenhua, > static enum rcr_result ipcp_rcr(struct pppcp_data *pppcp, > const struct pppcp_packet *packet, > guint8 **new_options, guint16 *new_len) > { > struct ppp_option_iter iter; > + struct ipcp_data *ipcp = pppcp_get_data(pppcp); > + guint32 peer_addr = 0; > + guint32 dns1 = 0; > + guint32 dns2 = 0; > + guint32 nbns1 = 0; > + guint32 nbns2 = 0; > > ppp_option_iter_init(&iter, packet); > > - if (ppp_option_iter_next(&iter) == FALSE) > - return RCR_ACCEPT; > + while (ppp_option_iter_next(&iter) == TRUE) { > + const guint8 *data = ppp_option_iter_get_data(&iter); > + > + switch (ppp_option_iter_get_type(&iter)) { > + case IP_ADDRESS: > + memcpy(&peer_addr, data, 4); > + break; > + case PRIMARY_DNS_SERVER: > + memcpy(&dns1, data, 4); > + break; > + case SECONDARY_DNS_SERVER: > + memcpy(&dns2, data, 4); > + break; > + case PRIMARY_NBNS_SERVER: > + memcpy(&nbns1, data, 4); > + break; > + case SECONDARY_NBNS_SERVER: > + memcpy(&nbns2, data, 4); > + break; > + default: > + break; > + } > + } > + > + if (peer_addr) { > + if (ipcp->peer_addr == 0) { > + /* RFC 1332 section 3.3 > + * As client, accept the server IP as peer's address > + */ > + ipcp->peer_addr = peer_addr; > + > + return RCR_ACCEPT; I'm still confused about this part. As client we should accept server's IP address as long as its non-zero. Otherwise Conf-Rej the option. > + } else if (ipcp->peer_addr == peer_addr && ipcp->dns1 == dns1 > + && ipcp->nbns1 == nbns1 && ipcp->nbns2 == nbns2) > + /* As server, verify the client's info and then send > + * acknowledgement back > + */ > + return RCR_ACCEPT; > + } else { > + /* Client requests server to send IP/DNS/NBNS information in the > + * config options > + */ > + if (ipcp->peer_addr) { > + guint8 *options; > + guint16 len; > + > + options = ipcp_generate_peer_config_options(ipcp, &len); > + if (!options) > + goto reject; > + > + *new_len = len; > + *new_options = options; > + return RCR_NAK; > + } Here we want to ensure that we nak the client's options for as long as the options don't match. Even ipcp->peer_addr is 0 (e.g. we're allocating client's address via DHCP or something) Overall I think this code path is a little too complicated. Can you see whether you can clean it up a bit? Regards, -Denis ^ permalink raw reply [flat|nested] 8+ messages in thread
* RE: [PATCH 1/5] gatppp: Add PPP server extension 2010-06-22 4:36 ` [PATCH 1/5] gatppp: Add PPP server extension Denis Kenzior @ 2010-06-22 6:24 ` Zhang, Zhenhua 0 siblings, 0 replies; 8+ messages in thread From: Zhang, Zhenhua @ 2010-06-22 6:24 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 3226 bytes --] Hi Denis, Denis Kenzior wrote: > Hi Zhenhua, > >> static enum rcr_result ipcp_rcr(struct pppcp_data *pppcp, >> const struct > pppcp_packet *packet, >> guint8 **new_options, > guint16 *new_len) >> { >> struct ppp_option_iter iter; >> + struct ipcp_data *ipcp = pppcp_get_data(pppcp); >> + guint32 peer_addr = 0; >> + guint32 dns1 = 0; >> + guint32 dns2 = 0; >> + guint32 nbns1 = 0; >> + guint32 nbns2 = 0; >> >> ppp_option_iter_init(&iter, packet); >> >> - if (ppp_option_iter_next(&iter) == FALSE) >> - return RCR_ACCEPT; >> + while (ppp_option_iter_next(&iter) == TRUE) { >> + const guint8 *data = ppp_option_iter_get_data(&iter); + >> + switch (ppp_option_iter_get_type(&iter)) { >> + case IP_ADDRESS: >> + memcpy(&peer_addr, data, 4); >> + break; >> + case PRIMARY_DNS_SERVER: >> + memcpy(&dns1, data, 4); >> + break; >> + case SECONDARY_DNS_SERVER: >> + memcpy(&dns2, data, 4); >> + break; >> + case PRIMARY_NBNS_SERVER: >> + memcpy(&nbns1, data, 4); >> + break; >> + case SECONDARY_NBNS_SERVER: >> + memcpy(&nbns2, data, 4); >> + break; >> + default: >> + break; >> + } >> + } >> + >> + if (peer_addr) { >> + if (ipcp->peer_addr == 0) { >> + /* RFC 1332 section 3.3 >> + * As client, accept the server IP as peer's address + */ >> + ipcp->peer_addr = peer_addr; >> + >> + return RCR_ACCEPT; > > I'm still confused about this part. As client we should > accept server's IP > address as long as its non-zero. Otherwise Conf-Rej the option. Right, initially, client know nothing about server, so client->peer_addr is zero. Once client get a non-zero IP from configure option, we fill this IP as peer's IP address. Looks like this IP is exposed as gateway to Connman. Maybe I could change it like: if (ipcp->is_server == FALSE && ipcp->peer_addr == 0) >> + } else if (ipcp->peer_addr == peer_addr && ipcp->dns1 == dns1 >> + && ipcp->nbns1 == nbns1 && > ipcp->nbns2 == nbns2) >> + /* As server, verify the client's info > and then send >> + * acknowledgement back >> + */ >> + return RCR_ACCEPT; >> + } else { >> + /* Client requests server to send IP/DNS/NBNS information in the >> + * config options + */ >> + if (ipcp->peer_addr) { >> + guint8 *options; >> + guint16 len; >> + >> + options = > ipcp_generate_peer_config_options(ipcp, &len); >> + if (!options) >> + goto reject; >> + >> + *new_len = len; >> + *new_options = options; >> + return RCR_NAK; >> + } > > Here we want to ensure that we nak the client's options for as > long as the > options don't match. Even ipcp->peer_addr is 0 (e.g. we're allocating > client's address via DHCP or something) In theory, it's true. But I don't see a PPP modem without client's address here. Even in drivers/atmodem/gprs-context.c, we assume the PPP interface has a static IP instead of dynamic one. Anyway, I will modify this part. > Overall I think this code path is a little too complicated. > Can you see > whether you can clean it up a bit? Okay, I will try to elimiate some conditional branchs here. > Regards, > -Denis Regards, Zhenhua ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 0/5] Add PPP server support @ 2010-06-25 3:19 Zhenhua Zhang 2010-06-25 3:19 ` [PATCH 1/5] gatppp: Add PPP server extension Zhenhua Zhang 0 siblings, 1 reply; 8+ messages in thread From: Zhenhua Zhang @ 2010-06-25 3:19 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 111 bytes --] Hi, I updated the patch according to the comments. Please review them. Thanks! Best Regards, Zhenhua ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/5] gatppp: Add PPP server extension 2010-06-25 3:19 [PATCH 0/5] Add PPP server support Zhenhua Zhang @ 2010-06-25 3:19 ` Zhenhua Zhang 0 siblings, 0 replies; 8+ messages in thread From: Zhenhua Zhang @ 2010-06-25 3:19 UTC (permalink / raw) To: ofono [-- Attachment #1: Type: text/plain, Size: 13594 bytes --] 1. Add interface to set PPP server info by g_at_ppp_set_server_info. 2. Pass local and peer address through IPCP handshaking. --- gatchat/gatppp.c | 11 ++- gatchat/gatppp.h | 6 +- gatchat/ppp.h | 5 +- gatchat/ppp_ipcp.c | 239 +++++++++++++++++++++++++++++++++++++++++++++------- 4 files changed, 225 insertions(+), 36 deletions(-) diff --git a/gatchat/gatppp.c b/gatchat/gatppp.c index e92fe5d..b65733e 100644 --- a/gatchat/gatppp.c +++ b/gatchat/gatppp.c @@ -246,7 +246,7 @@ void ppp_auth_notify(GAtPPP *ppp, gboolean success) pppcp_signal_up(ppp->ipcp); } -void ppp_ipcp_up_notify(GAtPPP *ppp, const char *ip, +void ppp_ipcp_up_notify(GAtPPP *ppp, const char *local, const char *peer, const char *dns1, const char *dns2) { ppp->net = ppp_net_new(ppp); @@ -264,7 +264,8 @@ void ppp_ipcp_up_notify(GAtPPP *ppp, const char *ip, if (ppp->connect_cb) ppp->connect_cb(ppp_net_get_interface(ppp->net), - ip, dns1, dns2, ppp->connect_data); + local, peer, dns1, dns2, + ppp->connect_data); } void ppp_ipcp_down_notify(GAtPPP *ppp) @@ -464,6 +465,12 @@ void g_at_ppp_unref(GAtPPP *ppp) g_free(ppp); } +void g_at_ppp_set_server_info(GAtPPP *ppp, guint32 local, guint32 peer, + guint32 dns1, guint32 dns2) +{ + ipcp_set_server_info(ppp->ipcp, local, peer, dns1, dns2); +} + static GAtPPP *ppp_init_common(GAtHDLC *hdlc) { GAtPPP *ppp; diff --git a/gatchat/gatppp.h b/gatchat/gatppp.h index 438b952..aea4ec0 100644 --- a/gatchat/gatppp.h +++ b/gatchat/gatppp.h @@ -43,7 +43,8 @@ typedef enum _GAtPPPDisconnectReason { G_AT_PPP_REASON_LOCAL_CLOSE, /* Normal user close */ } GAtPPPDisconnectReason; -typedef void (*GAtPPPConnectFunc)(const char *iface, const char *ip, +typedef void (*GAtPPPConnectFunc)(const char *iface, const char *local, + const char *peer, const char *dns1, const char *dns2, gpointer user_data); typedef void (*GAtPPPDisconnectFunc)(GAtPPPDisconnectReason reason, @@ -68,6 +69,9 @@ const char *g_at_ppp_get_password(GAtPPP *ppp); void g_at_ppp_set_recording(GAtPPP *ppp, const char *filename); +void g_at_ppp_set_server_info(GAtPPP *ppp, guint32 local, guint32 peer, + guint32 dns1, guint32 dns2); + #ifdef __cplusplus } #endif diff --git a/gatchat/ppp.h b/gatchat/ppp.h index b6c5f4a..c41cd7f 100644 --- a/gatchat/ppp.h +++ b/gatchat/ppp.h @@ -86,6 +86,9 @@ void lcp_protocol_reject(struct pppcp_data *lcp, guint8 *packet, gsize len); /* IPCP related functions */ struct pppcp_data *ipcp_new(GAtPPP *ppp); void ipcp_free(struct pppcp_data *data); +void ipcp_set_server_info(struct pppcp_data *ipcp, guint32 local_addr, + guint32 peer_addr, + guint32 dns1, guint32 dns2); /* CHAP related functions */ struct ppp_chap *ppp_chap_new(GAtPPP *ppp, guint8 method); @@ -104,7 +107,7 @@ void ppp_debug(GAtPPP *ppp, const char *str); void ppp_transmit(GAtPPP *ppp, guint8 *packet, guint infolen); void ppp_set_auth(GAtPPP *ppp, const guint8 *auth_data); void ppp_auth_notify(GAtPPP *ppp, gboolean success); -void ppp_ipcp_up_notify(GAtPPP *ppp, const char *ip, +void ppp_ipcp_up_notify(GAtPPP *ppp, const char *local, const char *peer, const char *dns1, const char *dns2); void ppp_ipcp_down_notify(GAtPPP *ppp); void ppp_ipcp_finished_notify(GAtPPP *ppp); diff --git a/gatchat/ppp_ipcp.c b/gatchat/ppp_ipcp.c index 0b3c381..a0acf1b 100644 --- a/gatchat/ppp_ipcp.c +++ b/gatchat/ppp_ipcp.c @@ -67,46 +67,50 @@ struct ipcp_data { guint8 options[MAX_CONFIG_OPTION_SIZE]; guint16 options_len; guint8 req_options; - guint32 ipaddr; + guint32 local_addr; + guint32 peer_addr; guint32 dns1; guint32 dns2; guint32 nbns1; guint32 nbns2; + gboolean is_server; }; -#define FILL_IP(req, type, var) \ - if (req) { \ - ipcp->options[len] = type; \ - ipcp->options[len + 1] = 6; \ - memcpy(ipcp->options + len + 2, var, 4); \ - \ - len += 6; \ - } \ +#define FILL_IP(options, req, type, var) \ + if (req) { \ + options[len] = type; \ + options[len + 1] = 6; \ + memcpy(options + len + 2, var, 4); \ + \ + len += 6; \ + } \ static void ipcp_generate_config_options(struct ipcp_data *ipcp) { guint16 len = 0; - FILL_IP(ipcp->req_options & REQ_OPTION_IPADDR, - IP_ADDRESS, &ipcp->ipaddr); - FILL_IP(ipcp->req_options & REQ_OPTION_DNS1, + FILL_IP(ipcp->options, ipcp->req_options & REQ_OPTION_IPADDR, + IP_ADDRESS, &ipcp->local_addr); + FILL_IP(ipcp->options, ipcp->req_options & REQ_OPTION_DNS1, PRIMARY_DNS_SERVER, &ipcp->dns1); - FILL_IP(ipcp->req_options & REQ_OPTION_DNS2, + FILL_IP(ipcp->options, ipcp->req_options & REQ_OPTION_DNS2, SECONDARY_DNS_SERVER, &ipcp->dns2); - FILL_IP(ipcp->req_options & REQ_OPTION_NBNS1, + FILL_IP(ipcp->options, ipcp->req_options & REQ_OPTION_NBNS1, PRIMARY_NBNS_SERVER, &ipcp->nbns1); - FILL_IP(ipcp->req_options & REQ_OPTION_NBNS2, + FILL_IP(ipcp->options, ipcp->req_options & REQ_OPTION_NBNS2, SECONDARY_NBNS_SERVER, &ipcp->nbns2); ipcp->options_len = len; } -static void ipcp_reset_config_options(struct ipcp_data *ipcp) +static void ipcp_reset_client_config_options(struct ipcp_data *ipcp) { ipcp->req_options = REQ_OPTION_IPADDR | REQ_OPTION_DNS1 | REQ_OPTION_DNS2 | REQ_OPTION_NBNS1 | REQ_OPTION_NBNS2; - ipcp->ipaddr = 0; + + ipcp->local_addr = 0; + ipcp->peer_addr = 0; ipcp->dns1 = 0; ipcp->dns2 = 0; ipcp->nbns1 = 0; @@ -115,17 +119,53 @@ static void ipcp_reset_config_options(struct ipcp_data *ipcp) ipcp_generate_config_options(ipcp); } +static void ipcp_reset_server_config_options(struct ipcp_data *ipcp) +{ + if (ipcp->local_addr != 0) + ipcp->req_options = REQ_OPTION_IPADDR; + else + ipcp->req_options = 0; + + ipcp_generate_config_options(ipcp); +} + +void ipcp_set_server_info(struct pppcp_data *pppcp, guint32 local_addr, + guint32 peer_addr, + guint32 dns1, guint32 dns2) +{ + struct ipcp_data *ipcp = pppcp_get_data(pppcp); + + if (local_addr != 0) + ipcp->req_options = REQ_OPTION_IPADDR; + else + ipcp->req_options = 0; + + ipcp->local_addr = local_addr; + ipcp->peer_addr = peer_addr; + ipcp->dns1 = dns1; + ipcp->dns2 = dns2; + ipcp->is_server = TRUE; + + ipcp_generate_config_options(ipcp); + pppcp_set_local_options(pppcp, ipcp->options, ipcp->options_len); +} + static void ipcp_up(struct pppcp_data *pppcp) { struct ipcp_data *ipcp = pppcp_get_data(pppcp); - char ip[INET_ADDRSTRLEN]; + char local[INET_ADDRSTRLEN]; + char peer[INET_ADDRSTRLEN]; char dns1[INET_ADDRSTRLEN]; char dns2[INET_ADDRSTRLEN]; struct in_addr addr; - memset(ip, 0, sizeof(ip)); - addr.s_addr = ipcp->ipaddr; - inet_ntop(AF_INET, &addr, ip, INET_ADDRSTRLEN); + memset(local, 0, sizeof(local)); + addr.s_addr = ipcp->local_addr; + inet_ntop(AF_INET, &addr, local, INET_ADDRSTRLEN); + + memset(peer, 0, sizeof(peer)); + addr.s_addr = ipcp->peer_addr; + inet_ntop(AF_INET, &addr, peer, INET_ADDRSTRLEN); memset(dns1, 0, sizeof(dns1)); addr.s_addr = ipcp->dns1; @@ -135,7 +175,8 @@ static void ipcp_up(struct pppcp_data *pppcp) addr.s_addr = ipcp->dns2; inet_ntop(AF_INET, &addr, dns2, INET_ADDRSTRLEN); - ppp_ipcp_up_notify(pppcp_get_ppp(pppcp), ip[0] ? ip : NULL, + ppp_ipcp_up_notify(pppcp_get_ppp(pppcp), local[0] ? local : NULL, + peer[0] ? peer : NULL, dns1[0] ? dns1 : NULL, dns2[0] ? dns2 : NULL); } @@ -144,7 +185,11 @@ static void ipcp_down(struct pppcp_data *pppcp) { struct ipcp_data *ipcp = pppcp_get_data(pppcp); - ipcp_reset_config_options(ipcp); + if (ipcp->is_server) + ipcp_reset_server_config_options(ipcp); + else + ipcp_reset_client_config_options(ipcp); + pppcp_set_local_options(pppcp, ipcp->options, ipcp->options_len); ppp_ipcp_down_notify(pppcp_get_ppp(pppcp)); } @@ -160,6 +205,9 @@ static void ipcp_rca(struct pppcp_data *pppcp, struct ipcp_data *ipcp = pppcp_get_data(pppcp); struct ppp_option_iter iter; + if (ipcp->is_server) + return; + ppp_option_iter_init(&iter, packet); while (ppp_option_iter_next(&iter) == TRUE) { @@ -167,7 +215,7 @@ static void ipcp_rca(struct pppcp_data *pppcp, switch (ppp_option_iter_get_type(&iter)) { case IP_ADDRESS: - memcpy(&ipcp->ipaddr, data, 4); + memcpy(&ipcp->local_addr, data, 4); break; case PRIMARY_DNS_SERVER: memcpy(&ipcp->dns1, data, 4); @@ -193,6 +241,9 @@ static void ipcp_rcn_nak(struct pppcp_data *pppcp, struct ipcp_data *ipcp = pppcp_get_data(pppcp); struct ppp_option_iter iter; + if (ipcp->is_server) + return; + g_print("Received IPCP NAK\n"); ppp_option_iter_init(&iter, packet); @@ -204,7 +255,7 @@ static void ipcp_rcn_nak(struct pppcp_data *pppcp, case IP_ADDRESS: g_print("Setting suggested ip addr\n"); ipcp->req_options |= REQ_OPTION_IPADDR; - memcpy(&ipcp->ipaddr, data, 4); + memcpy(&ipcp->local_addr, data, 4); break; case PRIMARY_DNS_SERVER: g_print("Setting suggested dns1\n"); @@ -269,22 +320,146 @@ static void ipcp_rcn_rej(struct pppcp_data *pppcp, pppcp_set_local_options(pppcp, ipcp->options, ipcp->options_len); } -static enum rcr_result ipcp_rcr(struct pppcp_data *pppcp, +static void ipcp_generate_peer_config_options(struct ipcp_data *ipcp, + guint8 *options, + guint16 *new_len) +{ + guint16 len = 0; + + FILL_IP(options, TRUE, IP_ADDRESS, &ipcp->peer_addr); + FILL_IP(options, TRUE, PRIMARY_DNS_SERVER, &ipcp->dns1); + FILL_IP(options, TRUE, SECONDARY_DNS_SERVER, &ipcp->dns2); + + *new_len = len; +} + +static enum rcr_result ipcp_server_rcr(struct ipcp_data *ipcp, + const struct pppcp_packet *packet, + guint8 **new_options, guint16 *new_len) +{ + struct ppp_option_iter iter; + guint8 options[MAX_CONFIG_OPTION_SIZE]; + guint16 len = 0; + guint32 peer_addr = 0; + guint32 dns1 = 0; + guint32 dns2 = 0; + + ppp_option_iter_init(&iter, packet); + + while (ppp_option_iter_next(&iter) == TRUE) { + const guint8 *data = ppp_option_iter_get_data(&iter); + guint8 type = ppp_option_iter_get_type(&iter); + + switch (type) { + case IP_ADDRESS: + memcpy(&peer_addr, data, 4); + break; + case PRIMARY_DNS_SERVER: + memcpy(&dns1, data, 4); + break; + case SECONDARY_DNS_SERVER: + memcpy(&dns2, data, 4); + break; + case PRIMARY_NBNS_SERVER: + case SECONDARY_NBNS_SERVER: + default: + /* Reject */ + FILL_IP(options, TRUE, type, data); + break; + } + } + + if (len > 0) { + *new_len = len; + *new_options = g_memdup(options, len); + + return RCR_REJECT; + } + + /* Return Conf-Nak if we have not assign client address yet */ + if (ipcp->peer_addr == 0 && ipcp->dns1 == 0 && ipcp->dns2 == 0) + return RCR_NAK; + + /* Acknowledge client options if it matches with server options */ + if (ipcp->peer_addr == peer_addr && ipcp->dns1 == dns1 && + ipcp->dns2 == dns2) + return RCR_ACCEPT; + + /* Send client IP/DNS/NBNS information in the config options */ + ipcp_generate_peer_config_options(ipcp, options, &len); + + *new_len = len; + *new_options = g_memdup(options, len); + + return RCR_NAK; +} + +static enum rcr_result ipcp_client_rcr(struct ipcp_data *ipcp, const struct pppcp_packet *packet, guint8 **new_options, guint16 *new_len) { struct ppp_option_iter iter; + guint8 options[6]; + guint16 len = 0; + guint32 peer_addr = 0; + + /* Return Conf-Ack if we have received client info */ + if (ipcp->local_addr && ipcp->dns1 && ipcp->dns2) + return RCR_ACCEPT; ppp_option_iter_init(&iter, packet); - if (ppp_option_iter_next(&iter) == FALSE) + while (ppp_option_iter_next(&iter) == TRUE) { + const guint8 *data = ppp_option_iter_get_data(&iter); + guint8 type = ppp_option_iter_get_type(&iter); + + switch (type) { + case IP_ADDRESS: + memcpy(&peer_addr, data, 4); + break; + case PRIMARY_DNS_SERVER: + case SECONDARY_DNS_SERVER: + case PRIMARY_NBNS_SERVER: + case SECONDARY_NBNS_SERVER: + break; + default: + FILL_IP(options, TRUE, type, data); + break; + } + } + + if (len > 0) { + *new_len = len; + *new_options = g_memdup(options, len); + + return RCR_REJECT; + } + + /* Accept server IP address as peer's address */ + if (peer_addr) { + ipcp->peer_addr = peer_addr; return RCR_ACCEPT; + } + + /* Request server IP address */ + FILL_IP(options, TRUE, IP_ADDRESS, &ipcp->peer_addr); + + *new_len = len; + *new_options = g_memdup(options, len); + + return RCR_NAK; +} - /* Reject all options */ - *new_len = ntohs(packet->length) - sizeof(*packet); - *new_options = g_memdup(packet->data, *new_len); +static enum rcr_result ipcp_rcr(struct pppcp_data *pppcp, + const struct pppcp_packet *packet, + guint8 **new_options, guint16 *new_len) +{ + struct ipcp_data *ipcp = pppcp_get_data(pppcp); - return RCR_REJECT; + if (ipcp->is_server) + return ipcp_server_rcr(ipcp, packet, new_options, new_len); + else + return ipcp_client_rcr(ipcp, packet, new_options, new_len); } struct pppcp_proto ipcp_proto = { @@ -317,7 +492,7 @@ struct pppcp_data *ipcp_new(GAtPPP *ppp) } pppcp_set_data(pppcp, ipcp); - ipcp_reset_config_options(ipcp); + ipcp_reset_client_config_options(ipcp); pppcp_set_local_options(pppcp, ipcp->options, ipcp->options_len); return pppcp; -- 1.6.3.3 ^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2010-06-25 3:19 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2010-06-21 9:47 [PATCH 1/5] gatppp: Add PPP server extension Zhenhua Zhang 2010-06-21 9:47 ` [PATCH 2/5] atmodem: Fix GAtPPPConnectFunc interface change Zhenhua Zhang 2010-06-21 9:48 ` [PATCH 3/5] test-server: Add PPP server support Zhenhua Zhang 2010-06-21 9:48 ` [PATCH 4/5] test-server: Configure network interface Zhenhua Zhang 2010-06-21 9:48 ` [PATCH 5/5] gsmdial: Configure network interface for PPP Zhenhua Zhang 2010-06-22 4:36 ` [PATCH 1/5] gatppp: Add PPP server extension Denis Kenzior 2010-06-22 6:24 ` Zhang, Zhenhua -- strict thread matches above, loose matches on Subject: below -- 2010-06-25 3:19 [PATCH 0/5] Add PPP server support Zhenhua Zhang 2010-06-25 3:19 ` [PATCH 1/5] gatppp: Add PPP server extension Zhenhua Zhang
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox