Files
2026-07-30 11:19:44 +05:30

975 lines
30 KiB
C

/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipl2tp_example_v3.c,v $ $Revision: 1.13.10.4 $
* $Source: /home/interpeak/CVSRoot/ipl2tp/config/ipl2tp_example_v3.c,v $
* $Author: jren $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Joel Hortelius <joel.hortelis@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#define IPCOM_USE_CLIB_PROTO
#include "ipcom_clib.h"
#include "ipcom_clib2.h"
#include "ipcom_err.h"
#include "ipcom_ipd.h"
#include "ipcom_os.h"
#include "ipcom_shell.h"
#include "ipcom_sock2.h"
#include "ipcom_syslog.h"
#include "ipcom_type.h"
#include "ipcom_hash.h"
#include "ipcom_sysvar.h"
#include "ipcom_netif.h"
#include "ipcom_strlib.h"
#include "ipl2tp_h.h"
#include "ipl2tp_api.h"
#include "ipl2tp_api_tunnel.h"
#include "ipl2tp_api_session.h"
#include "ipl2tp_attr.h"
#include "ipl2tp_cmd.h"
#include "ipl2tp_example.h"
#include "ipl2tp_example_v3.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
typedef struct Ipl2tp_v3_circuit
{
char *name;
char *intf;
Ip_u32 ifnum;
int pw_type;
int vlan_tag;
}
Ipl2tp_v3_circuit_t;
typedef struct Ipl2tp_v3_ethernet_circuit
{
Ipl2tp_example_session_t session;
Ipl2tp_example_fd_entry_t *fd_eth;
}
Ipl2tp_v3_ethernet_circuit_t;
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipl2tp_eth_data_cb
*===========================================================================
* Description: Data callback.
* Parameters: user_data - User callback data.
* buffer - Original data buffer.
* payload - Payload pointer in data buffer.
* length - Length of payload.
* Returns:
*
*/
IP_STATIC void
ipl2tp_example_session_eth_data_output(void *user_data,
Ipl2tp_key *key,
void *buffer,
void *payload,
Ip_u16 length)
{
Ipl2tp_v3_ethernet_circuit_t *session = user_data;
IPL2TP_UNUSED(key);
IPL2TP_UNUSED(buffer);
/* Do the write */
if (session != IP_NULL)
{
struct Ip_sockaddr_ll to_ll;
Ipl2tp_v3_circuit_t *circuit = session->session.circuit;
/* Modify the frame */
if (circuit->pw_type == IPL2TP_ATTR_PW_TYPE_ETHERNET_VLAN &&
circuit->vlan_tag != 0)
{
Ip_u8 *frame = payload;
Ip_u16 vid = IP_GET_HTONS(frame + 14);
vid = (Ip_u16)(vid & 0xf000);
vid = (Ip_u16)(vid | (Ip_u16)(circuit->vlan_tag & 0x0fff));
IP_SET_HTONS(frame + 14, vid);
}
ipcom_memset(&to_ll, 0, sizeof(to_ll));
to_ll.sll_len = (Ip_u8)sizeof(to_ll);
to_ll.sll_family = IP_AF_PACKET;
to_ll.sll_ifindex = circuit->ifnum;
if (ipcom_sendto(session->fd_eth->fd, payload, length, 0,
(struct Ip_sockaddr *)&to_ll, sizeof(to_ll)) < 0)
{
IPCOM_LOG0(ERR, "IPL2TPv3: Error in ipcom send");
}
}
}
IP_STATIC void
ipl2tp_example_session_eth_data_input(Ipl2tp_example_fd_entry_t *entry,
void *buffer,
void *data,
Ip_size_t size)
{
Ip_ptrdiff_t offset = (Ip_u8 *)data - (Ip_u8 *)buffer;
/* Get the eth session ID */
Ipl2tp_v3_ethernet_circuit_t *session = entry->ptr;
/* Done */
ipl2tp_api_session_ethernet_input(&session->session.key,
data,
(int)size,
(int)offset,
0,
IP_TRUE);
}
/*
*===========================================================================
* ipl2tp_example_session_check_eth_interface
*===========================================================================
* Description: Determine if interface is currently in use by another circuit
* Parameters: key: session key of sessio to be compared against
* intf: name of interface
* Returns: 1 if the interface is currently in use by another session
* 0 otherwise
*
*/
IP_STATIC int
ipl2tp_example_session_check_eth_interface(Ipl2tp_key * key, char * intf)
{
Ipl2tp_status status;
Ipl2tp_key this_tkey, next_tkey;
Ipl2tp_key this_skey, next_skey;
Ipl2tp_v3_circuit_t *circuit;
Ipl2tp_v3_ethernet_circuit_t *session;
if ((intf == IP_NULL) || (ipcom_strlen(intf) == 0))
return (0);
/* Get the first tunnel, if there is one */
this_tkey.ident = 0;
this_tkey.version = IPL2TP_VERSION_L2TPV3;
if ((status = ipl2tp_api_tunnel_next(&this_tkey, &next_tkey)) != IPL2TP_STATUS_OK)
return (0);
/* Go through all tunnels */
while (status == IPL2TP_STATUS_OK)
{
/* If status is OK, next_tkey.ident must be non-zero */
this_tkey.ident = next_tkey.ident;
/* Get the first session if there is one */
if ((status = ipl2tp_api_session_next(&this_tkey, IP_NULL, &next_skey)) != IPL2TP_STATUS_OK)
continue;
/* Go through all sessions in this tunnel */
while (status == IPL2TP_STATUS_OK)
{
/* If status is OK, next_skey.ident must be non-zero, so use it */
this_skey.ident = next_skey.ident;
this_skey.version = next_skey.version;
/* Check the version - this only applies to version 3 */
if (this_skey.version != IPL2TP_VERSION_L2TPV3)
continue;
/* Check for a match, if the session is different */
if (this_skey.ident != key->ident)
{
session = ipcom_hash_get(ipl2tp_example_sessions, &this_skey);
if (session == IP_NULL)
continue;
/* Check the interface name */
circuit = (Ipl2tp_v3_circuit_t *)session->session.circuit;
if (ipcom_strcmp(circuit->intf, intf) == 0)
return (1);
}
/* Get the next session, if there is one */
status = ipl2tp_api_session_next(&this_tkey, &this_skey, &next_skey);
}
/* Get the next tunnel if there is one */
status = ipl2tp_api_tunnel_next(&this_tkey, &next_tkey);
}
return (0);
}
/*
*===========================================================================
* ipl2tp_example_session_eth_destroy
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC void
ipl2tp_example_session_eth_destroy(Ipl2tp_key *key)
{
Ipl2tp_v3_ethernet_circuit_t *session = ipcom_hash_get(ipl2tp_example_sessions, key);
if (session != IP_NULL)
{
struct Ip_ifreq ifreq;
Ipl2tp_attrobj attr = IP_NULL;
Ipl2tp_v3_circuit_t *circuit = session->session.circuit;
if (ipl2tp_example_session_check_eth_interface(key, circuit->intf) == 0)
{
IPCOM_LOG1(DEBUG, "Interface %s has no other users", circuit->intf);
/* OK to turn off promisc mode */
ipcom_memset(&ifreq, 0, sizeof(struct Ip_ifreq));
ipcom_strncpy(ifreq.ifr_name, circuit->intf, IP_IFNAMSIZ - 1);
if (ipcom_socketioctl(session->fd_eth->fd, IP_SIOCGIFFLAGS, &ifreq) < 0)
IPCOM_LOG1(ERR,
"IPL2TPv3: failed to get interface flags: %s",
ipcom_strerror(ipcom_errno));
else
{
IP_BIT_CLR(ifreq.ip_ifr_flags, IP_IFF_PROMISC);
if (ipcom_socketioctl(session->fd_eth->fd, IP_SIOCSIFFLAGS, &ifreq) < 0)
IPCOM_LOG1(ERR,
"IPL2TPv3: failed to set interface flags: %s",
ipcom_strerror(ipcom_errno));
}
}
else
IPCOM_LOG1(DEBUG, "Interface %s does have other users", circuit->intf);
/* Remove the object */
ipcom_hash_remove(ipl2tp_example_sessions, session);
/* Remove the socket */
session->fd_eth->data = IP_NULL;
session->fd_eth = IP_NULL;
/* Free the session */
ipcom_free(session->session.circuit);
ipcom_free(session);
/* Set the user data */
if (ipl2tp_attr_pappend(&attr,
IPL2TP_SATTR_SET_USER_DATA,
IP_NULL) == IPL2TP_STATUS_OK)
{
ipl2tp_api_session_attribute_set(key, attr);
ipl2tp_attr_delete(&attr);
}
}
}
/*
*===========================================================================
* ipl2tp_example_session_eth_create
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ipl2tp_v3_ethernet_circuit_t *
ipl2tp_example_session_eth_create(Ipl2tp_v3_circuit_t *circuit,
Ipl2tp_key *key)
{
Ipl2tp_v3_ethernet_circuit_t *session;
Ipl2tp_attrobj attr = IP_NULL;
struct Ip_ifreq ifreq;
Ipl2tp_callback cb;
session = ipcom_calloc(1, sizeof(*session));
if (session == IP_NULL)
goto fail;
ipcom_memcpy(&session->session.key, key, sizeof(*key));
session->session.circuit = circuit;
session->fd_eth = ipcom_malloc(sizeof(*session->fd_eth));
if (session->fd_eth == IP_NULL)
goto fail;
/* Create socket for catching packets destined to proxied MNs */
session->fd_eth->fd = ipcom_socket(IP_AF_PACKET, IP_SOCK_RAW, 0);
if (session->fd_eth->fd == IP_INVALID_SOCKET)
goto fail;
/* Bind raw socket to device */
if (ipcom_setsockopt(session->fd_eth->fd, IP_SOL_SOCKET, IP_SO_BINDTODEVICE,
circuit->intf, IP_IFNAMSIZ) == IP_SOCKERR)
{
ipcom_socketclose(session->fd_eth->fd);
goto fail;
}
ipcom_memset(&ifreq, 0, sizeof(struct Ip_ifreq));
ipcom_if_indextoname(circuit->ifnum, ifreq.ifr_name);
if (ipcom_socketioctl(session->fd_eth->fd, IP_SIOCGIFFLAGS, &ifreq) < 0)
{
IPCOM_LOG1(ERR,
"IPL2TPv3: failed to get interface flags: %s",
ipcom_strerror(ipcom_errno));
goto fail;
}
IP_BIT_SET(ifreq.ip_ifr_flags, IP_IFF_PROMISC);
if (ipcom_socketioctl(session->fd_eth->fd, IP_SIOCSIFFLAGS, &ifreq) < 0)
{
IPCOM_LOG1(ERR,
"IPL2TPv3: failed to set interface flags: %s",
ipcom_strerror(ipcom_errno));
goto fail;
}
session->fd_eth->ptr = session;
session->fd_eth->data = ipl2tp_example_session_eth_data_input;
if (ipcom_hash_add(ipl2tp_example_sessions, session) != IPCOM_SUCCESS)
{
IPCOM_LOG0(ERR, "IPL2TPv3: failed to add session");
goto fail;
}
ipcom_list_insert_last(&ipl2tp_example_fds, &session->fd_eth->next);
/* Set the user data */
if (ipl2tp_attr_pappend(&attr,
IPL2TP_SATTR_SET_USER_DATA,
session) != IPL2TP_STATUS_OK)
{
IPCOM_LOG0(ERR, "IPL2TPv3: failed to set sesion user data");
goto fail;
}
/* Set the data callback */
cb.eth_callback = (Ipl2tp_eth_callback)ipl2tp_example_session_eth_data_output;
if (ipl2tp_attr_pappend(&attr,
IPL2TP_SATTR_SET_DATA_CALLBACK,
(void *)cb.voidptr) != IPL2TP_STATUS_OK ||
ipl2tp_attr_iappend(&attr,
IPL2TP_SATTR_SET_LOCAL_CIRCUIT_STATUS,
IPL2TP_MIB_UP) != IPL2TP_STATUS_OK)
{
IPCOM_LOG0(WARNING, "IPL2TPv3: failed to set attributes");
}
ipl2tp_api_session_attribute_set(key, attr);
ipl2tp_attr_delete(&attr);
return session;
fail:
if (session)
{
if (session->fd_eth)
ipcom_free(session->fd_eth);
ipcom_free(session);
}
ipcom_free(circuit);
return IP_NULL;
}
/*
*===========================================================================
* ipl2tp_example_session_to_link
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ipl2tp_v3_circuit_t *
ipl2tp_example_session_to_circuit(Ipl2tp_key *key,
int type)
{
Ipl2tp_v3_circuit_t *circuit;
Ipl2tp_attrobj replies = IP_NULL;
Ipl2tp_attrobj attr = IP_NULL;
Ipl2tp_attr a;
Ip_u32 id;
char buf[128];
char *ctype;
int i;
int argc;
char **argv = IP_NULL;
ipl2tp_api_session_attribute_query(key,
IPL2TP_SATTR_GET_REMOTE_END_ID,
&replies);
if ((a = ipl2tp_attr_first(replies)) == IP_NULL)
return IP_NULL;
if (ipl2tp_attr_length(a) != 4)
return IP_NULL;
/* Get the router ID */
id = IP_GET_NTOHL(ipl2tp_attr_vdata(a));
ipl2tp_attr_delete(&replies);
/* Parse the circuit */
circuit = ipcom_calloc(1, sizeof(*circuit));
if(circuit == IP_NULL)
{
return IP_NULL;
}
/* */
ipcom_snprintf(buf, sizeof(buf), "ipl2tp.v3.circuit.%ld.name", id);
if ((circuit->name = ipcom_sysvar_get(buf, IP_NULL, IP_NULL)) == IP_NULL)
goto fail;
ipcom_snprintf(buf, sizeof(buf), "ipl2tp.v3.circuit.%ld.interface", id);
if ((circuit->intf = ipcom_sysvar_get(buf, IP_NULL, IP_NULL)) == IP_NULL)
goto fail;
ipcom_snprintf(buf, sizeof(buf), "ipl2tp.v3.circuit.%ld.attributes", id);
if ((ctype = ipcom_sysvar_get(buf, IP_NULL, IP_NULL)) == IP_NULL)
{
ipcom_snprintf(buf, sizeof(buf), "ipl2tp.v3.circuit.any.attributes");
if ((ctype = ipcom_sysvar_get(buf, IP_NULL, IP_NULL)) == IP_NULL)
goto fail;
}
/* Got the argument vector; time to explode it */
if (ipcom_parse_argstr(ctype, (int *)&argc, &argv) != 0)
{
ipcom_free(ctype);
goto fail;
}
for (i = 0; i < argc; i++)
{
char *value;
Ipl2tp_attr_info *info;
/**/
if ((info = ipl2tp_api_attribute_find(ipl2tp_session_tags, argv[i], &value)) == IP_NULL)
{
IPCOM_LOG2(ERR,
"L2TP: circuit %s: Invalid attribute %s",
circuit->name, argv[i]);
continue;
}
if (ipl2tp_api_attribute_parse(&attr,info,&value) == IP_FALSE)
{
IPCOM_LOG3(ERR,
"L2TP: circuit %s: Invalid attribute %s and value %s",
circuit->name, argv[i], value);
continue;
}
}
ipl2tp_api_session_attribute_set(key,attr);
ipl2tp_attr_delete(&attr);
ipcom_free(argv);
ipcom_free(ctype);
/* Retrieve the pseudowire type of the session */
ipl2tp_api_session_attribute_query(key,
IPL2TP_SATTR_GET_PSEUDOWIRE_TYPE,
&replies);
if((a = ipl2tp_attr_first(replies)) == IP_NULL)
{
ipl2tp_attr_delete(&replies);
goto fail;
}
/* Does it match? */
circuit->pw_type = ipl2tp_attr_idata(a);
ipl2tp_attr_delete(&replies);
if (circuit->pw_type != type)
{
IPCOM_LOG3(ERR,
"L2TP: circuit %s: Invalid pseudowire %u vs %u",
circuit->name,
circuit->pw_type,
type);
goto fail;
}
/* No interface */
if ((circuit->ifnum = ipcom_if_nametoindex(circuit->intf)) == 0)
goto fail;
/* VLAN tag */
ipcom_snprintf(buf, sizeof(buf), "ipl2tp.v3.circuit.%ld.vlan", id);
circuit->vlan_tag = ipcom_sysvar_get_as_int0(buf, 0);
return circuit;
fail:
if (circuit->name != IP_NULL)
ipcom_free(circuit->name);
if (circuit->intf != IP_NULL)
ipcom_free(circuit->intf);
ipcom_free(circuit);
return IP_NULL;
}
/*
*===========================================================================
* ipl2tp_example_session_eth_setup
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC Ipl2tp_v3_ethernet_circuit_t *
ipl2tp_example_session_eth_setup(Ipl2tp_key *key,
int type)
{
Ipl2tp_v3_circuit_t *circuit;
/* Destroy any previous sessions */
ipl2tp_example_session_eth_destroy(key);
/* Setup this end of the tunnel */
if ((circuit = ipl2tp_example_session_to_circuit(key, type)) == IP_NULL)
return IP_NULL;
/* Create the session */
return ipl2tp_example_session_eth_create(circuit, key);
}
/*
*===========================================================================
* ipl2tp_example_session_eth_status
*===========================================================================
* Description: Session status callback.
* Parameters: user_data - User callback data.
* key - Session ID.
* status - Pointer to status info.
* Returns:
*
*/
IP_STATIC int
ipl2tp_example_session_eth_status(void *user_data,
Ipl2tp_key *key,
Ipl2tp_result *result,
int type)
{
Ipl2tp_v3_ethernet_circuit_t *session = user_data;
switch (result->status)
{
case IPL2TP_STATUS_OK:
switch (result->result_code)
{
case IPL2TP_OUTGOING_REQUEST:
{
/* Setup */
if ((session = ipl2tp_example_session_eth_setup(key, type)) == IP_NULL)
return IPL2TP_STATUS_BADID;
IPCOM_LOG4(DEBUG,
"IPL2TPv3: SESSION (IPL2TP_OUTGOING_REQUEST) session[%s] v%d %d %s",
((Ipl2tp_v3_circuit_t *)session->session.circuit)->name,
key->version, key->ident,
ipl2tp_api_session_type(key));
break;
}
case IPL2TP_OUTGOING_REPLY:
{
IPCOM_LOG3(DEBUG,
"IPL2TPv3: SESSION (IPL2TP_OUTGOING_REPLY) v%d %d %s",
key->version, key->ident,
ipl2tp_api_session_type(key));
ipl2tp_api_session_outgoing_established(key, 0, 0, "");
break;
}
case IPL2TP_OUTGOING_ESTABLISHED:
/* */
if (session == IP_NULL)
{
/* Setup */
if ((session = ipl2tp_example_session_eth_setup(key, type)) == IP_NULL)
return IPL2TP_STATUS_BADID;
}
IPCOM_LOG4(DEBUG,
"IPL2TPv3: SESSION (IPL2TP_OUTGOING_ESTABLISHED) session[%s] v%d %d %s",
((Ipl2tp_v3_circuit_t *)session->session.circuit)->name,
key->version, key->ident,
ipl2tp_api_session_type(key));
break;
case IPL2TP_INCOMING_REQUEST:
/* Destroy any previous sessions */
/* Setup */
if ((session = ipl2tp_example_session_eth_setup(key, type)) == IP_NULL)
return IPL2TP_STATUS_BADID;
IPCOM_LOG4(DEBUG,
"IPL2TPv3: SESSION (IPL2TP_INCOMING_REQUEST) session[%s] v%d %d %s",
((Ipl2tp_v3_circuit_t *)session->session.circuit)->name,
key->version, key->ident,
ipl2tp_api_session_type(key));
ipl2tp_api_session_incoming_established(key, 0, 0, "");
break;
case IPL2TP_INCOMING_ESTABLISHED:
/* */
if (session == IP_NULL)
{
/* Setup */
if ((session = ipl2tp_example_session_eth_setup(key, type)) == IP_NULL)
return IPL2TP_STATUS_BADID;
}
IPCOM_LOG4(DEBUG,
"IPL2TPv3: SESSION (IPL2TP_INCOMING_ESTABLISHED) session[%s] v%d %d %s",
((Ipl2tp_v3_circuit_t *)session->session.circuit)->name,
key->version, key->ident,
ipl2tp_api_session_type(key));
break;
}
break;
default:
IPCOM_LOG6(DEBUG,
"IPL2TPv3: SESSION (%u) Session[%s] v%d %d %s closed with status %s",
(int)result->status,
session? ((Ipl2tp_v3_circuit_t *)session->session.circuit)->name : "<invalid>",
key->version, key->ident,
ipl2tp_api_session_type(key),
ipl2tp_api_errname(result->status));
ipl2tp_example_session_eth_destroy(key);
break;
}
return 0;
}
/*
*===========================================================================
* ipl2tp_example_tunnel_auth
*===========================================================================
* Description: Set the tunnel auth if available.
* Parameters:
* Returns:
*
*/
IP_STATIC void
ipl2tp_example_tunnel_auth(Ipl2tp_key *key,
Ip_u32 rID,
const char *peer)
{
char buf[128];
char *ctype;
Ipl2tp_attrobj attr = IP_NULL;
int argc;
char **argv = IP_NULL;
int i;
do
{
IPCOM_LOG2(INFO,
"L2TP: Verifying attributes for %ld@%s",
rID, peer);
ipcom_snprintf(buf, sizeof(buf), "ipl2tp.v3.control.%ld.attributes", rID);
if ((ctype = ipcom_sysvar_get(buf, IP_NULL, IP_NULL)) != IP_NULL)
break;
ipcom_snprintf(buf, sizeof(buf), "ipl2tp.v3.control.%s.attributes", peer);
if ((ctype = ipcom_sysvar_get(buf, IP_NULL, IP_NULL)) != IP_NULL)
break;
ipcom_snprintf(buf, sizeof(buf), "ipl2tp.v3.control.any.attributes");
if ((ctype = ipcom_sysvar_get(buf, IP_NULL, IP_NULL)) != IP_NULL)
break;
return;
} while (0);
/* Got the argument vector; time to explode it */
if (ipcom_parse_argstr(ctype, (int *)&argc, &argv) != 0)
{
ipcom_free(ctype);
return;
}
for (i = 0; i < argc; i++)
{
char *value;
Ipl2tp_attr_info *info;
/**/
if ((info = ipl2tp_api_attribute_find(ipl2tp_tunnel_tags, argv[i], &value)) == IP_NULL)
{
IPCOM_LOG1(ERR,
"L2TP: tunnel: Invalid attribute %s",
argv[i]);
continue;
}
if (ipl2tp_api_attribute_parse(&attr,info,&value) == IP_FALSE)
{
IPCOM_LOG2(ERR,
"L2TP: Invalid attribute %s and value %s",
argv[i], value);
continue;
}
}
ipl2tp_api_tunnel_attribute_set(key,attr);
ipl2tp_attr_delete(&attr);
ipcom_free(argv);
ipcom_free(ctype);
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipl2tp_example_sstatus_v3
*===========================================================================
* Description: Session status callback.
* Parameters: user_data - User callback data.
* key - Session ID.
* status - Pointer to status info.
* Returns:
*
*/
IP_GLOBAL int
ipl2tp_example_sstatus_v3(void *user_data,
Ipl2tp_key *key,
Ipl2tp_result *result)
{
int type;
Ipl2tp_attrobj replies = IP_NULL;
Ipl2tp_attr a;
ipl2tp_api_session_attribute_query(key,
IPL2TP_SATTR_GET_PSEUDOWIRE_TYPE,
&replies);
if((a = ipl2tp_attr_first(replies)) == IP_NULL)
{
ipl2tp_attr_delete(&replies);
return IPL2TP_STATUS_BADAVP;
}
type = ipl2tp_attr_idata(a);
ipl2tp_attr_delete(&replies);
/* ETHERNET pseudowire type */
if (type == IPL2TP_ATTR_PW_TYPE_ETHERNET ||
type == IPL2TP_ATTR_PW_TYPE_ETHERNET_VLAN)
{
/* */
return ipl2tp_example_session_eth_status(user_data, key, result, type);
}
return IPL2TP_STATUS_BADPW;
}
/*
*===========================================================================
* ipl2tp_example_tstatus_v3
*===========================================================================
* Description: Tunnel status callback.
* Parameters: user_data - User callback data.
* key - Tunnel ID.
* status - Pointer to status info.
* Returns:
*
*/
IP_GLOBAL int
ipl2tp_example_tstatus_v3(void *user_data,
Ipl2tp_key *key,
Ipl2tp_result *result)
{
Ipl2tp_attrobj replies = IP_NULL;
Ipl2tp_attrobj attr = IP_NULL;
Ipl2tp_attr a;
Ip_u32 rID;
const char *peer;
IPL2TP_UNUSED(user_data);
/* Get the remote info */
ipl2tp_attr_add_query(&attr, IPL2TP_TATTR_GET_REMOTE_ROUTER_ID);
ipl2tp_attr_add_query(&attr, IPL2TP_TATTR_GET_l2tpTunnelStatsRemoteHostName);
ipl2tp_api_tunnel_attribute_get(key, attr, &replies);
ipl2tp_attr_delete(&attr);
/* Get the router ID */
a = ipl2tp_attr_first(replies);
if(a == IP_NULL)
{
ipl2tp_attr_delete(&replies);
return 0;
}
rID = ipl2tp_attr_idata(a);
/* Get the remote host name */
a = ipl2tp_attr_next(a);
peer = ipl2tp_attr_strdata(a);
switch (result->status)
{
case IPL2TP_STATUS_OK:
switch (result->result_code)
{
case IPL2TP_OUTGOING_AUTHENTICATION:
{
/* Allocate an attribute object */
IPCOM_LOG3(DEBUG,
"IPL2TPv3: TUNNEL (IPL2TP_OUTGOING_AUTHENTICATION) v%d %d requested by '%s'",
key->version, key->ident,
peer);
ipl2tp_example_tunnel_auth(key, rID, peer);
/* We've installed the authentication data required,
* do continue the tunnel processing and attempt to establish */
ipl2tp_api_tunnel_authentication_established(key);
break;
}
case IPL2TP_OUTGOING_REQUEST:
{
IPCOM_LOG3(DEBUG,
"IPL2TPv3: TUNNEL (IPL2TP_OUTGOING_REQUEST) v%d %d from '%s'",
key->version, key->ident,
peer);
break;
}
case IPL2TP_OUTGOING_ESTABLISHED:
IPCOM_LOG2(DEBUG,
"IPL2TPv3: TUNNEL (IPL2TP_OUTGOING_ESTABLISHED) v%d %d opened",
key->version, key->ident);
break;
case IPL2TP_INCOMING_ESTABLISHED:
IPCOM_LOG2(DEBUG,
"IPL2TPv3: TUNNEL (IPL2TP_INCOMING_ESTABLISHED) v%d %d opened",
key->version, key->ident);
break;
}
break;
case IPL2TP_STATUS_NEGOTIATION:
IPCOM_LOG2(DEBUG,
"IPL2TPv3: TUNNEL (IPL2TP_STATUS_NEGOTIATION) v%d %d closed obsoleted by version negotiation",
key->version, key->ident);
break;
default:
IPCOM_LOG4(DEBUG,
"IPL2TPv3: TUNNEL (%u) v%d %d closed with status %s",
(int)result->status,
key->version, key->ident,
ipl2tp_api_errname(result->status));
break;
}
ipl2tp_attr_delete(&replies);
return 0;
}
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/