uint32_t RIP_init (void) { /* Body */ RIP_CFG_STRUCT_PTR cfg = RTCS_getcfg(RIP); uint32_t err; if (RTCS_getcfg(RIP)) return RTCS_OK; /* allocate the memory */ cfg = RTCS_mem_alloc_zero(sizeof(*cfg)); if (!cfg) return RTCSERR_OUT_OF_MEMORY; /* bind the udp port */ err = UDP_openbind_internal(IPPORT_RIP, RIP_service, &cfg->UCB); if (err){ _mem_free(cfg); return err; } RTCS_setcfg(RIP, cfg); ROUTE_register(&RIP_routefn); /* Start the retransmission timer to start sending immediately */ cfg->TIMER_PERIODIC.TIME = 0; cfg->TIMER_PERIODIC.EVENT = RIP_expire_periodic; cfg->TIMER_PERIODIC.PRIVATE = NULL; TCPIP_Event_add(&cfg->TIMER_PERIODIC); /* probe all the interfaces now to build the route table faster */ err = RIP_send_req(); return RTCS_OK; } /* Endbody */
static uint32_t RIP_send_resp( uint32_t rip_vers, /* [IN] the rip version */ uint32_t onlyChangeF /* [IN] TRUE if only the changed routes are sent */ ) { /* Body */ RIP_CFG_STRUCT_PTR ripcfg = RTCS_getcfg(RIP); IP_CFG_STRUCT_PTR IP_cfg_ptr = RTCS_getcfg(IP); struct RIP_send_resp_struct testdata; testdata.nb_try = 0; testdata.nb_fail = 0; testdata.localhost = RTCS_IF_LOCALHOST_PRV; testdata.rip_vers = rip_vers; testdata.onlyChangeF = onlyChangeF; if (rip_vers == RIP_V1) testdata.ipdest = INADDR_BROADCAST; else testdata.ipdest = INADDR_RIP_GROUP; IPRADIX_walk(&IP_cfg_ptr->ROUTE_ROOT.NODE, RIP_send_resp_test, &testdata); /* test if the routes has been all advertized (nbFail==0 && nbTry > 0)*/ if (testdata.nb_fail) return (uint32_t)RTCS_ERROR; if (testdata.nb_try == 0) return RTCS_OK; /* clear the flags only if required */ if (ripcfg->RT_CHANGED_F == FALSE) return RTCS_OK; /* update the flag */ ripcfg->RT_CHANGED_F = FALSE; /* clear the flag in all changed route entries */ IPRADIX_walk(&IP_cfg_ptr->ROUTE_ROOT.NODE, RIP_send_resp_test2, NULL); return RTCS_OK; } /* Endbody */
void RIP_new_bindif ( IP_ROUTE_DIRECT_PTR bindif /* [IN] the outgoing binded interface */ ) { /* Body */ RIP_CFG_STRUCT_PTR cfg = RTCS_getcfg(RIP); IP_CFG_STRUCT_PTR IP_cfg_ptr = RTCS_getcfg(IP); ip_mreq mreq; if (!cfg) { return; } /* Endif */ /* do not init the routing on the local interface */ if (bindif->NETIF == RTCS_IF_LOCALHOST_PRV) { return; } /* Endif */ /* init the multicast group */ mreq.imr_multiaddr.s_addr = INADDR_RIP_GROUP; mreq.imr_interface.s_addr = bindif->ADDRESS; IGMP_join_group(&cfg->UCB->MCB_PTR, &mreq, &cfg->UCB->IGMP_LEAVEALL); if (bindif->NETIF) { RIP_send_req_ipif(bindif->NETIF); } else { RIP_send_req_ipif(bindif->DESTIF); } /* Endif */ } /* Endbody */
static void RIP_create_rt( RTCSPCB_PTR pcb, /* [IN] incoming packet */ RIP_ENTRY_PTR rte, uint8_t rip_vers ) { /* Body */ uint32_t nmetric= RIP_cpu_metric(pcb,mqx_ntohl(rte->METRIC)); RIP_CFG_STRUCT_PTR ripcfg = RTCS_getcfg(RIP); IP_CFG_STRUCT_PTR IP_cfg_ptr = RTCS_getcfg(IP); IP_ROUTE_INDIRECT_PTR gate; _ip_address network, netmask; gate = RTCS_part_alloc(IP_cfg_ptr->GATE_PARTID); if (!gate) return; _mem_zero(gate, sizeof(*gate)); /* init the route */ RIP_adopt_rt(pcb, gate, rte, nmetric, &network, &netmask); /* insert it in the table */ ROUTE_insert(gate, network, netmask); /* flag it as changed */ ripcfg->RT_CHANGED_F = TRUE; } /* Endbody */
void DNAT_get_next_rule_internal ( DNAT_PARM_PTR dparm_ptr /* [IN] */ ) { /* Body */ NAT_CFG_STRUCT_PTR nat_cfg_ptr = RTCS_getcfg(NAT); DNAT_ELEMENT_STRUCT_PTR prev_element_ptr, next_element_ptr; if (nat_cfg_ptr == NULL) { RTCSCMD_complete(dparm_ptr, RTCSERR_NAT_NOT_INITIALIZED); return; } prev_element_ptr = NULL; next_element_ptr = (DNAT_ELEMENT_STRUCT_PTR) _queue_head(&nat_cfg_ptr->RULE_QUEUE); while ((next_element_ptr != NULL) && (next_element_ptr->RULE.PRIORITY >= dparm_ptr->RULE.PRIORITY)) { prev_element_ptr = next_element_ptr; next_element_ptr = (DNAT_ELEMENT_STRUCT_PTR) _queue_next(&nat_cfg_ptr->RULE_QUEUE, &prev_element_ptr->ELEMENT); } if (next_element_ptr == NULL) { RTCSCMD_complete(dparm_ptr, RTCSERR_NAT_END_OF_RULES); } else { dparm_ptr->RULE = next_element_ptr->RULE; RTCSCMD_complete(dparm_ptr, RTCS_OK); } }/* Endbody */
void DNAT_delete_rule_internal ( DNAT_PARM_PTR dparm_ptr /* [IN] */ ) { /* Body */ NAT_CFG_STRUCT_PTR nat_cfg_ptr = RTCS_getcfg(NAT); DNAT_ELEMENT_STRUCT_PTR element_ptr; uint32_t priority = dparm_ptr->RULE.PRIORITY; if (nat_cfg_ptr == NULL) { RTCSCMD_complete(dparm_ptr, RTCSERR_NAT_NOT_INITIALIZED); return; } element_ptr = (DNAT_ELEMENT_STRUCT_PTR) _queue_head(&nat_cfg_ptr->RULE_QUEUE); while (element_ptr != NULL) { if (element_ptr->RULE.PRIORITY == priority) { _queue_unlink(&nat_cfg_ptr->RULE_QUEUE, &element_ptr->ELEMENT); _mem_free((void *)element_ptr); RTCSCMD_complete(dparm_ptr, RTCS_OK); return; } element_ptr = (DNAT_ELEMENT_STRUCT_PTR) _queue_next(&nat_cfg_ptr->RULE_QUEUE, &element_ptr->ELEMENT); } RTCSCMD_complete(dparm_ptr, RTCSERR_NAT_INVALID_RULE); } /* Endbody */
void NAT_config_ports ( NAT_PORTS_STRUCT_PTR nat_ports_ptr /* [IN] New values for port ranges */ ) { /* Body */ NAT_CFG_STRUCT_PTR nat_cfg_ptr = RTCS_getcfg(NAT); if (nat_ports_ptr->port_min) { if (nat_ports_ptr->port_min > nat_cfg_ptr->PORT_MAX) { nat_cfg_ptr->PORT_MIN = nat_cfg_ptr->PORT_MAX; } else { nat_cfg_ptr->PORT_MIN = nat_ports_ptr->port_min; } /* Endif */ } /* Endif */ if (nat_ports_ptr->port_max) { if (nat_ports_ptr->port_max < nat_cfg_ptr->PORT_MIN) { nat_cfg_ptr->PORT_MAX = nat_cfg_ptr->PORT_MIN; } else { nat_cfg_ptr->PORT_MAX = nat_ports_ptr->port_max; } /* Endif */ /* Fix the last used port numbers so that they don't exceed max */ nat_cfg_ptr->TCP_PORT = nat_cfg_ptr->PORT_MIN; nat_cfg_ptr->UDP_PORT = nat_cfg_ptr->PORT_MIN; nat_cfg_ptr->ICMP_ID = nat_cfg_ptr->PORT_MIN; } /* Endif */ } /* Endbody */
void NAT_remove_network_internal ( NAT_PARM_PTR parm_ptr /* [IN] Initialization parameters */ ) { /* Body */ NAT_CFG_STRUCT_PTR nat_cfg_ptr = RTCS_getcfg(NAT); uint_32 error; // Make sure NAT is already up if (nat_cfg_ptr == NULL) { error = RTCSERR_NAT_NOT_INITIALIZED; /* ** Make sure the netmask is valid. We use the fact that ** (x & x+1) == 0 <=> x = 2^n-1. */ } else if (~parm_ptr->IP_MASK & (~parm_ptr->IP_MASK + 1)) { error = RTCSERR_INVALID_PARAMETER; /* Make sure other parameters have been supplied */ } else if (!parm_ptr->IP_PRV) { error = RTCSERR_INVALID_PARAMETER; } else { // Try to remove the private network error=NAT_remove_private_network(&nat_cfg_ptr->PRIVATE_NETWORKS, parm_ptr->IP_PRV, parm_ptr->IP_MASK); } RTCSCMD_complete(parm_ptr, error); } /* Endbody */
boolean IGMP_is_member ( MC_MEMBER_PTR _PTR_ phead, /* [IN] head of MCB list */ IP_IF_PTR ipif, /* [IN] the incoming interface */ _ip_address multiaddr /* [IN] the multicast ip */ ) { /* Body */ IP_CFG_STRUCT_PTR IP_cfg_ptr = RTCS_getcfg(IP); struct IGMP_is_member_test_struct testdata; if (!*phead) { return FALSE; } /* Endif */ testdata.multiaddr = multiaddr; testdata.ipif = ipif; testdata.phead = phead; testdata.result = FALSE; /* ** Scan all directly connected networks, to have all the ip ** address of this interface */ IPRADIX_walk(&IP_cfg_ptr->ROUTE_ROOT.NODE, IGMP_is_member_test, &testdata); return testdata.result; } /* Endbody */
uint_32 ROUTE_remove ( IP_ROUTE_INDIRECT_PTR gate /* [IN] the route entry to remove */ ) { /* Body */ IP_CFG_STRUCT_PTR IP_cfg_ptr = RTCS_getcfg(IP); IP_ROUTE_FN_PTR fn; struct ROUTE_remove_struct testdata; fn = IP_cfg_ptr->ROUTE_FN; while (fn) { fn->REM_RT(gate); fn = fn->NEXT; } /* Endwhile */ testdata.gate = gate; testdata.network = INADDR_ANY; testdata.netmask = INADDR_ANY; testdata.found = FALSE; IPRADIX_walk(&IP_cfg_ptr->ROUTE_ROOT.NODE, ROUTE_remove_test, &testdata); if (testdata.found) { /* Start CR 1135 */ IP_route_remove_indirect(gate->GATEWAY, testdata.netmask, testdata.network, gate->FLAGS, gate->METRIC); /* End CR 1135 */ } /* Endif */ return RTCS_OK; } /* Endbody */
void NAT_config_timeouts ( NAT_TIMEOUTS_STRUCT_PTR nat_timeouts_ptr /* [IN] New values for timeouts */ ) { /* Body */ NAT_CFG_STRUCT_PTR nat_cfg_ptr = RTCS_getcfg(NAT); if (nat_timeouts_ptr->timeout_tcp) { nat_cfg_ptr->TIMEOUT_TCP = nat_timeouts_ptr->timeout_tcp; NAT_tout_max(&nat_cfg_ptr->TCP_TOUT, nat_cfg_ptr->TIMEOUT_TCP); } /* Endif */ if (nat_timeouts_ptr->timeout_fin) { nat_cfg_ptr->TIMEOUT_FIN = nat_timeouts_ptr->timeout_fin; NAT_tout_max(&nat_cfg_ptr->FIN_TOUT, nat_cfg_ptr->TIMEOUT_FIN); } /* Endif */ if (nat_timeouts_ptr->timeout_udp) { nat_cfg_ptr->TIMEOUT_UDP = nat_timeouts_ptr->timeout_udp; NAT_tout_max(&nat_cfg_ptr->UDP_TOUT, nat_cfg_ptr->TIMEOUT_UDP); } /* Endif */ if (nat_timeouts_ptr->timeout_icmp) { nat_cfg_ptr->TIMEOUT_ICMP = nat_timeouts_ptr->timeout_icmp; NAT_tout_max(&nat_cfg_ptr->ICMP_TOUT, nat_cfg_ptr->TIMEOUT_ICMP); } /* Endif */ } /* Endbody */
void IP_route_remove_virtual ( _ip_address address, /* IP address of route to remove */ _ip_address netmask, /* IP netmask of route to remove */ _ip_address source, /* IP of interface */ _ip_address source_net, /* Allowed source network */ _ip_address source_mask, /* Allowed source source netmak */ IP_IF_PTR netif /* pointer to the route interface */ ) { /* Body */ IP_CFG_STRUCT_PTR IP_cfg_ptr = RTCS_getcfg(IP); struct ip_route_remove_virtual removedata; struct ip_route_delete deldata; removedata.source = source; removedata.source_net = source_net; removedata.source_mask = source_mask; removedata.netif = netif; deldata.data = &removedata; deldata.index = 2; deldata.test = IP_route_delete_virtual_test; deldata.fn = IP_cfg_ptr->ROUTE_FN; IPRADIX_insert(&IP_cfg_ptr->ROUTE_ROOT.NODE, address & netmask, netmask, 0, IP_route_delete, &deldata); } /* Endbody */
void IP_route_remove_indirect ( _ip_address gateway, /* Gateway address */ _ip_address netmask, /* Network mask */ _ip_address network, /* Network address */ uint_32 flag, /* [IN] RTF_* */ uint_16 metric /* [IN] the route metric [0,65535] */ ) { /* Body */ IP_CFG_STRUCT_PTR IP_cfg_ptr = RTCS_getcfg(IP); struct ip_route_delete deldata; struct { _ip_address gate; uint_32 flag; uint_16 metric; } testdata; if (gateway) { testdata.gate = gateway; testdata.flag = flag; testdata.metric = metric; deldata.index = 1; deldata.data = &testdata; deldata.test = IP_route_delete_indirect_test; deldata.fn = IP_cfg_ptr->ROUTE_FN; IPRADIX_insert(&IP_cfg_ptr->ROUTE_ROOT.NODE, network & netmask, netmask, 0, IP_route_delete, &deldata); } else { IPRADIX_insert(&IP_cfg_ptr->ROUTE_ROOT.NODE, network & netmask, netmask, 0, IP_route_delete_indirect_all, &gateway); } /* Endif */ } /* Endbody */
static uint32_t RIP_send_resp_ipif ( IP_IF_PTR ipif, /* [IN] the destination interface */ _ip_address ipdest, /* [IN] the destination ip address */ uint16_t portdst, /* [IN] the destination port */ uint32_t rip_vers,/* [IN] the rip version */ uint32_t onlyChangeF /* [IN] TRUE if only the changed routes are sent */ ) { /* Body */ IP_CFG_STRUCT_PTR IP_cfg_ptr = RTCS_getcfg(IP); struct RIP_send_resp_ipif_struct testdata; testdata.ipif = ipif; testdata.ipdest = ipdest; testdata.portdst = portdst; testdata.onlyChangeF = onlyChangeF; testdata.rip_vers = rip_vers; testdata.pkt = NULL; testdata.curs = NULL; IPRADIX_walk(&IP_cfg_ptr->ROUTE_ROOT.NODE, RIP_send_resp_ipif_test, &testdata); /* if the packet is empty, dont send it */ if (testdata.curs-testdata.pkt == sizeof(RIP_HEADER)){ _mem_free(testdata.pkt); } else { /* send the packet */ RIP_send_pkt(ipif, ipdest, portdst, testdata.pkt, testdata.curs - testdata.pkt); } /* Endif */ return RTCS_OK; } /* Endbody */
void RIP_init_static_rt ( IP_ROUTE_INDIRECT_PTR gate, /* [IN] the route to init */ uint16_t metric /* [IN] metric of this route. [0,65535] */ ) { /* Body */ RIP_CFG_STRUCT_PTR ripcfg = RTCS_getcfg(RIP); _mem_zero(&gate->RIP, sizeof(gate->RIP)); gate->RIP.METRIC = metric / 4096; /* sanity check */ if (gate->RIP.METRIC < RIP_MIN_METRIC) { gate->RIP.METRIC = RIP_MIN_METRIC; } /* Endif */ if (gate->RIP.METRIC > RIP_MAX_METRIC) { gate->RIP.METRIC = RIP_MAX_METRIC; } /* Endif */ /* no src interface for a static route */ gate->RIP.IPIFSRC = NULL; gate->RIP.CHANGED_F = TRUE; if (ripcfg){ ripcfg->RT_CHANGED_F = TRUE; RIP_trig_upd(); } } /* Endbody */
static void IGMP_service ( RTCSPCB_PTR pcb, /* [IN/OUT] incoming packet */ void *dummy /* [IN] not used */ ) { /* Body */ IGMP_HEADER_PTR header; IGMP_CFG_STRUCT_PTR IGMP_cfg_ptr; IGMP_cfg_ptr = RTCS_getcfg(IGMP); IF_IGMP_STATS_ENABLED(IGMP_cfg_ptr->STATS.COMMON.ST_RX_TOTAL++); header = (IGMP_HEADER_PTR)RTCSPCB_DATA(pcb); /* check if length >= sizeof(IGMP_HEADER) */ if (RTCSPCB_SIZE(pcb) < sizeof(IGMP_HEADER)) { IF_IGMP_STATS_ENABLED(IGMP_cfg_ptr->STATS.COMMON.ST_RX_DISCARDED++); IF_IGMP_STATS_ENABLED(IGMP_cfg_ptr->STATS.ST_RX_SMALL_DGRAM++); RTCSLOG_PCB_FREE(pcb, RTCSERR_IGMP_BAD_HEADER); RTCSPCB_free(pcb); return; } /* Endif */ /* Verify the checksum */ if (IP_Sum_PCB(0, pcb) != 0xFFFF) { IF_IGMP_STATS_ENABLED(IGMP_cfg_ptr->STATS.COMMON.ST_RX_DISCARDED++); IF_IGMP_STATS_ENABLED(IGMP_cfg_ptr->STATS.ST_RX_BAD_CHECKSUM++); RTCSLOG_PCB_FREE(pcb, RTCSERR_IGMP_BAD_CHECKSUM); RTCSPCB_free(pcb); return; } /* Endif */ if (mqx_ntohc(header->TYPE) == IGMPTYPE_V2_REPORT) { RTCSLOG_PCB_READ(pcb, RTCS_LOGCTRL_PROTO(IPPROTO_IGMP), 2); } else { RTCSLOG_PCB_READ(pcb, RTCS_LOGCTRL_PROTO(IPPROTO_IGMP), 1); } /* Endif */ switch (mqx_ntohc(header->TYPE)) { case IGMPTYPE_QUERY: IF_IGMP_STATS_ENABLED(IGMP_cfg_ptr->STATS.ST_RX_QUERY++); IGMP_rcv_query(pcb->IFSRC, mqx_ntohl(header->GROUP_ADDRESS), mqx_ntohc(header->MAX_RESP_TIME)); break; case IGMPTYPE_V1_REPORT: case IGMPTYPE_V2_REPORT: IF_IGMP_STATS_ENABLED(IGMP_cfg_ptr->STATS.ST_RX_REPORT++); IGMP_rcv_report(pcb->IFSRC, mqx_ntohl(header->GROUP_ADDRESS)); break; default: IF_IGMP_STATS_ENABLED(IGMP_cfg_ptr->STATS.ST_RX_BAD_TYPE++); } /* Endswitch */ RTCSLOG_PCB_FREE(pcb, RTCS_OK); RTCSPCB_free(pcb); } /* Endbody */
static uint32_t RIP_send_pkt( IP_IF_PTR ipif, /* [IN] the outgoing interface */ _ip_address ipdst, /* [IN] the destination ip */ uint16_t portdst,/* [IN] the destination port */ unsigned char *data, /* [IN] the data to send */ uint32_t len /* [IN] the length of data to send */ ) { /* Body */ RTCSPCB_PTR pcb; RIP_CFG_STRUCT_PTR ripcfg = RTCS_getcfg(RIP); RIP_HEADER_PTR hd = (RIP_HEADER_PTR)data; uint32_t err; _ip_address ipsrc = IP_get_ipif_addr(ipif); if (ipsrc == INADDR_ANY) { _mem_free(data); return RTCS_OK; } /* Endif */ /* Allocate a PCB */ pcb = RTCSPCB_alloc_send(); if (pcb == NULL) { _mem_free(data); return RTCSERR_PCB_ALLOC; } /* Endif */ //RTCSLOG_PCB_ALLOC(pcb); /* add my data in the pcb */ err = RTCSPCB_append_fragment_autofree(pcb, len, data); if (err) { _mem_free(data); RTCSLOG_PCB_FREE(pcb, err); RTCSPCB_free(pcb); return err; } /* Endif */ RTCSLOG_PCB_WRITE(pcb, RTCS_LOGCTRL_PORT(IPPORT_RIP), mqx_ntohc(hd->VERSION)); /* dont advertize in limited broadcast but in ip broadcast */ if (ipdst == INADDR_BROADCAST){ _ip_address netmask; ipdst = IP_get_ipif_addr(ipif); /* Get IP address of interface */ IP_get_netmask(ipif, ipdst, &netmask); /* Get netmask */ ipdst = ipdst | ~netmask; } /* Endif */ /* send it */ /* use a flag to prevent the broadcast/multicast packet from ** looping back to us. */ return UDP_send_internal(ripcfg->UCB, ipsrc, ipdst, portdst, pcb, RTCS_MSG_NOLOOP); } /* Endbody */
uint_32 IP_route_local ( RTCSPCB_PTR pcb, /* [IN] the packet to send */ _ip_address ipdest /* [IN] the ultimate destination */ ) { /* Body */ IP_CFG_STRUCT_PTR IP_cfg_ptr = RTCS_getcfg(IP); struct ip_route_local_test testdata; /* ** RFC 2131 says: ** "In the case of a client using DHCP for initial configuration (before ** the client's TCP/IP software has been completely configured), DHCP ** requires creative use of the client's TCP/IP software and liberal ** interpretation of RFC 1122. The TCP/IP software SHOULD accept and ** forward to the IP layer any IP packets delivered to the client's ** hardware address before the IP address is configured." ** ** So if the broadcast flag is disabled, we check, and if the packet's ** source interface is not bound, we send the packet to IF_LOCALHOST. ** This is paired with the same test in ip.c:IP_service(), which sends ** the packet here. */ if ((ipdest == INADDR_BROADCAST) || IN_MULTICAST(ipdest) || (!_DHCP_broadcast && (IP_get_ipif_addr(pcb->IFSRC) == INADDR_ANY))) { /* Accept broadcasts and multicasts and unbound unicasts */ testdata.ifdest = IP_cfg_ptr->IF_LOCALHOST; } else { /* If unicast, check routing table */ testdata.ifdest = NULL; testdata.ipdest = ipdest; testdata.pcb = pcb; IPRADIX_findbest(&IP_cfg_ptr->ROUTE_ROOT.NODE, ipdest, IP_route_local_test, &testdata); } /* Endif */ /* Send the packet to the interface. */ if (testdata.ifdest) { return IP_send_dgram(IP_cfg_ptr->IF_LOCALHOST, pcb, 0, ipdest, ipdest, 0, NULL); } /* Endif */ /* No interface was found. Discard the packet */ IF_IP_STATS_ENABLED(IP_cfg_ptr->STATS.COMMON.ST_RX_DISCARDED++); IF_IP_STATS_ENABLED(IP_cfg_ptr->STATS.ST_RX_ADDR_ERRORS++); RTCSLOG_PCB_FREE(pcb, RTCSERR_IP_UNREACH); RTCSPCB_free(pcb); return RTCSERR_IP_UNREACH; } /* Endbody */
void ROUTE_register ( IP_ROUTE_FN_PTR fn ) { /* Body */ IP_CFG_STRUCT_PTR IP_cfg_ptr = RTCS_getcfg( IP ); fn->NEXT = IP_cfg_ptr->ROUTE_FN; IP_cfg_ptr->ROUTE_FN = fn; } /* Endbody */
static void RIP_update_rt( IP_ROUTE_INDIRECT_PTR gate, RTCSPCB_PTR pcb, /* [IN] incoming packet */ RIP_ENTRY_PTR rte ) { /* Body */ RIP_CFG_STRUCT_PTR ripcfg = RTCS_getcfg(RIP); uint32_t nmetric= RIP_cpu_metric(pcb,mqx_ntohl(rte->METRIC)); _ip_address ipsrc = IP_source(pcb); /* dont modify a static route */ if (gate->FLAGS & RTF_STATIC) return; /* ** if the source isnt "authoritative" (i.e. not the current ** gateway) and have a bigger metric, ignore the route. */ if (ipsrc != gate->GATEWAY && nmetric > gate->RIP.METRIC) return; /* ** if the source isnt "authoritative" (i.e. not the current ** gateway) and have a equal metric and will "soon" timed out, ** update the route entry. */ if (ipsrc != gate->GATEWAY && nmetric == gate->RIP.METRIC){ uint32_t timeout = TCPIP_Event_expire(&gate->RIP.TIMEOUT); /* if the both metrics are infinite, dont update the route. */ if (nmetric >= RIP_MAX_METRIC) return; if (timeout > RIP_ALMOST_EXPIRED_TIME) return; } /* cancel the timeout/gc timer */ TCPIP_Event_cancel(&gate->RIP.TIMEOUT); /* If the sources and the metrics are equal, just reinit the timer. */ if (ipsrc == gate->GATEWAY && gate->RIP.METRIC == nmetric){ if (nmetric < RIP_MAX_METRIC){ RIP_init_timer(gate, gate->RIP.METRIC); } return; } /* ** Reinit the route and the timer. ipsrc no longer needed, just used ** to fill all of the function parameters */ RIP_adopt_rt(pcb, gate, rte, nmetric, &ipsrc, &ipsrc); /* flag it as changed */ ripcfg->RT_CHANGED_F = TRUE; } /* Endbody */
uint_32 IP_route_add_virtual ( _ip_address address, /* Destination address */ _ip_address netmask, /* Mask for the address parameter */ _ip_address source, /* Source address for interface */ _ip_address source_net, /* Allowed source network */ _ip_address source_mask, /* Allowes source network mask */ IP_IF_PTR destif, /* Interface for outgoing packets */ pointer data /* Route information */ ) { /* Body */ #if RTCSCFG_ENABLE_VIRTUAL_ROUTES IP_CFG_STRUCT_PTR IP_cfg_ptr = RTCS_getcfg(IP); IP_ROUTE_VIRTUAL_PTR route; struct ip_route_insert insdata; IP_ROUTE_FN_PTR fn; route = RTCS_part_alloc(IP_cfg_ptr->VIRTUAL_PARTID); if (!route) { return RTCSERR_IP_VIRTUAL_ALLOC; } /* Endif */ route->ADDRESS = source; route->IS_DIRECT = NULL; route->DESTIF = destif; route->FLAGS = RTF_STATIC | RTF_UP; route->SOURCE_NET = source_net; route->SOURCE_MASK = source_mask; route->DATA = data; insdata.error = RTCSERR_IP_VIRTUAL_ALLOC; insdata.route = route; insdata.index = 2; insdata.sort = NULL; IPRADIX_insert(&IP_cfg_ptr->ROUTE_ROOT.NODE, address & netmask, netmask, IP_cfg_ptr->RADIX_PARTID, IP_route_insert, &insdata); if (insdata.error) { RTCS_part_free(route); } else if (!~netmask) { fn = IP_cfg_ptr->ROUTE_FN; while (fn) { fn->INIT_RT((IP_ROUTE_INDIRECT_PTR)route, 0); fn = fn->NEXT; } /* Endwhile */ } /* Endif */ return insdata.error; #else return RTCSERR_IP_VIRTUAL_ALLOC; #endif } /* Endbody */
void RTCS_walk_route(void) { /* Body */ IP_CFG_STRUCT_PTR IP_cfg_ptr = RTCS_getcfg( IP ); struct ROUTE_get_struct testdata; testdata.netaddr = 0; testdata.netmask = 0; testdata.gate = NULL; IPRADIX_walk(&IP_cfg_ptr->ROUTE_ROOT.NODE, ROUTE_walk_test, &testdata); } /* Endbody */
static uint32_t RIP_send_req( void ) { /* Body */ IP_CFG_STRUCT_PTR IP_cfg_ptr = RTCS_getcfg(IP); struct RIP_send_req_struct testdata; testdata.localhost = RTCS_IF_LOCALHOST_PRV; IPRADIX_walk(&IP_cfg_ptr->ROUTE_ROOT.NODE, RIP_send_req_test, &testdata); return RTCS_OK; } /* Endbody */
void DNAT_add_rule_internal ( DNAT_PARM_PTR dparm_ptr /* [IN] */ ) { /* Body */ NAT_CFG_STRUCT_PTR nat_cfg_ptr = RTCS_getcfg(NAT); DNAT_ELEMENT_STRUCT_PTR new_element_ptr, prev_element_ptr, next_element_ptr; if (nat_cfg_ptr == NULL) { RTCSCMD_complete(dparm_ptr, RTCSERR_NAT_NOT_INITIALIZED); return; } if (! NAT_is_private_addr(&nat_cfg_ptr->PRIVATE_NETWORKS,dparm_ptr->RULE.PRIVATE_IP)) { RTCSCMD_complete(dparm_ptr, RTCSERR_NAT_INVALID_PRIVATE_ADDRESS); return; } if (IP_is_local(NULL, dparm_ptr->RULE.PRIVATE_IP)) { RTCSCMD_complete(dparm_ptr, RTCSERR_NAT_INVALID_PRIVATE_ADDRESS); return; } prev_element_ptr = NULL; next_element_ptr = (DNAT_ELEMENT_STRUCT_PTR) _queue_head(&nat_cfg_ptr->RULE_QUEUE); while ((next_element_ptr != NULL) && (next_element_ptr->RULE.PRIORITY > dparm_ptr->RULE.PRIORITY)) { prev_element_ptr = next_element_ptr; next_element_ptr = (DNAT_ELEMENT_STRUCT_PTR) _queue_next(&nat_cfg_ptr->RULE_QUEUE, &prev_element_ptr->ELEMENT); } if (next_element_ptr != NULL) { if (next_element_ptr->RULE.PRIORITY == dparm_ptr->RULE.PRIORITY) { // A rule of the given priority exist RTCSCMD_complete(dparm_ptr, RTCSERR_NAT_DUPLICATE_PRIORITY); return; } } new_element_ptr = (DNAT_ELEMENT_STRUCT_PTR)_mem_alloc_system_zero(sizeof(DNAT_ELEMENT_STRUCT)); if (new_element_ptr == NULL) { RTCSCMD_complete(dparm_ptr, RTCSERR_OUT_OF_MEMORY); return; } /* Endif */ new_element_ptr->RULE = dparm_ptr->RULE; _queue_insert(&nat_cfg_ptr->RULE_QUEUE, &prev_element_ptr->ELEMENT, &new_element_ptr->ELEMENT); RTCSCMD_complete(dparm_ptr, RTCS_OK); }/* Endbody */
void SOCK_Free_sock_struct ( SOCKET_STRUCT_PTR socket_ptr ) { /* Body */ SOCKET_CONFIG_STRUCT_PTR socket_cfg_ptr = RTCS_getcfg(SOCKET); #if RTCSCFG_SOCKET_OWNERSHIP //FSL AB SOCKET_OWNER_STRUCT_PTR owner_ptr; SOCKET_OWNER_STRUCT_PTR free_ptr; #endif socket_ptr->VALID = 0; #if RTCSCFG_SOCKET_OWNERSHIP owner_ptr = socket_ptr->OWNERS.NEXT; while (owner_ptr != NULL) { free_ptr = owner_ptr; owner_ptr = owner_ptr->NEXT; _mem_free(free_ptr); } /* Endwhile */ #endif RTCS_mutex_lock(&socket_cfg_ptr->SOCK_MUTEX); /* ** Fix up the head/next pointer of our predecessor. */ if ( socket_ptr->PREV == NULL ) { socket_cfg_ptr->SOCKET_HEAD = socket_ptr->NEXT; } else { (socket_ptr->PREV)->NEXT = socket_ptr->NEXT; } /* Endif */ /* ** Fix up the tail/prev pointer of our successor. */ if ( socket_ptr->NEXT == NULL ) { socket_cfg_ptr->SOCKET_TAIL = socket_ptr->PREV; } else { (socket_ptr->NEXT)->PREV = socket_ptr->PREV; } /* Endif */ /* ** Release the socket structure memory. */ RTCS_part_free(socket_ptr); socket_cfg_ptr->CURRENT_SOCKETS--; RTCS_mutex_unlock(&socket_cfg_ptr->SOCK_MUTEX); } /* Endbody */
static void RIP_trig_upd( void ) { /* Body */ RIP_CFG_STRUCT_PTR ripcfg = RTCS_getcfg(RIP); if (RTCS_getcfg(RIP) == NULL) return; /* if the timer is currently running, dont send the data */ if (ripcfg->TIMER_TRIG_UPD.PRIVATE) return; /* send the changed routes */ RIP_send_resp(ADV_VERSION, TRUE); /* start the timer */ ripcfg->TIMER_TRIG_UPD.TIME = RND_RANGE(RIP_TIME_MIN_TRIG_UPD, RIP_TIME_MAX_TRIG_UPD); ripcfg->TIMER_TRIG_UPD.EVENT = RIP_expire_trig_upd; ripcfg->TIMER_TRIG_UPD.PRIVATE = ripcfg; TCPIP_Event_add(&ripcfg->TIMER_TRIG_UPD); } /* Endbody */
NAT_NETWORK_STRUCT_PTR NAT_networks ( void ) { /* Body */ NAT_CFG_STRUCT_PTR nat_cfg_ptr = RTCS_getcfg(NAT); if (nat_cfg_ptr) { return &nat_cfg_ptr->PRIVATE_NETWORKS; } /* Endif */ return NULL; } /* Endbody */
NAT_STATS_PTR NAT_stats ( void ) { /* Body */ NAT_CFG_STRUCT_PTR nat_cfg_ptr = RTCS_getcfg(NAT); if (nat_cfg_ptr) { return &nat_cfg_ptr->STATS; } /* Endif */ return NULL; } /* Endbody */
uint_32 ROUTE_new_bindif ( IP_ROUTE_DIRECT_PTR bindif /* [IN] the outgoing binded interface */ ) { /* Body */ IP_CFG_STRUCT_PTR IP_cfg_ptr = RTCS_getcfg(IP); IP_ROUTE_FN_PTR fn; fn = IP_cfg_ptr->ROUTE_FN; while (fn) { fn->INIT_IF(bindif); fn = fn->NEXT; } /* Endwhile */ return RTCS_OK; } /* Endbody */
uint_32 IP_route_add_direct ( _ip_address address, /* Address or network address of destif */ _ip_address netmask, /* Mask for the address parameter */ IP_IF_PTR netif, /* Interface for incomming packets */ IP_IF_PTR destif /* Interface for outgoing packets */ ) { /* Body */ IP_CFG_STRUCT_PTR IP_cfg_ptr = RTCS_getcfg(IP); IP_ROUTE_DIRECT_PTR route; IP_ROUTE_FN_PTR fn; struct ip_route_insert insertdata; route = RTCS_part_alloc(IP_cfg_ptr->ROUTE_PARTID); if (!route) { return RTCSERR_IP_ROUTE_ALLOC; } /* Endif */ route->ADDRESS = address; route->NETIF = netif; route->DESTIF = destif; route->FLAGS = RTF_STATIC | RTF_UP; insertdata.error = RTCSERR_IP_ROUTE_ALLOC; insertdata.route = route; insertdata.index = 0; insertdata.sort = NULL; IPRADIX_insert(&IP_cfg_ptr->ROUTE_ROOT.NODE, address & netmask, netmask, IP_cfg_ptr->RADIX_PARTID, IP_route_insert, &insertdata); if (insertdata.error) { RTCS_part_free(route); } else if (!~netmask) { ROUTE_new_bindif(route); /* If the route is a leaf (has a full IP) */ } else if (route->DESTIF != IP_cfg_ptr->IF_LOCALHOST) { fn = IP_cfg_ptr->ROUTE_FN; /* If the route is a network connection */ while (fn) { fn->INIT_RT((IP_ROUTE_INDIRECT_PTR)((void _PTR_)route), 0); fn = fn->NEXT; } /* Endwhile */ } /* Endif */ return insertdata.error; } /* Endbody */