Beispiel #1
0
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 */
Beispiel #2
0
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 */
Beispiel #3
0
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 */
Beispiel #4
0
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 */
Beispiel #5
0
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 */
Beispiel #6
0
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 */
Beispiel #7
0
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 */
Beispiel #8
0
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 */
Beispiel #9
0
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 */
Beispiel #10
0
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 */
Beispiel #11
0
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 */
Beispiel #12
0
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 */
Beispiel #13
0
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 */
Beispiel #14
0
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 */
Beispiel #15
0
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 */
Beispiel #16
0
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 */
Beispiel #17
0
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 */
Beispiel #18
0
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 */
Beispiel #19
0
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 */
Beispiel #20
0
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 */
Beispiel #21
0
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 */
Beispiel #22
0
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 */
Beispiel #23
0
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 */
Beispiel #24
0
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 */
Beispiel #25
0
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 */
Beispiel #26
0
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 */
Beispiel #27
0
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 */
Beispiel #28
0
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 */
Beispiel #29
0
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 */
Beispiel #30
0
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 */