/* *=========================================================================== * ipcom_random_init *=========================================================================== * Description: * Parameters: * Returns: * */ IP_GLOBAL Ip_err ipcom_random_init(void) { struct Ip_timeval tval; Ip_err rc = IPCOM_SUCCESS; unsigned int deliberately_uninitialized; /* Make sure we have some random seed at boot. Good in general and in * particular since IPNET uses ipcom_random to generate random MAC * addresses in the unix port. */ (void) ipcom_gettimeofday(&tval, IP_NULL); ipcom_srandom((unsigned int)(tval.tv_sec + tval.tv_usec)); ipcom_srandom(ipcom_getpid()); ipcom_srandom(deliberately_uninitialized); #ifdef IPCOM_USE_EGD { Ipcom_proc_attr attr; ipcom_proc_attr_init(&attr); attr.priority = IPCOM_PRIORITY_BACKGROUND; attr.flags = IPCOM_PROC_FLAG_FP; rc = ipcom_proc_acreate("ipcom_egd", ipcom_egd, &attr, IP_NULL); } #endif return rc; }
/* *=========================================================================== * ipcom_cmd_smptest_server *=========================================================================== * Description: This is the server part of the smptest command * Parameters: The address we should listen to, and info about how many sockets * we should use. * Returns: 0 on success. -1 on failure. */ IP_STATIC int ipcom_cmd_smptest_server() { Ipcom_proc_attr attr; unsigned int i; Ipcom_proc *proc; int retval; spawn_number_server = 0; if ( 0 != ipcom_sem_create( &sem_wait_server, 0 ) ) { ipcom_printf("ipcom_sem_create failed: %s"IP_LF, ipcom_strerror(ipcom_errno)); return -1; } ipcom_atomic_set( &num_wait_server, smp_opt_server.num_sock ); ipcom_atomic_set( &listen_wait, smp_opt_server.num_sock ); ipcom_proc_attr_init(&attr); attr.priority = IPCOM_PRIORITY_DEFAULT; /* Hacky hacky way to write from a task.. copied from ipcom_mshell.c */ proc = ipcom_proc_self(); ip_assert( proc != 0 ); server_out = proc->shell_fd; for ( i = 0;i < smp_opt_server.num_sock;++i ) { retval = ipcom_proc_acreate("ipcom_cmd_smptest_server_spawn", (Ipcom_proc_func)ipcom_cmd_smptest_server_spawn, &attr, 0 ); if (retval != 0) { ipcom_printf( "Error spawning smptest server"IP_LF ); return retval; } } ipcom_sem_wait( sem_wait_server ); ipcom_sem_delete( &sem_wait_server ); return 0; }
/* *=========================================================================== * ipcom_cmd_smptest_client *=========================================================================== * Description: This is the client part of the smptest command * Parameters: The address we should connect to, and info about how many sockets * we should use. * Returns: 0 on success. -1 on failure. */ IP_STATIC int ipcom_cmd_smptest_client() { Ipcom_proc_attr attr; unsigned int i; int retval; spawn_number_client = 0; if ( 0 != ipcom_sem_create( &sem_wait_client, 0 ) ) { ipcom_printf("ipcom_sem_create failed: %s"IP_LF, ipcom_strerror(ipcom_errno)); return -1; } ipcom_atomic_set( &num_wait_client, smp_opt_client.num_sock ); ipcom_proc_attr_init(&attr); attr.priority = IPCOM_PRIORITY_DEFAULT; for ( i = 0;i < smp_opt_client.num_sock;++i ) { retval = ipcom_proc_acreate("ipcom_cmd_smptest_client_spawn", (Ipcom_proc_func)ipcom_cmd_smptest_client_spawn, &attr, 0 ); if (retval != 0) { ipcom_printf( "Error spawning smptest client"IP_LF ); return retval; } } ipcom_sem_wait( sem_wait_client ); /* wait for tasks to complete */ ipcom_sem_delete( &sem_wait_client ); return 0; }
/* *=========================================================================== * 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; Ip_u32 enable_v2; Ip_u32 enable_v3; 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 */ ipl2tp_attr_strappend(&attr, IPL2TP_ATTR_SET_HOST_NAME, L2TP_HOST_NAME); ipl2tp_attr_pappend(&attr, IPL2TP_ATTR_SET_L2TP_WRITE_CALLBACK, (void *)ipl2tp_l2tp_write); ipl2tp_attr_iappend(&attr, IPL2TP_ATTR_SET_ENABLE_OUTGOING, IPL2TP_MIB_YES); #if L2TP_VERSION_2_ENABLE == TRUE enable_v2 = IPL2TP_MIB_YES; #else enable_v2 = IPL2TP_MIB_NO; #endif ipl2tp_attr_iappend(&attr, IPL2TP_ATTR_SET_ENABLE_L2TP_V2, enable_v2); #if L2TP_VERSION_3_ENABLE == TRUE enable_v3 = IPL2TP_MIB_YES; #else enable_v3 = IPL2TP_MIB_NO; #endif ipl2tp_attr_iappend(&attr, IPL2TP_ATTR_SET_ENABLE_L2TP_V3, enable_v3); ipl2tp_attr_pappend(&tattr2, IPL2TP_TATTR_SET_STATUS_CALLBACK, (void *)ipl2tp_example_tstatus_v2); ipl2tp_attr_pappend(&tattr3, IPL2TP_TATTR_SET_STATUS_CALLBACK, (void *)ipl2tp_example_tstatus_v3); ipl2tp_attr_vappend(&tattr3, IPL2TP_TATTR_SET_LOCAL_PSEUDOWIRE_CAPABILITIES_LIST, (void *)pw_list, sizeof(pw_list)); ipl2tp_attr_pappend(&sattr2, IPL2TP_SATTR_SET_STATUS_CALLBACK, (void *)ipl2tp_example_sstatus_v2); ipl2tp_attr_pappend(&sattr2, IPL2TP_SATTR_SET_DATA_CALLBACK, (void *)ipl2tp_ppp_data_cb); ipl2tp_attr_pappend(&sattr3, IPL2TP_SATTR_SET_STATUS_CALLBACK, (void *)ipl2tp_example_sstatus_v3); ipl2tp_attr_iappend(&sattr3, IPL2TP_SATTR_SET_PSEUDOWIRE_TYPE, IPL2TP_ATTR_PW_TYPE_ETHERNET_VLAN); ipl2tp_api_open(attr, tattr2, tattr3, sattr2, sattr3); 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); }
/* *=========================================================================== * ipcom_shell_run_extcmd *=========================================================================== * Description: Starts a shell command process and delivers the command arguments * and stdio socket to that process. * Parameters: argc, argv - traditional command arguments * stdio_fd - the standard input, output and error sock * ppid - parent pid * cmd_pid - shell command process id * * Returns: 1 : command process started * 0 : not an external command * -1 : error * */ IP_PUBLIC Ip_err ipcom_shell_run_extcmd(int argc, char **argv, Ip_fd *stdio_fd, Ip_pid_t ppid, Ip_u32 seqno, Ip_pid_t *cmd_pid, int *proc_index) { Ipcom_proc_attr attr; Ipcom_ipc ipc; Ipcom_shellcmd_info *sinfo; Ipcom_shell_cmd *cmd = IP_NULL; Ipcom_shell_cmd *tcmd; Ip_err retval; char procname[40]; Ip_u32 stack = IPCOM_PROC_STACK_DEFAULT; Ip_pid_t pid; pid = ipcom_getpid(); ipcom_sprintf(procname, "ipcom_sc_0x%lx_%d", (Ip_u32)pid, *proc_index); /* Find command and max stack size (since we are reusing the process). */ if (argc > 0) { for (tcmd = IPCOM_LIST_FIRST(&ipcom_shell_cmd_head); tcmd; tcmd = IPCOM_LIST_NEXT(&tcmd->cmd_list)) { stack = (Ip_u32)IP_MAX(stack, tcmd->stack_size); if (cmd == IP_NULL && ipcom_strcmp(tcmd->name, argv[0]) == 0) { cmd = tcmd; if (*cmd_pid != 0) break; } } if (cmd == IP_NULL) return 0; /* Start the shell_cmd process. */ if (*cmd_pid == 0) { ipcom_proc_attr_init(&attr); attr.priority = (Ip_u32)cmd->priority; attr.stacksize = stack; attr.flags |= IPCOM_PROC_FLAG_FP; if (ipcom_proc_acreate(procname, (Ipcom_proc_func)ipcom_shell_cmd, &attr, cmd_pid)) { IPCOM_LOG0(ERR, "ipcom_shell_run_extcmd :: ipcom_proc_acreate() failed"); goto fail; } ip_assert(*cmd_pid != 0); } } else { /* argc == 0 is used to kill the shell_cmd process. */ ip_assert(*cmd_pid != 0); } /* Open IPC with ipcom_shell. */ retval = ipcom_ipc_open(&ipc, procname, -1); if (retval != IPCOM_SUCCESS) { IPCOM_LOG2(ERR, "ipcom_shell_run_extcmd :: ipcom_ipc_open(%s) failed, ret = %d", procname, retval); goto fail; } /* Send a message to ipcom_shell. */ sinfo = ipcom_ipc_malloc(sizeof(Ipcom_shellcmd_info)); if (sinfo == IP_NULL) { IPCOM_LOG1(ERR, "ipcom_shell_run_extcmd :: ipcom_ipc_malloc() failed, ret = %d", retval); goto fail; } /* Fill in IPC info. */ sinfo->argc = argc; if (argc > 0) { sinfo->hook = cmd->hook; sinfo->argv = argv; sinfo->fd = *stdio_fd; sinfo->pid = pid; sinfo->ppid = ppid; sinfo->seqno = seqno; #if IPCOM_USE_FILE != IPCOM_FILE_NONE if (ipcom_getcwd(sinfo->cwd, sizeof(sinfo->cwd)) == IP_NULL) ipcom_memset(sinfo->cwd, 0, sizeof(sinfo->cwd)); else sinfo->cwd[sizeof(sinfo->cwd)-1] = '\0'; #endif sinfo->prio = cmd->priority; } /* Send the IPC info. */ retval = ipcom_ipc_send(&ipc, sinfo); if (retval != IPCOM_SUCCESS) { IPCOM_LOG1(ERR, "ipcom_shell_run_extcmd :: ipcom_ipc_send() failed, ret = %d", retval); ipcom_ipc_free(sinfo); goto fail; } (void)ipcom_ipc_close(&ipc); #ifdef IP_PORT_OSE5 if (argc > 0) { /* OSE5 has process specific sockets -> donate child fd */ ip_assert(*cmd_pid != 0); retval = (Ip_err)efs_donate_fd(*stdio_fd, *cmd_pid); if (retval != 0) { IPCOM_LOG1(ERR, "ipcom_shell_run_extcmd :: efs_donate_fd, ret = %d", retval); goto fail; } } #endif /* IP_PORT_OSE5 */ /* Wait for exit message from shell_cmd process. */ retval = ipcom_ipc_receive(IP_NULL, &sinfo, -1); if (retval != IPCOM_SUCCESS) { IPCOM_LOG1(ERR, "ipcom_shell_run_extcmd :: ipcom_ipc_receive(shell_cmd) failed, ret = %d", retval); goto fail; } ip_assert(argc > 0 || *(Ip_u32 *)sinfo == 1); if (*(Ip_u32 *)sinfo == 1) { *cmd_pid = 0; /* shell command called ipcom_exit(). */ (*proc_index)++; } else { #ifdef IP_PORT_OSE5 *stdio_fd = efs_receive_fd(0); if (*stdio_fd == -1) { IP_PANIC(); goto fail; } #endif #if defined(IP_PORT_OSE) || defined(IP_PORT_OSE5) /* Change child socket owner (A must for OSE to work due to poor ipcom_block impl). */ pid = ipcom_getpid(); if (ipcom_socketioctl(*stdio_fd, IP_SIOCSPGRP, &pid) < 0) { IP_PANIC2(); IPCOM_LOG1(WARNING, "ipcom_shell_run_extcmd :: ipcom_socketioctl(IP_SIOCSPGRP) failed, errno = %d", ipcom_errno); } #endif } ipcom_ipc_free(sinfo); return 1; fail: if (ipcom_ipc_isopen(&ipc)) (void)ipcom_ipc_close(&ipc); return -1; }
/* *=========================================================================== * ipcom_drv_ppp_init *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC int ipcom_drv_ppp_init(Ipcom_drv_ppp_link *plink) { Ipcom_ipc ipc; Ipcom_drv_ppp_ipc *ipcbuf; char procname[IPCOM_PROC_NAME_MAX]; Ip_err retval; Ipcom_proc_attr attr; /* Open driver */ if (ipcom_drv_ppp_open(plink) != 0) goto fail; /* Create driver I/O daemons */ ipcom_proc_attr_init(&attr); attr.priority = IPCOM_PRIORITY_MIN; attr.stacksize = IPCOM_PROC_STACK_SMALL; /* Create and open output daemon */ ipcom_sprintf(procname, "ipcom_drv_%s_output", plink->netif->name); retval = ipcom_proc_acreate(procname, ipcom_drv_ppp_outputd, &attr, IP_NULL); if (retval != IPCOM_SUCCESS) goto fail; retval = ipcom_ipc_open(&plink->out_ipc, procname, -1); if (retval != IPCOM_SUCCESS) goto fail; /* Create and start input daemon */ ipcom_sprintf(procname, "ipcom_drv_%s_input", plink->netif->name); retval = ipcom_proc_acreate(procname, ipcom_drv_ppp_inputd, &attr, IP_NULL); if (retval != IPCOM_SUCCESS) goto fail; /* Open IPC. */ ipcom_sprintf(procname, "ipcom_drv_%s_input", plink->netif->name); retval = ipcom_ipc_open(&ipc, procname, -1); if (retval != IPCOM_SUCCESS) goto fail; /* Create IPC buf */ ipcbuf = ipcom_ipc_malloc(sizeof(Ipcom_drv_ppp_ipc)); if (ipcbuf == IP_NULL) goto fail; ipcbuf->netif = plink->netif; /* Send IPC buf */ retval = ipcom_ipc_send(&ipc, ipcbuf); if (retval != IPCOM_SUCCESS) { (void)ipcom_ipc_close(&ipc); goto fail; } /* Close IPC. */ (void)ipcom_ipc_close(&ipc); /* Success. */ return 0; fail: if (plink->fd != -1) { (void)close(plink->fd); plink->fd = -1; } IPCOM_LOG2(ERR, "ipcom_drv_ppp_init :: failed to open %s for %s", plink->devname, plink->netif->name); return -IP_ERRNO_EINVAL; }
/* *=========================================================================== * ipcom_start_shell *=========================================================================== * Description: Starts a shell process and sets up a TCP connection. The * TCP connection is used to convey stdin and stdout data. The * stdio proxy process and the underlaying shell process is * terminated by closing the socket. If the shell terminates * (e.g. if the user gives the command 'exit') the stdio proxy * will close the TCP connection and terminate. * Parameters: * Returns: * */ IP_PUBLIC Ip_err ipcom_start_shell(Ip_fd *stdio_sock, Ip_fd client_fd) { Ip_fd mother = IP_INVALID_SOCKET; Ip_fd shell_fd = IP_INVALID_SOCKET; Ip_socklen_t addr_len; Ipcom_ipc ipc; Ipcom_shell_info *sinfo; char procname[40]; Ip_err retval; Ipcom_proc_attr attr; Ip_bool ipc_opened = IP_FALSE; Ip_pid_t ppid, shell_pid; Ip_u16 mother_port; static Ip_u32 seqno = 0; struct Ip_addrinfo hints; struct Ip_addrinfo *res = IP_NULL; union Ip_sockaddr_union sa; *stdio_sock = IP_INVALID_SOCKET; sinfo = ipcom_ipc_malloc(sizeof(Ipcom_shell_info)); if (sinfo == IP_NULL) { IPCOM_LOG0(ERR, "ipcom_start_shell :: ipcom_ipc_malloc() failed"); goto exit; } addr_len = sizeof(sinfo->sa_prompt); if (ipcom_getsockname(client_fd, (struct Ip_sockaddr *)&sinfo->sa_prompt, &addr_len) == IP_SOCKERR) { IPCOM_LOG1(ERR, "ipcom_start_shell :: ipcom_getsockname(client_fd) failed, errno = %d", ipcom_errno); goto exit; } /* Get a tcp socket and let the stack pick a port */ ipcom_memset(&hints, 0, sizeof(hints)); hints.ai_family = sinfo->sa_prompt.sa.sa_family; hints.ai_socktype = IP_SOCK_STREAM; if (ipcom_getaddrinfo(IP_NULL, "0", &hints, &res) != 0) { IPCOM_LOG1(ERR, "ipcom_start_shell :: ipcom_getsockname(client_fd) failed, errno = %d", ipcom_errno); goto exit; } mother = ipcom_socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (mother == IP_INVALID_SOCKET) { IPCOM_LOG1(ERR, "ipcom_start_shell :: ipcom_socket(IP_AF_INET) failed, errno = %d", ipcom_errno); goto exit; } if (ipcom_bind(mother, res->ai_addr, res->ai_addrlen) == IP_SOCKERR) { IPCOM_LOG1(ERR, "ipcom_start_shell :: ipcom_bind(IP_AF_INET) failed, errno = %d", ipcom_errno); goto exit; } /* Find out which port was assigned. */ addr_len = sizeof(sa); if (ipcom_getsockname(mother, (struct Ip_sockaddr *)&sa, &addr_len) == IP_SOCKERR) { IPCOM_LOG1(ERR, "ipcom_start_shell :: ipcom_getsockname(IP_AF_INET) failed, errno = %d", ipcom_errno); goto exit; } mother_port = ip_ntohs(sa.sin.sin_port); if (ipcom_listen(mother, 1) == IP_SOCKERR) { IPCOM_LOG1(ERR, "ipcom_start_shell :: ipcom_listen() failed, errno = %d", ipcom_errno); goto exit; } /* Create and start the shell process. */ ipcom_proc_attr_init(&attr); #ifdef IP_PORT_VXWORKS attr.stacksize = IPCOM_PROC_STACK_LARGE; #else attr.priority = IPCOM_PRIORITY_DEFAULT; #endif /* IP_PORT_VXWORKS */ ppid = ipcom_getpid(); ipcom_sprintf(procname, "ipcom_shell_%lx_%lx", (Ip_u32)ppid, ++seqno); if (ipcom_proc_acreate(procname, (Ipcom_proc_func)ipcom_shell, &attr, &shell_pid)) { IPCOM_LOG0(ERR, "ipcom_start_shell :: ipcom_proc_acreate() failed"); goto exit; } /* Open IPC with ipcom_shell. */ retval = ipcom_ipc_open(&ipc, procname, -1); if (retval != IPCOM_SUCCESS) { IPCOM_LOG2(ERR, "ipcom_start_shell :: ipcom_ipc_open(%s) failed, ret = %d", procname, retval); goto exit; } ipc_opened = IP_TRUE; /* Send a message to ipcom_shell. */ sinfo->port = mother_port; sinfo->ppid = ppid; sinfo->seqno = seqno; retval = ipcom_ipc_send(&ipc, sinfo); if (retval != IPCOM_SUCCESS) { IPCOM_LOG1(ERR, "ipcom_start_shell :: ipcom_ipc_send() failed, ret = %d", retval); goto exit; } /* Wait for the shell process to connect */ shell_fd = ipcom_accept(mother, IP_NULL, IP_NULL); exit: if (mother != IP_INVALID_SOCKET) (void)ipcom_socketclose(mother); if (res != IP_NULL) ipcom_freeaddrinfo(res); if (ipc_opened) (void)ipcom_ipc_close(&ipc); else if (sinfo != IP_NULL) ipcom_ipc_free(sinfo); if (shell_fd == IP_INVALID_SOCKET) return IPCOM_ERR_FAILED; else { int enable = IP_TRUE; *stdio_sock = shell_fd; /* Disable Nagle (enable no delay) on this socket since it is an interactive connection */ (void)ipcom_setsockopt(shell_fd, IP_IPPROTO_TCP, IP_TCP_NODELAY, &enable, sizeof(enable)); return IPCOM_SUCCESS; } }