diff options
Diffstat (limited to 'usr.sbin/rtadvd/rrenum.c')
-rw-r--r-- | usr.sbin/rtadvd/rrenum.c | 212 |
1 files changed, 113 insertions, 99 deletions
diff --git a/usr.sbin/rtadvd/rrenum.c b/usr.sbin/rtadvd/rrenum.c index aafa0f97cdc3..3e3631151556 100644 --- a/usr.sbin/rtadvd/rrenum.c +++ b/usr.sbin/rtadvd/rrenum.c @@ -36,6 +36,7 @@ #include <sys/sysctl.h> #include <net/if.h> +#include <net/if_dl.h> #include <net/if_var.h> #include <net/route.h> #include <netinet/in.h> @@ -45,6 +46,7 @@ #include <arpa/inet.h> #include <errno.h> +#include <netdb.h> #include <string.h> #include <stdlib.h> #include <syslog.h> @@ -74,7 +76,7 @@ static int s = -1; /* * Check validity of a Prefix Control Operation(PCO). - * Return 0 on success, 1 on failure. + * return 0 on success, 1 on failure. */ static int rr_pco_check(int len, struct rr_pco_match *rpm) @@ -86,8 +88,8 @@ rr_pco_check(int len, struct rr_pco_match *rpm) if ((rpm->rpm_len - 3) < 0 || /* must be at least 3 */ (rpm->rpm_len - 3) & 0x3) { /* must be multiple of 4 */ syslog(LOG_WARNING, "<%s> rpm_len %d is not 4N * 3", - __func__, rpm->rpm_len); - return 1; + __func__, rpm->rpm_len); + return (1); } /* rpm->rpm_code must be valid value */ switch (rpm->rpm_code) { @@ -97,14 +99,14 @@ rr_pco_check(int len, struct rr_pco_match *rpm) break; default: syslog(LOG_WARNING, "<%s> unknown rpm_code %d", __func__, - rpm->rpm_code); - return 1; + rpm->rpm_code); + return (1); } /* rpm->rpm_matchlen must be 0 to 128 inclusive */ if (rpm->rpm_matchlen > 128) { syslog(LOG_WARNING, "<%s> rpm_matchlen %d is over 128", - __func__, rpm->rpm_matchlen); - return 1; + __func__, rpm->rpm_matchlen); + return (1); } /* @@ -126,23 +128,23 @@ rr_pco_check(int len, struct rr_pco_match *rpm) */ if (checklen > 128) { syslog(LOG_WARNING, "<%s> sum of rpu_uselen %d and" - " rpu_keeplen %d is %d(over 128)", - __func__, rpu->rpu_uselen, - rpu->rpu_keeplen, - rpu->rpu_uselen + rpu->rpu_keeplen); - return 1; + " rpu_keeplen %d is %d(over 128)", + __func__, rpu->rpu_uselen, rpu->rpu_keeplen, + rpu->rpu_uselen + rpu->rpu_keeplen); + return (1); } } - return 0; + return (0); } static void do_use_prefix(int len, struct rr_pco_match *rpm, - struct in6_rrenumreq *irr, int ifindex) + struct in6_rrenumreq *irr, int ifindex) { struct rr_pco_use *rpu, *rpulim; struct rainfo *rai; - struct prefix *pp; + struct ifinfo *ifi; + struct prefix *pfx; rpu = (struct rr_pco_use *)(rpm + 1); rpulim = (struct rr_pco_use *)((char *)rpm + len); @@ -164,7 +166,7 @@ do_use_prefix(int len, struct rr_pco_match *rpm, if (ioctl(s, rrcmd2pco[rpm->rpm_code], (caddr_t)irr) < 0 && errno != EADDRNOTAVAIL) syslog(LOG_ERR, "<%s> ioctl: %s", __func__, - strerror(errno)); + strerror(errno)); return; } @@ -176,19 +178,23 @@ do_use_prefix(int len, struct rr_pco_match *rpm, irr->irr_u_uselen = rpu->rpu_uselen; irr->irr_u_keeplen = rpu->rpu_keeplen; irr->irr_raf_mask_onlink = - !!(rpu->rpu_ramask & ICMP6_RR_PCOUSE_RAFLAGS_ONLINK); + !!(rpu->rpu_ramask & ICMP6_RR_PCOUSE_RAFLAGS_ONLINK); irr->irr_raf_mask_auto = - !!(rpu->rpu_ramask & ICMP6_RR_PCOUSE_RAFLAGS_AUTO); + !!(rpu->rpu_ramask & ICMP6_RR_PCOUSE_RAFLAGS_AUTO); irr->irr_vltime = ntohl(rpu->rpu_vltime); irr->irr_pltime = ntohl(rpu->rpu_pltime); irr->irr_raf_onlink = - (rpu->rpu_raflags & ICMP6_RR_PCOUSE_RAFLAGS_ONLINK) == 0 ? 0 : 1; + (rpu->rpu_raflags & ICMP6_RR_PCOUSE_RAFLAGS_ONLINK) == 0 ? + 0 : 1; irr->irr_raf_auto = - (rpu->rpu_raflags & ICMP6_RR_PCOUSE_RAFLAGS_AUTO) == 0 ? 0 : 1; + (rpu->rpu_raflags & ICMP6_RR_PCOUSE_RAFLAGS_AUTO) == 0 ? + 0 : 1; irr->irr_rrf_decrvalid = - (rpu->rpu_flags & ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME) == 0 ? 0 : 1; + (rpu->rpu_flags & ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME) == 0 ? + 0 : 1; irr->irr_rrf_decrprefd = - (rpu->rpu_flags & ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME) == 0 ? 0 : 1; + (rpu->rpu_flags & ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME) == 0 ? + 0 : 1; irr->irr_useprefix.sin6_len = sizeof(irr->irr_useprefix); irr->irr_useprefix.sin6_family = AF_INET6; irr->irr_useprefix.sin6_addr = rpu->rpu_prefix; @@ -196,38 +202,43 @@ do_use_prefix(int len, struct rr_pco_match *rpm, if (ioctl(s, rrcmd2pco[rpm->rpm_code], (caddr_t)irr) < 0 && errno != EADDRNOTAVAIL) syslog(LOG_ERR, "<%s> ioctl: %s", __func__, - strerror(errno)); + strerror(errno)); /* very adhoc: should be rewritten */ if (rpm->rpm_code == RPM_PCO_CHANGE && IN6_ARE_ADDR_EQUAL(&rpm->rpm_prefix, &rpu->rpu_prefix) && rpm->rpm_matchlen == rpu->rpu_uselen && rpu->rpu_uselen == rpu->rpu_keeplen) { - if ((rai = if_indextorainfo(ifindex)) == NULL) + ifi = if_indextoifinfo(ifindex); + if (ifi == NULL || ifi->ifi_rainfo == NULL) continue; /* non-advertising IF */ + rai = ifi->ifi_rainfo; - for (pp = rai->prefix.next; pp != &rai->prefix; - pp = pp->next) { + TAILQ_FOREACH(pfx, &rai->rai_prefix, pfx_next) { struct timeval now; - if (prefix_match(&pp->prefix, pp->prefixlen, - &rpm->rpm_prefix, - rpm->rpm_matchlen)) { + if (prefix_match(&pfx->pfx_prefix, + pfx->pfx_prefixlen, &rpm->rpm_prefix, + rpm->rpm_matchlen)) { /* change parameters */ - pp->validlifetime = ntohl(rpu->rpu_vltime); - pp->preflifetime = ntohl(rpu->rpu_pltime); + pfx->pfx_validlifetime = + ntohl(rpu->rpu_vltime); + pfx->pfx_preflifetime = + ntohl(rpu->rpu_pltime); if (irr->irr_rrf_decrvalid) { gettimeofday(&now, 0); - pp->vltimeexpire = - now.tv_sec + pp->validlifetime; + pfx->pfx_vltimeexpire = + now.tv_sec + + pfx->pfx_validlifetime; } else - pp->vltimeexpire = 0; + pfx->pfx_vltimeexpire = 0; if (irr->irr_rrf_decrprefd) { gettimeofday(&now, 0); - pp->pltimeexpire = - now.tv_sec + pp->preflifetime; + pfx->pfx_pltimeexpire = + now.tv_sec + + pfx->pfx_preflifetime; } else - pp->pltimeexpire = 0; + pfx->pfx_pltimeexpire = 0; } } } @@ -243,13 +254,14 @@ do_pco(struct icmp6_router_renum *rr, int len, struct rr_pco_match *rpm) { int ifindex = 0; struct in6_rrenumreq irr; - + struct ifinfo *ifi; + if ((rr_pco_check(len, rpm) != 0)) - return 1; + return (1); if (s == -1 && (s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { syslog(LOG_ERR, "<%s> socket: %s", __func__, - strerror(errno)); + strerror(errno)); exit(1); } @@ -263,24 +275,30 @@ do_pco(struct icmp6_router_renum *rr, int len, struct rr_pco_match *rpm) irr.irr_matchprefix.sin6_addr = rpm->rpm_prefix; while (if_indextoname(++ifindex, irr.irr_name)) { + ifi = if_indextoifinfo(ifindex); + if (ifi == NULL) { + syslog(LOG_ERR, "<%s> ifindex not found.", + __func__); + return (1); + } /* - * if ICMP6_RR_FLAGS_FORCEAPPLY(A flag) is 0 and IFF_UP is off, - * the interface is not applied + * if ICMP6_RR_FLAGS_FORCEAPPLY(A flag) is 0 and + * IFF_UP is off, the interface is not applied */ if ((rr->rr_flags & ICMP6_RR_FLAGS_FORCEAPPLY) == 0 && - (iflist[ifindex]->ifm_flags & IFF_UP) == 0) + (ifi->ifi_flags & IFF_UP) == 0) continue; /* TODO: interface scope check */ do_use_prefix(len, rpm, &irr, ifindex); } if (errno == ENXIO) - return 0; + return (0); else if (errno) { syslog(LOG_ERR, "<%s> if_indextoname: %s", __func__, - strerror(errno)); - return 1; + strerror(errno)); + return (1); } - return 0; + return (0); } /* @@ -298,18 +316,17 @@ do_rr(int len, struct icmp6_router_renum *rr) cp = (char *)(rr + 1); len -= sizeof(struct icmp6_router_renum); - /* get iflist block from kernel again, to get up-to-date information */ - init_iflist(); + update_ifinfo(&ifilist, UPDATE_IFINFO_ALL); while (cp < lim) { int rpmlen; rpm = (struct rr_pco_match *)cp; - if (len < sizeof(struct rr_pco_match)) { + if ((size_t)len < sizeof(struct rr_pco_match)) { tooshort: syslog(LOG_ERR, "<%s> pkt too short. left len = %d. " - "gabage at end of pkt?", __func__, len); - return 1; + "gabage at end of pkt?", __func__, len); + return (1); } rpmlen = rpm->rpm_len << 3; if (len < rpmlen) @@ -325,7 +342,7 @@ do_rr(int len, struct icmp6_router_renum *rr) len -= rpmlen; } - return 0; + return (0); } /* @@ -334,46 +351,45 @@ do_rr(int len, struct icmp6_router_renum *rr) */ static int rr_command_check(int len, struct icmp6_router_renum *rr, struct in6_addr *from, - struct in6_addr *dst) + struct in6_addr *dst) { u_char ntopbuf[INET6_ADDRSTRLEN]; /* omit rr minimal length check. hope kernel have done it. */ /* rr_command length check */ - if (len < (sizeof(struct icmp6_router_renum) + - sizeof(struct rr_pco_match))) { + if ((size_t)len < (sizeof(struct icmp6_router_renum) + + sizeof(struct rr_pco_match))) { syslog(LOG_ERR, "<%s> rr_command len %d is too short", - __func__, len); - return 1; + __func__, len); + return (1); } /* destination check. only for multicast. omit unicast check. */ if (IN6_IS_ADDR_MULTICAST(dst) && !IN6_IS_ADDR_MC_LINKLOCAL(dst) && !IN6_IS_ADDR_MC_SITELOCAL(dst)) { syslog(LOG_ERR, "<%s> dst mcast addr %s is illegal", - __func__, - inet_ntop(AF_INET6, dst, ntopbuf, INET6_ADDRSTRLEN)); - return 1; + __func__, + inet_ntop(AF_INET6, dst, ntopbuf, sizeof(ntopbuf))); + return (1); } /* seqnum and segnum check */ if (rro.rro_seqnum > rr->rr_seqnum) { syslog(LOG_WARNING, - "<%s> rcvd old seqnum %d from %s", - __func__, (u_int32_t)ntohl(rr->rr_seqnum), - inet_ntop(AF_INET6, from, ntopbuf, INET6_ADDRSTRLEN)); - return 1; + "<%s> rcvd old seqnum %d from %s", + __func__, (u_int32_t)ntohl(rr->rr_seqnum), + inet_ntop(AF_INET6, from, ntopbuf, sizeof(ntopbuf))); + return (1); } if (rro.rro_seqnum == rr->rr_seqnum && (rr->rr_flags & ICMP6_RR_FLAGS_TEST) == 0 && RR_ISSET_SEGNUM(rro.rro_segnum_bits, rr->rr_segnum)) { if ((rr->rr_flags & ICMP6_RR_FLAGS_REQRESULT) != 0) syslog(LOG_WARNING, - "<%s> rcvd duped segnum %d from %s", - __func__, rr->rr_segnum, - inet_ntop(AF_INET6, from, ntopbuf, - INET6_ADDRSTRLEN)); - return 0; + "<%s> rcvd duped segnum %d from %s", + __func__, rr->rr_segnum, inet_ntop(AF_INET6, from, + ntopbuf, sizeof(ntopbuf))); + return (0); } /* update seqnum */ @@ -382,16 +398,16 @@ rr_command_check(int len, struct icmp6_router_renum *rr, struct in6_addr *from, /* init rro_segnum_bits */ memset(rro.rro_segnum_bits, 0, - sizeof(rro.rro_segnum_bits)); + sizeof(rro.rro_segnum_bits)); } rro.rro_seqnum = rr->rr_seqnum; - return 0; + return (0); } static void rr_command_input(int len, struct icmp6_router_renum *rr, - struct in6_addr *from, struct in6_addr *dst) + struct in6_addr *from, struct in6_addr *dst) { /* rr_command validity check */ if (rr_command_check(len, rr, from, dst)) @@ -401,9 +417,8 @@ rr_command_input(int len, struct icmp6_router_renum *rr, return; /* do router renumbering */ - if (do_rr(len, rr)) { + if (do_rr(len, rr)) goto failed; - } /* update segnum */ RR_SET_SEGNUM(rro.rro_segnum_bits, rr->rr_segnum); @@ -417,27 +432,26 @@ rr_command_input(int len, struct icmp6_router_renum *rr, void rr_input(int len, struct icmp6_router_renum *rr, struct in6_pktinfo *pi, - struct sockaddr_in6 *from, struct in6_addr *dst) + struct sockaddr_in6 *from, struct in6_addr *dst) { u_char ntopbuf[2][INET6_ADDRSTRLEN], ifnamebuf[IFNAMSIZ]; syslog(LOG_DEBUG, - "<%s> RR received from %s to %s on %s", - __func__, - inet_ntop(AF_INET6, &from->sin6_addr, - ntopbuf[0], INET6_ADDRSTRLEN), - inet_ntop(AF_INET6, &dst, ntopbuf[1], INET6_ADDRSTRLEN), - if_indextoname(pi->ipi6_ifindex, ifnamebuf)); + "<%s> RR received from %s to %s on %s", + __func__, + inet_ntop(AF_INET6, &from->sin6_addr, ntopbuf[0] ,sizeof(ntopbuf[0])), + inet_ntop(AF_INET6, &dst, ntopbuf[1], sizeof(ntopbuf[1])), + if_indextoname(pi->ipi6_ifindex, ifnamebuf)); /* packet validation based on Section 4.1 of RFC2894 */ - if (len < sizeof(struct icmp6_router_renum)) { + if ((size_t)len < sizeof(struct icmp6_router_renum)) { syslog(LOG_NOTICE, - "<%s>: RR short message (size %d) from %s to %s on %s", - __func__, len, - inet_ntop(AF_INET6, &from->sin6_addr, - ntopbuf[0], INET6_ADDRSTRLEN), - inet_ntop(AF_INET6, &dst, ntopbuf[1], INET6_ADDRSTRLEN), - if_indextoname(pi->ipi6_ifindex, ifnamebuf)); + "<%s>: RR short message (size %d) from %s to %s on %s", + __func__, len, + inet_ntop(AF_INET6, &from->sin6_addr, ntopbuf[0], + sizeof(ntopbuf[0])), + inet_ntop(AF_INET6, &dst, ntopbuf[1], sizeof(ntopbuf[1])), + if_indextoname(pi->ipi6_ifindex, ifnamebuf)); return; } @@ -449,16 +463,16 @@ rr_input(int len, struct icmp6_router_renum *rr, struct in6_pktinfo *pi, * We rely on the kernel input routine for unicast addresses, and thus * check multicast destinations only. */ - if (IN6_IS_ADDR_MULTICAST(&pi->ipi6_addr) && - !IN6_ARE_ADDR_EQUAL(&in6a_site_allrouters, &pi->ipi6_addr)) { + if (IN6_IS_ADDR_MULTICAST(&pi->ipi6_addr) && !IN6_ARE_ADDR_EQUAL( + &sin6_sitelocal_allrouters.sin6_addr, &pi->ipi6_addr)) { syslog(LOG_NOTICE, - "<%s>: RR message with invalid destination (%s) " - "from %s on %s", - __func__, - inet_ntop(AF_INET6, &dst, ntopbuf[0], INET6_ADDRSTRLEN), - inet_ntop(AF_INET6, &from->sin6_addr, - ntopbuf[1], INET6_ADDRSTRLEN), - if_indextoname(pi->ipi6_ifindex, ifnamebuf)); + "<%s>: RR message with invalid destination (%s) " + "from %s on %s", + __func__, + inet_ntop(AF_INET6, &dst, ntopbuf[0], sizeof(ntopbuf[0])), + inet_ntop(AF_INET6, &from->sin6_addr, ntopbuf[1], + sizeof(ntopbuf[1])), + if_indextoname(pi->ipi6_ifindex, ifnamebuf)); return; } @@ -477,7 +491,7 @@ rr_input(int len, struct icmp6_router_renum *rr, struct in6_pktinfo *pi, break; default: syslog(LOG_ERR, "<%s> received unknown code %d", - __func__, rr->rr_code); + __func__, rr->rr_code); break; } |