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

📄 client6_addr.c

📁 DHCPv6协议在Linux操作系统下的一个客户端实现。
💻 C
📖 第 1 页 / 共 2 页
字号:
	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 + -