[PATCH 03/11] gatppp: Add PPP server extension
Denis Kenzior
denkenz at gmail.com
Fri Jun 18 10:49:33 PDT 2010
Hi Zhenhua,
> 1. Add interface to set PPP server info by g_at_ppp_set_server_info.
> 2. Pass local and peer address through IPCP handshaking.
> ---
Its great that you're working on the PPP Server extensions. Can I get you to
submit a patch taking ownership of this task? See ofono/TODO 'PPP Server
support'.
> +static void ipcp_generate_peer_config_options(struct ipcp_data *ipcp)
> +{
> + guint16 len = 0;
> +
> + FILL_IP(ipcp->req_options & REQ_OPTION_IPADDR,
> + IP_ADDRESS, &ipcp->peer_addr);
> + FILL_IP(ipcp->req_options & REQ_OPTION_DNS1,
> + PRIMARY_DNS_SERVER, &ipcp->dns1);
> + FILL_IP(ipcp->req_options & REQ_OPTION_DNS2,
> + SECONDARY_DNS_SERVER, &ipcp->dns2);
> + FILL_IP(ipcp->req_options & REQ_OPTION_NBNS1,
> + PRIMARY_NBNS_SERVER, &ipcp->nbns1);
> + FILL_IP(ipcp->req_options & REQ_OPTION_NBNS2,
> + SECONDARY_NBNS_SERVER, &ipcp->nbns2);
> +
Using ipcp->req_options is the wrong thing here. That is used for options
sent in a Configure-Req. Here you're filling in options to be sent in a
Configure-Nak, Configure-Reject or a Configure-Ack. You should simply be filling
these in ipcp_rcr. Feel free to modify the FILL_IP macro to take an
additional destination parameter.
> + ipcp->options_len = len;
> +}
> +
> +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 | REQ_OPTION_DNS1 |
> + REQ_OPTION_DNS2 | REQ_OPTION_NBNS1 |
> + REQ_OPTION_NBNS2;
> +
> + ipcp->local_addr = local_addr;
> + ipcp->peer_addr = peer_addr;
> + ipcp->dns1 = dns1;
> + ipcp->dns2 = dns2;
> + ipcp->nbns1 = nbns1;
> + ipcp->nbns2 = nbns2;
> +
> + ipcp_generate_config_options(ipcp);
Please note that this function is currently having no effect, you're missing a
call to pppcp_set_local_options. However, in the case of a server, we
actually do not want to request DNS or NBNS, and we should only send our local
address to the peer if it is non-zero. Please note that all PPP modems we
have encountered so far, do not send their local IP address in a Configure-
Request. Thus calling ipcp_set_server_info should end up generating an empty
Configure-Request or with only the local IP address present.
> +}
> +
> static void ipcp_reset_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;
In the case of a server, the local_address should not be reset.
> + ipcp->peer_addr = 0;
> ipcp->dns1 = 0;
> ipcp->dns2 = 0;
> ipcp->nbns1 = 0;
> @@ -274,11 +321,54 @@ static enum rcr_result ipcp_rcr(struct pppcp_data
> *pppcp, guint8 **new_options, guint16 *new_len)
> {
> struct ppp_option_iter iter;
> + struct ipcp_data *ipcp = pppcp_get_data(pppcp);
> + guint32 peer_addr;
> + guint32 dns1;
> + guint32 dns2;
>
> ppp_option_iter_init(&iter, packet);
>
> - if (ppp_option_iter_next(&iter) == FALSE)
> - return RCR_ACCEPT;
Again, be careful here. In the case of a client we should only accept the
Server's IP-Address, nothing else.
> + 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;
> + default:
> + break;
> + }
> + }
> +
> + if (peer_addr && dns1 && dns2) {
> + if (ipcp->peer_addr == 0) {
> + /* RFC 1332 Section 3.3
> + * Accept the value of IP address as peer IP address
> + */
> + ipcp->peer_addr = peer_addr;
> +
This part doesn't really make any sense, if peer is sending 0, he's asking us
for an IP.
> + return RCR_ACCEPT;
> + } else if (ipcp->peer_addr == peer_addr)
> + return RCR_ACCEPT;
You need to ensure that not only the peer_addr matches, but also the dns /
nbns addresses. In our case we should be Configure-Rejecting the NBNS options
and Configure-Naking DNS ones if they're set to zero or don't match what the
peer is sending us.
> + } else {
> + /* Peer requests us to send ip address in config options */
> + if (ipcp->peer_addr) {
> + struct ipcp_data *peer;
> +
> + peer = g_memdup(ipcp, sizeof(struct ipcp_data));
> + ipcp_generate_peer_config_options(peer);
Yuck, please don't do this. The main PPPCP layer will take care of freeing
new_options, however you're now leaking the rest of the ipcp_data structure.
> +
> + *new_len = peer->options_len;
> + *new_options = peer->options;
> + return RCR_NAK;
> + }
> + }
>
> /* Reject all options */
> *new_len = packet->length - sizeof(*packet);
>
Regards,
-Denis
More information about the ofono
mailing list