📄 config.c
字号:
cp += 2; bp++; } duid->duid_len = duidlen; duid->duid_id = idbuf; return(0); bad: if (idbuf) free(idbuf); dprintf(LOG_ERR, "%s" "assumption failure (bad string)", FNAME); return(-1);}/* we currently only construct EUI-64 based interface ID */static intget_default_ifid(pif) struct prefix_ifconf *pif;{ struct ifaddrs *ifa, *ifap; struct sockaddr_dl *sdl; if (pif->ifid_len < 64) { dprintf(LOG_NOTICE, "%s" "ID length too short", FNAME); return -1; } if (getifaddrs(&ifap) < 0) { dprintf(LOG_ERR, "%s" "getifaddrs failed: %s", FNAME, strerror(errno)); return -1; } for (ifa = ifap; ifa; ifa = ifa->ifa_next) { char *cp; if (strcmp(ifa->ifa_name, pif->ifname) != 0) continue; if (ifa->ifa_addr->sa_family != AF_LINK) continue; sdl = (struct sockaddr_dl *)ifa->ifa_addr; if (sdl->sdl_alen < 6) { dprintf(LOG_NOTICE, "%s" "link layer address is too short (%s)", FNAME, pif->ifname); goto fail; } memset(pif->ifid, 0, sizeof(pif->ifid)); cp = (char *)(sdl->sdl_data + sdl->sdl_nlen); pif->ifid[8] = cp[0]; pif->ifid[8] ^= 0x02; /* reverse the u/l bit*/ pif->ifid[9] = cp[1]; pif->ifid[10] = cp[2]; pif->ifid[11] = 0xff; pif->ifid[12] = 0xfe; pif->ifid[13] = cp[3]; pif->ifid[14] = cp[4]; pif->ifid[15] = cp[5]; break; } if (ifa == NULL) { dprintf(LOG_INFO, "%s" "cannot find interface information for %s", FNAME, pif->ifname); goto fail; } freeifaddrs(ifap); return(0); fail: freeifaddrs(ifap); return(-1);}voidconfigure_cleanup(){ clear_ifconf(dhcp6_ifconflist); dhcp6_ifconflist = NULL; clear_prefixifconf(prefix_ifconflist0); prefix_ifconflist0 = NULL; clear_hostconf(host_conflist0); host_conflist0 = NULL; dhcp6_clear_list(&dnslist0); TAILQ_INIT(&dnslist0);}voidconfigure_commit(){ struct dhcp6_ifconf *ifc; struct dhcp6_if *ifp; /* commit interface configuration */ for (ifc = dhcp6_ifconflist; ifc; ifc = ifc->next) { if ((ifp = find_ifconfbyname(ifc->ifname)) != NULL) { ifp->send_flags = ifc->send_flags; ifp->allow_flags = ifc->allow_flags; clear_options(ifp->send_options); ifp->send_options = ifc->send_options; ifc->send_options = NULL; dhcp6_clear_list(&ifp->reqopt_list); ifp->reqopt_list = ifc->reqopt_list; TAILQ_INIT(&ifc->reqopt_list); ifp->server_pref = ifc->server_pref; } } clear_ifconf(dhcp6_ifconflist); /* commit prefix configuration */ if (prefix_ifconflist) { /* clear previous configuration. (need more work?) */ clear_prefixifconf(prefix_ifconflist); } prefix_ifconflist = prefix_ifconflist0; prefix_ifconflist0 = NULL; /* commit prefix configuration */ if (host_conflist) { /* clear previous configuration. (need more work?) */ clear_hostconf(host_conflist); } host_conflist = host_conflist0; host_conflist0 = NULL; /* commit DNS addresses */ if (!TAILQ_EMPTY(&dnslist)) { dhcp6_clear_list(&dnslist); } dnslist = dnslist0; TAILQ_INIT(&dnslist0);}static voidclear_ifconf(iflist) struct dhcp6_ifconf *iflist;{ struct dhcp6_ifconf *ifc, *ifc_next; for (ifc = iflist; ifc; ifc = ifc_next) { ifc_next = ifc->next; free(ifc->ifname); clear_options(ifc->send_options); dhcp6_clear_list(&ifc->reqopt_list); free(ifc); }}static voidclear_prefixifconf(iflist) struct prefix_ifconf *iflist;{ struct prefix_ifconf *pif, *pif_next; for (pif = iflist; pif; pif = pif_next) { pif_next = pif->next; free(pif->ifname); free(pif); }}static voidclear_hostconf(hlist) struct host_conf *hlist;{ struct host_conf *host, *host_next; struct dhcp6_listval *p; for (host = hlist; host; host = host_next) { host_next = host->next; free(host->name); while (p = TAILQ_FIRST(&host->prefix_list)) { TAILQ_REMOVE(&host->prefix_list, p, link); free(p); } if (host->duid.duid_id) free(host->duid.duid_id); free(host); }}static voidclear_options(opt0) struct dhcp6_optconf *opt0;{ struct dhcp6_optconf *opt, *opt_next; for (opt = opt0; opt; opt = opt_next) { opt_next = opt->next; free(opt->val); free(opt); }}static intadd_options(opcode, ifc, cfl0) int opcode; struct dhcp6_ifconf *ifc; struct cf_list *cfl0;{ struct dhcp6_listval *opt; struct cf_list *cfl; int opttype; for (cfl = cfl0; cfl; cfl = cfl->next) { if (opcode == DHCPOPTCODE_REQUEST) { for (TAILQ_FIRST(&ifc->reqopt_list); opt; opt = TAILQ_NEXT(opt, link)) { if (opt->val_num == cfl->type) { dprintf(LOG_INFO, "%s" "duplicated requested" " option: %s", FNAME, dhcp6optstr(cfl->type)); goto next; /* ignore it */ } } } switch(cfl->type) { case DHCPOPT_RAPID_COMMIT: switch(opcode) { case DHCPOPTCODE_SEND: ifc->send_flags |= DHCIFF_RAPID_COMMIT; break; case DHCPOPTCODE_ALLOW: ifc->allow_flags |= DHCIFF_RAPID_COMMIT; break; default: dprintf(LOG_ERR, "%s" "invalid operation (%d) " "for option type (%d)", FNAME, opcode, cfl->type); return(-1); } break; case DHCPOPT_PREFIX_DELEGATION: switch(opcode) { case DHCPOPTCODE_REQUEST: opttype = DH6OPT_PREFIX_DELEGATION; if (dhcp6_add_listval(&ifc->reqopt_list, &opttype, DHCP6_LISTVAL_NUM) == NULL) { dprintf(LOG_ERR, "%s" "failed to " "configure an option", FNAME); return(-1); } break; default: dprintf(LOG_ERR, "%s" "invalid operation (%d) " "for option type (%d)", FNAME, opcode, cfl->type); break; } break; case DHCPOPT_DNS: switch(opcode) { case DHCPOPTCODE_REQUEST: opttype = DH6OPT_DNS; if (dhcp6_add_listval(&ifc->reqopt_list, &opttype, DHCP6_LISTVAL_NUM) == NULL) { dprintf(LOG_ERR, "%s" "failed to " "configure an option", FNAME); return(-1); } break; default: dprintf(LOG_ERR, "%s" "invalid operation (%d) " "for option type (%d)", FNAME, opcode, cfl->type); break; } break; default: dprintf(LOG_ERR, "%s" "unknown option type: %d", FNAME, cfl->type); return(-1); } next: } return(0);}static intadd_prefix(hconf, prefix0) struct host_conf *hconf; struct dhcp6_prefix *prefix0;{ struct dhcp6_prefix oprefix; struct dhcp6_listval *p, *pent; oprefix = *prefix0; /* additional validation of parameters */ if (oprefix.plen < 0 || oprefix.plen > 128) { dprintf(LOG_ERR, "%s" "invalid prefix: %d", FNAME, oprefix.plen); return(-1); } /* clear trailing bits */ prefix6_mask(&oprefix.addr, oprefix.plen); if (!IN6_ARE_ADDR_EQUAL(&prefix0->addr, &oprefix.addr)) { dprintf(LOG_WARNING, "%s" "prefix %s/%d for %s " "has a trailing garbage. It should be %s/%d", FNAME, in6addr2str(&prefix0->addr, 0), prefix0->plen, hconf->name, in6addr2str(&oprefix.addr, 0), oprefix.plen); /* ignore the error */ } /* avoid invalid prefix addresses */ if (IN6_IS_ADDR_MULTICAST(&oprefix.addr) || IN6_IS_ADDR_LINKLOCAL(&oprefix.addr) || IN6_IS_ADDR_SITELOCAL(&oprefix.addr)) { dprintf(LOG_ERR, "%s" "invalid prefix address: %s", FNAME, in6addr2str(&oprefix.addr, 0)); return(-1); } /* prefix duplication check */ for (p = TAILQ_FIRST(&hconf->prefix_list); p; p = TAILQ_NEXT(p, link)) { if (IN6_ARE_ADDR_EQUAL(&p->val_prefix6.addr, &oprefix.addr) && p->val_prefix6.plen == oprefix.plen) { dprintf(LOG_ERR, "%s" "duplicated prefix: %s/%d for %s", FNAME, in6addr2str(&oprefix.addr, 0), oprefix.plen, hconf->name); return(-1); } } /* allocate memory for the new prefix and insert it to the chain */ if ((pent = malloc(sizeof(*pent))) == NULL) { dprintf(LOG_ERR, "%s" "memory allocation failed for %s", FNAME, hconf->name); return(-1); } memset(pent, 0, sizeof(*pent)); pent->val_prefix6 = oprefix; TAILQ_INSERT_TAIL(&hconf->prefix_list, pent, link); return(0);}struct dhcp6_if *find_ifconfbyname(ifname) char *ifname;{ struct dhcp6_if *ifp; for (ifp = dhcp6_if; ifp; ifp = ifp->next) { if (strcmp(ifp->ifname, ifname) == 0) return(ifp); } return(NULL);}struct dhcp6_if *find_ifconfbyid(id) unsigned int id;{ struct dhcp6_if *ifp; for (ifp = dhcp6_if; ifp; ifp = ifp->next) { if (ifp->ifid == id) return(ifp); } return(NULL);}struct prefix_ifconf *find_prefixifconf(ifname) char *ifname;{ struct prefix_ifconf *ifp; for (ifp = prefix_ifconflist; ifp; ifp = ifp->next) { if (strcmp(ifp->ifname, ifname) == NULL) return(ifp); } return(NULL);}struct host_conf *find_hostconf(duid) struct duid *duid;{ struct host_conf *host; for (host = host_conflist; host; host = host->next) { if (host->duid.duid_len == duid->duid_len && memcmp(host->duid.duid_id, duid->duid_id, host->duid.duid_len) == 0) { return(host); } } return(NULL);}struct dhcp6_prefix *find_prefix6(list, prefix) struct dhcp6_list *list; struct dhcp6_prefix *prefix;{ struct dhcp6_listval *v; for (v = TAILQ_FIRST(list); v; v = TAILQ_NEXT(v, link)) { if (v->val_prefix6.plen == prefix->plen && IN6_ARE_ADDR_EQUAL(&v->val_prefix6.addr, &prefix->addr)) { return(&v->val_prefix6); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -