📄 common.c
字号:
pi.validlifetime = htonl(dp->val_dhcp6addr.validlifetime); pi.plen = dp->val_dhcp6addr.plen; memcpy(&pi.prefix, &dp->val_dhcp6addr.addr, sizeof(pi.prefix)); memcpy(tp, &pi, sizeof(pi)); tp += sizeof(pi); dprintf(LOG_DEBUG, "set IAPREFIX option len %d: " "%s/%d preferlifetime %d validlifetime %d", iaddr_len, in6addr2str(&pi.prefix, 0), pi.plen, ntohl(pi.preferlifetime), ntohl(pi.validlifetime)); /* set up address status code if any */ if (dp->val_dhcp6addr.status_code != DH6OPT_STCODE_UNDEFINE) { status.dh6_status_type = htons(DH6OPT_STATUS_CODE); status.dh6_status_len = htons(sizeof(status.dh6_status_code)); status.dh6_status_code = htons(dp->val_dhcp6addr.status_code); memcpy(tp, &status, sizeof(status)); dprintf(LOG_DEBUG, " this address status code: %s", dhcp6_stcodestr(ntohs(status.dh6_status_code))); optlen += sizeof(status); tp += sizeof(status); /* copy status message if any */ } } } else if (dhcp6_mode == DHCP6_MODE_SERVER) { int num; num = DH6OPT_STCODE_NOPREFIXAVAIL; dprintf(LOG_DEBUG, " status code: %s", dhcp6_stcodestr(num)); /* XXX: need to check duplication? */ if (dhcp6_add_listval(&optinfo->stcode_list, &num, DHCP6_LISTVAL_NUM) == NULL) { dprintf(LOG_ERR, "%s" "failed to copy " "status code", FNAME); goto fail; } } COPY_OPTION(DH6OPT_IA_PD, optlen, tmpbuf, p); free(tmpbuf); break; default: break; } if (dhcp6_mode == DHCP6_MODE_SERVER && optinfo->pref != DH6OPT_PREF_UNDEF) { u_int8_t p8 = (u_int8_t)optinfo->pref; dprintf(LOG_DEBUG, "server preference %2x", optinfo->pref); COPY_OPTION(DH6OPT_PREFERENCE, sizeof(p8), &p8, p); } for (stcode = TAILQ_FIRST(&optinfo->stcode_list); stcode; stcode = TAILQ_NEXT(stcode, link)) { u_int16_t code; code = htons(stcode->val_num); COPY_OPTION(DH6OPT_STATUS_CODE, sizeof(code), &code, p); } if (!TAILQ_EMPTY(&optinfo->reqopt_list)) { struct dhcp6_listval *opt; u_int16_t *valp; tmpbuf = NULL; optlen = dhcp6_count_list(&optinfo->reqopt_list) * sizeof(u_int16_t); if ((tmpbuf = malloc(optlen)) == NULL) { dprintf(LOG_ERR, "%s" "memory allocation failed for options", FNAME); goto fail; } valp = (u_int16_t *)tmpbuf; for (opt = TAILQ_FIRST(&optinfo->reqopt_list); opt; opt = TAILQ_NEXT(opt, link), valp++) { *valp = htons((u_int16_t)opt->val_num); } COPY_OPTION(DH6OPT_ORO, optlen, tmpbuf, p); free(tmpbuf); } if (!TAILQ_EMPTY(&optinfo->dns_list.addrlist)) { struct in6_addr *in6; struct dhcp6_listval *d; tmpbuf = NULL; optlen = dhcp6_count_list(&optinfo->dns_list.addrlist) * sizeof(struct in6_addr); if ((tmpbuf = malloc(optlen)) == NULL) { dprintf(LOG_ERR, "%s" "memory allocation failed for DNS options", FNAME); goto fail; } in6 = (struct in6_addr *)tmpbuf; for (d = TAILQ_FIRST(&optinfo->dns_list.addrlist); d; d = TAILQ_NEXT(d, link), in6++) { memcpy(in6, &d->val_addr6, sizeof(*in6)); } COPY_OPTION(DH6OPT_DNS_RESOLVERS, optlen, tmpbuf, p); free(tmpbuf); } if (optinfo->dns_list.domainlist != NULL) { struct domain_list *dlist; u_char *dst; size_t dstsiz; optlen = 0; tmpbuf = NULL; if ((tmpbuf = malloc(MAXDNAME * MAXDN)) == NULL) { dprintf(LOG_ERR, "%s" "memory allocation failed for DNS options", FNAME); goto fail; } dst = tmpbuf; for (dlist = optinfo->dns_list.domainlist; dlist; dlist = dlist->next) { int n; n = dn_comp(dlist->name, dst, MAXDNAME, NULL, NULL); if (n < 0) { dprintf(LOG_ERR, "%s" "compress domain name failed", FNAME); goto fail; } else dprintf(LOG_DEBUG, "compress domain name %s", dlist->name); optlen += n ; dst += n; } COPY_OPTION(DH6OPT_DOMAIN_LIST, optlen, tmpbuf, p); free(tmpbuf); } return (len); fail: if (tmpbuf) free(tmpbuf); return (-1);}#undef COPY_OPTIONvoiddhcp6_set_timeoparam(ev) struct dhcp6_event *ev;{ ev->retrans = 0; ev->init_retrans = 0; ev->max_retrans_cnt = 0; ev->max_retrans_dur = 0; ev->max_retrans_time = 0; switch(ev->state) { case DHCP6S_SOLICIT: ev->init_retrans = SOL_TIMEOUT; ev->max_retrans_time = SOL_MAX_RT; break; case DHCP6S_INFOREQ: ev->init_retrans = INF_TIMEOUT; ev->max_retrans_time = INF_MAX_RT; break; case DHCP6S_REQUEST: ev->init_retrans = REQ_TIMEOUT; ev->max_retrans_time = REQ_MAX_RT; ev->max_retrans_cnt = REQ_MAX_RC; break; case DHCP6S_RENEW: ev->init_retrans = REN_TIMEOUT; ev->max_retrans_time = REN_MAX_RT; break; case DHCP6S_REBIND: ev->init_retrans = REB_TIMEOUT; ev->max_retrans_time = REB_MAX_RT; break; case DHCP6S_DECLINE: ev->init_retrans = DEC_TIMEOUT; ev->max_retrans_cnt = DEC_MAX_RC; break; case DHCP6S_RELEASE: ev->init_retrans = REL_TIMEOUT; ev->max_retrans_cnt = REL_MAX_RC; break; case DHCP6S_CONFIRM: ev->init_retrans = CNF_TIMEOUT; ev->max_retrans_dur = CNF_MAX_RD; ev->max_retrans_time = CNF_MAX_RT; break; default: dprintf(LOG_INFO, "%s" "unexpected event state %d on %s", FNAME, ev->state, ev->ifp->ifname); exit(1); }}voiddhcp6_reset_timer(ev) struct dhcp6_event *ev;{ double n, r; char *statestr; struct timeval interval; switch(ev->state) { case DHCP6S_INIT: /* * The first Solicit message from the client on the interface * MUST be delayed by a random amount of time between * MIN_SOL_DELAY and MAX_SOL_DELAY. * [dhcpv6-28 14.] */ ev->retrans = (random() % (MAX_SOL_DELAY - MIN_SOL_DELAY)) + MIN_SOL_DELAY; break; default: if (ev->timeouts == 0) { /* * The first RT MUST be selected to be strictly * greater than IRT by choosing RAND to be strictly * greater than 0. * [dhcpv6-28 14.] */ r = (double)((random() % 1000) + 1) / 10000; n = ev->init_retrans + r * ev->init_retrans; } else { r = (double)((random() % 2000) - 1000) / 10000; if (ev->timeouts == 0) { n = ev->init_retrans + r * ev->init_retrans; } else n = 2 * ev->retrans + r * ev->retrans; } if (ev->max_retrans_time && n > ev->max_retrans_time) n = ev->max_retrans_time + r * ev->max_retrans_time; ev->retrans = (long)n; break; } switch(ev->state) { case DHCP6S_INIT: statestr = "INIT"; break; case DHCP6S_SOLICIT: statestr = "SOLICIT"; break; case DHCP6S_INFOREQ: statestr = "INFOREQ"; break; case DHCP6S_REQUEST: statestr = "REQUEST"; break; case DHCP6S_RENEW: statestr = "RENEW"; break; case DHCP6S_REBIND: statestr = "REBIND"; break; case DHCP6S_CONFIRM: statestr = "CONFIRM"; break; case DHCP6S_DECLINE: statestr = "DECLINE"; break; case DHCP6S_RELEASE: statestr = "RELEASE"; break; case DHCP6S_IDLE: statestr = "IDLE"; break; default: statestr = "???"; /* XXX */ break; } interval.tv_sec = (ev->retrans * 1000) / 1000000; interval.tv_usec = (ev->retrans * 1000) % 1000000; dhcp6_set_timer(&interval, ev->timer); dprintf(LOG_DEBUG, "%s" "reset a timer on %s, " "state=%s, timeo=%d, retrans=%ld", FNAME, ev->ifp->ifname, statestr, ev->timeouts, (long) ev->retrans);}intduidcpy(struct duid *dd, const struct duid *ds){ dd->duid_len = ds->duid_len; if ((dd->duid_id = malloc(dd->duid_len)) == NULL) { dprintf(LOG_ERR, "%s" "len %d memory allocation failed", FNAME, dd->duid_len); return (-1); } memcpy(dd->duid_id, ds->duid_id, dd->duid_len); return (0);}intduidcmp(const struct duid *d1, const struct duid *d2){ if (d1->duid_len == d2->duid_len) { return (memcmp(d1->duid_id, d2->duid_id, d1->duid_len)); } else return (-1);}voidduidfree(duid) struct duid *duid;{ dprintf(LOG_DEBUG, "%s" "DUID is %s, DUID_LEN is %d", FNAME, duidstr(duid), duid->duid_len); if (duid->duid_id != NULL && duid->duid_len != 0) { dprintf(LOG_DEBUG, "%s" "removing ID (ID: %s)", FNAME, duidstr(duid)); free(duid->duid_id); duid->duid_id = NULL; duid->duid_len = 0; } duid->duid_len = 0;}char *dhcp6optstr(type) int type;{ static char genstr[sizeof("opt_65535") + 1]; /* XXX thread unsafe */ if (type > 65535) return "INVALID option"; switch(type) { case DH6OPT_CLIENTID: return "client ID"; case DH6OPT_SERVERID: return "server ID"; case DH6OPT_ORO: return "option request"; case DH6OPT_PREFERENCE: return "preference"; case DH6OPT_STATUS_CODE: return "status code"; case DH6OPT_RAPID_COMMIT: return "rapid commit"; case DH6OPT_DNS_RESOLVERS: return "DNS_RESOLVERS"; default: sprintf(genstr, "opt_%d", type); return (genstr); }}char *dhcp6msgstr(type) int type;{ static char genstr[sizeof("msg255") + 1]; /* XXX thread unsafe */ if (type > 255) return "INVALID msg"; switch(type) { case DH6_SOLICIT: return "solicit"; case DH6_ADVERTISE: return "advertise"; case DH6_RENEW: return "renew"; case DH6_REBIND: return "rebind"; case DH6_REQUEST: return "request"; case DH6_REPLY: return "reply"; case DH6_CONFIRM: return "confirm"; case DH6_RELEASE: return "release"; case DH6_DECLINE: return "decline"; case DH6_INFORM_REQ: return "information request"; case DH6_RECONFIGURE: return "reconfigure"; case DH6_RELAY_FORW: return "relay forwarding"; case DH6_RELAY_REPL: return "relay reply"; default: sprintf(genstr, "msg%d", type); return (genstr); }}char *dhcp6_stcodestr(code) int code;{ static char genstr[sizeof("code255") + 1]; /* XXX thread unsafe */ if (code > 255) return "INVALID code"; switch(code) { case DH6OPT_STCODE_SUCCESS: return "success"; case DH6OPT_STCODE_UNSPECFAIL: return "unspec failure"; case DH6OPT_STCODE_AUTHFAILED: return "auth fail"; case DH6OPT_STCODE_ADDRUNAVAIL: return "address unavailable"; case DH6OPT_STCODE_NOADDRAVAIL: return "no addresses"; case DH6OPT_STCODE_NOBINDING: return "no binding"; case DH6OPT_STCODE_CONFNOMATCH: return "confirm no match"; case DH6OPT_STCODE_NOTONLINK: return "not on-link"; case DH6OPT_STCODE_USEMULTICAST: return "use multicast"; default: sprintf(genstr, "code%d", code); return (genstr); }}char *duidstr(const struct duid *duid){ int i; char *cp; static char duidstr[sizeof("xx:") * 256 + sizeof("...")]; duidstr[0] ='\0'; cp = duidstr; for (i = 0; i < duid->duid_len && i <= 256; i++) { cp += sprintf(cp, "%s%02x", i == 0 ? "" : ":", duid->duid_id[i] & 0xff); } if (i < duid->duid_len) sprintf(cp, "%s", "..."); return (duidstr);}voidsetloglevel(debuglevel) int debuglevel;{ if (foreground) { switch(debuglevel) { case 0: debug_thresh = LOG_ERR; break; case 1: debug_thresh = LOG_INFO; break; default: debug_thresh = LOG_DEBUG; break; } } else { switch(debuglevel) { case 0: setlogmask(LOG_UPTO(LOG_ERR)); break; case 1: setlogmask(LOG_UPTO(LOG_INFO)); break; } }}voiddprintf(int level, const char *fmt, ...){ va_list ap; char logbuf[LINE_MAX]; va_start(ap, fmt); vsnprintf(logbuf, sizeof(logbuf), fmt, ap); if (foreground && debug_thresh >= level) { time_t now; struct tm *tm_now; const char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", }; if ((now = time(NULL)) < 0) exit(1); /* XXX */ tm_now = localtime(&now); fprintf(stderr, "%3s/%02d/%04d %02d:%02d:%02d %s\n", month[tm_now->tm_mon], tm_now->tm_mday, tm_now->tm_year + 1900, tm_now->tm_hour, tm_now->tm_min, tm_now->tm_sec, logbuf); } else syslog(level, "%s", logbuf);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -