/* *=========================================================================== * 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; }
/* *=========================================================================== * 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_create_ifaddrs_entry *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC struct Ip_ifaddrs * ipcom_create_ifaddrs_entry(const char *ifname, struct Ipnet_if_msghdr *ifm, struct Ipnet_ifa_msghdr *ifa, struct Ip_sockaddr **addrs) { /**/ struct Ip_ifaddrs *nifa = ipcom_calloc(1, sizeof(*nifa)); if (nifa == IP_NULL) return IP_NULL; /* Interface name */ nifa->ifa_name = ipcom_strdup(ifname); if(nifa->ifa_name == IP_NULL) goto fail; /* Interface flags */ nifa->ifa_flags = ifm->ifm_flags; /* Interface address */ nifa->ifa_addr = ipcom_malloc(sizeof(union Ip_sockaddr_union)); if(nifa->ifa_addr == IP_NULL) goto fail; ipcom_memcpy(nifa->ifa_addr, addrs[IPNET_RTAX_IFA], IPCOM_SA_LEN_GET(addrs[IPNET_RTAX_IFA])); nifa->ifa_netmask = ipcom_malloc(sizeof(union Ip_sockaddr_union)); if(nifa->ifa_netmask == IP_NULL) goto fail; ipcom_memcpy(nifa->ifa_netmask, addrs[IPNET_RTAX_NETMASK], IPCOM_SA_LEN_GET(addrs[IPNET_RTAX_IFA])); if (IP_BIT_ISSET(ifa->ifam_addrs, IPNET_RTA_BRD)) { nifa->ifa_broadaddr = ipcom_malloc(sizeof(union Ip_sockaddr_union)); if(nifa->ifa_broadaddr == IP_NULL) goto fail; ipcom_memcpy(nifa->ifa_broadaddr, addrs[IPNET_RTAX_BRD], IPCOM_SA_LEN_GET(addrs[IPNET_RTAX_BRD])); } return nifa; fail: ipcom_ifaddrs_free(nifa); return IP_NULL; }
/* *=========================================================================== * 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; }
/***************************************************************************** * * example_concatenate_tokens - Concatenate all options on this line * * .IP <tok> * The tokenizer buffer * * RETURNS: * A dynamically allocated memory buffer containing all the tokenized options * on success, IP_NULL otherwise. * * NOMANUAL */ IP_STATIC char * example_concatenate_tokens(example_token_buffer_t *tok) { char *value; char *conc = ipcom_malloc(256); if (conc != IP_NULL) { int no_values = 0; conc[0] = '\0'; while ((value = example_get_token(tok, IP_FALSE)) != IP_NULL) { if (ipcom_strcasecmp(value, ";") == 0) break; no_values++; ipcom_strncat(conc, value, 256); ipcom_strncat(conc, " ", 256); } /* No semicolon or no values */ if (no_values == 0 || value == IP_NULL) { ipcom_free(conc); return IP_NULL; } return conc; } return IP_NULL; }
/* *=========================================================================== * 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; }
/* *=========================================================================== * ipl2tp_cache_malloc *=========================================================================== * Description: Allocate buffer from local cache * Parameters: * Returns: * */ IP_STATIC void * ipl2tp_cache_malloc(Ip_u32 size) { Ipl2tp_cache_head *head; Ip_u32 msr; msr = ipcom_interrupt_disable(); if (free_list != IP_NULL) { head = free_list; free_list = head->next; ipcom_interrupt_enable(msr); } else { ipcom_interrupt_enable(msr); if ((head = ipcom_malloc(sizeof(*head) + size)) == IP_NULL) { return IP_NULL; } } return head + 1; }
/* *=========================================================================== * ipdnsc_hostent_insert_name *=========================================================================== * Description: Inserts a host name in a hostent structure * Parameters: he - pointer to the hostent structure * name - the name to insert * Returns: 0 for OK, -1 for fail. */ IP_GLOBAL Ip_s32 ipdnsc_hostent_insert_name(struct Ip_hostent *he, char *name) { if (he == IP_NULL) return -1; if (ipcom_strlen(name) > (IPDNSC_MAXNAME-1)) return -1; /* Free the memory for the current name if any */ if (he != IP_NULL && he->h_name != IP_NULL) { ipcom_free(he->h_name); } /* Allocate storage for the host name */ he->h_name = ipcom_malloc(ipcom_strlen(name)+1); if (he->h_name == IP_NULL) { return -1; } /* Copy the host name */ ipcom_strcpy(he->h_name, name); return 0; }
/**************************************************************************** * * example_restore_lease_db - restore DHCP Server lease database * * This is an example on how the contents of the IPDHCPS lease database can * be restored by initializing it with data stored in a file system. * * RETURNS: * 0 if success, -1 if failed. * * NOMANUAL */ IP_STATIC int example_restore_lease_db(void) { int retval = -1; IP_FILE *fd = IP_NULL; struct Ip_stat statbuf; void *buf = IP_NULL; if(ipcom_stat("/home/jonas/dumpfile", &statbuf) == -1) goto leave; if((fd = ipcom_fopen("/home/jonas/dumpfile", "r")) == 0) goto leave; if((buf = ipcom_malloc(statbuf.st_size)) == IP_NULL) goto leave; if(ipcom_fread(buf, statbuf.st_size, 1, fd) <= 0) goto leave; ipdhcps_lease_db_restore(buf); retval = 0; leave: if(fd) ipcom_fclose(fd); if(buf != IP_NULL) ipcom_free(buf); return retval; }
/**************************************************************************** * * example_do_command - Execute a DHCPS command * * This routine execute a DHCPS command containing the parameters we're * interested in adding to the configuration. * * .IP <format> * The format string * * .IP <...> * The arguments for the format string * * RETURNS: * N/A * * NOMANUAL */ IP_STATIC void example_do_command(const char *format, ...) { va_list vargs; char *cmd; int argc; char **argv = IP_NULL; if ((cmd = ipcom_malloc(256)) != IP_NULL) { va_start(vargs, format); ipcom_vsnprintf(cmd, 256, format, vargs); va_end(vargs); IPCOM_LOG1(INFO,"DHCP Executing '%s'", cmd); if(ipcom_parse_argstr(cmd, (int*)&argc, &argv) != IPCOM_SUCCESS) { IPCOM_LOG1(ERR,"failed to parse command '%s'", cmd); goto out; } if(ipdhcps_cmd_dhcps(argc, argv) != IPCOM_SUCCESS) { IPCOM_LOG1(ERR,"failed to execute command '%s'", cmd); goto out; } out: if (argv != IP_NULL) ipcom_free(argv); if (cmd) ipcom_free(cmd); } }
/* *=========================================================================== * ipnet_nat_proxy_sip_callidstr *=========================================================================== * Description: Extract the callid string * Parameters: pdata - pointer to message. * Returns: pointer to allocated buffer with callid string or * IP_NULL if wrong format or out of memory. */ IP_STATIC char * ipnet_nat_proxy_sip_callidstr(char *pmsg) { char *pstart; char *pcallid; int i; SIP_SKIP_SPACES(pmsg); pstart = pmsg; for (i = 0; i < 200; i++) { if (*pmsg != '\r') pmsg++; else break; } /* in case we have a wrong string format */ if (i >= 200) { IPCOM_LOG0(ERR, "ipnet_nat_proxy_sip_callidstr() :: ERROR, wrong string format"); return IP_NULL; } if ((pcallid = ipcom_malloc((pmsg - pstart) + 1)) == IP_NULL) return IP_NULL; ipcom_memcpy(pcallid, pstart, pmsg - pstart); *(pcallid + (pmsg - pstart)) = 0; IPCOM_LOG1(DEBUG, "ipnet_nat_proxy_sip_callidstr() :: callid=%s", pcallid); return pcallid; }
/* *=========================================================================== * 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_buffer_init *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC void ipcom_buffer_init(Ipcom_buffer *buffer) { buffer->alloc = IPCOM_BUFFER_SIZE; buffer->buf = ipcom_malloc(IPCOM_BUFFER_SIZE); buffer->offset = 0; buffer->end = 0; }
/* *=========================================================================== * ipnet_vrrp_add_addr *=========================================================================== * Description: Adds a virtual router address. * Parameters: netif - The network interface the VRIP will be assigned to. * vrid - The VRID the address will be assigned to. * Returns: 0 = success, <0 = error code. * */ IP_GLOBAL int ipnet_vrrp_add_addr(Ipnet_netif *netif, Ip_u8 vrid, struct Ip_in_addr addr) { Ipnet_vrrp_addr_t *addr_entry; if (ipnet->vrrp_addrs == IP_NULL) { ipnet->vrrp_addrs = ipcom_hash_new((Ipcom_hash_obj_func) ipnet_vrrp_obj_hash, (Ipcom_hash_key_func) ipnet_vrrp_obj_hash, (Ipcom_hash_cmp_func) ipnet_vrrp_hash_cmp); if (ipnet->vrrp_addrs == IP_NULL) return -IP_ERRNO_ENOMEM; } addr_entry = ipnet_vrrp_get_addr_entry(netif, vrid); if (addr_entry == IP_NULL) { addr_entry = ipcom_malloc(sizeof(Ipnet_vrrp_addr_t)); if (addr_entry == IP_NULL) return -IP_ERRNO_ENOMEM; IPNET_IF_LOCK(netif); addr_entry->netif = netif; addr_entry->vrid = vrid; addr_entry->num_addrs = 1; addr_entry->addrs[0] = addr; } else { Ipnet_vrrp_addr_t *a; int i; i = ipnet_vrrp_addr_index(addr_entry, addr); if (i >= 0) return -IP_ERRNO_EEXIST; (void)ipcom_hash_remove(ipnet->vrrp_addrs, addr_entry); a = ipcom_realloc(addr_entry, sizeof(Ipnet_vrrp_addr_t) + addr_entry->num_addrs * sizeof(Ipnet_vrrp_addr_t)); if (a == IP_NULL) return -IP_ERRNO_ENOMEM; a->addrs[a->num_addrs++] = addr; addr_entry = a; } if (ipcom_hash_add(ipnet->vrrp_addrs, addr_entry) != IPCOM_SUCCESS) { ipcom_free(addr_entry); return -IP_ERRNO_ENOMEM; } IPCOM_LOG2(INFO, "VRRP: added address %s on %s", ipcom_inet_ntop(IP_AF_INET, &addr, ipnet->log_buf, sizeof(ipnet->log_buf)), netif->ipcom.name); return 0; }
IP_PUBLIC char * ipcom_strdup(const char *s1) { char *s2; s2 = ipcom_malloc(ipcom_strlen(s1) + 1); if(s2 == IP_NULL) return IP_NULL; ipcom_strcpy(s2, s1); return s2; }
ZBUF_ID zbufSockRecvfrom ( int s, /* socket to receive from */ int flags, /* flags to underlying protocols */ int * pLen, /* number of bytes requested/returned */ struct sockaddr *from, /* where to copy sender's addr */ int * pFromLen /* value/result length of <from> */ ) { ZBUF_ID zbufId; /* zbuf returned to user */ ZBUF_SEG zbufSeg = NULL; /* received zbuf chain */ int status; /* recvfrom() return status */ char* buf = NULL; int so_type; socklen_t optlen = sizeof(int); if (-1 == getsockopt(s, (int)SOL_SOCKET, (int)SO_TYPE, (char*)&so_type, (int*)&optlen)) return (ZBUF_ID)NULL; ZBUF_ID_CREATE(zbufId); /* create ID for recv data */ if (zbufId == (ZBUF_ID)NULL) return (ZBUF_ID)NULL; if (so_type == SOCK_DGRAM) { if((status = recvfrom(s, (char*)&zbufSeg, *pLen, flags | IP_MSG_ZBUF, from, pFromLen)) < 0) goto cleanup; } else { ip_assert(so_type == SOCK_STREAM); buf = ipcom_malloc(*pLen); if (buf == NULL) goto cleanup; if ((status = recvfrom(s, buf, *pLen, flags | IP_MSG_ZBUF, from, pFromLen)) < 0) goto cleanup; if ((zbufSeg = zbufInsertBuf(zbufId, NULL, 0, buf, status, simple_free, 0)) == NULL) goto cleanup; } ZBUF_SETSEG(zbufId, zbufSeg); *pLen = status; return zbufId; cleanup: if (zbufId) ZBUF_ID_DELETE_EMPTY(zbufId); if (buf) ipcom_free(buf); return (ZBUF_ID)NULL; }
/* *=========================================================================== * 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; }
/* *=========================================================================== * ipppp_work_alloc *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC struct Ipppp_action_work * ipppp_work_alloc(Ipcom_netif *netif, int action, void *data) { struct Ipppp_action_work *work; work = ipcom_malloc(sizeof(*work)); if (work) { ipcom_strcpy(work->ifname, netif->name); work->ifindex = netif->ifindex; work->link_index = netif->link_index; work->action = action; work->data = data; } return work; }
/* *=========================================================================== * ipcom_spinlock_create *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC Ip_err ipcom_spinlock_create(Ipcom_spinlock *sl_handle) { #ifdef IPCOM_USE_SMP Ipcom_vxworks_spinlock_t *sl; *sl_handle = sl = ipcom_malloc(sizeof(*sl)); if (sl != IP_NULL) { vxAtomicSet(&sl->count, 1); sl->sem = semBCreate(SEM_Q_PRIORITY | SEM_Q_FIFO, SEM_EMPTY); } return *sl_handle ? IPCOM_SUCCESS : IPCOM_ERR_FAILED; #else *sl_handle = IPCOM_SPINLOCK_TAG; return IPCOM_SUCCESS; #endif }
/* *=========================================================================== * ipdnsc_hostent_insert_alias *=========================================================================== * Description: Inserts an alias name in a hostent structure * Parameters: he - pointer to the hostent structure * name - the name to insert * Returns: 0 for OK, -1 for fail. */ IP_GLOBAL Ip_s32 ipdnsc_hostent_insert_alias(struct Ip_hostent *he, char *name) { Ip_s32 num_alias, i=0; char **tmp; if (ipcom_strlen(name) > (IPDNSC_MAXNAME-1)) return -1; /* Find out the current number of aliases */ num_alias = ipdnsc_hostent_alias_count(he); /* Allocate memory for the another alias list entry */ tmp = ipcom_realloc(he->h_aliases, (num_alias+1) * sizeof(char *)); if(tmp == IP_NULL) return -1; he->h_aliases = tmp; /* Allocate memory for the alias */ he->h_aliases[num_alias-1] = ipcom_malloc(ipcom_strlen(name)+1); if (he->h_aliases[num_alias-1] == IP_NULL) { /* We have to free to whole list here */ while (he->h_aliases[i] != IP_NULL) { ipcom_free(he->h_aliases[i]); i++; } /* Free the alias list */ ipcom_free(he->h_aliases); he->h_aliases = IP_NULL; return -1; } /* Set the alias */ ipcom_strcpy(he->h_aliases[num_alias-1], name); /* Null terminate the list */ he->h_aliases[num_alias] = IP_NULL; return 0; }
/* *=========================================================================== * ipcom_minlock_create *=========================================================================== * Description: * Parameters: * Returns: * */ IP_PUBLIC Ip_err ipcom_minlock_create(Ipcom_spinlock *sl_handle) { #ifdef IPCOM_USE_SMP spinlockIsrNd_t *sl; sl = ipcom_malloc(sizeof(*sl)); if (sl != IP_NULL) { *sl_handle = sl; spinlockIsrNdInit (sl); } return sl ? IPCOM_SUCCESS : IPCOM_ERR_FAILED; #else *sl_handle = (Ipcom_spinlock) 0xabadaba2; /* arbitrary */ return IPCOM_SUCCESS; #endif }
/* *=========================================================================== * ipdnsc_hostent_insert_addr *=========================================================================== * Description: Inserts an address in a hostent structure * Parameters: he - pointer to the hostent structure * addr - the addr to insert * Returns: 0 for OK, -1 for fail. */ IP_GLOBAL Ip_s32 ipdnsc_hostent_insert_addr(struct Ip_hostent *he, char *addr) { Ip_s32 num_addr, i=0; char **tmp; /* Find out the current number of addresses */ num_addr = ipdnsc_hostent_addr_count(he); /* Allocate memory for the another address list entry */ tmp = ipcom_realloc(he->h_addr_list, (num_addr+1) * sizeof(char *)); if(tmp == IP_NULL) return -1; he->h_addr_list = tmp; /* Allocate memory for the address */ he->h_addr_list[num_addr-1] = ipcom_malloc(he->h_length); if (he->h_addr_list[num_addr-1] == IP_NULL) { /* We have to free to whole list here */ while (he->h_addr_list[i] != IP_NULL) { ipcom_free(he->h_addr_list[i]); i++; } /* Free the address list */ ipcom_free(he->h_addr_list); he->h_addr_list = IP_NULL; return -1; } /* Set the address */ ipcom_memcpy(he->h_addr_list[num_addr-1], addr, he->h_length); /* Null terminate the list */ he->h_addr_list[num_addr] = IP_NULL; return 0; }
/* *=========================================================================== * ipcom_env_create *=========================================================================== * Description: * Parameters: * Returns: */ IP_STATIC Ipcom_env_entry * ipcom_env_create(const char *name, const char *value) { Ip_size_t name_length; Ip_size_t value_length; Ipcom_env_entry *env; /* Create environment variable */ name_length = ipcom_strlen(name) + 1; value_length = ipcom_strlen(value) + 1; env = ipcom_malloc(sizeof(Ipcom_env_entry) + name_length + value_length); if(env == IP_NULL) return IP_NULL; /* Init environment variable */ env->name = (const char *)env + sizeof(Ipcom_env_entry); ipcom_memcpy((void *)env->name, name, name_length); env->value = env->name + name_length; ipcom_memcpy((void *)env->value, value, value_length); return env; }
/* *=========================================================================== * ipnet_cmd_sysctl_get *=========================================================================== * Description: * Parameters: * Returns: * */ IP_STATIC Ip_bool ipnet_cmd_sysctl_get(int *name, int namelen, void **oldp, Ip_size_t *oldlenp) { *oldlenp = 0; if (ipcom_sysctl(name, namelen, IP_NULL, oldlenp, IP_NULL, 0) < 0) return IP_FALSE; *oldp = ipcom_malloc(*oldlenp); if (*oldp == IP_NULL) return IP_FALSE; if (ipcom_sysctl(name, namelen, *oldp, oldlenp, IP_NULL, 0) < 0) { ipcom_free(*oldp); return IP_FALSE; } return IP_TRUE; }
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(); }
/* *=========================================================================== * 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_sysvar_set_internal *=========================================================================== * Description: * Parameters: * Returns: */ IP_GLOBAL Ip_err ipcom_sysvar_set_tree(const char *name, const char *value, int flags, Ipcom_sysvar_tree *tree) { Ip_size_t name_length; Ip_size_t value_length; Ipcom_sysvar_entry *sysvar; Ip_err retval = IPCOM_SUCCESS; /* Check for duplicate. */ sysvar = ipcom_hash_get(tree->sysvars, name); if (sysvar) { if (IP_BIT_ISSET(sysvar->flags, IPCOM_SYSVAR_FLAG_READONLY)) { retval = IPCOM_ERR_READONLY; goto leave; } else if (IP_BIT_ISFALSE(flags, IPCOM_SYSVAR_FLAG_OVERWRITE)) { retval = IPCOM_ERR_DUPLICATE; goto leave; } else { flags |= sysvar->flags & IPCOM_SYSVAR_FLAG_KERNEL; ipcom_hash_remove(tree->sysvars, sysvar); ipcom_free(sysvar); goto set; } } /* No current entry found and not allowed to create a new entry. */ if(IP_BIT_ISSET(flags, IPCOM_SYSVAR_FLAG_NOCREATE)) { retval = IPCOM_ERR_FAILED; goto leave; } /* Add the new sysvar. */ set: name_length = ipcom_strlen(name) + 1; value_length = ipcom_strlen(value) + 1; sysvar = ipcom_malloc(sizeof(Ipcom_sysvar_entry) + name_length + value_length); if(sysvar == IP_NULL) { retval = IPCOM_ERR_NO_MEMORY; goto leave; } sysvar->refcount = 1; sysvar->flags = flags; if (IP_BIT_ISFALSE(flags, IPCOM_SYSVAR_FLAG_INIT)) { tree->modified = IP_TRUE; sysvar->flags |= IPCOM_SYSVAR_FLAG_MODIFIED; } sysvar->name = (const char *)sysvar + sizeof(Ipcom_sysvar_entry); ipcom_memcpy((void *)sysvar->name, name, name_length); sysvar->value = sysvar->name + name_length; ipcom_memcpy((void *)sysvar->value, value, value_length); retval = ipcom_hash_add(tree->sysvars, sysvar); leave: return retval; /*lint !e429 Custodial pointer 'sysvar' has not been freed or returned */ }
/* *=========================================================================== * ipcom_waitif_gifaddr *=========================================================================== * Description: Get interface address. * Parameters: fd - socket descriptor * ifindex - Interface index. * domain - The address domain. * Returns: 0 = No address available, 1 = No address available, -1 = error. * */ IP_STATIC int ipcom_waitif_gifaddr(Ip_fd fd, int ifindex, int domain) { int ret = -1; switch (domain) { case IP_AF_INET: { struct Ip_ifreq ifreq; /* Get if name */ ipcom_memset(&ifreq, 0, sizeof(ifreq)); (void)ipcom_if_indextoname(ifindex, ifreq.ifr_name); /* Get main address */ if (ipcom_socketioctl(fd, IP_SIOCGIFADDR, &ifreq) < 0) { if (ipcom_errno != IP_ERRNO_EADDRNOTAVAIL && ipcom_errno != IP_ERRNO_ENXIO) { IPCOM_LOG1(ERR, "ipcom_waitif :: ipcom_socketioctl(SIOCGIFADDR) failed, errno = %d", ipcom_errno); } } else { struct Ip_in_addr network = ((struct Ip_sockaddr_in *)&ifreq.ip_ifr_addr)->sin_addr; if (network.s_addr != IP_INADDR_DEFAULT) { ret = 0; } } break; } #ifdef IPCOM_USE_INET6 case IP_AF_INET6: { int len = IPNET_WAITIF_MAXIF * sizeof(struct Ip_ifreq); char ifname[IP_IFNAMSIZ]; struct Ip_ifconf ifc; char *buf = IP_NULL; char *ptr; /* Get if name */ (void)ipcom_if_indextoname(ifindex, ifname); /* Get if data buffer */ if ((buf = ipcom_malloc(IPNET_WAITIF_MAXIF * sizeof(struct Ip_ifreq))) == IP_NULL) { IPCOM_LOG0(ERR, "ipcom_waitif :: Out of memory"); goto leave; } /* Enter buf in ifconf struct */ ifc.ifc_len = len; ifc.ip_ifc_buf = buf; if (ipcom_socketioctl(fd, IP_SIOCGIFCONF, &ifc) < 0) { IPCOM_LOG1(ERR, "ipcom_socketioctl(SIOCGIFCONF) failed, errno = %d\n", ipcom_errno); goto leave; } /* Loop for all interfaces */ for (ptr = buf; ptr < buf + ifc.ifc_len; ) { struct Ip_ifreq *ifr = (struct Ip_ifreq *)ptr; char *cptr; /* Calculate pointer to next if */ len = IP_MAX(sizeof(struct Ip_sockaddr_in), ifr->ip_ifr_addr.sa_len); ptr += sizeof(ifr->ifr_name) + len; if ((cptr = ipcom_strchr(ifr->ifr_name, ':')) != IP_NULL) { *cptr = '\0'; } /* Only for v6 addresses */ if (ipcom_strcmp(ifr->ifr_name, ifname) == 0 && ifr->ip_ifr_addr.sa_family == IP_AF_INET6) { struct Ip_sockaddr_in6 *in6 = (struct Ip_sockaddr_in6 *)&ifr->ip_ifr_addr; if (!IP_IN6_IS_ADDR_UNSPECIFIED(&in6->sin6_addr)) { ret = 0; break; } } } leave: if (buf != IP_NULL) { ipcom_free(buf); } break; } #endif /* IPCOM_USE_INET6 */ } return ret; }
/* *=========================================================================== * ipnet_nat_proxy_sip_payload_parse *=========================================================================== * Description: Parse SIP payload. * Parameters: appdata - pointer to application data. * applen - pointer to length of application data. * growspace - space available to extend application data. * param - pointer to proxy parameters. * newdata - pointer to pointer to new application data. * Returns: IP_TRUE = Packet modified. * IP_FALSE = Packet untouched. */ IP_STATIC Ip_bool ipnet_nat_proxy_sip_payload_parse(Ip_u8 *appdata, int *applen, int growspace, Ipnet_nat_proxy_param *param, Ip_u8 **newdata) { char *psipmsg = (char *)appdata; char *pcallid = IP_NULL; char *pendstr, *pstartstr, *psearch; Ip_bool retcode = IP_FALSE; int pos, sdpdatalen, searchlen, msgtype = 0; char tmpholder[50]; char laddrstr[20]; char gaddrstr[20]; char *pend = (char *)sipbuf + *applen - 1; char *sdplen_start, *sdplen_end, *sdp_end; int newlen, diff; if (param->incoming == IP_TRUE) { /* Incoming message*/ goto parseFalseExit; } if (param->inbound == IP_FALSE) { /* Outbound session */ if ((psipmsg = ipnet_nat_proxy_sip_outboundmsgtypecheck(psipmsg, &msgtype, *applen)) == IP_NULL) return IP_FALSE; /* not the message we're looking for */ } else { /* Inbound session */ if ((psipmsg = ipnet_nat_proxy_sip_inboundmsgtypecheck(psipmsg, &msgtype, *applen)) == IP_NULL) return IP_FALSE; /* not the message we're looking for */ } /* find the call-id field */ if (ipnet_nat_proxy_sip_keyfind(psipmsg, SIP_CALLID_STR, &pos, *applen - (psipmsg - (char *)appdata)) == IP_FALSE) { IPCOM_LOG0(ERR, "ipnet_nat_proxy_sip_payload_parse() :: no callid field"); return IP_FALSE; } /* get callid string */ pcallid = ipnet_nat_proxy_sip_callidstr(psipmsg + pos + SIP_TAG_TO_DATAPOS(SIP_CALLID_STR)); if (pcallid == IP_NULL) { IPCOM_LOG0(ERR, "ipnet_nat_proxy_sip_payload_parse() :: failed to parse callid string"); return IP_FALSE; } if (msgtype == SIP_MSG_TYPE_INVITE) { if (param->inbound == IP_FALSE) { /* Update the mapping timeout */ IPCOM_LOG1(DEBUG, "ipnet_nat_proxy_sip_payload_parse() :: setting mapping timeout to %d seconds", IPNET_NAT_SIP_ENTRY_INVITE_TIMEOUT); ipnet_nat_proxy_set_mapping_timeout(IPNET_NAT_SIP_ENTRY_INVITE_TIMEOUT, param->mapping); } else { /* ALG will not detect the ACK for inbound calls so use the INVITE response to set established timeout */ IPCOM_LOG1(DEBUG, "ipnet_nat_proxy_sip_payload_parse() :: setting mapping timeout to %d seconds", IPNET_NAT_SIP_ENTRY_ESTABLISHED_TIMEOUT); ipnet_nat_proxy_set_mapping_timeout(IPNET_NAT_SIP_ENTRY_ESTABLISHED_TIMEOUT, param->mapping); } } else if (msgtype == SIP_MSG_TYPE_ACK) { /* Update the mapping timeout */ IPCOM_LOG1(DEBUG, "ipnet_nat_proxy_sip_payload_parse() :: setting mapping timeout to %d seconds", IPNET_NAT_SIP_ENTRY_ESTABLISHED_TIMEOUT); ipnet_nat_proxy_set_mapping_timeout(IPNET_NAT_SIP_ENTRY_ESTABLISHED_TIMEOUT, param->mapping); } /* Copy the message to scratch buffer and set pointer */ if (*applen > (int)sizeof(sipbuf)) { IPCOM_LOG0(ERR, "ipnet_nat_proxy_sip_payload_parse() :: message to long"); goto parseFalseExit; } ipcom_memcpy(sipbuf, appdata, *applen); psipmsg = (char *)sipbuf + (psipmsg - (char *)appdata); /* first the via field * For response message, the Via field will not contain the private address. * The localAddrProcess() will check if the address is private. */ laddrstr[0] = gaddrstr[0] = 0; if (ipnet_nat_proxy_sip_keyfind(psipmsg, SIP_VIA_STR, &pos, (pend - psipmsg) + 1) == IP_TRUE) { /* advance to IP/Port string */ psipmsg += (pos + ipcom_strlen(SIP_VIA_STR) + SIP_VIA_FIELD_IPADDR_DIS); IPCOM_LOG0(DEBUG, "ipnet_nat_proxy_sip_payload_parse() :: parse via field"); psipmsg = ipnet_nat_proxy_sip_localaddrprocess(psipmsg, laddrstr, gaddrstr, pcallid, SIP_ADDRESS_PORT_STRING, param, &pend); if (psipmsg == IP_NULL) goto parseFalseExit; } /* find the contact field */ if (ipnet_nat_proxy_sip_keyfind (psipmsg, SIP_CONTACT_STR, &pos, (pend - psipmsg) + 1) == IP_TRUE) { /* advance to IP/Port string */ psipmsg += (pos + ipcom_strlen(SIP_CONTACT_STR) + SIP_CTAC_FIELD_IPADDR_DIS); IPCOM_LOG0(DEBUG, "ipnet_nat_proxy_sip_payload_parse() :: parse contact field"); psipmsg = ipnet_nat_proxy_sip_localaddrprocess(psipmsg, laddrstr, gaddrstr, pcallid, SIP_ADDRESS_PORT_STRING, param, &pend); if (psipmsg == IP_NULL) goto parseFalseExit; } /* exit if there isn't any private info in SIP message header */ if (laddrstr[0] == 0 || gaddrstr[0] == 0) goto parseFalseExit; /* When program reaches here, it indicates at least one place in the * packet should be modified. Use parseFalseExit only if it is an error */ /* find the Content-Type field */ if (ipnet_nat_proxy_sip_keyfind (psipmsg, SIP_CONTYPE_STR, &pos, (pend - psipmsg) + 1) == IP_FALSE) goto parseTrueExit; /* advance to start of data field */ psipmsg += (pos + SIP_TAG_TO_DATAPOS(SIP_CONTYPE_STR)); SIP_SKIP_SPACES(psipmsg); /*check the application/sdp type, if not, exit */ if (!SIP_IS_STRING_SAME(psipmsg, SIP_APPSDP_STR)) goto parseTrueExit; /* find the content length field */ if (ipnet_nat_proxy_sip_keyfind (psipmsg, SIP_CONTLEN_STR, &pos, (pend - psipmsg) + 1) == IP_FALSE) goto parseTrueExit; IPCOM_LOG0(DEBUG, "ipnet_nat_proxy_sip_payload_parse() :: parse Content-Length field"); /* reach to the content length field, advance to length data */ psipmsg += (pos + SIP_TAG_TO_DATAPOS(SIP_CONTLEN_STR)); SIP_SKIP_SPACES(psipmsg); sdpdatalen = ipcom_strtol(psipmsg, &pendstr, 10); IPCOM_LOG1(DEBUG, "ipnet_nat_proxy_sip_payload_parse() :: data length = %d", sdpdatalen); if (sdpdatalen == 0) goto parseTrueExit; /* store start and end of sdp datalength string as well as end of message */ sdplen_start = psipmsg; sdplen_end = pendstr; sdp_end = pend; /* advance to the start of SDP data */ if (ipnet_nat_proxy_sip_keyfind (psipmsg, IP_NULL, &pos, (pend - psipmsg) + 1) == IP_FALSE) { IPCOM_LOG0(DEBUG, "ipnet_nat_proxy_sip_payload_parse() :: Can't find header end mark"); goto parseTrueExit; } /* start of the SIP data field */ psipmsg += pos; searchlen = sdpdatalen; /* search the local IP address, and replace it with global address */ pstartstr = psipmsg; while (IP_TRUE) { psearch = ipnet_nat_proxy_sip_faststrsearch(laddrstr, ipcom_strlen(laddrstr), pstartstr, searchlen, IP_FALSE); if (psearch != IP_NULL) { IPCOM_LOG1(DEBUG, "ipnet_nat_proxy_sip_payload_parse() :: Local IP address in SDP: %s", laddrstr); if (ipnet_nat_proxy_sip_modmsg(gaddrstr, ipcom_strlen(gaddrstr), psearch, ipcom_strlen(laddrstr), &pend) < 0) { goto parseFalseExit; } searchlen = searchlen - (psearch + ipcom_strlen(gaddrstr) - pstartstr); pstartstr = psearch + ipcom_strlen(gaddrstr); } else break; } IPCOM_LOG1(DEBUG, "ipnet_nat_proxy_sip_payload_parse() :: the last search length %d", searchlen); /* search for the audio port */ if (ipnet_nat_proxy_sip_keyfind (psipmsg, SIP_AUDIO_STR, &pos, sdpdatalen) == IP_TRUE) { /* advance to the port field */ psipmsg += (pos + SIP_TAG_TO_DATAPOS(SIP_AUDIO_STR)); SIP_SKIP_SPACES(psipmsg); ipnet_nat_proxy_sip_localaddrprocess(psipmsg, laddrstr, gaddrstr, pcallid, SIP_PORT_STRING, param, &pend); } /* search for the audio control port */ if (ipnet_nat_proxy_sip_keyfind (psipmsg, SIP_RTCP_STR, &pos, sdpdatalen) == IP_TRUE) { /* advance to the port field */ psipmsg += (pos + SIP_TAG_TO_DATAPOS(SIP_RTCP_STR)); SIP_SKIP_SPACES(psipmsg); ipnet_nat_proxy_sip_localaddrprocess(psipmsg, laddrstr, gaddrstr, pcallid, SIP_PORT_STRING, param, &pend); } /* adjust the length node */ sdpdatalen += pend - sdp_end; ipcom_sprintf(tmpholder, "%d", sdpdatalen); if (ipnet_nat_proxy_sip_modmsg(tmpholder, ipcom_strlen(tmpholder), sdplen_start, sdplen_end - sdplen_start, &pend) < 0) { goto parseFalseExit; } parseTrueExit: /* Update application data with the modified buffer */ newlen = pend - (char *)sipbuf + 1; diff = newlen - *applen; if (diff > growspace) { /* Must allocate a new buffer */ *newdata = ipcom_malloc(*applen + diff); if (*newdata == IP_NULL) { IPCOM_LOG1(ERR, "ipnet_nat_proxy_sip_payload_parse() :: ipcom_malloc(%d) failed", *applen + diff); goto parseFalseExit; } ipcom_memcpy(*newdata, sipbuf, newlen); } else { /* Let the current buffer grow */ ipcom_memcpy(appdata, sipbuf, newlen); } *applen = newlen; IPCOM_LOG1(DEBUG, "ipnet_nat_proxy_sip_msg() :: the delta length = %d ", diff); retcode = IP_TRUE; parseFalseExit: if (msgtype == SIP_MSG_TYPE_BYE) ipnet_nat_proxy_sip_endmsgprocess(pcallid, param); if (pcallid) ipcom_free(pcallid); return retcode; }