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

📄 common.c

📁 DHCPv6协议在Linux操作系统下的一个客户端实现。
💻 C
📖 第 1 页 / 共 4 页
字号:
/*	$Id: common.c,v 1.19 2004/02/04 23:30:17 shemminger Exp $	*//*	ported from KAME: common.c,v 1.65 2002/12/06 01:41:29 suz Exp	*//* * Copyright (C) 1998 and 1999 WIDE Project. * All rights reserved. *  * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. *  * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#include <sys/types.h>#include <sys/socket.h>#include <linux/sockios.h>#include <sys/ioctl.h>#if TIME_WITH_SYS_TIME# include <sys/time.h># include <time.h>#else# if HAVE_SYS_TIME_H#  include <sys/time.h># else#  include <time.h># endif#endif#include <net/if.h>#if defined(__FreeBSD__) && __FreeBSD__ >= 3#include <net/if_var.h>#endif#include <net/if_arp.h>#include <netinet/in.h>#include <errno.h>#include <limits.h>#include <stdio.h>#include <stdarg.h>#include <syslog.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <err.h>#include <netdb.h>#include <ifaddrs.h>#include <resolv.h>#ifdef HAVE_GETIFADDRS # ifdef HAVE_IFADDRS_H#  define USE_GETIFADDRS#  include <ifaddrs.h># endif#endif#include "queue.h"#include "dhcp6.h"#include "config.h"#include "common.h"#include "timer.h"#include "lease.h"int foreground;int debug_thresh;struct dhcp6_if *dhcp6_if;struct dns_list dnslist;static struct host_conf *host_conflist;static int in6_matchflags __P((struct sockaddr *, char *, int));ssize_t gethwid __P((char *, int, const char *, u_int16_t *));static int get_assigned_ipv6addrs __P((char *, char *,					struct dhcp6_optinfo *));struct dhcp6_if *find_ifconfbyname(const 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(unsigned int id){	struct dhcp6_if *ifp;	for (ifp = dhcp6_if; ifp; ifp = ifp->next) {		if (ifp->ifid == id)			return (ifp);	}	return (NULL);}struct host_conf *find_hostconf(const 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);}voidifinit(const char *ifname){	struct dhcp6_if *ifp;	if ((ifp = find_ifconfbyname(ifname)) != NULL) {		dprintf(LOG_NOTICE, "%s" "duplicated interface: %s",			FNAME, ifname);		return;	}	if ((ifp = malloc(sizeof(*ifp))) == NULL) {		dprintf(LOG_ERR, "%s" "malloc failed", FNAME);		goto die;	}	memset(ifp, 0, sizeof(*ifp));	TAILQ_INIT(&ifp->event_list);	if ((ifp->ifname = strdup(ifname)) == NULL) {		dprintf(LOG_ERR, "%s" "failed to copy ifname", FNAME);		goto die;	}	if ((ifp->ifid = if_nametoindex(ifname)) == 0) {		dprintf(LOG_ERR, "%s" "invalid interface(%s): %s", FNAME,			ifname, strerror(errno));		goto die;	}#ifdef HAVE_SCOPELIB	if (inet_zoneid(AF_INET6, 2, ifname, &ifp->linkid)) {		dprintf(LOG_ERR, "%s" "failed to get link ID for %s",			FNAME, ifname);		goto die;	}#else	ifp->linkid = ifp->ifid; /* XXX */#endif	if (get_linklocal(ifname, &ifp->linklocal) < 0)		goto die;	ifp->next = dhcp6_if;	dhcp6_if = ifp;	return;  die:	exit(1);}intdhcp6_copy_list(struct dhcp6_list *dst, 		const struct dhcp6_list *src){	const struct dhcp6_listval *ent;	struct dhcp6_listval *dent;	for (ent = TAILQ_FIRST(src); ent; ent = TAILQ_NEXT(ent, link)) {		if ((dent = malloc(sizeof(*dent))) == NULL)			goto fail;		memset(dent, 0, sizeof(*dent));		memcpy(&dent->uv, &ent->uv, sizeof(ent->uv));		TAILQ_INSERT_TAIL(dst, dent, link);	}	return 0;  fail:	dhcp6_clear_list(dst);	return -1;}voiddhcp6_clear_list(head)	struct dhcp6_list *head;{	struct dhcp6_listval *v;	while ((v = TAILQ_FIRST(head)) != NULL) {		TAILQ_REMOVE(head, v, link);		free(v);	}	return;}intdhcp6_count_list(head)	struct dhcp6_list *head;{	struct dhcp6_listval *v;	int i;	for (i = 0, v = TAILQ_FIRST(head); v; v = TAILQ_NEXT(v, link))		i++;	return i;}struct dhcp6_listval *dhcp6_find_listval(head, val, type)	struct dhcp6_list *head;	void *val;	dhcp6_listval_type_t type;{	struct dhcp6_listval *lv;	for (lv = TAILQ_FIRST(head); lv; lv = TAILQ_NEXT(lv, link)) {		switch(type) {		case DHCP6_LISTVAL_NUM:			if (lv->val_num == *(int *)val)				return (lv);			break;		case DHCP6_LISTVAL_ADDR6:			if (IN6_ARE_ADDR_EQUAL(&lv->val_addr6,			    (struct in6_addr *)val)) {				return (lv);			}			break;		case DHCP6_LISTVAL_DHCP6ADDR:			if (IN6_ARE_ADDR_EQUAL(&lv->val_dhcp6addr.addr,			    &((struct dhcp6_addr *)val)->addr) && 			    (lv->val_dhcp6addr.plen == ((struct dhcp6_addr *)val)->plen)) {				return (lv);			}			break;		}	}	return (NULL);}struct dhcp6_listval *dhcp6_add_listval(head, val, type)	struct dhcp6_list *head;	void *val;	dhcp6_listval_type_t type;{	struct dhcp6_listval *lv;	if ((lv = malloc(sizeof(*lv))) == NULL) {		dprintf(LOG_ERR, "%s" "failed to allocate memory for list "		    "entry", FNAME);		return (NULL);	}	memset(lv, 0, sizeof(*lv));	switch(type) {	case DHCP6_LISTVAL_NUM:		lv->val_num = *(int *)val;		break;	case DHCP6_LISTVAL_ADDR6:		lv->val_addr6 = *(struct in6_addr *)val;		break;	case DHCP6_LISTVAL_DHCP6ADDR:		lv->val_dhcp6addr = *(struct dhcp6_addr *)val;		break;	default:		dprintf(LOG_ERR, "%s" "unexpected list value type (%d)",		    FNAME, type);		return (NULL);	}	TAILQ_INSERT_TAIL(head, lv, link);	return (lv);}struct dhcp6_event *dhcp6_create_event(ifp, state)	struct dhcp6_if *ifp;	int state;{	struct dhcp6_event *ev;	if ((ev = malloc(sizeof(*ev))) == NULL) {		dprintf(LOG_ERR, "%s" "failed to allocate memory for an event",			FNAME);		return (NULL);	}	/* for safety */	memset(ev, 0, sizeof(*ev));	ev->serverid.duid_id = NULL;		ev->ifp = ifp;	ev->state = state;	TAILQ_INIT(&ev->data_list);	dprintf(LOG_DEBUG, "%s" "create an event %p xid %d for state %d", 		FNAME, ev, ev->xid, ev->state);	return (ev);}voiddhcp6_remove_event(ev)	struct dhcp6_event *ev;{	dprintf(LOG_DEBUG, "%s" "removing an event %p on %s, state=%d, xid=%x", FNAME,		ev, ev->ifp->ifname, ev->state, ev->xid);	if (!TAILQ_EMPTY(&ev->data_list)) {		dprintf(LOG_ERR, "%s" "assumption failure: "			"event data list is not empty", FNAME);		exit(1);	}	if (ev->serverid.duid_id != NULL)		duidfree(&ev->serverid);	if (ev->timer)		dhcp6_remove_timer(ev->timer);	TAILQ_REMOVE(&ev->ifp->event_list, ev, link);	free(ev);	/* XXX: for safety */	ev = NULL;}intgetifaddr(addr, ifnam, prefix, plen, strong, ignoreflags)	struct in6_addr *addr;	char *ifnam;	struct in6_addr *prefix;	int plen;	int strong;		/* if strong host model is required or not */	int ignoreflags;{	struct ifaddrs *ifap, *ifa;	struct sockaddr_in6 sin6;	int error = -1;	if (getifaddrs(&ifap) != 0) {		err(1, "getifaddr: getifaddrs");		/*NOTREACHED*/	}	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {		int s1, s2;		if (strong && strcmp(ifnam, ifa->ifa_name) != 0)			continue;		/* in any case, ignore interfaces in different scope zones. */		if ((s1 = in6_addrscopebyif(prefix, ifnam)) < 0 ||		    (s2 = in6_addrscopebyif(prefix, ifa->ifa_name)) < 0 ||		     s1 != s2)			continue;		if (ifa->ifa_addr->sa_family != AF_INET6)			continue;		if (sizeof(*(ifa->ifa_addr)) > sizeof(sin6))			continue;		if (in6_matchflags(ifa->ifa_addr, ifa->ifa_name, ignoreflags))			continue;		memcpy(&sin6, ifa->ifa_addr, sizeof(sin6));#ifdef __KAME__		if (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr)) {			sin6.sin6_addr.s6_addr[2] = 0;			sin6.sin6_addr.s6_addr[3] = 0;		}#endif		if (plen % 8 == 0) {			if (memcmp(&sin6.sin6_addr, prefix, plen / 8) != 0)				continue;		} else {			struct in6_addr a, m;			int i;			memcpy(&a, &sin6.sin6_addr, sizeof(a));			memset(&m, 0, sizeof(m));			memset(&m, 0xff, plen / 8);			m.s6_addr[plen / 8] = (0xff00 >> (plen % 8)) & 0xff;			for (i = 0; i < sizeof(a); i++)				a.s6_addr[i] &= m.s6_addr[i];			if (memcmp(&a, prefix, plen / 8) != 0 ||			    a.s6_addr[plen / 8] !=			    (prefix->s6_addr[plen / 8] & m.s6_addr[plen / 8]))				continue;		}		memcpy(addr, &sin6.sin6_addr, sizeof(*addr));#ifdef __KAME__		if (IN6_IS_ADDR_LINKLOCAL(addr))			addr->s6_addr[2] = addr->s6_addr[3] = 0; #endif		error = 0;		break;	}	freeifaddrs(ifap);	return (error);}intin6_addrscopebyif(addr, ifnam)	struct in6_addr *addr;	char *ifnam;{	u_int ifindex; 	if ((ifindex = if_nametoindex(ifnam)) == 0)		return (-1);	if (IN6_IS_ADDR_LINKLOCAL(addr) || IN6_IS_ADDR_MC_LINKLOCAL(addr))		return (ifindex);	if (IN6_IS_ADDR_SITELOCAL(addr) || IN6_IS_ADDR_MC_SITELOCAL(addr))		return (1);	/* XXX */	if (IN6_IS_ADDR_MC_ORGLOCAL(addr))		return (1);	/* XXX */	return (1);		/* treat it as global */}/* XXX: this code assumes getifaddrs(3) */const char *getdev(addr)	struct sockaddr_in6 *addr;{	struct ifaddrs *ifap, *ifa;	struct sockaddr_in6 *a6;	static char ret_ifname[IFNAMSIZ];	if (getifaddrs(&ifap) != 0) {		err(1, "getdev: getifaddrs");		/* NOTREACHED */	}	for (ifa = ifap; ifa; ifa = ifa->ifa_next) {		if (ifa->ifa_addr->sa_family != AF_INET6)			continue;		a6 = (struct sockaddr_in6 *)ifa->ifa_addr;		if (!IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &addr->sin6_addr) ||		    a6->sin6_scope_id != addr->sin6_scope_id)			continue;		break;	}	if (ifa)		strlcpy(ret_ifname, ifa->ifa_name, sizeof(ret_ifname));	freeifaddrs(ifap);	return (ifa ? ret_ifname : NULL);}inttransmit_sa(s, sa, buf, len)	int s;	struct sockaddr_in6 *sa;	char *buf;	size_t len;{	int error;	error = sendto(s, buf, len, MSG_DONTROUTE, (struct sockaddr *)sa, sizeof(*sa));	return (error != len) ? -1 : 0;}longrandom_between(x, y)	long x;	long y;{	long ratio;	ratio = 1 << 16;	while ((y - x) * ratio < (y - x))

⌨️ 快捷键说明

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