Hi Denis,

Denis Kenzior wrote:
> 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.
> 
> Ok getting pretty close now :)
> 
>> +static void ipcp_reset_server_config_options(struct ipcp_data
>> *ipcp) +{ +  ipcp->req_options = REQ_OPTION_IPADDR;
> 
> Might want to only request IP Addr if local_addr is not zero.
> Just like in
> set_server_info.

Ok. Local updated.
 
>> +
>> +    ipcp_generate_config_options(ipcp);
>> +}
>> +
> 
> <snip>
> 
>> @@ -167,7 +211,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);
> 
> You might not want to do anything here in the case of a server role.

Agree. So in case of a server role, we simply do nothing in ipcp_rca and 
ipcp_rcn_nak. Good catch.

>> @@ -204,7 +248,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");
> 
> Again, probably don't want to set the local_addr in the case
> of a server role.
> 
>> @@ -269,17 +313,102 @@ 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;
> 
> Don't use MAX_CONFIG_OPTION_SIZE, instead use len (which is
> filled properly by
> the FILL_IP macro)  Also, we shouldn't bother supporting NBNS,
> lets never
> suggest those options as a server or set them in set_server_info.

Fixed, so I have removed NBNS parameters for set_server_info() at all.

>> +
>> +    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)
>> +    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;
>> +            }
>> +    }
>> +
> 
> As mentioned above, if Primary / Secondary NBNS server is sent
> by the client,
> we need to Conf-Rej just those options to the client.  Any
> other unrecognized
> options should also be Conf-Rejected.  The order is important
> here, read the
> spec for details.  The IP Address, DNS1/DNS2 should not be
> Conf-Rejected. 

Looks like we need more Conf-Nak than Conf-Reject in ipcp_rcr. :-)

As PPP client, actually I think we don't need to send NBNS request at all. It's 
clear that pppd client only requests IP/DNS in Conf-Req. Secondly, if server 
sent us empty Conf-Req, the client should request server IP address in Conf-Nak 
response, instead of Conf-Rej all options. Once we get local_addr from server, 
we return Conf-Ack in ipcp_rcr and don't request server IP any more.

See attached pppd.log for details.

>> +    if (ipcp->is_server) {
>> +            guint8 *options;
>> +            guint16 len;
>> +
>> +            /* Reject if we have not assign client address yet */
>> +            if (ipcp->peer_addr == 0 && ipcp->dns1 == 0 && ipcp->dns2 == 0)
>> +                    goto reject;
> 
> Actually you should be NAKing here, not Rejecting.  Reject
> means you don't
> support this option at all.

Okay.

>> +
>> +            /* Acknowledge client options if it matches with server options
>> +             */ +           if (ipcp->peer_addr == peer_addr &&
>> +                            ipcp->dns1 == dns1 &&
> ipcp->dns2 == dns2 &&
>> +                            ipcp->nbns1 == nbns1 &&
> ipcp->nbns2 == nbns2)
>> +                    return RCR_ACCEPT;
>> +
>> +            /* Send client IP/DNS/NBNS information in the config options */
>> +            options = ipcp_generate_peer_config_options(ipcp, &len); +      
>>         if
>> (!options) +                 goto reject;
>> +
>> +            *new_len = len;
>> +            *new_options = options;
>> +
>> +            return RCR_NAK;
>> +    }
>> +
>> +    /* Client */
>> +    if (peer_addr && ipcp->peer_addr == 0) {
>> +            /* RFC 1332 section 3.3
>> +             * As client, accept the server IP as peer's address +          
>>  */
>> +            ipcp->peer_addr = peer_addr;
>> +

As client, can we just accept peer_addr as long as it's no zero, and return 
Conf-Ack? No matter what ipcp->peer_addr is.

>>              return RCR_ACCEPT;
>> +    }
>> 
>> +reject:
>>      /* Reject all options */
>>      *new_len = ntohs(packet->length) - sizeof(*packet);
>>      *new_options = g_memdup(packet->data, *new_len);
>> @@ -317,7 +446,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;
>> 
> 
> Regards,
> -Denis



Regards,
Zhenhua

_______________________________________________
ofono mailing list
[email protected]
http://lists.ofono.org/listinfo/ofono

Reply via email to