/* * Verify that the lifetimes and onlink/auto flags are consistent * with our settings. */ static void verify_prefix_opt(struct phyint *pi, uchar_t *opt, char *frombuf) { struct nd_opt_prefix_info *po = (struct nd_opt_prefix_info *)opt; int plen; struct adv_prefix *adv_pr; uint32_t validtime, preftime; char prefixbuf[INET6_ADDRSTRLEN]; int pktflag, myflag; if (8 * po->nd_opt_pi_len != sizeof (*po)) { logmsg(LOG_INFO, "RA prefix option from %s on %s wrong size " "(%d bytes)\n", frombuf, pi->pi_name, 8 * (int)po->nd_opt_pi_len); return; } if (IN6_IS_ADDR_LINKLOCAL(&po->nd_opt_pi_prefix)) { logmsg(LOG_INFO, "RA from %s on %s contains link-local " "prefix - ignored\n", frombuf, pi->pi_name); return; } plen = po->nd_opt_pi_prefix_len; adv_pr = adv_prefix_lookup(pi, po->nd_opt_pi_prefix, plen); if (adv_pr == NULL) return; /* Ignore prefixes which we do not advertise */ if (!adv_pr->adv_pr_AdvAutonomousFlag && !adv_pr->adv_pr_AdvOnLinkFlag) return; (void) inet_ntop(AF_INET6, (void *)&adv_pr->adv_pr_prefix, prefixbuf, sizeof (prefixbuf)); pktflag = ((po->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_AUTO) != 0); myflag = (adv_pr->adv_pr_AdvAutonomousFlag != 0); if (pktflag != myflag) { logmsg(LOG_INFO, "RA from %s on %s inconsistent autonomous flag for \n\t" "prefix %s/%u: received %s configuration %s\n", frombuf, pi->pi_name, prefixbuf, adv_pr->adv_pr_prefix_len, (pktflag ? "ON" : "OFF"), (myflag ? "ON" : "OFF")); } pktflag = ((po->nd_opt_pi_flags_reserved & ND_OPT_PI_FLAG_ONLINK) != 0); myflag = (adv_pr->adv_pr_AdvOnLinkFlag != 0); if (pktflag != myflag) { logmsg(LOG_INFO, "RA from %s on %s inconsistent on link flag " "for \n\tprefix %s/%u: received %s configuration %s\n", frombuf, pi->pi_name, prefixbuf, adv_pr->adv_pr_prefix_len, (pktflag ? "ON" : "OFF"), (myflag ? "ON" : "OFF")); } validtime = ntohl(po->nd_opt_pi_valid_time); preftime = ntohl(po->nd_opt_pi_preferred_time); /* * Take into account variation for lifetimes decrementing * in real time. Allow +/- 10 percent and +/- 10 seconds. */ #define LOWER_LIMIT(val) ((val) - (val)/10 - 10) #define UPPER_LIMIT(val) ((val) + (val)/10 + 10) if (adv_pr->adv_pr_AdvValidRealTime) { if (adv_pr->adv_pr_AdvValidExpiration > 0 && (validtime < LOWER_LIMIT(adv_pr->adv_pr_AdvValidExpiration) || validtime > UPPER_LIMIT(adv_pr->adv_pr_AdvValidExpiration))) { logmsg(LOG_INFO, "RA from %s on %s inconsistent valid " "lifetime for\n\tprefix %s/%u: received %d " "configuration %d\n", frombuf, pi->pi_name, prefixbuf, adv_pr->adv_pr_prefix_len, validtime, adv_pr->adv_pr_AdvValidExpiration); } } else { if (validtime != adv_pr->adv_pr_AdvValidLifetime) { logmsg(LOG_INFO, "RA from %s on %s inconsistent valid " "lifetime for\n\tprefix %s/%u: received %d " "configuration %d\n", frombuf, pi->pi_name, prefixbuf, adv_pr->adv_pr_prefix_len, validtime, adv_pr->adv_pr_AdvValidLifetime); } } if (adv_pr->adv_pr_AdvPreferredRealTime) { if (adv_pr->adv_pr_AdvPreferredExpiration > 0 && (preftime < LOWER_LIMIT(adv_pr->adv_pr_AdvPreferredExpiration) || preftime > UPPER_LIMIT(adv_pr->adv_pr_AdvPreferredExpiration))) { logmsg(LOG_INFO, "RA from %s on %s inconsistent " "preferred lifetime for\n\tprefix %s/%u: " "received %d configuration %d\n", frombuf, pi->pi_name, prefixbuf, adv_pr->adv_pr_prefix_len, preftime, adv_pr->adv_pr_AdvPreferredExpiration); } } else { if (preftime != adv_pr->adv_pr_AdvPreferredLifetime) { logmsg(LOG_INFO, "RA from %s on %s inconsistent " "preferred lifetime for\n\tprefix %s/%u: " "received %d configuration %d\n", frombuf, pi->pi_name, prefixbuf, adv_pr->adv_pr_prefix_len, preftime, adv_pr->adv_pr_AdvPreferredLifetime); } } }
static void parse_prefix(struct configinfo *list, char *argvec[], int argcount) { char *ifname, *prefix; struct phyint *pi; struct adv_prefix *adv_pr; struct in6_addr in6; int prefixlen; char save[sizeof (adv_pr->adv_pr_config)]; if (debug & D_CONFIG) logmsg(LOG_DEBUG, "parse_prefix: argc %d\n", argcount); if (argcount < 2) { conferr("Missing prefix and/or interface name\n"); return; } prefix = argvec[0]; ifname = argvec[1]; argvec += 2; argcount -= 2; prefixlen = parse_addrprefix(prefix, &in6); if (prefixlen == -1) { conferr("Bad prefix %s\n", prefix); return; } pi = phyint_lookup(ifname); if (pi == NULL) { /* * Create the physical interface structure. * Note, phyint_create() sets the interface * defaults in pi_config. */ pi = phyint_create(ifname); if (pi == NULL) { conferr("Unable to use interface %s\n", ifname); return; } } adv_pr = adv_prefix_lookup(pi, in6, prefixlen); if (adv_pr == NULL) { int i; adv_pr = adv_prefix_create(pi, in6, prefixlen); if (adv_pr == NULL) { conferr("Unable to create prefix %s\n", prefix); return; } /* * Copy the defaults from the default array. */ for (i = 0; i < I_PREFIXSIZE; i++) { adv_pr->adv_pr_config[i].cf_value = prefixdefaults[i].cf_value; adv_pr->adv_pr_config[i].cf_notdefault = prefixdefaults[i].cf_notdefault; } } (void) memcpy(save, adv_pr->adv_pr_config, sizeof (save)); while (argcount >= 2) { parse_var_value(CONFIG_PREFIX, list, argvec[0], argvec[1], adv_pr->adv_pr_config); argcount -= 2; argvec += 2; } check_var_consistency(adv_pr->adv_pr_config, save, sizeof (save)); if (argcount != 0) logmsg(LOG_ERR, "Trailing text <%s> ignored\n", argvec[0]); }