/* *=========================================================================== * ipnet_sysctl_route_add_addr *=========================================================================== * Description: Adds an address in route table format. * Parameters: buf - the buffer to where the address should be written. * domain - the domain this address is part of. * rt_addr - a address or mask from the route table. * Returns: The address to where the next data should be written in * the buffer. * */ IP_STATIC void * ipnet_sysctl_route_add_addr(void *buf, int domain, void *rt_addr) { union Ip_sockaddr_union *addr; addr = (union Ip_sockaddr_union *) buf; #ifdef IPCOM_USE_INET if (domain == IP_AF_INET) { struct Ipnet_ipv4_key *key = (struct Ipnet_ipv4_key *) rt_addr; ipcom_memset(addr, 0, sizeof(struct Ip_sockaddr_in)); addr->sin.sin_family = IP_AF_INET; IPCOM_SA_LEN_SET(&addr->sin, sizeof(struct Ip_sockaddr_in)); ipcom_memcpy(&addr->sin.sin_addr, &key->addr, sizeof(addr->sin.sin_addr)); } #endif /* IPCOM_USE_INET */ #ifdef IPCOM_USE_INET6 if (domain == IP_AF_INET6) { struct Ipnet_ipv6_key *key = (struct Ipnet_ipv6_key *) rt_addr; ipcom_memset(addr, 0, sizeof(struct Ip_sockaddr_in6)); addr->sin6.sin6_family = IP_AF_INET6; IPCOM_SA_LEN_SET(&addr->sin6, sizeof(struct Ip_sockaddr_in6)); ipcom_memcpy(&addr->sin6.sin6_scope_id, &key->scope_id, sizeof(addr->sin6.sin6_scope_id)); ipcom_memcpy(&addr->sin6.sin6_addr, &key->addr, sizeof(addr->sin6.sin6_addr)); } #endif /* IPCOM_USE_INET6 */ return (Ip_u8 *) buf + IPCOM_SA_LEN_GET(&addr->sa); }
IP_GLOBAL int ipnet_loopback_if_setup(Ipnet_netif *netif) { int ret = 0; #ifdef IPCOM_USE_INET6 struct Ip_in6_addr lo_addr = IP_IN6ADDR_LOOPBACK_INIT; struct Ipnet_route_add_param param; struct Ipnet_ipv6_key key; struct Ipnet_ipv6_key mask; /* Add ::1 loopback address to interface */ (void)ipnet_ip6_add_addr(netif, &lo_addr, IP_TRUE, 0xffffffff, 0xffffffff, 128); /* All packets matching ff02::/16 with no scope specified must be rejected */ ipcom_memset(&key, 0, sizeof(key)); ipcom_memset(&mask, 0, sizeof(mask)); ipcom_memset(¶m, 0, sizeof(param)); key.addr.in6.addr16[0] = ip_htons(0xff02); ipnet_route_create_mask(&mask.addr, 16); param.domain = IP_AF_INET6; param.key = &key; param.netmask = &mask; param.flags = IPNET_RTF_X_HIDDEN | IPNET_RTF_REJECT | IPNET_RTF_DONE; param.netif = netif; param.vr = netif->vr_index; param.table = IPCOM_ROUTE_TABLE_DEFAULT; ret = ipnet_route_add(¶m); if (ret < 0) IPCOM_LOG2(ERR, "Failed to setup routes on %s in vr %d", netif->ipcom.name, netif->vr_index); #endif /* IPCOM_USE_INET6 */ #ifdef IPCOM_USE_INET /* Add 127.0.0.1 loopback address to interface */ (void)ipnet_ip4_add_addr(netif, ip_htonl(IP_INADDR_LOOPBACK), ip_htonl(0xff000000), IP_TRUE, IPNET_ADDR_TYPE_UNICAST); #endif /* IPCOM_USE_INET */ return ret; }
/* *=========================================================================== * ipcom_buffer_new *=========================================================================== * Description: * Parameters: * Returns: * */ Ipcom_buffer* ipcom_buffer_new(Ip_s32 size) { Ipcom_buffer *buffer; buffer = ipcom_malloc(sizeof(Ipcom_buffer)); if(!buffer) { IPCOM_LOG0(ERR, "ipcom_buffer_new() :: out of memory"); return IP_NULL; } buffer->buf = ipcom_malloc(size); if(buffer->buf == IP_NULL) { IPCOM_LOG0(ERR, "ipcom_buffer_new() :: out of memory"); ipcom_free(buffer); return IP_NULL; } buffer->alloc = size; buffer->offset = 0; buffer->end = 0; #ifdef IP_DEBUG ipcom_memset(buffer->buf, 0xcc, size); #endif return buffer; }
/* *=========================================================================== * ipnet_nat_proxy_dns_add_transaction *=========================================================================== * Description: Add a DNS transaction to the list of active transactions. * Parameters: type - DNS query type * dns_hdr - pointer to the DNS protocol header. * param - pointer to NAT proxy parameters. * Returns: pointer to the transaction or IP_NULL if failed to add. */ IP_STATIC Ipnet_nat_dns_transaction * ipnet_nat_proxy_dns_add_transaction(int type, Ipnet_nat_dns_hdr *dns_hdr, Ipnet_nat_proxy_param *param, Ip_u8 *ptrname) { Ipnet_nat_dns_transaction *trans; /* Check that there is room for another transaction */ if(ipnet_nat_proxy_dns_list.size >= IPNET_NAT_DNS_TRANS_MAX_ENTRIES) return IP_NULL; trans = ipcom_malloc(sizeof(*trans)); if (trans == IP_NULL) return IP_NULL; ipcom_memset(trans, 0, sizeof(*trans)); trans->id = (Ip_u16)IP_GET_NTOHS(&dns_hdr->id); trans->srcport = param->tuple.private_port; trans->dstaddr = param->tuple.public_addr; trans->type = type; if (ptrname != IP_NULL) ipcom_strncpy((char *)trans->ptrname, (char *)ptrname, sizeof(trans->ptrname)-1); ipcom_list_insert_last(&ipnet_nat_proxy_dns_list, &trans->list); /* Add the timeout */ if (ipnet_nat_proxy_timeout_schedule(IPNET_NAT_DNS_TRANS_TIMEOUT, ipnet_nat_proxy_dns_transaction_timeout, trans, &trans->tmo) < 0) { ipcom_list_remove(&trans->list); ipcom_free(trans); return IP_NULL; } return trans; }
/* *=========================================================================== * ipnet_wlan_if_init *=========================================================================== * Description: WLAN uses the Ethernet interface with a few modifications * Parameters: * Returns: * */ IP_PUBLIC int ipnet_wlan_if_init(Ipnet_netif *netif) { int i; ipnet_eth_if_init(netif); netif->wlan = ipcom_malloc(sizeof(Ipnet_netif_wlan)); if (netif->wlan == IP_NULL) return -IP_ERRNO_ENOMEM; ipcom_memset(netif->wlan, 0, sizeof(Ipnet_netif_wlan)); i = 0; do { ipcom_sprintf(netif->ipcom.name, "wlan%d", i++); } while (ipnet_if_nametonetif(netif->vr_index, netif->ipcom.name) != IP_NULL); /* Setup link functions for WLAN use. */ netif->wlan->eth_link_ioctl = (int (*)(Ipnet_netif *, Ip_u32, void *))netif->link_ioctl; netif->link_ioctl = (Ipnet_link_ioctl)ipnet_wlan_ioctl; return 0; }
/* *=========================================================================== * ipcom_drv_ppp_if_init *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC int ipcom_drv_ppp_if_init(const char *ifname, const char *devname, int unit) { Ipcom_netif *netif; Ipcom_pdrv_ppp *pdrv; Ipcom_drv_ppp_link *plink; /* Allocate memory for the network interface structure */ netif = ipcom_if_malloc(IP_IFT_PPP); if (netif == IP_NULL) return IPCOM_ERR_FAILED; /* Set up the driver downcall function pointers */ netif->drv_ioctl = ipcom_drv_ppp_ioctl; netif->drv_output = ipcom_drv_ppp_output; /* Set interface name */ ipcom_strncpy(netif->name, ifname, sizeof(netif->name) - 1); /* Allocate and init memory for the driver structure */ pdrv = ipcom_malloc(sizeof(*pdrv)); if (pdrv == IP_NULL) goto fail; ipcom_memset(pdrv, 0, sizeof(*pdrv)); netif->pdrv = pdrv; plink = &pdrv->plink[unit]; if (devname == IP_NULL) { char value[64]; Ip_size_t value_size = sizeof(value); devname = ipcom_sysvar_get_conf("devname", value, &value_size, IP_NULL, ifname); } if (devname != IP_NULL) plink->devname = ipcom_strdup(devname); plink->sv[0] = plink->sv[1] = -1; /* Initialize PPP link */ plink->index = unit; plink->netif = netif; plink->out_q_nr = 0; plink->fd = -1; plink->baudrate = ipcom_sysvar_get_conf_as_int("ipppp.baudrate", IP_NULL, netif->name); if (plink->baudrate <= 0) plink->baudrate = IPCOM_DRV_PPP_BAUDRATE; /* Attach the interface. */ if (ipcom_if_attach(netif) < 0) goto fail; /* Success. */ return IPCOM_SUCCESS; fail: if (pdrv != IP_NULL) ipcom_free(pdrv); ipcom_if_free(netif); return IPCOM_ERR_FAILED; }
/* *=========================================================================== * ipcom_sysvar_init *=========================================================================== * Description: * Parameters: * Returns: */ IP_STATIC Ip_err ipcom_sysvar_init(void *ununsed) { IPCOM_UNUSED_ARG(ununsed); ipcom_memset(&ipcom_sysvar, 0, sizeof(Ipcom_sysvar_data)); return ipcom_mutex_create(&ipcom_sysvar.lock); }
/* *=========================================================================== * ipnet_cmd_qc_set_filter_id *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC void ipnet_cmd_qc_set_filter_id(Ipnet_cmd_qc *p) { int id = p->p.ifq.ifq_id; int queue_id = p->p.ifq.ifq_parent_id; p->p.filter.filter_id = id; p->p.filter.filter_queue_id = queue_id; ipcom_memset(&p->p.filter.filter_rule, 0, sizeof(p->p.filter.filter_rule)); }
/* *=========================================================================== * ipcom_buffer_free *=========================================================================== * Description: Frees any memory used for the buffer. * Parameters: * Returns: * */ IP_PUBLIC void ipcom_buffer_free(Ipcom_buffer *buffer) { #ifdef IP_DEBUG ipcom_memset(buffer->buf, 0xdd, buffer->alloc); #endif ip_assert( buffer->buf && buffer ); ipcom_free(buffer->buf); ipcom_free(buffer); }
IP_STATIC void * ipnet_sysctl_if_add_ip4_addr(void *buf, Ip_u32 addr_n) { struct Ip_sockaddr_in *in = (struct Ip_sockaddr_in *) buf; ipcom_memset(in, 0, sizeof(struct Ip_sockaddr_in)); in->sin_family = IP_AF_INET; IPCOM_SA_LEN_SET(in, sizeof(struct Ip_sockaddr_in)); ipcom_memcpy(&in->sin_addr, &addr_n, sizeof(in->sin_addr)); return in + 1; }
/* *=========================================================================== * ipcom_egd *=========================================================================== * Description: This process gathers random data by calling ipcom_random_bingo_lotto() * * Applications can access the random data before the full entropy * has been gathered. This will of course mean that the quality of * the random data will not be as good, but in some situations that * may be a better trade-off than no random data at all. * Parameters: * Returns: * */ IP_STATIC IPCOM_PROCESS(ipcom_egd) { Ipcom_egd_hash_ctx md5_ctx; Ipcom_egd_hash_ctx tmp_md5_ctx; Ip_s32 rnd; Ipcom_tmo tmo; #ifdef IPCOM_EGD_DEBUG int i; #endif ipcom_proc_init(); IPCOM_LOG0(DEBUG, "ipcom_egd :: starting"); ipcom_egd_hash_init(&md5_ctx); ipcom_egd_laps = 0; #ifdef IPCOM_EGD_DEBUG ipcom_memset(ipcom_egd_raw_data, 0, sizeof(ipcom_egd_raw_data)); #endif while(ipcom_egd_laps < IPCOM_RANDOM_LAPS) { ipcom_egd_tmo_flag = 0; if(ipcom_tmo_request(&tmo, ipcom_random_tmo_handler, (int*)&ipcom_egd_tmo_flag, 50) != IPCOM_SUCCESS) { IPCOM_LOG0(ERR, "ipcom_egd :: timeout request failed, seed aborted"); goto exit; } rnd = ipcom_random_bingo_lotto(); #ifdef IPCOM_EGD_DEBUG ipcom_egd_raw_data[ipcom_egd_laps] = rnd; #endif ipcom_egd_hash_update(&md5_ctx, (void*) &rnd, sizeof(Ip_u32)); ipcom_memcpy(&tmp_md5_ctx, &md5_ctx, sizeof(Ipcom_egd_hash_ctx)); ipcom_egd_hash_final(ipcom_random_state, &tmp_md5_ctx); ipcom_egd_laps++; ipcom_millisleep(IPCOM_EGD_SLEEP_TIME); } exit: #ifdef IPCOM_EGD_DEBUG for (i=0; i < ipcom_egd_laps; i++) { IPCOM_LOG2(INFO, "ipcom_egd_raw_data[%d] = %d", i, ipcom_egd_raw_data[i]); ipcom_millisleep(100); } #endif IPCOM_LOG0(DEBUG, "ipcom_egd :: terminating"); ipcom_proc_exit(); }
IP_STATIC Ip_size_t ipcom_create_ifaddrs_inet6(Ip_fd fd, const char *ifname, Ip_u8 *ifa_first, Ip_size_t buf_len, struct Ipnet_if_msghdr *ifm, struct Ip_ifaddrs ***tail) { struct Ip_in6_aliasreq ifareq; struct Ipnet_ifa_msghdr *ifa; struct Ip_sockaddr_in6 *addrs[IPNET_RTAX_MAX]; Ip_size_t offset = 0; offset = 0; while (offset < buf_len) { struct Ip_ifaddrs *nifa; ifa = (struct Ipnet_ifa_msghdr *) &ifa_first[offset]; #if defined(IP_PORT_VXWORKS) && !defined(_WRS_KERNEL) ipnet_cmd_init_addrs_rtp(ifa + 1, ifa->ifam_addrs, (struct Ip_sockaddr **) addrs); #else ipnet_cmd_init_addrs(ifa + 1, ifa->ifam_addrs, (struct Ip_sockaddr **) addrs); #endif if (ifa->ifam_type != IPNET_RTM_NEWADDR || addrs[IPNET_RTAX_IFA]->sin6_family != IP_AF_INET6) break; offset += ifa->ifam_msglen; ipcom_memset(&ifareq, 0, sizeof(ifareq)); ipcom_memcpy(ifareq.ifra_name, ifname, IP_IFNAMSIZ); ipcom_memcpy(&ifareq.ifra_addr, addrs[IPNET_RTAX_IFA], sizeof(ifareq.ifra_addr)); (void)ipcom_socketioctl(fd, IP_SIOCXGIFADDR_IN6, &ifareq); if (IP_BIT_ISSET(ifareq.ifra_flags, IP_IN6_IFF_ANYCAST)) continue; if (IP_IN6_IS_ADDR_MULTICAST(&addrs[IPNET_RTAX_IFA]->sin6_addr)) continue; nifa = ipcom_create_ifaddrs_entry(ifname, ifm, ifa, (struct Ip_sockaddr **)addrs); if (nifa != IP_NULL) { **tail = nifa; *tail = &nifa->ifa_next; } } return offset; }
IP_GLOBAL void * ipcom_shell_info_new(void) { Ipcom_shell_info *shell_info; shell_info = ipcom_ipc_malloc(sizeof(Ipcom_shell_info)); if (shell_info != IP_NULL) { ipcom_memset(shell_info, 0, sizeof(Ipcom_shell_info)); shell_info->ppid = ipcom_getpid(); } return shell_info; }
/* *=========================================================================== * ipdnsc_hostent_create *=========================================================================== * Description: Creates a hostent structure with empty alias and address * lists * Parameters: type - the type of hostent structure * Returns: pointer to the newly created hostent structure */ IP_GLOBAL struct Ip_hostent* ipdnsc_hostent_create(Ip_s32 type) { struct Ip_hostent *he; /* Allocate the host entry structure */ he = ipcom_malloc(sizeof(*he)); if (he == IP_NULL) { return IP_NULL; } ipcom_memset(he, 0, sizeof(*he)); /* Set the type and length fields */ he->h_addrtype = type; if (type == IP_AF_INET) { he->h_length = IPDNSC_INADDRSZ; } else if (type == IP_AF_INET6) { he->h_length = IPDNSC_IN6ADDRSZ; } else { ipcom_free(he); return IP_NULL; } /* Allocate memory for the alias list */ he->h_aliases = ipcom_malloc(sizeof(char *)); if (he->h_aliases == IP_NULL) { ipcom_free(he); return IP_NULL; } he->h_aliases[0] = IP_NULL; /* Allocate memory for the address list */ he->h_addr_list = ipcom_malloc(sizeof(char *)); if (he->h_addr_list == IP_NULL) { ipcom_free(he->h_aliases); ipcom_free(he); return IP_NULL; } he->h_addr_list[0] = IP_NULL; return he; }
/* *=========================================================================== * ipcom_shell_add_cmd *=========================================================================== * Description: Add a command to the list of available ipcom_shell commands * Parameters: name : command's name * usage : usage string * description : description of command * hook : function to that executes the command * priority : na * stack_size : the stack to be used by the process that * executes the hook. * * Returns: IPCOM_SUCCESS : ok * IPCOM_ERR_DUPLICATE : command already exists * IPCOM_ERR_NO_MEMORY : out of memory * * */ IP_PUBLIC Ip_err ipcom_shell_add_cmd(const char *name, const char *usage, const char *description, Ipcom_shell_cmd_type hook, Ip_s32 priority, Ip_s32 stack_size) { Ipcom_shell_cmd *cmd; static Ipcom_once_t once = IPCOM_ONCE_INIT; Ip_err err; err = ipcom_once(&once, ipcom_shellcmd_init, IP_NULL); if (err != IPCOM_SUCCESS) return err; /* First check if present */ cmd = ipcom_shell_find_cmd(name); if (cmd != IP_NULL) return IPCOM_ERR_DUPLICATE; /*!!allow duplicates for overlay. */ /* Add a new entry to the list */ cmd = (Ipcom_shell_cmd *)ipcom_malloc(sizeof(Ipcom_shell_cmd)); if (cmd == IP_NULL) return IPCOM_ERR_NO_MEMORY; ipcom_memset(cmd, 0, sizeof(Ipcom_shell_cmd)); ipcom_strncpy(cmd->name, name, sizeof(cmd->name)-1); ipcom_strncpy(cmd->usage, usage, sizeof(cmd->usage)-1); ipcom_strncpy(cmd->description, description, sizeof(cmd->description)-1); cmd->hook = hook; if (priority == 0 || priority == IPCOM_SHELL_PRIO_SAME) cmd->priority = ipcom_proc_getprio(ipcom_getpid()); else cmd->priority = priority; cmd->stack_size = stack_size; ipcom_list_insert_last(&ipcom_shell_cmd_head, &cmd->cmd_list); #if defined(WRS_IPNET) && defined(IP_PORT_VXWORKS) && (IP_PORT_VXWORKS >= 65) (void)ipcom_vxshell_add_cmd(name, usage, description, hook, priority, stack_size); #endif return IPCOM_SUCCESS; }
/* *=========================================================================== * ipnet_pkt_queue_mbc_init *=========================================================================== * Description: Configures a queue with new parameters. * Parameters: q - A packet queue. * Returns: * */ IP_STATIC int ipnet_pkt_queue_mbc_init(Ipnet_pkt_queue_mbc *q) { ipcom_memset((Ip_u8 *) q + sizeof(Ipnet_pkt_queue), 0, sizeof(Ipnet_pkt_queue_mbc) - sizeof(Ipnet_pkt_queue)); q->classifier = ipnet_classifier_new(); if (q->classifier == IP_NULL) { IPCOM_LOG0(ERR, "MBC init: Failed to create classifier: out of memory"); return -IP_ERRNO_ENOMEM; } return 0; }
/* *=========================================================================== * ipcom_inet6_rth_init *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC void * ipcom_inet6_rth_init(void *bp, Ip_socklen_t bp_len, int type, int segments) { Ip_pkt_ip6_rthdr *rthdr = (Ip_pkt_ip6_rthdr *) bp; Ip_socklen_t required_bp_len; required_bp_len = ipcom_inet6_rth_space(type, segments); if (required_bp_len == 0 /* Unsupported type or too many segments*/ || bp_len < required_bp_len /* Too small buffer */) return IP_NULL; ipcom_memset(rthdr, 0, bp_len); rthdr->ip6r_type = (Ip_u8) type; rthdr->ip6r_nxt = IP_IPPROTO_NONE; return rthdr; }
/* *=========================================================================== * ipnet_sysctl_if_add_ip6_addr *=========================================================================== * Description: Adds a IPv6 socket address to the buffer. * Parameters: buf - the buffer where the socket address should be written. * addr - the address in network byte order. * is_scoped - IP_TRUE if the address or mask is scoped. * scope_id - The scope_id to use if the mask/address is scoped. * Returns: Pointer to where next address should be written. * */ IP_STATIC void * ipnet_sysctl_if_add_ip6_addr(void *buf, IP_CONST struct Ip_in6_addr *addr, Ip_bool is_scoped, Ip_u32 scope_id) { struct Ip_sockaddr_in6 *in6 = (struct Ip_sockaddr_in6 *) buf; ipcom_memset(in6, 0, sizeof(struct Ip_sockaddr_in6)); in6->sin6_family = IP_AF_INET6; IPCOM_SA_LEN_SET(in6, sizeof(struct Ip_sockaddr_in6)); in6->sin6_scope_id = (is_scoped ? scope_id : 0); IPNET_IP6_SET_ADDR(&in6->sin6_addr, addr); return in6 + 1; }
/* *=========================================================================== * ipl2tp_l2tp_write *=========================================================================== * Description: Send a L2TP control message via UDP. * Parameters: message - Message to send. * addr - Destination IP address. * Returns: * */ IP_STATIC int ipl2tp_l2tp_write(void *user_data, Ipl2tp_key *key, struct Ip_iovec *iov, int iovlen, union Ip_sockaddr_union *addr, int transport) { int sz; int fd; struct Ip_msghdr msg; (void)user_data; (void)key; if (transport == IPL2TP_ATTR_TRANSPORT_UDP) { fd = udp_fd; } else if (transport == IPL2TP_ATTR_TRANSPORT_IP) { fd = ip_fd; } else { ipcom_printf("Bad transport %u!!"IP_LF, transport); return -1; } ipcom_memset(&msg, 0, sizeof(msg)); /* Set it up */ msg.msg_iov = iov; msg.msg_iovlen = iovlen; msg.msg_name = &addr->sa; msg.msg_namelen = addr->sa.sa_len; /* Transmit the UDP packet */ if ((sz = ipcom_sendmsg(fd, &msg, 0)) < 0) { ipcom_printf("ipl2tp_l2tp_write() failed with errno: %d"IP_LF, ipcom_errno); return 0; } return sz; }
int get_ip( char * ifname) { struct Ip_ifreq ifr; int fd; int addr; fd = ipcom_socket(IP_AF_INET, IP_SOCK_DGRAM, 0); ipcom_memset(&ifr,0,sizeof(ifr)); ipcom_strcpy(ifr.ifr_name, ifname); if (ipcom_socketioctl(fd, IP_SIOCGIFADDR, &ifr) != IP_SOCKERR) { addr =((struct Ip_sockaddr_in *)&ifr.ip_ifr_addr)->sin_addr.s_addr; return addr; } }
/* *=========================================================================== * ipcom_inet6_opt_init *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC int ipcom_inet6_opt_init(void *extbuf, Ip_socklen_t extlen) { Ip_pkt_ip6_ext_hdr *ext_hdr; if (extbuf != IP_NULL) { if ((extlen & 7) != 0 || extlen < sizeof(Ip_pkt_ip6_ext_hdr)) return -1; ext_hdr = (Ip_pkt_ip6_ext_hdr *) extbuf; /* Fill the buffer with a patter to detect errors easier */ ipcom_memset(extbuf, 0xbe, extlen); ext_hdr->nxt = IP_IPPROTO_NONE; ext_hdr->len = 0; } return sizeof(Ip_pkt_ip6_ext_hdr); }
/* *=========================================================================== * ipcom_drv_eth_filter_remove_mcast_addr *=========================================================================== * Description: Removes a multicast Ethernet address that should be passed * by the filter. * Parameters: filter - A filter from where the address should be removed. * eth_mcast_addr - The address to remove. * Returns: 0 = success, <0 = error code. * */ IP_PUBLIC int ipcom_drv_eth_filter_remove_mcast_addr(Ipcom_drv_eth_filter *filter, Ip_u8 eth_mcast_addr[IPCOM_DRV_ETH_ADDR_SIZE]) { int i; for (i = 0; i < IPCOM_DRV_ETH_MAX_MULTIADDR; i++) { if (filter->ref[i] != 0 && ipcom_memcmp(eth_mcast_addr, filter->mcast_addr[i], IPCOM_DRV_ETH_ADDR_SIZE) == 0) { /* Address found */ if (--filter->ref[i] == 0) /* Last reference, remove the address */ ipcom_memset(filter->mcast_addr[i], 0, IPCOM_DRV_ETH_ADDR_SIZE); return 0; } } /* Unknown address */ return -IP_ERRNO_EADDRNOTAVAIL; }
int vlan_check(int ifindex, char * parent) { struct Ip_ifreq ifreq; struct Ip_vlanreq vlanreq; int fd; fd = ipcom_socket(IP_AF_INET, IP_SOCK_DGRAM, 0); ipcom_memset(&vlanreq, 0, sizeof(struct Ip_vlanreq)); ifreq.ip_ifr_data = &vlanreq; if (ipcom_if_indextoname(ifindex, ifreq.ifr_name) == IP_NULL || ipcom_socketioctl(fd, IP_SIOCGETVLAN, &ifreq) < 0) return 0; if(ipcom_strcmp(parent,vlanreq.vlr_parent) == 0) { return 1; } else return -1; }
/* *=========================================================================== * ipnet_nat_proxy_h225_msg *=========================================================================== * Description: Track H.225 packets. * This function handles the H.225/Q.931 call signalling packets. NAT calls * this function after translating the address and port number in the IP and * TCP headers, and when the source or destination port is the H.323 port * registered to NAT during the H.323 ALG registration (the standard port for * H.323 protocol is 1720). The H.225 call signalling protocol is used in H.323 * to establish connection between two end-points. * * This function must look at both an outbound as well as an inbound packet. * H.323 connection can be attempted from local to global endpoint or vice * versa. * * NOTE 1: * The fields in the H.225 message are ASN.1 encoded. However, due to schedule, * constraint, rather than employing an ASN.1 decoder, this function uses a simple * strategy to look for the ip+port address in the H.225 payload by taking advantage * of the fact that the port number always follows immediately after the ip address. * Since the ALG can get the expected ip address from NAT, it can search byte by * byte for this ip address to locate where it is in the H.225 payload.. * * Local host (L) <---------------> NAT <----------------> Global host (G) * * The tuple of IP address and TCP/UDP port number is sometimes called transport * address in some publications, and the same terminology will be used here. * * Case 1: Local (L) endpoint to global (G) endpoint connection * * L starts a TCP connection to G and the H.225 call signaling session starts. * The establishment of this TCP connection is all handled by NAT, so by now, * NAT should have the bind entry for this connection. During the H.225 session, * L will embed its sourceCallSignalAddress (ip/port) and G's transport address * in the H.225 payload to G. Thus, this function must parse for each H.225 * outbound packet, look for L's transport address, and substitute it with the * translated address obtained from NAT. * * In addition, this function must also observe the H.225 inbound packets from G * to look for the H.245 transport address (ip/port) in the connect message from * G. The port number provided by G here will serve as the H.245 port number. * L will use this port number to open the H.245 TCP connection with G. So upon * obtaining the H.245 port number, this function must also register the H.245 * ALG agent to NAT . * * Case 2: Global (G) endpoint to local (L) endpoint connection * * G starts a TCP connection to L via the NAT's H.323 static entry and the H.225 * call signaling session starts. As in case 1, the establishment of this TCP * connection is all handled by NAT, so by now, NAT should have the bind entry * for this connection. During the H.225 session, G will embed its sourceCall- * SignalAddress and L's global transport address in the H.225 payload. So, this * function must examine all inbound H.225 packets and substitute L's global * transport address with its real transport address. * * In addition, this function must also observe the H.225 outbound packets * to look for L's H.245 transport address which is embedded in the connect * message from L to G. The port number embedded in this message will serve as * the H.245 port number. * * G will use this port number to open the H.245 TCP connection with L. So, this * function must also register the H.245 ALG agent to NAT upon obtaining the * H.245 port number. Furthermore, since the H.245 TCP connection will be * started from G to L, this function must create a new TCP bind entry for the * impending H.245 port connection. * * NOTE 2: * TCP sequence adjustment is not required since it is a binary substitution of * IP address and port number in the payload. However, the checksum in the TCP * header must be adjusted when the TCP payload is modified. * * Parameters: appdata - pointer to application data. * applen - pointer to length of application data. * param - pointer to proxy parameters. * Returns: 1 = Packet modified. * 0 = Packet untouched. * -1 = Drop packet. */ IP_STATIC int ipnet_nat_proxy_h225_msg(Ip_u8 *appdata, int applen, Ipnet_nat_proxy_param *param) { Ipnet_nat_proxy_tuple proxy_tuple; Ip_u8 *data, *data_start; Ip_u16 local_port, port; Ip_u32 remote_address, local_address, ip_addr; int data_length, tmp; Ip_bool mod = IP_FALSE; data_length = applen; /* length of TCP payload */ if (data_length <= 0) { /* no payload to look at */ return 0; } /* go to start of TCP payload */ data = appdata; data_start = data; local_address = param->tuple.private_addr; local_port = param->tuple.private_port; remote_address = param->tuple.public_addr; if (param->incoming == IP_FALSE) /* outbound packet */ { /* get the H.225 TCP bind descriptor using L's translated source transport address from the source address in the TCP/IP header. From the bind descriptor, obtain L's real transport address and the session flow (i.e. who starts the connection first) of this connection. */ if (param->inbound == IP_FALSE) /* session started by L */ { IPCOM_LOG0(DEBUG, "ipnet_nat_proxy_h225_msg() :: outbound packet, outbound session. " "Look for sourceCallSignalAddress from local host."); while ((data + 6) <= (data_start + data_length)) { ip_addr = IP_GET_NTOHL(data); /* look for L's sourceCallSignalAddress match */ if (ip_addr == local_address) { port = IP_GET_NTOHS(data + 4); if (port == local_port) { /* replace with L's translated sourceCallSignalAdress */ IPCOM_LOG2(DEBUG, "ipnet_nat_proxy_h225_msg() :: " "Replace local address and port (0x%08x:%d) in H225 payload.", ip_addr, port); IP_SET_HTONL(data, param->nat_addr); IP_SET_HTONS(data + 4, param->nat_port); data += 6; mod = IP_TRUE; IPCOM_LOG2(DEBUG, "ipnet_nat_proxy_h225_msg() :: " "Translated local address and port are (0x%08x:%d)", param->nat_addr, param->nat_port); } else /* port != bind_info.local_transport */ { data++; IPCOM_LOG0(DEBUG, "ipnet_nat_proxy_h225_msg() :: matched local address found, " "but not the port number."); } } else /* ip_addr != bind_info.local_addr */ { data++; } } } else /* session started by G */ { IPCOM_LOG0(DEBUG, "ipnet_nat_proxy_h225_msg() :: outbound packet, inbound session. " "Look for H245Address from local host."); while ((data + 6) <= (data_start + data_length)) { ip_addr = IP_GET_NTOHL(data); /* look for L's H245Address port */ if (ip_addr == local_address) { port = IP_GET_NTOHS(data + 4); IPCOM_LOG2(DEBUG, "ipnet_nat_proxy_h225_msg() :: " "Found H245Address (0x%08x:%d) in H225 payload.", ip_addr, port); /* register H.245 ALG to NAT */ /* if NAPT, create a H.245 TCP bind entry to prepare for H.245 connection request from G */ ipcom_memset(&proxy_tuple, 0, sizeof(proxy_tuple)); proxy_tuple.protocol = param->tuple.protocol; proxy_tuple.private_addr = local_address; proxy_tuple.private_port = port; proxy_tuple.public_addr = remote_address; tmp = ipnet_nat_proxy_add_mapping(&proxy_tuple, 0, param->mapping, IP_TRUE, /* Use port translation */ IP_TRUE, /* Inbound session */ ipnet_nat_proxy_h245, IP_NULL); if (tmp < 0) { IPCOM_LOG2(ERR, "ipnet_nat_proxy_h225_msg() :: Failed to add mapping for address = 0x%08x, port = %d", local_address, port); } else { IPCOM_LOG2(DEBUG, "ipnet_nat_proxy_h225_msg() :: Added mapping for address = 0x%08x, port = %d", local_address, port); } IP_SET_HTONL(data, param->nat_addr); IP_SET_HTONS(data + 4, (Ip_u16)tmp); data += 6; mod = IP_TRUE; IPCOM_LOG2(DEBUG, "ipnet_nat_proxy_h225_msg() :: " "Translated local address and port are (0x%08x:%d)", param->nat_addr, tmp); } else /* ip_addr != bind_info.local_addr */ { data++; } }/* while */ } /* else: session started by G */ } else /* inbound packet */ { if (param->inbound == IP_FALSE) /* session started by L */ { IPCOM_LOG0(DEBUG, "ipnet_nat_proxy_h225_msg() :: inbound packet, outbound session. " "Look for H245Address from remote host."); while ((data + 6) <= (data_start + data_length)) { ip_addr = IP_GET_NTOHL(data); /* look for G's H245Address match */ if (ip_addr == remote_address) { port = IP_GET_NTOHS(data + 4); IPCOM_LOG2(DEBUG, "ipnet_nat_proxy_h225_msg() :: " "H245Address from remote host found (0x%08x:%d).", ip_addr, port); /* register H.245 ALG to NAT */ ipcom_memset(&proxy_tuple, 0, sizeof(proxy_tuple)); proxy_tuple.protocol = param->tuple.protocol; proxy_tuple.public_addr = ip_addr; proxy_tuple.public_port = port; proxy_tuple.private_addr = param->tuple.private_addr; if (ipnet_nat_proxy_add_mapping(&proxy_tuple, 0, param->mapping, IP_TRUE, /* Use port translation */ IP_FALSE, /* Outbound session */ ipnet_nat_proxy_h245, IP_NULL) < 0) { IPCOM_LOG2(ERR, "ipnet_nat_proxy_h225_msg() :: Failed to add mapping for address = 0x%08x, port = %d", remote_address, port); } else { IPCOM_LOG2(DEBUG, "ipnet_nat_proxy_h225_msg() :: Added mapping for address = 0x%08x, port = %d", remote_address, port); } } data++; } } else /* session started by G */ { /* search for L's transport address in the H225 payload. If found, translate it to its real transport address. */ IPCOM_LOG0(DEBUG, "ipnet_nat_proxy_h225_msg() :: inbound packet, inbound session." "Translate global transport to its local transport."); while ((data + 6) <= (data_start + data_length)) { ip_addr = IP_GET_NTOHL(data); /* look for L's translated address match */ if (ip_addr == param->nat_addr) { port = IP_GET_NTOHS(data + 4); IPCOM_LOG2(DEBUG, "ipnet_nat_proxy_h225_msg() :: " "global ip match found in H.225 payload (0x%08x:%d).", ip_addr, port); if (port == param->nat_port) { IP_SET_HTONL(data, local_address); IP_SET_HTONS(data + 4, local_port); data += 6; mod = IP_TRUE; IPCOM_LOG2(DEBUG, "ipnet_nat_proxy_h225_msg() :: " "After translation local_address and port are (0x%08x:%d).", local_address, local_port); } else /* port != bind_info.global_transport */ { data++; } } else /* ip_addr != bind_info.global_addr */ { data++; } } /* while */ } /* else (session started by G) */ } return mod == IP_TRUE ? 1 : 0; }
/* *=========================================================================== * ipnet_nat_proxy_h245_msg *=========================================================================== * Description: Track H.245 packets. * This function handles the H.245 call control packets. NAT calls this function * after translating the address and port number in the IP and TCP headers, and * when the source or destination port is the H.245 port. The H.245 port was * negotiated during the H.225 call signaling session and registered to NAT. * The H.245 call control protocol is used in H.323 to negotiate call parameters * between two end-points. For example, it negotiates the UDP connections for * the open logical channels for RTP and RTCP streams between the two endpoints. * In addition, it also negotiates the TCP connection for the T1.120 session. * * NOTE 1: * The H.245 message is ASN.1 encoded. However, due to resource and schedule * constraint, rather than employing an ASN.1 decoder, this function uses a simple * work-around alternative which appears to work just as well. This work-around * strategy looks for the ip+port address in the H.245 payload by taking advantage * of the fact that the port number always follows immediately after the ip address. * Since the ALG can get the expected ip address from NAT, it can search byte by * byte for this ip address to locate where it is in the H.245 payload. * * Local host (L) <---------------> NAT <----------------> Global host (G) * * The tuple of IP address and TCP/UDP port number is sometimes called transport * address in some publications, and the same terminology will be used here. * * For an outbound packet, L may be sending its transport addresses to G to let * G make TCP/UDP connections to it. Similarly, for an inbound packet, G may be * sending its transport addresses to L to let L make TCP/UDP connections to it. * Since only the L's transport addresses in the payload need to be translated, * it is sufficient to examine only the outbound packets. * * NOTE 2: * TCP sequence adjustment is not required since it is a binary substitution of * IP address and port number in the payload. However, the checksum in the TCP * header must be adjusted when the TCP payload is modified. * * Parameters: appdata - pointer to application data. * applen - pointer to length of application data. * param - pointer to proxy parameters. * Returns: 1 = Packet modified. * 0 = Packet untouched. * -1 = Drop packet. */ IP_STATIC int ipnet_nat_proxy_h245_msg(Ip_u8 *appdata, int applen, Ipnet_nat_proxy_param *param) { Ipnet_nat_proxy_tuple proxy_tuple; Ip_u8 *data, *data_start; Ip_u16 port; Ip_u32 local_address, ip_addr; int data_length; Ip_bool mod = IP_FALSE; if (param->incoming == IP_TRUE) return 0; data_length = applen; /* length of TCP payload */ if (data_length <= 0) { /* no payload to look at */ return 0; } /* go to start of TCP payload */ data = appdata; data_start = data; local_address = param->tuple.private_addr; /* L's local ip */ /* search for L's ip address in the H.245 payload for all possible TCP/UDP connections that may be negotiated. For each one found, create create a static TCP/UDP control block to get the translated transport address. We must do this for all L's ip address found in the H.245 payload since we are not decoding the ASN.1 message thus don't really know which ones will actually be used. A check is made to prevent creation of duplicate bind entries. The ID of each created static entry is recorded so the ALG can delete them when the Netmeeting session is terminated */ while ((data + 6) <= (data_start + data_length)) { ip_addr = IP_GET_NTOHL(data); /* look for L's global address match */ if (ip_addr == local_address) { port = IP_GET_NTOHS(data + 4); if (port > IPNET_NAT_H323_LOWER_EPHEMERAL_PORT_VALUE) { IPCOM_LOG2(DEBUG, "ipnet_nat_proxy_h245_msg() :: Local host address found in H245 payload. " "ip = 0x%08x, port = %d", ip_addr, port); /* Do not add a mapping for the TCP T1.120 port here. Should be taken care of by NAT rules */ if (port != IPNET_NAT_T1_120_PORT) { /* create a bind entry for this transport address if it hasn't been created yet */ ipcom_memset(&proxy_tuple, 0, sizeof(proxy_tuple)); proxy_tuple.protocol = IP_IPPROTO_UDP; proxy_tuple.private_addr = local_address; proxy_tuple.private_port = port; proxy_tuple.public_addr = param->tuple.public_addr; if (ipnet_nat_proxy_add_mapping(&proxy_tuple, IPNET_NAT_H323_MEDIA_TIMEOUT, param->mapping, IP_FALSE, /* NAT port = local source port */ IP_TRUE, /* Inbound session */ IP_NULL, IP_NULL) < 0) { IPCOM_LOG2(ERR, "ipnet_nat_proxy_h245_msg() :: Failed to add mapping for address = 0x%08x, port = %d", local_address, port); } else { IPCOM_LOG2(DEBUG, "ipnet_nat_proxy_h245_msg() :: Added mapping for address = 0x%08x, port = %d", local_address, port); } } /* Replace L's local address with its global address in the payload */ IP_SET_HTONL(data, param->nat_addr); data += 6; mod = IP_TRUE; IPCOM_LOG1(DEBUG, "ipnet_nat_proxy_h245_msg() :: " "Translated local address is (0x%08x)", param->nat_addr); } else /* detected port number is not a valid ephemeral port value */ { IPCOM_LOG1(INFO, "ipnet_nat_proxy_h245_msg() :: detected port invalid, ignore! port = %d", port); data++; } } else /* ip_addr != local_address */ { data++; } } /* end while loop */ return mod == IP_TRUE ? 1 : 0; }
IP_PUBLIC int ipcom_cmd_smptest(int argc, char **argv) { Ipcom_getopt opt; int c; struct Ip_addrinfo hints; struct Ip_addrinfo *res; char *hostname = "0.0.0.0"; char *servname = "8484"; int socktype = IP_SOCK_STREAM; int domain = IP_AF_INET; Ipcom_cmd_smptest_t smp_opt; return_client = 0; return_server = 0; verbose = 0; ipcom_memset(&smp_opt, 0, sizeof(smp_opt)); smp_opt.server = 1; smp_opt.ip4 = 1; smp_opt.tcp = 1; smp_opt.num_bytes = 1024; smp_opt.num_sock = 1; smp_opt.port = 8484; ipcom_getopt_clear_r(&opt); while ((c = ipcom_getopt_r(argc, argv, "l:p:s:c6uhv", &opt)) != -1) { switch(c) { case 'c': smp_opt.server = 0; if ( verbose ) ipcom_printf( "client"IP_LF ); break; case '6': smp_opt.ip4 = 0; domain = IP_AF_INET6; hostname = "::"; if ( verbose ) ipcom_printf( "IPv6"IP_LF ); break; case 'u': smp_opt.tcp = 0; socktype = IP_SOCK_DGRAM; if ( verbose ) ipcom_printf( "UDP"IP_LF ); break; case 'l': smp_opt.num_bytes = ipcom_atoi(opt.optarg); if ( verbose ) ipcom_printf( "num bytes: %d"IP_LF, smp_opt.num_bytes ); break; case 'p': servname = opt.optarg; smp_opt.port = ipcom_atoi(opt.optarg); if ( verbose ) ipcom_printf( "port: %s"IP_LF, servname ); break; case 's': smp_opt.num_sock = ipcom_atoi(opt.optarg); if ( smp_opt.num_sock > MAX_TASKS ) smp_opt.num_sock = MAX_TASKS; if ( verbose ) ipcom_printf( "sockets: %d"IP_LF, smp_opt.num_sock ); break; case 'v': verbose = 1; break; case 'h': ipcom_cmd_smptest_print_usage(); return -1; default: ipcom_printf("smptest: unknown option %c"IP_LF, (char)c); ipcom_cmd_smptest_print_usage(); return -1; } } if (opt.optind < argc) hostname = argv[opt.optind]; else { if ( 0 == smp_opt.server ) { if ( smp_opt.ip4 ) hostname = "127.0.0.1"; else hostname = "::1"; } } if ( verbose ) ipcom_printf( "%s : %s"IP_LF, hostname, servname ); ipcom_memset(&hints, 0, sizeof(hints)); hints.ai_socktype = socktype; hints.ai_flags = IP_AI_CANONNAME; hints.ai_family = domain; if (ipcom_getaddrinfo(hostname, servname, &hints, &res) != 0) { ipcom_printf("sockperf: getaddrinfo() failed"IP_LF); goto cleanup; } smp_opt.res = res; if ( smp_opt.server ) smp_opt_server = smp_opt; else smp_opt_client = smp_opt; if ( smp_opt.server == 1 ) { if ( 0 != ipcom_cmd_smptest_server() || 0 != return_server ) { ipcom_printf( "Failure."IP_LF ); goto cleanup; } } else { if ( 0 != ipcom_cmd_smptest_client() || 0 != return_client ) { ipcom_printf( "Failure"IP_LF ); goto cleanup; } } ipcom_printf( "Success." ); /* Success */ cleanup: ipcom_freeaddrinfo( res ); return 0; }
IP_STATIC IPCOM_PROCESS( ipcom_cmd_smptest_client_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 socket; unsigned char *buf = 0; int portadd = spawn_number_client++; int opt_val = 1; int sec = SECONDS_CLIENT; int send = 0; int num_sends = 0; unsigned long num_bytes = 0; ipcom_proc_init(); ipcom_memset( &addr.ss, 0, sizeof( addr.ss ) ); ipcom_memcpy( &addr.sa, smp_opt_client.res->ai_addr, smp_opt_client.res->ai_addrlen ); socket = ipcom_socket( smp_opt_client.res->ai_family, smp_opt_client.res->ai_socktype, smp_opt_client.res->ai_protocol ); if (socket == IP_SOCKERR) { ipcom_printf("Failed to create socket for thread %d: %s"IP_LF, portadd, ipcom_strerror(ipcom_errno)); return_client = 1; ipcom_sem_post( sem_wait_client ); return; } if ( 0 != ipcom_setsockopt(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_client = 1; ipcom_sem_post( sem_wait_client ); return; } if ( 0 != ipcom_socketioctl( socket, IP_X_SIOCSINTR, &sec ) ) { ipcom_printf("ipcom_socketioctl failed: %s"IP_LF, ipcom_strerror(ipcom_errno)); return_client = 1; ipcom_sem_post( sem_wait_client ); return; } addr.sin.sin_port = ip_htons( smp_opt_client.port + portadd ); /* port is in the same place for IPv4 and IPv6 */ if ( smp_opt_client.tcp ) { if ( 0 != ipcom_connect( socket, &addr.sa, smp_opt_client.res->ai_addrlen ) ) { ipcom_printf("Thread %d failed to connect: %s"IP_LF, portadd, ipcom_strerror(ipcom_errno)); return_client = 1; ipcom_sem_post( sem_wait_client ); return; } if ( verbose ) ipcom_printf("Thread %d connected to port %d"IP_LF, portadd, smp_opt_client.port + portadd ); } buf = ipcom_malloc( smp_opt_client.num_bytes ); while ( 1 ) { if ( smp_opt_client.tcp ) send = ipcom_send( socket, buf, smp_opt_client.num_bytes, 0); else send = ipcom_sendto( socket, buf, smp_opt_client.num_bytes, 0, &addr.sa, smp_opt_client.res->ai_addrlen ); if ( send > 0 ) num_bytes += send; num_sends++; if ( send == 0 ) { ipcom_printf( "Error: Disconnected"IP_LF ); return_client = 1; break; } else if ( send < 0 ) { if ( ipcom_errno == IP_ERRNO_EINTR ) { if ( verbose ) { ipcom_printf("Thread %d done."IP_LF, portadd ); ipcom_printf(" Sends: %d"IP_LF, num_sends ); ipcom_printf(" MB/s: %f"IP_LF, ((float)(num_bytes)/(1024.0f*1024.0f) )/5.0f ); } break; } return_client = 1; ipcom_printf("Error on thread %d: %s"IP_LF, portadd, ipcom_strerror(ipcom_errno)); break; } } if ( verbose ) { if ( spawn_number_client != smp_opt_client.num_sock ) { ipcom_printf("Error. Only %d client-sockets seemed to work."IP_LF, spawn_number_client ); } } ipcom_socketclose( socket ); ipcom_free( buf ); if ( 0 == ipcom_atomic_sub_and_return( &num_wait_client, 1 ) ) ipcom_sem_post( sem_wait_client ); ipcom_proc_exit(); }
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(); }
/* *=========================================================================== * 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(); }
/* *=========================================================================== * ipnet_sysctl_route_dump_cb *=========================================================================== * Description: Checks if this entry should be added and adds it if it should. * Parameters: rt - the route entry to add * data - callback data. * Returns: IP_FALSE (the entry should never be deleted). * */ IP_STATIC Ip_bool ipnet_sysctl_route_dump_cb(Ipnet_route_entry *rt, Ipnet_sysctl_route_data *data) { struct Ipnet_rt_msghdr *rt_msg; Ip_u16 len; if (rt->next) (void)ipnet_sysctl_route_dump_cb(rt->next, data); if (rt->narrow) (void) ipnet_sysctl_route_dump_cb(rt->narrow, data); if ((rt->hdr.flags & data->flags) != data->flags) return IP_FALSE; /* Do not list the 255.255.255.255, 224.0.0.0/4 or IPv6 multicast routes. */ if (IP_BIT_ISSET(rt->hdr.flags, IPNET_RTF_X_MCAST_RO | IPNET_RTF_X_BCAST_RO | IPNET_RTF_X_HIDDEN)) return IP_FALSE; len = ipnet_sysctl_route_dump_elem_len(rt); data->bytes_written += len; if (data->bytes_written > data->buf_len) { /* Buffer to small */ if (data->buf != IP_NULL) data->soerrno = -IP_ERRNO_ENOMEM; return IP_FALSE; } rt_msg = (struct Ipnet_rt_msghdr *) data->buf; data->buf = (Ip_u8 *) data->buf + sizeof(struct Ipnet_rt_msghdr); ipcom_memset(rt_msg, 0, sizeof(struct Ipnet_rt_msghdr)); rt_msg->rtm_msglen = len; rt_msg->rtm_version = IPNET_RTM_VERSION; rt_msg->rtm_type = IPNET_RTM_GET; rt_msg->rtm_index = rt->netif ? rt->netif->ipcom.ifindex : 0; rt_msg->rtm_table = data->table; rt_msg->rtm_flags = rt->hdr.flags; rt_msg->rtm_use = rt->use; rt_msg->rtm_rmx = rt->metrics; /* add destination address */ IP_BIT_SET(rt_msg->rtm_addrs, IPNET_RTA_DST); data->buf = ipnet_sysctl_route_add_addr(data->buf, IPNET_ROUTE_GET_FAMILY(rt->head), rt->hdr.key); if (rt->gateway) { IP_BIT_SET(rt_msg->rtm_addrs, IPNET_RTA_GATEWAY); ipcom_memcpy(data->buf, rt->gateway, IPCOM_SA_LEN_GET(rt->gateway)); data->buf = (Ip_u8 *) data->buf + IPCOM_SA_LEN_GET(rt->gateway); } else if (IP_BIT_ISSET(rt->hdr.flags, IPNET_RTF_CLONING)) { struct Ip_sockaddr_dl *dl = data->buf; IP_BIT_SET(rt_msg->rtm_addrs, IPNET_RTA_GATEWAY); ipcom_memset(data->buf, 0, sizeof(struct Ip_sockaddr_dl)); IPCOM_SA_LEN_SET(dl, sizeof(struct Ip_sockaddr_dl)); dl->sdl_family = IP_AF_LINK; ip_assert(rt->netif != IP_NULL); if (rt->netif != IP_NULL) { dl->sdl_index = (Ip_u16)rt->netif->ipcom.ifindex; dl->sdl_type = (Ip_u8)rt->netif->ipcom.type; } data->buf = (Ip_u8 *) data->buf + sizeof(struct Ip_sockaddr_dl); } if (rt->hdr.mask) { /* add destination mask */ IP_BIT_SET(rt_msg->rtm_addrs, IPNET_RTA_NETMASK); data->buf = ipnet_sysctl_route_add_addr(data->buf, IPNET_ROUTE_GET_FAMILY(rt->head), rt->hdr.mask); } ip_assert((Ip_u16)((Ip_ptrdiff_t) data->buf - (Ip_ptrdiff_t) rt_msg) == len); return IP_FALSE; }