File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird2 / proto / rip / packets.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Mon Oct 21 16:03:57 2019 UTC (5 years, 2 months ago) by misho
Branches: bird2, MAIN
CVS tags: v2_0_7p0, HEAD
bird2 ver 2.0.7

    1: /*
    2:  *	BIRD -- Routing Information Protocol (RIP)
    3:  *
    4:  *	(c) 1998--1999 Pavel Machek <pavel@ucw.cz>
    5:  *	(c) 2004--2013 Ondrej Filip <feela@network.cz>
    6:  *	(c) 2009--2015 Ondrej Zajicek <santiago@crfreenet.org>
    7:  *	(c) 2009--2015 CZ.NIC z.s.p.o.
    8:  *
    9:  *	Can be freely distributed and used under the terms of the GNU GPL.
   10:  */
   11: 
   12: #undef LOCAL_DEBUG
   13: 
   14: #include "rip.h"
   15: #include "lib/mac.h"
   16: 
   17: 
   18: #define RIP_CMD_REQUEST		1	/* want info */
   19: #define RIP_CMD_RESPONSE	2	/* responding to request */
   20: 
   21: #define RIP_BLOCK_LENGTH	20
   22: #define RIP_PASSWD_LENGTH	16
   23: 
   24: #define RIP_AF_IPV4		2
   25: #define RIP_AF_AUTH		0xffff
   26: 
   27: 
   28: /* RIP packet header */
   29: struct rip_packet
   30: {
   31:   u8 command;
   32:   u8 version;
   33:   u16 unused;
   34: };
   35: 
   36: /* RTE block for RIPv2 */
   37: struct rip_block_v2
   38: {
   39:   u16 family;
   40:   u16 tag;
   41:   ip4_addr network;
   42:   ip4_addr netmask;
   43:   ip4_addr next_hop;
   44:   u32 metric;
   45: };
   46: 
   47: /* RTE block for RIPng */
   48: struct rip_block_ng
   49: {
   50:   ip6_addr prefix;
   51:   u16 tag;
   52:   u8 pxlen;
   53:   u8 metric;
   54: };
   55: 
   56: /* Authentication block for RIPv2 */
   57: struct rip_block_auth
   58: {
   59:   u16 must_be_ffff;
   60:   u16 auth_type;
   61:   union {
   62:     char password[16];
   63:     struct {
   64:       u16 packet_len;
   65:       u8 key_id;
   66:       u8 auth_len;
   67:       u32 seq_num;
   68:       u32 unused1;
   69:       u32 unused2;
   70:     };
   71:   };
   72: };
   73: 
   74: /* Authentication tail, RFC 4822 */
   75: struct rip_auth_tail
   76: {
   77:   u16 must_be_ffff;
   78:   u16 must_be_0001;
   79:   byte auth_data[0];
   80: };
   81: 
   82: /* Internal representation of RTE block data */
   83: struct rip_block
   84: {
   85:   net_addr net;
   86:   u32 metric;
   87:   u16 tag;
   88:   u16 no_af;
   89:   ip_addr next_hop;
   90: };
   91: 
   92: 
   93: #define DROP(DSC,VAL) do { err_dsc = DSC; err_val = VAL; goto drop; } while(0)
   94: #define DROP1(DSC) do { err_dsc = DSC; goto drop; } while(0)
   95: #define SKIP(DSC) do { err_dsc = DSC; goto skip; } while(0)
   96: 
   97: #define LOG_PKT(msg, args...) \
   98:   log_rl(&p->log_pkt_tbf, L_REMOTE "%s: " msg, p->p.name, args)
   99: 
  100: #define LOG_PKT_AUTH(msg, args...) \
  101:   log_rl(&p->log_pkt_tbf, L_AUTH "%s: " msg, p->p.name, args)
  102: 
  103: #define LOG_RTE(msg, args...) \
  104:   log_rl(&p->log_rte_tbf, L_REMOTE "%s: " msg, p->p.name, args)
  105: 
  106: 
  107: static inline void * rip_tx_buffer(struct rip_iface *ifa)
  108: { return ifa->sk->tbuf; }
  109: 
  110: static inline uint rip_pkt_hdrlen(struct rip_iface *ifa)
  111: { return sizeof(struct rip_packet) + (ifa->cf->auth_type ? RIP_BLOCK_LENGTH : 0); }
  112: 
  113: static inline void
  114: rip_put_block(struct rip_proto *p, byte *pos, struct rip_block *rte)
  115: {
  116:   if (rip_is_v2(p))
  117:   {
  118:     struct rip_block_v2 *block = (void *) pos;
  119:     block->family = rte->no_af ? 0 : htons(RIP_AF_IPV4);
  120:     block->tag = htons(rte->tag);
  121:     block->network = ip4_hton(net4_prefix(&rte->net));
  122:     block->netmask = ip4_hton(ip4_mkmask(net4_pxlen(&rte->net)));
  123:     block->next_hop = ip4_hton(ipa_to_ip4(rte->next_hop));
  124:     block->metric = htonl(rte->metric);
  125:   }
  126:   else /* RIPng */
  127:   {
  128:     struct rip_block_ng *block = (void *) pos;
  129:     block->prefix = ip6_hton(net6_prefix(&rte->net));
  130:     block->tag = htons(rte->tag);
  131:     block->pxlen = net6_pxlen(&rte->net);
  132:     block->metric = rte->metric;
  133:   }
  134: }
  135: 
  136: static inline void
  137: rip_put_next_hop(struct rip_proto *p UNUSED, byte *pos, struct rip_block *rte)
  138: {
  139:   struct rip_block_ng *block = (void *) pos;
  140:   block->prefix = ip6_hton(ipa_to_ip6(rte->next_hop));
  141:   block->tag = 0;
  142:   block->pxlen = 0;
  143:   block->metric = 0xff;
  144: }
  145: 
  146: static inline int
  147: rip_get_block(struct rip_proto *p, byte *pos, struct rip_block *rte)
  148: {
  149:   if (rip_is_v2(p))
  150:   {
  151:     struct rip_block_v2 *block = (void *) pos;
  152: 
  153:     /* Skip blocks with strange AF, including authentication blocks */
  154:     if (block->family != (rte->no_af ? 0 : htons(RIP_AF_IPV4)))
  155:       return 0;
  156: 
  157:     uint pxlen = ip4_masklen(ip4_ntoh(block->netmask));
  158:     net_fill_ip4(&rte->net, ip4_ntoh(block->network), pxlen);
  159:     rte->metric = ntohl(block->metric);
  160:     rte->tag = ntohs(block->tag);
  161:     rte->next_hop = ipa_from_ip4(ip4_ntoh(block->next_hop));
  162: 
  163:     return 1;
  164:   }
  165:   else /* RIPng */
  166:   {
  167:     struct rip_block_ng *block = (void *) pos;
  168: 
  169:     /* Handle and skip next hop blocks */
  170:     if (block->metric == 0xff)
  171:     {
  172:       rte->next_hop = ipa_from_ip6(ip6_ntoh(block->prefix));
  173:       if (!ipa_is_link_local(rte->next_hop)) rte->next_hop = IPA_NONE;
  174:       return 0;
  175:     }
  176: 
  177:     uint pxlen = (block->pxlen <= IP6_MAX_PREFIX_LENGTH) ? block->pxlen : 255;
  178:     net_fill_ip6(&rte->net, ip6_ntoh(block->prefix), pxlen);
  179:     rte->metric = block->metric;
  180:     rte->tag = ntohs(block->tag);
  181:     /* rte->next_hop is deliberately kept unmodified */;
  182: 
  183:     return 1;
  184:   }
  185: }
  186: 
  187: static inline void
  188: rip_update_csn(struct rip_proto *p UNUSED, struct rip_iface *ifa)
  189: {
  190:   /*
  191:    * We update crypto sequence numbers at the beginning of update session to
  192:    * avoid issues with packet reordering, so packets inside one update session
  193:    * have the same CSN. We are using real time, but enforcing monotonicity.
  194:    */
  195:   if (ifa->cf->auth_type == RIP_AUTH_CRYPTO)
  196:   {
  197:     u32 now_real = (u32) (current_real_time() TO_S);
  198:     ifa->csn = (ifa->csn < now_real) ? now_real : ifa->csn + 1;
  199:   }
  200: }
  201: 
  202: static void
  203: rip_fill_authentication(struct rip_proto *p, struct rip_iface *ifa, struct rip_packet *pkt, uint *plen)
  204: {
  205:   struct rip_block_auth *auth = (void *) (pkt + 1);
  206:   struct password_item *pass = password_find(ifa->cf->passwords, 0);
  207: 
  208:   if (!pass)
  209:   {
  210:     /* FIXME: This should not happen */
  211:     log(L_ERR "%s: No suitable password found for authentication", p->p.name);
  212:     memset(auth, 0, sizeof(struct rip_block_auth));
  213:     return;
  214:   }
  215: 
  216:   switch (ifa->cf->auth_type)
  217:   {
  218:   case RIP_AUTH_PLAIN:
  219:     auth->must_be_ffff = htons(0xffff);
  220:     auth->auth_type = htons(RIP_AUTH_PLAIN);
  221:     strncpy(auth->password, pass->password, RIP_PASSWD_LENGTH);
  222:     return;
  223: 
  224:   case RIP_AUTH_CRYPTO:
  225:     auth->must_be_ffff = htons(0xffff);
  226:     auth->auth_type = htons(RIP_AUTH_CRYPTO);
  227:     auth->packet_len = htons(*plen);
  228:     auth->key_id = pass->id;
  229:     auth->auth_len = mac_type_length(pass->alg);
  230:     auth->seq_num = ifa->csn_ready ? htonl(ifa->csn) : 0;
  231:     auth->unused1 = 0;
  232:     auth->unused2 = 0;
  233:     ifa->csn_ready = 1;
  234: 
  235:     if (pass->alg < ALG_HMAC)
  236:       auth->auth_len += sizeof(struct rip_auth_tail);
  237: 
  238:     /*
  239:      * Note that RFC 4822 is unclear whether auth_len should cover whole
  240:      * authentication trailer or just auth_data length.
  241:      *
  242:      * FIXME: We should use just auth_data length by default. Currently we put
  243:      * the whole auth trailer length in keyed hash case to keep old behavior,
  244:      * but we put just auth_data length in the new HMAC case. Note that Quagga
  245:      * has config option for this.
  246:      *
  247:      * Crypto sequence numbers are increased by sender in rip_update_csn().
  248:      * First CSN should be zero, this is handled by csn_ready.
  249:      */
  250: 
  251:     struct rip_auth_tail *tail = (void *) ((byte *) pkt + *plen);
  252:     tail->must_be_ffff = htons(0xffff);
  253:     tail->must_be_0001 = htons(0x0001);
  254: 
  255:     uint auth_len = mac_type_length(pass->alg);
  256:     *plen += sizeof(struct rip_auth_tail) + auth_len;
  257: 
  258:     /* Append key for keyed hash, append padding for HMAC (RFC 4822 2.5) */
  259:     if (pass->alg < ALG_HMAC)
  260:       strncpy(tail->auth_data, pass->password, auth_len);
  261:     else
  262:       memset32(tail->auth_data, HMAC_MAGIC, auth_len / 4);
  263: 
  264:     mac_fill(pass->alg, pass->password, pass->length,
  265: 	     (byte *) pkt, *plen, tail->auth_data);
  266:     return;
  267: 
  268:   default:
  269:     bug("Unknown authentication type");
  270:   }
  271: }
  272: 
  273: static int
  274: rip_check_authentication(struct rip_proto *p, struct rip_iface *ifa, struct rip_packet *pkt, uint *plen, struct rip_neighbor *n)
  275: {
  276:   struct rip_block_auth *auth = (void *) (pkt + 1);
  277:   struct password_item *pass = NULL;
  278:   const char *err_dsc = NULL;
  279:   uint err_val = 0;
  280:   uint auth_type = 0;
  281: 
  282:   /* Check for authentication entry */
  283:   if ((*plen >= (sizeof(struct rip_packet) + sizeof(struct rip_block_auth))) &&
  284:       (auth->must_be_ffff == htons(0xffff)))
  285:     auth_type = ntohs(auth->auth_type);
  286: 
  287:   if (auth_type != ifa->cf->auth_type)
  288:     DROP("authentication method mismatch", auth_type);
  289: 
  290:   switch (auth_type)
  291:   {
  292:   case RIP_AUTH_NONE:
  293:     return 1;
  294: 
  295:   case RIP_AUTH_PLAIN:
  296:     pass = password_find_by_value(ifa->cf->passwords, auth->password, RIP_PASSWD_LENGTH);
  297:     if (!pass)
  298:       DROP1("wrong password");
  299: 
  300:     return 1;
  301: 
  302:   case RIP_AUTH_CRYPTO:
  303:     pass = password_find_by_id(ifa->cf->passwords, auth->key_id);
  304:     if (!pass)
  305:       DROP("no suitable password found", auth->key_id);
  306: 
  307:     uint data_len = ntohs(auth->packet_len);
  308:     uint auth_len = mac_type_length(pass->alg);
  309:     uint auth_len2 = sizeof(struct rip_auth_tail) + auth_len;
  310: 
  311:     /*
  312:      * Ideally, first check should be check for internal consistency:
  313:      *   (data_len + sizeof(struct rip_auth_tail) + auth->auth_len) != *plen
  314:      *
  315:      * Second one should check expected code length:
  316:      *   auth->auth_len != auth_len
  317:      *
  318:      * But as auth->auth_len has two interpretations, we simplify this
  319:      */
  320: 
  321:     if (data_len + auth_len2 != *plen)
  322:       DROP("packet length mismatch", *plen);
  323: 
  324:     /* Warning: two interpretations of auth_len field */
  325:     if ((auth->auth_len != auth_len) && (auth->auth_len != auth_len2))
  326:       DROP("wrong authentication length", auth->auth_len);
  327: 
  328:     struct rip_auth_tail *tail = (void *) ((byte *) pkt + data_len);
  329:     if ((tail->must_be_ffff != htons(0xffff)) || (tail->must_be_0001 != htons(0x0001)))
  330:       DROP1("authentication trailer is missing");
  331: 
  332:     /* Accept higher sequence number, or zero if connectivity is lost */
  333:     /* FIXME: sequence number must be password/SA specific */
  334:     u32 rcv_csn = ntohl(auth->seq_num);
  335:     if ((rcv_csn < n->csn) && (rcv_csn || n->uc))
  336:     {
  337:       /* We want to report both new and old CSN */
  338:       LOG_PKT_AUTH("Authentication failed for %I on %s - "
  339: 		   "lower sequence number (rcv %u, old %u)",
  340: 		   n->nbr->addr, ifa->iface->name, rcv_csn, n->csn);
  341:       return 0;
  342:     }
  343: 
  344:     byte *auth_data = alloca(auth_len);
  345:     memcpy(auth_data, tail->auth_data, auth_len);
  346: 
  347:     /* Append key for keyed hash, append padding for HMAC (RFC 4822 2.5) */
  348:     if (pass->alg < ALG_HMAC)
  349:       strncpy(tail->auth_data, pass->password, auth_len);
  350:     else
  351:       memset32(tail->auth_data, HMAC_MAGIC, auth_len / 4);
  352: 
  353:     if (!mac_verify(pass->alg, pass->password, pass->length,
  354: 		    (byte *) pkt, *plen, auth_data))
  355:       DROP("wrong authentication code", pass->id);
  356: 
  357:     *plen = data_len;
  358:     n->csn = rcv_csn;
  359: 
  360:     return 1;
  361:   }
  362: 
  363: drop:
  364:   LOG_PKT_AUTH("Authentication failed for %I on %s - %s (%u)",
  365: 	       n->nbr->addr, ifa->iface->name, err_dsc, err_val);
  366: 
  367:   return 0;
  368: }
  369: 
  370: static inline int
  371: rip_send_to(struct rip_proto *p, struct rip_iface *ifa, struct rip_packet *pkt, uint plen, ip_addr dst)
  372: {
  373:   if (ifa->cf->auth_type)
  374:     rip_fill_authentication(p, ifa, pkt, &plen);
  375: 
  376:   return sk_send_to(ifa->sk, plen, dst, 0);
  377: }
  378: 
  379: 
  380: void
  381: rip_send_request(struct rip_proto *p, struct rip_iface *ifa)
  382: {
  383:   byte *pos = rip_tx_buffer(ifa);
  384: 
  385:   struct rip_packet *pkt = (void *) pos;
  386:   pkt->command = RIP_CMD_REQUEST;
  387:   pkt->version = ifa->cf->version;
  388:   pkt->unused = 0;
  389:   pos += rip_pkt_hdrlen(ifa);
  390: 
  391:   struct rip_block b = { .no_af = 1, .metric = p->infinity };
  392:   rip_put_block(p, pos, &b);
  393:   pos += RIP_BLOCK_LENGTH;
  394: 
  395:   rip_update_csn(p, ifa);
  396: 
  397:   TRACE(D_PACKETS, "Sending request via %s", ifa->iface->name);
  398:   rip_send_to(p, ifa, pkt, pos - (byte *) pkt, ifa->addr);
  399: }
  400: 
  401: static void
  402: rip_receive_request(struct rip_proto *p, struct rip_iface *ifa, struct rip_packet *pkt, uint plen, struct rip_neighbor *from)
  403: {
  404:   TRACE(D_PACKETS, "Request received from %I on %s", from->nbr->addr, ifa->iface->name);
  405: 
  406:   byte *pos = (byte *) pkt + rip_pkt_hdrlen(ifa);
  407: 
  408:   /* We expect one regular block */
  409:   if (plen != (rip_pkt_hdrlen(ifa) + RIP_BLOCK_LENGTH))
  410:     return;
  411: 
  412:   struct rip_block b = { .no_af = 1 };
  413: 
  414:   if (!rip_get_block(p, pos, &b))
  415:     return;
  416: 
  417:   /* Special case - infinity metric, for RIPng also zero prefix */
  418:   if ((b.metric != p->infinity) ||
  419:       (rip_is_ng(p) && !net_zero_ip6((net_addr_ip6 *) &b.net)))
  420:     return;
  421: 
  422:   /* We do nothing if TX is already active */
  423:   if (ifa->tx_active)
  424:   {
  425:     TRACE(D_EVENTS, "Skipping request from %I on %s, TX is busy", from->nbr->addr, ifa->iface->name);
  426:     return;
  427:   }
  428: 
  429:   if (!ifa->cf->passive)
  430:     rip_send_table(p, ifa, from->nbr->addr, 0);
  431: }
  432: 
  433: 
  434: static int
  435: rip_send_response(struct rip_proto *p, struct rip_iface *ifa)
  436: {
  437:   if (! ifa->tx_active)
  438:     return 0;
  439: 
  440:   byte *pos = rip_tx_buffer(ifa);
  441:   byte *max = rip_tx_buffer(ifa) + ifa->tx_plen -
  442:     (rip_is_v2(p) ? RIP_BLOCK_LENGTH : 2*RIP_BLOCK_LENGTH);
  443:   ip_addr last_next_hop = IPA_NONE;
  444:   btime now_ = current_time();
  445:   int send = 0;
  446: 
  447:   struct rip_packet *pkt = (void *) pos;
  448:   pkt->command = RIP_CMD_RESPONSE;
  449:   pkt->version = ifa->cf->version;
  450:   pkt->unused = 0;
  451:   pos += rip_pkt_hdrlen(ifa);
  452: 
  453:   FIB_ITERATE_START(&p->rtable, &ifa->tx_fit, struct rip_entry, en)
  454:   {
  455:     /* Dummy entries */
  456:     if (!en->valid)
  457:       goto next_entry;
  458: 
  459:     /* Stale entries that should be removed */
  460:     if ((en->valid == RIP_ENTRY_STALE) &&
  461: 	((en->changed + ifa->cf->garbage_time) <= now_))
  462:       goto next_entry;
  463: 
  464:     /* Triggered updates */
  465:     if (en->changed < ifa->tx_changed)
  466:       goto next_entry;
  467: 
  468:     /* Not enough space for current entry */
  469:     if (pos > max)
  470:     {
  471:       FIB_ITERATE_PUT(&ifa->tx_fit);
  472:       goto break_loop;
  473:     }
  474: 
  475:     struct rip_block rte = {
  476:       .metric = en->metric,
  477:       .tag = en->tag
  478:     };
  479: 
  480:     net_copy(&rte.net, en->n.addr);
  481: 
  482:     if (en->iface == ifa->iface)
  483:       rte.next_hop = en->next_hop;
  484: 
  485:     if (rip_is_v2(p) && (ifa->cf->version == RIP_V1))
  486:     {
  487:       /* Skipping subnets (i.e. not hosts, classful networks or default route) */
  488:       if (ip4_masklen(ip4_class_mask(net4_prefix(&rte.net))) != rte.net.pxlen)
  489: 	goto next_entry;
  490: 
  491:       rte.tag = 0;
  492:       rte.net.pxlen = 0;
  493:       rte.next_hop = IPA_NONE;
  494:     }
  495: 
  496:     /* Split horizon */
  497:     if (en->from == ifa->iface && ifa->cf->split_horizon)
  498:     {
  499:       if (ifa->cf->poison_reverse)
  500:       {
  501: 	rte.metric = p->infinity;
  502: 	rte.next_hop = IPA_NONE;
  503:       }
  504:       else
  505: 	goto next_entry;
  506:     }
  507: 
  508:     // TRACE(D_PACKETS, "    %N -> %I metric %d", &rte.net, rte.next_hop, rte.metric);
  509: 
  510:     /* RIPng next hop entry */
  511:     if (rip_is_ng(p) && !ipa_equal(rte.next_hop, last_next_hop))
  512:     {
  513:       last_next_hop = rte.next_hop;
  514:       rip_put_next_hop(p, pos, &rte);
  515:       pos += RIP_BLOCK_LENGTH;
  516:     }
  517: 
  518:     rip_put_block(p, pos, &rte);
  519:     pos += RIP_BLOCK_LENGTH;
  520:     send = 1;
  521: 
  522:   next_entry: ;
  523:   }
  524:   FIB_ITERATE_END;
  525:   ifa->tx_active = 0;
  526: 
  527:   /* Do not send empty packet */
  528:   if (!send)
  529:     return 0;
  530: 
  531: break_loop:
  532:   TRACE(D_PACKETS, "Sending response via %s", ifa->iface->name);
  533:   return rip_send_to(p, ifa, pkt, pos - (byte *) pkt, ifa->tx_addr);
  534: }
  535: 
  536: /**
  537:  * rip_send_table - RIP interface timer hook
  538:  * @p: RIP instance
  539:  * @ifa: RIP interface
  540:  * @addr: destination IP address
  541:  * @changed: time limit for triggered updates
  542:  *
  543:  * The function activates an update session and starts sending routing update
  544:  * packets (using rip_send_response()). The session may be finished during the
  545:  * call or may continue in rip_tx_hook() until all appropriate routes are
  546:  * transmitted. Note that there may be at most one active update session per
  547:  * interface, the function will terminate the old active session before
  548:  * activating the new one.
  549:  */
  550: void
  551: rip_send_table(struct rip_proto *p, struct rip_iface *ifa, ip_addr addr, btime changed)
  552: {
  553:   DBG("RIP: Opening TX session to %I on %s\n", addr, ifa->iface->name);
  554: 
  555:   rip_reset_tx_session(p, ifa);
  556: 
  557:   ifa->tx_active = 1;
  558:   ifa->tx_addr = addr;
  559:   ifa->tx_changed = changed;
  560:   FIB_ITERATE_INIT(&ifa->tx_fit, &p->rtable);
  561: 
  562:   rip_update_csn(p, ifa);
  563: 
  564:   while (rip_send_response(p, ifa) > 0)
  565:     ;
  566: }
  567: 
  568: static void
  569: rip_tx_hook(sock *sk)
  570: {
  571:   struct rip_iface *ifa = sk->data;
  572:   struct rip_proto *p = ifa->rip;
  573: 
  574:   DBG("RIP: TX hook called (iface %s, src %I, dst %I)\n",
  575:       sk->iface->name, sk->saddr, sk->daddr);
  576: 
  577:   while (rip_send_response(p, ifa) > 0)
  578:     ;
  579: }
  580: 
  581: static void
  582: rip_err_hook(sock *sk, int err)
  583: {
  584:   struct rip_iface *ifa = sk->data;
  585:   struct rip_proto *p = ifa->rip;
  586: 
  587:   log(L_ERR "%s: Socket error on %s: %M", p->p.name, ifa->iface->name, err);
  588: 
  589:   rip_reset_tx_session(p, ifa);
  590: }
  591: 
  592: static void
  593: rip_receive_response(struct rip_proto *p, struct rip_iface *ifa, struct rip_packet *pkt, uint plen, struct rip_neighbor *from)
  594: {
  595:   struct rip_block rte = {};
  596:   const char *err_dsc = NULL;
  597: 
  598:   TRACE(D_PACKETS, "Response received from %I on %s", from->nbr->addr, ifa->iface->name);
  599: 
  600:   byte *pos = (byte *) pkt + sizeof(struct rip_packet);
  601:   byte *end = (byte *) pkt + plen;
  602:   btime now_ = current_time();
  603: 
  604:   for (; pos < end; pos += RIP_BLOCK_LENGTH)
  605:   {
  606:     /* Find next regular RTE */
  607:     if (!rip_get_block(p, pos, &rte))
  608:       continue;
  609: 
  610:     if (rip_is_v2(p) && (pkt->version == RIP_V1))
  611:     {
  612:       if (ifa->cf->check_zero && (rte.tag || rte.net.pxlen || ipa_nonzero(rte.next_hop)))
  613: 	SKIP("RIPv1 reserved field is nonzero");
  614: 
  615:       rte.tag = 0;
  616:       rte.net.pxlen = ip4_masklen(ip4_class_mask(net4_prefix(&rte.net)));
  617:       rte.next_hop = IPA_NONE;
  618:     }
  619: 
  620:     if (rte.net.pxlen == 255)
  621:       SKIP("invalid prefix length");
  622: 
  623:     net_normalize(&rte.net);
  624: 
  625:     int c = net_classify(&rte.net);
  626:     if ((c < 0) || !(c & IADDR_HOST) || ((c & IADDR_SCOPE_MASK) <= SCOPE_LINK))
  627:       SKIP("invalid prefix");
  628: 
  629:     if (rte.metric > p->infinity)
  630:       SKIP("invalid metric");
  631: 
  632:     if (ipa_nonzero(rte.next_hop))
  633:     {
  634:       neighbor *nbr = neigh_find(&p->p, rte.next_hop, ifa->iface, 0);
  635:       if (!nbr || (nbr->scope <= 0))
  636: 	rte.next_hop = IPA_NONE;
  637:     }
  638: 
  639:     // TRACE(D_PACKETS, "    %N -> %I metric %d", &rte.net.n, rte.next_hop, rte.metric);
  640: 
  641:     rte.metric += ifa->cf->metric;
  642: 
  643:     if (rte.metric < p->infinity)
  644:     {
  645:       struct rip_rte new = {
  646: 	.from = from,
  647: 	.next_hop = ipa_nonzero(rte.next_hop) ? rte.next_hop : from->nbr->addr,
  648: 	.metric = rte.metric,
  649: 	.tag = rte.tag,
  650: 	.expires = now_ + ifa->cf->timeout_time
  651:       };
  652: 
  653:       rip_update_rte(p, &rte.net, &new);
  654:     }
  655:     else
  656:       rip_withdraw_rte(p, &rte.net, from);
  657: 
  658:     continue;
  659: 
  660:   skip:
  661:     LOG_RTE("Ignoring route %N received from %I - %s",
  662: 	    &rte.net, from->nbr->addr, err_dsc);
  663:   }
  664: }
  665: 
  666: static int
  667: rip_rx_hook(sock *sk, uint len)
  668: {
  669:   struct rip_iface *ifa = sk->data;
  670:   struct rip_proto *p = ifa->rip;
  671:   const char *err_dsc = NULL;
  672:   uint err_val = 0;
  673: 
  674:   if (sk->lifindex != sk->iface->index)
  675:     return 1;
  676: 
  677:   DBG("RIP: RX hook called (iface %s, src %I, dst %I)\n",
  678:       sk->iface->name, sk->faddr, sk->laddr);
  679: 
  680:   /* Silently ignore my own packets */
  681:   if (ipa_equal(sk->faddr, sk->saddr))
  682:     return 1;
  683: 
  684:   if (rip_is_ng(p) && !ipa_is_link_local(sk->faddr))
  685:     DROP1("wrong src address");
  686: 
  687:   struct rip_neighbor *n = rip_get_neighbor(p, &sk->faddr, ifa);
  688: 
  689:   if (!n)
  690:     DROP1("not from neighbor");
  691: 
  692:   if ((ifa->cf->ttl_security == 1) && (sk->rcv_ttl < 255))
  693:     DROP("wrong TTL", sk->rcv_ttl);
  694: 
  695:   if (sk->fport != sk->dport)
  696:     DROP("wrong src port", sk->fport);
  697: 
  698:   if (len < sizeof(struct rip_packet))
  699:     DROP("too short", len);
  700: 
  701:   if (sk->flags & SKF_TRUNCATED)
  702:     DROP("truncated", len);
  703: 
  704:   struct rip_packet *pkt = (struct rip_packet *) sk->rbuf;
  705:   uint plen = len;
  706: 
  707:   if (!pkt->version || (ifa->cf->version_only && (pkt->version != ifa->cf->version)))
  708:     DROP("wrong version", pkt->version);
  709: 
  710:   /* rip_check_authentication() has its own error logging */
  711:   if (rip_is_v2(p) && !rip_check_authentication(p, ifa, pkt, &plen, n))
  712:     return 1;
  713: 
  714:   if ((plen - sizeof(struct rip_packet)) % RIP_BLOCK_LENGTH)
  715:     DROP("invalid length", plen);
  716: 
  717:   n->last_seen = current_time();
  718:   rip_update_bfd(p, n);
  719: 
  720:   switch (pkt->command)
  721:   {
  722:   case RIP_CMD_REQUEST:
  723:     rip_receive_request(p, ifa, pkt, plen, n);
  724:     break;
  725: 
  726:   case RIP_CMD_RESPONSE:
  727:     rip_receive_response(p, ifa, pkt, plen, n);
  728:     break;
  729: 
  730:   default:
  731:     DROP("unknown command", pkt->command);
  732:   }
  733:   return 1;
  734: 
  735: drop:
  736:   LOG_PKT("Bad packet from %I via %s - %s (%u)",
  737: 	  sk->faddr, sk->iface->name, err_dsc, err_val);
  738: 
  739:   return 1;
  740: }
  741: 
  742: int
  743: rip_open_socket(struct rip_iface *ifa)
  744: {
  745:   struct rip_proto *p = ifa->rip;
  746: 
  747:   sock *sk = sk_new(p->p.pool);
  748:   sk->type = SK_UDP;
  749:   sk->subtype = rip_is_v2(p) ? SK_IPV4 : SK_IPV6;
  750:   sk->sport = ifa->cf->port;
  751:   sk->dport = ifa->cf->port;
  752:   sk->iface = ifa->iface;
  753:   sk->saddr = rip_is_v2(p) ? ifa->iface->addr4->ip : ifa->iface->llv6->ip;
  754:   sk->vrf = p->p.vrf;
  755: 
  756:   sk->rx_hook = rip_rx_hook;
  757:   sk->tx_hook = rip_tx_hook;
  758:   sk->err_hook = rip_err_hook;
  759:   sk->data = ifa;
  760: 
  761:   sk->tos = ifa->cf->tx_tos;
  762:   sk->priority = ifa->cf->tx_priority;
  763:   sk->ttl = ifa->cf->ttl_security ? 255 : 1;
  764:   sk->flags = SKF_LADDR_RX | ((ifa->cf->ttl_security == 1) ? SKF_TTL_RX : 0);
  765: 
  766:   /* sk->rbsize and sk->tbsize are handled in rip_iface_update_buffers() */
  767: 
  768:   if (sk_open(sk) < 0)
  769:     goto err;
  770: 
  771:   if (ifa->cf->mode == RIP_IM_MULTICAST)
  772:   {
  773:     if (sk_setup_multicast(sk) < 0)
  774:       goto err;
  775: 
  776:     if (sk_join_group(sk, ifa->addr) < 0)
  777:       goto err;
  778:   }
  779:   else /* Broadcast */
  780:   {
  781:     if (sk_setup_broadcast(sk) < 0)
  782:       goto err;
  783: 
  784:     if (ipa_zero(ifa->addr))
  785:     {
  786:       sk->err = "Missing broadcast address";
  787:       goto err;
  788:     }
  789:   }
  790: 
  791:   ifa->sk = sk;
  792:   return 1;
  793: 
  794: err:
  795:   sk_log_error(sk, p->p.name);
  796:   rfree(sk);
  797:   return 0;
  798: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>