/* ****************************************************************************** * SOURCE FILE * * Document no: @(#) $Name: VXWORKS_ITER40_2019102207 $ $RCSfile: ipl2tp_example.c,v $ $Revision: 1.11 $ * $Source: /home/interpeak/CVSRoot/ipl2tp/config/ipl2tp_example.c,v $ * $Author: tneale $ * $State: Exp $ $Locker: $ * * INTERPEAK_COPYRIGHT_STRING * ****************************************************************************** */ /* **************************************************************************** * DESCRIPTION **************************************************************************** * * L2TP example file. */ /* **************************************************************************** * INCLUDE FILES **************************************************************************** */ #ifdef IP_PORT_VXWORKS #ifdef IPCOM_USE_CLIB_PROTO #undef IPCOM_USE_CLIB_PROTO #endif #ifndef IPCOM_KERNEL #define IPCOM_KERNEL #endif /* Synchronize build with configuration definitions */ #include "ipcom_config.h" #ifdef INCLUDE_IPPPP #define IPPPP #endif #ifdef INCLUDE_IPL2TP #define IPL2TP #endif #ifdef IPPPP #include "ipppp_config.h" #include "ipppp.h" #endif #include #include #include #include #include #include #include #include #include #include #include #include "ipl2tp.h" #include "ipl2tp_api_session.h" #else #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 "ipnet_h.h" #include "ipl2tp.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_v2.h" #include "ipl2tp_example_v3.h" #ifdef IPPPP #include "ipppp.h" #endif #endif /* IP_PORT_VXWORKS */ /* **************************************************************************** * DEFINES **************************************************************************** */ /* L2TP control port */ #define IPL2TP_PORT_NUMBER 1701 /* Extra header space allocated before L2TP header */ #define HEADER_SPACE 0 #define LF "\n" #define ARGC_NAME -1 #define ARGC_DESCR -2 /* PPP protocols */ #define PPPP_LCP 0xc021 /* Link Control Protocol */ #define PPPP_IPCP 0x8021 /* IP Control Protocol */ #define PPPP_PAP 0xc023 /* Password Authentication Protocol */ #define PPPP_CHAP 0xc223 /* Cryptographic Handshake Auth. Prot. */ #define PPPP_IP 0x0021 /* Internet Protocol */ /* PPP CP (LCP, IPCP, etc) codes */ #define PPP_CP_CONFREQ 1 /* Configuration Request */ #define PPP_CP_CONFACK 2 /* Configuration Ack */ #define PPP_CP_CONFNAK 3 /* Configuration Nak */ #define PPP_CP_CONFREJ 4 /* Configuration Reject */ #define PPP_CP_TERMREQ 5 /* Termination Request */ #define PPP_CP_TERMACK 6 /* Termination Ack */ #define PPP_CP_CODEREJ 7 /* Code Reject */ #define PPP_CP_PROTREJ 8 /* Protocol Reject, */ #define PPP_CP_ECHOREQ 9 /* Echo Request */ #define PPP_CP_ECHOREP 10 /* Echo Reply */ #define PPP_CP_DISCREQ 11 /* Discard Request */ #ifndef IP_IPPROTO_L2TP #define IP_IPPROTO_L2TP 115 #endif /* **************************************************************************** * TYPES **************************************************************************** */ typedef struct Ipl2tp_cache_head { struct Ipl2tp_cache_head *next; } Ipl2tp_cache_head; /* **************************************************************************** * LOCAL DATA **************************************************************************** */ /* List of free cache buffers */ IP_STATIC Ipl2tp_cache_head *free_list = IP_NULL; /* Main socket fd */ IP_STATIC Ip_fd udp_fd = IP_INVALID_SOCKET; IP_STATIC Ip_fd ip_fd = IP_INVALID_SOCKET; /* Output flag */ IP_STATIC int l2tp_output = 0; /* **************************************************************************** * PUBLIC DATA **************************************************************************** */ int ipl2tp_buffer_free = 1; Ipcom_hash *ipl2tp_example_sessions = IP_NULL; Ipcom_list ipl2tp_example_fds; /* **************************************************************************** * EXTERNAL DATA **************************************************************************** */ /* Poke vars */ IP_EXTERN int poke_count; IP_EXTERN int poke_mtype; IP_EXTERN int poke_avp; IP_EXTERN int poke_offset; IP_EXTERN int poke_value; IP_EXTERN int poke_skip; IP_EXTERN Ip_u16 session_table[]; IP_EXTERN Ip_u16 session_table_size; /* **************************************************************************** * PROTOTYPES **************************************************************************** */ IP_PUBLIC Ip_err ipl2tp_create(void); IP_PUBLIC Ip_err ipl2tp_start(void); #if 0 /* PPP/L2TPv2 integration for third-party PPP */ IP_PUBLIC int ppp_input_hook(int ifindex, void *pppbuf, Ip_size_t length, Ip_size_t offset); IP_PUBLIC int ppp_output_hook(Ip_u32 ifindex, void *pppbuf, Ip_u32 length, Ip_u32 offset); IP_PUBLIC int ppp_open_hook(int ifindex, int protocol); IP_PUBLIC int ppp_writedone_hook(int ifindex, void *pppbuf, void *cookie); #endif /* **************************************************************************** * LOCAL FUNCTIONS **************************************************************************** */ /* *=========================================================================== * ipl2tp_data_obj_hash_tunnel_assigned *=========================================================================== * Description: * Parameters: * Returns: */ IP_STATIC unsigned ipl2tp_example_obj_hash_key(Ipl2tp_key *key) { /* Hash the version first */ unsigned val = ipcom_hash_update(&key->version, sizeof(key->version), 0); /* Hash the key ID */ return ipcom_hash_update(&key->ident, sizeof(key->ident), val); } /* *=========================================================================== * ipl2tp_data_cmp_tunnel_assigned *=========================================================================== * Description: * Parameters: * Returns: */ IP_STATIC Ip_bool ipl2tp_example_cmp_key(Ipl2tp_key *obj_key, Ipl2tp_key *key) { /* Addr, Version & ID must match */ return obj_key->version == key->version && obj_key->ident == key->ident; } /* *=========================================================================== * ipl2tp_cache_malloc *=========================================================================== * Description: Allocate buffer from local cache * Parameters: * Returns: * */ IP_STATIC void * ipl2tp_cache_malloc(Ip_u32 size) { Ipl2tp_cache_head *head; Ip_u32 msr; msr = ipcom_interrupt_disable(); if (free_list != IP_NULL) { head = free_list; free_list = head->next; ipcom_interrupt_enable(msr); } else { ipcom_interrupt_enable(msr); if ((head = ipcom_malloc(sizeof(*head) + size)) == IP_NULL) { return IP_NULL; } } return head + 1; } /* *=========================================================================== * ipl2tp_cache_free *=========================================================================== * Description: Return buffer to local cache. Allows data to be freed * within interrupt context. * Parameters: * Returns: * */ IP_STATIC void ipl2tp_cache_free(void *buf) { Ipl2tp_cache_head *head = buf; Ip_u32 msr; head--; msr = ipcom_interrupt_disable(); head->next = free_list; free_list = head; ipcom_interrupt_enable(msr); } /* *=========================================================================== * ipl2tp_ppp_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_ppp_data_cb(void *user_data, Ipl2tp_key *id, void *buffer, void *payload, Ip_u16 length) { #ifdef IP_PORT_VXWORKS int ifindex = (long)user_data; #else int ifindex = (int)user_data; #endif (void)id; (void)buffer; (void)payload; (void)length; /* Do the write */ if (ifindex != -1) { l2tp_output = 1; /* ** Insert PPP write routine here, e.g.: ** ppplink_write(ifindex, payload, length, HEADER_SPACE, buffer); */ #ifdef IPPPP_USE_PPPL2TP if (user_data == (void *)0x0) { #ifdef IPPPP_USE_PPPL2TP_LNS if ((ipcom_sysvar_get_conf_as_int("ipppp.l2tp.server", IP_NULL, IP_NULL) != 1) || ((ifindex = ipppp_pppl2tp_if_create_server(id)) < 0)) { ipcom_printf ("Failed to create new server interface."IP_LF); return; } #else ipcom_printf ("Data callback: no ifindex."IP_LF); return; #endif } ipppp_pppl2tp_input (ifindex, payload, length); #endif l2tp_output = 0; } } /* *=========================================================================== * ipl2tp_l2tp_read *=========================================================================== * Description: Read a L2TP control message via UDP. * Parameters: * Returns: * */ IP_STATIC int ipl2tp_l2tp_read(Ip_fd fd, Ip_u8 **buf, union Ip_sockaddr_union *ipp) { Ip_socklen_t faddrsize = sizeof(*ipp); int length; Ip_u8 *buffer; /* Get buffer */ if ((buffer = ipl2tp_cache_malloc(HEADER_SPACE + IPL2TP_MAX_MESSAGE_SIZE)) == IP_NULL) { ipcom_printf("Out of memory when reading L2TP socket"IP_LF); return 0; } /* Receive an UDP packet */ if ((length = ipcom_recvfrom(fd, buffer, IPL2TP_MAX_MESSAGE_SIZE, 0, &ipp->sa, &faddrsize)) < 0) { ipcom_printf("ipl2tp_l2tp_read() failed with errno: %d"IP_LF, ipcom_errno); ipl2tp_cache_free(buffer); return 0; } *buf = buffer; return length; } /* *=========================================================================== * ipl2tp_l2tp_write *=========================================================================== * Description: Send a L2TP control message via UDP. * Parameters: message - Message to send. * addr - Destination IP address. * Returns: * */ IP_STATIC int ipl2tp_l2tp_write(void *user_data, Ipl2tp_key *key, struct Ip_iovec *iov, int iovlen, union Ip_sockaddr_union *addr, int transport) { int sz; int fd; struct Ip_msghdr msg; (void)user_data; (void)key; if (transport == IPL2TP_ATTR_TRANSPORT_UDP) { fd = udp_fd; } else if (transport == IPL2TP_ATTR_TRANSPORT_IP) { fd = ip_fd; } else { ipcom_printf("Bad transport %u!!"IP_LF, transport); return -1; } ipcom_memset(&msg, 0, sizeof(msg)); /* Set it up */ msg.msg_iov = iov; msg.msg_iovlen = iovlen; msg.msg_name = &addr->sa; msg.msg_namelen = addr->sa.sa_len; /* Transmit the UDP packet */ if ((sz = ipcom_sendmsg(fd, &msg, 0)) < 0) { ipcom_printf("ipl2tp_l2tp_write() failed with errno: %d"IP_LF, ipcom_errno); return 0; } return sz; } #if 0 /* L2TP Debugging */ /* *=========================================================================== * peek_poke *=========================================================================== * Description: Peek and optionally poke at incoming L2TP data. * Parameters: data - Data buffer. * Returns: * */ IP_STATIC int peek_poke(Ip_u8 *data) { if (poke_count != 0 && /* Poke active */ (data[0] & 0x80) != 0 && /* Control msg */ (poke_mtype == 0 || /* Wildcard */ (data[3] > 12 && /* Non-ZLB */ poke_mtype == data[19]))) /* Msg type match */ { poke_count--; if (poke_skip != 0) { /* Skip message */ return 0; } if (poke_avp != 0) { int mindex; int length; /* Find correct AVP */ for (mindex = 12, length = 1; length != 0 && mindex < data[3]; mindex += length) { /* Only allow 8-bit length */ length = data[mindex + 1]; if (data[mindex + 5] == poke_avp) { data[mindex + poke_offset] = (Ip_u8)poke_value; break; } } } else { data[poke_offset] = (Ip_u8)poke_value; } } return 1; } #endif /* *=========================================================================== * ipl2tps *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC IPCOM_PROCESS(ipl2tps) { Ip_fd ipd_fd = IP_INVALID_SOCKET; Ip_bool ipd_init = 0; #ifdef IPPPP_USE_PPPL2TP Ip_fd ipl2tp_ppp_ipc_recv_fd = IP_INVALID_SOCKET; #endif ipcom_proc_init(); #ifdef IPPPP_USE_PPPL2TP if ((ipl2tp_ppp_ipc_recv_fd = ipppp_pppl2tp_pkt_que_open()) == IP_INVALID_SOCKET) { ipcom_printf("Cannot allocate data packet output socket, errno: %d"IP_LF, ipcom_errno); goto leave; } #endif /* Get socket */ if ((udp_fd = ipcom_socket(IP_AF_INET, IP_SOCK_DGRAM, IP_IPPROTO_UDP)) < 0) { ipcom_printf("Cannot allocate socket, errno: %d"IP_LF, ipcom_errno); goto leave; } else { union Ip_sockaddr_union uaddr; /* Bind to L2TP port */ ipcom_memset(&uaddr, 0, sizeof(uaddr)); uaddr.sin.sin_family = IP_AF_INET; uaddr.sin.sin_addr.s_addr = IP_INADDR_ANY; uaddr.sin.sin_port = ip_htons(IPL2TP_PORT_NUMBER); uaddr.sin.sin_len = sizeof(struct Ip_sockaddr_in); if (ipcom_bind(udp_fd, &uaddr.sa, sizeof(struct Ip_sockaddr_in)) < 0) { ipcom_printf("Cannot bind socket, errno: %d"IP_LF, ipcom_errno); ipcom_socketclose(udp_fd); goto leave; } } /* Get socket */ if ((ip_fd = ipcom_socket(IP_AF_INET, IP_SOCK_RAW, IP_IPPROTO_L2TP)) < 0) { ipcom_printf("Cannot allocate socket, errno: %d"IP_LF, ipcom_errno); ipcom_socketclose(udp_fd); goto leave; } /* Init IPD */ if (ipd_init == 0 && ipcom_ipd_init("ipl2tp", IPCOM_SUCCESS, &ipd_fd) != IPCOM_SUCCESS) { ipcom_printf("Cannot initialize ipd: %s"IP_LF, ipcom_strerror(ipcom_errno)); goto leave; } ipd_init = 1; /* Enter read loop (never return) */ for (;;) { Ip_fd_set fds; Ipl2tp_example_fd_entry_t *fd; int fd_max; struct Ip_timeval tv; int ret; IP_FD_ZERO(&fds); IP_FD_SET(udp_fd, &fds); IP_FD_SET(ip_fd, &fds); IP_FD_SET(ipd_fd, &fds); fd_max = IP_MAX(udp_fd, ip_fd); fd_max = IP_MAX(fd_max, ipd_fd); #ifdef IPPPP_USE_PPPL2TP IP_FD_SET(ipl2tp_ppp_ipc_recv_fd, &fds); fd_max = IP_MAX(fd_max, ipl2tp_ppp_ipc_recv_fd); #endif fd = IPCOM_LIST_FIRST(&ipl2tp_example_fds); while (fd != IP_NULL) { Ipl2tp_example_fd_entry_t *nfd = IPCOM_LIST_NEXT(&fd->next); if (fd->data != IP_NULL) { IP_FD_SET(fd->fd, &fds); fd_max = IP_MAX(fd_max, fd->fd); } else { ipcom_list_remove(&fd->next); ipcom_socketclose(fd->fd); ipcom_free(fd); } fd = nfd; } tv.tv_sec = 0; tv.tv_usec = 10000; if ((ret = ipcom_socketselect(fd_max + 1, &fds, IP_NULL, IP_NULL, &tv)) > 0) { union Ip_sockaddr_union uaddr; int length; Ip_u8 *buffer; if (IP_FD_ISSET(ipd_fd, &fds)) { int event; event = ipcom_ipd_input(ipd_fd); if (event == IPCOM_IPD_EVENT_RECONFIGURE) goto leave; } #ifdef IPPPP_USE_PPPL2TP if (IP_FD_ISSET(ipl2tp_ppp_ipc_recv_fd, &fds)) { Ipppp_pppl2tp_pkt_que_entry que_entry; Ipcom_netif *netif; Ipcom_pkt *pkt; char addrstr[IP_INET_ADDRSTRLEN]; /* Read message and feed it to L2TP main input */ if (ipppp_pppl2tp_pkt_que_recv(&que_entry, &uaddr) == IPCOM_SUCCESS) { if ((que_entry.netif == IP_NULL) || (que_entry.pkt == IP_NULL)) { ipcom_printf("ipl2tps: L2TPv2 pkt from %s:%d contains null ptr(s)."IP_LF, ipcom_inet_ntop(IP_AF_INET, &uaddr.sin.sin_addr, addrstr, sizeof(addrstr)), ipcom_ntohs(uaddr.sin.sin_port)); } else { pkt = que_entry.pkt; netif = que_entry.netif; ipppp_pppl2tp_output(netif, pkt); } } else ipcom_printf("ipl2tps: PPP pkt recv failed."IP_LF); } #endif /* IPPPP_USE_PPPL2TP */ if (IP_FD_ISSET(udp_fd, &fds)) { /* Read message and feed it to L2TP main input */ if ((length = ipl2tp_l2tp_read(udp_fd, &buffer, &uaddr)) > 0) { ipl2tp_api_l2tp_input(buffer, buffer + HEADER_SPACE, (Ip_u16)length, &uaddr, IPL2TP_ATTR_TRANSPORT_UDP); /* Free buffer if not in PPP output queue */ if (ipl2tp_buffer_free) { ipl2tp_cache_free(buffer); } } } if (IP_FD_ISSET(ip_fd, &fds)) { /* Read message and feed it to L2TP main input */ if ((length = ipl2tp_l2tp_read(ip_fd, &buffer, &uaddr)) > 0) { /* Remove the IP header before invoking */ ipl2tp_api_l2tp_input(buffer, buffer + HEADER_SPACE + 20, (Ip_u16)(length - 20), &uaddr, IPL2TP_ATTR_TRANSPORT_IP); /* Free buffer if not in PPP output queue */ if (ipl2tp_buffer_free) { ipl2tp_cache_free(buffer); } } } fd = IPCOM_LIST_FIRST(&ipl2tp_example_fds); while (fd != IP_NULL) { Ipl2tp_example_fd_entry_t *nfd = IPCOM_LIST_NEXT(&fd->next); if (fd->data!= IP_NULL && IP_FD_ISSET(fd->fd, &fds)) { /* Read message and feed it to L2TP main input */ if ((length = ipl2tp_l2tp_read(fd->fd, &buffer, &uaddr)) > 0) { if (fd->data != IP_NULL) { (*fd->data) (fd, buffer, buffer + HEADER_SPACE, length); } /* Free buffer if not in PPP output queue */ if (ipl2tp_buffer_free) { ipl2tp_cache_free(buffer); } } } fd = nfd; } } else if (ret < 0) { ipcom_printf("select error"IP_LF); } } leave: /* Have to call ipd init if not done yet */ if (ipd_init == 0 && ipcom_ipd_init("ipl2tp", IPCOM_ERR_FAILED, &ipd_fd) == IPCOM_SUCCESS) { ipd_init = 1; } if (ipd_init != 0) { (void)ipcom_ipd_exit("ipl2tp", ipd_fd); } ipcom_proc_exit(); } /* *=========================================================================== * ipl2tp_create *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC Ip_err ipl2tp_create(void) { return ipl2tp_api_init() == IPL2TP_STATUS_OK ? IPCOM_SUCCESS : IPCOM_ERR_FAILED; } /* * For VxWorks, the start-up routine uses run time configuration. */ /* *=========================================================================== * ipl2tp_start *=========================================================================== * Description: Start L2TP daemon. * Parameters: * Returns: * */ IP_PUBLIC Ip_err ipl2tp_start(void) { Ip_u16 pw_list[] = { IPL2TP_ATTR_PW_TYPE_ETHERNET, IPL2TP_ATTR_PW_TYPE_ETHERNET_VLAN }; Ipl2tp_attrobj attr = IP_NULL; Ipl2tp_attrobj tattr2 = IP_NULL; Ipl2tp_attrobj sattr2 = IP_NULL; Ipl2tp_attrobj tattr3 = IP_NULL; Ipl2tp_attrobj sattr3 = IP_NULL; Ipl2tp_callback cb; Ip_err ret; #ifdef IP_PORT_VXWORKS Ip_u32 enable_v2; Ip_u32 enable_v3; #endif ipl2tp_example_sessions = ipcom_hash_new((Ipcom_hash_obj_func)ipl2tp_example_obj_hash_key, (Ipcom_hash_key_func)ipl2tp_example_obj_hash_key, (Ipcom_hash_cmp_func)ipl2tp_example_cmp_key); ipcom_list_init(&ipl2tp_example_fds); /* Initialize */ ret = ipl2tp_attr_strappend(&attr, IPL2TP_ATTR_SET_HOST_NAME, #ifdef IP_PORT_VXWORKS L2TP_HOST_NAME); #else "LAC"); #endif if (ret != IPL2TP_STATUS_OK) return (IPCOM_ERR_FAILED); cb.write_callback = (Ipl2tp_write_callback)ipl2tp_l2tp_write; if ((ipl2tp_attr_pappend(&attr, IPL2TP_ATTR_SET_L2TP_WRITE_CALLBACK, (void *)cb.voidptr) != IPL2TP_STATUS_OK) || (ipl2tp_attr_iappend(&attr, IPL2TP_ATTR_SET_ENABLE_OUTGOING, IPL2TP_MIB_YES) != IPL2TP_STATUS_OK)) return (IPCOM_ERR_FAILED); #ifdef IP_PORT_VXWORKS #if L2TP_VERSION_2_ENABLE == TRUE enable_v2 = IPL2TP_MIB_YES; #else enable_v2 = IPL2TP_MIB_NO; #endif #if L2TP_VERSION_3_ENABLE == TRUE enable_v3 = IPL2TP_MIB_YES; #else enable_v3 = IPL2TP_MIB_NO; #endif if ((ipl2tp_attr_iappend(&attr, IPL2TP_ATTR_SET_ENABLE_L2TP_V2, enable_v2) != IPL2TP_STATUS_OK) || (ipl2tp_attr_iappend(&attr, IPL2TP_ATTR_SET_ENABLE_L2TP_V3, enable_v3) != IPL2TP_STATUS_OK)) return (IPCOM_ERR_FAILED); #endif /* IP_PORT_VXWORKS */ cb.status_callback = (Ipl2tp_status_callback)ipl2tp_example_tstatus_v2; if (ipl2tp_attr_pappend(&tattr2, IPL2TP_TATTR_SET_STATUS_CALLBACK, (void *)cb.voidptr) != IPL2TP_STATUS_OK) return (IPCOM_ERR_FAILED); cb.status_callback = (Ipl2tp_status_callback)ipl2tp_example_tstatus_v3; if (ipl2tp_attr_pappend(&tattr3, IPL2TP_TATTR_SET_STATUS_CALLBACK, (void *)cb.voidptr) != IPL2TP_STATUS_OK) return (IPCOM_ERR_FAILED); if (ipl2tp_attr_vappend(&tattr3, IPL2TP_TATTR_SET_LOCAL_PSEUDOWIRE_CAPABILITIES_LIST, (void *)pw_list, sizeof(pw_list)) != IPL2TP_STATUS_OK) return (IPCOM_ERR_FAILED); cb.status_callback = (Ipl2tp_status_callback)ipl2tp_example_sstatus_v2; if (ipl2tp_attr_pappend(&sattr2, IPL2TP_SATTR_SET_STATUS_CALLBACK, (void *)cb.voidptr) != IPL2TP_STATUS_OK) return (IPCOM_ERR_FAILED); cb.ppp_callback = (Ipl2tp_ppp_callback)ipl2tp_ppp_data_cb; if (ipl2tp_attr_pappend(&sattr2, IPL2TP_SATTR_SET_DATA_CALLBACK, (void *)cb.voidptr) != IPL2TP_STATUS_OK) return (IPCOM_ERR_FAILED); cb.status_callback = (Ipl2tp_status_callback)ipl2tp_example_sstatus_v3; if ((ipl2tp_attr_pappend(&sattr3, IPL2TP_SATTR_SET_STATUS_CALLBACK, (void *)cb.voidptr) != IPL2TP_STATUS_OK) || (ipl2tp_attr_iappend(&sattr3, IPL2TP_SATTR_SET_PSEUDOWIRE_TYPE, IPL2TP_ATTR_PW_TYPE_ETHERNET_VLAN) != IPL2TP_STATUS_OK)) return (IPCOM_ERR_FAILED); if (ipl2tp_api_open(attr, tattr2, tattr3, sattr2, sattr3) != IPL2TP_STATUS_OK) return (IPCOM_ERR_FAILED); ipl2tp_attr_delete(&attr); ipl2tp_attr_delete(&tattr2); ipl2tp_attr_delete(&sattr2); ipl2tp_attr_delete(&tattr3); ipl2tp_attr_delete(&sattr3); /* Spawn new daemon process */ return ipcom_proc_acreate("l2tps", ipl2tps, IP_NULL, IP_NULL); } #if 0 /* PPP/L2TPv2 integration for third-party PPP */ /* *=========================================================================== * ppp_input_hook *=========================================================================== * Description: PPP packet input hook. * Parameters: ifindex - Interface index. * pppbuf - PPP packet. * length - Length of PPP packet. * offset . ??? * Returns: 0 to let PPP frame be parsed, else silently discarded. * */ IP_PUBLIC int ppp_input_hook(int ifindex, void *pppbuf, Ip_size_t length, Ip_size_t offset) { Ipl2tp_key *key = ipl2tp_cmd_session_key(ifindex); /* Did we locate a session key for this index? */ if (key == IP_NULL) return 0; ipl2tp_api_session_ppp_input(key, pppbuf, length, offset, 0, IP_TRUE); return 1; } /* *=========================================================================== * ppp_output_hook *=========================================================================== * Description: PPP packet output hook. This hook may be called reentrantly * in interrupt context. Such calls will be ignored, which means * that an occasional CONFREQ may be lost. However, this only * happens in the case of PPP congestion, which should never * occur during LCP negotiation. * Parameters: ifindex - Interface index. * pppbuf - PPP packet. * length - Length of PPP packet. * offset - ??? * Returns: 0 to let PPP frame be parsed, else silently discarded. * */ IP_PUBLIC int ppp_output_hook(Ip_u32 ifindex, void *pppbuf, Ip_u32 length, Ip_u32 offset) { (void)ifindex; (void)pppbuf; (void)length; (void)offset; return l2tp_output == 0; } /* *=========================================================================== * ppp_open_hook *=========================================================================== * Description: PPP link * Parameters: ifindex - Interface index. * protocol - Protocol code. * Returns: * */ IP_PUBLIC int ppp_open_hook(int ifindex, int protocol) { (void)ifindex; switch (ip_ntohs(protocol)) { case PPPP_LCP: case PPPP_PAP: case PPPP_CHAP: case PPPP_IPCP: break; default: return 1; } return 0; } /* *=========================================================================== * ppp_writedone_hook *=========================================================================== * Description: Release buffer when not required any more. * Parameters: ifindex - Interface index. * pppbuf - PPP buffer. * cookie - Original buffer pointer. * Returns: * */ IP_PUBLIC int ppp_writedone_hook(int ifindex, void *pppbuf, void *cookie) { (void)ifindex; (void)pppbuf; ipl2tp_cache_free(cookie); return 0; } #endif /* 0 */ /* **************************************************************************** * END OF FILE **************************************************************************** */