📄 client6_addr.c
字号:
if (client6_iaidaddr.state == REBIND) { if (duidcpy(&client6_iaidaddr.client6_info.serverid, &optinfo->serverID)) { dprintf(LOG_ERR, "%s" "failed to copy server ID", FNAME); return (-1); } } if (TAILQ_EMPTY(&client6_iaidaddr.lease_list)) return (0); /* set up renew T1, rebind T2 timer renew/rebind based on iaid */ /* Should we process IA_TA, IA_NA differently */ if (client6_iaidaddr.client6_info.iaidinfo.renewtime == 0) { u_int32_t min_plifetime; min_plifetime = get_min_preferlifetime(&client6_iaidaddr); if (min_plifetime == DHCP6_DURATITION_INFINITE) client6_iaidaddr.client6_info.iaidinfo.renewtime = min_plifetime; else client6_iaidaddr.client6_info.iaidinfo.renewtime = min_plifetime / 2; } if (client6_iaidaddr.client6_info.iaidinfo.rebindtime == 0) { client6_iaidaddr.client6_info.iaidinfo.rebindtime = get_min_preferlifetime(&client6_iaidaddr) * 4 / 5; } dprintf(LOG_INFO, "renew time %d, rebind time %d", client6_iaidaddr.client6_info.iaidinfo.renewtime, client6_iaidaddr.client6_info.iaidinfo.rebindtime); if (client6_iaidaddr.client6_info.iaidinfo.renewtime == 0) return (0); if (client6_iaidaddr.client6_info.iaidinfo.renewtime == DHCP6_DURATITION_INFINITE) { client6_iaidaddr.client6_info.iaidinfo.rebindtime == DHCP6_DURATITION_INFINITE; if (client6_iaidaddr.timer) dhcp6_remove_timer(client6_iaidaddr.timer); return (0); } /* update the start date and timer */ if (client6_iaidaddr.timer == NULL) { if ((client6_iaidaddr.timer = dhcp6_add_timer(dhcp6_iaidaddr_timo, &client6_iaidaddr)) == NULL) { dprintf(LOG_ERR, "%s" "failed to add a timer for iaid %u", FNAME, client6_iaidaddr.client6_info.iaidinfo.iaid); return (-1); } } time(&client6_iaidaddr.start_date); client6_iaidaddr.state = ACTIVE; d = client6_iaidaddr.client6_info.iaidinfo.renewtime; timo.tv_sec = (long)d; timo.tv_usec = 0; dhcp6_set_timer(&timo, client6_iaidaddr.timer); return 0;}static intdhcp6_update_lease(struct dhcp6_addr *addr, struct dhcp6_lease *sp){ struct timeval timo; double d; if (addr->status_code != DH6OPT_STCODE_SUCCESS && addr->status_code != DH6OPT_STCODE_UNDEFINE) { dprintf(LOG_ERR, "%s" "not successful status code for %s is %s", FNAME, in6addr2str(&addr->addr, 0), dhcp6_stcodestr(addr->status_code)); dhcp6_remove_lease(sp); return (0); } /* remove leases with validlifetime == 0, and preferlifetime == 0 */ if (addr->validlifetime == 0 || addr->preferlifetime == 0 || addr->preferlifetime > addr->validlifetime) { dprintf(LOG_ERR, "%s" "invalid address life time for %s", FNAME, in6addr2str(&addr->addr, 0)); dhcp6_remove_lease(sp); return (0); } memcpy(&sp->lease_addr, addr, sizeof(sp->lease_addr)); sp->state = ACTIVE; time(&sp->start_date); if (write_lease(sp, client6_lease_file) != 0) { dprintf(LOG_ERR, "%s" "failed to write an updated lease address %s to lease file", FNAME, in6addr2str(&sp->lease_addr.addr, 0)); return (-1); } if (sp->lease_addr.validlifetime == DHCP6_DURATITION_INFINITE || sp->lease_addr.preferlifetime == DHCP6_DURATITION_INFINITE) { dprintf(LOG_INFO, "%s" "infinity address life time for %s", FNAME, in6addr2str(&addr->addr, 0)); if (sp->timer) dhcp6_remove_timer(sp->timer); return (0); } if (sp->timer == NULL) { if ((sp->timer = dhcp6_add_timer(dhcp6_lease_timo, sp)) == NULL) { dprintf(LOG_ERR, "%s" "failed to add a timer for lease %s", FNAME, in6addr2str(&addr->addr, 0)); return (-1); } } d = sp->lease_addr.preferlifetime; timo.tv_sec = (long)d; timo.tv_usec = 0; dhcp6_set_timer(&timo, sp->timer); return (0);}struct dhcp6_lease *dhcp6_find_lease(struct dhcp6_iaidaddr *iaidaddr, struct dhcp6_addr *ifaddr){ struct dhcp6_lease *sp; for (sp = TAILQ_FIRST(&iaidaddr->lease_list); sp; sp = TAILQ_NEXT(sp, link)) { /* sp->lease_addr.plen == ifaddr->plen */ dprintf(LOG_DEBUG, "%s" "get address is %s/%d ", FNAME, in6addr2str(&ifaddr->addr, 0), ifaddr->plen); dprintf(LOG_DEBUG, "%s" "lease address is %s/%d ", FNAME, in6addr2str(&sp->lease_addr.addr, 0), ifaddr->plen); if (IN6_ARE_ADDR_EQUAL(&sp->lease_addr.addr, &ifaddr->addr)) { if (sp->lease_addr.type == IAPD) { if (sp->lease_addr.plen == ifaddr->plen) return (sp); } else if (sp->lease_addr.type == IANA || sp->lease_addr.type == IATA) return (sp); } } return (NULL);}struct dhcp6_timer *dhcp6_iaidaddr_timo(void *arg){ struct dhcp6_iaidaddr *sp = (struct dhcp6_iaidaddr *)arg; struct dhcp6_event *ev; struct timeval timeo; int dhcpstate; double d = 0; dprintf(LOG_DEBUG, "client6_iaidaddr timeout for %d, state=%d", client6_iaidaddr.client6_info.iaidinfo.iaid, sp->state); dhcp6_clear_list(&request_list); TAILQ_INIT(&request_list); /* ToDo: what kind of opiton Request value, client would like to pass? */ switch(sp->state) { case ACTIVE: sp->state = RENEW; dhcpstate = DHCP6S_RENEW; d = sp->client6_info.iaidinfo.rebindtime - sp->client6_info.iaidinfo.renewtime; timeo.tv_sec = (long)d; timeo.tv_usec = 0; break; case RENEW: sp->state = REBIND; dhcpstate = DHCP6S_REBIND; d = get_max_validlifetime(&client6_iaidaddr) - sp->client6_info.iaidinfo.rebindtime; timeo.tv_sec = (long)d; timeo.tv_usec = 0; if (sp->client6_info.serverid.duid_id != NULL) duidfree(&sp->client6_info.serverid); break; case REBIND: dprintf(LOG_INFO, "%s" "failed to rebind a client6_iaidaddr %d" " go to solicit and request new ipv6 addresses", FNAME, client6_iaidaddr.client6_info.iaidinfo.iaid); sp->state = INVALID; dhcpstate = DHCP6S_SOLICIT; free_servers(sp->ifp); break; default: return (NULL); } if ((ev = dhcp6_create_event(sp->ifp, dhcpstate)) == NULL) { dprintf(LOG_ERR, "%s" "failed to create a new event", FNAME); return (NULL); /* XXX: should try to recover reserve memory?? */ } switch(sp->state) { case RENEW: if (duidcpy(&ev->serverid, &sp->client6_info.serverid)) { dprintf(LOG_ERR, "%s" "failed to copy server ID", FNAME); return (NULL); } case REBIND: /* BUG: d not set! */ ev->max_retrans_dur = d; break; default: break; } if ((ev->timer = dhcp6_add_timer(client6_timo, ev)) == NULL) { dprintf(LOG_ERR, "%s" "failed to create a new event timer", FNAME); free(ev); return (NULL); /* XXX */ } TAILQ_INSERT_TAIL(&sp->ifp->event_list, ev, link); if (sp->state != INVALID) { struct dhcp6_lease *cl; /* create an address list for renew and rebind */ for (cl = TAILQ_FIRST(&client6_iaidaddr.lease_list); cl; cl = TAILQ_NEXT(cl, link)) { struct dhcp6_listval *lv; /* IA_NA address */ if ((lv = malloc(sizeof(*lv))) == NULL) { dprintf(LOG_ERR, "%s" "failed to allocate memory for an ipv6 addr", FNAME); return (NULL); } memcpy(&lv->val_dhcp6addr, &cl->lease_addr, sizeof(lv->val_dhcp6addr)); lv->val_dhcp6addr.status_code = DH6OPT_STCODE_UNDEFINE; TAILQ_INSERT_TAIL(&request_list, lv, link); } dhcp6_set_timer(&timeo, sp->timer); } else { dhcp6_remove_iaidaddr(&client6_iaidaddr); /* remove event data for that event */ sp->timer = NULL; } ev->timeouts = 0; dhcp6_set_timeoparam(ev); dhcp6_reset_timer(ev); client6_send(ev); return (sp->timer);}struct dhcp6_timer *dhcp6_lease_timo(void *arg){ struct dhcp6_lease *sp = (struct dhcp6_lease *)arg; struct timeval timeo; double d; dprintf(LOG_DEBUG, "%s" "lease timeout for %s, state=%d", FNAME, in6addr2str(&sp->lease_addr.addr, 0), sp->state); /* cancel the current event for this lease */ if (sp->state == INVALID) { dprintf(LOG_INFO, "%s" "failed to remove an addr %s", FNAME, in6addr2str(&sp->lease_addr.addr, 0)); dhcp6_remove_lease(sp); return (NULL); } switch(sp->state) { case ACTIVE: sp->state = EXPIRED; d = sp->lease_addr.validlifetime - sp->lease_addr.preferlifetime; timeo.tv_sec = (long)d; timeo.tv_usec = 0; dhcp6_set_timer(&timeo, sp->timer); break; case EXPIRED: sp->state = INVALID; dhcp6_remove_lease(sp); default: return (NULL); } return (sp->timer);}intclient6_ifaddrconf(ifaddrconf_cmd_t cmd, struct dhcp6_addr *ifaddr){ struct in6_ifreq req; struct dhcp6_if *ifp = client6_iaidaddr.ifp; unsigned long ioctl_cmd; char *cmdstr; int s, errno; switch(cmd) { case IFADDRCONF_ADD: cmdstr = "add"; ioctl_cmd = SIOCSIFADDR; break; case IFADDRCONF_REMOVE: cmdstr = "remove"; ioctl_cmd = SIOCDIFADDR; break; default: return (-1); } if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { dprintf(LOG_ERR, "%s" "can't open a temporary socket: %s", FNAME, strerror(errno)); return (-1); } memset(&req, 0, sizeof(req)); req.ifr6_ifindex = if_nametoindex(ifp->ifname); memcpy(&req.ifr6_addr, &ifaddr->addr, sizeof(req.ifr6_addr)); req.ifr6_prefixlen = ifaddr->plen; if (ioctl(s, ioctl_cmd, &req) && errno != EEXIST) { dprintf(LOG_NOTICE, "%s" "failed to %s an address on %s: %s", FNAME, cmdstr, ifp->ifname, strerror(errno)); close(s); return (-1); } dprintf(LOG_DEBUG, "%s" "%s an address %s on %s", FNAME, cmdstr, in6addr2str(&ifaddr->addr, 0), ifp->ifname); close(s); return (0);}intget_iaid(const char *ifname, const struct iaid_table *iaidtab, int num_device){ struct hardware hdaddr; struct iaid_table *temp = (struct iaid_table *)iaidtab; int i; hdaddr.len = gethwid(hdaddr.data, 6, ifname, &hdaddr.type); for (i = 0; i < num_device; i++, temp++) { if (!memcmp(temp->hwaddr.data, hdaddr.data, temp->hwaddr.len) && hdaddr.len == temp->hwaddr.len && hdaddr.type == temp->hwaddr.type) { dprintf(LOG_DEBUG, "%s"" found interface %s iaid %u", FNAME, ifname, temp->iaid); return temp->iaid; } else continue; } return 0;}int create_iaid(struct iaid_table *iaidtab, int num_device){ struct iaid_table *temp = iaidtab; char buff[1024]; struct ifconf ifc; struct ifreq *ifr, if_hwaddr; int i; ifc.ifc_len = sizeof(buff); ifc.ifc_buf = buff; if (ioctl(nlsock, SIOCGIFCONF, &ifc) < 0) { dprintf(LOG_ERR, "%s" "ioctl SIOCGIFCONF", FNAME); return -1; } ifr = ifc.ifc_req; for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0 && num_device < MAX_DEVICE; ifr++) { if (!strcmp(ifr->ifr_name, "lo")) continue; temp->hwaddr.len = gethwid(temp->hwaddr.data, sizeof(temp->hwaddr.data), ifr->ifr_name, &temp->hwaddr.type); switch (temp->hwaddr.type) { case ARPHRD_ETHER: case ARPHRD_IEEE802: memcpy(&temp->iaid, temp->hwaddr.data, sizeof(temp->iaid)); break; case ARPHRD_PPP: temp->iaid = do_hash(ifr->ifr_name,sizeof(ifr->ifr_name)) + if_nametoindex(ifr->ifr_name); break; default: dprintf(LOG_INFO, "doesn't support %s address family %d", ifr->ifr_name, temp->hwaddr.type); continue; } dprintf(LOG_DEBUG, "%s"" create iaid %u for interface %s", FNAME, temp->iaid, ifr->ifr_name); num_device++; temp++; } return num_device;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -