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

📄 common.c

📁 DHCPv6协议在Linux操作系统下的一个客户端实现。
💻 C
📖 第 1 页 / 共 4 页
字号:
		ratio = ratio / 2;	return x + ((y - x) * (ratio - 1) / random() & (ratio - 1));}intprefix6_mask(in6, plen)	struct in6_addr *in6;	int plen;{	struct sockaddr_in6 mask6;	int i;	if (sa6_plen2mask(&mask6, plen))		return (-1);	for (i = 0; i < 16; i++)		in6->s6_addr[i] &= mask6.sin6_addr.s6_addr[i];	return (0);}intsa6_plen2mask(sa6, plen)	struct sockaddr_in6 *sa6;	int plen;{	u_char *cp;	if (plen < 0 || plen > 128)		return (-1);	memset(sa6, 0, sizeof(*sa6));	sa6->sin6_family = AF_INET6;		for (cp = (u_char *)&sa6->sin6_addr; plen > 7; plen -= 8)		*cp++ = 0xff;	*cp = 0xff << (8 - plen);	return (0);}char *addr2str(sa)	struct sockaddr *sa;{	static char addrbuf[8][NI_MAXHOST];	static int round = 0;	char *cp;	round = (round + 1) & 7;	cp = addrbuf[round];	if (getnameinfo(sa, NI_MAXSERV, cp, NI_MAXHOST, NULL, 				0, NI_NUMERICHOST) != 0)		dprintf(LOG_ERR, "%s getnameinfo return error", FNAME);	return (cp);}char *in6addr2str(in6, scopeid)	struct in6_addr *in6;	int scopeid;{	struct sockaddr_in6 sa6;	memset(&sa6, 0, sizeof(sa6));	sa6.sin6_family = AF_INET6;	sa6.sin6_addr = *in6;	sa6.sin6_scope_id = scopeid;	return (addr2str((struct sockaddr *)&sa6));}/* return IPv6 address scope type. caller assumes that smaller is narrower. */intin6_scope(addr)	struct in6_addr *addr;{	int scope;	if (addr->s6_addr[0] == 0xfe) {		scope = addr->s6_addr[1] & 0xc0;		switch (scope) {		case 0x80:			return 2; /* link-local */			break;		case 0xc0:			return 5; /* site-local */			break;		default:			return 14; /* global: just in case */			break;		}	}	/* multicast scope. just return the scope field */	if (addr->s6_addr[0] == 0xff)		return (addr->s6_addr[1] & 0x0f);	if (bcmp(&in6addr_loopback, addr, sizeof(addr) - 1) == 0) {		if (addr->s6_addr[15] == 1) /* loopback */			return 1;		if (addr->s6_addr[15] == 0) /* unspecified */			return 0; /* XXX: good value? */	}	return 14;		/* global */}static intin6_matchflags(addr, ifnam, flags)	struct sockaddr *addr;	char *ifnam;	int flags;{	int s;	struct ifreq ifr;	if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {		warn("in6_matchflags: socket(DGRAM6)");		return (-1);	}	memset(&ifr, 0, sizeof(ifr));	strncpy(ifr.ifr_name, ifnam, sizeof(ifr.ifr_name));	ifr.ifr_addr = *(struct sockaddr *)addr;	if (ioctl(s, SIOCGIFFLAGS, &ifr) < 0) {		warn("in6_matchflags: ioctl(SIOCGIFFLAGS, %s)",		     addr2str(addr));		close(s);		return (-1);	}	close(s);	return (ifr.ifr_ifru.ifru_flags & flags);}intconfigure_duid(const char *str,	       struct duid *duid){	const char *cp;	char  *bp, *idbuf = NULL;	int duidlen, slen;	unsigned int x;	/* calculate DUID len */	slen = strlen(str);	if (slen < 2)		goto bad;	duidlen = 1;	slen -= 2;	if ((slen % 3) != 0)		goto bad;	duidlen += (slen / 3);	if (duidlen > 256) {		dprintf(LOG_ERR, "%s" "too long DUID (%d)", FNAME, duidlen);		return (-1);	}	if ((idbuf = (char *)malloc(duidlen)) == NULL) {		dprintf(LOG_ERR, "%s" "memory allocation failed", FNAME);		return (-1);	}	for (cp = str, bp = idbuf; *cp;) {		if (*cp == ':') {			cp++;			continue;		}		if (sscanf(cp, "%02x", &x) != 1)			goto bad;		*bp = x;		cp += 2;		bp++;	}	duid->duid_len = duidlen;	duid->duid_id = idbuf;	dprintf(LOG_DEBUG, "configure duid is %s", duidstr(duid));	return (0);  bad:	if (idbuf)		free(idbuf);	dprintf(LOG_ERR, "%s" "assumption failure (bad string)", FNAME);	return (-1);}intget_duid(const 	char *idfile, const char *ifname,	 struct duid *duid){	FILE *fp = NULL;	u_int16_t len = 0, hwtype;	struct dhcp6_duid_type1 *dp; /* we only support the type1 DUID */	char tmpbuf[256];	/* DUID should be no more than 256 bytes */	if ((fp = fopen(idfile, "r")) == NULL && errno != ENOENT)		dprintf(LOG_NOTICE, "%s" "failed to open DUID file: %s",		    FNAME, idfile);	if (fp) {		/* decode length */		if (fread(&len, sizeof(len), 1, fp) != 1) {			dprintf(LOG_ERR, "%s" "DUID file corrupted", FNAME);			goto fail;		}	} else {		int l;		if ((l = gethwid(tmpbuf, sizeof(tmpbuf), ifname, &hwtype)) < 0) {			dprintf(LOG_INFO, "%s"			    "failed to get a hardware address", FNAME);			goto fail;		}		len = l + sizeof(struct dhcp6_duid_type1);	}	memset(duid, 0, sizeof(*duid));	duid->duid_len = len;	if ((duid->duid_id = (char *)malloc(len)) == NULL) {		dprintf(LOG_ERR, "%s" "failed to allocate memory", FNAME);		goto fail;	}	/* copy (and fill) the ID */	if (fp) {		if (fread(duid->duid_id, len, 1, fp) != 1) {			dprintf(LOG_ERR, "%s" "DUID file corrupted", FNAME);			goto fail;		}		dprintf(LOG_DEBUG, "%s"		    "extracted an existing DUID from %s: %s", FNAME,		    idfile, duidstr(duid));	} else {		u_int64_t t64;		dp = (struct dhcp6_duid_type1 *)duid->duid_id;		dp->dh6duid1_type = htons(1); /* type 1 */		dp->dh6duid1_hwtype = htons(hwtype);		/* time is Jan 1, 2000 (UTC), modulo 2^32 */		t64 = (u_int64_t)(time(NULL) - 946684800);		dp->dh6duid1_time = htonl((u_long)(t64 & 0xffffffff));		memcpy((void *)(dp + 1), tmpbuf, (len - sizeof(*dp)));		dprintf(LOG_DEBUG, "%s" "generated a new DUID: %s", FNAME,			duidstr(duid));	}	/* save the (new) ID to the file for next time */	if (!fp) {		if ((fp = fopen(idfile, "w+")) == NULL) {			dprintf(LOG_ERR, "%s"			    "failed to open DUID file for save", FNAME);			goto fail;		}		if ((fwrite(&len, sizeof(len), 1, fp)) != 1) {			dprintf(LOG_ERR, "%s" "failed to save DUID", FNAME);			goto fail;		}		if ((fwrite(duid->duid_id, len, 1, fp)) != 1) {			dprintf(LOG_ERR, "%s" "failed to save DUID", FNAME);			goto fail;		}		dprintf(LOG_DEBUG, "%s" "saved generated DUID to %s", FNAME,			idfile);	}	if (fp)		fclose(fp);	return (0);  fail:	if (fp)		fclose(fp);	if (duid->duid_id != NULL) {		duidfree(duid);	}	return (-1);}ssize_tgethwid(buf, len, ifname, hwtypep)	char *buf;	int len;	const char *ifname;	u_int16_t *hwtypep;{	int skfd;	ssize_t l;	struct ifreq if_hwaddr;		if ((skfd = socket(AF_INET6, SOCK_DGRAM, 0 )) < 0)		return -1;	strcpy(if_hwaddr.ifr_name, ifname);	if (ioctl(skfd, SIOCGIFHWADDR, &if_hwaddr) < 0)		return -1;	/* only support Ethernet */	switch (if_hwaddr.ifr_hwaddr.sa_family) {	case ARPHRD_ETHER:	case ARPHRD_IEEE802:		*hwtypep = ARPHRD_ETHER;		l = 6;		break;	case ARPHRD_PPP:		*hwtypep = ARPHRD_PPP;		l = 0;		return l;	default:		dprintf(LOG_INFO, "dhcpv6 doesn't support hardware type %d",			if_hwaddr.ifr_hwaddr.sa_family);		return -1; /* XXX */	}	memcpy(buf, if_hwaddr.ifr_hwaddr.sa_data, l);	dprintf(LOG_DEBUG, "%s" "found an interface %s harware %x",		FNAME, ifname, buf);	return l;}voiddhcp6_init_options(optinfo)	struct dhcp6_optinfo *optinfo;{	memset(optinfo, 0, sizeof(*optinfo));	/* for safety */	optinfo->clientID.duid_id = NULL;	optinfo->serverID.duid_id = NULL;	optinfo->pref = DH6OPT_PREF_UNDEF;	TAILQ_INIT(&optinfo->addr_list);	TAILQ_INIT(&optinfo->reqopt_list);	TAILQ_INIT(&optinfo->stcode_list);	TAILQ_INIT(&optinfo->dns_list.addrlist);	optinfo->dns_list.domainlist = NULL;}voiddhcp6_clear_options(optinfo)	struct dhcp6_optinfo *optinfo;{	struct domain_list *dlist, *dlist_next;	duidfree(&optinfo->clientID);	duidfree(&optinfo->serverID);	dhcp6_clear_list(&optinfo->addr_list);	dhcp6_clear_list(&optinfo->reqopt_list);	dhcp6_clear_list(&optinfo->stcode_list);	dhcp6_clear_list(&optinfo->dns_list.addrlist);	if (dhcp6_mode == DHCP6_MODE_CLIENT) {		for (dlist = optinfo->dns_list.domainlist; dlist; dlist = dlist_next) {			dlist_next = dlist->next;			free(dlist);		}	}	optinfo->dns_list.domainlist = NULL;	dhcp6_init_options(optinfo);}intdhcp6_copy_options(dst, src)	struct dhcp6_optinfo *dst, *src;{	if (duidcpy(&dst->clientID, &src->clientID))		goto fail;	if (duidcpy(&dst->serverID, &src->serverID))		goto fail;	dst->flags = src->flags;		if (dhcp6_copy_list(&dst->addr_list, &src->addr_list))		goto fail;	if (dhcp6_copy_list(&dst->reqopt_list, &src->reqopt_list))		goto fail;	if (dhcp6_copy_list(&dst->stcode_list, &src->stcode_list))		goto fail;	if (dhcp6_copy_list(&dst->dns_list.addrlist, &src->dns_list.addrlist))		goto fail;	memcpy(&dst->server_addr, &src->server_addr, sizeof(dst->server_addr));	dst->pref = src->pref;	return 0;  fail:	/* cleanup temporary resources */	dhcp6_clear_options(dst);	return -1;}intdhcp6_get_options(p, ep, optinfo)	struct dhcp6opt *p, *ep;	struct dhcp6_optinfo *optinfo;{	struct dhcp6opt *np, opth;	int i, opt, optlen, reqopts, num;	char *cp, *val;	u_int16_t val16;	for (; p + 1 <= ep; p = np) {		struct duid duid0;		/*		 * get the option header.  XXX: since there is no guarantee		 * about the header alignment, we need to make a local copy.		 */		memcpy(&opth, p, sizeof(opth));		optlen = ntohs(opth.dh6opt_len);		opt = ntohs(opth.dh6opt_type);		cp = (char *)(p + 1);		np = (struct dhcp6opt *)(cp + optlen);		dprintf(LOG_DEBUG, "%s" "get DHCP option %s, len %d",		    FNAME, dhcp6optstr(opt), optlen);		/* option length field overrun */		if (np > ep) {			dprintf(LOG_INFO,			    "%s" "malformed DHCP options", FNAME);			return -1;		}		switch (opt) {		case DH6OPT_CLIENTID:			if (optlen == 0)				goto malformed;			duid0.duid_len = optlen;			duid0.duid_id = cp;			dprintf(LOG_DEBUG, "  DUID: %s", duidstr(&duid0));			if (duidcpy(&optinfo->clientID, &duid0)) {				dprintf(LOG_ERR, "%s" "failed to copy DUID",					FNAME);				goto fail;			}			break;		case DH6OPT_SERVERID:			if (optlen == 0)				goto malformed;			duid0.duid_len = optlen;			duid0.duid_id = cp;			dprintf(LOG_DEBUG, "  DUID: %s", duidstr(&duid0));			if (duidcpy(&optinfo->serverID, &duid0)) {				dprintf(LOG_ERR, "%s" "failed to copy DUID",					FNAME);				goto fail;			}			break;		case DH6OPT_ELAPSED_TIME:			if (optlen != sizeof(u_int16_t))				goto malformed;			memcpy(&val16, cp, sizeof(val16));			num = ntohs(val16);			dprintf(LOG_DEBUG, " this message elapsed time is: %d",				num);			break;		case DH6OPT_STATUS_CODE:			if (optlen < sizeof(u_int16_t))				goto malformed;			memcpy(&val16, cp, sizeof(val16));			num = ntohs(val16);			dprintf(LOG_DEBUG, "  this message status code: %s",			    dhcp6_stcodestr(num));						/* XXX: status message */						/* 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;			}			break;		case DH6OPT_ORO:			if ((optlen % 2) != 0 || optlen == 0)				goto malformed;			reqopts = optlen / 2;			for (i = 0, val = cp; i < reqopts;			     i++, val += sizeof(u_int16_t)) {				u_int16_t opttype;				memcpy(&opttype, val, sizeof(u_int16_t));				num = ntohs(opttype);				dprintf(LOG_DEBUG, "  requested option: %s",					dhcp6optstr(num));				if (dhcp6_find_listval(&optinfo->reqopt_list,				    &num, DHCP6_LISTVAL_NUM)) {					dprintf(LOG_INFO, "%s" "duplicated "					    "option type (%s)", FNAME,

⌨️ 快捷键说明

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