/* *=========================================================================== * ipnet_gre_tmo *=========================================================================== * Description: Reassembly timeout handler. * Parameters: netif - A GRE tunnel interface. * Returns: 0 = success, <0 = error code. * */ IP_STATIC void ipnet_gre_seq_tmo(Ipnet_netif *netif) { Ipnet_pkt_gre *gre_hdr; Ipcom_pkt *pkt; Ipnet_gre_t *gre = netif->ipcom.pdrv; /* RFC 2890, chapter 2.2 ... Under no circumstances should a packet wait more that OUTOFORDER_TIMER milliseconds in the buffer. If a packet has been waiting that long, the receiver MUST immediately traverse the buffer in sorted order, decapsulating packets (and ignoring any sequence number gaps) until there are no more packets in the buffer that have been waiting longer than OUTOFORDER_TIMER milliseconds. The "last successfully decapsulated sequence number" should then be set to the last packet so decapsulated. ... */ pkt = ipcom_pqueue_get_next(gre->reassembly_queue); ip_assert(pkt != IP_NULL); gre->recv_seqnum = IP_GET_NTOHL(&pkt->data[pkt->start]); do { pkt = ipcom_pqueue_remove_next(gre->reassembly_queue); /* Discard the sequence number option and make place for a GRE header */ pkt->start += IPNET_GRE_OPT_SEQNUM_SIZE - IPNET_GRE_HDR_SIZE; gre_hdr = (Ipnet_pkt_gre *)&pkt->data[pkt->start]; gre_hdr->flags_reserved0_ver = 0; if (IP_BIT_ISSET(pkt->flags, IPCOM_PKT_FLAG_IPV4)) gre_hdr->protocol_type = ip_htons(0x0800); else if (IP_BIT_ISSET(pkt->flags, IPCOM_PKT_FLAG_IPV6)) gre_hdr->protocol_type = ip_htons(0x86DD); (void) ipnet_gre_input(netif, pkt); ++gre->recv_seqnum; } while (IP_NULL != (pkt = ipcom_pqueue_get_next(gre->reassembly_queue)) && gre->recv_seqnum == IP_GET_NTOHL(&pkt->data[pkt->start])); if (pkt != IP_NULL) { Ip_u32 timeout = IPNET_PKT_GET_TIMEOUT_ABS(pkt); /* More out of order packets waiting, schedule a timeout of the time remaining until this packet sequence timer timeouts */ (void) ipnet_timeout_schedule((timeout < ipnet->msec_now ? 0 : timeout - ipnet->msec_now), (Ipnet_timeout_handler) ipnet_gre_seq_tmo, netif, &gre->reassembly_tmo); } }
/* *=========================================================================== * ipnet_gre_destroy *=========================================================================== * Description: Destroy the GRE tunnel. * Parameters: netif - A GRE tunnel interface. * Returns: * */ IP_GLOBAL void ipnet_gre_destroy(Ipnet_netif *netif) { #ifdef IPNET_USE_RFC2890 Ipnet_gre_t *gre = netif->ipcom.pdrv; Ipcom_pkt *pkt; if (gre != IP_NULL) { if (gre->reassembly_queue != IP_NULL) { while (IP_NULL != (pkt = ipcom_pqueue_remove_next(gre->reassembly_queue))) ipcom_pkt_free(pkt); ipcom_pqueue_delete(gre->reassembly_queue); } ipnet_timeout_cancel(gre->reassembly_tmo); ipcom_free(gre); } #endif /* IPNET_USE_RFC2890 */ }
/* *=========================================================================== * ipcom_sysvar_for_each *=========================================================================== * Description: * Parameters: * Returns: */ IP_PUBLIC Ip_err ipcom_sysvar_for_each(const char *name, Ipcom_sysvar_for_each cb_func, void *cookie) { Ipcom_sysvar_entry *sysvar; Ipcom_sysvar_tree *tree; Ip_size_t namelen = 0; Ip_err retval; Ipcom_pqueue *pq; retval = ipcom_once(&ipcom_sysvar_once, ipcom_sysvar_init, IP_NULL); if (retval != IPCOM_SUCCESS) return retval; if (name) { namelen = ipcom_strlen(name); if (name[namelen-1] == '*') namelen--; /* ignore trailing wildcard sign */ } pq = ipcom_pqueue_new((Ipcom_pqueue_cmp_func)ipcom_sysvar_pqueue_cmp, ipcom_pqueue_nop_store_index); if (pq == IP_NULL) return IPCOM_ERR_NO_MEMORY; IPCOM_CODE_LOCK(); tree = ipcom_sysvar_tree_get(-1); if (tree == IP_NULL) { ipcom_pqueue_delete(pq); IPCOM_CODE_UNLOCK(); return IPCOM_ERR_NO_MEMORY; } /* Add all sysvars to the priority queue so they can be extracted sorted in lexicographical order */ ipcom_hash_for_each(tree->sysvars, (Ipcom_hash_foreach_cb_func)ipcom_sysvar_pqueue_insert_cb, pq); while (IP_NULL != (sysvar = ipcom_pqueue_remove_next(pq))) { if (name == IP_NULL || ipcom_strncmp(sysvar->name, name, namelen) == 0) { IPCOM_CODE_UNLOCK(); (void)cb_func(sysvar->name, sysvar->value, sysvar->flags, cookie); IPCOM_CODE_LOCK(); } ipcom_sysvar_release(tree, sysvar); } ipcom_pqueue_delete(pq); ipcom_sysvar_tree_done(tree); IPCOM_CODE_UNLOCK(); #ifdef IP_PORT_OSE5_DISABLED return ipcom_sysvar_for_each_ose5(name, cb_func, cookie); #else return IPCOM_SUCCESS; #endif }