/*
 *===========================================================================
 *                    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);
}
Exemple #5
0
/*
 *===========================================================================
 *                    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;
    }
}