/* *=========================================================================== * ipcom_shellalias_find *=========================================================================== * Description: Find a given alias based on name. * Parameters: name - The alias name. * Returns: The alias if found. * */ IP_STATIC struct Ipcom_shellalias_alias * ipcom_shellalias_find(const char *name) { struct Ipcom_shellalias_alias *alias; /* Go through the aliases */ for (alias = IPCOM_LIST_FIRST(&ipcom_shellalias_head); alias != IP_NULL; alias = IPCOM_LIST_NEXT(&alias->next)) { if (name == IP_NULL) { int i; ipcom_printf("%-15s\t'", alias->name); for (i = 0; i < alias->argc; i++) { ipcom_printf("%s%s", alias->argv[i], (i == alias->argc - 1)? "" : " "); } ipcom_printf("'"IP_LF); } /* Did it match? */ else if (ipcom_strcmp(alias->name, name) == 0) { /* Return it */ return alias; } } /* No go */ return IP_NULL; }
/* *=========================================================================== * ipcom_shell_cmd_help *=========================================================================== * Description: Shell command: Get help on command or display all commands * Parameters: argc - number of arguments * argv - pointer to pointer to the arguments * Returns: 0 * */ IP_STATIC int ipcom_shell_cmd_help(int argc, char **argv) { Ipcom_shell_cmd *cmd; Ipcom_shell_intcmd *intcmd; Ip_s32 i = 0; /* Check if argument is supplied */ if (argc > 1) { intcmd = IP_NULL; /* Find shell internal command */ while(shell_intcmd[i].name[0] != 0) { intcmd = (Ipcom_shell_intcmd *)&shell_intcmd[i]; if (ipcom_strcmp(intcmd->name, argv[1]) == 0) break; intcmd = IP_NULL; i++; } if (intcmd) { ipcom_printf("Usage: %s\n", intcmd->usage); return 0; } /* Find shell command */ cmd = ipcom_shell_find_cmd(argv[1]); if (cmd) { ipcom_printf("Usage: %s\n", cmd->usage); return 0; } /* Command not found */ ipcom_printf("help: Unknown command '%s'\n", argv[1]); } else { /* List all shell internal commands */ while(shell_intcmd[i].name[0] != 0) { ipcom_printf("%-32s %s\n", shell_intcmd[i].name, shell_intcmd[i].description); i++; } /* List all shell commands */ for (cmd = IPCOM_LIST_FIRST(&ipcom_shell_cmd_head); cmd; cmd = IPCOM_LIST_NEXT(&cmd->cmd_list)) { ipcom_printf("%-32s %s\n", cmd->name, cmd->description); } ipcom_printf("\n"); } return 0; }
/* *=========================================================================== * ipcom_shell_find_cmd *=========================================================================== * Description: Search for a command in the list of available ipcom_shell * commands * Parameters: name : the command to search for * Returns: pointer to the command or IP_NULL if not found * */ IP_PUBLIC Ipcom_shell_cmd * ipcom_shell_find_cmd(const char *name) { Ipcom_shell_cmd *cmd; /* First check if present */ for (cmd = IPCOM_LIST_FIRST(&ipcom_shell_cmd_head); cmd; cmd = IPCOM_LIST_NEXT(&cmd->cmd_list)) if (ipcom_strcmp(cmd->name, name) == 0) break; return cmd; }
/* *=========================================================================== * ipnet_nat_proxy_dns_find_transaction *=========================================================================== * Description: Find a transaction in the list of transactions. * Parameters: type - DNS query type. * dns_hdr - pointer to the DNS protocol header. * param - pointer to NAT proxy parameters. * Returns: A pointer to transaction if found or else IP_NULL. */ IP_STATIC Ipnet_nat_dns_transaction * ipnet_nat_proxy_dns_find_transaction(int type, Ipnet_nat_dns_hdr *dns_hdr, Ipnet_nat_proxy_param *param) { Ipnet_nat_dns_transaction *trans; Ip_u16 id; id = (Ip_u16)IP_GET_NTOHS(&dns_hdr->id); for (trans = IPCOM_LIST_FIRST(&ipnet_nat_proxy_dns_list); trans != IP_NULL; trans = IPCOM_LIST_NEXT(&trans->list)) { if (id == trans->id && param->tuple.private_port == trans->srcport && param->tuple.public_addr == trans->dstaddr && type == trans->type) { return trans; } } return IP_NULL; }
/* *=========================================================================== * 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(); }
/* *=========================================================================== * 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; }