Authenticating the Client

The following code shows how the code (in jnx_gw_ctrl_gre_gw_msg_handler in the jnx-gateway-ctrl_gre.c file) authenticates the client on receipt of the JNX_GW_CTRL_GRE_SESN_INIT_REQ message.

First, the code interprets the messages and calls the appropriate function:

 /* while message length, for the gre gateway, process
     * the message
    pgre_msg = pmsg; 
    while (len < msg_len) {

        switch(pgre_msg->msg_type) {
            case JNX_GW_CTRL_GRE_SESN_INIT_REQ:
                jnx_gw_ctrl_sig_gre_session_add(pvrf, pgre_gw, pgre_msg);
            case JNX_GW_CTRL_GRE_SESN_END_REQ:
            case JNX_GW_CTRL_GRE_SESN_ERR_REQ:
            case JNX_GW_CTRL_GRE_SESN_ERR:
                jnx_gw_ctrl_sig_gre_session_delete(pvrf, pgre_gw, pgre_msg);

Once the jnx_gw_ctrl_sig_gre_session_add() function is called, it creates variables for the structures shown in Data Structures, and fills in the structures with the values in the incoming message.

jnx_gw_ctrl_sig_gre_session_add(jnx_gw_ctrl_vrf_t     *pvrf,
                             jnx_gw_ctrl_gre_gw_t  *pgre_gw, 
                             jnx_gw_ctrl_gre_msg_t *pmsg)
    jnx_gw_ctrl_gre_session_t * pgre_session, gre_config;
    jnx_gw_ctrl_clnt_5t_info_t * puser_info;

    /* get the user information from the init request message */
    puser_info = &pmsg->user_5t;

    /* memset */
    memset(&gre_config, 0, sizeof(gre_config));

    gre_config.sesn_msgid     = ntohl(pmsg->msg_id);
    gre_config.sesn_flags     = pmsg->flags;
    gre_config.sesn_proto     = puser_info->proto;
    gre_config.sesn_dport     = ntohs(puser_info->dst_port);
    gre_config.sesn_sport     = ntohs(puser_info->src_port);
    gre_config.sesn_server_ip = ntohl(puser_info->dst_ip);
    gre_config.sesn_client_ip = ntohl(puser_info->src_ip);

    gre_config.ingress_gw_ip  = pgre_gw->gre_gw_ip;
    gre_config.ingress_vrf_id = pvrf->vrf_id;

    gre_config.pingress_vrf   = pvrf;
    gre_config.pgre_gw        = pgre_gw;

If no session exists, the code then calls jnx_gw_ctrl_match_user() to verify the user profile:

/* check whether the session exists */
    pgre_session = jnx_gw_ctrl_get_valid_gre_session(pvrf, pgre_gw,

    if (pgre_session) {

        if (pgre_session->sesn_msgid == gre_config.sesn_msgid) {
            return EOK;

        /* if fail, send error message  & return */
        gre_config.sesn_errcode = JNX_GW_MSG_ERR_GRE_SESS_EXISTS;

        goto sesn_add_fail;

    /* match  user profile */
    if (jnx_gw_ctrl_match_user(&gre_config) == EFAIL) {

        /* if fail, send error message  & return */
        gre_config.sesn_errcode = JNX_GW_MSG_ERR_SESSION_AUTH_FAIL;
        goto sesn_add_fail;

jnx_gw_ctrl_match_user() is in the jnx-gateway-ctrl_ctrl.c file. This file contains pointers to database tables that represent the sessions, gateways, control policies, and interfaces the application is processing.

The function attempts to find a matching user policy for a new GRE session; if it succeeds, it extracts the egress VRF and IP-in-IP gateway information to allow packets to be forewarded from the GRE gateway to the IP-in-IP gateway.

The function calls the function jnx_gw_ctrl_get_next_user() to walk a patricia tree and retrieve each policy. The called function is defined as follows.

patricia_find_next() is defined along with the other patricia tree functions in in src/juniper/lib/libjuniper/h/jnx/patricia.h.

jnx_gw_ctrl_user_t *
jnx_gw_ctrl_get_next_user(jnx_gw_ctrl_user_t * puser)
    if (puser == NULL) {
        return jnx_gw_ctrl_get_first_user();
    return jnx_gw_ctrl_user_entry(patricia_find_next(&jnx_gw_ctrl.user_db,

The patricia_find_next() function is declared along with the other public patricia tree functions in src/juniper/lib/libjuniper/h/jnx/patricia.h.

When it retrieves a user entry, jnx_gw_ctrl_match_user() first decides whether the session already exists, and continues only if not:

jnx_gw_ctrl_match_user(jnx_gw_ctrl_gre_session_t * pgre_session)
    jnx_gw_ctrl_user_t * puser = NULL;
    jnx_gw_ctrl_ipip_gw_t * pipip_gw = NULL;
    uint32_t user_subnet, sesn_subnet;

    while ((puser = jnx_gw_ctrl_get_next_user(puser))) {

        /* match the subnets */

        user_subnet = (puser->user_addr & puser->user_mask);
        sesn_subnet = (pgre_session->sesn_client_ip & puser->user_mask);

        if (user_subnet != sesn_subnet) {

Next, the function extracts the egress VRF and IP-in-IP gateway addresses:

 pipip_gw = puser->pipip_gw;
        /* the ipip gateway does not have any
           active vrf interfaces on data pics
           configured with */
        if (pipip_gw) {
            if (pipip_gw->ipip_gw_status != JNX_GW_CTRL_STATUS_UP)
        pgre_session->puser          = puser;
        pgre_session->pegress_vrf    = puser->pvrf;
        pgre_session->pipip_gw       = puser->pipip_gw;
        pgre_session->egress_gw_ip   = puser->user_ipip_gw_ip;
        pgre_session->egress_vrf_id  = puser->user_evrf_id;
        return EOK;

2007-2009 Juniper Networks, Inc. All rights reserved. The information contained herein is confidential information of Juniper Networks, Inc., and may not be used, disclosed, distributed, modified, or copied without the prior written consent of Juniper Networks, Inc. in an express license. This information is subject to change by Juniper Networks, Inc. Juniper Networks, the Juniper Networks logo, and JUNOS are registered trademarks of Juniper Networks, Inc. in the United States and other countries. All other trademarks, service marks, registered trademarks, or registered service marks are the property of their respective owners.
Generated on Sun May 30 20:26:47 2010 for Juniper Networks Partner Solution Development Platform JUNOS SDK 10.2R1 by Doxygen 1.4.5