Files
m241Neelima/components/ip_net2-6.9/ipnet2/src/ipnet_ppp.c
T
2026-07-30 11:19:44 +05:30

644 lines
20 KiB
C

/*
******************************************************************************
* INTERPEAK SOURCE FILE
*
* Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipnet_ppp.c,v $ $Revision: 1.118.10.2 $
* $Source: /home/interpeak/CVSRoot/ipnet2/src/ipnet_ppp.c,v $
* $Author: qsun $
* $State: Exp $ $Locker: $
*
* INTERPEAK_COPYRIGHT_STRING
* Design and implementation by Lennart Bang <lob@interpeak.se>
******************************************************************************
*/
/*
****************************************************************************
* 1 DESCRIPTION
****************************************************************************
*/
/*
****************************************************************************
* 2 CONFIGURATION
****************************************************************************
*/
#ifndef IPCOM_KERNEL
#define IPCOM_KERNEL
#endif
#include "ipnet_config.h"
/*
****************************************************************************
* 3 INCLUDE FILES
****************************************************************************
*/
#ifdef IPPPP
#define IPCOM_USE_CLIB_PROTO
#include <ipcom_clib.h>
#include <ipcom_cstyle.h>
#include <ipcom_type.h>
#include <ipppp.h>
#include <ipppp_ipstack.h>
#include "ipnet_h.h"
#include "ipnet_netif.h"
#include "ipnet_pkt_queue.h"
/*
****************************************************************************
* 4 DEFINES
****************************************************************************
*/
/* Number of bits in the host part (EUI-64) when using the
* PPP to create a IPv6 address (RFC 2464?)
*/
#define IPPPP_IP6_ID_BITS 64
/*
****************************************************************************
* 5 TYPES
****************************************************************************
*/
/*
****************************************************************************
* 6 EXTERN PROTOTYPES
****************************************************************************
*/
/*
****************************************************************************
* 7 LOCAL PROTOTYPES
****************************************************************************
*/
IP_STATIC int ipnet_ppp_input(struct Ipnet_netif_struct *netif, Ipcom_pkt *pkt);
IP_STATIC int ipnet_ppp_ioctl(struct Ipnet_netif_struct *netif, Ip_u32 command, void *data);
IP_STATIC int ipnet_ppp_ioevent(Ipcom_netif *netif, int command, void *data, int fcflags);
IP_PUBLIC int ipppp_if_init2(void *voidif);
/*
****************************************************************************
* 8 DATA
****************************************************************************
*/
Ipcom_once_t ipnet_ppp_ioevent_once = IPCOM_ONCE_INIT;
/*
****************************************************************************
* 9 STATIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipnet_ppp_input
*===========================================================================
* Description: Input handler for ethernet frames. pkt->start is the offset
* to the ethernet header.
* Parameters: pkt - The ethernet frame.
* Returns: 0 = success, <0 error code
*
*/
IP_STATIC int
ipnet_ppp_input(struct Ipnet_netif_struct *netif, Ipcom_pkt *pkt)
{
int vr;
int ret;
ip_assert(ipnet_is_stack_task());
vr = ipcom_proc_vr_get();
/* Set virtual router index */
if (vr != netif->vr_index)
ipcom_proc_vr_set(netif->vr_index);
ret = ipppp_input(&netif->ipcom, pkt);
/* Restore virtual router index */
if (vr != netif->vr_index)
ipcom_proc_vr_set(vr);
return ret;
}
/*
*===========================================================================
* ipnet_ppp_ioctl
*===========================================================================
* Description: PPP IO control.
* Parameters: netif - The interface on which the multicast address will
* be used.
* command - ioctl command.
* data - Depends on command.
* Returns: 0 = success, < 0 = error code
*
*/
IP_STATIC int
ipnet_ppp_ioctl(struct Ipnet_netif_struct *netif, Ip_u32 command, void *data)
{
int vr;
int ret;
ip_assert(ipnet_is_stack_task());
vr = ipcom_proc_vr_get();
/* Set virtual router index */
if (vr != netif->vr_index)
ipcom_proc_vr_set(netif->vr_index);
ret = ipppp_ioctl(&netif->ipcom, command, data);
/* Restore virtual router index */
if (vr != netif->vr_index)
ipcom_proc_vr_set(vr);
return ret;
}
IP_STATIC int
ipnet_ppp_tx(Ipnet_neigh *neigh, Ipcom_pkt *pkt)
{
ip_assert(ipnet_is_stack_task());
switch (neigh->domain)
{
#ifdef IPCOM_USE_INET
case IP_AF_INET:
return ipppp_ip4_output(&neigh->netif->ipcom, pkt);
#endif
#ifdef IPCOM_USE_INET6
case IP_AF_INET6:
return ipppp_ip6_output(&neigh->netif->ipcom, pkt);
#endif
}
return -IP_ERRNO_EINVAL;
}
#ifdef IPCOM_USE_INET6
/*
*===========================================================================
* ipnet_ppp_ip6_create_addr
*===========================================================================
* Description: Creates an unique address based on the passed prefix.
* Parameters: netif - The interface to which this address will be bound.
* prefix - The network identifier part of the address.
* in6_addr - Will hold a unique address if the function is
* successful.
* Returns: 0 = succeess. <0 = error code.
*
*/
IP_STATIC int
ipnet_ppp_ip6_create_addr(Ipnet_netif *netif,
IP_CONST struct Ip_in6_addr *prefix,
struct Ip_in6_addr *in6_addr)
{
struct Ip_in6_addr mask;
struct Ip_in6_addr host_id;
unsigned i;
/* Create the EUI-64 ideaantifier for the PPP interface */
ip_assert(ipnet_is_stack_task());
if (netif->inet6_addr_list != IP_NULL
&& IP_IN6_IS_ADDR_MULTICAST(netif->inet6_addr_list) == IP_FALSE)
/* Host ID already generated, reuse that host ID */
IPNET_IP6_SET_ADDR(&host_id, &netif->inet6_addr_list->addr);
else
{
/* Generate a random host ID */
long pid_tick;
pid_tick = (long)ipcom_getpid() + (long)ipcom_time(IP_NULL);
/* Let's create a random number */
host_id.in6.addr32[0] = (Ip_u32) (ipcom_random() + pid_tick);
host_id.in6.addr32[1] = (Ip_u32) (ipcom_random() + pid_tick);
host_id.in6.addr32[2] = (Ip_u32) (ipcom_random() + pid_tick);
host_id.in6.addr32[3] = (Ip_u32) (ipcom_random() + pid_tick);
/* The universal/local bit must be 0 in this case */
IP_BIT_CLR(in6_addr->in6.addr16[4], IP_SWAP16(0x0200));
}
/* Create an inverted mask */
ipcom_memset(&mask, 0, sizeof(mask));
ipnet_route_create_mask(&mask, netif->inet6_if_id_bits);
mask.in6.addr32[0] = ~mask.in6.addr32[0];
mask.in6.addr32[1] = ~mask.in6.addr32[1];
mask.in6.addr32[2] = ~mask.in6.addr32[2];
mask.in6.addr32[3] = ~mask.in6.addr32[3];
ipnet_route_apply_mask(&host_id, &mask, netif->inet6_if_id_bits);
IPNET_IP6_SET_ADDR(in6_addr, prefix);
for (i = 0; i < sizeof(host_id) / sizeof(host_id.in6.addr16[0]); i++)
in6_addr->in6.addr16[i] |= host_id.in6.addr16[i];
return 0;
}
#endif /* IPCOM_USE_INET6 */
/*
*===========================================================================
* ipnet_ppp_ioevent
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_STATIC int
ipnet_ppp_ioevent(Ipcom_netif *netif, int command, void *data, int fcflags)
{
int retval = 0;
IPCOM_UNUSED_ARG(fcflags);
if (ipnet_is_stack_task())
retval = ipppp_ioevent(netif, command, data);
else
{
}
return retval;
}
/*
*===========================================================================
* ipnet_ppp_ioevent_init
*===========================================================================
* Description: Creates the ppp code mutex.
* Parameters:
* Returns:
*
*/
IP_STATIC Ip_err
ipnet_ppp_ioevent_init(Ipcom_mutex *ppp_code_mutex)
{
return ipcom_mutex_create(ppp_code_mutex);
}
/*
****************************************************************************
* 10 GLOBAL FUNCTIONS
****************************************************************************
*/
/*
****************************************************************************
* 11 PUBLIC FUNCTIONS
****************************************************************************
*/
/*
*===========================================================================
* ipppp_if_init2
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC int
ipppp_if_init2(void *voidif)
{
Ipnet_netif *netif = voidif;
int ret;
Ip_bool is_stack_task = ipnet_is_stack_task();
if (!is_stack_task)
ipcom_ppp_ioevent(voidif, IPPPP_EIOXCODE_LOCK, IP_NULL);
/* Setup link functions for PPP use. */
netif->link_input = ipnet_ppp_input;
netif->link_ioctl = ipnet_ppp_ioctl;
netif->ipcom.link_ioevent = ipnet_ppp_ioevent;
netif->link_output = ipnet_ppp_tx;
#ifdef IPCOM_USE_INET6
netif->inet6_if_id_bits = IPPPP_IP6_ID_BITS;
netif->link_ip6_create_addr = ipnet_ppp_ip6_create_addr;
#endif
ret = ipppp_if_init(&netif->ipcom);
if (!is_stack_task)
ipcom_ppp_ioevent(voidif, IPPPP_EIOXCODE_UNLOCK, IP_NULL);
return ret;
}
/*
*===========================================================================
* ipcom_ppp_ioevent
*===========================================================================
* Description:
* Parameters:
* Returns:
*
*/
IP_PUBLIC long
ipcom_ppp_ioevent(Ipcom_netif *netif, int command, void *data)
{
struct Ipnet_route_add_param param;
struct Ipnet_rt_metrics metrics;
Ip_u32 netmask_n;
Ipnet_netif *ipnet_netif = (Ipnet_netif *)netif;
long ret = 0;
static Ipcom_mutex ppp_code_mutex = IPCOM_MUTEX_INVALID;
static void *suspend_handle = IP_NULL;
switch(command)
{
case IPPPP_EIOXBLOCKOK:
if (ipnet_is_stack_task() == IP_FALSE)
ret = 1; /* user process -> block is ok. */
break;
case IPPPP_EIOXDRVIOCTL:
{
Ipppp_eio_ioctl *eio_ioctl = data;
ip_assert(netif);
ip_assert(ipnet_is_stack_task());
ret = netif->drv_ioctl(netif, eio_ioctl->command, eio_ioctl->data);
break;
}
case IPPPP_EIOXOUTPUT_IF:
ip_assert(ipnet_netif);
ip_assert(ipnet_is_stack_task());
ret = ipnet_if_output(ipnet_netif, data);
break;
case IPPPP_EIOXINDEXTONETIF:
{
Ipnet_netif *ptr;
unsigned long dataul = (unsigned long)data;
ip_assert(ipnet_is_stack_task());
ptr = ipnet_if_indextonetif(IPCOM_VR_ANY, (Ip_u32)dataul);
return (long)ptr;
}
case IPPPP_EIOXCODE_LOCK:
if (ipcom_once(&ipnet_ppp_ioevent_once,
(Ip_err(*)(void*)) ipnet_ppp_ioevent_init,
(void *) &ppp_code_mutex)
!= IPCOM_SUCCESS)
{
IP_PANIC();
return -1;
}
(void)ipcom_mutex_lock(ppp_code_mutex);
suspend_handle = ipnet_suspend_stack();
break;
case IPPPP_EIOXCODE_UNLOCK:
ipnet_resume_stack(suspend_handle);
(void)ipcom_mutex_unlock(ppp_code_mutex);
break;
case IPPPP_EIOXIF_LOCK:
ip_assert(netif);
ip_assert(ipnet_is_stack_task());
IPNET_IF_LOCK(ipnet_netif);
break;
case IPPPP_EIOXIF_UNLOCK:
ip_assert(netif);
ip_assert(ipnet_is_stack_task());
IPNET_IF_UNLOCK(ipnet_netif);
break;
#ifdef IPCOM_USE_INET
case IPPPP_EIOXINPUT_IN:
ip_assert(ipnet_netif);
ip_assert(ipnet_is_stack_task());
ret = ipnet_ip4_input(ipnet_netif, data);
break;
case IPPPP_EIOXUP_IN:
{
Ipppp_eio_in *eio_in = data;
ip_assert(netif);
ip_assert(ipnet_is_stack_task());
/* Add local IPv4 address to this interface. */
ip_assert(ipnet_netif->inet4_addr_list == IP_NULL
|| ipnet_netif->inet4_addr_list->type != IPNET_ADDR_TYPE_UNICAST);
netmask_n = 0xffffffff;
ret = ipnet_ip4_add_addr(ipnet_netif, eio_in->local_addr_n, netmask_n,
IP_TRUE, IPNET_ADDR_TYPE_UNICAST);
if (ret < 0)
{
IP_PANIC2();
return ret;
}
/* Add a host route to the peer. */
ipcom_memset(&param, 0, sizeof(struct Ipnet_route_add_param));
ipcom_memset(&metrics, 0, sizeof(struct Ipnet_rt_metrics));
param.domain = IP_AF_INET;
param.vr = ipnet_netif->vr_index;
param.table = IPCOM_ROUTE_TABLE_DEFAULT;
param.netif = ipnet_netif;
param.key = &eio_in->peer_addr_n;
param.flags = IPNET_RTF_UP | IPNET_RTF_HOST | IPNET_RTF_DONE;
if (ipppp_sysvar_get_conf_string(netif, IP_NULL, "ipppp.flags", "proxyarp"))
IP_BIT_SET(param.flags, IPNET_RTF_PROTO2);
param.metrics = &metrics;
metrics.rmx_hopcount = netif->metric;
metrics.rmx_expire = IPCOM_ADDR_INFINITE;
ret = ipnet_route_add(&param);
if (ret < 0)
{
IP_PANIC2();
return ret;
}
/* Add/Change default gateway to peer. */
if (ipppp_sysvar_get_conf_string(netif, IP_NULL, "ipppp.flags", "defaultroute"))
{
struct Ip_sockaddr_in gw;
Ip_u32 inaddr_any = 0;
(void)ipnet_route_delete(IP_AF_INET, ipnet_netif->vr_index, &inaddr_any);
ipcom_memset(&gw, 0, sizeof(struct Ip_sockaddr_in));
gw.sin_family = IP_AF_INET;
IPCOM_SA_LEN_SET(&gw, sizeof(struct Ip_sockaddr_in));
gw.sin_addr.s_addr = eio_in->peer_addr_n;
param.flags = IPNET_RTF_UP | IPNET_RTF_GATEWAY | IPNET_RTF_DONE;
param.gateway = (struct Ip_sockaddr *)&gw;
param.key = &inaddr_any;
param.netmask = &inaddr_any;
ret = ipnet_route_add(&param);
if (ret < 0)
{
IP_PANIC2();
return ret;
}
}
}
break;
case IPPPP_EIOXDOWN_IN:
ip_assert(ipnet_netif);
ip_assert(ipnet_is_stack_task());
ipnet_if_clean(ipnet_netif, IP_TRUE, IP_FALSE);
break;
case IPPPP_EIOXDSTADDR_IN:
{
struct Ip_ifreq ifreq;
struct Ip_sockaddr_in *inaddr = (struct Ip_sockaddr_in *)&ifreq.ip_ifr_addr;
Ip_u32 dstaddr = ((struct Ip_in_addr *)data)->s_addr;
Ipnet_netif *tmpif;
unsigned i;
ip_assert(ipnet_is_stack_task());
dstaddr = ip_htonl(dstaddr);
/*
* IPNET_NETIF_FOR_EACH sets netif to NULL after the for loop,
* this is a performance optimized defination
*/
/* coverity[result_independent_of_operands] */
IPNET_NETIF_FOR_EACH(tmpif, i)
{
if (IP_BIT_ISFALSE(tmpif->ipcom.flags, IP_IFF_POINTOPOINT))
continue;
(void)ipnet_if_link_ioctl(tmpif, IP_SIOCGIFDSTADDR, &ifreq);
if (inaddr->sin_addr.s_addr == dstaddr)
return 1;
}
}
return 0;
#endif /* ifdef IPCOM_USE_INET */
#ifdef IPCOM_USE_INET6
case IPPPP_EIOXINPUT_IN6:
ip_assert(ipnet_netif);
ip_assert(ipnet_is_stack_task());
ret = ipnet_ip6_input(ipnet_netif, data);
break;
case IPPPP_EIOXUP_IN6:
{
struct Ipnet_ipv6_key rt6[2];
Ipppp_eio_in6 *eio_in6 = data;
ip_assert(netif);
ip_assert(ipnet_is_stack_task());
/* Add IPv6 address. */
ret = ipnet_ip6_add_addr(ipnet_netif, &eio_in6->local_addr, 0,
IPCOM_ADDR_INFINITE, IPCOM_ADDR_INFINITE, 128);
if (ret < 0)
return ret;
/* Add cloning route for link local net. */
ipcom_memset(&param, 0, sizeof(struct Ipnet_route_add_param));
ipcom_memset(&metrics, 0, sizeof(struct Ipnet_rt_metrics));
ipcom_memset(rt6, 0, sizeof(struct Ipnet_ipv6_key) * 2);
rt6[0].scope_id = netif->ifindex;
rt6[0].addr.in6.addr8[0] = 0xfe;
rt6[0].addr.in6.addr8[1] = 0x80;
rt6[1].scope_id = 0xffffffff;
rt6[1].addr.in6.addr32[0] = 0xffffffff;
rt6[1].addr.in6.addr32[1] = 0xffffffff;
param.domain = IP_AF_INET6;
param.vr = ipnet_netif->vr_index;
param.table = IPCOM_ROUTE_TABLE_DEFAULT;
param.netif = ipnet_netif;
param.key = &rt6[0];
param.netmask = &rt6[1];
param.flags = IPNET_RTF_UP | IPNET_RTF_MASK | IPNET_RTF_CLONING | IPNET_RTF_DONE;
param.metrics = &metrics;
metrics.rmx_hopcount = netif->metric;
metrics.rmx_expire = IPCOM_ADDR_INFINITE;
ret = ipnet_route_add(&param);
if (ret < 0)
{
IP_PANIC2();
return ret;
}
/* Add link local multicast route. */
rt6[0].addr.in6.addr8[0] = 0xff;
rt6[0].addr.in6.addr8[1] = 0x02;
param.flags = IPNET_RTF_UP | IPNET_RTF_MASK | IPNET_RTF_DONE;
ret = ipnet_route_add(&param);
if (ret < 0)
{
IP_PANIC2();
return ret;
}
/* Add IPv6 host route to peer. */
ipcom_memcpy(&rt6[0].addr, &eio_in6->peer_addr, sizeof(struct Ip_in6_addr));
param.netmask = IP_NULL;
param.flags = IPNET_RTF_UP | IPNET_RTF_HOST | IPNET_RTF_DONE;
ret = ipnet_route_add(&param);
if (ret < 0)
{
IP_PANIC2();
return ret;
}
}
break;
case IPPPP_EIOXDOWN_IN6:
ip_assert(ipnet_netif);
ip_assert(ipnet_is_stack_task());
ipnet_if_clean(ipnet_netif, IP_FALSE, IP_TRUE);
break;
#endif /* ifdef IPCOM_USE_INET6 */
default:
ip_assert(ipnet_netif);
ip_assert(ipnet_is_stack_task());
ipnet_kioevent(ipnet_netif, command, data, 0);
break;
}
return ret;
}
#endif /* IPPPP */
/*
****************************************************************************
* END OF FILE
****************************************************************************
*/