/* *=========================================================================== * ipnet_udp_fast_deliver_data *=========================================================================== * Description: Deliver an UDP packet to a socket that is bound to a unicast * address. * Parameters: sock - The socket the packet will be delivered to. * pkt - The UDP packet to deliver. * nat_t - NAT_T processing. * Returns: IP_TRUE - The fast path processing was successful. * IP_FALSE - Need to use the normal receive path. * */ IP_STATIC Ip_bool ipnet_udp_fast_deliver_data(Ipnet_socket *sock, Ipcom_pkt *pkt, int *nat_t) { Ipnet_pkt_udp *udp_hdr; int original_start = pkt->start; Ipcom_socket_eventcb event_cb = sock->ipcom.event_cb; udp_hdr = (Ipnet_pkt_udp*) &pkt->data[pkt->tlstart]; if (IP_UNLIKELY(pkt->end - pkt->tlstart < IPNET_UDP_HDR_SIZE || pkt->end - pkt->tlstart < ip_ntohs(udp_hdr->ulen))) return IP_FALSE; if (udp_hdr->sum != 0 && IP_BIT_ISFALSE(pkt->flags, IPCOM_PKT_FLAG_LOOPED_BACK)) { Ip_u16 chksum; /* Only check packets that was not created locally */ #ifdef IPCOM_USE_HW_CHECKSUM_RX if (IP_BIT_ISSET(pkt->flags, IPCOM_PKT_FLAG_HW_CHECKSUM)) chksum = 0; else if (IP_BIT_ISSET(pkt->flags, IPCOM_PKT_FLAG_TL_CHECKSUM)) chksum = ipcom_in_checksum_finish(pkt->chk); else #endif /* IPCOM_USE_HW_CHECKSUM_RX */ { pkt->chk += ipcom_in_checksum_update(&pkt->data[pkt->tlstart], (Ip_size_t) ip_ntohs(udp_hdr->ulen)); chksum = ipcom_in_checksum_finish(pkt->chk); } if (IP_UNLIKELY(chksum != 0)) return IP_FALSE; } pkt->fd = sock->ipcom.fd; pkt->start = pkt->tlstart + IPNET_UDP_HDR_SIZE; if (IP_UNLIKELY(ipnet_udp_encapsulation(sock, pkt, nat_t))) { /* Continue processing */ ipcom_pkt_set_info(pkt, IPNET_PKT_INFO_ENCAP_UDP, sizeof(*udp_hdr), udp_hdr); pkt->start = original_start; return IP_FALSE; } if (ipnet_queue_received_packet(pkt, sock) != 0) { pkt->start = original_start; return IP_FALSE; } if (event_cb != IP_NULL) event_cb(&sock->ipcom, pkt, IP_SOEVENT_CB_INPKT); IPCOM_MIB2(udpInDatagrams++); IPCOM_MIB2_U64_INC(udpHCInDatagrams); return IP_TRUE; }
/* *=========================================================================== * ipsecctrl_selectorTable_print *=========================================================================== * Description: * Parameters: * Returns: * */ static void ipsecctrl_selectorTable_print(Argvars *vars) { Ipipsec_ctrl_selector sel; #ifdef IPCOM_USE_INET6 char str[IP_INET6_ADDRSTRLEN]; #else char str[16]; #endif ipcom_printf(IP_LF"***** selectorTable ::"IP_LF); sel.Index = 0; /* get first selector. */ /* Get and print the Selectors in MIB format. */ for (;;) { /* Get first/next Selector */ if (ipcom_socketioctl(vars->fd, IP_SIOCXIPSEC_SELECTOR, &sel) < 0) { ipcom_printf("ipsecctrl: ipcom_socketioctl(SELECTOR) failed (%s)"IP_LF, ipcom_strerror(ipcom_errno)); return; } if (sel.Index == 0) break; /* Print selector index */ ipcom_printf(IP_LF"Selector Entry #%ld:"IP_LF "selectorIndex = %ld"IP_LF, sel.Index, sel.Index); ipcom_printf("selectorLocalId = %s"IP_LF "selectorLocalIdType = %s"IP_LF, ipcom_inet_ntop(sel.domain, &sel.LocalId, str, sizeof(str)), sel.domain == IP_AF_INET ? "idIpv4Addr" : "idIpv6Addr"); ipcom_printf("selectorRemoteId = %s"IP_LF "selectorRemoteIdType = %s"IP_LF, ipcom_inet_ntop(sel.domain, &sel.RemoteId, str, sizeof(str)), sel.domain == IP_AF_INET ? "idIpv4Addr" : "idIpv6Addr"); ipcom_printf("selectorProtocol = %s"IP_LF, ipcom_ipproto_name(sel.Protocol)); ipcom_printf("selectorLocalPort = %d"IP_LF, ip_ntohs(sel.LocalPort)); ipcom_printf("selectorRemotePort = %d"IP_LF, ip_ntohs(sel.RemotePort)); } }
/* *=========================================================================== * ipcom_cmd_sockperf_connect *=========================================================================== * Description: Active open of socket(s) * Parameters: * Returns: */ IP_STATIC void ipcom_cmd_sockperf_connect(Ipcom_cmd_sockperf_t *cmd) { Ip_fd *s = cmd->sock_array; Ip_u32 created_sockets; struct Ip_timeval start; struct Ip_timeval stop; ipcom_printf("sockperf-c: connecting to %s[%d]"IP_LF, cmd->res->ai_canonname, ip_ntohs(((struct Ip_sockaddr_in *)cmd->res->ai_addr)->sin_port)); ipcom_microtime(&start); for (created_sockets = 0; created_sockets < cmd->num_sock; created_sockets++) { s[created_sockets] = ipcom_socket(cmd->res->ai_family, cmd->res->ai_socktype, cmd->res->ai_protocol); if (s[created_sockets] == IP_SOCKERR) { ipcom_printf("sockperf-c: Failed to create socket: %s"IP_LF, ipcom_strerror(ipcom_errno)); created_sockets--; goto cleanup; } if (ipcom_setsockopt(s[created_sockets], IP_SOL_SOCKET, IP_SO_LINGER, &cmd->linger, sizeof(cmd->linger)) < 0) { ipcom_printf("sockperf-c: setsockopt SO_LINGER failed : %s"IP_LF, ipcom_strerror(ipcom_errno)); goto cleanup; } if (ipcom_connect(s[created_sockets], cmd->res->ai_addr, cmd->res->ai_addrlen) < 0) { ipcom_printf("sockperf-c: Failed to connect: %s"IP_LF, ipcom_strerror(ipcom_errno)); goto cleanup; } } ipcom_microtime(&stop); ipcom_printf("sockperf-t: %ld sockets connected in %ld ms"IP_LF, created_sockets, ipcom_cmd_sockperf_tv_to_msec(&start, &stop)); ipcom_cmd_sockperf_run(cmd); cleanup: while (created_sockets > 0) (void)ipcom_socketclose(s[created_sockets--]); }
/* *=========================================================================== * ipnet_loopback_raw_output *=========================================================================== * Description: Output function for AF_PACKET socket datagrams. * Parameters: netif - The interface the packet was sent to. * to - The recipient of this packet. * pkt - The packet to loopback. pkt->start is the offset to the * IP header. * Returns: 0 = success, 0< = error code. * */ IP_STATIC int ipnet_loopback_raw_output(struct Ipnet_netif_struct *netif, IP_CONST struct Ip_sockaddr_ll *to, Ipcom_pkt *pkt) { #ifdef IPCOM_USE_INET if (ip_ntohs(to->sll_protocol) == IP_IPPROTO_IPV4) { IP_BIT_SET(pkt->flags, IPCOM_PKT_FLAG_IPV4); return netif->link_ip4_output(netif, IP_NULL, pkt); } #endif /* IPCOM_USE_INET */ #ifdef IPCOM_USE_INET6 if (ip_ntohs(to->sll_protocol) == IP_IPPROTO_IPV6) { IP_BIT_SET(pkt->flags, IPCOM_PKT_FLAG_IPV6); return netif->link_ip6_output(netif, IP_NULL, pkt); } #endif /* IPCOM_USE_INET6 */ IP_PANIC2(); return -IP_ERRNO_EINVAL; }
/* *=========================================================================== * 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; }
/* *=========================================================================== * ipcom_getservbyport *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC struct Ip_servent * ipcom_getservbyport(int port, char *proto) { static struct Ip_servent se; static char *s_aliases[3] = { IP_NULL, IP_NULL, IP_NULL }; struct Ipcom_service *sp; sp = ipcom_find_service_byport((int)ip_ntohs(port), proto); if(sp == IP_NULL) return IP_NULL; se.s_name = sp->name; s_aliases[0] = sp->alias1; s_aliases[1] = sp->alias2; se.s_aliases = s_aliases; se.s_port = (int)ip_htons(sp->port); se.s_proto = sp->proto; return &se; }
/* *=========================================================================== * ipcom_drv_eth_filter_pkt_to_me *=========================================================================== * Description: Returns if this packet was sent to this node. * Parameters: filter - The current filter for this interface. * frame - An Ethernet frame. * Returns: IP_TRUE if this packet was sent to this node. * */ IP_PUBLIC Ip_bool ipcom_drv_eth_filter_pkt_to_me(Ipcom_drv_eth_filter *filter, Ipcom_eth_hdr *frame) { int i; if (filter->promisc) /* Driver in software-promiscuous mode, accept all packets. */ return IP_TRUE; if (frame->dst[0] == 0xFF) /* Ethernet broadcast is always accepted */ return IP_TRUE; if (IP_BIT_ISFALSE(frame->dst[0], 0x01)) { /* Unicast packet */ if (ipcom_memcmp(filter->unicast_addr, frame->dst, IPCOM_DRV_ETH_ADDR_SIZE) != 0) /* Not my MAC address */ return IP_FALSE; #ifdef IPCOM_USE_INET if (filter->in_block_addr.s_addr && ip_ntohs(frame->type) == 0x0800 && ipcom_memcmp(&filter->in_block_addr, &frame->data[16], 4) == 0) /*lint !e416 !e420 */ return IP_FALSE; #endif return IP_TRUE; } /* Check multicast groups */ for (i = 0; i < IPCOM_DRV_ETH_MAX_MULTIADDR; i++) if (filter->ref[i] != 0 && ipcom_memcmp(filter->mcast_addr[i], frame->dst, IPCOM_DRV_ETH_ADDR_SIZE) == 0) return IP_TRUE; /* This multicast frame was not sent to this interface */ return IP_FALSE; }
IP_STATIC IPCOM_PROCESS( ipcom_cmd_smptest_server_spawn ) { union { struct Ip_sockaddr sa; #ifdef IPCOM_USE_INET6 struct Ip_sockaddr_in6 sin6; #endif struct Ip_sockaddr_storage ss; struct Ip_sockaddr_in sin; } addr; Ip_fd listen_socket; Ip_fd connect_sock = 0; int opt_val = 1; int portadd = spawn_number_server++; int bytes = 0; int sec = SECONDS_CLIENT + SECONDS_SERVER; unsigned char *buf = 0; int num_recives = 0; unsigned long num_bytes = 0; struct Ip_sockaddr from; struct Ip_linger linger; Ip_socklen_t from_length = 0; int retry_count = 0; ipcom_proc_init(); ipcom_memset( &addr.ss, 0, sizeof( addr.ss ) ); ipcom_memcpy( &addr.sa, smp_opt_server.res->ai_addr, smp_opt_server.res->ai_addrlen ); linger.l_onoff = 1; linger.l_linger = 2; listen_socket = ipcom_socket( smp_opt_server.res->ai_family, smp_opt_server.res->ai_socktype, smp_opt_server.res->ai_protocol ); if (listen_socket == IP_SOCKERR) { ipcom_printf("Failed to create socket: %s"IP_LF, ipcom_strerror(ipcom_errno)); return_server = 1; ipcom_sem_post( sem_wait_server ); return; } if ( 0 != ipcom_setsockopt(listen_socket, IP_SOL_SOCKET, IP_SO_REUSEPORT, &opt_val, sizeof (opt_val)) ) { ipcom_printf("ipcom_setsockopt failed: %s"IP_LF, ipcom_strerror(ipcom_errno)); return_server = 1; ipcom_sem_post( sem_wait_server ); return; } addr.sin.sin_port = ip_htons( smp_opt_server.port + portadd ); /* port is in the same place for IPv4 and IPv6 */ if ( 0 != ipcom_bind( listen_socket, &addr.sa, sizeof( addr.ss ) ) ) { ipcom_printf("Failed to bind: %s"IP_LF, ipcom_strerror(ipcom_errno)); return_server = 1; ipcom_sem_post( sem_wait_server ); return; } buf = ipcom_malloc( smp_opt_server.num_bytes ); if ( smp_opt_server.tcp ) { if ( -1 == ipcom_listen( listen_socket, 0 ) ) { ipcom_printf("Listen failed: %s"IP_LF, ipcom_strerror(ipcom_errno)); return_server = 1; ipcom_sem_post( sem_wait_server ); return; } if ( verbose ) ipcom_printf("Thread %d listens to %s:%d"IP_LF, portadd, smp_opt_server.res->ai_canonname, ip_ntohs( addr.sin.sin_port ) ); } if ( 0 == ipcom_atomic_sub_and_return( &listen_wait, 1 ) ) { /* Send to the test-server or write to stdout? */ if ( server_out >= 0 ) { char ready[] = "Ready."; ipcom_socketwrite(server_out, ready, 8 ); } else ipcom_printf("Ready."IP_LF ); } if ( 0 != ipcom_socketioctl( listen_socket, IP_X_SIOCSINTR, &sec ) ) { ipcom_printf("ipcom_socketioctl failed: %s"IP_LF, ipcom_strerror(ipcom_errno)); return_server = 1; ipcom_sem_post( sem_wait_server ); return; } if ( smp_opt_server.tcp ) { retry: connect_sock = ipcom_accept( listen_socket, IP_NULL, 0 ); if ( -1 == connect_sock ) { if ( ipcom_errno == IP_ERRNO_EINTR ) { if ( verbose ) { if ( ++retry_count < 5 ) { ipcom_printf("Accept failed for thread %d: %s.. Retrying."IP_LF, portadd, ipcom_strerror(ipcom_errno)); goto retry; } } } ipcom_printf("Accept failed for thread %d: %s"IP_LF, portadd, ipcom_strerror(ipcom_errno)); return_server = 1; ipcom_socketclose( listen_socket ); ipcom_sem_post( sem_wait_server ); return; } if ( 0 != ipcom_socketioctl( connect_sock, IP_X_SIOCSINTR, &sec ) ) { ipcom_printf("ipcom_socketioctl failed: %s"IP_LF, ipcom_strerror(ipcom_errno)); return_server = 1; ipcom_sem_post( sem_wait_server ); return; } if ( 0 != ipcom_setsockopt( connect_sock, IP_SOL_SOCKET, IP_SO_LINGER, &linger, sizeof (linger)) ) { ipcom_printf("ipcom_setsockopt failed: %s"IP_LF, ipcom_strerror(ipcom_errno)); return_server = 1; ipcom_sem_post( sem_wait_server ); return; } } while ( 1 ) { num_recives++; if ( smp_opt_server.tcp ) bytes = ipcom_recv( connect_sock, buf, smp_opt_server.num_bytes, 0); else { bytes = ipcom_recvfrom( listen_socket, buf, smp_opt_server.num_bytes, 0, &from, &from_length ); if ( num_recives == 1 && 0 == smp_opt_server.tcp ) { sec = SECONDS_CLIENT+2+portadd; if ( 0 != ipcom_socketioctl( listen_socket, IP_X_SIOCSINTR, &sec ) ) { ipcom_printf("ipcom_socketioctl failed: %s"IP_LF, ipcom_strerror(ipcom_errno)); return_server = 1; ipcom_sem_post( sem_wait_server ); return; } } } if ( bytes > 0 ) num_bytes += bytes; if (bytes == 0) { if ( verbose ) { ipcom_printf("Thread %d done."IP_LF, portadd ); ipcom_printf(" Recives: %d"IP_LF, num_recives ); ipcom_printf(" MB/s: %f"IP_LF, ((float)(num_bytes)/(1024.0f*1024.0f) )/5.0f ); } break; } else if (bytes < 0) { if ( ipcom_errno == IP_ERRNO_EINTR ) { if ( smp_opt_server.tcp ) { return_server = 1; ipcom_printf("Error! Out of time!"IP_LF ); break; } else { if ( verbose ) { ipcom_printf("Thread %d done."IP_LF, portadd ); ipcom_printf(" Recives: %d"IP_LF, num_recives ); ipcom_printf(" MB/s: %f"IP_LF, ((float)(num_bytes)/(1024.0f*1024.0f) )/5.0f ); } break; } } else if ( bytes == IP_SOCKERR ) /* Connection reset by peer */ { } return_server = 1; ipcom_printf("recv failed: %s"IP_LF, ipcom_strerror(ipcom_errno)); return; } } if ( verbose ) { if ( spawn_number_server != smp_opt_server.num_sock ) { ipcom_printf("Error. Only %d server-sockets seemed to work."IP_LF, spawn_number_server ); } } if ( smp_opt_server.tcp ) ipcom_shutdown( connect_sock, IP_SHUT_RDWR ); ipcom_free( buf ); ipcom_socketclose( listen_socket ); if ( 0 == ipcom_atomic_sub_and_return( &num_wait_server, 1 ) ) ipcom_sem_post( sem_wait_server ); if ( smp_opt_server.tcp ) ipcom_socketclose( connect_sock ); ipcom_proc_exit(); }
/* *=========================================================================== * ipcom_cmd_ttcp *=========================================================================== */ int ipcom_cmd_ttcp(int argc, char **argv) { /* Uninitialized variables. */ union Ip_sockaddr_union addrme; char *host = IP_NULL; /* ptr to name of host */ int c; Ip_u32 msec0, msec1, msecd, bpermsec, kbpersec; Ip_fd sockfd = -1; char *buf; /* ptr to dynamic buffer */ char *orgbuf = 0; /* the buffer to free. */ struct Ipcom_cmd_ttcp_data context; /* misc initialized variables. */ #ifdef IPCOM_USE_TCP union Ip_sockaddr_union frominet; Ip_socklen_t fromlen; int one = 1; /* for 4.3 BSD style setsockopt() */ Ip_fd oldfd; /* fd of network socket */ #endif Ip_u32 nbytes = 0; /* bytes on net */ int trans = 1; /* 0=receive, !0=transmit mode. Default transmit! */ /* Configuration variables. */ #if defined(IP_SO_X_VR) int vr = 0; #endif int buflen = 8 * 1024; /* length of buffer */ int nbuf = 2 * 1024; /* number of buffers to send in sinkmode */ int bufoffset = 0; /* align buffer to this */ int bufalign = 16; /* modulo this */ int options = 0; /* socket options */ unsigned short port = DEFAULT_PORT; /* TCP port number */ unsigned short meport = 0; /* local port, default 0. */ int sinkmode = 1; /* 0=normal I/O, !0=sink/source mode */ int verbose = 0; /* 0=print basic info, 1=print cpu rate, proc resource usage. */ int sockbufsize = -1; /* Default socket buffer size to use. */ #ifdef IP_TCP_NODELAY int nodelay = 0; /* set TCP_NODELAY socket option. */ #endif int enable = 1; #ifdef TCP_OSERFC2385 char *md5opt = IP_NULL; #endif #ifdef IP_SO_REUSEPORT int reuse_port = 0; #endif #ifdef IPCOM_TTCP_REENTRANT union Ip_sockaddr_union addrhim; #endif int sock_error; int mev = 0; /* Use event logging */ int nend = 5; /* Number of UDP end packets */ #ifdef IPCOM_CMD_TTCP_USE_ZEROCOPY_API int zerocopy = 0; #endif int cpu = -1; #ifdef IPSCTP Ip_bool sctp_type_conflict = IP_FALSE; #endif /* Initialize some static data, default configuration. */ #ifdef IPCOM_USE_TCP int proto = IP_IPPROTO_TCP; int sock_type = IP_SOCK_STREAM; const char *proto_as_str = "TCP"; context.udp = 0; /* Default is TCP. */ #else int proto = IP_IPPROTO_UDP; int sock_type = IP_SOCK_DGRAM; const char *proto_as_str = "UDP"; context.udp = 1; /* Only UDP. */ #endif context.b_flag = 0; context.touchdata = 0; context.numCalls = 0; context.err_no = 0; #ifdef IPCOM_USE_INET context.family = IP_AF_INET; /* default IPv4 */ #else context.family = IP_AF_INET6; /* default IPv6 */ #endif context.addrsize = sizeof(struct Ip_sockaddr_in); (void)ipcom_proc_self(); /* when called from vxworks shell, this prevents a crash */ (void)options; /* Init some more. */ ipcom_memset(&addrhim, 0, sizeof (addrhim)); IPCOM_SA_LEN_SET(&addrhim.sin, sizeof(struct Ip_sockaddr_in)); addrhim.sin.sin_family = IP_AF_INET; ipcom_memset(&addrme, 0, sizeof(addrme)); IPCOM_SA_LEN_SET(&addrme.sin, sizeof(struct Ip_sockaddr_in)); addrme.sin.sin_family = IP_AF_INET; #ifdef IP_PORT_INTEGRITY ipcom_init_libsocket(); #endif if (argc < 2) goto usage; ipcom_getopt_clear(); while ((c = ipcom_getopt(argc, argv, "M:xdrstUuvBDTb:f:l:n:p:A:O:V:RP:me:a:cS")) != -1) { switch (c) { #ifdef TCP_OSERFC2385 case 'M': /* MD5 signature option */ md5opt = ip_optarg; break; #endif #ifdef IPCOM_USE_INET6 case 'x': context.family = IP_AF_INET6; break; #endif case 'm': mev = 1; break; case 'e': nend = ipcom_atoi(ip_optarg); break; case 'B': context.b_flag = 1; break; case 't': trans = 1; break; case 'r': trans = 0; break; #ifdef IP_SO_DEBUG case 'd': options |= IP_SO_DEBUG; break; #endif case 'D': #ifdef IP_TCP_NODELAY nodelay = 1; #else ipcom_fprintf(ip_stderr, "ttcp: -D option ignored: IP_TCP_NODELAY socket option not supported"IP_LF); #endif break; case 'n': nbuf = ipcom_atoi(ip_optarg); break; case 'l': buflen = ipcom_atoi(ip_optarg); break; case 's': #ifdef IPCOM_TTCP_USE_STDIOMODE sinkmode = !sinkmode; #endif break; case 'p': port = (unsigned short)ipcom_atoi(ip_optarg); break; case 'P': meport = (unsigned short)ipcom_atoi(ip_optarg); break; #ifdef IPCOM_CMD_TTCP_USE_ZEROCOPY_API case 'U': zerocopy = 1; /* fall through */ #endif case 'u': proto = IP_IPPROTO_UDP; sock_type = IP_SOCK_DGRAM; proto_as_str = "UDP"; context.udp = 1; break; case 'v': verbose = 1; break; case 'A': bufalign = ipcom_atoi(ip_optarg); break; case 'O': bufoffset = ipcom_atoi(ip_optarg); break; case 'b': #if defined(IP_SO_SNDBUF) || defined(IP_SO_RCVBUF) sockbufsize = ipcom_atoi(ip_optarg); #else ipcom_fprintf(ip_stderr, "ttcp: -b option ignored: IP_SO_SNDBUF/IP_SO_RCVBUF socket options not supported"IP_LF); #endif break; #ifdef IP_SO_REUSEPORT case 'R': reuse_port = 1; break; #endif case 'T': context.touchdata = 1; break; #if defined(IP_SO_X_VR) case 'V': vr = ipcom_atoi(ip_optarg); break; #endif case 'a': cpu = ipcom_atoi(ip_optarg); break; #ifdef IPSCTP case 'c': proto = IP_IPPROTO_SCTP; sock_type = IP_SOCK_STREAM; proto_as_str = "SCTP"; if (IP_TRUE == sctp_type_conflict) { ipcom_fprintf(ip_stderr, "ttcp: c/S conflict in command."IP_LF); goto errorout; } sctp_type_conflict = IP_TRUE; break; case 'S': proto = IP_IPPROTO_SCTP; sock_type = IP_SOCK_SEQPACKET; proto_as_str = "SCTP"; if (IP_TRUE == sctp_type_conflict) { ipcom_fprintf(ip_stderr, "ttcp: c/S conflict in command."IP_LF); goto errorout; } sctp_type_conflict = IP_TRUE; break; #endif default: goto usage; } } #ifndef IP_PORT_LAS if (cpu >= 0) { Ip_cpu_set_t cpuset; if (cpu < 0 || cpu >= IP_CPU_SETSIZE) { ipcom_fprintf(ip_stderr, "ttcp: CPU must be between #0 and #%d"IP_LF, IP_CPU_SETSIZE-1); return -1; } IP_CPU_ZERO(&cpuset); IP_CPU_SET(cpu, &cpuset); if (ipcom_proc_cpu_affinity_set(0, &cpuset) != IPCOM_SUCCESS) { ipcom_fprintf(ip_stderr, "ttcp: Failed to set affinity to CPU #%d"IP_LF, cpu); return -1; } } #endif /* IP_PORT_LAS */ if(trans) { host = argv[ip_optind]; if (host == 0) goto usage; sock_error = ipcom_getsockaddrbyaddrname(context.family, IP_FALSE, host, (struct Ip_sockaddr *)&addrhim); if(sock_error != 0) { ipcom_fprintf(ip_stderr, "ttcp error: ipcom_getsockaddrbyaddrname failed, errno = %d."IP_LF, sock_error); ttcperror(&context, "unknown host"); } addrme.sin.sin_port = ip_htons(meport); addrhim.sin.sin_port = ip_htons(port); /* same port offset for IPv4 and IPv6 */ } else { /* rcvr */ addrme.sin.sin_port = ip_htons(port); } #ifdef IPCOM_USE_INET6 if(context.family == IP_AF_INET6) { context.addrsize = sizeof(struct Ip_sockaddr_in6); IPCOM_SA_LEN_SET(&addrme.sin6, sizeof(struct Ip_sockaddr_in6)); addrme.sin6.sin6_family = IP_AF_INET6; IPCOM_SA_LEN_SET(&addrhim.sin6, sizeof(struct Ip_sockaddr_in6)); addrhim.sin6.sin6_family = IP_AF_INET6; } #endif /* Send more than the sentinel size - UDPMINLEN. */ if(context.udp && buflen <= UDPMINLEN) buflen = UDPMINLEN + 1; /* Align buffer. */ if ((buf = (char *) ipcom_malloc(buflen + bufalign)) == (char *) IP_NULL) ttcperror(&context, "malloc"); else orgbuf = buf; if (bufalign != 0) buf += (bufalign - ((Ip_ptrdiff_t) buf % bufalign) + bufoffset) % bufalign; /* Get a socket. */ if ((sockfd = ipcom_socket(context.family, sock_type, proto)) == ERR) ttcperror(&context,"socket"); if (trans) { if(sockbufsize < 0) { if(context.udp) sockbufsize = DEFAULT_UDP_SNDBUF; else sockbufsize = DEFAULT_TCP_SNDBUF; } ipcom_fprintf(ip_stdout, "ttcp-t: fd=%d, buflen=%d, nbuf=%d, align=%d/%d, port=%d", sockfd, buflen, nbuf, bufalign, bufoffset, (int)port); if (sockbufsize) ipcom_fprintf(ip_stdout, ", sockbufsize=%d", sockbufsize); ipcom_fprintf(ip_stdout, " %s -> %s"IP_LF, proto_as_str, host); } else { if(sockbufsize < 0) { if(context.udp) sockbufsize = DEFAULT_UDP_RCVBUF; else sockbufsize = DEFAULT_TCP_RCVBUF; } ipcom_fprintf(ip_stdout, "ttcp-r: fd=%d, buflen=%d, nbuf=%d, align=%d/%d, port=%d", sockfd, buflen, nbuf, bufalign, bufoffset, (int)port); if (sockbufsize) ipcom_fprintf(ip_stdout, ", sockbufsize=%d", sockbufsize); ipcom_fprintf(ip_stdout, " %s"IP_LF, proto_as_str); } /* Code to open socket is moved to before the printf to get 'sockfd' right. */ mes(trans, "socket"); /* Set REUSE addr */ if(ipcom_setsockopt(sockfd, IP_SOL_SOCKET, IP_SO_REUSEADDR, (char *)&enable, sizeof (int)) == ERR) ttcperror(&context, "setsockopt(IP_SO_REUSEADDR)"); else mes(trans, "setsockopt(IP_SO_REUSEADDR)"); #ifdef IP_SO_REUSEPORT /* Set REUSE port */ if(reuse_port) { if(ipcom_setsockopt(sockfd, IP_SOL_SOCKET, IP_SO_REUSEPORT, (char *)&reuse_port, sizeof (int)) == ERR) ttcperror(&context, "setsockopt(IP_SO_REUSEPORT)"); else mes(trans, "setsockopt(IP_SO_REUSEPORT)"); } #endif #ifdef IPCOM_USE_TCP #ifdef TCP_OSERFC2385 if (!udp && md5opt) { if (ipcom_setsockopt(sockfd, IPPROTO_TCP, TCP_OSERFC2385, md5opt, strlen(md5opt)) == ERR) { ttcperror(&context, "setsockopt(IP_SO_REUSEADDR)"); } else { mes(trans, "setsockopt(IP_SO_REUSEADDR)"); } } #endif #endif /* Set routing table index in socket. */ #if defined(IP_SO_X_VR) if(vr != 0) { if (ipcom_setsockopt(sockfd, IP_SOL_SOCKET, IP_SO_X_VR, (char *)&vr, 4) == ERR) ttcperror(&context, "setsockopt: vr"); else mes(trans, "setsockopt(vr)"); } #endif /* Bind the socket. */ if(ipcom_bind(sockfd, (struct Ip_sockaddr *)&addrme, context.addrsize) == ERR) ttcperror(&context, "bind"); else #ifdef IPCOM_USE_INET6 ipcom_fprintf(ip_stderr, "ttcp%s: bind %s %d"IP_LF, trans ? "-t" : "-r", context.family == IP_AF_INET ? "IPv4" : "IPv6", (int)ip_ntohs(addrme.sin.sin_port)); #else { char tmpbuf[32]; ipcom_sprintf(tmpbuf, "bind %d", ip_ntohs(addrme.sin.sin_port)); mes(trans, tmpbuf); } #endif /* Adjust socker buffer size. */ #if defined(IP_SO_SNDBUF) || defined(IP_SO_RCVBUF) if(sockbufsize) { if (trans) { if (ipcom_setsockopt(sockfd, IP_SOL_SOCKET, IP_SO_SNDBUF, (char *)&sockbufsize, sizeof sockbufsize) == ERR) ttcperror(&context,"setsockopt: sndbuf"); else mes(trans, "setsockopt(sndbuf)"); } else { if (ipcom_setsockopt(sockfd, IP_SOL_SOCKET, IP_SO_RCVBUF, (char *)&sockbufsize, sizeof sockbufsize) == ERR) ttcperror(&context,"setsockopt: rcvbuf"); else mes(trans, "setsockopt(rcvbuf)"); } } #endif /* If TCP we need to connect else accept to remote side. */ #ifdef IPCOM_USE_TCP if (context.udp) { mes(trans, "opened"); } else { /* We are the client if transmitting */ if(trans) { if(options) { if(ipcom_setsockopt(sockfd, IP_SOL_SOCKET, options, (char *)&one, sizeof (one)) == ERR) ttcperror(&context,"setsockopt"); } #ifdef IP_TCP_NODELAY if(nodelay) { if(ipcom_setsockopt(sockfd, IP_IPPROTO_TCP, IP_TCP_NODELAY, (char *)&one, sizeof (one)) == ERR) ttcperror(&context,"setsockopt: nodelay"); mes(trans, "nodelay"); } #endif if(ipcom_connect(sockfd, (struct Ip_sockaddr *)&addrhim, context.addrsize) == ERR) ttcperror(&context,"connect"); else mes(trans, "connect"); } /* Otherwise, we are the TCP server and should listen for the connections. */ else { if(ipcom_listen(sockfd, 0) == ERR) ttcperror(&context,"listen"); else mes(trans, "listen"); if(options) { if(ipcom_setsockopt(sockfd, IP_SOL_SOCKET, options, (char *)&one, sizeof (one)) == ERR) ttcperror(&context,"setsockopt"); } fromlen = context.addrsize; oldfd = sockfd; #ifdef IPSCTP if ((IP_SOCK_SEQPACKET == sock_type) && (IP_IPPROTO_SCTP == proto)) { #define TTCP_SCTP_RCV_BUF_LEN 128 struct Ipsctp_event_subscribe events; union Ip_sockaddr_union local_addr; struct Ipsctp_sndrcvinfo sinfo; Ip_u32 len = 0; char pbuf[TTCP_SCTP_RCV_BUF_LEN]; int flags = 0; int ret = 0; /* set data I/O event flag */ ipcom_memset(&events, 0, sizeof(events)); events.Ipsctp_data_io_event = 1; ret = ipcom_setsockopt(sockfd, IP_IPPROTO_SCTP, IPSCTP_EVENTS, (void *)&events, sizeof(events)); if (ERR == ret) ttcperror(&context, "setsockopt events"); /* get the association identifier */ ipcom_memset(pbuf, 0, TTCP_SCTP_RCV_BUF_LEN); len = sizeof(local_addr); /* Wait for connections */ ret = ipsctp_recvmsg(sockfd, pbuf, TTCP_SCTP_RCV_BUF_LEN, &local_addr.sa, &len, &sinfo, &flags); sockfd = ipsctp_peeloff(sockfd, sinfo.sinfo_assoc_id); if (IP_SOCKERR == sockfd) ttcperror(&context,"peeloff"); } else #endif { if((sockfd = ipcom_accept(sockfd, (struct Ip_sockaddr *)&frominet, &fromlen)) == ERR) ttcperror(&context,"accept"); } { union Ip_sockaddr_union peer; Ip_socklen_t peerlen = context.addrsize; /* Close the mother socket. */ if(ipcom_socketclose(oldfd) == ERR) ttcperror(&context,"close of oldfd."); #if defined(IP_SO_RCVBUF) /* Had to add this code in addition to the above because some stacks don't inherit * the receive buffer size from the server socket. /Lennart Bang Enea Ose Systems 980116. */ if(sockbufsize) { if(ipcom_setsockopt(sockfd, IP_SOL_SOCKET, IP_SO_RCVBUF, (char *)&sockbufsize, sizeof sockbufsize) == ERR) ttcperror(&context,"setsockopt: rcvbuf"); else mes(trans, "setsockopt(rcvbuf)"); } #endif if(ipcom_getpeername(sockfd, (struct Ip_sockaddr *) &peer, &peerlen) == ERR) ttcperror(&context, "getpeername"); #ifdef IPCOM_USE_INET if(context.family == IP_AF_INET) { char addr[16]; ipcom_fprintf(ip_stderr, "ttcp-r: accept from %s"IP_LF, ipcom_inet_ntop(IP_AF_INET, &peer.sin.sin_addr, addr, sizeof(addr))); } #endif #ifdef IPCOM_USE_INET6 if(context.family == IP_AF_INET6) { char addr[40]; ipcom_fprintf(ip_stderr, "ttcp-r: accept from %s"IP_LF, ipcom_inet_ntop(IP_AF_INET6, &peer.sin6.sin6_addr, addr, sizeof(addr))); } #endif } } } #endif /* Begin the TTCP performance test. */ msec0 = get_millisec(); if (mev) { #if defined (IP_PORT_INTEGRITY) #include "ipcom_integrity.h" extern void EventLogOn(void); #if IP_VER < 500 extern void EventLogMask(unsigned int newmask); EventLogMask(~0); #endif EventLogOn(); #endif } if(sinkmode) { register int cnt; /* Transmit side. */ if(trans) { pattern(buf, buflen); if(context.udp) { (void) NWRITE(sockfd, buf, UDPMINLEN, &context); /* rcvr start */ ipcom_millisleep(500); /* arp time */ /* Renew the start time to not include the 500 msec sleep */ msec0 = get_millisec(); } #ifdef IPCOM_CMD_TTCP_USE_ZEROCOPY_API if (zerocopy) { while (nbuf-- && ZERONWRITE(sockfd, buflen, &context) == buflen) nbytes += buflen; } else #endif { while (nbuf-- && NWRITE(sockfd, buf, buflen, &context) == buflen) nbytes += buflen; } if(context.udp) (void) NWRITE(sockfd, buf, UDPMINLEN, &context); /* rcvr end */ } /* Receive side. */ else { if(context.udp) { int going = 0; #ifdef IPCOM_CMD_TTCP_USE_ZEROCOPY_API if (zerocopy) { while ((cnt = ZeroNread(sockfd, &context)) > 0) { if(cnt <= UDPMINLEN) { if(going) break; /* "EOF" */ going = 1; msec0 = get_millisec(); } else { nbytes += cnt; } } } else #endif { while ((cnt = Nread(sockfd, buf, buflen, &context)) > 0) { if(cnt <= UDPMINLEN) { if(going) break; /* "EOF" */ going = 1; msec0 = get_millisec(); } else { nbytes += cnt; } } } } #ifdef IPCOM_USE_TCP else { while ((cnt = Nread(sockfd, buf, buflen, &context)) > 0) { nbytes += cnt; } } #endif } } #ifdef IPCOM_TTCP_USE_STDIOMODE /* non sinkmode. */ else { register int cnt; if(trans) { /* Read from standard input and send to other side. */ while ((cnt = ipcom_fread(buf, buflen, 1, ip_stdin)) > 0 && NWRITE(sockfd, buf, cnt) == cnt) nbytes += cnt; } else { /* Read from network and print on stdout. */ while ((cnt = Nread(sockfd, buf, buflen, &context)) > 0) { ipcom_fwrite(buf, cnt, 1, ip_stdout); nbytes += cnt; } } } #endif if (mev) { #if defined (IP_PORT_INTEGRITY) extern void EventLogOff(void); EventLogOff(); #elif defined (IP_PORT_RTCORE) extern void ip_trace(char *what, char *file, int line, int id, void *data); extern void ip_tracedump(void); ip_trace("[ASSERT]", __FILE__, __LINE__, ipcom_getpid(), IP_NULL); ip_tracedump(); #endif } /* Read the final time and calculate some statistics. */ msec1 = get_millisec(); msecd = msec1 - msec0; if (msecd == 0) msecd = 1; bpermsec = nbytes / msecd; /* Bytes per millisecond. */ kbpersec = nbytes / 128; kbpersec = kbpersec * 125 / msecd; /* kilobyte per sec. */ /* End of test assemble statistice. */ if(context.err_no) { ipcom_fprintf(ip_stdout, "ttcp%s: socket errno: %d."IP_LF, trans ? "-t" : "-r", context.err_no); } if(context.udp && trans) { int j; for (j = 0; j < nend; j++) { ipcom_millisleep(100); /* Let the reading side catch up. */ (void) NWRITE(sockfd, buf, UDPMINLEN, &context); /* rcvr end */ } } /* Print the statistics. */ ipcom_fprintf(ip_stdout, "ttcp%s: %lu bytes in %lu milliseconds = %lu KB/sec, %lu B/msec +++"IP_LF, trans ? "-t" : "-r", nbytes, msecd, kbpersec, bpermsec); ipcom_fprintf(ip_stdout, "ttcp%s: %lu I/O calls, msec/call = %lu, calls/sec = %lu"IP_LF, trans ? "-t" : "-r", context.numCalls, msecd / context.numCalls, 1000 * context.numCalls / msecd); if (verbose) ipcom_fprintf(ip_stdout, "ttcp%s: buffer address %p"IP_LF, trans ? "-t" : "-r", buf); /* Test succeeded, goto errorout to cleanup. */ goto errorout; /* Usage. */ usage: ipcom_fprintf(ip_stderr, "Usage: ttcp -t [-options] host [ < in ]"IP_LF "ttcp -r [-options > out]"IP_LF "Common options:"IP_LF "-x use IPv6 instead of IPv4"IP_LF "-l ## length of bufs read from or written to network (default 8192)"IP_LF #ifdef IPCOM_CMD_TTCP_USE_ZEROCOPY_API "-U use UDP and interpeak zero copy API instead of TCP"IP_LF #endif "-u use UDP (default is TCP)"IP_LF #ifdef IPSCTP "-c use SCTP STREAM type(default is TCP)"IP_LF "-S use SCTP SEQPACKET type(default is TCP)"IP_LF #endif "-p ## port number to send to or listen at (default DEFAULT_PORT)"IP_LF); ipcom_fprintf(ip_stderr, "-s -t: source a pattern to network"IP_LF "-r sink (discard) all data from network"IP_LF "-e ## number of packets to end UDP transmission"IP_LF "-m use event logging (not supported on all platforms)"IP_LF "-A align the start of buffers to this modulus (default 16384)"IP_LF "-O start buffers at this offset from the modulus (default 0)"IP_LF "-v verbose: print more statistics"IP_LF "-d set SO_DEBUG socket option (if supported)"IP_LF); ipcom_fprintf(ip_stderr, "-b ## set socket buffer size (if supported)"IP_LF "Options specific to -t:"IP_LF "-n## number of source bufs written to network (default 2048)"IP_LF "-D don't buffer TCP writes (sets TCP_NODELAY socket option)"IP_LF "Options specific to -r:"IP_LF "-B for -s, only output full blocks as specified by -l (for TAR)"IP_LF "-T \"touch\": access each byte as it's read"IP_LF #if defined(IP_SO_X_VR) "-V virtual router index (if supported)"IP_LF); #endif /* fall through to cleanup...*/ /* Free buffer and close socket if any error. */ errorout: #ifndef IP_PORT_LAS if (cpu >= 0) ipcom_proc_cpu_affinity_clr(0); #endif /* IP_PORT_LAS */ if(orgbuf) ipcom_free(orgbuf); if(sockfd != -1) { if(ipcom_socketclose(sockfd) == ERR) ipcom_fprintf(ip_stderr, "ttcp error: close of sockfd. (line %d, errno %d)."IP_LF, __LINE__, ipcom_errno); } #ifdef IP_PORT_INTEGRITY ipcom_shutdown_libsocket(); #endif return 0; }
/* *=========================================================================== * ipcom_cmd_sockperf_accept *=========================================================================== * Description: Passive open of socket(s). * Parameters: * Returns: */ IP_STATIC void ipcom_cmd_sockperf_accept(Ipcom_cmd_sockperf_t *cmd) { Ip_fd *s = cmd->sock_array; int listen_sock; Ip_u32 accepted_sockets = 0; struct Ip_timeval start; struct Ip_timeval stop; int on = 1; listen_sock = ipcom_socket(cmd->res->ai_family, cmd->res->ai_socktype, cmd->res->ai_protocol); if (listen_sock == IP_SOCKERR) { ipcom_printf("sockperf-a: Failed to create socket: %s"IP_LF, ipcom_strerror(ipcom_errno)); goto cleanup; } if (ipcom_setsockopt(listen_sock, IP_SOL_SOCKET, IP_SO_REUSEADDR, &on, sizeof(on)) < 0) { ipcom_printf("sockperf-a: setsockopt IP_SO_REUSEADDR failed : %s"IP_LF, ipcom_strerror(ipcom_errno)); return; } if (ipcom_bind(listen_sock, cmd->res->ai_addr, cmd->res->ai_addrlen) < 0) { ipcom_printf("sockperf-a: Failed to bind: %s"IP_LF, ipcom_strerror(ipcom_errno)); goto cleanup; } if (ipcom_listen(listen_sock, cmd->num_sock) < 0) { ipcom_printf("sockperf-a: Failed to listen: %s"IP_LF, ipcom_strerror(ipcom_errno)); goto cleanup; } ipcom_printf("sockperf-a: listen on %s[%d]"IP_LF, cmd->res->ai_canonname, ip_ntohs(((struct Ip_sockaddr_in *)cmd->res->ai_addr)->sin_port)); IP_FD_ZERO(&cmd->read_set); IP_FD_SET(listen_sock, &cmd->read_set); if (ipcom_socketselect(listen_sock + 1, &cmd->read_set, IP_NULL, IP_NULL, IP_NULL) != 1) { ipcom_printf("sockperf-a: Select failed for listen socket: %s"IP_LF, ipcom_strerror(ipcom_errno)); goto cleanup; } ipcom_microtime(&start); for (;accepted_sockets < cmd->num_sock; accepted_sockets++) { s[accepted_sockets] = ipcom_accept(listen_sock, IP_NULL, IP_NULL); if (s[accepted_sockets] == IP_SOCKERR) { ipcom_printf("sockperf-a: Failed to create socket: %s"IP_LF, ipcom_strerror(ipcom_errno)); goto cleanup; } if (ipcom_setsockopt(s[accepted_sockets], IP_SOL_SOCKET, IP_SO_LINGER, &cmd->linger, sizeof(cmd->linger)) < 0) { ipcom_printf("sockperf-a: setsockopt SO_LINGER failed : %s"IP_LF, ipcom_strerror(ipcom_errno)); goto cleanup; } } ipcom_microtime(&stop); ipcom_printf("sockperf-a: %ld sockets accepted in %ld ms"IP_LF, accepted_sockets, ipcom_cmd_sockperf_tv_to_msec(&start, &stop)); ipcom_cmd_sockperf_run(cmd); cleanup: if (listen_sock >= 0) (void)ipcom_socketclose(listen_sock); while (accepted_sockets-- > 0) (void)ipcom_socketclose(s[accepted_sockets]); }
/* *=========================================================================== * ipsecctrl_flows *=========================================================================== */ static int ipsecctrl_flows(Argvars *vars) { Ipipsec_ctrl_selector sel; char srcport[32], dstport[32]; int num = 0; char str[IP_INET6_ADDRSTRLEN]; char str2[IP_INET6_ADDRSTRLEN+1]; ipcom_printf("Flows:"IP_LF); sel.Index = 0; /* get first selector. */ /* Get and print the Selectors in MIB format. */ for (;;) { /* Get first/next Selector */ if (ipcom_socketioctl(vars->fd, IP_SIOCXIPSEC_SELECTOR, &sel) < 0) { ipcom_printf("ipsecctrl: ipcom_socketioctl(SELECTOR) failed (%s)"IP_LF, ipcom_strerror(ipcom_errno)); return -1; } if (sel.Index == 0) break; /* Print selector aka flow: */ num++; ipcom_printf("[%ld] :: %s ", sel.Index, FLOW_TYPE(sel.flowtype)); if (sel.flowpri != 0) ipcom_printf("pri=%d ", (signed char)sel.flowpri); /* source */ if (sel.LocalPort != sel.LocalMaxPort) ipcom_sprintf(srcport, "%d-%d", (int)ip_ntohs(sel.LocalPort), (int)ip_ntohs(sel.LocalMaxPort)); else if (sel.LocalPort == 0) ipcom_strcpy(srcport, "any"); else ipcom_sprintf(srcport, "%d", (int)ip_ntohs(sel.LocalPort)); if (ipcom_memcmp(&sel.LocalId, &sel.LocalMaxId, sizeof(union Ip_in_addr_union))) ipcom_sprintf(str2, "-%s", ipcom_inet_ntop(sel.domain, &sel.LocalMaxId, str, sizeof(str))); else *str2 = '\0'; ipcom_printf("src=%s%s/%d:%s ", ipcom_inet_ntop(sel.domain, &sel.LocalId, str, sizeof(str)), str2, ipipsec_addrmasklen(sel.domain, (Ip_u8 *)&sel.local_mask), srcport); /* destination */ if (sel.RemotePort != sel.RemoteMaxPort) ipcom_sprintf(dstport, "%d-%d", (int)ip_ntohs(sel.RemotePort), (int)ip_ntohs(sel.RemoteMaxPort)); else if (sel.RemotePort == 0) ipcom_strcpy(dstport, "any"); else ipcom_sprintf(dstport, "%d", (int)ip_ntohs(sel.RemotePort)); if (ipcom_memcmp(&sel.RemoteId, &sel.RemoteMaxId, sizeof(union Ip_in_addr_union))) ipcom_sprintf(str2, "-%s", ipcom_inet_ntop(sel.domain, &sel.RemoteMaxId, str, sizeof(str))); else *str2 = '\0'; ipcom_printf("dst=%s%s/%d:%s ", ipcom_inet_ntop(sel.domain, &sel.RemoteId, str, sizeof(str)), str2, ipipsec_addrmasklen(sel.domain, (Ip_u8 *)&sel.remote_mask), dstport); ipcom_printf("%s", ipcom_ipproto_name(sel.Protocol)); switch (sel.Protocol) { case IP_IPPROTO_ICMP: case IP_IPPROTO_ICMPV6: if (sel.ports[0] || sel.ports[1]) ipcom_printf(" type=%d code=%d", sel.ports[0], sel.ports[1]); break; case IP_IPPROTO_MH: if (sel.ports[0]) ipcom_printf(" type=%d", sel.ports[0]); break; default: break; } /* Print SA */ if (sel.sa.domain) { if (sel.sa.domain == IPIPSEC_AF_BYPASS) ipcom_printf(" %s SA: %s", sel.direction == IPIPSEC_SADIR_INPUT ? "<-" : sel.direction == IPIPSEC_SADIR_OUTPUT ? "->" : "--", IPSECSATYPENAME(sel.sa.satype)); else ipcom_printf(" %s SA: %s spi=0x%lx src=%s dst=%s", sel.direction == IPIPSEC_SADIR_INPUT ? "<-" : sel.direction == IPIPSEC_SADIR_OUTPUT ? "->" : "--", IPSECSATYPENAME(sel.sa.satype), ip_ntohl(sel.sa.spi_n), ipcom_inet_ntop(sel.sa.domain, &sel.sa.src, str, sizeof(str)), ipcom_inet_ntop(sel.sa.domain, &sel.sa.dst, str2, sizeof(str2))); } else ipcom_printf(" %s SA: none", sel.direction == IPIPSEC_SADIR_INPUT ? "<-" : sel.direction == IPIPSEC_SADIR_OUTPUT ? "->" : "--"); ipcom_printf(IP_LF); } ipcom_printf("Total of %d flows."IP_LF, num); return 0; }
/* *=========================================================================== * ipnet_udp_input *=========================================================================== * Description: Input handler for packet to UDP sockets. This function will * NOT free the packet if the operation fails. * Parameters: pkt - The received packet, must be freed by the called if * this function fails. * is_multicast - Set to IP_TRUE if the packet was sent to a * multicast address. * proto - The protocol number. * src_addr - The address (Ipv4 or IPv6) of the sender. * dst_addr - The address (Ipv4 or IPv6) of the receiver (this system). * socklookup - A pointer to a function that can return the socket * that is associated with this packet. * nat_t - NAT traversal; if used. * Returns: 0 >= number of matching sockets, <0 = error code * */ IP_GLOBAL int ipnet_udp_input(Ipcom_pkt *pkt, Ip_bool is_multicast, IP_CONST void* src_addr, IP_CONST void* dst_addr, Ipnet_sock_lookup_f socklookup, int *nat_t) { Ipnet_pkt_udp *udp_hdr; int retval; int ulen_h; Ipnet_socket *sock; Ip_u16 src_port; Ip_u16 dst_port; Ip_bool pkt_no_rx_cache; IPCOM_WV_MARKER_1 (IPCOM_WV_NETD_IP4_DATAPATH_EVENT, IPCOM_WV_NETD_VERBOSE, 1, 3, IPCOM_WV_NETDEVENT_START, ipnet_udp_input, IPCOM_WV_IPNET_UDP_MODULE, IPCOM_WV_NETD_UDP4); IPNET_STATS(udp_input++); IPCOM_PKT_TRACE(pkt, IPCOM_PKT_ID_UDP_INPUT); if (IP_UNLIKELY(pkt->end - pkt->start < IPNET_UDP_HDR_SIZE)) { IPCOM_WV_EVENT_2 (IPCOM_WV_NETD_IP4_DATAPATH_EVENT, IPCOM_WV_NETD_WARNING, 1, 4, IPCOM_WV_NETDEVENT_WARNING, IPCOM_WV_NETD_RECV, ipnet_udp_input, IPCOM_WV_NETD_BADHLEN, IPCOM_WV_IPNET_UDP_MODULE, IPCOM_WV_NETD_UDP4); IPNET_STATS(udp_input_hdr_trunc++); IPCOM_MIB2(udpInErrors++); return -IP_ERRNO_EINVAL; } udp_hdr = (Ipnet_pkt_udp*) &pkt->data[pkt->start]; ulen_h = ip_ntohs(udp_hdr->ulen); src_port = ip_ntohs(udp_hdr->sport); dst_port = ip_ntohs(udp_hdr->dport); if (IP_UNLIKELY(pkt->end - pkt->start < ulen_h)) { IPCOM_WV_EVENT_2 (IPCOM_WV_NETD_IP4_DATAPATH_EVENT, IPCOM_WV_NETD_WARNING, 1, 5, IPCOM_WV_NETDEVENT_WARNING, IPCOM_WV_NETD_RECV, ipnet_udp_input, IPCOM_WV_NETD_BADLEN, IPCOM_WV_IPNET_UDP_MODULE, IPCOM_WV_NETD_UDP4); IPNET_STATS(udp_input_hdr_trunc++); IPCOM_MIB2(udpInErrors++); return -IP_ERRNO_EINVAL; } pkt->end = pkt->start + ulen_h; if (udp_hdr->sum != 0 && IP_BIT_ISFALSE(pkt->flags, IPCOM_PKT_FLAG_LOOPED_BACK)) { Ip_u16 chksum; /* Only check packets that was not created locally */ #ifdef IPCOM_USE_HW_CHECKSUM_RX if (IP_BIT_ISSET(pkt->flags, IPCOM_PKT_FLAG_HW_CHECKSUM)) chksum = 0; else if (IP_BIT_ISSET(pkt->flags, IPCOM_PKT_FLAG_TL_CHECKSUM)) chksum = ipcom_in_checksum_finish(pkt->chk); else #endif /* IPCOM_USE_HW_CHECKSUM_RX */ { pkt->chk += ipcom_in_checksum_update(&pkt->data[pkt->start], (Ip_size_t) ulen_h); chksum = ipcom_in_checksum_finish(pkt->chk); } if (IP_UNLIKELY(chksum != 0)) { /* Wrong checksum */ IPCOM_WV_EVENT_2 (IPCOM_WV_NETD_IP4_DATAPATH_EVENT, IPCOM_WV_NETD_WARNING, 1, 6, IPCOM_WV_NETDEVENT_WARNING, IPCOM_WV_NETD_RECV, ipnet_udp_input, IPCOM_WV_NETD_BADSUM, IPCOM_WV_IPNET_UDP_MODULE, IPCOM_WV_NETD_UDP4); IPNET_STATS(udp_input_badchksum++); IPCOM_MIB2(udpInErrors++); return -IP_ERRNO_EINVAL; } } /* Move the start to beginning of application data */ pkt->start += IPNET_UDP_HDR_SIZE; if (is_multicast) { IPCOM_WV_EVENT_2 (IPCOM_WV_NETD_IP4_DATAPATH_EVENT, IPCOM_WV_NETD_INFO, 1, 7, IPCOM_WV_NETDEVENT_INFO, IPCOM_WV_NETD_RECV, ipnet_udp_input, IPCOM_WV_NETD_INFO_RECEIVE, IPCOM_WV_IPNET_UDP_MODULE, IPCOM_WV_NETD_UDP4); IPNET_STATS(udp_input_multicast++); retval = ipnet_raw_input(pkt, IP_FALSE, IP_IPPROTO_UDP, src_addr, src_port, dst_addr, dst_port, socklookup); if (retval >= 0) { /* The packet must be freed unlesss an error occured */ ipcom_pkt_free(pkt); IPCOM_MIB2(udpInDatagrams++); IPCOM_MIB2_U64_INC(udpHCInDatagrams); } else { IPCOM_MIB2(udpInErrors++); } return retval; } sock = socklookup(pkt->vr_index, IP_IPPROTO_UDP, dst_addr, dst_port, src_addr, src_port); if (sock == IP_NULL) /* No matching socket, try the wildcard group */ sock = socklookup(IPCOM_VR_ANY, IP_IPPROTO_UDP, dst_addr, dst_port, src_addr, src_port); if (sock != IP_NULL) { Ipcom_socket_eventcb event_cb = sock->ipcom.event_cb; /* Verify NAT traversal */ if (IP_UNLIKELY(ipnet_udp_encapsulation(sock, pkt, nat_t))) { ipcom_pkt_set_info(pkt, IPNET_PKT_INFO_ENCAP_UDP, sizeof(*udp_hdr), udp_hdr); pkt->start -= IPNET_UDP_HDR_SIZE; return 0; } IPCOM_WV_EVENT_2 (IPCOM_WV_NETD_IP4_DATAPATH_EVENT, IPCOM_WV_NETD_INFO, 1, 8, IPCOM_WV_NETDEVENT_INFO, IPCOM_WV_NETD_RECV, ipnet_udp_input, IPCOM_WV_NETD_INFO_RECEIVE, IPCOM_WV_IPNET_UDP_MODULE, IPCOM_WV_NETD_UDP4); IPNET_STATS(udp_input_sock_match++); pkt->fd = sock->ipcom.fd; pkt_no_rx_cache = IP_BIT_ISSET(pkt->flags, IPCOM_PKT_FLAG_NO_RX_CACHE); retval = ipnet_queue_received_packet(pkt, sock); if (retval < 0) { IPCOM_WV_EVENT_2 (IPCOM_WV_NETD_IP4_DATAPATH_EVENT, IPCOM_WV_NETD_WARNING, 1, 9, IPCOM_WV_NETDEVENT_WARNING, IPCOM_WV_NETD_RECV, ipnet_udp_input, IPCOM_WV_NETD_INFO_QUEUE_FULL, IPCOM_WV_IPNET_UDP_MODULE, IPCOM_WV_NETD_UDP4); IPNET_STATS(udp_input_queue_pkt_err++); IPCOM_MIB2(udpInErrors++); return retval; } IPCOM_WV_EVENT_2 (IPCOM_WV_NETD_IP4_DATAPATH_EVENT, IPCOM_WV_NETD_INFO, 1, 10, IPCOM_WV_NETDEVENT_INFO, IPCOM_WV_NETD_RECV, ipnet_udp_input, IPCOM_WV_NETD_INFO_RECEIVE, IPCOM_WV_IPNET_UDP_MODULE, IPCOM_WV_NETD_UDP4); IPNET_STATS(udp_input_queue_pkt_ok++); if (event_cb != IP_NULL) event_cb(&sock->ipcom, pkt, IP_SOEVENT_CB_INPKT); IPCOM_MIB2(udpInDatagrams++); IPCOM_MIB2_U64_INC(udpHCInDatagrams); if (IP_BIT_ISFALSE(sock->flags, IPNET_SOCKET_FLAG_RX_CACHED) && !pkt_no_rx_cache) ipnet_sock_add_to_rx_cache(sock, src_addr, src_port, dst_addr, dst_port, ipnet_udp_fast_deliver_data); return 1; } else { IPCOM_WV_EVENT_2 (IPCOM_WV_NETD_IP4_DATAPATH_EVENT, IPCOM_WV_NETD_WARNING, 1, 13, IPCOM_WV_NETDEVENT_WARNING, IPCOM_WV_NETD_RECV, ipnet_udp_input, IPCOM_WV_NETD_NOPORT, IPCOM_WV_IPNET_UDP_MODULE, IPCOM_WV_NETD_UDP4); IPNET_STATS(udp_input_sock_nomatch++); IPCOM_MIB2(udpNoPorts++); } IPCOM_WV_EVENT_2 (IPCOM_WV_NETD_IP4_DATAPATH_EVENT, IPCOM_WV_NETD_WARNING, 1, 14, IPCOM_WV_NETDEVENT_WARNING, IPCOM_WV_NETD_RECV, ipnet_udp_input, IPCOM_WV_NETD_NOPORT, IPCOM_WV_IPNET_UDP_MODULE, IPCOM_WV_NETD_UDP4); IPNET_STATS(udp_input_econnrefused++); return -IP_ERRNO_ECONNREFUSED; }
/* *=========================================================================== * 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; } }