⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 server6_addr.c

📁 DHCPv6协议在Linux操作系统下的一个客户端实现。
💻 C
📖 第 1 页 / 共 2 页
字号:
			if (ifaddr->type == IAPD) {				if (sp->lease_addr.plen == ifaddr->plen)					return (sp);			} else if (ifaddr->type == IANA || ifaddr->type == IATA)				return (sp);		}	}	return (NULL);}struct dhcp6_timer *dhcp6_iaidaddr_timo(void *arg){	struct dhcp6_iaidaddr *sp = (struct dhcp6_iaidaddr *)arg;	dprintf(LOG_DEBUG, "server6_iaidaddr timeout for %u, state=%d", 		sp->client6_info.iaidinfo.iaid, sp->state);	switch(sp->state) {	case ACTIVE:	case EXPIRED:		sp->state = EXPIRED;		dhcp6_remove_iaidaddr(sp);	default:		break;	}	return (NULL);}		struct dhcp6_timer *dhcp6_lease_timo(arg)	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);	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:	case INVALID:		sp->state = INVALID;		dhcp6_remove_lease(sp);		return (NULL);	default:		return (NULL);	}	return (sp->timer);}static voidget_random_bytes(u_int8_t seed[], int num){	int i;	for (i = 0; i < num; i++)		seed[i] = random();	return;}static void create_tempaddr(prefix, plen, tempaddr)	struct in6_addr *prefix;	int plen;	struct in6_addr *tempaddr;{	int i, num_bytes;	u_int8_t digest[16];	u_int8_t seed[16];	get_random_bytes(seed, 16);	/* address mask */	memset(tempaddr, 0, sizeof(*tempaddr));		num_bytes = plen / 8;	for (i = 0; i < num_bytes; i++) {		tempaddr->s6_addr[i] = prefix->s6_addr[i];	}	tempaddr->s6_addr[num_bytes] = (prefix->s6_addr[num_bytes] | (0xFF >> plen % 8)) 		& (seed[num_bytes] | ((0xFF << 8) - plen % 8));		for (i = num_bytes + 1; i < 16; i++) {		tempaddr->s6_addr[i] = seed[i];	}	return;}intdhcp6_get_hostconf(roptinfo, optinfo, iaidaddr, host)	struct host_decl *host;	struct dhcp6_iaidaddr *iaidaddr;	struct dhcp6_optinfo *optinfo, *roptinfo;{	struct dhcp6_list *reply_list = &roptinfo->addr_list;	struct dhcp6_list *req_list = &optinfo->addr_list;	struct dhcp6_listval *lv, *lv_next;		if (!(host->hostscope.allow_flags & DHCIFF_TEMP_ADDRS)) {		roptinfo->iaidinfo.renewtime = host->hostscope.renew_time;		roptinfo->iaidinfo.rebindtime = host->hostscope.rebind_time;		roptinfo->type = optinfo->type;		switch (optinfo->type) {		case IANA:			dhcp6_copy_list(reply_list, &host->addrlist);			break;		case IATA:			break;		case IAPD:			dhcp6_copy_list(reply_list, &host->prefixlist);			break;		}	}	return 0;}intdhcp6_create_addrlist(roptinfo, optinfo, iaidaddr, subnet)	struct dhcp6_optinfo *roptinfo;	struct dhcp6_optinfo *optinfo; 	const struct dhcp6_iaidaddr *iaidaddr;	const struct link_decl *subnet;{	struct dhcp6_listval *v6addr;	struct v6addrseg *seg;	struct dhcp6_list *reply_list = &roptinfo->addr_list;	struct dhcp6_list *req_list = &optinfo->addr_list;	int numaddr;	struct dhcp6_listval *lv, *lv_next = NULL;	roptinfo->iaidinfo.renewtime = subnet->linkscope.renew_time;	roptinfo->iaidinfo.rebindtime = subnet->linkscope.rebind_time;	roptinfo->type = optinfo->type;	/* check the duplication */	for (lv = TAILQ_FIRST(req_list); lv; lv = lv_next) {		lv_next = TAILQ_NEXT(lv, link);		if (addr_on_addrlist(reply_list, &lv->val_dhcp6addr)) {			TAILQ_REMOVE(req_list, lv, link);		}	}	       	dhcp6_copy_list(reply_list, req_list);	for (lv = TAILQ_FIRST(reply_list); lv; lv = lv_next) {			lv_next = TAILQ_NEXT(lv, link);		lv->val_dhcp6addr.type = optinfo->type;		lv->val_dhcp6addr.status_code = DH6OPT_STCODE_UNDEFINE;		lv->val_dhcp6addr.status_msg = NULL;	}	for (seg = subnet->seglist; seg; seg = seg->next) {		numaddr = 0;		for (lv = TAILQ_FIRST(reply_list); lv; lv = lv_next) {			lv_next = TAILQ_NEXT(lv, link);			/* skip checked segment */			if (lv->val_dhcp6addr.status_code == DH6OPT_STCODE_SUCCESS) 				continue;			if (IN6_IS_ADDR_RESERVED(&lv->val_dhcp6addr.addr) ||			    is_anycast(&lv->val_dhcp6addr.addr, seg->prefix.plen)) {				lv->val_dhcp6addr.status_code = DH6OPT_STCODE_NOTONLINK;				dprintf(LOG_DEBUG, "%s" " %s address not on link", FNAME, 					in6addr2str(&lv->val_dhcp6addr.addr, 0));				continue;			}			lv->val_dhcp6addr.type = optinfo->type;			if (addr_on_segment(seg, &lv->val_dhcp6addr)) {				if (numaddr == 0) {					lv->val_dhcp6addr.type = optinfo->type;					server6_get_addrpara(&lv->val_dhcp6addr, seg);					numaddr += 1;				} else {			/* check the addr count per seg, we only allow one address			 * per segment, set the status code */					lv->val_dhcp6addr.status_code 							= DH6OPT_STCODE_NOADDRAVAIL;				}			} else {				lv->val_dhcp6addr.status_code = DH6OPT_STCODE_NOTONLINK;				dprintf(LOG_DEBUG, "%s" " %s address not on link", FNAME, 					in6addr2str(&lv->val_dhcp6addr.addr, 0));			}		}		if (iaidaddr != NULL) {			struct dhcp6_lease *cl;			for (cl = TAILQ_FIRST(&iaidaddr->lease_list); cl; 					cl = TAILQ_NEXT(cl, link)) {				if (addr_on_segment(seg, &cl->lease_addr)) { 					if (addr_on_addrlist(reply_list, 								&cl->lease_addr)) {						continue;					} else if (numaddr == 0) {						v6addr = (struct dhcp6_listval *)malloc(sizeof(*v6addr));						if (v6addr == NULL) {							dprintf(LOG_ERR, "%s" 								"fail to allocate memory %s", 								FNAME, strerror(errno));							return (-1);						}						memset(v6addr, 0, sizeof(*v6addr));						memcpy(&v6addr->val_dhcp6addr, &cl->lease_addr,							sizeof(v6addr->val_dhcp6addr));							v6addr->val_dhcp6addr.type = optinfo->type;						server6_get_addrpara(&v6addr->val_dhcp6addr, 									seg);						numaddr += 1;						TAILQ_INSERT_TAIL(reply_list, v6addr, link);						continue;					}				}								}		}		if (numaddr == 0) {			v6addr = (struct dhcp6_listval *)malloc(sizeof(*v6addr));			if (v6addr == NULL) {				dprintf(LOG_ERR, "%s" "fail to allocate memory %s", 					FNAME, strerror(errno));				return (-1);			}			memset(v6addr, 0, sizeof(*v6addr));			v6addr->val_dhcp6addr.type = optinfo->type;			server6_get_newaddr(optinfo->type, &v6addr->val_dhcp6addr, seg);			if (IN6_IS_ADDR_UNSPECIFIED(&v6addr->val_dhcp6addr.addr)) {				free(v6addr);				continue;			}			TAILQ_INSERT_TAIL(reply_list, v6addr, link);		}	}	return (0);}static intaddr_on_segment(seg, addr)	struct v6addrseg *seg;	struct dhcp6_addr *addr;{	int onseg = 0;	struct v6addr *prefix;	dprintf(LOG_DEBUG, "%s" " checking address %s on segment", 		FNAME, in6addr2str(&addr->addr, 0));	switch (addr->type) {	case IATA:		prefix = getprefix(&addr->addr, seg->prefix.plen);		if (prefix && !memcmp(&seg->prefix, prefix, sizeof(seg->prefix))) {			dprintf(LOG_DEBUG, "%s" " address is on link", FNAME);			onseg = 1;		} else			onseg = 0;		free(prefix);		break;	case IANA:		if (ipv6addrcmp(&addr->addr, &seg->min) >= 0 &&		    ipv6addrcmp(&seg->max, &addr->addr) >= 0) {			dprintf(LOG_DEBUG, "%s" " address is on link", FNAME);			onseg = 1;		}		else 			onseg = 0;		break;	default:		break;	}	return onseg;	}static void server6_get_newaddr(type, v6addr, seg)	iatype_t type;	struct dhcp6_addr *v6addr;	struct v6addrseg *seg;{	struct in6_addr current;	int round = 0;	memcpy(&current, &seg->free, sizeof(current));	do {		v6addr->type = type;		switch(type) {		case IATA:			/* assume the temp addr never being run out */			create_tempaddr(&seg->prefix.addr, seg->prefix.plen, &v6addr->addr);			break;			case IANA:			memcpy(&v6addr->addr, &seg->free, sizeof(v6addr->addr));			if (round && IN6_ARE_ADDR_EQUAL(&current, &v6addr->addr)) {				memset(&v6addr->addr, 0, sizeof(v6addr->addr));				break;			}			inc_ipv6addr(&seg->free);			if (ipv6addrcmp(&seg->free, &seg->max) == 1 ) {				round = 1;				memcpy(&seg->free, &seg->min, sizeof(seg->free));			}			break;		default:			break;		}	} while ((hash_search(lease_hash_table, (void *)v6addr) != NULL) ||		 (hash_search(host_addr_hash_table, (void *)&v6addr->addr) != NULL) ||		 (is_anycast(&v6addr->addr, seg->prefix.plen)));	if (IN6_IS_ADDR_UNSPECIFIED(&v6addr->addr)) {		return;	}	dprintf(LOG_DEBUG, "new address %s is got", in6addr2str(&v6addr->addr, 0));	server6_get_addrpara(v6addr, seg);	return;}static voidserver6_get_prefixpara(v6addr, seg)	struct dhcp6_addr *v6addr;	struct v6prefix *seg;{	v6addr->plen = seg->prefix.plen;	if (seg->parainfo.prefer_life_time == 0 && seg->parainfo.valid_life_time == 0) {		seg->parainfo.valid_life_time = DEFAULT_VALID_LIFE_TIME;		seg->parainfo.prefer_life_time = DEFAULT_PREFERRED_LIFE_TIME;	} else if (seg->parainfo.prefer_life_time == 0) {		seg->parainfo.prefer_life_time = seg->parainfo.valid_life_time / 2;	} else if (seg->parainfo.valid_life_time == 0) {		seg->parainfo.valid_life_time = 2 * seg->parainfo.prefer_life_time;	}	dprintf(LOG_DEBUG, " preferlifetime %u, validlifetime %u", 		seg->parainfo.prefer_life_time, seg->parainfo.valid_life_time);	dprintf(LOG_DEBUG, " renewtime %u, rebindtime %u", 		seg->parainfo.renew_time, seg->parainfo.rebind_time);	v6addr->preferlifetime = seg->parainfo.prefer_life_time;	v6addr->validlifetime = seg->parainfo.valid_life_time;	v6addr->status_code = DH6OPT_STCODE_SUCCESS;	v6addr->status_msg = NULL;	return;}static voidserver6_get_addrpara(v6addr, seg)	struct dhcp6_addr *v6addr;	struct v6addrseg *seg;{	v6addr->plen = seg->prefix.plen;	if (seg->parainfo.prefer_life_time == 0 && seg->parainfo.valid_life_time == 0) {		seg->parainfo.valid_life_time = DEFAULT_VALID_LIFE_TIME;		seg->parainfo.prefer_life_time = DEFAULT_PREFERRED_LIFE_TIME;	} else if (seg->parainfo.prefer_life_time == 0) {		seg->parainfo.prefer_life_time = seg->parainfo.valid_life_time / 2;	} else if (seg->parainfo.valid_life_time == 0) {		seg->parainfo.valid_life_time = 2 * seg->parainfo.prefer_life_time;	}	dprintf(LOG_DEBUG, " preferlifetime %u, validlifetime %u",		seg->parainfo.prefer_life_time, seg->parainfo.valid_life_time);	dprintf(LOG_DEBUG, " renewtime %u, rebindtime %u", 		seg->parainfo.renew_time, seg->parainfo.rebind_time);	v6addr->preferlifetime = seg->parainfo.prefer_life_time;	v6addr->validlifetime = seg->parainfo.valid_life_time;	v6addr->status_code = DH6OPT_STCODE_SUCCESS;	v6addr->status_msg = NULL;	return;}intdhcp6_create_prefixlist(roptinfo, optinfo, iaidaddr, subnet)	struct dhcp6_optinfo *roptinfo;	const struct dhcp6_optinfo *optinfo; 	const struct dhcp6_iaidaddr *iaidaddr;	const struct link_decl *subnet;{	struct dhcp6_listval *v6addr;	struct v6prefix *prefix6;	struct dhcp6_list *reply_list = &roptinfo->addr_list;	const struct dhcp6_list *req_list = &optinfo->addr_list;	struct dhcp6_listval *lv, *lv_next = NULL;	/* XXX: ToDo check hostdecl first */	roptinfo->iaidinfo.renewtime = subnet->linkscope.renew_time;	roptinfo->iaidinfo.rebindtime = subnet->linkscope.rebind_time;	roptinfo->type = optinfo->type;	for (prefix6 = subnet->prefixlist; prefix6; prefix6 = prefix6->next) {		v6addr = (struct dhcp6_listval *)malloc(sizeof(*v6addr));		if (v6addr == NULL) {			dprintf(LOG_ERR, "%s" "fail to allocate memory", FNAME);			return (-1);		}		memset(v6addr, 0, sizeof(*v6addr));		/* XXX: ToDo: get new paras */		memcpy(&v6addr->val_dhcp6addr.addr, &prefix6->prefix.addr, 				sizeof(v6addr->val_dhcp6addr.addr));		v6addr->val_dhcp6addr.plen = prefix6->prefix.plen;		v6addr->val_dhcp6addr.type = IAPD;		server6_get_prefixpara(&v6addr->val_dhcp6addr, prefix6);		dprintf(LOG_DEBUG, " get prefix %s/%d, "			"preferlifetime %u, validlifetime %u",			in6addr2str(&v6addr->val_dhcp6addr.addr, 0), 			v6addr->val_dhcp6addr.plen,			v6addr->val_dhcp6addr.preferlifetime, 			v6addr->val_dhcp6addr.validlifetime);		TAILQ_INSERT_TAIL(reply_list, v6addr, link);	}	for (prefix6 = subnet->prefixlist; prefix6; prefix6 = prefix6->next) {		for (lv = TAILQ_FIRST(req_list); lv; lv = lv_next) {			lv_next = TAILQ_NEXT(lv, link);			if (IN6_IS_ADDR_RESERVED(&lv->val_dhcp6addr.addr) ||			    is_anycast(&lv->val_dhcp6addr.addr, prefix6->prefix.plen) ||			    !addr_on_addrlist(reply_list, &lv->val_dhcp6addr)) {				lv->val_dhcp6addr.status_code = DH6OPT_STCODE_NOTONLINK;				dprintf(LOG_DEBUG, " %s prefix not on link", 					in6addr2str(&lv->val_dhcp6addr.addr, 0));				lv->val_dhcp6addr.type = IAPD;				TAILQ_INSERT_TAIL(reply_list, lv, link);			}		}	}	return (0);}struct host_decl *dhcp6_allocate_host(ifp, rootgroup, optinfo)	struct dhcp6_if *ifp;	struct rootgroup *rootgroup;	struct dhcp6_optinfo *optinfo;{	struct host_decl *host = NULL;	struct interface *ifnetwork;	struct duid *duid = &optinfo->clientID;	u_int32_t iaid = optinfo->iaidinfo.iaid;	for (ifnetwork = rootgroup->iflist; ifnetwork; ifnetwork = ifnetwork->next) {		if (strcmp(ifnetwork->name, ifp->ifname) != 0)			continue;		else {			host = find_hostdecl(duid, iaid, ifnetwork->hostlist);			break;		}	}	return host;}struct link_decl *dhcp6_allocate_link(ifp, rootgroup, relay)	struct dhcp6_if *ifp;	struct rootgroup *rootgroup;	struct in6_addr *relay;{	struct link_decl *link;	struct interface *ifnetwork;	ifnetwork = rootgroup->iflist;	for (ifnetwork = rootgroup->iflist; ifnetwork; ifnetwork = ifnetwork->next) {		if (strcmp(ifnetwork->name, ifp->ifname) != 0)			continue;		else {			for (link = ifnetwork->linklist; link; link = link->next) {				/* without relay agent support, so far we assume				 * that client and server on the same link, no relay				 */				struct v6addrlist *temp;				if (relay == NULL) {					if (link->relaylist != NULL) 						continue;					else						return link;				} else {					for (temp = link->relaylist; temp; temp = temp->next) {						if (IN6_ARE_ADDR_EQUAL(relay, 									&temp->v6addr.addr))							return link;						else							continue;					}				}			}		}	}	return NULL;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -